Index: ai/aicity.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v retrieving revision 1.129 diff -u -r1.129 aicity.c --- ai/aicity.c 19 Nov 2002 13:31:07 -0000 1.129 +++ ai/aicity.c 5 Dec 2002 02:05:48 -0000 @@ -55,6 +55,25 @@ #include "aicity.h" static void ai_manage_city(struct player *pplayer, struct city *pcity); + +/************************************************************************** + This calculates the usefulness of pcity to us. Note that you can pass + another player's ai_data structure here for evaluation by different + priorities. +**************************************************************************/ +int ai_eval_calc_city(struct city *pcity, struct ai_data *ai) +{ + int i = (pcity->food_surplus * ai->food_priority + + pcity->shield_surplus * ai->shield_priority + + pcity->luxury_total * ai->trade_priority + + pcity->tax_total * ai->trade_priority + + pcity->science_total * ai->trade_priority + + pcity->ppl_happy[4] * ai->happy_priority + - pcity->ppl_unhappy[4] * ai->unhappy_priority + - pcity->ppl_angry[4] * ai->angry_priority); + + return i; +} /************************************************************************** ... Index: ai/aicity.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aicity.h,v retrieving revision 1.16 diff -u -r1.16 aicity.h --- ai/aicity.h 7 Nov 2002 15:40:24 -0000 1.16 +++ ai/aicity.h 5 Dec 2002 02:05:48 -0000 @@ -18,6 +18,9 @@ struct player; struct city; struct ai_choice; +struct ai_data; + +int ai_eval_calc_city(struct city *pcity, struct ai_data *ai); void ai_manage_cities(struct player *pplayer); void ai_choose_ferryboat(struct player *pplayer, struct city *pcity, struct ai_choice *choice); Index: ai/aidata.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v retrieving revision 1.3 diff -u -r1.3 aidata.c --- ai/aidata.c 14 Nov 2002 09:14:50 -0000 1.3 +++ ai/aidata.c 5 Dec 2002 02:05:48 -0000 @@ -188,6 +188,19 @@ ai->stats.workers[ptile->continent]++; } } unit_list_iterate_end; + + /* + * Priorities. NEVER set these to zero! Weight values are usually + * multiplied by these values, so be careful with them. They are + * used in city calculations, and food and shields should be slightly + * bigger because we only look at surpluses there. + */ + ai->food_priority = FOOD_WEIGHTING; + ai->shield_priority = SHIELD_WEIGHTING; + ai->trade_priority = TRADE_WEIGHTING; + ai->happy_priority = TRADE_WEIGHTING; + ai->unhappy_priority = TRADE_WEIGHTING; + ai->angry_priority = TRADE_WEIGHTING * 3; /* danger */ } /************************************************************************** @@ -195,10 +208,11 @@ **************************************************************************/ void ai_data_turn_done(struct player *pplayer) { struct ai_data *ai = &aidata[pplayer->player_no]; - free(ai->explore.continent); - free(ai->threats.continent); - free(ai->stats.workers); - free(ai->stats.cities); + + free(ai->explore.continent); ai->explore.continent = NULL; + free(ai->threats.continent); ai->threats.continent = NULL; + free(ai->stats.workers); ai->stats.workers = NULL; + free(ai->stats.cities); ai->stats.cities = NULL; } /************************************************************************** Index: ai/aidata.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v retrieving revision 1.2 diff -u -r1.2 aidata.h --- ai/aidata.h 15 Nov 2002 22:15:01 -0000 1.2 +++ ai/aidata.h 5 Dec 2002 02:05:48 -0000 @@ -50,6 +50,14 @@ } stats; int num_continents; /* last time we updated our continent data */ + + /* Dynamic weights used in addition to Syela's hardcoded weights */ + int shield_priority; + int food_priority; + int trade_priority; + int happy_priority; + int unhappy_priority; + int angry_priority; }; void ai_data_turn_init(struct player *pplayer); Index: ai/aihand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v retrieving revision 1.71 diff -u -r1.71 aihand.c --- ai/aihand.c 14 Nov 2002 09:14:50 -0000 1.71 +++ ai/aihand.c 5 Dec 2002 02:05:48 -0000 @@ -35,6 +35,7 @@ #include "unithand.h" #include "aicity.h" +#include "aidata.h" #include "aitech.h" #include "aitools.h" #include "aiunit.h" @@ -303,59 +304,74 @@ } /************************************************************************** - change the government form, if it can and there is a good reason + Change the government form, if it can and there is a good reason **************************************************************************/ static void ai_manage_government(struct player *pplayer) { - int goal; - int subgoal; - int failsafe; - - goal = game.ai_goal_government; - /* Was G_REPUBLIC; need to be REPUBLIC+ to love */ - - /* advantages of DEMOCRACY: - partisans, no bribes, no corrup, +1 content if courthouse; - disadvantages of DEMOCRACY: - doubled unhappiness from attacking units, anarchy - realistically we should allow DEMOC in some circumstances but - not yet -- Syela - */ - if (pplayer->government == goal) { - freelog(LOG_DEBUG, "ai_man_gov (%s): there %d", pplayer->name, goal); - return; - } - if (can_change_to_government(pplayer, goal)) { - freelog(LOG_DEBUG, "ai_man_gov (%s): change %d", pplayer->name, goal); - ai_government_change(pplayer, goal); - return; - } - failsafe = 0; - while((subgoal = get_government(goal)->subgoal) >= 0) { - if (can_change_to_government(pplayer, subgoal)) { - freelog(LOG_DEBUG, "ai_man_gov (%s): change sub %d (%d)", - pplayer->name, subgoal, goal); - ai_government_change(pplayer, subgoal); - break; - } - goal = subgoal; - if (++failsafe > game.government_count) { - freelog(LOG_ERROR, "Loop in ai_manage_government? (%s)", - pplayer->name); - return; + struct ai_data *ai = ai_data_get(pplayer); + int best_gov = 0; + int best_val = 0; + int really_best_val = 0; + int really_best_req = A_NONE; + int i; + int bonus = 0; /* in percentage */ + + for (i = 0; i < game.government_count; ++i) { + struct government *gov = &governments[i]; + int val = 0; + + if (i == game.government_when_anarchy) { + continue; /* pointless */ } - } + pplayer->government = gov->index; + update_all_effects(); + city_list_iterate(pplayer->cities, acity) { + generic_city_refresh(acity, TRUE); + auto_arrange_workers(acity); + if (ai_fix_unhappy(acity)) { + ai_scientists_taxmen(acity); + } + } city_list_iterate_end; + city_list_iterate(pplayer->cities, pcity) { + val += ai_eval_calc_city(pcity, ai); + } city_list_iterate_end; + + /* Bonuses for non-economic abilities */ + if (government_has_flag(gov, G_BUILD_VETERAN_DIPLOMAT)) { + bonus += 3; + } + if (government_has_flag(gov, G_REVOLUTION_WHEN_UNHAPPY)) { + bonus -= 1; /* Not really a problem for us */ + } + if (government_has_flag(gov, G_UNBRIBABLE)) { + bonus += 10; + } + if (government_has_flag(gov, G_INSPIRES_PARTISANS)) { + bonus += 5; + } + if (government_has_flag(gov, G_RAPTURE_CITY_GROWTH)) { + bonus += 8; + } + if (get_nation_by_idx(pplayer->nation)->goals.government == i) { + bonus += 20; + } + + val += (val * bonus) / 100; - if (pplayer->government == game.government_when_anarchy) { - /* if the ai ever intends to stay anarchy, */ - /* change condition to if( (pplayer->revolution==0) && */ - if( ((pplayer->revolution<=0) || (pplayer->revolution>5)) - && can_change_to_government(pplayer, game.default_government)) { - freelog(LOG_DEBUG, "ai_man_gov (%s): change from anarchy", - pplayer->name); - ai_government_change(pplayer, game.default_government); + if (val > best_val && can_change_to_government(pplayer, i)) { + best_val = val; + best_gov = i; } + if (val > really_best_val) { + really_best_val = val; + really_best_req = gov->required_tech; + } + freelog(LOG_NORMAL, "%s govt eval %s: %d", pplayer->name, gov->name, val); } + /* Crank up tech want */ + pplayer->ai.tech_want[really_best_req] += (really_best_val - best_val) * 3; + + ai_government_change(pplayer, best_gov); } /************************************************************************** Index: ai/aitech.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v retrieving revision 1.35 diff -u -r1.35 aitech.c --- ai/aitech.c 14 Nov 2002 09:14:50 -0000 1.35 +++ ai/aitech.c 5 Dec 2002 02:05:48 -0000 @@ -37,40 +37,6 @@ #include "aitech.h" /************************************************************************** -.. AI got some tech goals, and should try to fulfill them. -**************************************************************************/ - -/************************************************************************** -.. calculate next government wish. -**************************************************************************/ -static Tech_Type_id get_government_tech(struct player *plr) -{ - int goal = get_nation_by_plr(plr)->goals.government; - int subgoal = get_government(goal)->subgoal; - - if (can_change_to_government(plr, goal)) { - freelog(LOG_DEBUG, "get_gov_tech (%s): have %d", plr->name, goal); - return A_NONE; - } - - if (subgoal >= 0) { - struct government *subgov = get_government(subgoal); - if (get_invention(plr, subgov->required_tech) == TECH_KNOWN) { - freelog(LOG_DEBUG, "get_gov_tech (%s): have sub %d %s", - plr->name, goal, subgov->name); - return get_government(goal)->required_tech; - } else { - freelog(LOG_DEBUG, "get_gov_tech (%s): do sub %d %s", - plr->name, goal, subgov->name); - return subgov->required_tech; - } - } else { - freelog(LOG_DEBUG, "get_gov_tech (%s): no sub %d", plr->name, goal); - return get_government(goal)->required_tech; - } -} - -/************************************************************************** Returns tech corresponding to players wonder goal from nations[], if it makes sense, and wonder is not already built and not obsolete. Otherwise returns A_NONE. @@ -113,14 +79,6 @@ break; /* remove this to restore old functionality -- Syela */ } } - tech = get_government_tech(pplayer); - if (tech != A_NONE && tech_exists(tech)) { - dist = num_unknown_techs_for_goal(pplayer, tech); - if (dist < bestdist) { - bestdist = dist; - goal = tech; - } - } tech = get_wonder_tech(pplayer); if (tech != A_NONE) { dist = num_unknown_techs_for_goal(pplayer, tech); Index: ai/aitools.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v retrieving revision 1.63 diff -u -r1.63 aitools.c --- ai/aitools.c 2 Dec 2002 22:48:13 -0000 1.63 +++ ai/aitools.c 5 Dec 2002 02:05:48 -0000 @@ -398,16 +398,18 @@ } /************************************************************************** -.. change government,pretty fast.... + Change government, pretty fast... **************************************************************************/ void ai_government_change(struct player *pplayer, int gov) { struct packet_player_request preq; - if (gov == pplayer->government) + + if (gov == pplayer->government) { return; - preq.government=gov; - pplayer->revolution=0; - pplayer->government=game.government_when_anarchy; + } + preq.government = gov; + pplayer->revolution = 0; + pplayer->government = game.government_when_anarchy; handle_player_government(pplayer, &preq); pplayer->revolution = -1; /* yes, I really mean this. -- Syela */ } @@ -572,80 +574,4 @@ if (unhap < 0) unhap = 0; return unhap > 0; -} - -/********************************************************************** - Evaluate a government form, still pretty sketchy. - - This evaluation should be more dynamic (based on players current - needs, like expansion, at war, etc, etc). -SKi - - 0 is my first attempt at government evaluation - 1 is new evaluation based on patch from rizos -SKi -**********************************************************************/ -int ai_evaluate_government (struct player *pplayer, struct government *g) -{ - int current_gov = pplayer->government; - int shield_surplus = 0; - int food_surplus = 0; - int trade_prod = 0; - int shield_need = 0; - int food_need = 0; - bool gov_overthrown = FALSE; - int score; - - pplayer->government = g->index; - - city_list_iterate(pplayer->cities, pcity) { - city_refresh(pcity); - - /* the lines that follow are copied from ai_manage_city - - we don't need the sell_obsolete_buildings */ - auto_arrange_workers(pcity); - if (ai_fix_unhappy (pcity)) - ai_scientists_taxmen(pcity); - - trade_prod += pcity->trade_prod; - if (pcity->shield_prod > 0) - shield_surplus += pcity->shield_surplus; - else - shield_need += pcity->shield_surplus; - if (pcity->food_surplus > 0) - food_surplus += pcity->food_surplus; - else - food_need += pcity->food_surplus; - - if (city_unhappy(pcity)) { - /* the following is essential to prevent falling into anarchy */ - if (pcity->anarchy > 0 - && government_has_flag(g, G_REVOLUTION_WHEN_UNHAPPY)) - gov_overthrown = TRUE; - } - } city_list_iterate_end; - - pplayer->government = current_gov; - - /* Restore all cities. */ - city_list_iterate(pplayer->cities, pcity) { - city_refresh(pcity); - - /* the lines that follow are copied from ai_manage_city - - we don't need the sell_obsolete_buildings */ - auto_arrange_workers(pcity); - if (ai_fix_unhappy (pcity)) - ai_scientists_taxmen(pcity); - } city_list_iterate_end; - sync_cities(); - - score = - 3 * trade_prod - + 2 * shield_surplus + 2 * food_surplus - - 4 * shield_need - 4 * food_need; - - score = gov_overthrown ? 0 : MAX(score, 0); - - freelog(LOG_DEBUG, "a_e_g (%12s) = score=%3d; trade=%3d; shield=%3d/%3d; " - "food=%3d/%3d;", g->name, score, trade_prod, - shield_surplus, shield_need, food_surplus, food_need); - return score; }