khetai 0.1.7 → 0.2.0

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +36 -22
  5. data/ext/khetai/dev/README.md +15 -0
  6. data/ext/khetai/dev/fltk-ui/Makefile +65 -0
  7. data/ext/khetai/dev/fltk-ui/Makefile.khetai +46 -0
  8. data/ext/khetai/dev/fltk-ui/README.md +34 -0
  9. data/ext/khetai/dev/fltk-ui/ai_loader.cpp +93 -0
  10. data/ext/khetai/dev/fltk-ui/ai_loader.h +33 -0
  11. data/ext/khetai/dev/fltk-ui/assets/anubis_red_e.png +0 -0
  12. data/ext/khetai/dev/fltk-ui/assets/anubis_red_n.png +0 -0
  13. data/ext/khetai/dev/fltk-ui/assets/anubis_red_s.png +0 -0
  14. data/ext/khetai/dev/fltk-ui/assets/anubis_red_w.png +0 -0
  15. data/ext/khetai/dev/fltk-ui/assets/anubis_silver_e.png +0 -0
  16. data/ext/khetai/dev/fltk-ui/assets/anubis_silver_n.png +0 -0
  17. data/ext/khetai/dev/fltk-ui/assets/anubis_silver_s.png +0 -0
  18. data/ext/khetai/dev/fltk-ui/assets/anubis_silver_w.png +0 -0
  19. data/ext/khetai/dev/fltk-ui/assets/example_board.png +0 -0
  20. data/ext/khetai/dev/fltk-ui/assets/laser_red_e.png +0 -0
  21. data/ext/khetai/dev/fltk-ui/assets/laser_red_n.png +0 -0
  22. data/ext/khetai/dev/fltk-ui/assets/laser_red_s.png +0 -0
  23. data/ext/khetai/dev/fltk-ui/assets/laser_red_w.png +0 -0
  24. data/ext/khetai/dev/fltk-ui/assets/laser_silver_e.png +0 -0
  25. data/ext/khetai/dev/fltk-ui/assets/laser_silver_n.png +0 -0
  26. data/ext/khetai/dev/fltk-ui/assets/laser_silver_s.png +0 -0
  27. data/ext/khetai/dev/fltk-ui/assets/laser_silver_w.png +0 -0
  28. data/ext/khetai/dev/fltk-ui/assets/pharaoh_red.png +0 -0
  29. data/ext/khetai/dev/fltk-ui/assets/pharaoh_silver.png +0 -0
  30. data/ext/khetai/dev/fltk-ui/assets/pyramid_red_e.png +0 -0
  31. data/ext/khetai/dev/fltk-ui/assets/pyramid_red_n.png +0 -0
  32. data/ext/khetai/dev/fltk-ui/assets/pyramid_red_s.png +0 -0
  33. data/ext/khetai/dev/fltk-ui/assets/pyramid_red_w.png +0 -0
  34. data/ext/khetai/dev/fltk-ui/assets/pyramid_silver_e.png +0 -0
  35. data/ext/khetai/dev/fltk-ui/assets/pyramid_silver_n.png +0 -0
  36. data/ext/khetai/dev/fltk-ui/assets/pyramid_silver_s.png +0 -0
  37. data/ext/khetai/dev/fltk-ui/assets/pyramid_silver_w.png +0 -0
  38. data/ext/khetai/dev/fltk-ui/assets/scarab_red_e.png +0 -0
  39. data/ext/khetai/dev/fltk-ui/assets/scarab_red_n.png +0 -0
  40. data/ext/khetai/dev/fltk-ui/assets/scarab_red_s.png +0 -0
  41. data/ext/khetai/dev/fltk-ui/assets/scarab_red_w.png +0 -0
  42. data/ext/khetai/dev/fltk-ui/assets/scarab_silver_e.png +0 -0
  43. data/ext/khetai/dev/fltk-ui/assets/scarab_silver_n.png +0 -0
  44. data/ext/khetai/dev/fltk-ui/assets/scarab_silver_s.png +0 -0
  45. data/ext/khetai/dev/fltk-ui/assets/scarab_silver_w.png +0 -0
  46. data/ext/khetai/dev/fltk-ui/build_khetai.sh +9 -0
  47. data/ext/khetai/dev/fltk-ui/game_board.cpp +896 -0
  48. data/ext/khetai/dev/fltk-ui/game_board.h +105 -0
  49. data/ext/khetai/dev/fltk-ui/game_board_util.cpp +119 -0
  50. data/ext/khetai/dev/fltk-ui/game_board_util.h +15 -0
  51. data/ext/khetai/dev/fltk-ui/khet.cpp +59 -0
  52. data/ext/khetai/dev/main.c +8 -7
  53. data/ext/khetai/dev/main.rb +9 -10
  54. data/ext/khetai/khetai.c +22 -6
  55. data/ext/khetai/khetai_lib.c +24 -13
  56. data/ext/khetai/khetai_lib.h +51 -24
  57. data/lib/khetai/version.rb +1 -1
  58. metadata +50 -4
  59. data/README_ORIGINAL.md +0 -40
