khetai 0.2.3 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,33 +1,50 @@
1
- #include <stdio.h>
1
+ #include "khetai_lib.h"
2
2
  #include <ctype.h>
3
+ #include <stdio.h>
3
4
  #include <stdlib.h>
4
- #include <time.h>
5
- #include "khetai_lib.h"
6
5
 
7
6
  int max_time;
8
7
  time_t start_time;
9
8
 
10
- Square board[120] = {0};
11
- int pharaoh_loc[2] = {0};
12
- enum Player whose_turn;
13
- enum Player starter;
14
- int initial_depth = 0;
9
+ static Square board[120] = {0};
10
+ static int pharaoh_loc[2] = {0};
11
+ static enum Player whose_turn;
12
+ static enum Player starter;
13
+ static int initial_depth = 0;
15
14
 
16
- Move undo_moves[MAX_DEPTH] = {0};
17
- int undo_capture_indices[MAX_DEPTH] = {0};
18
- Square undo_capture_squares[MAX_DEPTH] = {0};
15
+ static Move undo_moves[MAX_DEPTH] = {0};
16
+ static int undo_capture_indices[MAX_DEPTH] = {0};
17
+ static Square undo_capture_squares[MAX_DEPTH] = {0};
19
18
 
20
- HashEntry table[TABLE_SIZE] = {0};
21
- uint64_t hashes[MAX_DEPTH] = {0};
22
- uint64_t keys[0xFF][120] = {0};
23
- uint64_t turn_key = 0;
24
-
25
- int undo_index = 0;
26
- int move_num = 0;
27
- bool checkmate = false;
19
+ PieceTracker piece_trackers[2] = {0};
28
20
 
