Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2000:
[Freeciv-Dev] Dynamic worklists
Home

[Freeciv-Dev] Dynamic worklists

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Dynamic worklists
From: Richard Atkins <rja@xxxxxxxxxxx>
Date: Tue, 25 Apr 2000 14:53:06 +1000 (EST)

Hi all,

Just updating my dynamic worklists patch.

Now in the gtk client:
- when inserting a global worklist, the targets list is updated.
- when inserting an improvement, the targets list is updated and the item
after the target is reselected (and the scroll recenters on it)
- when deleting an improvement, the targets list is updated, and the
target last selected is reselected and recentered.

In the server:
- the server now processes the whole of each cities worklist, and upgrades
anything it can/deletes anything obsolete
- added functions to do similar processing to a player's global worklist
every turn. This could probably be optimized later by only doing this when
something happens that would require it: discovered a tech, built a
wonder, gained/lost a wonder etc.

This pretty much does what was suggested earlier

Richard

--------
       Richard Atkins  rja@xxxxxxxxxxx
       http://www.pcug.org.au/~rja/

       "All these moments will be lost in
       time, like tears in the rain."
                              Blade Runner
                                         --------

--- cvs-freeciv/server/cityturn.c       Mon Apr 24 16:25:50 2000
+++ mod-freeciv/server/cityturn.c       Tue Apr 25 13:02:17 2000
@@ -959,13 +959,14 @@
 {
   int success = 0;
   int i;
+  int change_target_idx = 0;
 
   if (worklist_is_empty(pcity->worklist))
     /* Nothing in the worklist; bail now. */
     return 0;
 
   i = 0;
-  while (1) {
+  while (i < MAX_LEN_WORKLIST) {
     int target, is_unit;
 
     /* What's the next item in the worklist? */
@@ -1001,12 +1002,13 @@
 
       /* Maybe we can just upgrade the target to what the city /can/ build. */
       if (new_target == target) {
-       /* Nope, we're stuck.  Dump this item from the worklist. */
-       notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
-                        _("Game: %s can't build %s from the worklist; "
-                          "tech not yet available.  Postponing..."),
-                        pcity->name,
-                        get_unit_type(target)->name);
+       /* Nope, we're stuck.  Postpone until we can build target. */
+       if (!success)
+         notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
+                          _("Game: %s can't build %s from the worklist; "
+                            "tech not yet available.  Postponing..."),
+                          pcity->name,
+                          get_unit_type(target)->name);
        continue;
       } else {
        /* Yep, we can go after new_target instead.  Joy! */
@@ -1042,11 +1044,12 @@
         we can build. */
       if (new_target == target) {
        /* Nope, no use.  *sigh*  */
-       notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
-                        _("Game: %s can't build %s from the worklist; "
-                          "tech not yet available.  Postponing..."),
-                        pcity->name,
-                        get_impr_name_ex(pcity, target));
+       if (!success)
+         notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
+                          _("Game: %s can't build %s from the worklist; "
+                            "tech not yet available.  Postponing..."),
+                          pcity->name,
+                          get_impr_name_ex(pcity, target));
        continue;
       } else {
        /* Hey, we can upgrade the improvement!  */
@@ -1059,17 +1062,16 @@
       }
     }
 
-    /* All okay.  Switch targets. */
-    change_build_target(pplayer, pcity, target, is_unit, E_WORKLIST);
-
-    success = 1;
-    break;
+    if (!success) {
+      /* All okay.  Switch targets. */
+      change_build_target(pplayer, pcity, target, is_unit, E_WORKLIST);
+      change_target_idx = i-1;
+      success = 1;
+    }
   }
 
   if (success) {
-    /* i is the index immediately _after_ the item we're changing to.
-       Remove the (i-1)th item from the worklist. */
-    worklist_remove(pcity->worklist, i-1);
+    worklist_remove(pcity->worklist, change_target_idx);
   }
 
   if (worklist_is_empty(pcity->worklist)) {
--- cvs-freeciv/server/plrhand.c        Wed Apr 19 14:53:48 2000
+++ mod-freeciv/server/plrhand.c        Tue Apr 25 12:56:02 2000
@@ -77,6 +77,12 @@
 };
 
 static void update_player_aliveness(struct player *pplayer);
