private static GridCell[,] ParseGrid(IEnumerable <string> lines) { int y = 0; var allLines = lines.ToList(); int width = allLines[0].Length; var grid = new GridCell[allLines.Count, width]; int nextGoblinId = 0; int nextElfId = 0; foreach (string line in lines.Where(s => !string.IsNullOrWhiteSpace(s))) { if (line.Length != width) { throw new ArgumentException("All lines must be same length"); } int x = 0; foreach (char c in line) { GridCell cell; switch (c) { case '#': cell = GridCell.Wall(); break; case '.': cell = GridCell.Empty(); break; case 'G': cell = GridCell.Goblin(nextGoblinId++); break; case 'E': cell = GridCell.Elf(nextElfId++); break; default: throw new ArgumentException("Unknown map cell type: " + c); } grid[y, x++] = cell; } y += 1; } return(grid); }
public (GameState state, bool combatEnds) PlayRound() { bool combatEnds = false; var coordinates = new List <(int x, int y)>(); int height = Grid.GetLength(0); int width = Grid.GetLength(1); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { GridCell cell = Grid[y, x]; if (cell.IsElf || cell.IsGoblin) { coordinates.Add((x, y)); } } } var elfHitPoints = ElfHitPoints; var goblinHitPoints = GoblinHitPoints; GridCell[,] grid = Grid; for (int i = 0; i < coordinates.Count; ++i) { var xy = coordinates[i]; GridCell unitCell = grid[xy.y, xy.x]; if (!(unitCell.IsElf || unitCell.IsGoblin)) { // Already taken out in an earlier turn this round. continue; } if ((unitCell.IsElf && !goblinHitPoints.Any(kv => kv.Value > 0)) || (unitCell.IsGoblin && !elfHitPoints.Any(kv => kv.Value > 0))) { combatEnds = true; break; } int hitPower = unitCell.IsElf ? elfHitPoints[unitCell.ElfId.Value] : goblinHitPoints[unitCell.GoblinId.Value]; // Move if appropriate. var move = GridOperations.CalculateMove(grid, xy.x, xy.y); if (move.HasValue) { bool isElf = unitCell.IsElf; int unitId = isElf ? unitCell.ElfId.Value : unitCell.GoblinId.Value; RemoveItem(height, width, grid, xy); var newCoordinates = (x : xy.x + move.Value.dx, y : xy.y + move.Value.dy); grid[newCoordinates.y, newCoordinates.x] = isElf ? GridCell.Elf(unitId) : GridCell.Goblin(unitId); GridOperations.CalculateCloseness(_gridPair); coordinates[i] = newCoordinates; } // Attack if appropriate. xy = coordinates[i]; var match = GridOperations.FindBest( grid, xy.x, xy.y, c => { bool isTarget = unitCell.IsElf ? c.IsGoblin : c.IsElf; return(isTarget ? NullIfDead(unitCell.IsElf ? goblinHitPoints[c.GoblinId.Value] : elfHitPoints[c.ElfId.Value]) : default); int?NullIfDead(int v) => v > 0 ? v : default; },