29
- Move alphabeta_root(int depth, enum Player player)
30
- {
21
+ HashEntry table[TABLE_SIZE] = {0};
22
+ static uint64_t hashes[MAX_DEPTH] = {0};
23
+ static uint64_t keys[0xFF][120] = {0};
24
+ static uint64_t turn_key = 0;
25
+
26
+ static int undo_index = 0;
27
+ static int hashes_index = 0;
28
+ static bool checkmate = false;
29
+
30
+ static int alphabeta(int depth, enum Player player, int alpha, int beta);
31
+ static void insert_table(HashEntry *entry, uint64_t key, int depth, int flag, int score, Move move);
32
+ static int calculate_score(void);
33
+ static int distance_from_pharaoh(int i, int p);
34
+ static void fire_laser(uint64_t *hash);
35
+ static void undo_move();
36
+ static void find_valid_moves(Move *valid_moves, int *vi);
37
+ static void find_valid_anubis_pyramid_moves(int i, Move *valid_moves, int *vi);
38
+ static void find_valid_scarab_moves(int i, Move *valid_moves, int *vi);
39
+ static void find_valid_pharaoh_moves(int i, Move *valid_moves, int *vi);
40
+ static void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi);
41
+ static uint64_t get_board_hash();
42
+ static void init_piece_trackers();
43
+ static bool is_move_legal(Move move);
44
+ static Square str_to_square(char *str);
45
+ static void print_piece(Square s);
46
+
47
+ Move alphabeta_root(int depth, enum Player player) {
31
48
  whose_turn = player;
32
49
  starter = player;
33
50
  initial_depth = depth;
@@ -38,16 +55,14 @@ Move alphabeta_root(int depth, enum Player player)
38
55
  Move valid_moves[NUM_VALID_MOVES] = {0};
39
56
  int vi = 0;
40
57
  find_valid_moves(valid_moves, &vi);
41
- for (int i = 0; i < NUM_VALID_MOVES; i++)
42
- {
58
+ for (int i = 0; i < NUM_VALID_MOVES; i++) {
43
59
  if (valid_moves[i] == 0)
44
60
  break;
45
61
  make_move(valid_moves[i]);
46
62
  int score = -alphabeta(depth - 1, opposite_player(player), -beta, -alpha);
47
63
  undo_move();
48
64
  whose_turn = player;
49
- if (score > best_score)
50
- {
65
+ if (score > best_score) {
51
66
  best_score = score;
52
67
  best_move = valid_moves[i];
53
68
  }
@@ -62,12 +77,10 @@ Move alphabeta_root(int depth, enum Player player)
62
77
  return best_move;
63
78
  }
64
79
 
65
- int alphabeta(int depth, enum Player player, int alpha, int beta)
66
- {
80
+ int alphabeta(int depth, enum Player player, int alpha, int beta) {
67
81
  whose_turn = player;
68
- if (depth == 0 || checkmate)
69
- {
70
- return player == Red ? calculate_score() : -calculate_score();
82
+ if (depth == 0 || checkmate) {
83
+ return player == RED ? calculate_score() : -calculate_score();
71
84
  }
72
85
 
73
86
  int alpha_orig = alpha;
@@ -75,43 +88,33 @@ int alphabeta(int depth, enum Player player, int alpha, int beta)
75
88
  int vi = 0;
76
89
 
77
90
  int table_depth = initial_depth - depth;
78
- HashEntry *entry = search_table(hashes[move_num]);
79
- if (entry->key == hashes[move_num] && entry->depth > table_depth)
80
- {
91
+ HashEntry *entry = search_table(hashes[hashes_index]);
92
+ if (entry->key == hashes[hashes_index] && entry->depth > table_depth && is_move_legal(entry->move)) {
93
+ valid_moves[vi++] = entry->move;
94
+
81
95
  if (entry->flag == EXACT)
82
96
  return entry->score;
83
- else if (entry->flag == ALPHA)
84
- {
85
- if (entry->score > alpha)
86
- alpha = entry->score;
87
- }
88
- else
89
- {
90
- if (entry->score < beta)
91
- beta = entry->score;
92
- }
97
+ else if (entry->flag == LOWERBOUND && entry->score > alpha)
98
+ alpha = entry->score;
99
+ else if (entry->flag == UPPERBOUND && entry->score < beta)
100
+ beta = entry->score;
93
101
 
94
102
  if (alpha >= beta)
95
103
  return entry->score;
96
-
97
- if (is_move_legal(entry->move))
98
- valid_moves[vi++] = entry->move;
99
104
  }
100
105
 
101
106
  find_valid_moves(valid_moves, &vi);
102
107
  int best_score = -MAX_SCORE;
103
108
  Move best_move = (Move)0;
104
109
 
105
- for (int i = 0; (i < NUM_VALID_MOVES && (time(NULL) - start_time < max_time)); i++)
106
- {
110
+ for (int i = 0; (i < NUM_VALID_MOVES && (time(NULL) - start_time < max_time)); i++) {
107
111
  if (valid_moves[i] == 0)
108
112
  break;
109
113
  make_move(valid_moves[i]);
110
114
  int score = -alphabeta(depth - 1, opposite_player(player), -beta, -alpha);
111
115
  undo_move();
112
116
  whose_turn = player;
113
- if (score > best_score)
114
- {
117
+ if (score > best_score) {
115
118
  best_score = score;
116
119
  best_move = valid_moves[i];
117
120
  }
@@ -123,30 +126,16 @@ int alphabeta(int depth, enum Player player, int alpha, int beta)
123
126
 
124
127
  int flag = EXACT;
125
128
  if (best_score <= alpha_orig)
126
- flag = BETA;
129
+ flag = UPPERBOUND;
127
130
  else if (best_score >= beta)
128
- flag = ALPHA;
131
+ flag = LOWERBOUND;
129
132
 
130
-
131
- insert_table(entry, hashes[move_num], table_depth, flag, best_score, best_move);
133
+ insert_table(entry, hashes[hashes_index], table_depth, flag, best_score, best_move);
132
134
  return best_score;
133
135
  }
134
136
 
135
- void insert_table(HashEntry *entry, uint64_t key, int table_depth, int flag, int score, Move move)
136
- {
137
- if (entry->key != 0)
138
- {
139
- if (table_depth > entry->depth)
140
- {
141
- entry->key = key;
142
- entry->depth = table_depth;
143
- entry->flag = flag;
144
- entry->score = score;
145
- entry->move = move;
146
- }
147
- }
148
- else
149
- {
137
+ void insert_table(HashEntry *entry, uint64_t key, int table_depth, int flag, int score, Move move) {
138
+ if (entry->key == 0 || table_depth > entry->depth) {
150
139
  entry->key = key;
151
140
  entry->depth = table_depth;
152
141
  entry->flag = flag;
@@ -155,47 +144,47 @@ void insert_table(HashEntry *entry, uint64_t key, int table_depth, int flag, int
155
144
  }
156
145
  }
157
146
 
158
- int calculate_score()
159
- {
147
+ int calculate_score() {
160
148
  int score = 0;
161
149
  int anubis_score = 800;
162
150
  int pyramid_score = 1000;
163
151
  int pharaoh_score = 100000;
164
- for (int i = 0; i < 120; i++)
165
- {
166
- Square s = board[i];
167
- if (is_piece(s))
168
- {
169
- int value = 0;
170
- switch (get_piece(s))
171
- {
172
- case Anubis:
173
- value += anubis_score;
174
- value -= distance_from_pharaoh(i, pharaoh_loc[get_owner(s)]) * 10;
175
- break;
176
- case Pyramid:
177
- value += pyramid_score;
178
- value += rand() % 20;
179
- break;
180
- case Scarab:
181
- int max_distance = 16;
182
- int base_score = 1000;
183
- value += (max_distance - distance_from_pharaoh(i, pharaoh_loc[opposite_player(get_owner(s))])) * base_score / max_distance;
184
- break;
185
- case Pharaoh:
186
- value += pharaoh_score;
187
- break;
188
- default:
189
- break;
152
+
153
+ for (int j = 0; j < 2; j++) {
154
+ enum Player player = j;
155
+ for (int k = 0; k < 13; k++) {
156
+ int i = get_board_index(player, k);
157
+ if (i != EPT) {
158
+ Square s = board[i];
159
+ int value = 0;
160
+ switch (get_piece(s)) {
161
+ case ANUBIS:
162
+ value += anubis_score;
163
+ value -= distance_from_pharaoh(i, pharaoh_loc[player]) * 10;
164
+ break;
165
+ case PYRAMID:
166
+ value += pyramid_score;
167
+ value += (rand() % 51) - 25;
168
+ break;
169
+ case SCARAB:
170
+ int max_distance = 16;
171
+ int base_score = 1000;
172
+ value += (max_distance - distance_from_pharaoh(i, pharaoh_loc[opposite_player(player)])) * base_score / max_distance;
173
+ break;
174
+ case PHARAOH:
175
+ value += pharaoh_score;
176
+ break;
177
+ default:
178
+ break;
179
+ }
180
+ score += get_owner(s) == RED ? value : -value;
190
181
  }
191
- score += get_owner(s) == Red ? value : -value;
192
182
  }
193
183
  }
194
184
  return score;
195
185
  }
196
186
 
197
- int distance_from_pharaoh(int i, int p)
198
- {
187
+ int distance_from_pharaoh(int i, int p) {
199
188
  int px = p / 12;
200
189
  int py = p % 12;
201
190
  int ix = i / 12;
@@ -204,9 +193,8 @@ int distance_from_pharaoh(int i, int p)
204
193
  return m_distance;
205
194
  }
206
195
 
207
- void make_move(Move move)
208
- {
209
- uint64_t hash = hashes[move_num++];
196
+ void make_move(Move move) {
197
+ uint64_t hash = hashes[hashes_index++];
210
198
 
211
199
  int start = get_start(move);
212
200
  // remove starting piece
@@ -214,15 +202,12 @@ void make_move(Move move)
214
202
  int end = get_end(move);
215
203
  int rotation = get_rotation(move);
216
204
 
217
- if (rotation != 0)
218
- {
205
+ if (rotation != 0) {
219
206
  board[start] = rotate(board[start], rotation);
220
207
  // add starting piece back with rotation
221
208
  hash ^= keys[board[start]][start];
222
- }
223
- else
224
- {
225
- // remove ending piece if swapping
209
+ } else {
210
+ // remove ending piece
226
211
  if (is_piece(board[end]))
227
212
  hash ^= keys[board[end]][end];
228
213
 
@@ -232,11 +217,18 @@ void make_move(Move move)
232
217
  // add starting piece to end location
233
218
  hash ^= keys[board[end]][end];
234
219
 
220
+ enum Player moving_player = get_owner(moving_piece);
221
+ update_piece_tracker(moving_player, start, end);
222
+
235
223
  // add ending piece to start location if swapping
236
- if (is_piece(board[start]))
224
+ if (is_piece(board[start])) {
237
225
  hash ^= keys[board[start]][start];
238
226
 
239
- if (get_piece(moving_piece) == Pharaoh)
227
+ enum Player other_player = get_owner(board[start]);
228
+ update_piece_tracker(other_player, end, start);
229
+ }
230
+
231
+ if (get_piece(moving_piece) == PHARAOH)
240
232
  pharaoh_loc[get_owner(moving_piece)] = end;
241
233
  }
242
234
 
@@ -248,65 +240,60 @@ void make_move(Move move)
248
240
  // testing that hashing works properly
249
241
  // printf("\nHASH:\t%lu\nBOARD:\t%lu\n", hash, get_board_hash());
250
242
 
251
- hashes[move_num] = hash;
243
+ hashes[hashes_index] = hash;
252
244
  undo_index++;
253
245
  }
254
246
 
255
- void fire_laser(uint64_t *hash)
256
- {
247
+ void fire_laser(uint64_t *hash) {
257
248
  int i = sphinx_loc[whose_turn];
258
249
  int laser_dir = get_orientation(board[i]);
259
250
  bool traversing = true;
260
- while (traversing)
261
- {
251
+ while (traversing) {
262
252
  i = i + directions[laser_dir];
263
- if (i >= 0 && i < 120 && on_board[i] == 1)
264
- {
253
+ if (i >= 0 && i < 120 && on_board[i] == 1) {
265
254
  Square s = board[i];
266
- if (is_piece(s))
267
- {
255
+ if (is_piece(s)) {
268
256
  int piece = get_piece(s) - 1;
269
257
  int orientation = get_orientation(s);
270
258
  int result = reflections[laser_dir][piece][orientation];
271
- if (result == Dead)
272
- {
273
- if (get_piece(s) == Pharaoh)
259
+ if (result == DEAD) {
260
+ if (get_piece(s) == PHARAOH)
274
261
  checkmate = true;
275
262
  // remove piece
276
263
  *hash ^= keys[s][i];
264
+
265
+ enum Player remove_player = get_owner(s);
266
+ remove_from_piece_tracker(remove_player, i);
267
+
277
268
  undo_capture_indices[undo_index] = i;
278
269
  undo_capture_squares[undo_index] = s;
279
270
  board[i] = (Square)0;
280
271
  traversing = false;
281
- }
282
- else if (result == Absorbed)
283
- {
272
+ } else if (result == ABSORBED) {
284
273
  traversing = false;
285
- }
286
- else
287
- {
274
+ } else {
288
275
  laser_dir = result;
289
276
  }
290
277
  }
291
- }
292
- else
293
- {
278
+ } else {
294
279
  traversing = false;
295
280
  }
296
281
  }
297
282
  }
298
283
 
299
- void undo_move()
300
- {
301
- move_num--;
284
+ void undo_move() {
285
+ hashes_index--;
302
286
  undo_index--;
303
287
 
304
288
  Square captured = (Square)undo_capture_squares[undo_index];
305
289
  undo_capture_squares[undo_index] = 0;
306
- if (captured > 0)
307
- {
308
- board[undo_capture_indices[undo_index]] = captured;
290
+ if (captured > 0) {
291
+ uint8_t board_pos = undo_capture_indices[undo_index];
292
+ board[board_pos] = captured;
309
293
  undo_capture_indices[undo_index] = 0;
294
+
295
+ enum Player captured_player = get_owner(captured);
296
+ add_to_piece_tracker(captured_player, board_pos);
310
297
  }
311
298
 
312
299
  Move move = undo_moves[undo_index];
@@ -315,47 +302,47 @@ void undo_move()
315
302
  int end = get_end(move);
316
303
  int rotation = get_rotation(move);
317
304
 
318
- if (rotation != 0)
319
- {
305
+ if (rotation != 0) {
320
306
  board[start] = rotate(board[start], rotation);
321
- }
322
- else
323
- {
307
+ } else {
324
308
  Square moving_piece = board[start];
325
309
  board[start] = board[end];
326
310
  board[end] = moving_piece;
327
311
 
328
- if (get_piece(moving_piece) == Pharaoh)
312
+ enum Player moving_player = get_owner(moving_piece);
313
+ update_piece_tracker(moving_player, start, end);
314
+
315
+ if (board[start] != 0) {
316
+ enum Player other_player = get_owner(board[start]);
317
+ update_piece_tracker(other_player, end, start);
318
+ }
319
+
320
+ if (get_piece(moving_piece) == PHARAOH)
329
321
  pharaoh_loc[get_owner(moving_piece)] = end;
330
322
  }
331
323
  checkmate = false;
332
324
  }
333
325
 
334
- void find_valid_moves(Move *valid_moves, int *vi)
335
- {
336
- for (int i = 0; i < 120; i++)
337
- {
338
- Square s = board[i];
339
- enum Player piece_color = get_owner(s);
340
- if (is_piece(s) && piece_color == whose_turn)
341
- {
342
- enum Piece piece = get_piece(s);
343
- switch (piece)
344
- {
345
- case Anubis:
346
- find_valid_anubis_pyramid_moves(i, valid_moves, vi);
326
+ void find_valid_moves(Move *valid_moves, int *vi) {
327
+ for (int i = 0; i < 13; i++) {
328
+ uint8_t board_pos = piece_trackers[whose_turn].positions[i];
329
+ if (board_pos != EPT) {
330
+ enum Piece piece = get_piece(board[board_pos]);
331
+ switch (piece) {
332
+ case ANUBIS:
333
+ find_valid_anubis_pyramid_moves(board_pos, valid_moves, vi);
347
334
  break;
348
- case Pyramid:
349
- find_valid_anubis_pyramid_moves(i, valid_moves, vi);
335
+ case PYRAMID:
336
+ find_valid_anubis_pyramid_moves(board_pos, valid_moves, vi);
350
337
  break;
351
- case Scarab:
352
- find_valid_scarab_moves(i, valid_moves, vi);
338
+ case SCARAB:
339
+ find_valid_scarab_moves(board_pos, valid_moves, vi);
353
340
  break;
354
- case Pharaoh:
355
- find_valid_pharaoh_moves(i, valid_moves, vi);
341
+ case PHARAOH:
342
+ find_valid_pharaoh_moves(board_pos, valid_moves, vi);
356
343
  break;
357
- case Sphinx:
358
- find_valid_sphinx_moves(i, valid_moves, vi);
344
+ case SPHINX:
345
+ find_valid_sphinx_moves(board_pos, valid_moves, vi);
359
346
  break;
360
347
  default:
361
348
  break;
@@ -364,78 +351,60 @@ void find_valid_moves(Move *valid_moves, int *vi)
364
351
  }
365
352
  }
366
353
 
367
- void find_valid_anubis_pyramid_moves(int i, Move *valid_moves, int *vi)
368
- {
369
- for (int j = 0; j < 8; j++)
370
- {
354
+ void find_valid_anubis_pyramid_moves(int i, Move *valid_moves, int *vi) {
355
+ for (int j = 0; j < 8; j++) {
371
356
  int dest = i + directions[j];
372
- if (!is_piece(board[dest]) && can_move[whose_turn][dest])
373
- {
357
+ if (!is_piece(board[dest]) && can_move[whose_turn][dest]) {
374
358
  valid_moves[(*vi)++] = new_move(i, dest, 0);
375
359
  }
376
360
  }
377
- for (int j = 0; j < 2; j++)
378
- {
361
+ for (int j = 0; j < 2; j++) {
379
362
  valid_moves[(*vi)++] = new_move(i, i, rotations[j]);
380
363
  }
381
364
  }
382
365
 
383
- void find_valid_scarab_moves(int i, Move *valid_moves, int *vi)
384
- {
385
- for (int j = 0; j < 8; j++)
386
- {
366
+ void find_valid_scarab_moves(int i, Move *valid_moves, int *vi) {
367
+ for (int j = 0; j < 8; j++) {
387
368
  int dest = i + directions[j];
388
- if (can_move[whose_turn][dest])
389
- {
390
- if (!is_piece(board[dest]) || get_piece(board[dest]) != Pharaoh)
391
- {
369
+ if (can_move[whose_turn][dest]) {
370
+ if (!is_piece(board[dest]) || (get_owner(board[dest]) != whose_turn && get_piece(board[dest]) != PHARAOH)) {
392
371
  valid_moves[(*vi)++] = new_move(i, dest, 0);
393
372
  }
394
373
  }
395
374
  }
396
- for (int j = 0; j < 2; j++)
397
- {
375
+ for (int j = 0; j < 2; j++) {
398
376
  valid_moves[(*vi)++] = new_move(i, i, rotations[j]);
399
377
  }
400
378
  }
401
379
 
402
- void find_valid_pharaoh_moves(int i, Move *valid_moves, int *vi)
403
- {
404
- for (int j = 0; j < 8; j++)
405
- {
380
+ void find_valid_pharaoh_moves(int i, Move *valid_moves, int *vi) {
381
+ for (int j = 0; j < 8; j++) {
406
382
  int dest = i + directions[j];
407
- if (!is_piece(board[dest]) && can_move[whose_turn][dest])
408
- {
383
+ if (!is_piece(board[dest]) && can_move[whose_turn][dest]) {
409
384
  valid_moves[(*vi)++] = new_move(i, dest, 0);
410
385
  }
411
386
  }
412
387
  }
413
388
 
414
- void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi)
415
- {
389
+ void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi) {
416
390
  enum Player player = get_owner(board[i]);
417
391
  enum Orientation orientation = get_orientation(board[i]);
418
- int rotation = player == Silver ? (orientation == North ? -1 : 1) : (orientation == South ? -1 : 1);
392
+ int rotation = player == SILVER ? (orientation == NORTH ? -1 : 1) : (orientation == SOUTH ? -1 : 1);
419
393
  valid_moves[(*vi)++] = new_move(i, i, rotation);
420
394
  }
421
395
 
422
- void init_zobrist()
423
- {
424
- for (int i = 0; i < 0xFF; i++)
425
- {
426
- for (int j = 0; j < 120; j++)
427
- {
396
+ void init_zobrist() {
397
+ for (int i = 0; i < 0xFF; i++) {
398
+ for (int j = 0; j < 120; j++) {
428
399
  keys[i][j] = random_number();
429
400
  }
430
401
  }
431
402
  turn_key = random_number();
432
403
  }
433
404
 
434
- uint64_t get_board_hash()
435
- {
405
+ uint64_t get_board_hash() {
436
406
  uint64_t hash = 0;
437
- for (int i = 0; i < 120; i++)
438
- {
407
+ for (int i = 0; i < 120; i++) {
439
408
  if (is_piece(board[i]))
440
409
  hash ^= keys[board[i]][i];
441
410
  }
@@ -444,97 +413,116 @@ uint64_t get_board_hash()
444
413
  return hash;
445
414
  }
446
415
 
447
- bool is_move_legal(Move move)
448
- {
416
+ void init_piece_trackers() {
417
+ for (int i = 0; i < 13; i++) {
418
+ piece_trackers[SILVER].positions[i] = EPT;
419
+ piece_trackers[RED].positions[i] = EPT;
420
+ }
421
+
422
+ int si = 0;
423
+ int ri = 0;
424
+
425
+ for (int i = 0; i < 120; i++) {
426
+ Square s = board[i];
427
+ if (is_piece(s)) {
428
+ if (get_owner(s) == SILVER) {
429
+ piece_trackers[SILVER].positions[si] = i;
430
+ piece_trackers[SILVER].board_idx_position[i] = si;
431
+ si++;
432
+ } else if (get_owner(s) == RED) {
433
+ piece_trackers[RED].positions[ri] = i;
434
+ piece_trackers[RED].board_idx_position[i] = ri;
435
+ ri++;
436
+ }
437
+ } else {
438
+ piece_trackers[SILVER].board_idx_position[i] = EPT;
439
+ piece_trackers[RED].board_idx_position[i] = EPT;
440
+ }
441
+ }
442
+ }
443
+
444
+ bool is_move_legal(Move move) {
449
445
  int start = get_start(move);
450
446
  int end = get_end(move);
451
- if (is_piece(board[start]) && get_owner(board[start]) == whose_turn)
452
- {
447
+ if (is_piece(board[start]) && get_owner(board[start]) == whose_turn) {
453
448
  if (!is_piece(board[end]) || get_rotation(move) != 0)
454
449
  return true;
455
- else if (is_piece(board[end]) && get_piece(board[start]) == Scarab && get_piece(board[end]) < 3)
450
+ else if (is_piece(board[end]) && get_piece(board[start]) == SCARAB && get_piece(board[end]) <= 3)
456
451
  return true;
457
452
  }
458
453
  return false;
459
454
  }
460
455
 
461
- void reset_undo()
462
- {
456
+ void reset_undo() {
463
457
  undo_index = 0;
464
- for (int i = 0; i < MAX_DEPTH; i++)
465
- {
458
+ for (int i = 0; i < MAX_DEPTH; i++) {
466
459
  undo_moves[i] = 0;
467
460
  undo_capture_indices[i] = 0;
468
461
  undo_capture_squares[i] = 0;
469
462
  }
470
463
  }
471
464
 
472
- void setup_board(char *init_board[120])
473
- {
474
- move_num = 0;
465
+ void setup_board(char *init_board[120]) {
466
+ hashes_index = 0;
475
467
  uint64_t hash = 0;
476
- for (int i = 0; i < 120; i++)
477
- {
468
+ for (int i = 0; i < 120; i++) {
478
469
  board[i] = str_to_square(init_board[i]);
479
470
  Square s = board[i];
480
- if (is_piece(s))
481
- {
471
+ if (is_piece(s)) {
482
472
  hash ^= keys[s][i];
483
- if (get_piece(s) == Pharaoh)
484
- {
485
- if (get_owner(s) == Silver)
486
- pharaoh_loc[Silver] = i;
487
- else if (get_owner(s) == Red)
488
- pharaoh_loc[Red] = i;
473
+ if (get_piece(s) == PHARAOH) {
474
+ if (get_owner(s) == SILVER)
475
+ pharaoh_loc[SILVER] = i;
476
+ else if (get_owner(s) == RED)
477
+ pharaoh_loc[RED] = i;
489
478
  }
490
479
  }
491
480
  }
492
- hashes[0] = hash;
481
+ hashes[hashes_index] = hash;
493
482
 
494
- for (int i = 0; i < TABLE_SIZE; i++)
495
- {
483
+ for (int i = 0; i < TABLE_SIZE; i++) {
496
484
  table[i].key = 0;
497
485
  table[i].depth = 0;
498
486
  table[i].flag = 0;
499
487
  table[i].score = 0;
500
488
  table[i].move = 0;
501
489
  }
490
+
491
+ init_piece_trackers();
502
492
  }
503
493
 
504
- Square str_to_square(char *str)
505
- {
494
+ Square str_to_square(char *str) {
506
495
  enum Player player;
507
496
  enum Piece piece;
508
497
  enum Orientation orientation;
509
498
 
510
- if (str[0] != '-')
511
- {
499
+ if (str[0] != '-') {
512
500
  if (islower(str[0]))
513
- player = Silver;
501
+ player = SILVER;
514
502
  else
515
- player = Red;
503
+ player = RED;
516
504
 
517
505
  char p = tolower(str[0]);
518
506
  if (p == 'a')
519
- piece = Anubis;
507
+ piece = ANUBIS;
520
508
  else if (p == 'p')
521
- piece = Pyramid;
509
+ piece = PYRAMID;
522
510
  else if (p == 's')
523
- piece = Scarab;
511
+ piece = SCARAB;
524
512
  else if (p == 'x')
525
- piece = Pharaoh;
513
+ piece = PHARAOH;
526
514
  else
527
- piece = Sphinx;
515
+ piece = SPHINX;
528
516
 
529
517
  char o = str[1];
530
518
  if (o == '0')
531
- orientation = North;
519
+ orientation = NORTH;
532
520
  else if (o == '1')
533
- orientation = East;
521
+ orientation = EAST;
534
522
  else if (o == '2')
535
- orientation = South;
523
+ orientation = SOUTH;
536
524
  else
537
- orientation = West;
525
+ orientation = WEST;
538
526
 
539
527
  return (Square)((int)player << 1 | (int)piece << 2 | (int)orientation << 5);
540
528
  }
@@ -542,55 +530,50 @@ Square str_to_square(char *str)
542
530
  return (Square)0;
543
531
  }
544
532
 
545
- void print_board()
546
- {
547
- for (int i = 0; i < 120; i++)
548
- {
533
+ void print_board() {
534
+ for (int i = 0; i < 120; i++) {
549
535
  print_piece(board[i]);
550
536
  if ((i + 1) % 12 == 0)
551
537
  printf("\n");
552
538
  }
553
539
  }
554
540
 
555
- void print_piece(Square s)
556
- {
541
+ void print_piece(Square s) {
557
542
  enum Player player = get_owner(s);
558
- if (is_piece(s))
559
- {
543
+ if (is_piece(s)) {
560
544
  enum Piece piece = get_piece(s);
561
545
  enum Orientation orientation = get_orientation(s);
562
- switch (piece)
563
- {
564
- case Anubis:
565
- if (player == Silver)
546
+ switch (piece) {
547
+ case ANUBIS:
548
+ if (player == SILVER)
566
549
  printf("a");
567
550
  else
568
551
  printf("A");
569
552
  break;
570
553
 
571
- case Pyramid:
572
- if (player == Silver)
554
+ case PYRAMID:
555
+ if (player == SILVER)
573
556
  printf("p");
574
557
  else
575
558
  printf("P");
576
559
  break;
577
560
 
578
- case Scarab:
579
- if (player == Silver)
561
+ case SCARAB:
562
+ if (player == SILVER)
580
563
  printf("s");
581
564
  else
582
565
  printf("S");
583
566
  break;
584
567
 
585
- case Pharaoh:
586
- if (player == Silver)
568
+ case PHARAOH:
569
+ if (player == SILVER)
587
570
  printf("x");
588
571
  else
589
572
  printf("X");
590
573
  break;
591
574
 
592
- case Sphinx:
593
- if (player == Silver)
575
+ case SPHINX:
576
+ if (player == SILVER)
594
577
  printf("l");
595
578
  else
596
579
  printf("L");
@@ -599,26 +582,24 @@ void print_piece(Square s)
599
582
  printf("-");
600
583
  break;
601
584
  }
602
- switch (orientation)
603
- {
604
- case North:
585
+ switch (orientation) {
586
+ case NORTH:
605
587
  printf("0");
606
588
  break;
607
- case East:
589
+ case EAST:
608
590
  printf("1");
609
591
  break;
610
- case South:
592
+ case SOUTH:
611
593
  printf("2");
612
594
  break;
613
- case West:
595
+ case WEST:
614
596
  printf("3");
615
597
  break;
616
598
  default:
617
599
  printf("-");
618
600
  break;
619
601
  }
620
- }
621
- else
602
+ } else
622
603
  printf("--");
623
604
  }
624
605
 
@@ -626,8 +607,7 @@ int get_start_wrapper(Move move) { return get_start(move); }
626
607
  int get_end_wrapper(Move move) { return get_end(move); }
627
608
  int get_rotation_wrapper(Move move) { return get_rotation(move); }
628
609
 
629
- void set_time_parameters(int _max_time, time_t _start_time)
630
- {
610
+ void set_time_parameters(int _max_time, time_t _start_time) {
631
611
  max_time = _max_time;
632
612
  start_time = _start_time;
633
613
  }