<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40169 >

 Somehow ferry movement caused alliance to break (by making new
contact). This caused units, including ferry, to bounce. Pathfinding
crashed because unit was no longer on path.

 Fix attached.


 - ML

diff -Nurd -X.diff_ignore freeciv/ai/aiferry.c freeciv/ai/aiferry.c
--- freeciv/ai/aiferry.c	2008-01-20 04:03:28.000000000 +0200
+++ freeciv/ai/aiferry.c	2008-03-27 06:36:01.000000000 +0200
@@ -553,7 +553,11 @@
        * has run out of movement points */
       struct tile *next_tile;
 
-      pft_advance_path(path, passenger->tile);
+      if (!pft_advance_path(path, passenger->tile)) {
+        /* Somehow we got thrown away from our route.
+         * This can happen if our movement caused alliance breakup. */
+        return alive;
+      }
       next_tile = path->positions[1].tile;
       if (!is_ocean_tile(next_tile)) {
 	UNIT_LOG(LOG_DEBUG, passenger, "Our boat has arrived "
diff -Nurd -X.diff_ignore freeciv/common/aicore/pf_tools.c freeciv/common/aicore/pf_tools.c
--- freeciv/common/aicore/pf_tools.c	2008-03-08 16:32:47.000000000 +0200
+++ freeciv/common/aicore/pf_tools.c	2008-03-27 06:36:21.000000000 +0200
@@ -869,17 +869,19 @@
 
 /****************************************************************************
   Remove the part of a path leading up to a given tile.
-  The given tile must be on the path.  If it is on the path more than once
+  If given tile is on the path more than once
   then the first occurrance will be the one used.
+  If tile is not on the path at all, returns FALSE and
+  path is not changed at all.
 ****************************************************************************/
-void pft_advance_path(struct pf_path *path, struct tile *ptile)
+bool pft_advance_path(struct pf_path *path, struct tile *ptile)
 {
   int i;
   struct pf_position *new_positions;
 
-  for (i = 0; i < path->length; i++) {
-    if (path->positions[i].tile == ptile) {
-      break;
+  for (i = 0; path->positions[i].tile != ptile ; i++) {
+    if (i >= path->length) {
+      return FALSE;
     }
   }
   assert(i < path->length);
@@ -889,4 +891,6 @@
 	 path->length * sizeof(*path->positions));
   free(path->positions);
   path->positions = new_positions;
+
+  return TRUE;
 }
diff -Nurd -X.diff_ignore freeciv/common/aicore/pf_tools.h freeciv/common/aicore/pf_tools.h
--- freeciv/common/aicore/pf_tools.h	2007-09-14 14:51:34.000000000 +0300
+++ freeciv/common/aicore/pf_tools.h	2008-03-27 06:36:01.000000000 +0200
@@ -40,7 +40,7 @@
 
 struct pf_path *pft_concat(struct pf_path *dest_path,
 			   const struct pf_path *src_path);
-void pft_advance_path(struct pf_path *path,
+bool pft_advance_path(struct pf_path *path,
 		      struct tile *ptile);
 void pft_fill_unit_parameter(struct pf_parameter *parameter,
 			     struct unit *punit);
diff -Nurd -X.diff_ignore freeciv/server/unithand.c freeciv/server/unithand.c
--- freeciv/server/unithand.c	2008-03-08 16:32:28.000000000 +0200
+++ freeciv/server/unithand.c	2008-03-27 06:36:01.000000000 +0200
@@ -1137,8 +1137,9 @@
 }
 
 /**************************************************************************
-  Will try to move to/attack the tile dest_x,dest_y.  Returns true if this
-  could be done, false if it couldn't for some reason.
+  Will try to move to/attack the tile dest_x,dest_y.  Returns TRUE if this
+  could be done, FALSE if it couldn't for some reason. Even if this
+  returns TRUE, unit may have died upon arrival to new tile.
   
   'igzoc' means ignore ZOC rules - not necessary for igzoc units etc, but
   done in some special cases (moving barbarians out of initial hut).
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to