/// <summary> /// When a penguin has no legal moves (i.e. is blocked by other penguins, or is alone on a single isloated tile), /// clicking on it triggers removal of it and the single tile it's standing on from the board. /// </summary> /// <param name="penguin">Selected penguin to remove</param> /// <remarks> /// CALLED BY: SubStateMach_MainGame->State_Move_xxx::OnPenguinClicked() /// </remarks> /// public void RemoveUnmovablePenguin(GamePenguin penguin) { CurrentPlayer.AddFish(penguin.CurrentTile.FishScoreValue); // Player wins fish on this tile penguin.CurrentTile.Sink(); // Animate sinking tile, and then remove it ExpungePenguin(penguin, penguinDepartPrefab); // Remove Penguin // Update the internal board the AI uses // if (IsUsingAI) { Command.GameMove move = PortmanteauRemovePenguin(penguin.CurrentTile); ExecuteMove_Internal(move); } // TODO: Delete? -- StateParam_MovePending = true; // Go to animation state while sinking tile anim plays // No point in waiting for the tile to vanish, so go directly to "NextPlayer" state // StateParam_PenguinRemoved = true; // StateTrigger_NextPlayer(); }
/// <summary> /// Apply a move made by the human user to the AI's internal board /// </summary> /// <param name="move">"Command.Move" object instantiated from GamePenguin that just moved</param> /// <remarks> /// CALLED BY: ExecuteHumanMove(), ExecuteAIMove() /// </remarks> /// void ExecuteMove_Internal(Command.GameMove move) { // If a human just moved, update the internal board the AI uses // (If the AI moved, the board is updated by the AI algorithms, so we need not do it here.) // m_refAIBoard.UpdateAIBoard(CurrentPlayer.Color, move); }
/// <summary> /// Remove one of al players' penguins when it can claim a /// whole "island" of tiles /// </summary> /// <returns> /// The total number of fish of the tiles to be added to the player's score /// </returns> /// public int RemovePenguin(Player player, GamePenguin penguin) { m_refTileMgr.workTiles.Clear(); // Clear "workspace" int islandFishTally = TileManager.CheckForIsland(m_refTileMgr, penguin.CurrentTile, m_refTileMgr.workTiles, true); if (islandFishTally >= 0) // -1 = Penguin not alone on contiguous tiles { player.AddFish(islandFishTally); // Add all fish on local tiles to score ExpungePenguin(penguin, penguinDepartPrefab); // Destroy penguin game object with particle effects m_refTileMgr.ExpungeTiles(m_refTileMgr.workTiles); // Sink/Destroy all tiles on penguin's "island" // Update the internal board the AI uses -- First apply penguin removal, then turn off the virtual tiles // if (IsUsingAI) { Command.GameMove move = PortmanteauRemovePenguin(penguin.CurrentTile); // ExecuteMove_Internal(move); ExpungeTiles_Internal(m_refTileMgr.workTiles); } // No point in waiting for all tiles to vanish, so go directly to "NextPlayer" state // StateParam_PenguinRemoved = true; // StateTrigger_NextPlayer(); } return(islandFishTally); }
void MiniMaxDebugInfo(Command.GameMove move, float score) { if (_debugMode) { Debug.Log("Checking move: " + move.ToString() + "; HScore = " + score); } }
/*** Operations on move stack ***/ public void PushMove(Command.GameMove testMove) { testMove.PlayMove(this); // Apply move to internal board testMoveStack.Push(testMove); // Save move to the stack NextEvalPlayer(); // Advance to next player / ply }
/// <summary> /// Clear move list and store chosen move to return to GameManager /// </summary> /// void StoreMove(Command.GameMove foundMove, List <Command.GameMove> refMoveList) { Debug.Assert(foundMove != null); refMoveList.Clear(); refMoveList.Add(foundMove); IsThinking = false; }
public Command.GameMove PopMove() { Command.GameMove lastMove = testMoveStack.Pop(); // Retrieve last move lastMove.HeuristicScore = GetHeuristicScore(); lastMove.RollBack(this); // Undo move on internal board PrevEvalPlayer(); // Backup one ply return(lastMove); }
/// <summary> /// AI Method 2 -- Give a heuristc "weight" to every tile that can reached next /// move and go there. /// </summary> /// <remarks> /// "Weight" of tile = Fish on tile + Sum of fish on all tiles accessible on next move /// (Because we care about the penguins' mobility, a "sunk" tile = -1, so if a three-fish tile /// is linked to only one other tile, the score with come out negative, and the tile will be avoided) /// </remarks> /// public void OnAI_HeuristicNextMove(List <Command.GameMove> allPossibleMoves) { // Get a list of all the candidate moves sorted by heuristic "weight" // m_refBoard.SortMovesHeuristic(allPossibleMoves); // Make highest scored move the pending move // Command.GameMove move = allPossibleMoves[0]; // StoreMove(move, allPossibleMoves); }
/// <summary> /// After AI selects move and updates the internal board, then animate the move on the Game Board /// </summary> /// <param name="tile">Destination tile</param> /// <remarks>FLOW: AIBrain::MakeMove_***() -> OnExeAIMove() -> ExecuteAIMove() /// </remarks> /// public void ExecuteAIMove(Command.GameMove move) { ExecuteMove_Internal(move); // Simulate a penguin click from AI move // GamePenguin penguin = m_refTileMgr.tileTable[move.fromTile].CurrentPenguin; // Simulate a destination tile click from AI move // GameTile tile = m_refTileMgr.tileTable[move.toTile]; // Execute move onscreen // ExecuteMove_GameWorld(penguin, tile); }
/* * /// <summary> * /// Internal move execution routine * /// </summary> * /// <param name="tile">Destination tile</param> * /// <param name="bHumanMove">Did a human (rather than the AI make this move?)</param> * /// * void ExecuteMove(GameTile tile, bool bHumanMove) * { * if (CurrentPenguin.MoveTo(tile)) // If a legal move was selected, start animating the penguin's move * { * // Player acquires this tile's fish * // * CurrentPlayer.AddFish(CurrentTile.FishScoreValue); * * // Start tile sinking animation for the tile just departed * // TODO: *** This may be a bug -- Shouldn't CurrentTile be the *selected* (destination) tile?? * // * CurrentTile.Sink(); * * // If a human just moved, update the internal board the AI uses * // (If the AI moved, the board is updated by the AI algorithms, so we need not do it here.) * // * if (IsUsingAI && bHumanMove) * { * m_refAIBoard.UpdateAIBoard(CurrentPlayer.Color, PortmanteauMovePenguin(CurrentTile, tile)); * } * * // Go to "MovePending" state until all animations complete * // * StateParam_AIMove = false; * StateParam_MovePending = true; * * // Clear selections * // * CurrentPenguin = null; * CurrentTile = null; * } * // Else continue to wait for a valid tile to be clicked * } */ /// <summary> /// If user selected a valid normal penguin move, execute that move, both onscreen and internally /// </summary> /// <param name="tile">Destination tile</param> /// <remarks> /// CALLED BY: SubStateMach_MainGame->State_Move_Human::OnTileClicked() /// </remarks> /// public void ExecuteHumanMove(GameTile tile) { if (CurrentPenguin.ValidateDestination(tile)) // First check that selected tile is a legal move { ExecuteMove_GameWorld(CurrentPenguin, tile); if (IsUsingAI) // Only need to do this bit if AI is in this Game { // Instantiate a command to send to the internal board // Command.GameMove move = PortmanteauMovePenguin(CurrentPenguin.CurrentTile, tile); // Tell the internal board to update to reflect the new move // ExecuteMove_Internal(move); } } }
// After a move the user has just made // public void ApplyMove(Command.GameMove move) { move.PlayMove(this); // Apply move to internal board (Already done in Game World) }
/// <summary> /// Accept move just made by human player and apply it to AI board /// </summary> /// <param name=""></param> /// <param name=""></param> /// public void UpdateAIBoard(GamePenguin.PenguinColor playerColor, Command.GameMove move) { Debug.Assert(playerColor == colorCurrentPlayer); // Board should be on current player ApplyMove(move); // Apply move to AI board ("move" object is polymorphic) }
/// <summary> /// Apply AI's move to the Game Board /// </summary> /// <param name="move">AI move just applied to internal board</param> /// public void OnAIMove_Apply(Command.GameMove move) { }