Example #1
0
        public static void Initialize()
        {
            var hexSystem = new HexDemo.Hex(1.0f);

            //           The starting board - 19 tiles
            //       __               __
            //    __/00\__         __/00\__    Neighbor
            // __/01\__/02\__     /01\__/05\    Directions
            ///03\__/04\__/05\    \__/  \__/
            //\__/06\__/07\__/    /02\__/04\
            ///08\__/09\__/0A\    \__/03\__/
            //\__/0B\__/0C\__/       \__/
            ///0D\__/0E\__/0F\
            //\__/10\__/11\__/
            //   \__/12\__/
            //      \__/

            HexWorldPositions = new Vector2[]
            {
              hexSystem.TileOrigin(0, 2),
              hexSystem.TileOrigin(-1, 1),
              hexSystem.TileOrigin(1, 1),
              hexSystem.TileOrigin(-2, 1),
              hexSystem.TileOrigin(0, 1),
              hexSystem.TileOrigin(2, 1),
              hexSystem.TileOrigin(-1, 0),
              hexSystem.TileOrigin(1, 0),
              hexSystem.TileOrigin(-2, 0),
              hexSystem.TileOrigin(0, 0),
              hexSystem.TileOrigin(2, 0),
              hexSystem.TileOrigin(-1, -1),
              hexSystem.TileOrigin(1, -1),
              hexSystem.TileOrigin(-2, -1),
              hexSystem.TileOrigin(0, -1),
              hexSystem.TileOrigin(2, -1),
              hexSystem.TileOrigin(-1, -2),
              hexSystem.TileOrigin(1, -2),
              hexSystem.TileOrigin(0, -2)
            };

            InitialBoard = Board.Empty().WithHeader(new StateHeader(0));
            for (var x = 0; x < 19; ++x)
            {
                var tile = new Tile((byte)x, 0x00);
                foreach (var item in InitialPiecePlacements[x])
                    tile = tile.WithTriangle(item, 0x01);
                InitialBoard = InitialBoard.WithTile((byte)x, tile);
            }
        }