+static Unit_Type_id player_upgrade_unit(struct player *pplayer,
+                                       Unit_Type_id id);
+static int player_upgrade_improvement(struct player *pplayer, int imp);
+static void update_player_worklist(struct player *pplayer,
+                                  struct worklist *pwl);
+static void update_player_worklists(struct player *pplayer);
 
 struct player_score_entry {
   int idx;
@@ -1362,6 +1368,7 @@
   if (city_list_size(&pplayer->cities)) /* has to be below the above for 
got_tech */ 
     update_tech(pplayer, city_list_size(&pplayer->cities));
 #endif
+  update_player_worklists(pplayer);
   update_unit_activities(pplayer);
   update_player_aliveness(pplayer);
 }
@@ -1385,6 +1392,78 @@
       map_know_and_see_all(pplayer);
     }
   }
+}
+
+static Unit_Type_id player_upgrade_unit(struct player *pplayer,
+                                       Unit_Type_id id)
+{
+  Unit_Type_id latest_ok = id;
+  if (!can_player_build_unit_direct(pplayer, id))
+    return -1;
+  while (unit_type_exists(id = unit_types[id].obsoleted_by))
+    if (can_player_build_unit_direct(pplayer, id))
+      latest_ok = id;
+
+  return latest_ok;
+}
+
+static int player_upgrade_improvement(struct player *pplayer, int imp)
+{
+  if (imp == B_BARRACKS && can_player_build_improvement(pplayer, B_BARRACKS3))
+    return B_BARRACKS3;
+  else if (imp == B_BARRACKS &&
+          can_player_build_improvement(pplayer, B_BARRACKS2))
+    return B_BARRACKS2;
+  else if (imp == B_BARRACKS2 &&
+          can_player_build_improvement(pplayer, B_BARRACKS3))
+    return B_BARRACKS3;
+  else
+    return imp;
+}
+
+static void update_player_worklist(struct player *pplayer,
+                                  struct worklist *pwl)
+{
+  int i, target, is_unit, new_target;
+
+  i = 0;
+  while (i < MAX_LEN_WORKLIST) {
+    if (!worklist_peek_ith(pwl, &target, &is_unit, i))
+      break;
+    i++;
+    if (is_unit && !can_player_eventually_build_unit(pplayer, target)) {
+      new_target = player_upgrade_unit(pplayer, target);
+      if (!can_player_eventually_build_unit(pplayer, new_target)) {
+       /* Nope, the player can't build this target, ever. */
+       /* purge this worklist item. */
+       worklist_remove(pwl, i-1);
+       i--;
+       continue;
+      }
+      /* new_target is what will go in the list */
+      target = new_target;
+      pwl->ids[i-1] = target+B_LAST;
+    } else if (!is_unit &&
+              !could_player_eventually_build_improvement(pplayer, target)) {
+      new_target = player_upgrade_improvement(pplayer, target);
+      if(!could_player_eventually_build_improvement(pplayer, new_target)) {
+       worklist_remove(pwl, i-1);
+       i--;
+       continue;
+      }
+      /* new_target is what will go in the list */
+      target = new_target;
+      pwl->ids[i-1] = target;
+    }
+  }
+}
+
+static void update_player_worklists(struct player *pplayer)
+{
+  int i;
+  for (i = 0; i < MAX_NUM_WORKLISTS; i++)
+    if (pplayer->worklists[i].is_valid)
+      update_player_worklist(pplayer, &pplayer->worklists[i]);
 }
 
 /**************************************************************************
--- cvs-freeciv/client/gui-gtk/wldlg.c  Sun Apr  2 20:54:39 2000
+++ mod-freeciv/client/gui-gtk/wldlg.c  Tue Apr 25 13:27:56 2000
@@ -793,8 +793,8 @@
 void insert_into_worklist(struct worklist_dialog *pdialog, 
                          int before, int id)
 {
-  int i, first_free;
-  int target, is_unit;
+  int i, j, first_free;
+  int target, is_unit, is_building;
 
   if (id >= B_LAST) {
     target = id - B_LAST;
@@ -808,14 +808,30 @@
      really can (eventually) build the target.  We've made sure that
      the list of available targets is okay for this city, but a global
      worklist may try to insert an odd-ball unit or target. */