@@ -0,0 +1,105 @@
1
+ #ifndef GAMEBOARD_H
2
+ #define GAMEBOARD_H
3
+
4
+ #include "ai_loader.h"
5
+
6
+ #include <FL/Fl_Widget.H>
7
+ #include <FL/Fl_PNG_Image.H>
8
+ #include <FL/Fl_Input.H>
9
+ #include <string>
10
+ #include <vector>
11
+ #include <unordered_map>
12
+
13
+ class GameBoard : public Fl_Widget
14
+ {
15
+ public:
16
+ GameBoard(int X, int Y, int W, int H, const char *L = 0);
17
+ Fl_Input *max_time_input, *max_depth_input;
18
+ void draw() override;
19
+ int handle(int event) override;
20
+ void init(const std::vector<std::vector<std::string>> &pieces);
21
+
22
+ enum Color
23
+ {
24
+ SILVER = 1,
25
+ RED = 2
26
+ };
27
+ enum LaserDirection
28
+ {
29
+ NORTH = 1,
30
+ EAST = 2,
31
+ SOUTH = 3,
32
+ WEST = 4
33
+ };
34
+ enum PieceType
35
+ {
36
+ ANUBIS,
37
+ PYRAMID,
38
+ SCARAB,
39
+ PHARAOH,
40
+ SPHINX
41
+ };
42
+ enum PieceOrientation
43
+ {
44
+ ORIENT_NORTH,
45
+ ORIENT_EAST,
46
+ ORIENT_SOUTH,
47
+ ORIENT_WEST
48
+ };
49
+ enum ReflectionResult
50
+ {
51
+ RESULT_DEAD,
52
+ RESULT_ABSORBED,
53
+ RESULT_EAST,
54
+ RESULT_WEST,
55
+ RESULT_SOUTH,
56
+ RESULT_NORTH
57
+ };
58
+ enum MovePermission
59
+ {
60
+ S = 1,
61
+ R = 2,
62
+ B = 3
63
+ };
64
+
65
+ static std::string getPieceFilename(char piece, int direction);
66
+ static std::pair<PieceType, PieceOrientation> getPieceTypeAndOrientation(const std::string &piece_str);
67
+ static void laser_timer_cb(void *data);
68
+
69
+ private:
70
+ AILoader ai_loader;
71
+ int rows = 8, cols = 10, clicked_row = -1, clicked_col = -1, square_selected_num = -1;
72
+ int cell_width, cell_height;
73
+ bool square_selected = false;
74
+ bool laser_active = false;
75
+ int laser_step = 3;
76
+ LaserDirection laser_direction;
77
+ float laser_y, laser_x;
78
+ bool remove_piece = false;
79
+ int laser_square_row, laser_square_col, remove_row, remove_col;
80
+ int l_idx;
81
+ std::vector<std::vector<std::string>> board_pieces;
82
+ std::vector<Fl_Image *> piece_images;
83
+ std::vector<std::tuple<int, int, int, int>> laser_path;
84
+ std::vector<std::tuple<int, int, int, int>> laser_path_squares;
85
+
86
+ static std::unordered_map<LaserDirection, std::unordered_map<PieceType, std::unordered_map<PieceOrientation, ReflectionResult>>> reflections_map;
87
+ static std::unordered_map<char, std::string> piece_map;
88
+ static std::unordered_map<int, int> rotate_left_map;
89
+ static std::unordered_map<int, int> rotate_right_map;
90
+ static const MovePermission move_permissions[8][10];
91
+
92
+ void drawInnerSquares();
93
+ void rotateSelectedPiece(bool clockwise);
94
+ void moveSelectedPiece(int end_square);
95
+ void swapPieces(int swap_square);
96
+ void deletePiece();
97
+ void resetPieces();
98
+ void fireLaser(Color color);
99
+ void updateLaserPosition();
100
+ void calculateLaserPathSquares();
101
+ bool squareContainsPiece(int square_num);
102
+ void rebuildReloadKhetAILib();
103
+ };
104
+
105
+ #endif
@@ -0,0 +1,119 @@
1
+ #include "game_board_util.h"
2
+
3
+ #include <iostream>
4
+ #include <cstring>
5
+
6
+ std::vector<std::string> flatten_2d_vector_with_buffer(const std::vector<std::vector<std::string>> &vec2d)
7
+ {
8
+ size_t new_rows = vec2d.size() + 2;
9
+ size_t new_cols = vec2d.empty() ? 0 : vec2d[0].size() + 2;
10
+
11
+ std::vector<std::vector<std::string>> buffered_vec2d(new_rows, std::vector<std::string>(new_cols, "--"));
12
+
13
+ for (size_t i = 0; i < vec2d.size(); ++i)
14
+ {
15
+ for (size_t j = 0; j < vec2d[i].size(); ++j)
16
+ {
17
+ buffered_vec2d[i + 1][j + 1] = vec2d[i][j];
18
+ }
19
+ }
20
+
21
+ std::vector<std::string> flattened;
22
+ for (const auto &row : buffered_vec2d)
23
+ {
24
+ for (const auto &elem : row)
25
+ {
26
+ flattened.push_back(elem);
27
+ }
28
+ }
29
+
30
+ return flattened;
31
+ }
32
+
33
+ char **vector_to_c_array(const std::vector<std::string> &vec)
34
+ {
35
+ char **c_array = new char *[vec.size()];
36
+ for (size_t i = 0; i < vec.size(); ++i)
37
+ {
38
+ c_array[i] = new char[vec[i].size() + 1];
39
+ std::strcpy(c_array[i], vec[i].c_str());
40
+ }
41
+
42
+ return c_array;
43
+ }
44
+
45
+ void free_c_array(char **c_array, size_t size)
46
+ {
47
+ for (size_t i = 0; i < size; ++i)
48
+ {
49
+ delete[] c_array[i];
50
+ }
51
+ delete[] c_array;
52
+ }
53
+
54
+ Move call_ai_move(AILoader &ai_loader, const std::vector<std::vector<std::string>> &board_pieces, Player player, int max_depth, int max_time)
55
+ {
56
+ auto init_zobrist = ai_loader.get_init_zobrist();
57
+ auto setup_board = ai_loader.get_setup_board();
58
+ auto print_board = ai_loader.get_print_board();
59
+ auto set_time_parameters = ai_loader.get_set_time_parameters();
60
+ auto alphabeta_root = ai_loader.get_alphabeta_root();
61
+ auto make_move = ai_loader.get_make_move();
62
+ auto get_start = ai_loader.get_get_start();
63
+ auto get_end = ai_loader.get_get_end();
64
+ auto get_rotation = ai_loader.get_get_rotation();
65
+
66
+ char **c_board = vector_to_c_array(flatten_2d_vector_with_buffer(board_pieces));
67
+
68
+ init_zobrist();
69
+ srand((unsigned)time(NULL));
70
+
71
+ setup_board(c_board);
72
+ printf("\nStarting Board:\n");
73
+ print_board();
74
+
75
+ time_t start_time = time(NULL);
76
+ set_time_parameters(max_time, start_time);
77
+
78
+ int depth = 1;
79
+ Move best_move = (Move)0;
80
+ Move current_move = (Move)0;
81
+ while (depth <= max_depth)
82
+ {
83
+ printf("\nDEPTH: %-3d-> ", depth);
84
+ current_move = alphabeta_root(depth, player);
85
+ printf("MOVE -> START: %d, END: %d, ROTATION: %d\n", get_start(current_move), get_end(current_move), get_rotation(current_move));
86
+ if ((time(NULL) - start_time < max_time))
87
+ best_move = current_move;
88
+ else
89
+ break;
90
+ depth++;
91
+ }
92
+ make_move(best_move);
93
+
94
+ printf("\n========================\n\n");
95
+ printf("Ending Board:\n");
96
+ print_board();
97
+
98
+ printf("\nDEPTH: %d\n", depth - 1);
99
+
100
+ int start = get_start(best_move);
101
+ int end = get_end(best_move);
102
+ int rotation = get_rotation(best_move);
103
+ std::cout << "START: " << start << ", END: " << end << ", ROTATION: " << rotation << std::endl;
104
+ return best_move;
105
+ }
106
+
107
+ void get_row_col(int index, int &row, int &col)
108
+ {
109
+ int border_width = 1;
110
+ int width_with_border = 10 + 2 * border_width;
111
+
112
+ int adjusted_index = index;
113
+
114
+ int row_with_border = adjusted_index / width_with_border;
115
+ int col_with_border = adjusted_index % width_with_border;
116
+
117
+ row = row_with_border - border_width;
118
+ col = col_with_border - border_width;
119
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef GAME_BOARD_UTIL_H
2
+ #define GAME_BOARD_UTIL_H
3
+
4
+ #include "ai_loader.h"
5
+
6
+ #include <vector>
7
+ #include <string>
8
+
9
+ std::vector<std::string> flatten_2d_vector_with_buffer(const std::vector<std::vector<std::string>> &vec2d);
10
+ char **vector_to_c_array(const std::vector<std::string> &vec);
11
+ void free_c_array(char **c_array, size_t size);
12
+ Move call_ai_move(AILoader &ai_loader, const std::vector<std::vector<std::string>> &board_pieces, Player player, int max_depth, int _max_time);
13
+ void get_row_col(int index, int &row, int &col);
14
+
15
+ #endif
@@ -0,0 +1,59 @@
1
+ #include <FL/Fl.H>
2
+ #include <FL/Fl_Double_Window.H>
3
+ #include <FL/Fl_Input.H>
4
+ #include <FL/Fl_Int_Input.H>
5
+ #include <FL/Fl_Box.H>
6
+ #include "game_board.h"
7
+
8
+ class PositiveIntInput : public Fl_Int_Input
9
+ {
10
+ public:
11
+ PositiveIntInput(int X, int Y, int W, int H, const char *L = 0)
12
+ : Fl_Int_Input(X, Y, W, H, L) {}
13
+
14
+ int handle(int event) override
15
+ {
16
+ int result = Fl_Int_Input::handle(event);
17
+ if (event == FL_KEYDOWN || event == FL_KEYUP || event == FL_PASTE)
18
+ {
19
+ const char *value = this->value();
20
+ if (value[0] == '-')
21
+ {
22
+ this->value("");
23
+ }
24
+ }
25
+ return result;
26
+ }
27
+ };
28
+
29
+ int main(int argc, char **argv)
30
+ {
31
+ Fl_Double_Window *window = new Fl_Double_Window(800, 600, "Khet AI");
32
+ GameBoard *board = new GameBoard(50, 50, 700, 504);
33
+
34
+ std::vector<std::vector<std::string>> init_board = {
35
+ {"L2", "--", "--", "--", "A2", "X2", "A2", "P1", "--", "--"},
36
+ {"--", "--", "P2", "--", "--", "--", "--", "--", "--", "--"},
37
+ {"--", "--", "--", "p3", "--", "--", "--", "--", "--", "--"},
38
+ {"P0", "--", "p2", "--", "S2", "S3", "--", "P1", "--", "p3"},
39
+ {"P1", "--", "p3", "--", "s1", "s0", "--", "P0", "--", "p2"},
40
+ {"--", "--", "--", "--", "--", "--", "P1", "--", "--", "--"},
41
+ {"--", "--", "--", "--", "--", "--", "--", "p0", "--", "--"},
42
+ {"--", "--", "p3", "a0", "x0", "a0", "--", "--", "--", "l0"}};
43
+
44
+ board->init(init_board);
45
+
46
+ Fl_Box *max_time_label = new Fl_Box(50, 10, 80, 30, "Max Time:");
47
+ PositiveIntInput *max_time_input = new PositiveIntInput(125, 15, 30, 20);
48
+ max_time_input->value("5");
49
+ board->max_time_input = max_time_input;
50
+
51
+ Fl_Box *max_depth_label = new Fl_Box(250, 10, 80, 30, "Max Depth:");
52
+ PositiveIntInput *max_depth_input = new PositiveIntInput(325, 15, 30, 20);
53
+ max_depth_input->value("10");
54
+ board->max_depth_input = max_depth_input;
55
+
56
+ window->end();
57
+ window->show(argc, argv);
58
+ return Fl::run();
59
+ }
@@ -15,9 +15,6 @@ char *init_board[120] =
15
15
  "--", "--", "--", "p3", "a0", "x0", "a0", "--", "--", "--", "l0", "--",
16
16
  "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--"};
