khetai 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09db06457292f856f5e69a7f1af7171cc3d1fcc39b4bf53638ed34607fbd35d0'
4
- data.tar.gz: 5a11e03e0a5fbfb4f6189fe35e5e75905b57cdc7ec6efcae50b2a5d69cc56be3
3
+ metadata.gz: 57b893b2ca7a9ab8690ce116801bbd6286bc5856c7f87d01b7d51a7bbd6cc8f9
4
+ data.tar.gz: 433c4c67445b585526e598f6c04c53ca9e3ce67dab012a65aafa9922d18d8a80
5
5
  SHA512:
6
- metadata.gz: c2595304f50a6ccb71b158f84377b4c10c747284081a1c4ac24f5fccbd42dc69ea074e7476626432bdd29e5519932740f577c9bb25dfe70e6421975993813fcf
7
- data.tar.gz: 277cc078b123efae38ddc9731eca386d7d11adbb063f8660cbfb2acccd47d5d4f109b122818100f0f5fa526f238728b72e6812d04f02fa16082f8189798d7384
6
+ metadata.gz: 5e85bedabf5229ac1abad59889e2d2980e0fe194ad42d3acff67fb72817ed6755b59798af3a7312836cc225bb044f1bc12641edb30f4693e37e91144581ac142
7
+ data.tar.gz: f7cb8d7735f580752ed50ca8f4cf084a5398bbac70d26b32da6c9a61049de9a79b68aceac685afe5a907ec8bea83ba24e72fcf3c991a88145996c5a8563b85e3
data/.gitignore CHANGED
@@ -6,5 +6,6 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /build/
9
10
  .vscode
10
11
  *.so
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- khetai (0.1.6)
4
+ khetai (0.1.7)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # KhetAI
2
2
 
3
+ ## Install
4
+ ```
5
+ gem install khetai
6
+ ```
7
+
3
8
  ## Usage
4
9
  ```
5
10
  require 'khetai'
@@ -40,7 +45,7 @@ move = KhetAI.move(board, whose_turn, max_search_depth, max_search_time)
40
45
  ## Build and Deploy Commands
41
46
  ```
42
47
  bundle exec rake compile
43
- bundle ecec rake build
48
+ bundle exec rake build
44
49
  bundle exec rake release
45
50
 
46
51
  gem push pkg/<gem>
@@ -0,0 +1,5 @@
1
+ cmake_minimum_required(VERSION 3.10)
2
+
3
+ project(khetai LANGUAGES C)
4
+
5
+ add_executable(khetai main.c ../khetai_lib.c)
@@ -0,0 +1,50 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <time.h>
4
+ #include "../khetai_lib.h"
5
+
6
+ char *init_board[120] =
7
+ {"--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--",
8
+ "--", "L2", "--", "--", "--", "A2", "X2", "A2", "P1", "--", "--", "--",
9
+ "--", "--", "--", "P2", "--", "--", "--", "--", "--", "--", "--", "--",
10
+ "--", "--", "--", "--", "p3", "--", "--", "--", "--", "--", "--", "--",
11
+ "--", "P0", "--", "p2", "--", "S2", "S3", "--", "P1", "--", "p3", "--",
12
+ "--", "P1", "--", "p3", "--", "s1", "s0", "--", "P0", "--", "p2", "--",
13
+ "--", "--", "--", "--", "--", "--", "--", "P1", "--", "--", "--", "--",
14
+ "--", "--", "--", "--", "--", "--", "--", "--", "p0", "--", "--", "--",
15
+ "--", "--", "--", "p3", "a0", "x0", "a0", "--", "--", "--", "l0", "--",
16
+ "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--"};
17
+
18
+ time_t start_time;
19
+ int max_time;
20
+
21
+ int main()
22
+ {
23
+ init_zobrist();
24
+ srand((unsigned)time(NULL));
25
+
26
+ setup_board(init_board);
27
+ print_board();
28
+
29
+ start_time = time(NULL);
30
+ max_time = 5;
31
+ int max_depth = 25;
32
+
33
+ int depth = 1;
34
+ Move best_move = (Move)0;
35
+ Move current_move = (Move)0;
36
+ while ((time(NULL) - start_time < max_time) && (depth <= max_depth))
37
+ {
38
+ best_move = current_move;
39
+ current_move = alphabeta_root(depth, Red);
40
+ depth++;
41
+ }
42
+ make_move(best_move);
43
+
44
+ printf("\n========================\n\n");
45
+ print_board();
46
+
47
+ printf("\nDEPTH: %d\n", depth - 1);
48
+
49
+ return 0;
50
+ }
@@ -0,0 +1,15 @@
1
+ require_relative "../../../lib/khetai/khetai.so"
2
+
3
+ board = ["--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--",
4
+ "--", "L2", "--", "--", "--", "A2", "X2", "A2", "P1", "--", "--", "--",
5
+ "--", "--", "--", "P2", "--", "--", "--", "--", "--", "--", "--", "--",
6
+ "--", "--", "--", "--", "p3", "--", "--", "--", "--", "--", "--", "--",
7
+ "--", "P0", "--", "p2", "--", "S2", "S3", "--", "P1", "--", "p3", "--",
8
+ "--", "P1", "--", "p3", "--", "s1", "s0", "--", "P0", "--", "p2", "--",
9
+ "--", "--", "--", "--", "--", "--", "--", "P1", "--", "--", "--", "--",
10
+ "--", "--", "--", "--", "--", "--", "--", "--", "p0", "--", "--", "--",
11
+ "--", "--", "--", "p3", "a0", "x0", "a0", "--", "--", "--", "l0", "--",
12
+ "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--"]
13
+
14
+ move = KhetAI.move(board, 1, 6, 5)
15
+ puts move.to_s
@@ -5,7 +5,9 @@
5
5
  #include "khetai_lib.h"
