I have a chess game made and I’m trying to minimax it. For example, I have a mini version of 4×4 chess, but I can’t help minimax to find the optimal solution.
You will notice that the evaluate function returns +1000 if I checked checkmate, but I never get this result in the process of writing out the rooks, even for great depth, on the contrary, I am able to detect the opponent’s checkmate while diving.
I must have some error somewhere, but we are unable to detect it.
int CGame::isFinished()
{
if(m_Board.isPieceUnderAttack(m_WhiteKing, Color::WHITE, m_WhitePlayable, m_BlackPlayable) && m_WhitePlayable.empty())
return 1;
if(m_Board.isPieceUnderAttack(m_BlackKing, Color::BLACK, m_WhitePlayable, m_BlackPlayable) && m_BlackPlayable.empty())
return 2;
if(m_BlackPlayable.empty() || m_WhitePlayable.empty())
return 3;
return 0;
}
void CGame::makeRandomMove(Color color)
{
srand(time(nullptr));
if(color == Color::WHITE)
{
int random = rand() % m_WhitePlayable.size();
makeMove(m_WhitePlayable[random].first, m_WhitePlayable[random].second, Color::WHITE, true);
}
else
{
int random = rand() % m_BlackPlayable.size();
makeMove(m_BlackPlayable[random].first, m_BlackPlayable[random].second, Color::BLACK, true);
}
}
void CGame::minimaxAlphaBeta(int depth, Color color, bool random)
{
cout << *this << endl;
while(!isFinished())
{
if(color == m_Player)
{
if(random)
makeRandomMove(m_Player);
else
loadMove(m_Player);
}
else
{
int bestVal = INT_MIN;
CPosition bestFromPosition;
CPosition bestToPosition;
auto& playableMoves = (m_Computer == Color::WHITE) ? m_WhitePlayable : m_BlackPlayable;
for(auto &[from, to] : playableMoves)
{
CGame gameCopy = *this;
gameCopy.makeMove(from, to, m_Computer, true);
int val = gameCopy.minimaxAlphaBetaAlg(gameCopy, depth, INT_MIN, INT_MAX, false, gameCopy.m_Player);
cout << "val: " << val << endl; // never + 1000
if(val > bestVal)
{
bestVal = val;
bestFromPosition = from;
bestToPosition = to;
}
}
makeMove(bestFromPosition, bestToPosition, m_Computer, true);
}
color = (color == Color::WHITE) ? Color::BLACK : Color::WHITE;
}
}
int CGame::minimaxAlphaBetaAlg(CGame& game, int depth, int alpha, int beta, bool isMaximizingPlayer, Color playerColor)
{
if(game.isFinished() || depth == 0)
return game.evaluateBoard(playerColor);
if(isMaximizingPlayer)
{
int maxEval = INT_MIN;
auto& playableMoves = (m_Computer == Color::WHITE) ? game.m_WhitePlayable : game.m_BlackPlayable;
for (auto& [from, to] : playableMoves)
{
CGame gameCopy = game;
gameCopy.makeMove(from, to, playerColor, true);
int eval = gameCopy.minimaxAlphaBetaAlg(gameCopy, depth - 1, alpha, beta, false, m_Player);
maxEval = max(maxEval, eval);
alpha = max(alpha, maxEval);
if(beta <= alpha)
break;
}
return maxEval;
}
else
{
int minEval = INT_MAX;
auto& playableMoves = (m_Player == Color::WHITE) ? game.m_WhitePlayable : game.m_BlackPlayable;
for (auto &[from, to] : playableMoves)
{
CGame gameCopy = game;
gameCopy.makeMove(from, to, m_Computer, true);
int eval = gameCopy.minimaxAlphaBetaAlg(gameCopy, depth - 1, alpha, beta, true, m_Computer);
minEval = min(minEval, eval);
beta = min(beta, minEval);
if(beta <= alpha)
break;
}
return minEval;
}
}
int CGame::evaluateBoard(Color color)
{
int eval = 0;
for(long int i = 0; i < m_Board.getSize(); i++)
{
for (long int j = 0; j < m_Board.getSize(); j++)
{
if(m_Board[i][j].getType() == Type::QUEEN)
{
if(m_Board[i][j].getColor() == color)
eval += 50;
else
eval -= 50;
}
else if(m_Board[i][j].getType() == Type::ROOK)
{
if(m_Board[i][j].getColor() == color)
eval += 20;
else
eval -= 20;
}
else if(m_Board[i][j].getType() == Type::KNIGHT)
{
if(m_Board[i][j].getColor() == color)
eval += 10;
else
eval -= 10;
}
else if(m_Board[i][j].getType() == Type::BISHOP)
{
if(m_Board[i][j].getColor() == color)
eval += 10;
else
eval -= 10;
}
else if(m_Board[i][j].getType() == Type::PAWN)
{
if(m_Board[i][j].getColor() == color)
eval += 2;
else
eval -= 2;
}
}
}
if(m_Board.isPieceUnderAttack(m_WhiteKing, Color::WHITE, m_WhitePlayable, m_BlackPlayable) && m_WhitePlayable.empty())
return (color == Color::BLACK) ? eval += 1000 : eval -= 1000;
if(m_Board.isPieceUnderAttack(m_BlackKing, Color::BLACK, m_WhitePlayable, m_BlackPlayable) && m_BlackPlayable.empty())
return (color == Color::WHITE) ? eval += 1000 : eval -= 1000;
return eval;
}`
main
int main()
{
CGame game(4, Color::BLACK, Color::WHITE);
game.minimaxAlphaBeta(5, Color::WHITE, false);
}
Complet program:
https://onecompiler.com/cpp/42e7874fq
C++ mini Chess game minimax alg
user24995323 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.