-  if (pdialog->pcity &&
-      ((is_unit  && !can_eventually_build_unit(pdialog->pcity, target)) ||
-       (!is_unit && !can_eventually_build_improvement(pdialog->pcity, 
target))))
-    /* Nope, this city can't build this target, ever.  Don't put it into
-       the worklist. */
-    return;
-    
-
+  if (pdialog->pcity) {
+    if ((is_unit  && !can_eventually_build_unit(pdialog->pcity, target)) ||
+       (!is_unit && 
+       !can_eventually_build_improvement(pdialog->pcity, target))) {
+      /* Nope, this city can't build this target, ever.  Don't put it into
+        the worklist. */
+      return;
+    }
+    if (!is_unit && can_eventually_build_improvement(pdialog->pcity, target)) {
+      j = 0;
+      is_building = FALSE;
+      while ((j < MAX_LEN_WORKLIST) && 
+            (pdialog->worklist_ids[j] != WORKLIST_END)) {
+       if (pdialog->worklist_ids[j] == target) {
+         is_building = TRUE;
+         break;
+       }
+       j++;
+      }
+      if (is_building)
+       /* city is already building this item, so don't add it. */
+       return;
+    }
+  }
   /* Find the first free element in the worklist */
   for (first_free = 0; first_free < MAX_LEN_WORKLIST; first_free++)
     if (pdialog->worklist_ids[first_free] == WORKLIST_END)
@@ -918,12 +934,17 @@
       if (where < MAX_LEN_WORKLIST)
        where++;
     }
+
+    /* Update the list of available targets */
+    worklist_populate_targets(pdialog);
+    update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+    /* note no target selected */
   } else if (idx >= pdialog->worklist_avail_num_improvements) {
-    /* target is an improvement or wonder */
+    /* target is a unit */
     insert_into_worklist(pdialog, where, target+B_LAST);
     where++;
   } else {
-    /* target is a unit */
+    /* target is an improvement or wonder */
     insert_into_worklist(pdialog, where, target);
     where++;
   }
@@ -937,8 +958,20 @@
       break;
 
   /* Re-select the item that was previously selected. */
-  if (where < len)
+  if (where < len) {
     gtk_clist_select_row((GtkCList *)pdialog->worklist, where, 0);
+    gtk_clist_moveto((GtkCList *)pdialog->worklist, where, 0, 0.5, 0);
+  }
+
+  if (idx < pdialog->worklist_avail_num_improvements) {
+    /* Update the list of available targets */
+    worklist_populate_targets(pdialog);
+    update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+
+    /* Select the next available target */
+    gtk_clist_select_row((GtkCList *)pdialog->avail, idx, 0);
+    gtk_clist_moveto((GtkCList *)pdialog->avail, idx, 0, 0.5, 0);
+  }
 }
 
 /****************************************************************
@@ -948,12 +981,21 @@
 {
   struct worklist_dialog *pdialog = (struct worklist_dialog *)data;
   GList *selection = GTK_CLIST(pdialog->worklist)->selection;
-  int i, j, k;
+  GList *avail_selection = GTK_CLIST(pdialog->avail)->selection;
+  int i, j, k, id, avail_idx, avail_id, avail_num_improvements;
+  avail_idx = avail_id = avail_num_improvements = 0;
 
   if (! selection)
     return;
 
   k = (int)selection->data;
+  id = pdialog->worklist_ids[k];
+
+  if (avail_selection != NULL) {
+    avail_idx = (int)avail_selection->data;
+    avail_id = pdialog->worklist_avail_ids[avail_idx];
+    avail_num_improvements = pdialog->worklist_avail_num_improvements;
+  }
 
   /* Find the last element in the worklist */
   for (i = 0; i < MAX_LEN_WORKLIST; i++)
