Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2004:
[Freeciv-Dev] (PR#10830) Trirem doesn't want to move
Home

[Freeciv-Dev] (PR#10830) Trirem doesn't want to move

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Francois-Xavier.Coudert@xxxxxx
Subject: [Freeciv-Dev] (PR#10830) Trirem doesn't want to move
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxxx>
Date: Sat, 27 Nov 2004 18:51:19 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=10830 >

> [jdorje - Fri Nov 05 15:35:39 2004]:
> 
> Gregory Berkolaiko wrote:
> 
> > Doing it with a high move-cost will break the "waiting" logic.  So we
> > will have triremes sinking again even when there is only one dangerous
> > tile between two oceans.
> 
> What about using extra cost (EC) for this?

EC is awarded always, whether the unit ends its move on a tile or not. 
And doing it otherwise is impossible outside danger framework, so we get
a loop.

Anyway, I hacked together a patch which does the following:

1. you put a unit into the goto mode (pressing G or via the menu)
2. move your cursor to a dangerous tile you really want to get to
3. press "f" to cycle through several available paths

sometimes some paths are obviously better than the others, I cannot do
anything about it.

it would be great if we could highlight:
a) the last danger segment
b) the points where we wait <- this one should have been done long ago.

currently you cannot make the unit actually take the selected path, but
it would be easy to change.

I would like the client people to 
i) think about the interface (maybe press some mouse key instead of f?)
ii) fix my surely barbaric changes to the client

Then I can clean up my PF changes and hopefully we'll have a solution to
this rather annoying problem.

G.
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.150
diff -u -r1.150 control.c
--- client/control.c    13 Nov 2004 08:27:46 -0000      1.150
+++ client/control.c    28 Nov 2004 02:40:28 -0000
@@ -1837,6 +1837,21 @@
 }
 
 /**************************************************************************
+  Force displaying path to a dangerous tile
+**************************************************************************/
+void key_unit_force_goto(struct tile *ptile)
+{
+  struct unit *punit = punit_focus;
+
+  if (!punit || hover_state != HOVER_GOTO) {
+    return;
+  } else if (!is_air_unit(punit) && !is_heli_unit(punit)) {
+    assert(goto_is_active());
+    goto_force_path(ptile);
+  }
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 void key_unit_goto(void)
Index: client/control.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.h,v
retrieving revision 1.45
diff -u -r1.45 control.h
--- client/control.h    29 Sep 2004 02:24:19 -0000      1.45
+++ client/control.h    28 Nov 2004 02:40:28 -0000
@@ -149,6 +149,7 @@
 void key_unit_fortify(void);
 void key_unit_fortress(void);
 void key_unit_goto(void);
+void key_unit_force_goto(struct tile *ptile);
 void key_unit_homecity(void);
 void key_unit_irrigate(void);
 void key_unit_mine(void);
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.79
diff -u -r1.79 goto.c
--- client/goto.c       22 Nov 2004 19:14:41 -0000      1.79
+++ client/goto.c       28 Nov 2004 02:40:29 -0000
@@ -125,29 +125,15 @@
 }
 
 /********************************************************************** 
-  Change the destination of the last part to the given position if a
-  path can be found. If not the destination is set to the start.
+  Draw a path, trying to reuse already drawn parts.  Record the new 
+  path and update the part structure.
 ***********************************************************************/