17
17
 
18
- time_t start_time;
19
- int max_time;
20
-
21
18
  int main()
22
19
  {
23
20
  init_zobrist();
@@ -26,17 +23,21 @@ int main()
26
23
  setup_board(init_board);
27
24
  print_board();
28
25
 
29
- start_time = time(NULL);
30
- max_time = 5;
26
+ time_t start_time = time(NULL);
27
+ int max_time = 5;
28
+ set_time_parameters(max_time, start_time);
31
29
  int max_depth = 25;
32
30
 
33
31
  int depth = 1;
34
32
  Move best_move = (Move)0;
35
33
  Move current_move = (Move)0;
36
- while ((time(NULL) - start_time < max_time) && (depth <= max_depth))
34
+ while (depth <= max_depth)
37
35
  {
38
- best_move = current_move;
39
36
  current_move = alphabeta_root(depth, Red);
37
+ if (time(NULL) - start_time < max_time)
38
+ best_move = current_move;
39
+ else
40
+ break;
40
41
  depth++;
41
42
  }
42
43
  make_move(best_move);
@@ -1,15 +1,14 @@
1
1
  require_relative "../../../lib/khetai/khetai.so"
2
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
- "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--", "--"]
3
+ board = ["L2", "--", "--", "--", "A2", "X2", "A2", "P1", "--", "--",
4
+ "--", "--", "P2", "--", "--", "--", "--", "--", "--", "--",
5
+ "--", "--", "--", "p3", "--", "--", "--", "--", "--", "--",
6
+ "P0", "--", "p2", "--", "S2", "S3", "--", "P1", "--", "p3",
7
+ "P1", "--", "p3", "--", "s1", "s0", "--", "P0", "--", "p2",
8
+ "--", "--", "--", "--", "--", "--", "P1", "--", "--", "--",
9
+ "--", "--", "--", "--", "--", "--", "--", "p0", "--", "--",
10
+ "--", "--", "p3", "a0", "x0", "a0", "--", "--", "--", "l0"]
11
+
13
12
 