6
6
 
7
7
  Square board[120] = {0};
8
+ int pharaoh_loc[2] = {0};
8
9
  enum Player whose_turn;
10
+ enum Player starter;
9
11
 
10
12
  Move undo_moves[MAX_DEPTH] = {0};
11
13
  int undo_capture_indices[MAX_DEPTH] = {0};
@@ -23,6 +25,7 @@ bool checkmate = false;
23
25
  Move alphabeta_root(int depth, enum Player player)
24
26
  {
25
27
  whose_turn = player;
28
+ starter = player;
26
29
  int best_score = -MAX_SCORE;
27
30
  Move best_move = (Move)0;
28
31
  int alpha = -MAX_SCORE;
@@ -145,24 +148,27 @@ int calculate_score()
145
148
  {
146
149
  int score = 0;
147
150
  int anubis_score = 500;
148
- int scarab_score = 750;
149
151
  int pyramid_score = 1000;
150
152
  int pharaoh_score = 100000;
151
153
  for (int i = 0; i < 120; i++)
152
154
  {
153
- if (board[i] > 0)
155
+ Square s = board[i];
156
+ if (is_piece(s))
154
157
  {
155
158
  int value = 0;
156
- switch (get_piece(board[i]))
159
+ switch (get_piece(s))
157
160
  {
158
161
  case Anubis:
159
162
  value += anubis_score;
163
+ value -= distance_from_pharaoh(i, pharaoh_loc[get_owner(s)]) * 10;
160
164
  break;
161
165
  case Pyramid:
162
166
  value += pyramid_score;
167
+ value += rand() % 20;
163
168
  break;
164
169
  case Scarab:
165
- value += scarab_score;
170
+ value += 100 / (distance_from_pharaoh(i, pharaoh_loc[opposite_player(get_owner(s))])) * 10;
171
+ value += rand() % 10;
166
172
  break;
167
173
  case Pharaoh:
168
174
  value += pharaoh_score;
@@ -170,10 +176,20 @@ int calculate_score()
170
176
  default:
171
177
  break;
172
178
  }
173
- score += get_owner(board[i]) == Red ? value : -value;
179
+ score += get_owner(s) == Red ? value : -value;
174
180
  }
175
181
  }
176
- return score += rand() % 100;
182
+ return score;
183
+ }
184
+
185
+ int distance_from_pharaoh(int i, int p)
186
+ {
187
+ int px = p / 12;
188
+ int py = p % 12;
189
+ int ix = i / 12;
190
+ int iy = i % 12;
191
+ int m_distance = abs(px - ix) + abs(py - iy);
192
+ return m_distance;
177
193
  }
178
194
 
179
195
  void make_move(Move move)
@@ -204,9 +220,12 @@ void make_move(Move move)
204
220
  // add starting piece to end location
205
221
  hash ^= keys[board[end]][end];
206
222
 
207
- // add ending piece to start position if swapping
223
+ // add ending piece to start location if swapping
208
224
  if (is_piece(board[start]))
209
225
  hash ^= keys[board[start]][start];
226
+
227
+ if (get_piece(moving_piece) == Pharaoh)
228
+ pharaoh_loc[whose_turn] = end;
210
229
  }