-static void update_last_part(struct tile *ptile)
+static void put_path(struct tile *ptile, struct pf_path *new_path)
 {
   struct part *p = &goto_map.parts[goto_map.num_parts - 1];
-  struct pf_path *new_path;
   struct tile *old_tile = p->start_tile;
   int i, start_index = 0;
 
-  freelog(LOG_DEBUG, "update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
-          TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
-  new_path = pf_get_path(p->map, ptile);
-
-  if (!new_path) {
-    freelog(PATH_LOG_LEVEL, "  no path found");
-    reset_last_part();
-    return;
-  }
-
-  freelog(PATH_LOG_LEVEL, "  path found:");
-  pf_print_path(PATH_LOG_LEVEL, new_path);
-
   if (p->path) {
     /* We had a path drawn already.  Determine how much of it we can reuse
      * in drawing the new path. */
@@ -212,6 +198,57 @@
   /* Refresh tiles so turn information is shown. */
   refresh_tile_mapcanvas(old_tile, FALSE);
   refresh_tile_mapcanvas(ptile, FALSE);
+
+}
+
+/********************************************************************** 
+  Change the destination of the last part to the given position if a
+  path can be found. If not the destination is set to the start.
+***********************************************************************/
+static void update_last_part(struct tile *ptile)
+{
+  struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+  struct pf_path *new_path;
+
+  freelog(LOG_DEBUG, "update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
+          TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
+  new_path = pf_get_path(p->map, ptile);
+
+  if (!new_path) {
+    freelog(PATH_LOG_LEVEL, "  no path found");
+    reset_last_part();
+    return;
+  }
+
+  freelog(PATH_LOG_LEVEL, "  path found:");
+  pf_print_path(PATH_LOG_LEVEL, new_path);
+
+  put_path(ptile, new_path);
+}
+
+/********************************************************************** 
+  Force dsiplay of the path to a dangerous tile
+***********************************************************************/
+void goto_force_path(struct tile *ptile)
+{
+  struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+  struct pf_path *path;
+
+  path = pf_force_get_path(p->map, ptile);
+
+  if (!path) {
+    /* Try resetting */
+    struct pf_parameter parameter = *pf_get_parameter(p->map);
+    
+    pf_destroy_map(p->map);
+    pf_create_map(&parameter);
+    path = pf_force_get_path(p->map, ptile);
+  }
+
+  if (path) {
+    pf_print_path(LOG_NORMAL, path);
+    put_path(ptile, path);
+  }
 }
 
 /********************************************************************** 
Index: client/goto.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.h,v
retrieving revision 1.16
diff -u -r1.16 goto.h
--- client/goto.h       29 Sep 2004 02:24:19 -0000      1.16
+++ client/goto.h       28 Nov 2004 02:40:29 -0000
@@ -27,6 +27,7 @@
 void goto_add_waypoint(void);
 bool goto_pop_waypoint(void);
 
+void goto_force_path(struct tile *ptile);
 void draw_line(struct tile *dest_tile);
 bool is_drawn_line(struct tile *dest_tile, int dir);
  
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.c,v
retrieving revision 1.96
diff -u -r1.96 gui_main.c
--- client/gui-gtk-2.0/gui_main.c       26 Nov 2004 22:28:42 -0000      1.96
+++ client/gui-gtk-2.0/gui_main.c       28 Nov 2004 02:40:29 -0000
@@ -436,6 +436,17 @@
         key_city_workers(w, ev);
         break;
 
+      case GDK_f:
+        { 
+          int x, y;
+          struct tile *ptile;
+          
+          gdk_window_get_pointer(map_canvas->window, &x, &y, NULL);
+          ptile = canvas_pos_to_tile(x, y);
+          key_unit_force_goto(ptile);
+          break;
+        }
+
       case GDK_KP_Divide:
         key_quickselect(SELECT_SEA);
         break;
Index: common/aicore/path_finding.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.c,v
retrieving revision 1.27
diff -u -r1.27 path_finding.c
--- common/aicore/path_finding.c        27 Nov 2004 22:11:09 -0000      1.27
+++ common/aicore/path_finding.c        28 Nov 2004 02:40:29 -0000
@@ -109,11 +109,12 @@
   struct danger_node *d_lattice;       /* Lattice with danger stuff */
 };
 
-static bool danger_iterate_map(struct pf_map *pf_map);
+static bool danger_iterate_map(struct pf_map *pf_map, bool return_dangerous);
 static struct pf_path* danger_construct_path(const struct pf_map *pf_map,
-                                            struct tile *ptile);
-static struct pf_path *danger_get_path(struct pf_map *pf_map,
-                                      struct tile *ptile);
+                                            struct tile *ptile, 
+                                             struct pf_danger_pos *d_seg);
+static struct pf_path *danger_get_path(struct pf_map *pf_map, 
+                                       struct tile *ptile);
 
 
 /* =================== manipulating the cost ===================== */
@@ -315,7 +316,7 @@
 
   if (pf_map->params->is_pos_dangerous) {
     /* It's a lot different if is_pos_dangerous is defined */
-    return danger_iterate_map(pf_map);
+    return danger_iterate_map(pf_map, FALSE);
   }
 
   if (pf_map->params->get_costs) {
@@ -657,7 +658,7 @@
     return construct_path(pf_map, pf_map->tile);
   } else {
     /* It's very different in the presence of danger */
-    return danger_construct_path(pf_map, pf_map->tile);
+    return danger_construct_path(pf_map, pf_map->tile, NULL);
   }
 }
 
