khetai 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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