14
13
  move = KhetAI.move(board, 1, 6, 5)
15
14
  puts move.to_s
data/ext/khetai/khetai.c CHANGED
@@ -3,28 +3,44 @@
3
3
  #include <time.h>
4
4
  #include "khetai_lib.h"
5
5
 
6
- time_t start_time;
7
- int max_time;
8
-
9
6
  VALUE move(VALUE self, VALUE board_array, VALUE player, VALUE max_depth, VALUE _max_time)
10
7
  {
11
8
  srand((unsigned)time(NULL));
12
9
 
10
+ // khetai_lib assumes an extra level of padding around the board
13
11
  char *init_board[120];
14
12
  unsigned int array_size = (unsigned int)RARRAY_LEN(board_array);
13
+
14
+ // top and bottom row padding
15
+ for (unsigned int i = 0; i < 12; i++)
16
+ {
17
+ init_board[i] = "--";
18
+ init_board[108 + i] = "--";
19
+ }
20
+
21
+ // left and right column padding
22
+ for (unsigned int i = 0; i < 8; i++)
23
+ {
24
+ init_board[12 * (i + 1)] = "--";
25
+ init_board[12 * (i + 2) - 1] = "--";
26
+ }
27
+
28
+ // fill in the rest of the baord passed from ruby
15
29
  for (unsigned int i = 0; i < array_size; i++)
16
30
  {
17
31
  VALUE square = rb_ary_entry(board_array, i);
18
- init_board[i] = StringValueCStr(square);
32
+ init_board[13 + ((i % 10) + ((i / 10) * 12))] = StringValueCStr(square);
19
33
  }
20
34
 
21
35
  reset_undo();
22
36
  init_zobrist();
23
37
  setup_board(init_board);
24
38
 
25
- start_time = time(NULL);
26
- max_time = NUM2INT(_max_time);
39
+ time_t start_time = time(NULL);
40
+ int max_time = NUM2INT(_max_time);
41
+ set_time_parameters(max_time, start_time);
27
42
 
43
+ // iterative deepening
28
44
  int depth = 1;
29
45
  Move best_move = (Move)0;
30
46
  Move current_move = (Move)0;
@@ -4,6 +4,9 @@
4
4
  #include <time.h>
5
5
  #include "khetai_lib.h"
6
6
 
7
+ int max_time;
8
+ time_t start_time;
9
+
7
10
  Square board[120] = {0};
8
11
  int pharaoh_loc[2] = {0};
9
12
  enum Player whose_turn;
@@ -51,6 +54,9 @@ Move alphabeta_root(int depth, enum Player player)
51
54
  if (alpha >= beta)
52
55
  break;
53
56
  }
