21#include "MoveSorter.hpp"
23using namespace GameSolver::Connect4;
39int Solver::negamax(
const Position &P,
int alpha,
int beta) {
47 return -(Position::WIDTH * Position::HEIGHT - P.
nbMoves()) / 2;
49 if(P.
nbMoves() >= Position::WIDTH * Position::HEIGHT - 2)
52 int min = -(Position::WIDTH * Position::HEIGHT - 2 - P.
nbMoves()) / 2;
55 if(alpha >= beta)
return alpha;
58 int max = (Position::WIDTH * Position::HEIGHT - 1 - P.
nbMoves()) / 2;
61 if(alpha >= beta)
return beta;
64 const Position::position_t key = P.
key();
65 if(
int val = transTable.get(key)) {
66 if(val > Position::MAX_SCORE - Position::MIN_SCORE + 1) {
67 min = val + 2 * Position::MIN_SCORE - Position::MAX_SCORE - 2;
70 if(alpha >= beta)
return alpha;
73 max = val + Position::MIN_SCORE - 1;
76 if(alpha >= beta)
return beta;
81 if(
int val = book.get(P))
return val + Position::MIN_SCORE - 1;
84 for(
int i = Position::WIDTH; i--;)
85 if(Position::position_t move = possible & Position::column_mask(columnOrder[i]))
88 while(Position::position_t next = moves.
getNext()) {
91 int score = -negamax(P2, -beta, -alpha);
96 transTable.put(key, score + Position::MAX_SCORE - 2 * Position::MIN_SCORE + 2);
99 if(score > alpha) alpha = score;
103 transTable.put(key, alpha - Position::MIN_SCORE + 1);
107int Solver::solve(
const Position &P,
bool weak) {
109 return (Position::WIDTH * Position::HEIGHT + 1 - P.
nbMoves()) / 2;
110 int min = -(Position::WIDTH * Position::HEIGHT - P.
nbMoves()) / 2;
111 int max = (Position::WIDTH * Position::HEIGHT + 1 - P.
nbMoves()) / 2;
118 int med = min + (max - min) / 2;
119 if(med <= 0 && min / 2 < med) med = min / 2;
120 else if(med >= 0 && max / 2 > med) med = max / 2;
121 int r = negamax(P, med, med + 1);
122 if(r <= med) max = r;
128std::vector<int> Solver::analyze(
const Position &P,
bool weak) {
129 std::vector<int> scores(Position::WIDTH, Solver::INVALID_MOVE);
130 for (
int col = 0; col < Position::WIDTH; col++)
132 if(P.
isWinningMove(col)) scores[col] = (Position::WIDTH * Position::HEIGHT + 1 - P.
nbMoves()) / 2;
136 scores[col] = -solve(P2, weak);
143Solver::Solver() : nodeCount{0} {
144 for(
int i = 0; i < Position::WIDTH; i++)
145 columnOrder[i] = Position::WIDTH / 2 + (1 - 2 * (i % 2)) * (i + 1) / 2;
void add(const Position::position_t move, const int score)
Position::position_t getNext()
bool canPlay(int col) const
bool isWinningMove(int col) const
position_t possibleNonLosingMoves() const
int moveScore(position_t move) const