示例#1
0
        private void Visit(CellState startCellState)
        {
            startCellState.Visited = true;
            count++;
            startCellState.DfsDepth = count;
            startCellState.DfsLow   = count;
            foreach (CellState adjacentCellState in startCellState.GetAdjacentCellStates())
            {
                if (adjacentCellState.OccupationStatus != OccupationStatus.YourWall && adjacentCellState.OccupationStatus != OccupationStatus.OpponentWall)
                {
                    if (!adjacentCellState.Visited)
                    {
                        Edge newEdge = new Edge
                        {
                            StartVertex = startCellState,
                            EndVertex   = adjacentCellState
                        };
                        edgeStack.Push(newEdge);
                        adjacentCellState.ParentCellState = startCellState;
                        Visit(adjacentCellState);
                        if (adjacentCellState.DfsLow >= startCellState.DfsDepth)
                        {
                            // Create a biconnected component
                            BiconnectedComponent component = new BiconnectedComponent(nextComponentNumber);
                            nextComponentNumber++;
                            startCellState.GameState.AddBiconnectedComponent(component);

                            Edge poppedEdge = null;
                            do
                            {
                                poppedEdge = edgeStack.Pop();
                                component.AddCell(poppedEdge.StartVertex);
                                component.AddCell(poppedEdge.EndVertex);
                                poppedEdge.StartVertex.AddBiconnectedComponent(component);
                                poppedEdge.EndVertex.AddBiconnectedComponent(component);
                            }while (poppedEdge != newEdge);
                        }
                        if (adjacentCellState.DfsLow < startCellState.DfsLow)
                        {
                            startCellState.DfsLow = adjacentCellState.DfsLow;
                        }
                    }
                    else
                    if (!(adjacentCellState.ParentCellState == startCellState) && (adjacentCellState.DfsDepth < startCellState.DfsDepth))
                    {
                        // The link from startCellState to adjacentCellState is a back edge to an ancestor of startCellState:
                        Edge backEdge = new Edge
                        {
                            StartVertex = startCellState,
                            EndVertex   = adjacentCellState
                        };
                        edgeStack.Push(backEdge);
                        if (adjacentCellState.DfsDepth < startCellState.DfsLow)
                        {
                            startCellState.DfsLow = adjacentCellState.DfsDepth;
                        }
                    }
                }
            }
        }
示例#2
0
        public override RuleOutcome ReplayAndChooseNextMove(GameState gameStateBeforeStep, GameState currentGameState)
        {
            Position to = To;

            if (GetPosition != null)
            {
                to = GetPosition(this, gameStateBeforeStep, currentGameState);
            }
            to = GetFlippedTo(to);

            Dijkstra.Perform(gameStateBeforeStep);
            CellState destinationState = gameStateBeforeStep[to];
            int       distanceFromYou  = destinationState.DistanceFromYou;

            List <Position> positionsOnRoute = new List <Position>();

            if (destinationState.OccupationStatus == OccupationStatus.Clear &&
                (destinationState.CompartmentStatus == CompartmentStatus.InYourCompartment ||
                 destinationState.CompartmentStatus == CompartmentStatus.InSharedCompartment))
            {
                for (int dist = distanceFromYou - 1; dist > 0; dist--)
                {
                    int d = dist;
                    destinationState = destinationState.GetAdjacentCellStates().Where(
                        cs => cs.OccupationStatus == OccupationStatus.Clear && cs.DistanceFromYou == d).FirstOrDefault();
                    positionsOnRoute.Insert(0, destinationState.Position);
                }

                int nextMoveNumber = gameStateBeforeStep.YourCell.MoveNumber;
                foreach (Position nextPosition in positionsOnRoute)
                {
                    nextMoveNumber++;
                    RuleOutcome outcome = MoveToNextPosition(gameStateBeforeStep, currentGameState, nextPosition, nextMoveNumber);
                    if (outcome.Status != RuleStatus.NoFurtherSuggestions)
                    {
                        return(outcome);
                    }
                }

                return(new RuleOutcome
                {
                    Status = RuleStatus.NoFurtherSuggestions
                });
            }
            else
            {
                return(new RuleOutcome
                {
                    Status = RuleStatus.OpponentBlockedMove
                });
            }
        }