57
+
58
+ // print final score for testing purposes:
59
+ // printf("SCORE: %-10d\n", best_score);
54
60
  return best_move;
55
61
  }
56
62
 
@@ -91,6 +97,7 @@ int alphabeta(int depth, enum Player player, int alpha, int beta)
91
97
  find_valid_moves(valid_moves, &vi);
92
98
  int best_score = -MAX_SCORE;
93
99
  Move best_move = (Move)0;
100
+
94
101
  for (int i = 0; (i < NUM_VALID_MOVES && (time(NULL) - start_time < max_time)); i++)
95
102
  {
96
103
  if (valid_moves[i] == 0)
@@ -125,7 +132,7 @@ void insert_table(uint64_t key, int depth, int flag, int score, Move move)
125
132
  HashEntry *entry = search_table(key);
126
133
  if (entry->key != 0)
127
134
  {
128
- if (depth > entry->depth)
135
+ if (depth < entry->depth)
129
136
  {
130
137
  entry->key = key;
131
138
  entry->depth = depth;
@@ -167,8 +174,9 @@ int calculate_score()
167
174
  value += rand() % 20;
168
175
  break;
169
176
  case Scarab:
170
- value += 100 / (distance_from_pharaoh(i, pharaoh_loc[opposite_player(get_owner(s))])) * 10;
171
- value += rand() % 10;
177
+ int max_distance = 16;
178
+ int base_score = 1000;
179
+ value += (max_distance - distance_from_pharaoh(i, pharaoh_loc[opposite_player(get_owner(s))])) * base_score / max_distance;
172
180
  break;
173
181
  case Pharaoh:
174
182
  value += pharaoh_score;
@@ -225,7 +233,7 @@ void make_move(Move move)
225
233
  hash ^= keys[board[start]][start];
226
234
 
227
235
  if (get_piece(moving_piece) == Pharaoh)
228
- pharaoh_loc[whose_turn] = end;
236
+ pharaoh_loc[get_owner(moving_piece)] = end;
229
237
  }
230
238
 
231
239
  undo_moves[undo_index] = new_move(end, start, -rotation);
@@ -314,7 +322,7 @@ void undo_move()
314
322
  board[end] = moving_piece;
315
323
 
316
324
  if (get_piece(moving_piece) == Pharaoh)
317
- pharaoh_loc[get_owner(board[end])] = end;
325
+ pharaoh_loc[get_owner(moving_piece)] = end;
318
326
  }
319
327
  checkmate = false;
320
328
  }