211
230
 
212
231
  undo_moves[undo_index] = new_move(end, start, -rotation);
@@ -214,6 +233,9 @@ void make_move(Move move)
214
233
  fire_laser(&hash);
215
234
  hash ^= turn_key;
216
235
 
236
+ // testing that hashing works properly
237
+ // printf("\nHASH:\t%lu\nBOARD:\t%lu\n", hash, get_board_hash());
238
+
217
239
  hashes[move_num] = hash;
218
240
  undo_index++;
219
241
  }
@@ -228,18 +250,20 @@ void fire_laser(uint64_t *hash)
228
250
  i = i + directions[laser_dir];
229
251
  if (i >= 0 && i < 120 && on_board[i] == 1)
230
252
  {
231
- if (board[i] > 0)
253
+ Square s = board[i];
254
+ if (is_piece(s))
232
255
  {
233
- int piece = get_piece(board[i]) - 1;
234
- int orientation = get_orientation(board[i]);
256
+ int piece = get_piece(s) - 1;
257
+ int orientation = get_orientation(s);
235
258
  int result = reflections[laser_dir][piece][orientation];
236
259
  if (result == Dead)
237
260
  {
238
- if (get_piece(board[i]) == Pharaoh)
261
+ if (get_piece(s) == Pharaoh)
239
262
  checkmate = true;
240
- *hash ^= keys[board[i]][i];
263
+ // remove piece
264
+ *hash ^= keys[s][i];
241
265
  undo_capture_indices[undo_index] = i;
242
- undo_capture_squares[undo_index] = board[i];
266
+ undo_capture_squares[undo_index] = s;
243
267
  board[i] = (Square)0;
244
268
  traversing = false;
245
269
  }
@@ -288,6 +312,9 @@ void undo_move()
288
312
  Square moving_piece = board[start];
289
313
  board[start] = board[end];
290
314
  board[end] = moving_piece;
315
+
316
+ if (get_piece(moving_piece) == Pharaoh)
317
+ pharaoh_loc[get_owner(board[end])] = end;
291
318
  }
292
319
  checkmate = false;
293
320
  }
@@ -387,14 +414,74 @@ void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi)
387
414
  valid_moves[(*vi)++] = new_move(i, i, rotation);
388
415
  }
389
416
 
417
+ void init_zobrist()
418
+ {
419
+ for (int i = 0; i < 0xFF; i++)
420
+ {
421
+ for (int j = 0; j < 120; j++)
422
+ {
423
+ keys[i][j] = random_number();
424
+ }
425
+ }
426
+ turn_key = random_number();
427
+ }
428
+
429
+ uint64_t get_board_hash()
430
+ {
431
+ uint64_t hash = 0;
432
+ for (int i = 0; i < 120; i++)
433
+ {
434
+ if (is_piece(board[i]))
435
+ hash ^= keys[board[i]][i];
436
+ }
437
+ if (whose_turn == starter)
438
+ hash ^= turn_key;
439
+ return hash;
440
+ }
441
+
442
+ bool is_move_legal(Move move)
443
+ {
444
+ int start = get_start(move);
445
+ int end = get_end(move);
446
+ if (is_piece(board[start]) && get_owner(board[start]) == whose_turn)
447
+ {
448
+ if (!is_piece(board[end]) || get_rotation(move) != 0)
449
+ return true;
450
+ else if (is_piece(board[end]) && get_piece(board[start]) == Scarab && get_piece(board[end]) < 3)
451
+ return true;
452
+ }
453
+ return false;
454
+ }
455
+
456
+ void reset_undo()
457
+ {
458
+ undo_index = 0;
459
+ for (int i = 0; i < MAX_DEPTH; i++)
460
+ {
461
+ undo_moves[i] = 0;
462
+ undo_capture_indices[i] = 0;
463
+ undo_capture_squares[i] = 0;
464
+ }
465
+ }
466
+
390
467
  void setup_board(char *init_board[120])
