diff ai/advdomestic.c ai/advdomestic.c --- ai/advdomestic.c Thu Jan 18 03:21:04 2001 +++ ai/advdomestic.c Sat Jan 20 12:52:47 2001 @@ -31,12 +31,6 @@ #include "advdomestic.h" -/********************************************************************** -... this function should assign a value to choice and want and type, where - want is a value between 1 and 100. - if want is 0 this advisor doesn't want anything - type = 1 means unit, type = 0 means building -***********************************************************************/ static int ai_best_tile_value(struct city *pcity) { @@ -523,7 +517,13 @@ } return; -} +} + +/********************************************************************** +... this function should assign a value to choice and want and type, where + want is a value between 1 and 100. + if want is 0 this advisor doesn't want anything +***********************************************************************/ void domestic_advisor_choose_build(struct player *pplayer, struct city *pcity, struct ai_choice *choice) @@ -538,7 +538,7 @@ choice->choice = 0; choice->want = 0; - choice->type = 0; + choice->type = CT_NONE; con = map_get_continent(pcity->x, pcity->y); utid = best_role_unit(pcity, F_SETTLERS); @@ -553,11 +553,11 @@ freelog(LOG_DEBUG, "%s (%d, %d) desires settlers with passion %d", pcity->name, pcity->x, pcity->y, want); choice->want = want; - choice->type = 1; + choice->type = CT_NONMIL; ai_choose_role_unit(pplayer, pcity, choice, F_SETTLERS, want); } else if (want < 0) { /* need boats to colonize! */ choice->want = 0 - want; - choice->type = 1; + choice->type = CT_NONMIL; choice->choice = best_role_unit(pcity, F_SETTLERS); /* default */ ai_choose_ferryboat(pplayer, pcity, choice); } @@ -576,11 +576,11 @@ freelog(LOG_DEBUG, "%s (%d, %d) desires founders with passion %d", pcity->name, pcity->x, pcity->y, want); choice->want = want; - choice->type = 1; + choice->type = CT_NONMIL; ai_choose_role_unit(pplayer, pcity, choice, F_CITIES, want); } else if (want < -choice->want) { /* need boats to colonize! */ choice->want = 0 - want; - choice->type = 1; + choice->type = CT_NONMIL; choice->choice = best_role_unit(pcity, F_CITIES); /* default */ ai_choose_ferryboat(pplayer, pcity, choice); } @@ -617,7 +617,7 @@ if (can_build_unit_direct(pcity, iunit)) { if (want > choice->want) { choice->want = want; - choice->type = 1; + choice->type = CT_NONMIL; ai_choose_role_unit(pplayer, pcity, choice, F_CARAVAN, dw/2); } } else @@ -631,7 +631,7 @@ choice->want = cur.want; /* if (choice->want > 100) choice->want = 100; */ /* want > 100 means BUY RIGHT NOW */ - choice->type = 0; + choice->type = CT_BUILDING; } /* allowing buy of peaceful units after much testing -- Syela */ @@ -643,7 +643,7 @@ } if (iunit != U_LAST) { choice->want = 1; - choice->type = 1; + choice->type = CT_NONMIL; choice->choice = iunit; } } diff ai/advmilitary.c ai/advmilitary.c --- ai/advmilitary.c Thu Jan 18 03:21:04 2001 +++ ai/advmilitary.c Sat Jan 20 12:52:47 2001 @@ -525,7 +525,7 @@ } choice->choice = bestid; choice->want = danger; - choice->type = 3; + choice->type = CT_DEFENDER; return; } @@ -859,11 +859,11 @@ choice->choice = B_BARRACKS2; else choice->choice = B_BARRACKS; choice->want = e; - choice->type = 0; + choice->type = CT_BUILDING; } else { if (!myunit->id) { choice->choice = v; - choice->type = 2; /* type == 2 identifies attackers */ + choice->type = CT_ATTACKER; choice->want = e; if (needferry) ai_choose_ferryboat(pplayer, pcity, choice); freelog(LOG_DEBUG, "%s has chosen attacker, %s", @@ -872,7 +872,7 @@ choice->choice = ai_choose_defender(pcity); freelog(LOG_DEBUG, "%s has chosen defender, %s", pcity->name, unit_types[choice->choice].name); - choice->type = 1; + choice->type = CT_NONMIL; choice->want = e; } if (is_sailing_unit(myunit) && improvement_exists(B_PORT) @@ -881,7 +881,7 @@ if (get_invention(pplayer, tech) == TECH_KNOWN) { choice->choice = B_PORT; choice->want = e; - choice->type = 0; + choice->type = CT_BUILDING; } else pplayer->ai.tech_want[tech] += e; } } @@ -919,7 +919,6 @@ ... this function should assign a value to choice and want and type, where want is a value between 1 and 100. if want is 0 this advisor doesn't want anything - type = 1 means unit, type = 0 means building ***********************************************************************/ void military_advisor_choose_build(struct player *pplayer, struct city *pcity, struct ai_choice *choice) @@ -933,7 +932,7 @@ struct unit *aunit = 0; choice->choice = 0; choice->want = 0; - choice->type = 0; + choice->type = CT_NONE; /* TODO: recognize units that can DEFEND_HOME but are in the field. -- Syela */ @@ -952,7 +951,7 @@ freelog(LOG_DEBUG, "A diplomat will be built in city %s.", pcity->name); choice->want = 16000; /* diplomat more important than soldiers */ pcity->ai.urgency = 1; - choice->type = 3; /* defender */ + choice->type = CT_DEFENDER; choice->choice = u; return; } else if (num_role_units(F_DIPLOMAT)>0) { @@ -985,7 +984,7 @@ choice->choice = B_CITY; /* great wall is under domestic */ choice->want = pcity->ai.building_want[B_CITY]; /* hacked by assess_danger */ if (!urgency && choice->want > 100) choice->want = 100; - choice->type = 0; + choice->type = CT_BUILDING; } else if (pcity->ai.building_want[B_COASTAL] && def && can_build_improvement(pcity, B_COASTAL) && (danger < 101 || unit_list_size(&ptile->units) > 1) && @@ -993,7 +992,7 @@ choice->choice = B_COASTAL; /* great wall is under domestic */ choice->want = pcity->ai.building_want[B_COASTAL]; /* hacked by assess_danger */ if (!urgency && choice->want > 100) choice->want = 100; - choice->type = 0; + choice->type = CT_BUILDING; } else if (pcity->ai.building_want[B_SAM] && def && can_build_improvement(pcity, B_SAM) && (danger < 101 || unit_list_size(&ptile->units) > 1) && @@ -1001,7 +1000,7 @@ choice->choice = B_SAM; /* great wall is under domestic */ choice->want = pcity->ai.building_want[B_SAM]; /* hacked by assess_danger */ if (!urgency && choice->want > 100) choice->want = 100; - choice->type = 0; + choice->type = CT_BUILDING; } else if (danger > 0 && unit_list_size(&ptile->units) <= urgency) { process_defender_want(pplayer, pcity, danger, choice); if (!urgency && unit_types[choice->choice].defense_strength == 1) { @@ -1035,7 +1034,7 @@ if (want > choice->want) { choice->want = want; choice->choice = v; - choice->type = 1; + choice->type = CT_NONMIL; /* Why not CT_DEFENDER? -- Caz */ } } diff ai/aicity.c ai/aicity.c --- ai/aicity.c Thu Jan 18 03:21:04 2001 +++ ai/aicity.c Sat Jan 20 12:52:47 2001 @@ -14,6 +14,7 @@ #include #endif +#include #include #include #include @@ -184,7 +185,7 @@ bestchoice.choice = A_NONE; bestchoice.want = 0; - bestchoice.type = 0; + bestchoice.type = CT_NONE; if( is_barbarian(pplayer) ) { /* always build best attack unit */ Unit_Type_id i, iunit, bestunit = -1; @@ -207,7 +208,7 @@ if (bestunit != -1) { bestchoice.choice = bestunit; bestchoice.want = 101; - bestchoice.type = 2; + bestchoice.type = CT_ATTACKER; } else { freelog(LOG_VERBOSE, "Barbarians don't know what to build!\n"); @@ -232,22 +233,25 @@ pcity->ai.choice.type = bestchoice.type; /* instead of the one atop the list */ } -/* type 0 = building, 1 = non-mil unit, 2 = attacker, 3 = defender */ - if (bestchoice.want) { /* Note - on fallbacks, will NOT get stopped building msg */ + + ASSERT_REAL_CHOICE_TYPE(bestchoice.type); + freelog(LOG_DEBUG, "%s wants %s with desire %d.", pcity->name, - (bestchoice.type ? unit_name(bestchoice.choice) - : get_improvement_name(bestchoice.choice)), + (is_unit_choice_type(bestchoice.type) ? + unit_name(bestchoice.choice) : + get_improvement_name(bestchoice.choice)), bestchoice.want); if(!pcity->is_building_unit && is_wonder(pcity->currently_building) && - (bestchoice.type || bestchoice.choice != pcity->currently_building)) + (is_unit_choice_type(bestchoice.type) || + bestchoice.choice != pcity->currently_building)) notify_player_ex(0, pcity->x, pcity->y, E_WONDER_STOPPED, _("Game: The %s have stopped building The %s in %s."), get_nation_name_plural(pplayer->nation), get_impr_name_ex(pcity, pcity->currently_building), pcity->name); - if (!bestchoice.type && (pcity->is_building_unit || + if (bestchoice.type == CT_BUILDING && (pcity->is_building_unit || pcity->currently_building != bestchoice.choice) && is_wonder(bestchoice.choice)) { notify_player_ex(0, pcity->x, pcity->y, E_WONDER_STARTED, @@ -255,12 +259,12 @@ get_nation_name_plural(city_owner(pcity)->nation), get_impr_name_ex(pcity, bestchoice.choice), pcity->name); pcity->currently_building = bestchoice.choice; - pcity->is_building_unit = (bestchoice.type > 0); + pcity->is_building_unit = is_unit_choice_type(bestchoice.type); generate_warmap(pcity, 0); /* need to establish distance to wondercity */ establish_city_distances(pplayer, pcity); /* for caravans in other cities */ } else { pcity->currently_building = bestchoice.choice; - pcity->is_building_unit = (bestchoice.type > 0); + pcity->is_building_unit = is_unit_choice_type(bestchoice.type); } return; @@ -330,7 +334,7 @@ break; bestchoice.want = 0; - bestchoice.type = 0; + bestchoice.type = CT_NONE; bestchoice.choice = 0; city_list_iterate(pplayer->cities, acity) if (acity->anarchy) continue; @@ -343,8 +347,12 @@ city_list_iterate_end; if (!bestchoice.want) break; + + ASSERT_REAL_CHOICE_TYPE(bestchoice.type); - if (bestchoice.type && (!frugal || bestchoice.want > 200)) { /* if we want a unit */ + if (is_unit_choice_type(bestchoice.type) && + (!frugal || bestchoice.want > 200)) { /* if we want a unit */ + buycost = city_buy_cost(pcity); unit_list_iterate(map_get_tile(pcity->x, pcity->y)->units, punit) id = can_upgrade_unittype(pplayer, punit->type); @@ -401,40 +409,45 @@ pplayer->research.researching == A_NONE) { /* nothing else to do */ buycost = city_buy_cost(pcity); if (!pcity->shield_stock) ; - else if (!bestchoice.type && is_wonder(bestchoice.choice) && - buycost >= 200) ; /* wait for more vans */ - else if (bestchoice.type && unit_flag(bestchoice.choice, F_SETTLERS) && - !city_got_effect(pcity, B_GRANARY) && (pcity->size < 2 || - pcity->food_stock < pcity->size * game.foodbox)) ; - else if (bestchoice.type && bestchoice.type < 3 && /* not a defender */ - buycost > unit_types[bestchoice.choice].build_cost * 2) { /* too expensive */ + else if (bestchoice.type == CT_BUILDING && + is_wonder(bestchoice.choice) && + buycost >= 200); /* wait for more vans */ + + else if (is_unit_choice_type(bestchoice.type) && + unit_flag(bestchoice.choice, F_SETTLERS) && + !city_got_effect(pcity, B_GRANARY) && (pcity->size < 2 || + pcity->food_stock < pcity->size * game.foodbox)); + else if (is_unit_choice_type(bestchoice.type) && + bestchoice.type != CT_DEFENDER && + buycost > unit_types[bestchoice.choice].build_cost * 2) { /* too expensive */ if (unit_flag(bestchoice.choice, F_CARAVAN) && pplayer->ai.maxbuycost < 100) pplayer->ai.maxbuycost = 100; - } #ifdef GRAVEDANGERWORKS - else if (bestchoice.type == 3 && pcity->size == 1 && - pcity->ai.grave_danger > (assess_defense_quadratic(pcity) + - ai_city_defender_value(pcity, U_LEGION, bestchoice.choice)) * 2 && + } else if (bestchoice.type == CT_DEFENDER && pcity->size == 1 && + pcity->ai.grave_danger > (assess_defense_quadratic(pcity) + + ai_city_defender_value(pcity, U_LEGION, bestchoice.choice)) * 2 && pcity->food_stock + pcity->food_surplus < 10) { /* We're DOOMED */ freelog(LOG_VERBOSE, "%s is DOOMED!", pcity->name); try_to_sell_stuff(pplayer, pcity); /* and don't buy stuff */ pcity->currently_building = ai_choose_defender_limited(pcity, pcity->shield_stock + pcity->shield_surplus, 0); - } #endif - else if ((pplayer->economic.gold-pplayer->ai.est_upkeep) >= buycost + } else if ((pplayer->economic.gold-pplayer->ai.est_upkeep) >= buycost && (!frugal || bestchoice.want > 200)) { if (ai_fuzzy(pplayer,1) || (pcity->ai.grave_danger && !assess_defense(pcity))) { really_handle_city_buy(pplayer, pcity); /* adequately tested now */ } - } else if (bestchoice.type || !is_wonder(bestchoice.choice)) { + } else if (is_unit_choice_type(bestchoice.type) || + !is_wonder(bestchoice.choice)) { freelog(LOG_DEBUG, "%s wants %s but can't afford to buy it" " (%d < %d).", pcity->name, - (bestchoice.type ? unit_name(bestchoice.choice) - : get_improvement_name(bestchoice.choice)), - pplayer->economic.gold, buycost); - if (bestchoice.type && !unit_flag(bestchoice.choice, F_NONMIL)) { + (is_unit_choice_type(bestchoice.type) ? + unit_name(bestchoice.choice) : + get_improvement_name(bestchoice.choice)), + pplayer->economic.gold, buycost); + if (is_unit_choice_type(bestchoice.type) && + !unit_flag(bestchoice.choice, F_NONMIL)) { if (pcity->ai.grave_danger && !assess_defense(pcity)) { /* oh dear */ try_to_sell_stuff(pplayer, pcity); if ((pplayer->economic.gold-pplayer->ai.est_upkeep) >= buycost) @@ -445,10 +458,14 @@ } else if (buycost > pplayer->ai.maxbuycost) pplayer->ai.maxbuycost = buycost; /* possibly upgrade units here */ } /* end panic subroutine */ - if (bestchoice.type && unit_flag(bestchoice.choice, F_CARAVAN)) - if (buycost > pplayer->ai.maxbuycost) pplayer->ai.maxbuycost = buycost; + if (is_unit_choice_type(bestchoice.type) && + unit_flag(bestchoice.choice, F_CARAVAN)) { + if (buycost > pplayer->ai.maxbuycost) + pplayer->ai.maxbuycost = buycost; /* Gudy reminded me AI was slow to build wonders, I thought of the above -- Syela */ - if (!bestchoice.type) switch (bestchoice.choice) { + } + if (bestchoice.type == CT_BUILDING) { + switch (bestchoice.choice) { case B_AQUEDUCT: if (city_happy(pcity)) break; /* PASS THROUGH */ @@ -463,7 +480,8 @@ if (buycost > pplayer->ai.maxbuycost) pplayer->ai.maxbuycost = buycost; break; /* granaries/harbors/wonders not worth the tax increase */ - } /* end switch */ + } /* end switch */ + } /* I just saw Alexander save up for walls then buy a granary. Never again! -- Syela */ /* if (bestchoice.want > 200 && pplayer->ai.maxbuycost) frugal++; */ if (pplayer->ai.maxbuycost) frugal++; /* much more frugal -- Syela */ diff ai/aihand.c ai/aihand.c --- ai/aihand.c Thu Jan 18 03:21:04 2001 +++ ai/aihand.c Sat Jan 20 12:52:47 2001 @@ -513,3 +513,9 @@ freelog(LOG_DEBUG, "Done with %s.", pplayer->name); } + +int is_unit_choice_type(enum choice_type type) +{ + return type == CT_NONMIL || type == CT_ATTACKER || type == CT_DEFENDER; +} + diff ai/aihand.h ai/aihand.h --- ai/aihand.h Sat Jun 12 10:41:38 1999 +++ ai/aihand.h Sat Jan 20 12:52:47 2001 @@ -18,4 +18,6 @@ void ai_do_first_activities(struct player *pplayer); void ai_do_last_activities(struct player *pplayer); +int is_unit_choice_type(enum choice_type type); + #endif /* FC__AIHAND_H */ diff ai/aitools.c ai/aitools.c --- ai/aitools.c Thu Jan 18 03:21:04 2001 +++ ai/aitools.c Sat Jan 20 12:52:47 2001 @@ -169,7 +169,7 @@ } choice->want = want; choice->choice = id; - choice->type = 0; + choice->type = CT_BUILDING; } diff common/city.h common/city.h --- common/city.h Thu Jan 18 03:21:19 2001 +++ common/city.h Sun Jan 21 08:26:53 2001 @@ -116,6 +116,22 @@ } +enum choice_type { CT_NONE = 0, CT_BUILDING = 0, CT_NONMIL, CT_ATTACKER, + CT_DEFENDER, CT_LAST }; + +/* FIXME: + + This should detect also cases where type is just initialized with + CT_NONE (probably in order to silence compiler warnings), but no real value + is given. You have to change value of CT_BUILDING into 1 before you + can add this check. It's left this way for now, is case hardcoded + value 0 is still used somewhere instead of CT_BUILDING. + + -- Caz +*/ +#define ASSERT_REAL_CHOICE_TYPE(type) \ + assert(type >= 0 && type < CT_LAST /* && type != CT_NONE */ ); + struct ai_choice { int choice; /* what the advisor wants */