@@ -375,14 +383,7 @@ void find_valid_scarab_moves(int i, Move *valid_moves, int *vi)
375
383
  int dest = i + directions[j];
376
384
  if (can_move[whose_turn][dest])
377
385
  {
378
- if (is_piece(board[dest]))
379
- {
380
- if (get_piece(board[dest]) == Anubis || get_piece(board[dest]) == Pyramid)
381
- {
382
- valid_moves[(*vi)++] = new_move(i, dest, 0);
383
- }
384
- }
385
- else
386
+ if (!is_piece(board[dest]) || get_piece(board[dest]) != Pharaoh)
386
387
  {
387
388
  valid_moves[(*vi)++] = new_move(i, dest, 0);
388
389
  }
@@ -615,3 +616,13 @@ void print_piece(Square s)
615
616
  else
616
617
  printf("--");
617
618
  }
619
+
620
+ int get_start_wrapper(Move move) { return get_start(move); }
621
+ int get_end_wrapper(Move move) { return get_end(move); }
622
+ int get_rotation_wrapper(Move move) { return get_rotation(move); }
623
+
624
+ void set_time_parameters(int _max_time, time_t _start_time)
625
+ {
626
+ max_time = _max_time;
627
+ start_time = _start_time;
628
+ }
@@ -4,6 +4,10 @@
4
4
  #include <stdint.h>