示例#3
0
        private static void CheckIfCellIsOnFrontierForPlayer(GameState gameState, CellState cellState, PlayerType playerType)
        {
            PlayerType       otherPlayerType;
            OccupationStatus otherPlayerOccupationStatus;
            int distanceFromPlayer;
            int distanceFromOtherPlayer;

            switch (playerType)
            {
            case PlayerType.You:
                otherPlayerType             = PlayerType.Opponent;
                otherPlayerOccupationStatus = OccupationStatus.Opponent;
                distanceFromPlayer          = cellState.DistanceFromYou;
                distanceFromOtherPlayer     = cellState.DistanceFromOpponent;
                break;

            default:      // Assume PlayerType.Opponent
                otherPlayerType             = PlayerType.You;
                otherPlayerOccupationStatus = OccupationStatus.You;
                distanceFromPlayer          = cellState.DistanceFromOpponent;
                distanceFromOtherPlayer     = cellState.DistanceFromYou;
                break;
            }

            // It's not on the frontier if it's too far from the other player:
            if (distanceFromPlayer < distanceFromOtherPlayer - 2)
            {
                return;
            }

            bool isOnFrontier = false;

            foreach (CellState adjacentCellState in cellState.GetAdjacentCellStates())
            {
                if (adjacentCellState.ClosestPlayer == otherPlayerType &&
                    (adjacentCellState.OccupationStatus == OccupationStatus.Clear || adjacentCellState.OccupationStatus == otherPlayerOccupationStatus))
                {
                    isOnFrontier = true;
                    break;
                }
            }

            if (isOnFrontier)
            {
                gameState.AddFrontierCellForPlayer(cellState, playerType);
            }
        }
        private void Visit(CellState startCellState)
        {
            startCellState.Visited = true;
            count++;
            startCellState.DfsDepth = count;
            startCellState.DfsLow   = count;
            foreach (CellState adjacentCellState in startCellState.GetAdjacentCellStates())
            {
                if (adjacentCellState.ClosestPlayer == player &&
                    (adjacentCellState.OccupationStatus == OccupationStatus.Clear || adjacentCellState.OccupationStatus == playerOccupationStatus))
                {
                    if (!adjacentCellState.Visited)
                    {
                        Edge newEdge = new Edge
                        {
                            StartVertex = startCellState,
                            EndVertex   = adjacentCellState
                        };
                        edgeStack.Push(newEdge);
                        adjacentCellState.ParentCellState = startCellState;
                        Visit(adjacentCellState);
                        if (adjacentCellState.DfsLow >= startCellState.DfsDepth)
                        {
                            // Create a chamber
                            Chamber chamber = new Chamber(nextChamberNumber);
                            nextChamberNumber++;
                            startCellState.GameState.AddChamber(chamber, player);

                            Edge poppedEdge = null;
                            do
                            {
                                poppedEdge = edgeStack.Pop();
                                chamber.AddCell(poppedEdge.StartVertex);
                                chamber.AddCell(poppedEdge.EndVertex);
                                poppedEdge.StartVertex.AddChamber(chamber, player);
                                poppedEdge.EndVertex.AddChamber(chamber, player);
                            }while (poppedEdge != newEdge);
                        }
                        if (adjacentCellState.DfsLow < startCellState.DfsLow)
                        {
                            startCellState.DfsLow = adjacentCellState.DfsLow;
                        }
                    }
                    else
                    if (!(adjacentCellState.ParentCellState == startCellState) && (adjacentCellState.DfsDepth < startCellState.DfsDepth))
                    {
                        // The link from startCellState to adjacentCellState is a back edge to an ancestor of startCellState:
                        Edge backEdge = new Edge
                        {
                            StartVertex = startCellState,
                            EndVertex   = adjacentCellState
                        };
                        edgeStack.Push(backEdge);
                        if (adjacentCellState.DfsDepth < startCellState.DfsLow)
                        {
                            startCellState.DfsLow = adjacentCellState.DfsDepth;
                        }
                    }
                }
            }
        }
