public QueuedAttack(PirateContainer p, List <Pirate> e) { P = p; E = e; queued.Add(this); foreach (Pirate t in e) { if (!targetMap.ContainsKey(t)) { targetMap.Add(t, new List <PirateContainer>()); } targetMap[t].Add(p); } }
public static void doAttacks(IPirateGame game, bool deadMap) { if (shot != null) { game.Debug("can only call doAttacks(IPirateGame) once per turn!"); return; } shot = new List <Pirate>(); foreach (Pirate p in targetMap.Keys) { foreach (PirateContainer c in targetMap[p]) { game.Debug(p.Id + " --> " + c.P.Id); } } for (int i = 1; i <= game.AllMyPirates().Count&& targetMap.Keys.Count > 0; i++) { List <Pirate> removed = new List <Pirate>(); foreach (Pirate p in targetMap.Keys) { if (targetMap[p].Count == i && p.DefenseExpirationTurns == 0 && (!deadMap || p.HasTreasure)) { PirateContainer pc = targetMap[p][0]; pc.attack(p, game); removed.Add(p); foreach (Pirate k in targetMap.Keys) { targetMap[k].Remove(pc); } } } foreach (Pirate p in removed) { targetMap.Remove(p); } } /*for (int i = 0; i < queued.Count; i++) * { * if (queued[i].E.Count == 1 && !shot.Contains(queued[i].E[0])) * { * queued[i].P.attack(queued[i].E[0], game);// TODO: if kamikaze, and my target, ignore it * shot.Add(queued[i].E[0]); * } * }*/ }
// can we move the given Pirate to the given Location according to the number of moves? // if so --> move it! private static int move(PirateContainer p, Location t, int moves, IPirateGame game, bool dontHitEnemies = false) { if (moves == 0 || !p.AVALIBLE || p.P.Location.Equals(t)) { return(0); } // calculate the best route foreach (Location l in game.GetSailOptions(p.P, t, moves)) { if (!QueuedMotion.isOccupied(l, game, dontHitEnemies) && p.move(l, game)) { return(game.Distance(p.P, l)); } } game.Debug("Failed to find a move for " + p.P.Id + " to " + t); return(0); }
// this is the actual turn public void DoTurn(IPirateGame game) { if (game.GetTurn() == 1) { Location l = new Location(1, 1); foreach (Treasure t in game.Treasures()) { if (t.Location.Equals(l)) { deadMap = true; break; } } game.Debug((deadMap ? "DEADMAP!!!" : "NIE!")); if (!deadMap) { return; // this stops some fighting over treasures } } nowhere = (game.GetEnemyScore() == game.GetMyScore() && game.GetTurn() == (game.GetMaxTurns() / 3)); if (nowhere) { game.Debug("ACTIVATING NOWHERE MODE!!!"); } panic = (((game.Treasures().Count == 0 || game.GetEnemyScore() >= (game.GetMaxPoints() - 2))) && game.EnemyPiratesWithTreasures().Count > 0); if (panic) { game.Debug("ACTIVATING PANIC MODE!!!"); } PirateContainer.init(game); QueuedAttack.init(); QueuedMotion.init(); int remaining = game.GetActionsPerTurn(); int ships = game.AllMyPirates().Count; try { // calculate the closest treasure to ps[i] PirateContainer[] ps = new PirateContainer[ships]; int[] ds = new int[ships]; Treasure[] ts = new Treasure[ships]; for (int i = 0; i < ships; i++) { ps[i] = new PirateContainer(game.GetMyPirate(i), (i % 2) == 1); ds[i] = int.MaxValue; foreach (Treasure t in game.Treasures()) { if (game.Distance(ps[i].P, t) < ds[i]) { ds[i] = game.Distance(ps[i].P, t); ts[i] = t; } } } // control the kamikazes calcKamikazes(ps, ref ts, ref ds, game); // move Pirates that have treasures towards the base { List <PirateContainer> ltp = PirateContainer.withTreasure; foreach (PirateContainer p in ltp) { remaining -= move(p, p.P.InitialLocation, 1, game, true); } } // search and destroy, TODO: prioritise this!!! Pirate k = null, tar = null; if (panic) { int mx = (game.GetRows() + game.GetCols() - game.GetAttackRadius()) / game.GetActionsPerTurn(); // turns it takes to get from a corner to its opposing corner int d = int.MaxValue; tar = game.EnemyPiratesWithTreasures()[0]; // TODO: focus on closest to enemy base // find closest Pirate foreach (PirateContainer p in PirateContainer.free) // notice all pirates with Treasure already moved, see: ltp { if (p.AVALIBLE && p.P.ReloadTurns < mx && d > game.Distance(p.P, tar)) { d = game.Distance(p.P, tar); k = p.P; } } if (k == null) // no Pirate with ammo, so choose the closest to the InitialLocation then move to there { foreach (PirateContainer p in PirateContainer.free) // notice all pirates with Treasure already moved, see: ltp { if (p.AVALIBLE && d > game.Distance(p.P, tar.InitialLocation)) // TODO: make the "6" generic to board size { d = game.Distance(p.P, tar.InitialLocation); k = p.P; } } } } List <int> dss = sortInto(ds); // sort the ds into the dss // AAAAATTTTTTTTTTTTAAAAAAAAAAACCCCCCCCKKKKKKKKKKKKKKK!!!!!!!!!!!!!!!! (or defend...) for (int i = PirateContainer.free.Count; i > 0;) { PirateContainer p = PirateContainer.free[--i]; if (p.P.ReloadTurns == 0 && !p.P.HasTreasure && p.AVALIBLE) { List <Pirate> es = findTargetsFor(p.P, game); if (es.Count > 0) { new QueuedAttack(p, es); } } } QueuedAttack.doAttacks(game, deadMap); // move for (int j = 0; j < ships; j++) { int i = dss[j]; if (ps[i].S == PirateContainer.State.none && ps[i].AVALIBLE && !ps[i].P.HasTreasure) { if (game.Treasures().Count > 0) // use typical motion { int mv = move(ps[i], ts[i].Location, remaining, game); if (mv > 0) { remaining -= mv; continue; } } if (game.EnemyPiratesWithTreasures().Count > 0 && ps[i].P == k) // activate search and destroy { remaining -= move(ps[i], tar.Location, remaining, game); } } } } catch (Exception e) { game.Debug("Crashed!"); game.Debug(e.Message); game.Debug(e.StackTrace); } game.Debug("turn " + game.GetTurn() + ": ran " + (game.GetActionsPerTurn() - remaining) + " motions"); }