5
5
  #include <stdbool.h>
6
6
 
7
+ #ifdef __cplusplus
8
+ #include <ctime>
9
+ #endif
10
+
7
11
  typedef uint8_t Square;
8
12
  typedef uint32_t Move;
9
13
 
@@ -83,27 +87,42 @@ static const int on_board[120] = {
83
87
  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
84
88
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
85
89
 
86
- extern void setup_board(char *init_board[120]);
87
- extern Square str_to_square(char *str);
88
- extern void print_board();
89
- extern void print_piece(Square s);
90
- extern void reset_undo();
90
+ extern time_t start_time;
91
+ extern int max_time;
92
+
93
+ #ifdef __cplusplus
94
+ extern "C"
95
+ {
96
+ #endif
97
+
98
+ void set_time_parameters(int _max_time, time_t _start_time);
99
+ void reset_undo();
100
+ void init_zobrist();
101
+ void setup_board(char *board[]);
102
+ Move alphabeta_root(int depth, enum Player player);
103
+ void make_move(Move move);
104
+ void print_board();
105
+
106
+ #ifdef __cplusplus
107
+ }
108
+ #endif
109
+
110
+ Square str_to_square(char *str);
111
+ void print_piece(Square s);
91
112
 
92
- extern void find_valid_moves(Move *valid_moves, int *vi);
93
- extern void find_valid_anubis_pyramid_moves(int i, Move *valid_moves, int *vi);
94
- extern void find_valid_scarab_moves(int i, Move *valid_moves, int *vi);
95
- extern void find_valid_pharaoh_moves(int i, Move *valid_moves, int *vi);
96
- extern void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi);
113
+ void find_valid_moves(Move *valid_moves, int *vi);
114
+ void find_valid_anubis_pyramid_moves(int i, Move *valid_moves, int *vi);
115
+ void find_valid_scarab_moves(int i, Move *valid_moves, int *vi);
116
+ void find_valid_pharaoh_moves(int i, Move *valid_moves, int *vi);
117
+ void find_valid_sphinx_moves(int i, Move *valid_moves, int *vi);
97
118
 