391
468
  {
392
469
  uint64_t hash = 0;
393
470
  for (int i = 0; i < 120; i++)
394
471
  {
395
472
  board[i] = str_to_square(init_board[i]);
396
- if (board[i] > 0)
397
- hash ^= keys[board[i]][i];
473
+ Square s = board[i];
474
+ if (is_piece(s))
475
+ {
476
+ hash ^= keys[s][i];
477
+ if (get_piece(s) == Pharaoh)
478
+ {
479
+ if (get_owner(s) == Silver)
480
+ pharaoh_loc[Silver] = i;
481
+ else if (get_owner(s) == Red)
482
+ pharaoh_loc[Red] = i;
483
+ }
484
+ }
398
485
  }
399
486
  hashes[0] = hash;
400
487
 
@@ -528,51 +615,3 @@ void print_piece(Square s)
528
615
  else
529
616
  printf("--");
530
617
  }
531
-
532
- void reset_undo()
533
- {
534
- undo_index = 0;
535
- for (int i = 0; i < MAX_DEPTH; i++)
536
- {
537
- undo_moves[i] = 0;
538
- undo_capture_indices[i] = 0;
539
- undo_capture_squares[i] = 0;
540
- }
541
- }
542
-
543
- void init_zobrist()
544
- {
545
- for (int i = 0; i < 0xFF; i++)
546
- {
547
- for (int j = 0; j < 120; j++)
548
- {
549
- keys[i][j] = random_number();
550
- }
551
- }
552
- turn_key = random_number();
553
- }
554
-
555
- bool is_move_legal(Move move)
556
- {
557
- int start = get_start(move);
558
- int end = get_end(move);
559
- if (is_piece(board[start]) && get_owner(board[start]) == whose_turn)
560
- {
561
- if (!is_piece(board[end]) || get_rotation(move) != 0)
562
- return true;
563
- else if (is_piece(board[end]) && get_piece(board[start]) == Scarab && get_piece(board[end]) < 3)
564
- return true;
565
- }
566
- return false;
567
- }
568
-
569
- uint64_t get_board_hash()
570
- {
571
- uint64_t hash = 0;
572
- for (int i = 0; i < 120; i++)
573
- {
574
- if (board[i] > 0)
575
- hash ^= keys[board[i]][i];
576
- }
577
- return hash;
578
- }
@@ -33,12 +33,15 @@ enum Orientation
33
33
  };
34
34
 
35
35
  extern enum Player whose_turn;
36
+ extern enum Player starter;
36
37
 
37
38
  // north, east, south, west, diagonals
38
39
  static const int directions[8] = {-12, 1, 12, -1, (12 + 1), (12 - 1), (-12 + 1), (-12 - 1)};
39
40
  static const int rotations[2] = {1, -1};
40
41
  static const int sphinx_loc[2] = {106, 13};
41
42
 
43
+ extern int pharaoh_loc[2];
44
+
42
45
  extern Square board[120];
43
46
  extern Move undo_moves[MAX_DEPTH];
44
47
  extern int undo_capture_indices[MAX_DEPTH];
@@ -95,6 +98,7 @@ extern void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi);
95
98
  extern Move alphabeta_root(int depth, enum Player player);
96
99
  extern int alphabeta(int depth, enum Player player, int alpha, int beta);
97
100
  extern int calculate_score();
101
+ extern int distance_from_pharaoh(int i, int p);
98
102
 
99
103
  extern void make_move(Move move);
100
104
  extern void undo_move();
@@ -166,6 +170,7 @@ extern int move_num;
166
170
  extern bool checkmate;
167
171
 
168
172
  extern void init_zobrist();
173
+ extern uint64_t get_board_hash();
169
174
  static uint64_t seed = 1070372;
170
175
  static inline uint64_t random_number()
171
176
  {
@@ -192,6 +197,5 @@ typedef struct HashEntry
192
197
  extern HashEntry table[TABLE_SIZE];
193
198
  static inline HashEntry *search_table(uint64_t key) { return &table[key % TABLE_SIZE]; };
194
199
  extern void insert_table(uint64_t key, int depth, int flag, int score, Move move);
195
- extern uint64_t get_board_hash();
196
200
 
197
201
  #endif // KHET_LIB_H_INCLUDED extern uint64_t get_board_hash();
@@ -1,3 +1,3 @@
1
1
  module KhetAI
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: khetai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - jkugs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-24 00:00:00.000000000 Z
11
+ date: 2022-03-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -27,6 +27,9 @@ files:
27
27
  - Rakefile
28
28
  - bin/console
29
29
  - bin/setup
30
+ - ext/khetai/dev/CMakeLists.txt
31
+ - ext/khetai/dev/main.c
32
+ - ext/khetai/dev/main.rb
30
33
  - ext/khetai/extconf.rb
31
34
  - ext/khetai/khetai.c
32
35
  - ext/khetai/khetai_lib.c