-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhistory.c
145 lines (127 loc) · 3.57 KB
/
history.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
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
#include "history.h"
#include "board.h"
#include <stdlib.h>
#include <string.h>
struct turn* turnHistory = NULL;
static unsigned char _ko;
static void destroyChangesFrom(struct change*);
void initHistory(unsigned char ko) {
_ko = ko;
}
void undo(void) {
if (turnCounter == 0)
return;
struct turn* tp = turnHistory;
struct turn* last = NULL;
//move forward to most recent turn
int i;
for (i = 1; i < turnCounter; i++) {
last = tp;
tp = tp->next;
}
if (last)
last->next = NULL;
else
turnHistory = NULL;
struct change* cp;
//revert board
for (cp = tp->first; cp; cp = cp->next) {
board[cp->y][cp->x] = cp->before;
//remove points if piece captured
if (!IS_EMPTY(cp->before) && IS_EMPTY(cp->after)) {
whitePoints -= (cp->before == BLACK);
blackPoints -= (cp->before == WHITE);
}
}
destroyTurnsFrom(tp);
}
void destroyTurnsFrom(struct turn* root) {
struct turn* tp = root; //turn pointer
struct turn* tnext = root; //next turn pointer
struct change* cp; //change pointer
struct change* cnext; //next change pointer
for (; tp; tp = tnext) {
tnext = tp->next;
//free changes
for (cp = tp->first; cp; cp = cnext) {
cnext = cp->next;
free(cp);
}
free(tp);
}
}
static void destroyChangesFrom(struct change* root) {
struct change* cp; //change pointer
struct change* cnext; //next change pointer
for (cp = root; cp; cp = cnext) {
cnext = cp->next;
free(cp);
}
}
int searchHistory(char* hash) {
struct turn* tp = turnHistory;
switch (_ko) {
case NO_SUPERKO:
for (int t = 0; t < turnCounter - 1; t++) {
if ((turnCounter - t) <= 2 && strncmp(hash, tp->hash, MD5_DIGEST_LENGTH) == 0)
return 1;
tp = tp->next;
}
break;
case POSI_SUPERKO:
for (int t = 0; t < turnCounter - 1; t++) {
//found collision with previous position
if (strncmp(hash, tp->hash, MD5_DIGEST_LENGTH) == 0)
return 1;
tp = tp->next;
}
break;
case SITU_SUPERKO:
for (int t = 0; t < turnCounter - 1; t++, tp = tp -> next) {
//incorrect turn, skip
if (GET_TURN(t) == nextTurn)
continue;
//found collision with previous position
if (strncmp(hash, tp->hash, MD5_DIGEST_LENGTH) == 0)
return 1;
}
break;
}
return 0;
}
struct turn* newTurn(void) {
struct turn* turn = turnHistory;
int i;
for (i = 1; i < turnCounter; i++)
turn = turn->next;
if (!turn) {
turn = (struct turn*) malloc(sizeof(struct turn));
if (!turn) {
return NULL;
}
turn->next = NULL;
turnHistory = turn;
}
else {
turn->next = (struct turn*) malloc(sizeof(struct turn));
turn = turn->next;
if (!turn) {
return NULL;
}
turn->next = NULL;
}
turn->first = NULL;
return turn;
}
struct change* newChange(unsigned char* c, unsigned char to) {
struct change* change = (struct change*) malloc(sizeof(struct change));
if (!change) {
return NULL;
}
change->x = GET_X(c);
change->y = GET_Y(c);
change->before = *c;
change->after = to;
change->next = NULL;
return change;
}