Esempio n. 1
0
        public static GameState Start(
            GridCell[,] grid,
            int elfAttackPower = 3)
        {
            var gridPair = GridPair.For(grid);

            GridOperations.CalculateCloseness(gridPair);
            var elfHitPoints    = ImmutableDictionary <int, int> .Empty;
            var goblinHitPoints = ImmutableDictionary <int, int> .Empty;
            int height          = gridPair.Primary.GetLength(0);
            int width           = gridPair.Primary.GetLength(1);

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    GridCell cell = gridPair.Primary[y, x];
                    if (cell.IsElf)
                    {
                        elfHitPoints = elfHitPoints.Add(cell.ElfId.Value, 200);
                    }
                    else if (cell.IsGoblin)
                    {
                        goblinHitPoints = goblinHitPoints.Add(cell.GoblinId.Value, 200);
                    }
                }
            }

            return(new GameState(gridPair, elfHitPoints, goblinHitPoints, elfAttackPower));
        }
Esempio n. 2
0
        public static (int score, bool totalElfVictory) SolvePart1(string map, bool show = false, int elfAttackPower = 3)
        {
            int       rounds = 0;
            GameState g;
            int       startLine  = Console.CursorTop;
            bool      combatEnds = false;

            for (g = GameState.Start(GridOperations.ParseGrid(map), elfAttackPower); !combatEnds; (g, combatEnds) = g.PlayRound())
            {
                rounds += 1;
                if (show)
                {
                    Console.SetCursorPosition(0, startLine);
                    ShowGrid(g.Grid);
                }
            }

            bool goblinsWon = g.GoblinHitPoints.Any(kv => kv.Value > 0);
            int  winningTeamHitPointsRemaining = (goblinsWon ? g.GoblinHitPoints : g.ElfHitPoints)
                                                 .Select(kv => kv.Value)
                                                 .Where(p => p > 0)
                                                 .Sum();

            return(winningTeamHitPointsRemaining * (rounds - 1), g.ElfHitPoints.All(kv => kv.Value > 0));
        }
Esempio n. 3
0
        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;
                },