public static bool CanPath(UnitJob job, Player player, Tile tile, bool ignoreUnits = false) { if (job == AI.WORKER) { return((ignoreUnits || tile.Unit == null) && tile.IsGrass && tile.Owner != player.Opponent && tile.Tower == null); } return(tile.IsPath && (ignoreUnits || tile.Unit == null || (tile.Unit.Job == job && tile.NumUnits(job) < job.PerTile))); }
public static bool canAttackJob(TowerJob towerJ, UnitJob unitJ) { if (unitJ == AI.WORKER) { return(false); } if (towerJ == AI.CASTLE) { return(true); } if (towerJ == AI.CLEANSING) { return(unitJ == AI.WRAITH || unitJ == AI.ABOMINATION); } return(unitJ != AI.WRAITH); }
public static int NumUnits(this Tile tile, UnitJob job) { if (tile.Unit == null) { return(0); } if (tile.Unit.Job.PerTile == 1) { return(1); } switch (job.Title) { case "zombie": return(tile.NumZombies); case "ghoul": return(tile.NumGhouls); case "hound": return(tile.NumHounds); } return(1); }
/// <summary> /// This is automatically called when the game first starts, once the Game and all GameObjects have been initialized, but before any players do anything. /// </summary> /// <remarks> /// This is a good place to initialize any variables you add to your AI or start tracking game objects. /// </remarks> public override void Start() { // <<-- Creer-Merge: start -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs. base.Start(); AI.GAME = this.Game; AI.US = this.Player; AI.THEM = this.Game.Players.First(p => p != AI.US); AI.CASTLE = this.Game.TowerJobs.First(t => t.Title == "castle"); AI.CLEANSING = this.Game.TowerJobs.First(t => t.Title == "cleansing"); AI.BALLISTA = this.Game.TowerJobs.First(t => t.Title == "ballista"); AI.ARROW = this.Game.TowerJobs.First(t => t.Title == "arrow"); AI.AOE = this.Game.TowerJobs.First(t => t.Title == "aoe"); AI.WORKER = this.Game.UnitJobs.First(t => t.Title == "worker"); AI.ZOMBIE = this.Game.UnitJobs.First(t => t.Title == "zombie"); AI.GHOUL = this.Game.UnitJobs.First(t => t.Title == "ghoul"); AI.HOUND = this.Game.UnitJobs.First(t => t.Title == "hound"); AI.ABOMINATION = this.Game.UnitJobs.First(t => t.Title == "abomination"); AI.WRAITH = this.Game.UnitJobs.First(t => t.Title == "wraith"); AI.HORSEMAN = this.Game.UnitJobs.First(t => t.Title == "horseman"); AI.UNIT_SPAWNER = this.Game.Tiles.First(t => t.IsUnitSpawn && t.Owner == AI.US); AI.WORKER_SPAWNER = this.Game.Tiles.First(t => t.IsWorkerSpawn && t.Owner == AI.US); AI.OUR_CASTLE = AI.US.Towers.First(t => t.Job == AI.CASTLE); AI.THEIR_CASTLE = AI.THEM.Towers.First(t => t.Job == AI.CASTLE); AI.GOLD_MINES = new HashSet <Tile>(AI.GAME.Tiles.Where(t => t.IsGoldMine && t.Owner == AI.US)); AI.ISLAND_GOLD_MINES = new HashSet <Tile>(AI.GAME.Tiles.Where(t => t.IsIslandGoldMine)); AI.RIVER_NEIGHBORS = new HashSet <Tile>(AI.GAME.Tiles.Where(t => t.IsRiver).SelectMany(t => t.GetNeighbors()).Where(t => t.IsGrass)); AI.CASTLE_TOWER = AI.US.Towers.First(t => t.Job == AI.CASTLE); var castleTile = AI.CASTLE_TOWER.Tile; if (castleTile.TileNorth.TileNorth.IsPath) { var leftX = castleTile.X - 1; var rightX = castleTile.X + 2; var startY = castleTile.Y - 3; AI.LEFT_TOWERS = Enumerable.Range(0, 15).Select(o => AI.GAME.GetTileAt(leftX, startY - o)).ToList(); AI.RIGHT_TOWERS = Enumerable.Range(0, 15).Select(o => AI.GAME.GetTileAt(rightX, startY - o)).ToList(); } else { var leftX = castleTile.X - 2; var rightX = castleTile.X + 1; var startY = castleTile.Y + 3; AI.LEFT_TOWERS = Enumerable.Range(0, 15).Select(o => AI.GAME.GetTileAt(leftX, startY + o)).ToList(); AI.RIGHT_TOWERS = Enumerable.Range(0, 15).Select(o => AI.GAME.GetTileAt(rightX, startY + o)).ToList(); } AI.TOWER_PATTERN = new List <TowerJob>() { AI.CLEANSING, AI.AOE, AI.ARROW }; string[][] patterns = new string[][] { new[] { "0110110", "1001001", "1000001", "0100010", "0010100", "0001000" }, // Heart new[] { "00111100", "01000010", "10100101", "10000001", "10100101", "10011001", "01000010", "00100100" }, // Smiley new[] { "01010", "10001", "11011", "01110", "00100", "00100", "00100" }, // Wrench new[] { "01100", "00010", "00101", "01001", "10000" }, // Pick axe new[] { "100010010", "100101010", "110010011" }, // L O L new[] { "00011000", "00100100", "01000010", "10000001", "01111110" }, // Delta new[] { "0001000", "0011100", "0000000", "0100010", "1110111" } // Triforce }; ; var pattern = patterns[new Random().Next(patterns.Length)]; Console.WriteLine(String.Join("\n", pattern)); AI.PATTERN = new HashSet <Tile>(); Tile patternAnchor; if (AI.CASTLE_TOWER.Tile.TileNorth.TileNorth.IsPath) { patternAnchor = AI.GAME.GetTileAt(36, 11); } else { patternAnchor = AI.GAME.GetTileAt(27 - pattern[0].Length, 11); } for (int x = 0; x < pattern[0].Length; x++) { for (int y = 0; y < pattern.Length; y++) { if (pattern[y][x] == '1') { AI.PATTERN.Add(AI.GAME.GetTileAt(patternAnchor.X + x, patternAnchor.Y + y)); } } } // <<-- /Creer-Merge: start -->> }
public static void MoveAndSpreadAndAttack(Unit unit, IEnumerable <Tower> targets, UnitJob job) { if (unit.Acted || unit.Moves == 0) { return; } var targetNeighbors = new HashSet <Tile>(targets.SelectMany(t => t.Tile.GetNeighbors())); var pathsToNeighbors = FindPaths(unit.Tile.ToEnumerable(), targetNeighbors, t => CanPath(job, AI.US, t)); var reachableTargetNeighbors = pathsToNeighbors.Keys.Where(t => pathsToNeighbors[t].Count <= unit.Moves + 1); LinkedList <Tile> path = null; if (reachableTargetNeighbors.Any()) { path = pathsToNeighbors[reachableTargetNeighbors.MinByValue(t => t.NumUnits(job))]; } else { var pathsIgnore = FindPaths(unit.Tile.ToEnumerable(), targetNeighbors, t => CanPath(job, AI.US, t, true)); if (pathsIgnore.Count > 0) { path = pathsIgnore.MinByValue(kvp => kvp.Value.Count).Value; } } if (path == null) { return; } path.RemoveFirst(); while (unit.Moves > 0 && path.Count > 0 && CanPath(job, AI.US, path.First())) { unit.Move(path.First()); path.RemoveFirst(); } var target = targets.FirstOrDefault(t => t.Tile.HasNeighbor(unit.Tile)); if (target != null) { unit.Attack(target.Tile); } }
public static Tuple <Unit, Tile> MoveNearest(IEnumerable <Unit> units, IEnumerable <Tile> targets, UnitJob job) { var movable = units.Where(u => !u.Acted && u.Moves > 0); if (!movable.Any()) { return(null); } var steps = FindPath(movable.Select(u => u.Tile), targets, t => CanPath(job, AI.US, t)); if (steps.Count == 0) { steps = FindPath(movable.Select(u => u.Tile), targets, t => CanPath(job, AI.US, t, true)); if (steps.Count == 0) { return(null); } } var moverTile = steps.First(); var mover = units.First(u => u.Tile == moverTile); var target = steps.Last(); steps.RemoveFirst(); while (mover.Moves > 0 && steps.Count > 0 && CanPath(job, AI.US, steps.First())) { mover.Move(steps.First()); steps.RemoveFirst(); } return(Tuple.Create(mover, target)); }
public static bool CanAfford(Player player, UnitJob job, int count = 1) { return(player.Gold >= job.GoldCost * count && player.Mana >= job.ManaCost * count); }