-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmc.c
112 lines (93 loc) · 2.29 KB
/
mc.c
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
// Order and Chaos AI: Monte Carlo. - Tom Smeding
#include "params.h"
#define _XOPEN_SOURCE 700 // random
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "ai.h"
#ifndef ASSERTS
#define NDEBUG
#endif
#include <assert.h>
#define INF 1000000000 //1e9
#include "winmasks.h"
const uint64_t fullmask=(1ULL<<(N*N))-1;
#define APPLY(bitmap,idx) do {(bitmap)|=1ULL<<(idx);} while(0)
#define REMOVE(bitmap,idx) do {(bitmap)&=~(1ULL<<(idx));} while(0)
#define ISEMPTY(bitmap,idx) (!((bitmap)&(1ULL<<(idx))))
Board* makeboard(void){
return calloc(1,sizeof(Board));
}
void applymove(Board *board,Move mv){
APPLY(board->b[mv.stone],mv.pos);
}
bool isempty(const Board *board,int pos){
return ISEMPTY(board->b[0]|board->b[1],pos);
}
void printboard(const Board *board){
uint64_t b0=board->b[0],b1=board->b[1];
for(int y=0;y<N;y++){
for(int x=0;x<N;x++){
fputc(".OX"[(b0&1)+2*(b1&1)],stderr);
fputc(' ',stderr);
b0>>=1;
b1>>=1;
}
fputc('\n',stderr);
}
}
int checkwin(const Board *board){
for(int i=0;i<nwinmasks;i++){
if((board->b[0]&winmasks[i])==winmasks[i]||
(board->b[1]&winmasks[i])==winmasks[i])return ORDER;
}
if(((board->b[0]|board->b[1])&fullmask)==fullmask)return CHAOS;
return -1;
}
static int playthrough(Board board,int player){
(void)player;
int win;
Move poss[2*N*N];
int nposs;
while(true){
win=checkwin(&board);
if(win!=-1)return 1-2*win;
nposs=0;
for(int p=0;p<N*N;p++){
for(int stone=0;stone<2;stone++){
if(!ISEMPTY(board.b[0]|board.b[1],p))continue;
poss[nposs].pos=p;
poss[nposs++].stone=stone;
}
}
assert(nposs>0); //else Chaos would've won
int i=random()%nposs;
APPLY(board.b[poss[i].stone],poss[i].pos);
}
}
Move calcmove(Board *board,int player){
if(board->b[0]==0&&board->b[1]==0){
Move mv={player==ORDER?N*(N/2)+N/2:1,XX};
return mv;
}
int score,best,bestp=-1,beststone=-1;
for(int p=0;p<N*N;p++){
if(!ISEMPTY(board->b[0]|board->b[1],p))continue;
for(int stone=0;stone<2;stone++){
score=0;
Board b2=*board;
APPLY(b2.b[stone],p);
for(int i=0;i<MC_PLAYTHROUGHS;i++){
score+=playthrough(b2,!player);
}
if(bestp==-1||(player==ORDER?score>best:score<best)){
best=score;
bestp=p;
beststone=stone;
}
}
}
Move mv={bestp,beststone};
return mv;
}