-
Notifications
You must be signed in to change notification settings - Fork 2
/
botMoves.m
126 lines (100 loc) · 3.38 KB
/
botMoves.m
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
function botMoves(game,nGames)
% game: a class
% nGames: number of random simulated game to run for each potential move.
% Find all the legal moves
moves = game.possibleMoves;
side = game.whoseMove;
resultCounts = [];
if isempty(moves)
% No moves are possible.
fprintf('No moves remain. Game is over.\n')
return
elseif length(moves)==1
% One move is possible. Make it.
move = moves;
else
% More than one move is possible. Which is the best one?
resultCounts = ratePossibleMoves(game,moves,side,nGames);
% Maximize likelihood of not losing (i.e. maximize victory + draw)
resultCountsNoLose = resultCounts(:,side) + resultCounts(:,3);
% Or maximize likelihood of victory only (ignore draws)
resultCountsWinOnly = resultCounts(:,side);
[~,ix] = max(resultCountsNoLose);
move = moves(ix);
showRatingsFlag = false;
if showRatingsFlag
showRatings(side, resultCounts, moves, ix)
end
end
game.makeMove(move,side);
game.showBoard
end
function winnerCounts = ratePossibleMoves(game,possibleMoveList,mySide,nGames)
nPossibleMoves = length(possibleMoveList);
winnerCounts = zeros(nPossibleMoves,3);
otherSide = toggleSide(mySide);
for i = 1:nPossibleMoves
newGame = game.copy;
newGame.makeMove(possibleMoveList(i),mySide);
whoWins = playManyGames(newGame,nGames);
winnerCounts(i,:) = whoWins;
end
end
function whoWins = playManyGames(game,nGames)
% From the current board, play many random games and report the results.
% nGames: how many games to play
% whoWins is a 1x3 vector: [wins for side 1, wins for side 2, draw]
whoWins = [0 0 0];
% Is the game is already over?
winner = game.isGameOver;
if winner
whoWins(winner) = nGames;
return
end
for i = 1:nGames
randGame = game.copy;
gameOver = false;
while ~gameOver
side = randGame.whoseMove;
move = randomMove(randGame);
randGame.makeMove(move,side);
winner = randGame.isGameOver;
% winner will be 0 (undetermined), 1, 2, or 3 (tie)
if winner
whoWins(winner) = whoWins(winner) + 1;
gameOver = true;
end
end
end
end
function move = randomMove(game)
% Pick exactly one of the legal moves
moves = game.possibleMoves;
move = moves(ceil(rand*length(moves)));
end
function sideOut = toggleSide(sideIn)
sideOut = 3 - sideIn;
end
function showRatings(side, resultCounts, moves, ix)
fprintf('\nSIDE %d TO MOVE\n',side);
if side==1
fprintf(' Move Wins Loses Ties\n')
else
fprintf(' Move Loses Wins Ties\n')
end
fprintf(' ------ ------ ------ ------\n')
for i = 1:length(moves)
if i==ix
str1 = ' >';
str2 = '< ';
else
str1 = ' ';
str2 = ' ';
end
fprintf('%s%5d. %6d %6d %6d %s\n', ...
str1, moves(i), ...
resultCounts(i,1), resultCounts(i,2), resultCounts(i,3), ...
str2)
end
fprintf(' ------ ------ ------ ------\n')
end