/* ==================================================================== Undo the steps (e.g. memory allocation) made in ai_init() ==================================================================== */ public static void ai_finalize() { Console.WriteLine("ai_finalize()"); while (Engine.stateMachine.scheduler.IsRunning) { Action.CheckScheduler(); System.Threading.Thread.Sleep(100); } if (finalized) return; Console.WriteLine("Really finalized"); ai_units.Clear(); #if DEBUG Console.WriteLine("AI Finalized"); #endif ai_status = AI_STATUS.AI_STATUS_INIT; finalized = true; }
/* ==================================================================== Queue next actions (if these actions were handled by the engine this function is called again and again until the end_turn action is received). ==================================================================== */ public static bool ai_run() { bool result = false; Unit[] partners = new Unit[Map.MAP_MERGE_UNIT_LIMIT]; int partner_count; int i, j, x = 0, y = 0, dx, dy, dist; bool found; Unit unit = null; Unit best; switch (ai_status) { case AI_STATUS.AI_STATUS_DEPLOY: /* deploy unit? */ if (Scenario.avail_units.Count > 0 && avail_unitsIterator.MoveNext() && (unit = avail_unitsIterator.Current) != null) { if (Engine.deploy_turn) { x = unit.x; y = unit.y; //assert(x >= 0 && y >= 0); Engine.map.map_remove_unit(unit); found = true; } else { Engine.map.map_get_deploy_mask(Engine.cur_player, unit, false); Engine.map.map_clear_mask(MAP_MASK.F_AUX); for (i = 0; i < Engine.map.map_w; i++) for (j = 0; j < Engine.map.map_h; j++) if (Engine.map.mask[i, j].deploy) if (ai_get_dist(unit, i, j, AI_FIND.AI_FIND_ENEMY_OBJ, out x, out y, out dist)) Engine.map.mask[i, j].aux = dist + 1; dist = 1000; found = false; for (i = 0; i < Engine.map.map_w; i++) for (j = 0; j < Engine.map.map_h; j++) if (Engine.map.mask[i, j].aux > 0 && Engine.map.mask[i, j].aux < dist) { dist = Engine.map.mask[i, j].aux; x = i; y = j; found = true; /* deploy close to enemy */ } } if (found) { Action.action_queue_deploy(unit, x, y); avail_unitsIterator = Scenario.avail_units.GetEnumerator(); ai_units.Add(unit); #if DEBUG Console.WriteLine("{0} deployed to {1},{2}", unit.name, x, y); #endif return false; } } else { ai_status = Engine.deploy_turn ? AI_STATUS.AI_STATUS_END : AI_STATUS.AI_STATUS_MERGE; ai_unitsIterator = ai_units.GetEnumerator(); #if DEBUG Console.WriteLine(Engine.deploy_turn ? "*** END TURN ***" : "*** MERGE ***"); #endif } break; case AI_STATUS.AI_STATUS_SUPPLY: /* get next unit */ ai_unitsIterator.MoveNext(); unit = ai_unitsIterator.Current; if (unit == null) { ai_status = AI_STATUS.AI_STATUS_GROUP; /* build a group with all units, -1,-1 as destination means it will simply attack/defend the nearest target. later on this should split up into several groups with different target and strategy */ ai_group = AI_Group.ai_group_create(Engine.cur_player.strat, -1, -1); ai_unitsIterator = ai_units.GetEnumerator(); while (ai_unitsIterator.MoveNext() && (unit = ai_unitsIterator.Current) != null) AI_Group.ai_group_add_unit(ai_group, unit); #if DEBUG Console.WriteLine("*** MOVE & ATTACK ***"); #endif } else { /* check if unit needs supply and remove it from ai_units if so */ if ((unit.CheckLowFuel() || unit.CheckLowAmmo())) { if (unit.supply_level > 0) { Action.action_queue_supply(unit); ai_units.Remove(unit); #if DEBUG Console.WriteLine("{0} supplies", unit.name); #endif break; } else { #if DEBUG Console.WriteLine("{0} searches depot", unit.name); #endif if (ai_get_dist(unit, unit.x, unit.y, AI_FIND.AI_FIND_DEPOT, out dx, out dy, out dist)) if (ai_approximate(unit, dx, dy, out x, out y)) { Action.action_queue_move(unit, x, y); ai_units.Remove(unit); #if DEBUG Console.WriteLine("{0} moves to {1},{2}", unit.name, x, y); #endif break; } } } } break; case AI_STATUS.AI_STATUS_MERGE: if (ai_unitsIterator.MoveNext() && (unit = ai_unitsIterator.Current) != null) { Engine.map.map_get_merge_units(unit, out partners, out partner_count); best = null; /* merge with the one that has the most strength points */ for (i = 0; i < partner_count; i++) if (best == null) best = partners[i]; else if (best.str < partners[i].str) best = partners[i]; if (best != null) { #if DEBUG Console.WriteLine("{0} merges with {1}", unit.name, best.name); #endif Action.action_queue_merge(unit, best); /* both units are handled now */ ai_units.Remove(unit); ai_units.Remove(best); } } else { ai_status = AI_STATUS.AI_STATUS_SUPPLY; ai_unitsIterator = ai_units.GetEnumerator(); #if DEBUG Console.WriteLine("*** SUPPLY ***"); #endif } break; case AI_STATUS.AI_STATUS_GROUP: if (!AI_Group.ai_group_handle_next_unit(ai_group)) { AI_Group.ai_group_delete(ai_group); ai_status = AI_STATUS.AI_STATUS_END; #if DEBUG Console.WriteLine("*** END TURN ***"); #endif } break; case AI_STATUS.AI_STATUS_END: Action.action_queue_end_turn(); ai_status = AI_STATUS.AI_STATUS_FINALIZE; result = true; break; } return result; }
/* ==================================================================== Exports ==================================================================== */ /* ==================================================================== Initiate turn ==================================================================== */ public static void ai_init() { List<Unit> list; /* used to speed up the creation of ai_units */ #if DEBUG Console.WriteLine("AI Turn: {0:n}", Engine.cur_player.name); #endif if (ai_status != AI_STATUS.AI_STATUS_INIT) { #if DEBUG Console.WriteLine("Aborted: Bad AI Status: {0:n}", ai_status); #endif return; } finalized = false; /* get all cur_player units, those with defensive fire come first */ list = new List<Unit>(); foreach (Unit unit in Scenario.units) if (unit.player == Engine.cur_player) list.Add(unit); ai_units = new List<Unit>(); for (int index = list.Count - 1; index >= 0; index--) { Unit unit = list[index]; if ((unit.sel_prop.flags & UnitFlags.ARTILLERY) == UnitFlags.ARTILLERY || (unit.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE) { ai_units.Add(unit); list.Remove(unit); } } foreach (Unit unit in list) { #if DEBUG if (unit.killed != 0) Console.WriteLine("!!Unit {0} is dead!!", unit.name); #endif ai_units.Add(unit); } list.Clear(); #if DEBUG Console.WriteLine("Units: {0}", ai_units.Count); #endif /* evaluate all units for strategic computations */ #if DEBUG Console.WriteLine("Evaluating units..."); #endif ai_eval_units(); /* build control masks */ #if DEBUG Console.WriteLine("Building control mask..."); #endif //ai_get_ctrl_masks(); /* check new units first */ ai_status = AI_STATUS.AI_STATUS_DEPLOY; avail_unitsIterator = Scenario.avail_units.GetEnumerator(); #if DEBUG Console.WriteLine("AI Initialized"); Console.WriteLine("*** DEPLOY ***"); #endif }