/// <summary> /// Update the position of all droids /// </summary> /// <param name="droids"></param> public void update(Droid[] droids, Tile[] tiles) { ourHangers = new Bb(mapWidth, mapHeight); theirHangers = new Bb(mapWidth, mapHeight); ourMovables = new Bb(mapWidth, mapHeight); theirMovables = new Bb(mapWidth, mapHeight); ourImmovables = new Bb(mapWidth, mapHeight); theirImmovables = new Bb(mapWidth, mapHeight); notAttackedByEnemy = new Bb(mapWidth, mapHeight); walkable = new Bb(mapWidth, mapHeight); attackTargets = new Bb(mapWidth, mapHeight); hackTargets = new Bb(mapWidth, mapHeight); ourHalf = new Bb(mapWidth, mapHeight); theirHalf = new Bb(mapWidth, mapHeight); ourUnitsLowArmor = new Bb(mapWidth, mapHeight); for (int i = 0; i < mapWidth; i++) { for (int j = 0; j < mapHeight; j++) { if (i < 20) { ourHalf.setValueAtSpot(i, j); } else { theirHalf.setValueAtSpot(i, j); } } } if (ourID == 1) { ourHalf.board = ourHalf.board.Not(); theirHalf.board = theirHalf.board.Not(); } for (int i = 0; i < droids.Length; i++) { Droid current = droids[i]; switch (current.Variant) { case (int)Unit.CLAW: case (int)Unit.ARCHER: case (int)Unit.REPAIRER: case (int)Unit.HACKER: case (int)Unit.TERMINATOR: if (current.HealthLeft > 0) { if (current.Owner == ourID) { ourMovables.setValueAtSpot(current.X, current.Y); if (current.HackedTurnsLeft > 0) { attackTargets.setValueAtSpot(current.X, current.Y); hackTargets.setValueAtSpot(current.X, current.Y); } else if(current.Armor < current.MaxArmor) { ourUnitsLowArmor.setValueAtSpot(current.X, current.Y); } } else { theirMovables.setValueAtSpot(current.X, current.Y); if (current.HackedTurnsLeft <= 0) { attackTargets.setValueAtSpot(current.X, current.Y); hackTargets.setValueAtSpot(current.X, current.Y); } } } break; case (int)Unit.TURRET: case (int)Unit.WALL: if (current.HealthLeft > 0) { if (current.Owner == ourID) ourImmovables.setValueAtSpot(current.X, current.Y); else { theirImmovables.setValueAtSpot(current.X, current.Y); attackTargets.setValueAtSpot(current.X, current.Y); } } break; case (int)Unit.HANGAR: if (current.HealthLeft > 0) { if (current.Owner == ourID) ourHangers.setValueAtSpot(current.X, current.Y); else { theirHangers.setValueAtSpot(current.X, current.Y); attackTargets.setValueAtSpot(current.X, current.Y); } } break; } if (current.Owner != ourID) { Queue<Point> frontier = new Queue<Point>(); HashSet<Point> explored = new HashSet<Point>(); frontier.Enqueue(new Point(current.X, current.Y)); explored.Add(new Point(current.X, current.Y)); int depth = 0; while (frontier.Count > 0 && depth < current.MaxMovement + current.Range) { depth++; Point point = frontier.Dequeue(); for (int j = -1; j < 2; j += 2) { Point pX = new Point(point.X + j, point.Y); if (pX.X >= 0 && pX.X < mapWidth) { if (!explored.Contains(pX)) { explored.Add(pX); frontier.Enqueue(new Point(pX.X, pX.Y)); notAttackedByEnemy.setValueAtSpot(pX.X, pX.Y); } } Point pY = new Point(point.X, point.Y + j); if (pY.Y >= 0 && pY.Y < mapHeight) { if (!explored.Contains(pY)) { explored.Add(pY); frontier.Enqueue(new Point(pY.X, pY.Y)); notAttackedByEnemy.setValueAtSpot(pY.X, pY.Y); } } } } } } notAttackedByEnemy.board.Not(); walkable.board.Or(ourHangers.board).Or(theirHangers.board).Or(ourMovables.board).Or(theirMovables.board).Or(ourImmovables.board).Or(theirImmovables.board); foreach (Tile t in tiles) { if (t.TurnsUntilAssembled == 1) { walkable.setValueAtSpot(t.X, t.Y); } } walkable.board.Not(); }
public override bool run() { BoardState boardState = new BoardState(droids, tiles, mapWidth(), mapHeight(), playerID()); Console.WriteLine("Turn Number: " + turnNumber().ToString()); // Find rightmost enemy turret and spawn terminator // If this is our first turn if (turnNumber() < 2) { int x1 = 10; int y1 = 0; int x2 = 10; int y2 = 0; bool foundSpot = false; bool foundSecondSpot = false; for (int i = 0; i < droids.Length; i++) { if (droids[i].Variant == (int)Unit.TURRET) { if (droids[i].Owner != playerID()) { if (getTile(droids[i].X, droids[i].Y).TurnsUntilAssembled == 0) { if (playerID() == 0) { if (droids[i].X > x1) { foundSpot = true; x1 = droids[i].X; y1 = droids[i].Y; } else if (droids[i].X > x2) { foundSecondSpot = true; x2 = droids[i].X; y2 = droids[i].Y; } } else { if (droids[i].X < x1) { foundSpot = true; x1 = droids[i].X; y1 = droids[i].Y; } else if (droids[i].X < x2) { foundSecondSpot = true; x2 = droids[i].X; y2 = droids[i].Y; } } } } } } if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost && foundSpot) { players[playerID()].orbitalDrop(x1, y1, (int)Unit.TERMINATOR); } if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost && foundSecondSpot) { players[playerID()].orbitalDrop(x2, y2, (int)Unit.TERMINATOR); } } // Find and spawn claws on enemy turrets // also count how many of each type we have int terminators = 0, claws = 0, archers = 0, hackers = 0, repair = 0; for (int i = 0; i < droids.Length; i++) { if (droids[i].Variant == (int)Unit.TURRET) { if (droids[i].Owner != playerID()) { if (getTile(droids[i].X, droids[i].Y).TurnsUntilAssembled == 0) { if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.CLAW].Cost) { players[playerID()].orbitalDrop(droids[i].X, droids[i].Y, (int)Unit.CLAW); } } } } else { if (droids[i].Owner == playerID()) { switch (droids[i].Variant) { case (int)Unit.TERMINATOR: terminators++; break; case (int)Unit.CLAW: claws++; break; case (int)Unit.ARCHER: archers++; break; case (int)Unit.HACKER: hackers++; break; case (int)Unit.REPAIRER: repair++; break; } } } } // DETECT WALLS int numUnits = 0; int colWithWall = -1; for (int i = 15; i < 25; i++) { int tempCount = 0; for (int j = 0; j < 20; j++) { if (boardState.theirMovables.getValueFromSpot(i, j) && !(getTile(i, j).TurnsUntilAssembled > 0)) tempCount++; } if (tempCount > numUnits) { numUnits = tempCount; colWithWall = i; } } // SPAWN CLAWS ON WALLS if (numUnits > 5) { for (int i = 0; i < 20; i++) { if (getTile(colWithWall, i).TurnsUntilAssembled == 0 && boardState.theirMovables.getValueFromSpot(colWithWall, i)) { if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.CLAW].Cost) { players[playerID()].orbitalDrop(colWithWall, i, (int)Unit.CLAW); } } } } Func<Point, bool> isWalkable = delegate(Point p) { return boardState.walkable.getValueFromSpot(p.X, p.Y); }; // Search for best spawn location int bestRow = 0; Bb middleRows = new Bb(mapWidth(), mapHeight()); HashSet<int> badRows = new HashSet<int>(); for (int i = 19; i < 21; i++) { for (int j = 0; j < mapHeight(); j++) { middleRows.setValueAtSpot(i, j); } } bool foundRow = false; int curCol = (playerID() == 0) ? 0 : mapWidth() - 1; Func<Point, bool> middleTarget = spot => { return middleRows.getValueFromSpot(spot.X, spot.Y); }; Bb spawnWalkable = new Bb(mapWidth(), mapHeight()); spawnWalkable.board = spawnWalkable.board.Or(boardState.walkable.board); spawnWalkable.board = spawnWalkable.board.Or(boardState.ourMovables.board); spawnWalkable.board = spawnWalkable.board.Or(boardState.theirMovables.board); int searches = 0; Func<Point, bool> spawnWalkableFunc = spot => { return spawnWalkable.getValueFromSpot(spot.X, spot.Y); }; while (!foundRow && searches < 15) { int shortest = 50; searches++; for (int i = 0; i < mapHeight(); i++) { if (getTile(curCol, i).TurnsUntilAssembled == 0) { IEnumerable<Point> path = Searcher.findPath(new Point(curCol, i), middleTarget, spawnWalkableFunc); int temp = -1; foreach (Point p in path) { temp++; } if (temp != -1 && temp < shortest) { shortest = temp; bestRow = i; foundRow = true; } else if (temp == -1) { badRows.Add(i); } } } if (!foundRow) { curCol = playerID() == 0 ? curCol + 1 : curCol - 1; badRows.Clear(); if (curCol < 0 || curCol >= mapWidth()) { curCol = (playerID() == 0) ? 0 : mapWidth() - 1; break; } } } if (searches >= 5) { curCol = playerID() == 0 ? curCol + 1 : curCol - 1; badRows.Clear(); bestRow = 0; } // want 1 terminator and hacker per 2 archers and 3 claws bool spawnClaws = terminators > claws && turnNumber() < 250; bool spawnArch = 2 * terminators > archers && !spawnClaws; bool spawnHack = terminators > hackers && turnNumber() > 25 && !spawnArch; bool spawnRepair = .5 * terminators > repair && turnNumber() > 75 && !spawnHack; int cost = 10; int unitID = 0; bool doomDrop = false; if (spawnClaws) { unitID = (int)Unit.CLAW; cost = modelVariants[(int)Unit.CLAW].Cost; } else if (spawnArch) { unitID = (int)Unit.ARCHER; cost = modelVariants[(int)Unit.ARCHER].Cost; } else if (spawnHack) { unitID = (int)Unit.HACKER; cost = modelVariants[(int)Unit.HACKER].Cost; } else if (spawnRepair) { unitID = (int)Unit.REPAIRER; cost = modelVariants[(int)Unit.REPAIRER].Cost; } else { Random rand = new Random(); if (rand.Next() % 3 == 0 && 500 - turnNumber() > 90) { // DOOM DROP TERMINATORS doomDrop = true; } unitID = (int)Unit.TERMINATOR; cost = modelVariants[(int)Unit.TERMINATOR].Cost; } Bb myUnits = new Bb(mapWidth(), mapHeight()); myUnits.board = myUnits.board.Or(boardState.ourHangers.board); myUnits.board = myUnits.board.Or(boardState.ourImmovables.board); myUnits.board = myUnits.board.Or(boardState.ourMovables.board); int iter = bestRow; int rowsChecked = 0; if (doomDrop) { // Search for walls bool foundAWall = true; while (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost && foundAWall) { bool foundWallThisIter = false; for (int i = 0; i < droids.Length; i++) { if (droids[i].Owner != playerID()) { if (droids[i].Variant == (int)Unit.WALL) { if (getTile(droids[i].X, droids[i].Y).TurnsUntilAssembled == 0) { if (playerID() == 0) { if (droids[i].X > 20) { players[playerID()].orbitalDrop(droids[i].X, droids[i].Y, (int)Unit.TERMINATOR); foundWallThisIter = true; } } else { if (droids[i].X < 20) { players[playerID()].orbitalDrop(droids[i].X, droids[i].Y, (int)Unit.TERMINATOR); foundWallThisIter = true; } } } } } } if (!foundWallThisIter) foundAWall = false; } if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost) { // search for unreachable squares int theirFirstCol = mapWidth() - 1; if (playerID() == 1) theirFirstCol = 0; int doomSearchIter = 0; bool blockedSpotFound = false; HashSet<int> rowsToSpawn = new HashSet<int>(); while (doomSearchIter < 12 && !blockedSpotFound) { for (int i = 0; i < mapHeight(); i++) { if (!(getTile(theirFirstCol, i).TurnsUntilAssembled > 0)) { IEnumerable<Point> path = Searcher.findPath(new Point(theirFirstCol, i), middleTarget, spawnWalkableFunc); int temp = -1; foreach (Point p in path) { temp++; } if (temp == -1) { rowsToSpawn.Add(i); } } } if (rowsToSpawn.Count > 0) { blockedSpotFound = true; } else { doomSearchIter++; if (playerID() == 0) { theirFirstCol--; } else { theirFirstCol++; } } } Console.WriteLine("Doom drop search spot done"); if (doomSearchIter >= 7) { doomSearchIter = 0; } int anotherIter = 0; while (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost && rowsToSpawn.Count > 0 && anotherIter < 2) { int chooseRow = rowsToSpawn.GetEnumerator().Current; players[playerID()].orbitalDrop(theirFirstCol, chooseRow, (int)Unit.TERMINATOR); rowsToSpawn.Remove(chooseRow); anotherIter++; } Console.WriteLine("Best spots have been tried"); if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost) { theirFirstCol = mapWidth() - 1; if (playerID() == 1) theirFirstCol = 0; for (int i = 0; i < mapHeight() && players[playerID()].ScrapAmount >= modelVariants[(int)Unit.TERMINATOR].Cost; i++) { if (!(getTile(theirFirstCol, i).TurnsUntilAssembled > 0)) { if (!boardState.theirHangers.getValueFromSpot(theirFirstCol, i)) { players[playerID()].orbitalDrop(theirFirstCol, i, (int)Unit.TERMINATOR); } } } } } } else { while (rowsChecked < mapHeight()) { // Not a bad row if (!badRows.Contains(iter)) { // enough scrap if (players[playerID()].ScrapAmount >= cost) { // nothing spawning here if (getTile(curCol, iter).TurnsUntilAssembled == 0) { if (!myUnits.getValueFromSpot(curCol, iter)) { // spawn it players[playerID()].orbitalDrop(curCol, iter, unitID); } } } iter++; if (iter >= mapHeight()) iter = 0; } rowsChecked++; } } // ATTACK Func<Point, bool> isAttackable = delegate(Point p) { return boardState.theirHangers.getValueFromSpot(p.X, p.Y) || boardState.hackTargets.getValueFromSpot(p.X, p.Y); }; Func<Point, bool> nope = delegate(Point p) { return false; }; for (int i = 0; i < droids.Length; i++) { //if you have control of the droid if ((droids[i].Owner == playerID() && droids[i].HackedTurnsLeft <= 0) || (droids[i].Owner != playerID() && droids[i].HackedTurnsLeft > 0)) { //if there are any attacks left if (droids[i].AttacksLeft > 0) { if (droids[i].Variant == (int)Unit.REPAIRER) { Bb targets = new Bb(boardState.ourHangers.width, boardState.ourHangers.height); targets.board = targets.board.Or(boardState.ourHangers.board); targets.board = targets.board.Or(boardState.ourMovables.board); targets.board = targets.board.Or(boardState.ourImmovables.board); Func<Point, bool> target = spot => { return targets.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], target, isWalkable, nope)); } else { Func<Point, bool> hackerTarget = spot => { return boardState.hackTargets.getValueFromSpot(spot.X, spot.Y); }; Func<Point, bool> target = spot => { return boardState.attackTargets.getValueFromSpot(spot.X, spot.Y); }; if (droids[i].Variant != (int)Unit.HACKER) { CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], target, isWalkable, nope)); } else { CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], hackerTarget, isWalkable, nope)); } } boardState.update(droids, tiles); } } } Func<Point, bool> isEnemyHangar = delegate(Point p) { return boardState.theirHangers.getValueFromSpot(p.X, p.Y); }; Func<Point, bool> isNotAttacked = delegate(Point p) { return boardState.notAttackedByEnemy.getValueFromSpot(p.X, p.Y); }; Func<Point, bool> isGoalHacker = delegate(Point p) { return boardState.hackTargets.getValueFromSpot(p.X, p.Y); }; for (int i = 0; i < droids.Length; i++) { if (droids[i].MovementLeft > 0 && ((droids[i].Owner == playerID() && droids[i].HackedTurnsLeft == 0) || (droids[i].Owner != playerID() && droids[i].HackedTurnsLeft > 0))) { if (droids[i].HealthLeft < .3 * droids[i].MaxHealth) { Bb spotsOnOurSide = new Bb(mapWidth(), mapHeight()); spotsOnOurSide.board = spotsOnOurSide.board.Or(boardState.ourHalf.board); if (droids[i].Variant == (int)Unit.REPAIRER) { Bb ourUnitsOurSide = new Bb(mapWidth(), mapHeight()); ourUnitsOurSide.board = ourUnitsOurSide.board.Or(boardState.ourHalf.board); ourUnitsOurSide.board = ourUnitsOurSide.board.And(boardState.ourMovables.board); Func<Point, bool> healTarget = spot => { return ourUnitsOurSide.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.goTo, droids[i], healTarget, isWalkable, nope)); spotsOnOurSide.board = spotsOnOurSide.board.And(boardState.walkable.board); Func<Point, bool> runAway = spot => { return spotsOnOurSide.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.goTo, droids[i], runAway, isWalkable, isAttackable)); } else { Bb theirUnitsOurSide = new Bb(mapWidth(), mapHeight()); theirUnitsOurSide.board = theirUnitsOurSide.board.Or(boardState.ourHalf.board); theirUnitsOurSide.board = theirUnitsOurSide.board.And(boardState.theirMovables.board); Func<Point, bool> attackOurSide = spot => { return theirUnitsOurSide.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.goTo, droids[i], attackOurSide, isWalkable, isAttackable)); spotsOnOurSide.board = spotsOnOurSide.board.And(boardState.walkable.board); Func<Point, bool> runAway = spot => { return spotsOnOurSide.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.goTo, droids[i], runAway, isWalkable, isAttackable)); } } else { if (!(droids[i].Variant == (int)Unit.HACKER)) { if (droids[i].Variant == (int)Unit.REPAIRER) { Func<Point, bool> healTarget = spot => { return boardState.ourUnitsLowArmor.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.goTo, droids[i], healTarget, isWalkable, nope)); } else if (droids[i].Variant == (int)Unit.TERMINATOR) { if (!CIA.runMission(new Mission(MissionTypes.goTo, droids[i], isEnemyHangar, isWalkable, isAttackable))) { CIA.runMission(new Mission(MissionTypes.goTo, droids[i], isGoalHacker, isWalkable, isAttackable)); } } else { if (!CIA.runMission(new Mission(MissionTypes.goTo, droids[i], isGoalHacker, isWalkable, isAttackable))) { CIA.runMission(new Mission(MissionTypes.goTo, droids[i], isEnemyHangar, isWalkable, isAttackable)); } } } else { CIA.runMission(new Mission(MissionTypes.goTo, droids[i], isGoalHacker, isWalkable, isAttackable)); } } boardState.update(droids, tiles); } } // ATTACK again for (int i = 0; i < droids.Length; i++) { //if you have control of the droid if ((droids[i].Owner == playerID() && droids[i].HackedTurnsLeft <= 0) || (droids[i].Owner != playerID() && droids[i].HackedTurnsLeft > 0)) { //if there are any attacks left if (droids[i].AttacksLeft > 0) { if (droids[i].Variant == (int)Unit.REPAIRER) { Bb targets = new Bb(boardState.ourHangers.width, boardState.ourHangers.height); targets.board = targets.board.Or(boardState.ourHangers.board); targets.board = targets.board.Or(boardState.ourMovables.board); targets.board = targets.board.Or(boardState.ourImmovables.board); Func<Point, bool> target = spot => { return targets.getValueFromSpot(spot.X, spot.Y); }; CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], target, isWalkable, nope)); } else { Func<Point, bool> hackerTarget = spot => { return boardState.hackTargets.getValueFromSpot(spot.X, spot.Y); }; Func<Point, bool> target = spot => { return boardState.attackTargets.getValueFromSpot(spot.X, spot.Y); }; if (droids[i].Variant != (int)Unit.HACKER) { CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], target, isWalkable, nope)); } else { CIA.runMission(new Mission(MissionTypes.attackInRange, droids[i], hackerTarget, isWalkable, nope)); } } boardState.update(droids, tiles); } } } #region Old Spawn Code //for (int i = 0; i < mapHeight(); i++) //{ // //make sure you own enough scrap // if (players[playerID()].ScrapAmount >= modelVariants[(int)Unit.CLAW].Cost) // { // //make sure nothing is spawning there // if (getTile((mapWidth() - 1) * playerID(), i).TurnsUntilAssembled == 0) // { // //make sure there isn't a hangar there // if (!boardState.ourHangers.getValueFromSpot((mapWidth() - 1) * playerID(), i)) // { // //spawn the claw // players[playerID()].orbitalDrop((mapWidth() - 1) * playerID(), i, (int)Unit.CLAW); // } // } // } //} #endregion return true; }