Author: sveinung
Date: Tue Jan 19 12:54:37 2016
New Revision: 31486

URL: http://svn.gna.org/viewcvs/freeciv?rev=31486&view=rev
Log:
Detect spaceship part autoplace failure.

Stop spaceship part autoplace when placing a spaceship part fails. This
avoids an eternal loop where placing the same part fails again and again.

The eternal loop was triggered when a player launched his space ship
without placing all the space ship parts built that turn. The bundled
clients placed the space ship components before the player had a chance to
launch the space ship. Freeciv-web didn't.

Reported by: Andreas Røsdal <andreasr>

See bug #24309

Modified:
    branches/S2_5/server/advisors/advspace.c
    branches/S2_5/server/spacerace.c
    branches/S2_5/server/spacerace.h

Modified: branches/S2_5/server/advisors/advspace.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/server/advisors/advspace.c?rev=31486&r1=31485&r2=31486&view=diff
==============================================================================
--- branches/S2_5/server/advisors/advspace.c    (original)
+++ branches/S2_5/server/advisors/advspace.c    Tue Jan 19 12:54:37 2016
@@ -26,8 +26,12 @@
 #include "advspace.h"
 
 /****************************************************************************
+  Place all available spaceship components.
+
   This borrows heavily from autoplace code already in the client source.
   AJS, 19990610
+
+  Returns TRUE iff at least one part was placed.
 ****************************************************************************/
 bool adv_spaceship_autoplace(struct player *pplayer,
                              struct player_spaceship *ship)
@@ -35,7 +39,7 @@
   enum spaceship_place_type type;
   int num, i;
   bool retval = FALSE;
-  
+
   while (ship->modules > (ship->habitation + ship->life_support
                       + ship->solar_panels)) {
     
@@ -64,8 +68,15 @@
     }
     fc_assert_ret_val(num <= NUM_SS_MODULES / 3, FALSE);
 
-    handle_spaceship_place(pplayer, type, num);
-    retval = TRUE;
+    if (do_spaceship_place(pplayer, FALSE,
+                           type, num)) {
+      /* A part was placed. It was placed even if the placement of future
+       * parts will fail. */
+      retval = TRUE;
+    } else {
+      /* Unable to place this part. Don't try to place it again. */
+      break;
+    }
   }
   while (ship->components > ship->fuel + ship->propulsion) {
     if (ship->fuel <= ship->propulsion) {
@@ -75,8 +86,16 @@
       type = SSHIP_PLACE_PROPULSION;
       num = ship->propulsion + 1;
     }
-    handle_spaceship_place(pplayer, type, num);
-    retval = TRUE;
+
+    if (do_spaceship_place(pplayer, FALSE,
+                           type, num)) {
+      /* A part was placed. It was placed even if the placement of future
+       * parts will fail. */
+      retval = TRUE;
+    } else {
+      /* Unable to place this part. Don't try to place it again. */
+      break;
+    }
   }
   while (ship->structurals > num_spaceship_structurals_placed(ship)) {
     /* Want to choose which structurals are most important.
@@ -90,7 +109,16 @@
       /* if we don't have the first structural, place that! */
       type = SSHIP_PLACE_STRUCTURAL;
       num = 0;
-      handle_spaceship_place(pplayer, type, num);
+
+      if (do_spaceship_place(pplayer, FALSE,
+                             type, num)) {
+        /* A part was placed. It was placed even if the placement of future
+         * parts will fail. */
+        retval = TRUE;
+      } else {
+        /* Unable to place this part. Don't try to place it again. */
+        break;
+      }
     }
     
     if (ship->habitation >= 1
@@ -147,8 +175,16 @@
     }
     type = SSHIP_PLACE_STRUCTURAL;
     num = req;
-    handle_spaceship_place(pplayer, type, num);
-    retval = TRUE;
+
+    if (do_spaceship_place(pplayer, FALSE,
+                           type, num)) {
+      /* A part was placed. It was placed even if the placement of future
+       * parts will fail. */
+      retval = TRUE;
+    } else {
+      /* Unable to place this part. Don't try to place it again. */
+      break;
+    }
   }
   return retval;
 }

