aiplayer.cpp
来自「Source code (C++) of the Amoebax game fo」· C++ 代码 · 共 689 行 · 第 1/2 页
CPP
689 行
//// Cross-platform free Puyo-Puyo clone.// Copyright (C) 2007 Emma's software//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//#if defined (HAVE_CONFIG_H)#include <config.h>#endif // !HAVE_CONFIG_H#include <cassert>#include <limits>#include "AIPlayer.h"#include "FrameManager.h"using namespace Amoebax;////// \brief Default constructor.////// \param side The player's grid side./// \param timeToWaitForNextMove The average time the player/// waits between moves, in ms./// \param timeDeviation The max. number of milliseconds to add or/// substracts to the average time to move/// (minimum is 1ms.)///AIPlayer::AIPlayer (IPlayer::PlayerSide side, uint32_t timeToWaitForNextMove, uint32_t timeDeviation): IPlayer (side), m_BestMove (), m_BestScore (std::numeric_limits<int32_t>::min ()), m_FallingPairAtPosition (false), m_HaveFinalMove (false), m_PairToCheck (CheckingCurrentFallingPair), m_TimeDeviation (timeDeviation), m_TimeOfNextMove (0), m_TimeToWaitForNextMove (timeToWaitForNextMove), m_WaitingNextPair (true){ assert ( 0 <= m_TimeDeviation && "The time deviation must be greater than 0!" );}////// \brief Tells if the AI player can move.////// Checks if the current time is past the time of the next move,/// letting the player move.////// \return \a true if the player can make the next move,/// \a false otherwise.///boolAIPlayer::canMove (void) const{ return FrameManager::getCurrentTime () > m_TimeOfNextMove;}////// \brief Checks all possible possitions of an state.////// \param state The state to check all its positions./// \param gridState The current grid state to make the check with./// \param parentScore The score of the parent's state.///voidAIPlayer::checkAllPositionsOf (State &state, const GridStatus &gridState, int32_t parentScore){ bool initialPosition = true; state.move.rotation = RotationLeft; do { if ( initialPosition ) { initialPosition = false; } else { // Next rotation. switch ( state.move.rotation ) { case RotationLeft: state.move.rotation = RotationTop; break; case RotationTop: state.move.rotation = RotationRight; break; case RotationRight: default: state.move.rotation = RotationBottom; break; } } switch ( state.move.rotation ) { case RotationBottom: state.move.main.x = 0; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth; // swap the satellite and main amoebas, so they will // be exactly the same case as RotationTop, but in reverse // order. std::swap (state.move.main, state.move.satellite); break; case RotationLeft: state.move.main.x = 1; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth - 1; break; case RotationRight: state.move.main.x = 0; state.move.satellite.x = 1; state.endX = Grid::k_GridWidth - 1; break; case RotationTop: state.move.main.x = 0; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth; break; default: state.move.rotation = RotationLeft; state.move.main.x = 1; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth - 1; break; } // Check all positions. for ( state.currentX = 0 ; state.currentX < state.endX ; ++state.currentX ) { state.gridState = gridState; GridStatus::PositionResult result; state.gridState.checkPositions (state.move.main, state.move.satellite, result); state.score = parentScore + computeScore (result); if ( state.score > getBestScore () ) { // Take into account that satellite and main are // reversed when the satellite is at bottom. if ( RotationBottom == m_BestMove.rotation ) { std::swap (m_PairState[0].move.main, m_PairState[0].move.satellite); } setBestMove (m_PairState[0].move, state.score); if ( RotationBottom == m_BestMove.rotation ) { std::swap (m_PairState[0].move.main, m_PairState[0].move.satellite); } } ++state.move.main.x; ++state.move.satellite.x; } } while ( RotationBottom != state.move.rotation );}////// \brief Checks the next position of the current falling pair.///voidAIPlayer::checkCurrentFallingPair (void){ if ( shouldCheckNextFallingPair () ) { if ( m_PairState[0].isAtLastPosition () ) { setHasFinalMove (); } else { checkNextPositionOf (m_PairState[0], getGrid ()->getState ()); initializeState (m_PairState[1], m_PairState[0].gridState, m_PairState[0].score); setPairToCheck (CheckingNextFallingPair); } } else { checkAllPositionsOf (m_PairState[0], getGrid ()->getState (), 0); setHasFinalMove (); }}////// \brief Checks all the position of the following (i.e., last) pair.///voidAIPlayer::checkFollowingFallingPair (void){ checkAllPositionsOf (m_PairState[2], m_PairState[1].gridState, m_PairState[1].score); setPairToCheck (CheckingNextFallingPair);}////// \brief Checks if a pair is starting to fall into the grid.////// If the pair has started to fall into the grid then initializes/// the first movement and computes its best score. Then sets the/// AI player in a non-waiting state.///voidAIPlayer::checkIfPairIsAvailable (void){ if ( getGrid ()->hasNewFallingPair () ) { // Get the current position of the falling pair, // which should be the center of the grid. This also gets m_PairState[0].move.main = getGrid ()->getFallingMainAmoeba (); m_PairState[0].move.satellite = getGrid ()->getFallingSatelliteAmoeba (); // Also get the next one or two pairs. if ( shouldCheckNextFallingPair () ) { m_PairState[1].move.main = getGrid ()->getNextFallingMainAmoeba (); m_PairState[1].move.satellite = getGrid ()->getNextFallingSatelliteAmoeba (); if ( shouldCheckFollowingFallingPair () ) { m_PairState[2].move.main = getGrid ()->getFollowingFallingMainAmoeba (); m_PairState[2].move.satellite = getGrid ()->getFollowingFallingSatelliteAmoeba (); } } // The best movement is also the initial position, as if we // don't have a better movement, why waste time moving the falling m_PairState[0].move.rotation = RotationTop; setBestMove (m_PairState[0].move, std::numeric_limits<int32_t>::min ()); initializeState (m_PairState[0], getGrid ()->getState ()); setPairToCheck (CheckingCurrentFallingPair); m_FallingPairAtPosition = false; m_HaveFinalMove = false; m_WaitingNextPair = false; }}////// \brief Checks the next position or all position of the next pair.///voidAIPlayer::checkNextFallingPair (void){ if ( shouldCheckFollowingFallingPair () ) { if ( m_PairState[1].isAtLastPosition () ) { setPairToCheck (CheckingCurrentFallingPair); } else { checkNextPositionOf (m_PairState[1], m_PairState[0].gridState, m_PairState[0].score); setPairToCheck (CheckingFollowingFallingPair); checkFollowingFallingPair (); checkNextFallingPair (); } } else { checkAllPositionsOf (m_PairState[1], m_PairState[0].gridState, m_PairState[0].score); setPairToCheck (CheckingCurrentFallingPair); }}////// \brief Changes the position of the state and computes its score.////// \param state The state to change and to check its score./// \param gridState The current state of the grid to check the/// position to./// \param parentScore The score of the parent state.///voidAIPlayer::checkNextPositionOf (State &state, const GridStatus &gridState, int32_t parentScore){ // If we are not at the end of the current rotation. if ( state.currentX < state.endX ) { ++state.currentX; ++state.move.main.x; ++state.move.satellite.x; } // Otherwise go to the next rotation and start again. else { state.currentX = 1; switch ( state.move.rotation ) { case RotationLeft: state.move.rotation = RotationTop; state.move.main.x = 0; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth; break; case RotationTop: state.move.rotation = RotationRight; state.move.main.x = 0; state.move.satellite.x = 1; state.endX = Grid::k_GridWidth - 1; break; case RotationRight: default: state.move.rotation = RotationBottom; state.move.main.x = 0; state.move.satellite.x = 0; state.endX = Grid::k_GridWidth; // swap the satellite and main amoebas, so they will // be exactly the same case as RotationTop, but in reverse // order. std::swap (state.move.main, state.move.satellite); break; } } state.gridState = gridState; GridStatus::PositionResult result; state.gridState.checkPositions (state.move.main, state.move.satellite, result); state.score = parentScore + computeScore (result);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?