protected override void DoSolve() { RuleOutcome outcome; GameState actualGameState = Coordinator.CurrentGameState.Clone(); Position initialPosition = actualGameState.YourOriginalCell.Position; int initialY = initialPosition.Y; GameState mutableGameState = RulesEngineHelper.GetInitialGameState(actualGameState); try { if (initialY <= 14) // TODO: Remove hard-coding! { outcome = SolveWhenStartingInNorthernHemisphere(mutableGameState, actualGameState); } else { // TODO: outcome = SolveWhenStartingInSouthernHemisphere(mutableGameState, newGameState); outcome = new RuleOutcome { Status = RuleStatus.NoFurtherSuggestions }; } } catch (Exception exc) { outcome = new RuleOutcome { Status = RuleStatus.ExceptionThrown, ExceptionThrown = exc }; } if (outcome.Status == RuleStatus.NextMoveSuggested) { actualGameState.MakeMove(outcome.SuggestedMove); Coordinator.SetBestMoveSoFar(actualGameState); } else { NegaMaxSolver solver = new NegaMaxSolver(); DelegateSolvingToAnotherSolver(solver); } return; }
private RuleOutcome SolveWhenStartingInNorthernHemisphere(GameState mutableGameState, GameState actualGameState) { RuleOutcome outcome; Position nextPosition = mutableGameState.YourOriginalCell.Position; int nextMoveNumber = 0; Block leftBlock = GetInitialLeftBlock(mutableGameState); Block rightBlock = GetInitialRightBlock(mutableGameState); /* Move to the equator: */ int distance = 14 - nextPosition.Y; // Remove hard-coding for (int i = 0; i < distance; i++) { nextMoveNumber++; nextPosition = new Position(nextPosition.X, nextPosition.Y + 1); outcome = RulesEngineHelper.MoveToNextPosition(mutableGameState, actualGameState, nextPosition, nextMoveNumber); if (outcome.Status != RuleStatus.NoFurtherSuggestions) { return(outcome); } // TODO: Update leftBlock and rightBlock } // Set up a state object to track various information: Position position = mutableGameState.YourCell.Position; NorthernPendulumBlock filledBlock = new NorthernPendulumBlock { LeftX = position.X, RightX = position.X, TopLeftY = position.Y, TopRightY = position.Y, BottomY = position.Y }; // Swing the pendulum back and forth, increasing its length with each iteration: for (int pendulumLevel = 0; pendulumLevel < 13; pendulumLevel++) { Position targetPosition; int targetX, targetY; // *** Move to first position: Dijkstra.Perform(mutableGameState); // Only move to first and second position if this reduces the opponent's gap: // ... bool isOpponentCloserToGapOnLeft = if (pendulumLevel % 2 == 0) { // Going left: targetX = Helper.NormalizedX(filledBlock.LeftX - 1); targetY = filledBlock.TopLeftY - 1; } else { // Going right: targetX = Helper.NormalizedX(filledBlock.RightX + 1); targetY = filledBlock.TopRightY - 1; } targetPosition = new Position(targetX, targetY); outcome = RulesEngineHelper.MoveToPositionAlongAnyRoute(mutableGameState, actualGameState, ref nextMoveNumber, targetPosition); if (outcome.Status != RuleStatus.NoFurtherSuggestions) { return(outcome); } // Update filled block: if (pendulumLevel % 2 == 0) { // Going left: filledBlock.LeftX = targetX; filledBlock.TopLeftY = targetY; } else { // Going right: filledBlock.RightX = targetX; filledBlock.TopRightY = targetY; } // *** Move to second position: Dijkstra.Perform(mutableGameState); if (pendulumLevel % 2 == 0) { // Going left: targetX = Helper.NormalizedX(filledBlock.LeftX - 1); } else { // Going right: targetX = Helper.NormalizedX(filledBlock.RightX + 1); } targetY = filledBlock.BottomY + 1; targetPosition = new Position(targetX, targetY); outcome = RulesEngineHelper.MoveToPositionAlongAnyRoute(mutableGameState, actualGameState, ref nextMoveNumber, targetPosition); if (outcome.Status != RuleStatus.NoFurtherSuggestions) { return(outcome); } // Update filled block: if (pendulumLevel % 2 == 0) { // Going left: filledBlock.LeftX = targetX; } else { // Going right: filledBlock.RightX = targetX; } filledBlock.BottomY = targetY; // *** Move to third position: Dijkstra.Perform(mutableGameState); if (pendulumLevel % 2 == 0) { // Going right: targetX = filledBlock.RightX; } else { // Going left: targetX = filledBlock.LeftX; } targetY = filledBlock.BottomY; targetPosition = new Position(targetX, targetY); outcome = RulesEngineHelper.MoveToPositionAlongAnyRoute(mutableGameState, actualGameState, ref nextMoveNumber, targetPosition); if (outcome.Status != RuleStatus.NoFurtherSuggestions) { return(outcome); } } // No more pre-programmed moves to make... hand over to normal solver now: outcome = new RuleOutcome { Status = RuleStatus.NoFurtherSuggestions }; return(outcome); }