static bool ai_evaluate_hex(ref AI_Eval eval) { int result; int i, nx, ny, ox, oy, odist, j, nx2, ny2; bool covered; eval.target = null; eval.mov_score = eval.atk_score = 0; /* terrain modifications which only apply for ground units */ if ((eval.unit.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING) { /* entrenchment bonus. infantry receives more than others. */ eval.mov_score += (((eval.unit.sel_prop.flags & UnitFlags.INFANTRY) == UnitFlags.INFANTRY) ? 2 : 1) * (Engine.map.map[eval.x, eval.y].terrain.min_entr * 2 + Engine.map.map[eval.x, eval.y].terrain.max_entr); /* if the unit looses initiative on this terrain we give a malus */ if (Engine.map.map[eval.x, eval.y].terrain.max_ini < eval.unit.sel_prop.ini) eval.mov_score -= 5 * (eval.unit.sel_prop.ini - Engine.map.map[eval.x, eval.y].terrain.max_ini); /* rivers should be avoided */ if ((Engine.map.map[eval.x, eval.y].terrain.flags[Scenario.cur_weather] & Terrain_flags.RIVER) == Terrain_flags.RIVER) eval.mov_score -= 50; if ((Engine.map.map[eval.x, eval.y].terrain.flags[Scenario.cur_weather] & Terrain_flags.SWAMP) == Terrain_flags.SWAMP) eval.mov_score -= 30; /* inf_close_def will benefit an infantry while disadvantaging other units */ if ((Engine.map.map[eval.x, eval.y].terrain.flags[Scenario.cur_weather] & Terrain_flags.INF_CLOSE_DEF) == Terrain_flags.INF_CLOSE_DEF) { if ((eval.unit.sel_prop.flags & UnitFlags.INFANTRY) == UnitFlags.INFANTRY) eval.mov_score += 30; else eval.mov_score -= 20; } /* if this is a mount position and an enemy or fog is less than 6 tiles away we give a big malus */ if (Engine.map.mask[eval.x, eval.y].mount != 0) if (ai_unsafe__mount(eval.unit, eval.x, eval.y)) eval.mov_score -= 1000; /* conquering a flag gives a bonus */ if (Engine.map.map[eval.x, eval.y].player != null) if (!Player.player_is_ally(eval.unit.player, Engine.map.map[eval.x, eval.y].player)) if (Engine.map.map[eval.x, eval.y].g_unit == null) { eval.mov_score += 600; if (Engine.map.map[eval.x, eval.y].obj) eval.mov_score += 600; } /* if this position allows debarking or is just one hex away this tile receives a big bonus. */ if (eval.unit.embark == UnitEmbarkTypes.EMBARK_SEA) { if (Engine.map.map_check_unit_debark(eval.unit, eval.x, eval.y, UnitEmbarkTypes.EMBARK_SEA, false)) eval.mov_score += 1000; else for (i = 0; i < 6; i++) if (Misc.get_close_hex_pos(eval.x, eval.y, i, out nx, out ny)) if (Engine.map.map_check_unit_debark(eval.unit, nx, ny, UnitEmbarkTypes.EMBARK_SEA, false)) { eval.mov_score += 500; break; } } } /* modifications on flying units */ if ((eval.unit.sel_prop.flags & UnitFlags.FLYING) == UnitFlags.FLYING) { /* if interceptor covers an uncovered bomber on this tile give bonus */ if ((eval.unit.sel_prop.flags & UnitFlags.INTERCEPTOR) == UnitFlags.INTERCEPTOR) { for (i = 0; i < 6; i++) if (Misc.get_close_hex_pos(eval.x, eval.y, i, out nx, out ny)) if (Engine.map.map[nx, ny].a_unit != null) if (Player.player_is_ally(Engine.cur_player, Engine.map.map[nx, ny].a_unit.player)) if ((Engine.map.map[nx, ny].a_unit.sel_prop.flags & UnitFlags.BOMBER) == UnitFlags.BOMBER) { covered = false; for (j = 0; j < 6; j++) if (Misc.get_close_hex_pos(nx, ny, j, out nx2, out ny2)) if (Engine.map.map[nx2, ny2].a_unit != null) if (Player.player_is_ally(Engine.cur_player, Engine.map.map[nx2, ny2].a_unit.player)) if ((Engine.map.map[nx2, ny2].a_unit.sel_prop.flags & UnitFlags.INTERCEPTOR) == UnitFlags.INTERCEPTOR) if (Engine.map.map[nx2, ny2].a_unit != eval.unit) { covered = true; break; } if (!covered) eval.mov_score += 2000; /* 100 equals one tile of getting to center of interest which must be overcome */ } } } /* each group has a 'center of interest'. getting closer to this center is honored. */ if (eval.group.x == -1) { /* proceed to the nearest flag */ if ((eval.unit.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING) { if (eval.group.order > 0) { if (AI.ai_get_dist(eval.unit, eval.x, eval.y, AI_FIND.AI_FIND_ENEMY_OBJ, out ox, out oy, out odist)) eval.mov_score -= odist * 100; } else if (eval.group.order < 0) { if (AI.ai_get_dist(eval.unit, eval.x, eval.y, AI_FIND.AI_FIND_OWN_OBJ, out ox, out oy, out odist)) eval.mov_score -= odist * 100; } } } else eval.mov_score -= 100 * Misc.get_dist(eval.x, eval.y, eval.group.x, eval.group.y); /* defensive support */ ai_count_df_units(eval.unit, eval.x, eval.y, out result); if (result > 2) result = 2; /* senseful limit */ eval.mov_score += result * 10; /* check for the best target and save the result to atk_score */ eval.atk_score = eval.mov_score; if (Engine.map.mask[eval.x, eval.y].mount == 0) if (((eval.unit.sel_prop.flags & UnitFlags.ATTACK_FIRST) != UnitFlags.ATTACK_FIRST) || eval.unit.x == eval.x && eval.unit.y == eval.y) if (ai_get_best_target(eval.unit, eval.x, eval.y, eval.group, out eval.target, out result)) eval.atk_score += result; return true; }
static AI_Eval ai_create_eval(Unit unit, AI_Group group, int x, int y) { AI_Eval eval = new AI_Eval(); eval.unit = unit; eval.group = group; eval.x = x; eval.y = y; return eval; }