|
@@ -63,31 +63,39 @@ size_t chessy::perft(std::ostream& out, ChessGame& chessGame, int depth)
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#include <iostream>
|
|
|
|
+using namespace std;
|
|
|
|
|
|
-Move chessy::miniMax(ChessGame& cg, int depth)
|
|
|
|
|
|
+std::pair<Move, MoveValue> chessy::miniMax(ChessGame& cg, int depth)
|
|
{
|
|
{
|
|
std::vector<Move> moves;
|
|
std::vector<Move> moves;
|
|
|
|
+ moves.reserve(200);
|
|
if (cg.getTurn() == WHITE_SIDE)
|
|
if (cg.getTurn() == WHITE_SIDE)
|
|
generateAllMoves<WHITE_SIDE>(cg, moves);
|
|
generateAllMoves<WHITE_SIDE>(cg, moves);
|
|
else
|
|
else
|
|
generateAllMoves<BLACK_SIDE>(cg, moves);
|
|
generateAllMoves<BLACK_SIDE>(cg, moves);
|
|
- Move bestMove;
|
|
|
|
- MoveValue best = std::numeric_limits<MoveValue>::min();
|
|
|
|
|
|
+ Move bestMove{ 0, 0 };
|
|
|
|
+ //MoveValue best = -1e+30;
|
|
|
|
+ MoveValue alpha = -1e+30;
|
|
|
|
+ MoveValue beta = 1e+30;
|
|
for (Move move : moves) {
|
|
for (Move move : moves) {
|
|
MoveInfo mi{ move, cg };
|
|
MoveInfo mi{ move, cg };
|
|
UndoInfo ui = cg.doMove(mi);
|
|
UndoInfo ui = cg.doMove(mi);
|
|
- MoveValue val = negamaxImplementation(cg, depth - 1);
|
|
|
|
|
|
+ MoveValue val = -negamaxImplementation(cg, depth - 1, -beta, -alpha);
|
|
|
|
+ //cout << move.asString() << ": " << val << ", " << best << ((val > best) ? " good" : " bad") << endl;
|
|
|
|
+ //MoveValue val = 0.0;
|
|
cg.undoMove(ui);
|
|
cg.undoMove(ui);
|
|
- if(val < best) {
|
|
|
|
- best = val;
|
|
|
|
|
|
+ if(val > alpha) {
|
|
|
|
+ alpha = val;
|
|
bestMove = move;
|
|
bestMove = move;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return bestMove; //negamaxImplementation(chessGame, 5);
|
|
|
|
|
|
+ return { bestMove, alpha }; //negamaxImplementation(chessGame, 5);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth)
|
|
|
|
|
|
+MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth,
|
|
|
|
+ chessy::MoveValue alpha, chessy::MoveValue beta)
|
|
{
|
|
{
|
|
if (depth <= 0) {
|
|
if (depth <= 0) {
|
|
if (cg.getTurn() == WHITE_SIDE)
|
|
if (cg.getTurn() == WHITE_SIDE)
|
|
@@ -102,21 +110,35 @@ MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth)
|
|
else
|
|
else
|
|
generateAllMoves<BLACK_SIDE>(cg, moves);
|
|
generateAllMoves<BLACK_SIDE>(cg, moves);
|
|
|
|
|
|
|
|
+ const Board& b = cg.getBoard();
|
|
for (Move move : moves) {
|
|
for (Move move : moves) {
|
|
MoveInfo mi{ move, cg };
|
|
MoveInfo mi{ move, cg };
|
|
- negamaxImplementation(cg, depth - 1);
|
|
|
|
UndoInfo ui = cg.doMove(mi);
|
|
UndoInfo ui = cg.doMove(mi);
|
|
|
|
+ /*Index king = b.getKing<side>().getLeastSignificantBit();
|
|
|
|
+ if((KnightMoveGenerator{ king }.getBitboard() &
|
|
|
|
+ b.getKnights<otherSide(side)>()) ||
|
|
|
|
+ (PrimitiveBishopMoveGenerator{ king, b.get<otherSide(side)>(),
|
|
|
|
+ b.get<side>() }.getBitboard() & (b.getBishops<otherSide(side)>() |
|
|
|
|
+ b.getQueens<otherSide(side)>())) ||
|
|
|
|
+ PrimitiveRookMoveGenerator{ king, b.get<otherSide(side)>(),
|
|
|
|
+ b.get<side>() }.getBitboard() & (b.getRooks<otherSide(side)>() |
|
|
|
|
+ b.getQueens<otherSide(side)>()))*/
|
|
|
|
+ MoveValue val = -negamaxImplementation(cg, depth - 1, -beta, -alpha);
|
|
cg.undoMove(ui);
|
|
cg.undoMove(ui);
|
|
|
|
+ if(val >= beta)
|
|
|
|
+ return beta;
|
|
|
|
+ if(val > alpha)
|
|
|
|
+ alpha = val;
|
|
}
|
|
}
|
|
|
|
|
|
- return 0.0;
|
|
|
|
|
|
+ return alpha;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
template<Side side>
|
|
template<Side side>
|
|
MoveValue chessy::evaluate(const ChessGame& game)
|
|
MoveValue chessy::evaluate(const ChessGame& game)
|
|
{
|
|
{
|
|
- int piecePoints = 0;
|
|
|
|
|
|
+ MoveValue piecePoints = 0;
|
|
const Board& bd = game.getBoard();
|
|
const Board& bd = game.getBoard();
|
|
Bitboard p = bd.getPawns<side>();
|
|
Bitboard p = bd.getPawns<side>();
|
|
Bitboard n = bd.getKnights<side>();
|
|
Bitboard n = bd.getKnights<side>();
|
|
@@ -124,6 +146,8 @@ MoveValue chessy::evaluate(const ChessGame& game)
|
|
Bitboard r = bd.getRooks<side>();
|
|
Bitboard r = bd.getRooks<side>();
|
|
Bitboard q = bd.getQueens<side>();
|
|
Bitboard q = bd.getQueens<side>();
|
|
Bitboard k = bd.getKing<side>();
|
|
Bitboard k = bd.getKing<side>();
|
|
|
|
+ for (auto pawn : PositionSet{ p })
|
|
|
|
+ piecePoints += 0.5 / 8.0 * pawn.getRow() + 1.0;
|
|
piecePoints += 1 * p.popcount();
|
|
piecePoints += 1 * p.popcount();
|
|
piecePoints += 3 * n.popcount();
|
|
piecePoints += 3 * n.popcount();
|
|
piecePoints += 3 * b.popcount();
|
|
piecePoints += 3 * b.popcount();
|
|
@@ -132,13 +156,15 @@ MoveValue chessy::evaluate(const ChessGame& game)
|
|
if (k == Bitboard(0ULL))
|
|
if (k == Bitboard(0ULL))
|
|
piecePoints -= 100000;
|
|
piecePoints -= 100000;
|
|
|
|
|
|
- const Side other = otherSide(side);
|
|
|
|
|
|
+ constexpr Side other = otherSide(side);
|
|
p = bd.getPawns<other>();
|
|
p = bd.getPawns<other>();
|
|
n = bd.getKnights<other>();
|
|
n = bd.getKnights<other>();
|
|
b = bd.getBishops<other>();
|
|
b = bd.getBishops<other>();
|
|
r = bd.getRooks<other>();
|
|
r = bd.getRooks<other>();
|
|
q = bd.getQueens<other>();
|
|
q = bd.getQueens<other>();
|
|
k = bd.getKing<other>();
|
|
k = bd.getKing<other>();
|
|
|
|
+ for (auto pawn : PositionSet{ p })
|
|
|
|
+ piecePoints += 0.5 / 8.0 * (7 - pawn.getRow()) + 1.0;
|
|
piecePoints -= 1 * p.popcount();
|
|
piecePoints -= 1 * p.popcount();
|
|
piecePoints -= 3 * n.popcount();
|
|
piecePoints -= 3 * n.popcount();
|
|
piecePoints -= 3 * b.popcount();
|
|
piecePoints -= 3 * b.popcount();
|
|
@@ -149,6 +175,7 @@ MoveValue chessy::evaluate(const ChessGame& game)
|
|
|
|
|
|
return piecePoints;
|
|
return piecePoints;
|
|
}
|
|
}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
template MiniMax::BestMove MiniMax::minimax<WHITE_SIDE>(int);
|
|
template MiniMax::BestMove MiniMax::minimax<WHITE_SIDE>(int);
|
|
template MiniMax::BestMove MiniMax::minimax<BLACK_SIDE>(int);
|
|
template MiniMax::BestMove MiniMax::minimax<BLACK_SIDE>(int);
|