示例#5
0
        protected override void CalculateDistancesFromAPlayer(GameState gameState, PlayerType player, HashSet <CellState> reachableCells)
        {
            int nextDistance                 = 0;
            int numberOfCellsReachable       = 0;
            int totalDegreesOfCellsReachable = 0;
            Queue <CellState> cellsToExpand  = new Queue <CellState>(120); // = 4 * 30; to prevent resizing later on

            DijkstraStatus dijkstraStatus           = DijkstraStatus.NotCalculated;
            bool           isPartiallyCalculated    = false;
            int            upToDateDijkstraDistance = 0;
            CellState      playersCell;

            CompartmentStatus   compartmentStatus;
            GetDistanceDelegate getDistance = null;
            SetDistanceDelegate setDistance = null;

            switch (player)
            {
            case PlayerType.You:
                compartmentStatus        = CompartmentStatus.InYourCompartment;
                getDistance              = GetDistanceFromYou;
                setDistance              = SetDistanceFromYou;
                dijkstraStatus           = gameState.YourDijkstraStatus;
                upToDateDijkstraDistance = gameState.YourUpToDateDijkstraDistance;
                playersCell              = gameState.YourCell;
                break;

            case PlayerType.Opponent:
                compartmentStatus        = CompartmentStatus.InOpponentsCompartment;
                getDistance              = GetDistanceFromOpponent;
                setDistance              = SetDistanceFromOpponent;
                dijkstraStatus           = gameState.OpponentsDijkstraStatus;
                upToDateDijkstraDistance = gameState.OpponentsUpToDateDijkstraDistance;
                playersCell              = gameState.OpponentsCell;
                break;

            default:
                throw new ApplicationException("The player must be specified when calculating distances");
            }

            if (dijkstraStatus != DijkstraStatus.FullyCalculated)
            {
                if (player == PlayerType.You)
                {
                    gameState.OpponentIsInSameCompartment = false;
                }

                isPartiallyCalculated = (dijkstraStatus == DijkstraStatus.PartiallyCalculated && upToDateDijkstraDistance > 0);

                if (isPartiallyCalculated)
                {
                    nextDistance = upToDateDijkstraDistance;
                    foreach (CellState cellState in gameState.GetAllCellStates())
                    {
                        int distance = getDistance(cellState);
                        if ((cellState.OccupationStatus == OccupationStatus.Clear) &&
                            (cellState.CompartmentStatus == compartmentStatus || cellState.CompartmentStatus == CompartmentStatus.InSharedCompartment) &&
                            (distance <= upToDateDijkstraDistance))
                        {
                            if (reachableCells != null)
                            {
                                reachableCells.Add(cellState);
                            }
                            numberOfCellsReachable++;
                            totalDegreesOfCellsReachable += cellState.DegreeOfVertex;
                            if (distance == upToDateDijkstraDistance)
                            {
                                cellsToExpand.Enqueue(cellState);
                            }
                        }
                        else
                        {
                            cellState.ClearDijkstraStateForPlayer(player);
                        }
                    }
                }
                else
                {
                    gameState.ClearDijkstraPropertiesForPlayer(player);
                    cellsToExpand.Enqueue(playersCell);
                }

                while (cellsToExpand.Count > 0)
                {
                    CellState sourceCell = cellsToExpand.Dequeue();
                    nextDistance = getDistance(sourceCell) + 1;
                    CellState[] adjacentCells = sourceCell.GetAdjacentCellStates();
                    foreach (CellState adjacentCell in adjacentCells)
                    {
                        switch (adjacentCell.OccupationStatus)
                        {
                        case OccupationStatus.Opponent:
                            if (player == PlayerType.You)
                            {
                                gameState.OpponentIsInSameCompartment = true;
                            }
                            break;

                        case OccupationStatus.Clear:
                            adjacentCell.CompartmentStatus |= compartmentStatus;
                            int existingDistance = getDistance(adjacentCell);
                            if (nextDistance < existingDistance)
                            {
                                setDistance(adjacentCell, nextDistance);

                                // HashSets automatically filter out duplicates, so no need to check:
                                cellsToExpand.Enqueue(adjacentCell);
                                if (reachableCells != null)
                                {
                                    reachableCells.Add(adjacentCell);
                                }
                            }
                            break;
                        }
                    }
                    numberOfCellsReachable++;
                    totalDegreesOfCellsReachable += sourceCell.DegreeOfVertex;
                }

                switch (player)
                {
                case PlayerType.You:
                    gameState.NumberOfCellsReachableByYou       = numberOfCellsReachable;
                    gameState.TotalDegreesOfCellsReachableByYou = totalDegreesOfCellsReachable;
                    break;

                case PlayerType.Opponent:
                    gameState.NumberOfCellsReachableByOpponent       = numberOfCellsReachable;
                    gameState.TotalDegreesOfCellsReachableByOpponent = totalDegreesOfCellsReachable;
                    break;
                }

                switch (player)
                {
                case PlayerType.You:
                    gameState.YourDijkstraStatus           = DijkstraStatus.FullyCalculated;
                    gameState.YourUpToDateDijkstraDistance = int.MaxValue;
                    break;

                case PlayerType.Opponent:
                    gameState.OpponentsDijkstraStatus           = DijkstraStatus.FullyCalculated;
                    gameState.OpponentsUpToDateDijkstraDistance = int.MaxValue;
                    break;
                }
            }
            else
            {
                // Fix ClosestPlayer:
                foreach (CellState cellState in gameState.GetAllCellStates())
                {
                    if (cellState.ClosestPlayer == PlayerType.Unknown)
                    {
                        switch (cellState.CompartmentStatus)
                        {
                        case CompartmentStatus.InYourCompartment:
                            cellState.ClosestPlayer = PlayerType.You;
                            break;

                        case CompartmentStatus.InOpponentsCompartment:
                            cellState.ClosestPlayer = PlayerType.Opponent;
                            break;

                        case CompartmentStatus.InSharedCompartment:
                            if (cellState.DistanceFromYou > cellState.DistanceFromOpponent)
                            {
                                cellState.ClosestPlayer = PlayerType.You;
                            }
                            else
                            if (cellState.DistanceFromOpponent > cellState.DistanceFromYou)
                            {
                                cellState.ClosestPlayer = PlayerType.Opponent;
                            }
                            else
                            {
                                cellState.ClosestPlayer = gameState.PlayerToMoveNext;
                            }
                            break;
                        }
                    }
                }

                gameState.YourCell.ClosestPlayer      = PlayerType.You;
                gameState.OpponentsCell.ClosestPlayer = PlayerType.Opponent;
            }
        }