summaryrefslogtreecommitdiff
path: root/minimax.h
blob: ad714fc427e6cce7af7afb83040c2c5b5dc42a19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#pragma once

#include <iostream>
#include <string>
#include <climits>
#include "board.h"


// >0 white good, <0 black good
template <int (*Eval)(const Board&)>  // should return high for white
int alphabeta(const Board &board, int depth);

int evaluate_pieceScore(const Board &board);



// IMPLEMENTATIONS

template <int (*Eval)(const Board&)>
static int alphabetaWhite(const Board &board, int depth, int alpha, int beta);

template <int (*Eval)(const Board&)>
static int alphabetaBlack(const Board &board, int depth, int alpha, int beta) {
	if (depth == 0 || board.pieceScore[WHITE] >= Board::worth(KING)) {
		return Eval(board);
	}
	int value = INT_MAX;
	vector<Board> subs = board.subsequents();
	if (depth >= 2) {
		sort(subs.begin(), subs.end(), [](const Board &B1, const Board &B2) {
			return Eval(B1) < Eval(B2);
		});
	}
	for (const Board &B : subs) {
		int v = alphabetaWhite<Eval>(B, depth - 1, alpha, beta);
		if (v < value) {
			value = v;
			if (v < beta) {
				beta = v;
				if (beta <= alpha) break;
			}
		}
	}
	// if (depth == 1) cerr << value << ", ";
	// else {
	// 	if (depth == 2) cerr << endl;
	// 	cerr << string(depth, ' ') << "alphabetaBlack: returning " << value << endl;
	// }
	// if (depth == 1 && abs(value) >= Board::worth(KING) / 10) cerr << board << endl;
	// cerr << board << endl;
	return value;
}

template <int (*Eval)(const Board&)>
static int alphabetaWhite(const Board &board, int depth, int alpha, int beta) {
	if (depth == 0 || board.pieceScore[BLACK] >= Board::worth(KING)) {
		return Eval(board);
	}
	int value = INT_MIN;
	vector<Board> subs = board.subsequents();
	if (depth >= 2) {
		sort(subs.begin(), subs.end(), [](const Board &B1, const Board &B2) {
			return Eval(B1) > Eval(B2);
		});
	}
	for (const Board &B : subs) {
		int v = alphabetaBlack<Eval>(B, depth - 1, alpha, beta);
		if (v > value) {
			value = v;
			if (v > alpha) {
				alpha = v;
				if (beta <= alpha) break;
			}
		}
	}
	// if (depth == 1) cerr << value << ", ";
	// else {
	// 	if (depth == 2) cerr << endl;
	// 	cerr << string(depth, ' ') << "alphabetaWhite: returning " << value << endl;
	// }
	// if (depth == 1 && abs(value) >= Board::worth(KING) / 10) cerr << board << endl;
	// cerr << board << endl;
	return value;
}

template <int (*Eval)(const Board&)>
int alphabeta(const Board &board, int depth) {
	if (board.onTurn == WHITE) {
		return alphabetaWhite<Eval>(board, depth, INT_MIN, INT_MAX);
	} else {
		return alphabetaBlack<Eval>(board, depth, INT_MIN, INT_MAX);
	}
}