Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2001:
[Freeciv-Dev] Citypref patch
Home

[Freeciv-Dev] Citypref patch

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Citypref patch
From: Andrew <andrew@xxxxxxxxxxx>
Date: Thu, 25 Jan 2001 22:06:26 -0500
Reply-to: andrew@xxxxxxxxxxx

This diff file was made against a CVS copy downloaded on 5PM EST 25 Jan
2001.

Attached is the corrected citypref patch. Following changes have been
made:

a. added "buildfirst" global worklist. If buildfirst exists, it's
entries take precedence over a city's local worklist. Local city
worklists have precedence over a citypref worklist.
b. buildfirst & citypref apply when a city is created;
c. if the city supports a unit of type_id, citypref and buildfirst will
not change build target to a unit of that type_id. This is to avoid the
"infinite rifleman" problem.

Note: had to move around some of the initializations in
server/cityhand.c: create_city because of dependencies in the buildlist
and citypref functions.

Andrew.
diff -r -u freeciv/server/cityhand.c freeciv3/server/cityhand.c
--- freeciv/server/cityhand.c   Fri Jan 19 21:00:58 2001
+++ freeciv3/server/cityhand.c  Thu Jan 25 18:12:04 2001
@@ -174,10 +174,8 @@
   pcity->shield_stock=0;
   pcity->trade_prod=0;
   pcity->original = pplayer->player_no;
-  pcity->is_building_unit=1;
   pcity->did_buy=-1; /* code so we get a different message */
   pcity->airlift=0;
-  pcity->currently_building=best_role_unit(pcity, L_FIRSTBUILD);
 
   /* Set up the worklist */
   pcity->worklist = create_worklist();
@@ -215,9 +213,21 @@
   /* Before arranging workers to show unknown land */
   map_unfog_pseudo_city_area(pplayer, x, y);
 
+  unit_list_init(&pcity->units_supported);
+
+       /* if buildlist global worklist exists, then build according
+                to buildlist, else look for citypref buildlist. If citypref
+          doesn't exist either, then use best_role_unit function */
+
+       if (!buildfirst_change_build_target(pplayer, pcity)) {
+               if      (!citypref_change_build_target(pplayer, pcity)) {
+                       pcity->currently_building = best_role_unit(pcity, 
L_FIRSTBUILD);
+                       pcity->is_building_unit = 1;
+               }
+       }
+
   map_set_city(x, y, pcity);
 
-  unit_list_init(&pcity->units_supported);
   city_list_insert(&pplayer->cities, pcity);
   add_city_to_minimap(x, y);
 