Example #2
0
        public static Board ApplyMove(Board Board, Move Move)
        {
            var checkForSurrounded = new List<Coordinate>();
            var checkForEmpty = new List<byte>();
            var sniping = false;

            switch ((MoveType)Move.Type)
            {
                case MoveType.Trade:
                    {
                        /*
                        // Verify move is legal.

                        // Reject move if attempting to snipe own piece.
                        if (Move.Triangle % 2 != Board.Header.WhoseTurnNext) throw new InvalidOperationException();

                        // Reject move if player does not hold at least two tiles.
                        var heldTileCount = Board.Tiles.Count(t => t.IsHeldBy(Board.Header.WhoseTurnNext));
                        if (heldTileCount < 2) throw new InvalidOperationException();

                        // Reject move if there is no enemy piece at the location.
                        if (Board.GetTriangle(Move.Coordinate) == 0) throw new InvalidOperationException();
                        */
                        // Turn is legal, mutate board.
                        foreach (var tile in Board.Tiles.Where(t => t.IsHeldBy(Board.Header.WhoseTurnNext)).Take(2))
                            Board = Board.WithTile(tile.ID, tile.WithStatus(0x03));
                        Board = Board.WithTile(Move.Tile, Board.GetTile(Move.Tile).WithTriangle(Move.Triangle, 0));

                        checkForEmpty.Add(Move.Tile);
                        sniping = true;
                    }
                    break;
                case MoveType.MovePiece:
                    {
                        /*
                        // Verify move is legal.

                        // Reject move if attempting to move opponent piece.
                        if (Move.Triangle % 2 == Board.Header.WhoseTurnNext) throw new InvalidOperationException();

                        // Reject move if there is no piece at the location.
                        if (Board.GetTriangle(Move.Coordinate) == 0) throw new InvalidOperationException();

                        // Find destination triangle coordinate.
                        */
                        var dest = FindMoveNeighbor(Move.Coordinate, Move.Direction);
                        /*
                        // Reject move if player attempted to move off board.
                        if (dest.Invalid) throw new InvalidOperationException();
                        if (Board.GetTile(dest.Tile).IsOutOfPlay()) throw new InvalidOperationException();

                        // Reject move if destination triangle is occupied.
                        if (Board.GetTriangle(dest) != 0) throw new InvalidOperationException();
                        */
                        // Move is legal, mutate board.

                        Board = Board.WithTile(Move.Tile, Board.GetTile(Move.Tile).WithTriangle(Move.Triangle, 0));
                        Board = Board.WithTile(dest.Tile, Board.GetTile(dest.Tile).WithTriangle(dest.Triangle, 1));

                        checkForEmpty.Add(Move.Tile);

                        for (byte x = 0; x < 3; ++x)
                        {
                            var neighbor = FindSurroundNeighbor(dest, x);
                            if (!neighbor.Invalid && !Board.GetTile(neighbor.Tile).IsOutOfPlay())
                                checkForSurrounded.Add(neighbor);
                        }
                    }
                    break;
            }

            while (checkForSurrounded.Count > 0 || checkForEmpty.Count > 0)
            {
                while (checkForSurrounded.Count > 0)
                {
                    var piece = checkForSurrounded[0];
                    checkForSurrounded.RemoveAt(0);

                    var sum = 0;
                    for (byte x = 0; x < 3; ++x)
                    {
                        var neighbor = FindSurroundNeighbor(piece, x);
                        if (neighbor.Invalid || Board.GetTile(neighbor.Tile).IsOutOfPlay())
                            sum += 1;
                        else
                            sum += Board.GetTriangle(neighbor);
                    }

                    if (sum == 3)
                    {
                        Board = Board.WithTile(piece.Tile, Board.GetTile(piece.Tile).WithTriangle(piece.Triangle, 0));
                        checkForEmpty.Add(piece.Tile);
                    }
                }

                while (checkForEmpty.Count > 0)
                {
                    var tileID = checkForEmpty[0];
                    checkForEmpty.RemoveAt(0);

                    if (!Board.GetTile(tileID).IsEmpty())
                        continue;

                    // Tile is empty - if it has 3 or less adjacent tiles in a row, it can be removed.

                    var runs = new AdjacentRun[3];
                    var runsCount = 0;

                    for (var x = 0; x < 6; ++x)
                    {
                        var neighbor = Tables.TileAdjacency[tileID][x];
                        if (neighbor != 0xFF && !Board.GetTile(neighbor).IsOutOfPlay())
                        {
                            if (runsCount == 0)
                            {
                                runs[0] = new AdjacentRun(x, x, 1);
                                runsCount += 1;
                            }
                            else if (runs[runsCount - 1].End == x - 1)
                                runs[runsCount - 1] = new AdjacentRun(runs[runsCount - 1].Start, x, runs[runsCount - 1].Count + 1);
                            else
                            {
                                runs[runsCount] = new AdjacentRun(x, x, 1);
                                runsCount += 1;
                            }
                        }
                    }

                    if (runsCount > 1 && runs[0].Start == 0 && runs[runsCount - 1].End == 5)
                    {
                        runs[0] = new AdjacentRun(runs[runsCount - 1].Start, runs[0].End, runs[0].Count + runs[runsCount - 1].Count);
                        runsCount -= 1;
                    }

                    if (runsCount == 1 && runs[0].Count <= 3)
                    {
                        if (sniping)
                            Board = Board.WithTile(tileID, Board.GetTile(tileID).WithStatus(0x03));
                        else
                            Board = Board.WithTile(tileID, Board.GetTile(tileID).WithStatus((byte)(Board.Header.WhoseTurnNext + 1)));

                        // Mark adjacent triangles for surround consideration.
                        for (var x = 0; x < 6; ++x)
                        {
                            // Don't check own pieces for surround
                            if (Tables.ExposedAdjacency[x] % 2 != Board.Header.WhoseTurnNext) continue;

                            // Don't check tiles that don't exist.
                            var neighbor = Tables.TileAdjacency[tileID][x];
                            if (neighbor == 0xFF || Board.GetTile(neighbor).IsOutOfPlay()) continue;

                            checkForSurrounded.Add(new Coordinate(neighbor, Tables.ExposedAdjacency[x]));
                        }

                        // Check neighboring tiles to see if they can be removed.
                        for (var x = 0; x < 6; ++x)
                        {
                            var neighbor = Tables.TileAdjacency[tileID][x];
                            if (neighbor == 0xFF || Board.GetTile(neighbor).IsOutOfPlay()) continue;
                            checkForEmpty.Add(neighbor);
                        }
                    }
                }
            }

            if (Board.Header.WhoseTurnNext == 0)
                Board = Board.WithHeader(new StateHeader(0x80));
            else
                Board = Board.WithHeader(new StateHeader(0x00));

            return Board;
        }