[Freeciv-Dev] Citypref patch
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
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 */
|
|