diff -r -u freeciv/server/cityturn.c freeciv3/server/cityturn.c
--- freeciv/server/cityturn.c   Wed Jan 24 09:18:11 2001
+++ freeciv3/server/cityturn.c  Thu Jan 25 21:16:31 2001
@@ -1058,6 +1058,190 @@
 }
 
 /**************************************************************************
+
+  Implement citypref feature:
+
+  If a global worklist named "citypref" exists, then use that worklist
+       and change build target. Return 0 if no targets are available, otherwise
+       return non-zero. Makes no changes to the citypref worklist
+**************************************************************************/
+
+int citypref_change_build_target (struct player *pplayer, struct city *pcity)
+{
+       int i;
+       int citypref_idx = -1;
+
+       /* which global worklist is named "citypref"? */
+
+       freelog(LOG_DEBUG, "citypref: entered citypref_change_build_target");
+
+       for (i=0; i<=MAX_NUM_WORKLISTS; i++) {
+               freelog(LOG_DEBUG, "citypref: looking at worklist %s", 
pplayer->worklists[i].name);
+               if (!strcmp(pplayer->worklists[i].name,"citypref")) 
citypref_idx = i;
+       }
+
+       /* if none named citypref, then return 0 */
+
+       if (citypref_idx == -1) return 0;
+
+       freelog(LOG_DEBUG, "citypref: returning from 
citypref_change_build_target");
+
+       return buildfirst_and_citypref(pplayer, pcity, citypref_idx);
+
+}
+
+/**************************************************************************
+
+  Implement buildfirst feature:
+
+  If a global worklist named "buildfirst" exists, then use that worklist
+       _before_ checking the city's worklist. Return 0 if no targets are 
available, 
+       otherwise return non-zero. Makes no changes to the citypref worklist
+**************************************************************************/
+
+int buildfirst_change_build_target (struct player *pplayer, struct city *pcity)
+{
+       int i;
+       int buildfirst_idx = -1;
+
+       /* which global worklist is named "citypref"? */
+
+       freelog(LOG_NORMAL, "citypref: entered buildfirst_change_build_target");
+
+       for (i=0; i<=MAX_NUM_WORKLISTS; i++) {
+               freelog(LOG_NORMAL, "buildfirst: looking at worklist %s", 
pplayer->worklists[i].name);
+               if (!strcmp(pplayer->worklists[i].name,"buildfirst")) 
buildfirst_idx = i;
+       }
+
+       /* if none named buildfirst, then return 0 */
+
+       if (buildfirst_idx == -1) return 0;
+
+       freelog(LOG_NORMAL, "citypref: returning from 
buildfirst_change_build_target");
+
+       return buildfirst_and_citypref(pplayer, pcity, buildfirst_idx);
+
+}
+
+int buildfirst_and_citypref (struct player *pplayer, struct city *pcity, int 
worklist_idx)
+{
+       int success = 0;
+       int i;
+
+       /* get a valid target from the citypref (or buildfirst) worklist
+                use the same algorithm as worklist_change_build_target,
+                but don't delete locally invalid entries from the global 
worklist */
+
+       freelog(LOG_NORMAL, "citypref: entered buildfirst_and_citypref");
+
+  i = 0;
+  while (1) {
+    int target, is_unit;
+
+    /* What's the next item in the worklist? */
+    if (!worklist_peek_ith( &pplayer->worklists[worklist_idx], &target, 
&is_unit, i))
+      /* Nothing more in the worklist.  Ah, well. */
+      break;
+
+               if (is_unit) {
+                       freelog(LOG_NORMAL, _("citypref: examining target %s 
%d"), get_unit_type(target)->name, target);
+               } else {
+                       freelog(LOG_NORMAL, _("citypref: examining target %s"), 
get_impr_name_ex(pcity,target));
+               }
+
+    i++;
+
+               /* if the city already supports a unit of that type, then don't 
build another */
+
+    if (is_unit && list_has_unit_type(pcity->units_supported, target)) 
continue;
+
+               /* Sanity checks. First, target is a unit but the city can't 
build it */
+    if (is_unit && !can_build_unit(pcity, target)) {
+      int new_target = unit_upgrades_to(pcity, target);
+
+                       if (list_has_unit_type(pcity->units_supported, 
new_target)) continue;
+
+      /* Maybe we can just upgrade the target to what the city /can/ build. */
+      if (new_target == target) {
+                               /* No upgrade available. Advise the player and 
proceed to next item in the worklist */
+                               notify_player_ex(pplayer, pcity->x, pcity->y, 
E_CITY_CANTBUILD,
+                                                                               
                 _("Game: %s cannot build %s from the %s worklist.  "),
+                                                                               
                 pcity->name,   get_unit_type(target)->name, 
+                                                                               
                 pplayer->worklists[worklist_idx].name);
+                               continue;
+                       } else {
+                               /* Yes, we can go after new_target instead. */
+                               /* but only if the city does not already 
support a unit of that type */
+                               if (list_has_unit_type(pcity->units_supported, 
new_target)) {
+                                       notify_player_ex(pplayer, pcity->x, 
pcity->y, E_WORKLIST,
+                                                                               
                         _("Game: %s skipping obsolete unit (%s) in the %s 
worklist."),
+                                                                               
                         pcity->name, get_unit_type(new_target)->name,
+                                                                               
                         pplayer->worklists[worklist_idx].name);
+                                       continue;
+                               } else {
+                                       notify_player_ex(pplayer, pcity->x, 
pcity->y, E_WORKLIST,
+                                                                               
                         _("Game: %s upgrading production target in %s worklist 
to %s."),
+                                                                               
                         pcity->name, pplayer->worklists[worklist_idx].name, 
+                                                                               
                         get_unit_type(new_target)->name);
+                               }
+      }
+    } else if (!is_unit && !can_build_improvement(pcity, target)) {
+      int new_target = improvement_upgrades_to(pcity, target);
+
+      /* Maybe this improvement has been obsoleted by something that we can 
build. */
+      if (new_target == target) {
+                               /* No. Warn the player and move to next id in 
worklist */
+
+                               /* Does the city already have that improvement? 
*/
+                               if (city_got_building(pcity, target)) {
+                                       freelog(LOG_NORMAL, "citypref: %s 
already has %s", pcity->name, 
+                                                                       
get_impr_name_ex(pcity, target));
+                               } else {
+                                       freelog(LOG_NORMAL, "citypref: %s can't 
build %s", pcity-> name,
+                                                                       
get_impr_name_ex(pcity, target));
+                                       notify_player_ex(pplayer, pcity->x, 
pcity->y, E_CITY_CANTBUILD,
+                                                                               
                         _("Game: %s can't build %s from the %s worklist; "),
+                                                                               
                         pcity->name, get_impr_name_ex(pcity, target),
+                                                                               
                         pplayer->worklists[worklist_idx].name);
+                               }
+                               continue;
+      } else {
+                               /* Hey, we can upgrade the improvement!  */
+                               notify_player_ex(pplayer, pcity->x, pcity->y, 
E_WORKLIST,
+                                                                               
                 _("Game: %s skipping obsolete improvement (%s) in the %s 
worklist."),
+                                                                               
                 pcity->name, 
+                                                                               
                 get_impr_name_ex(pcity, target), 
pplayer->worklists[worklist_idx].name);
+                               target = new_target;
+      }
+    }
+
+    /* All okay.  Switch targets. */
+    change_build_target(pplayer, pcity, target, is_unit, E_WORKLIST);
+
+    success = 1;
+    break;
+  }
+
+       freelog(LOG_NORMAL, "Exiting buildfirst_and_citypref");
+       return success;
+
+}
+
+/*************************************************
+  If list inludes a unit of type target_unit_type
+       return 1, else return 0
+ ***********************************************/
+
+int list_has_unit_type (struct unit_list units_supported, Unit_Type_id 
target_unit_type)
+{
+       unit_list_iterate(units_supported, punit) {
+               if (punit->type == target_unit_type) return 1;
+       }
+       unit_list_iterate_end;
+       return 0;
+}
+
+/**************************************************************************
   Examine the worklist and change the build target.  Return 0 if no
   targets are available to change to.  Otherwise return non-zero.  Has
   the side-effect of removing from the worklist any no-longer-available
@@ -1068,9 +1252,12 @@
   int success = 0;
   int i;
 
+       if (buildfirst_change_build_target(pplayer, pcity)) return 1;
+
   if (worklist_is_empty(pcity->worklist))
-    /* Nothing in the worklist; bail now. */
-    return 0;
+    /* Nothing in the city's worklist; check the citypref
+                  global worklist  */
+    return citypref_change_build_target(pplayer, pcity);
 
   i = 0;
   while (1) {
@@ -1187,6 +1374,8 @@
                     _("Game: %s's worklist is now empty."),
                     pcity->name);
   }
+
+       if (!success) success = citypref_change_build_target(pplayer, pcity);
 
   return success;
 }
diff -r -u freeciv/server/cityturn.h freeciv3/server/cityturn.h
--- freeciv/server/cityturn.h   Wed Dec 20 11:52:59 2000
+++ freeciv3/server/cityturn.h  Thu Jan 25 18:10:29 2001
@@ -37,5 +37,9 @@
 void city_incite_cost(struct city *pcity);
 void remove_obsolete_buildings_city(struct city *pcity, int refresh);
 void remove_obsolete_buildings(struct player *plr);
+int buildfirst_and_citypref (struct player *pplayer, struct city *pcity, int 
worklist_idx);
+int buildfirst_change_build_target (struct player *pplayer, struct city 
*pcity);
+int citypref_change_build_target (struct player *pplayer, struct city *pcity);
+int list_has_unit_type (struct unit_list units_supported, Unit_Type_id 
target_unit_type);
 
 #endif  /* FC__CITYTURN_H */

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