@@ -762,11 +763,10 @@
 /***********************************************************************
   Creating path segment going back from d_node1 to a safe tile.
 ***********************************************************************/
-static void create_danger_segment(struct pf_map *pf_map, enum direction8 dir,
+static void create_danger_segment(struct pf_map *pf_map, struct tile *ptile,
                                   struct danger_node *d_node1, int length)
 {
   int i;
-  struct tile *ptile = pf_map->tile;
   struct pf_node *node = &pf_map->lattice[ptile->index];
 
   /* Allocating memory */
@@ -855,7 +855,7 @@
   across danger, supply get_EC which returns small extra on 
   dangerous tiles.
 *****************************************************************************/
-static bool danger_iterate_map(struct pf_map *pf_map)
+static bool danger_iterate_map(struct pf_map *pf_map, bool return_dangerous)
 {
   mapindex_t index;
   struct pf_node *node = &pf_map->lattice[pf_map->tile->index];
@@ -946,7 +946,7 @@
           }
          if (d_node->is_dangerous) {
            /* Transition from red to blue, need to record the path back */
-           create_danger_segment(pf_map, dir, d_node1, 
+           create_danger_segment(pf_map, pf_map->tile, d_node1, 
                                   d_node->segment_length);
          } else {
             /* We don't consider waiting to get to a safe tile as 
@@ -1028,12 +1028,14 @@
     /* We've already returned this node once, skip it */
     freelog(LOG_DEBUG, "Considering waiting at (%d, %d)",
            pf_map->tile->x, pf_map->tile->y);
-    return danger_iterate_map(pf_map);
+    return danger_iterate_map(pf_map, return_dangerous);
   } else if (pf_map->d_lattice[index].is_dangerous) {
     /* We don't return dangerous tiles */
-    freelog(LOG_DEBUG, "Reached dangerous tile (%d, %d)",
-           pf_map->tile->x, pf_map->tile->y);
-    return danger_iterate_map(pf_map);
+    freelog(LOG_DEBUG, "Reached dangerous (%d, %d); cost %d, moves left %d",
+           pf_map->tile->x, pf_map->tile->y, pf_map->lattice[index].cost,
+            get_moves_left(pf_map, pf_map->lattice[index].cost));
+    return (return_dangerous ? TRUE 
+            : danger_iterate_map(pf_map, return_dangerous));
   } else {
     /* Just return it */
     return TRUE;
@@ -1045,16 +1047,16 @@
   NB: will only find paths to safe tiles!
 *******************************************************************/
 static struct pf_path *danger_construct_path(const struct pf_map *pf_map,
-                                             struct tile *ptile)
+                                             struct tile *ptile,
+                                             struct pf_danger_pos *d_seg)
 {
   struct pf_path *path = fc_malloc(sizeof(*path));
   int i;
   enum direction8 dir_next = -1;
-  struct pf_danger_pos *danger_seg = NULL;     /* For danger segments */
-  int segment_index = -1;                       /* For danger segments */
-  bool waited = FALSE;
+  int segment_index = 0;                        /* For danger segments */
   struct pf_node *node = &pf_map->lattice[ptile->index];
   struct danger_node *d_node = &pf_map->d_lattice[ptile->index];
+  bool waited = (d_seg ? d_node->waited : FALSE);
 
   if (pf_map->params->turn_mode != TM_BEST_TIME &&
       pf_map->params->turn_mode != TM_WORST_TIME) {
@@ -1098,9 +1100,9 @@
       path->positions[i].total_EC = node->extra_cost;
     } else {
       /* When on dangerous tiles, must have a valid danger segment */
-      assert(danger_seg != NULL);
-      path->positions[i].total_MC = danger_seg[segment_index].cost;
-      path->positions[i].total_EC = danger_seg[segment_index].extra_cost;
+      assert(d_seg != NULL);
+      path->positions[i].total_MC = d_seg[segment_index].cost;
+      path->positions[i].total_EC = d_seg[segment_index].extra_cost;
     } 
     path->positions[i].turn = get_turn(pf_map, path->positions[i].total_MC);
     path->positions[i].moves_left 
@@ -1122,12 +1124,12 @@
       dir_next = node->dir_to_here;
       /* d_node->danger_segment is the indicator of what lies ahead
        * if it's non-NULL, we are entering a danger segment, 
-       * if it's NULL, we are not on one so danger_seg should be NULL */
-      danger_seg = d_node->danger_segment;
+       * if it's NULL, we are not on one so d_seg should be NULL */
+      d_seg = d_node->danger_segment;
       segment_index = 0;
     } else {
       /* We are in a danger segment */
-      dir_next = danger_seg[segment_index].dir;
+      dir_next = d_seg[segment_index].dir;
       segment_index++;
     }
 
@@ -1151,6 +1153,14 @@
   mapindex_t index = ptile->index;
   utiny_t status = pf_map->status[index];
   struct danger_node *d_node = &pf_map->d_lattice[index];
+  
+  /* Initialise target tile to set the is_dangerous field */
+  if (pf_map->status[index] == NS_UNINIT) {
+    struct pf_node *node = &pf_map->lattice[index];
+
+    init_node(pf_map, node, ptile);
+    init_danger_node(pf_map, d_node, node, ptile);
+  }
 
   if (d_node->is_dangerous) {
     /* "Best" path to a dangerous tile is undefined */
@@ -1161,13 +1171,55 @@
   if (status == NS_PROCESSED || status == NS_WAITING 
       || same_pos(ptile, pf_map->tile)) {
     /* We already reached (x,y) */
-    return danger_construct_path(pf_map, ptile);
+    return danger_construct_path(pf_map, ptile, NULL);
   }
 
   while (pf_next(pf_map)) {
     if (same_pos(ptile, pf_map->tile)) {
       /* That's the one */
-      return danger_construct_path(pf_map, ptile);
+      return danger_construct_path(pf_map, ptile, NULL);
+    }
+  }
+
+  return NULL;
+}
+
+/************************************************************************
+  Force the path to a dangerous tile.
+************************************************************************/
+struct pf_path *pf_force_get_path(struct pf_map *pf_map, struct tile *ptile)
+{
+  mapindex_t index = ptile->index;
+  utiny_t status = pf_map->status[index];
+  struct danger_node *d_node = &pf_map->d_lattice[index];
+  struct pf_node *node = &pf_map->lattice[index];
+  
+  /* Initialise target tile to set the is_dangerous field */
+  if (status == NS_UNINIT) {
+    struct pf_node *node = &pf_map->lattice[index];
+
+    init_node(pf_map, node, ptile);
+    init_danger_node(pf_map, d_node, node, ptile);
+  }
+
+  if (!d_node->is_dangerous) {
+    /* Dialed a wrong number */
+    return NULL;
+  }
+
+  while (danger_iterate_map(pf_map, TRUE)) {
+    if (same_pos(ptile, pf_map->tile)) {
+      /* That's the one */
+      struct tile *itile = ptile;
+      struct pf_path *path;
+      int i;
+      
+      create_danger_segment(pf_map, ptile, d_node, d_node->segment_length);
+      path = danger_construct_path(pf_map, ptile, d_node->danger_segment);
+      free(d_node->danger_segment);
+      d_node->danger_segment = NULL;
+
+      return path;
     }
   }
 
Index: common/aicore/path_finding.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.h,v
retrieving revision 1.10
diff -u -r1.10 path_finding.h
--- common/aicore/path_finding.h        29 Sep 2004 02:24:23 -0000      1.10
+++ common/aicore/path_finding.h        28 Nov 2004 02:40:29 -0000
@@ -426,4 +426,7 @@
 /* Return the current parameters for the given map. */
 struct pf_parameter *pf_get_parameter(struct pf_map *map);
 
+/* Force return of a path to a dangerous tile */
+struct pf_path *pf_force_get_path(struct pf_map *pf_map, struct tile *ptile);
+
 #endif

[Prev in Thread] Current Thread [Next in Thread]