98
- extern Move alphabeta_root(int depth, enum Player player);
99
- extern int alphabeta(int depth, enum Player player, int alpha, int beta);
100
- extern int calculate_score();
101
- extern int distance_from_pharaoh(int i, int p);
119
+ int alphabeta(int depth, enum Player player, int alpha, int beta);
120
+ int calculate_score();
121
+ int distance_from_pharaoh(int i, int p);
102
122
 
103
- extern void make_move(Move move);
104
- extern void undo_move();
105
- extern void fire_laser(uint64_t *hash);
106
- extern bool is_move_legal(Move move);
123
+ void undo_move();
124
+ void fire_laser(uint64_t *hash);
125
+ bool is_move_legal(Move move);
107
126
 
108
127
  static inline bool is_piece(Square s) { return s > 0; }
109
128
 
@@ -116,6 +135,17 @@ static inline int get_start(Move m) { return m >> 1 & 0x7F; }
116
135
  static inline int get_end(Move m) { return m >> 8 & 0x7F; }
117
136
  static inline int get_rotation(Move m) { return (m >> 15 & 0x3) - 2; }
118
137
 
138
+ #ifdef __cplusplus
139
+ extern "C"
140
+ {
141
+ #endif
142
+ int get_start_wrapper(Move move);
143
+ int get_end_wrapper(Move move);
144
+ int get_rotation_wrapper(Move move);
145
+ #ifdef __cplusplus
146
+ }
147
+ #endif
148
+
119
149
  static inline Square rotate(Square s, int rotation)
120
150
  {
121
151
  int orientation = get_orientation(s);
@@ -161,16 +191,13 @@ static const int reflections[4][5][4] = {
161
191
  {Dead, Dead, Dead, Dead},
162
192
  {Absorbed, Absorbed, Absorbed, Absorbed}}};
163
193
 
164
- extern time_t start_time;
165
- extern int max_time;
166
194
  extern uint64_t keys[0xFF][120];
167
195
  extern uint64_t hashes[MAX_DEPTH];
168
196
  extern uint64_t turn_key;
169
197
  extern int move_num;
170
198
  extern bool checkmate;
171
199
 
172
- extern void init_zobrist();
173
- extern uint64_t get_board_hash();
200
+ uint64_t get_board_hash();
174
201
  static uint64_t seed = 1070372;
175
202
  static inline uint64_t random_number()
176
203
  {
@@ -196,6 +223,6 @@ typedef struct HashEntry
196
223
 
197
224
  extern HashEntry table[TABLE_SIZE];
198
225
  static inline HashEntry *search_table(uint64_t key) { return &table[key % TABLE_SIZE]; };
199
- extern void insert_table(uint64_t key, int depth, int flag, int score, Move move);
226
+ void insert_table(uint64_t key, int depth, int flag, int score, Move move);
200
227
 
201
- #endif // KHET_LIB_H_INCLUDED extern uint64_t get_board_hash();
228
+ #endif // KHET_LIB_H_INCLUDED
@@ -1,3 +1,3 @@
1
1
  module KhetAI
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.0"
3
3
  end