public override GameMoveType GetNextMove(GameState gameState, IGameInteractionService interactionService) { var move = base.GetNextMove (gameState, interactionService); // Sleep to allow better visualization. // TODO: Sleep? Or make async? Thread.Sleep (1000); return move; }
public GameMoveType GetNextMove(GameState gameState, IGameInteractionService interactionService) { while(true) { var move = GameMoveType.None; var key = Console.ReadKey ().Key; switch(key) { // Quit the program if ESC is pressed. case ConsoleKey.Escape: if(this.GameQuitRequested != null) { this.GameQuitRequested (); } return GameMoveType.None; case ConsoleKey.UpArrow: // Arrow up = move the item below the empty space UP. move = GameMoveType.MoveItemBelow; break; case ConsoleKey.DownArrow: // Arrow down = move the item above the empty space DOWN. move = GameMoveType.MoveItemAbove; break; case ConsoleKey.LeftArrow: // Arrow left = move the item right of the empty space LEFT. move = GameMoveType.MoveItemRight; break; case ConsoleKey.RightArrow: // Arrow right = move the item left of the empty space RIGHT. move = GameMoveType.MoveItemLeft; break; default: Console.Beep (); break; } if(interactionService.CanMove(gameState.GameField, move)) { return move; } } }
public GameMoveType GetNextMove(GameState gameState, IGameInteractionService interactionService) { return GameMoveType.None; }
public virtual GameMoveType GetNextMove(GameState gameState, IGameInteractionService interactionService) { var loggingService = ServiceContainer.Resolve<ILoggingService> (); var emptyLocation = gameState.GameField.GetUnusedItemLocation (); // Prepare a path to the target treasure if it hasn't happened yet. The AI decides first what path it will take, then it will follow it until // it fails or until it reaches the treasure. The current path is reset in UpdatePlayer() because this means that it's the other player's turn. if (this.currentPath == null || this.currentPath.Count <= 0) { #if EXTENSIVE_LOGGING loggingService.Log ("AI calculates a new path."); #endif // Populate the path finding algorithm and start at the unused item location. var populatedGrid = AIHelpers.PreparePathGrid (gameState.GameField, emptyLocation, gameState.GetActiveCard()); // Get the location of the current active card. This may return NULL if the AI cannot remember the location. GridLocation currentTreasureLocation = this.GetPresumedLocationOfTreasure(gameState.GetActiveCard()); // The AI has no clue where the active treasure is. It will pick a random location to move to. if (currentTreasureLocation == null) { currentTreasureLocation = this.GetRandomLocationAvoidingTreasures (gameState); #if EXTENSIVE_LOGGING loggingService.Log ("AI has no clue where '{0}' is located. Will move to random location {1}.", gameState.GetActiveCard(), currentTreasureLocation); #endif } // Log how AI calculates the distances. #if EXTENSIVE_LOGGING loggingService.Log ("AI sees the grid with these distances, starting at {0} to reach (presumed!) {1} at {2}:", emptyLocation, gameState.GetActiveCard(), currentTreasureLocation); for (int row = 0; row < populatedGrid.Rows; row++) { string s = string.Empty; for (int col = 0; col < populatedGrid.Columns; col++) { s += populatedGrid.GetItem (row, col).ToString ("000") + " |"; } loggingService.Log (s); } #endif // Find the path from the current unused location to the treasure, avoiding all other treasures if possible. var pathList = AIHelpers.GetPathToLocation (gameState.GameField, populatedGrid, emptyLocation, currentTreasureLocation, gameState.GetActiveCard()); // We need to reverse it to get the corret order when copying onto a stack. pathList.Reverse (); // Copy the path onto a stack for better processing. this.currentPath = new Stack<GridLocation>(pathList); pathList = null; // Log the path the AI will go. #if EXTENSIVE_LOGGING loggingService.Log ("AI's path to (presumed!) {0}:", gameState.GetActiveCard()); for (int row = 0; row < populatedGrid.Rows; row++) { string s = string.Empty; for (int col = 0; col < populatedGrid.Columns; col++) { var isPath = (from pathItem in this.currentPath where pathItem.Row == row && pathItem.Column == col select pathItem).Any (); if (isPath) { s += populatedGrid.GetItem (row, col).ToString ("000") + "X|"; } else { s += populatedGrid.GetItem (row, col).ToString ("000") + " |"; } } loggingService.Log (s); } #endif // A correct path has to contain at least two locations: the start and the target. if (this.currentPath.Count < 2) { // The AI failed and could not find a path from the unused location to the active treasure. Stupid AI. Should not happen and means there is a problem in the algorithm. loggingService.Log ("AI path is invalid. Path length: [{0}]. Next move will be random.", this.currentPath.Count.ToString ()); // Return a random move. var randomMove = AIHelpers.GetRandomMove (gameState.GameField, emptyLocation, gameState.GetActiveCard()); loggingService.Log ("AI moves randomly: {0}", randomMove); // Bail out. return randomMove; } else { // The found path is valid. Remove the first entry because this is the start location. No need to move, we're already there. // TODO: Verify that if the next treaure is the one that is currently active, the AI will spot that it is already uncovered. this.currentPath.Pop (); } } // Here the current path has either just been populated or we're following a previously populated path. // Get next location to move to. var moveLocation = this.currentPath.Pop (); // Remember that we visited that location. We want to avoid it for the next couple of moves. this.lastVisitedLocations.Enqueue (moveLocation); // Remember the treasure that has just been discoverd fully. this.LearnAboutTreasure (gameState.GameField.GetItem(moveLocation).Treasure, moveLocation); // Convert location to a move. var move = AIHelpers.GetMoveToAdjacentLocation (emptyLocation, moveLocation); loggingService.Log ("AI will move from [{0}] to [{1}], this is a move of type [{2}].", emptyLocation, moveLocation, move); // The AI forgets a bit after each move. this.ForgetTreasures (); return move; }
public override GameMoveType GetNextMove(GameState gameState, IGameInteractionService interactionService) { var move = base.GetNextMove (gameState, interactionService); return move; }