forked from caltechcs2/othello
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.cpp
171 lines (156 loc) · 3.98 KB
/
player.cpp
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "player.h"
/*
* Constructor for the player; initialize everything here. The side your AI is
* on (BLACK or WHITE) is passed in as "side". The constructor must finish
* within 30 seconds.
*/
Player::Player(Side side)
{
// Will be set to true in test_minimax.cpp.
testingMinimax = false;
/*
* TODO: Do any initialization you need to do here (setting up the board,
* precalculating things, etc.) However, remember that you will only have
* 30 seconds.
*/
myBoard = new Board();
mySide = side;
if (side == WHITE)
{
oppSide = BLACK;
}
else
{
oppSide = WHITE;
}
}
int Player::score_board(Board b, Side s)
{
Side oppSide;
if (s == WHITE)
{
oppSide = BLACK;
}
else
{
oppSide = WHITE;
}
int score = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if(b.get(s, j, i))
{
score += heuristicScore[j][i];
}
else if (b.get(oppSide, j, i))
{
score -= heuristicScore[j][i];
}
}
}
return score;
}
vector<Move*> findPossibleMoves(Board b, Side s)
{
vector<Move*> moves;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
Move * m = new Move(j, i);
if (b.checkMove(m, s))
{
moves.push_back(m);
}
}
}
return moves;
}
/*
* Destructor for the player.
*/
Player::~Player()
{
}
/*
* Compute the next move given the opponent's last move. Your AI is
* expected to keep track of the board on its own. If this is the first move,
* or if the opponent passed on the last move, then opponentsMove will be NULL.
*
* msLeft represents the time your AI has left for the total game, in
* milliseconds. doMove() must take no longer than msLeft, or your AI will
* be disqualified! An msLeft value of -1 indicates no time limit.
*
* The move returned must be legal; if there are no valid moves for your side,
* return NULL.
*/
Move *Player::doMove(Move *opponentsMove, int msLeft)
{
if (opponentsMove != NULL)
{
myBoard->doMove(opponentsMove, oppSide);
}
if (!myBoard->hasMoves(mySide))
{
return NULL;
}
vector<Move*> possible_moves = findPossibleMoves(*myBoard, mySide);
int max_score = -1000000;
Move *best_move = possible_moves.at(0);
for (unsigned int i = 0; i < possible_moves.size(); i++)
{
Board * new_board = myBoard->copy();
new_board->set(mySide, possible_moves.at(i)->getX(), possible_moves.at(i)->getY());
int score = -negascout(*new_board, oppSide, -999, 999, 3);
if (max_score < score)
{
max_score = score;
best_move = possible_moves.at(i);
}
}
myBoard->doMove(best_move, mySide);
return best_move;
}
int Player::negascout(Board board, Side side, int alpha, int beta, int depth)
{
Side oppSide;
if (side == WHITE)
{
oppSide = BLACK;
}
else
{
oppSide = WHITE;
}
if (!board.hasMoves(side) || depth <= 0)
{
return score_board(board, side);
}
vector<Move*> possible_moves = findPossibleMoves(board, side);
for (unsigned int i = 0; i < possible_moves.size(); i++)
{
Board * new_board = board.copy();
new_board->set(side, possible_moves.at(i)->getX(), possible_moves.at(i)->getY());
int score;
if (i > 0)
{
score = -negascout(*new_board, oppSide, -alpha - 1, -alpha, depth - 1);
if (alpha < score && score < beta)
{
score = -negascout(*new_board, oppSide, -beta, -score, depth - 1);
}
}
else
{
score = -negascout(*new_board, oppSide, -beta, -alpha, depth - 1);
}
alpha = max(alpha, score);
if (alpha >= beta)
{
return alpha;
}
}
return alpha;
}