Modified: branches/S2_5/server/spacerace.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/server/spacerace.c?rev=31486&r1=31485&r2=31486&view=diff
==============================================================================
--- branches/S2_5/server/spacerace.c    (original)
+++ branches/S2_5/server/spacerace.c    Tue Jan 19 12:54:37 2016
@@ -203,148 +203,214 @@
   Handle spaceship part placement request
 **************************************************************************/
 void handle_spaceship_place(struct player *pplayer,
-                           enum spaceship_place_type type, int num)
+                            enum spaceship_place_type type, int num)
+{
+  (void) do_spaceship_place(pplayer, TRUE, type, num);
+}
+
+/**************************************************************************
+  Place a spaceship part
+**************************************************************************/
+bool do_spaceship_place(struct player *pplayer, bool user_initiated,
+                        enum spaceship_place_type type, int num)
 {
   struct player_spaceship *ship = &pplayer->spaceship;
   
   if (ship->state == SSHIP_NONE) {
-    notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                  _("Spaceship action received,"
-                    " but you don't have a spaceship!"));
-    return;
-  }
+    if (user_initiated) {
+      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                    _("Spaceship action received,"
+                      " but you don't have a spaceship!"));
+    }
+
+    return FALSE;
+  }
+
   if (ship->state >= SSHIP_LAUNCHED) {
-    notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                  _("You can't modify your spaceship after launch!"));
-    return;
-  }
+    if (user_initiated) {
+      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                    _("You can't modify your spaceship after launch!"));
+    }
+
+    return FALSE;
+  }
+
   if (type == SSHIP_PLACE_STRUCTURAL) {
     if (num < 0 || num >= NUM_SS_STRUCTURALS
         || BV_ISSET(ship->structure, num)) {
-      return;
+      return FALSE;
     }
     if (num_spaceship_structurals_placed(ship) >= ship->structurals) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced Space Structurals!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced Space Structurals!"));
+      }
+
+      return FALSE;
     }
     if (num != 0
         && !BV_ISSET(ship->structure, structurals_info[num].required)) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("That Space Structural would not be connected!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("That Space Structural would not be connected!"));
+      }
+
+      return FALSE;
+    }
+
     BV_SET(ship->structure, num);
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   if (type == SSHIP_PLACE_FUEL) {
-    if (ship->fuel != num-1) {
-      return;
+    if (ship->fuel != num - 1) {
+      return FALSE;
     }
     if (ship->fuel + ship->propulsion >= ship->components) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced Space Components!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced Space Components!"));
+      }
+
+      return FALSE;
     }
     if (num > NUM_SS_COMPONENTS/2) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("Your spaceship already has"
-                      " the maximum number of Fuel Components!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("Your spaceship already has"
+                        " the maximum number of Fuel Components!"));
+      }
+
+      return FALSE;
+    }
+
     ship->fuel++;
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   if (type == SSHIP_PLACE_PROPULSION) {
-    if (ship->propulsion != num-1) {
-      return;
+    if (ship->propulsion != num - 1) {
+      return FALSE;
     }
     if (ship->fuel + ship->propulsion >= ship->components) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced"
-                      " Space Components!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced"
+                        " Space Components!"));
+      }
+
+      return FALSE;
     }
     if (num > NUM_SS_COMPONENTS/2) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("Your spaceship already has the"
-                      " maximum number of Propulsion Components!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("Your spaceship already has the"
+                        " maximum number of Propulsion Components!"));
+      }
+
+      return FALSE;
+    }
+
     ship->propulsion++;
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   if (type == SSHIP_PLACE_HABITATION) {
-    if (ship->habitation != num-1) {
-      return;
+    if (ship->habitation != num - 1) {
+      return FALSE;
     }
     if (ship->habitation + ship->life_support + ship->solar_panels
         >= ship->modules) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced Space Modules!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced Space Modules!"));
+      }
+
+      return FALSE;
     }
     if (num > NUM_SS_MODULES / 3) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("Your spaceship already has the"
-                      " maximum number of Habitation Modules!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("Your spaceship already has the"
+                        " maximum number of Habitation Modules!"));
+      }
+
+      return FALSE;
+    }
+
     ship->habitation++;
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   if (type == SSHIP_PLACE_LIFE_SUPPORT) {
-    if (ship->life_support != num-1) {
-      return;
+    if (ship->life_support != num - 1) {
+      return FALSE;
     }
     if (ship->habitation + ship->life_support + ship->solar_panels
         >= ship->modules) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced Space Modules!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced Space Modules!"));
+      }
+
+      return FALSE;
     }
     if (num > NUM_SS_MODULES / 3) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("Your spaceship already has the"
-                      " maximum number of Life Support Modules!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("Your spaceship already has the"
+                        " maximum number of Life Support Modules!"));
+      }
+
+      return FALSE;
+    }
+
     ship->life_support++;
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   if (type == SSHIP_PLACE_SOLAR_PANELS) {
-    if (ship->solar_panels != num-1) {
-      return;
+    if (ship->solar_panels != num - 1) {
+      return FALSE;
     }
     if (ship->habitation + ship->life_support + ship->solar_panels
         >= ship->modules) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("You don't have any unplaced Space Modules!"));
-      return;
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("You don't have any unplaced Space Modules!"));
+      }
+
+      return FALSE;
     }
     if (num > NUM_SS_MODULES / 3) {
-      notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
-                    _("Your spaceship already has the"
-                      " maximum number of Solar Panel Modules!"));
-      return;
-    }
+      if (user_initiated) {
+        notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
+                      _("Your spaceship already has the"
+                        " maximum number of Solar Panel Modules!"));
+      }
+
+      return FALSE;
+    }
+
     ship->solar_panels++;
     spaceship_calc_derived(ship);
     send_spaceship_info(pplayer, NULL);
-    return;
-  }
+    return TRUE;
+  }
+
   log_error("Received unknown spaceship place type %d from %s",
             type, player_name(pplayer));
+  return FALSE;
 }
 
 /**************************************************************************

Modified: branches/S2_5/server/spacerace.h
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/server/spacerace.h?rev=31486&r1=31485&r2=31486&view=diff
==============================================================================
--- branches/S2_5/server/spacerace.h    (original)
+++ branches/S2_5/server/spacerace.h    Tue Jan 19 12:54:37 2016
@@ -28,4 +28,7 @@
 void handle_spaceship_place(struct player *pplayer,
                            enum spaceship_place_type type, int num);
 
+bool do_spaceship_place(struct player *pplayer, bool user_initiated,
+                        enum spaceship_place_type type, int num);
+
 #endif /* FC__SPACERACE_H */


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to