@@ -982,8 +1024,28 @@
 
   /* Select the item immediately after the item we just deleted,
      if there is such an item. */
-  if (k < i)
+  if (k < i) {
     gtk_clist_select_row((GtkCList *)pdialog->worklist, k, 0);
+    gtk_clist_moveto((GtkCList *)pdialog->worklist, k, 0, 0.5, 0);
+  }
+
+  if (id < B_LAST) {
+    /* Update the list of available targets */
+    worklist_populate_targets(pdialog);
+    update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+    
+    /* Select the avail item previously selected */
+    if (avail_selection != NULL) {
+      /* id *might* have been inserted in the list */
+      if ((id < avail_id) && (avail_num_improvements < 
+                             pdialog->worklist_avail_num_improvements)) {
+       /* id is in the list before what was selected */
+       avail_idx++;
+      }
+      gtk_clist_select_row((GtkCList *)pdialog->avail, avail_idx, 0);
+      gtk_clist_moveto((GtkCList *)pdialog->avail, avail_idx, 0, 0.5, 0);
+    }
+  }
 }
 
 /****************************************************************
@@ -1230,10 +1292,10 @@
 *****************************************************************/
 void worklist_populate_targets(struct worklist_dialog *pdialog)
 {
-  int i, n;
+  int i, j, n;
   struct player *pplr = game.player_ptr;
   int advanced_tech;
-  int can_build, can_eventually_build;
+  int can_build, can_eventually_build, is_building;
   
 
   n = 0;
@@ -1253,6 +1315,18 @@
     can_build = can_player_build_improvement(pplr,i);
     can_eventually_build = could_player_eventually_build_improvement(pplr,i);
 
+    /* Is the player already going to build this improvement? */
+    j = 0;
+    is_building = FALSE;
+    while ((j < MAX_LEN_WORKLIST) && 
+          (pdialog->worklist_ids[j] != WORKLIST_END)) {
+      if (pdialog->worklist_ids[j] == i) {
+       is_building = TRUE;
+       break;
+      }
+      j++;
+    }
+
     /* If there's a city, can the city build the improvement? */
     if (pdialog->pcity) {
       can_build = can_build && can_build_improvement(pdialog->pcity, i);
@@ -1260,8 +1334,9 @@
        can_eventually_build_improvement(pdialog->pcity, i);
     }
     
-    if (( advanced_tech && can_eventually_build) ||
-       (!advanced_tech && can_build)) {
+    if ((( advanced_tech && can_eventually_build) ||
+        (!advanced_tech && can_build)) &&
+       !is_building) {
       worklist_id_to_name(pdialog->worklist_avail_names[n],
                          i, 0, pdialog->pcity);
       pdialog->worklist_avail_names_ptrs[n]=pdialog->worklist_avail_names[n];
@@ -1272,11 +1347,11 @@
 
   /*     + Second, units. */
   for(i=0; i<game.num_unit_types; i++) {
-    /* Can the player (eventually) build this improvement? */
+    /* Can the player (eventually) build this unit? */
     can_build = can_player_build_unit(pplr,i);
     can_eventually_build = can_player_eventually_build_unit(pplr,i);
 
-    /* If there's a city, can the city build the improvement? */
+    /* If there's a city, can the city build the unit? */
     if (pdialog->pcity) {
       can_build = can_build && can_build_unit(pdialog->pcity, i);
       can_eventually_build = can_eventually_build &&

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Dynamic worklists, Richard Atkins <=