khetai 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.clang-format +14 -0
- data/Gemfile.lock +1 -1
- data/ext/khetai/dev/fltk-ui/ai_loader.cpp +20 -40
- data/ext/khetai/dev/fltk-ui/ai_loader.h +4 -5
- data/ext/khetai/dev/fltk-ui/game_board.cpp +98 -204
- data/ext/khetai/dev/fltk-ui/game_board.h +12 -19
- data/ext/khetai/dev/fltk-ui/game_board_util.cpp +13 -25
- data/ext/khetai/dev/fltk-ui/game_board_util.h +1 -1
- data/ext/khetai/dev/fltk-ui/khet.cpp +9 -14
- data/ext/khetai/dev/main.c +4 -6
- data/ext/khetai/khetai.c +16 -31
- data/ext/khetai/khetai_lib.c +220 -257
- data/ext/khetai/khetai_lib.h +88 -67
- data/lib/khetai/version.rb +1 -1
- metadata +3 -2
@@ -1,22 +1,20 @@
|
|
1
1
|
#include "game_board.h"
|
2
|
-
#include "game_board_util.h"
|
3
2
|
#include "../../khetai_lib.h"
|
3
|
+
#include "game_board_util.h"
|
4
4
|
|
5
|
-
#include <FL/fl_draw.H>
|
6
5
|
#include <FL/Fl.H>
|
7
|
-
#include <
|
6
|
+
#include <FL/fl_draw.H>
|
8
7
|
#include <cstring>
|
8
|
+
#include <iostream>
|
9
9
|
|
10
10
|
GameBoard::GameBoard(int X, int Y, int W, int H, const char *L)
|
11
11
|
: Fl_Widget(X, Y, W, H, L),
|
12
|
-
ai_loader("./libkhetai.so")
|
13
|
-
{
|
12
|
+
ai_loader("./libkhetai.so") {
|
14
13
|
cell_width = w() / cols;
|
15
14
|
cell_height = h() / rows;
|
16
15
|
}
|
17
16
|
|
18
|
-
void GameBoard::draw()
|
19
|
-
{
|
17
|
+
void GameBoard::draw() {
|
20
18
|
// background
|
21
19
|
fl_color(FL_WHITE);
|
22
20
|
fl_rectf(x(), y(), w(), h());
|
@@ -25,15 +23,13 @@ void GameBoard::draw()
|
|
25
23
|
fl_color(FL_BLACK);
|
26
24
|
|
27
25
|
// vertical lines
|
28
|
-
for (int i = 0; i <= cols; ++i)
|
29
|
-
{
|
26
|
+
for (int i = 0; i <= cols; ++i) {
|
30
27
|
int current_x = x() + (cell_width * i);
|
31
28
|
fl_line(current_x, y(), current_x, y() + h());
|
32
29
|
}
|
33
30
|
|
34
31
|
// horizontal lines
|
35
|
-
for (int j = 0; j <= rows; ++j)
|
36
|
-
{
|
32
|
+
for (int j = 0; j <= rows; ++j) {
|
37
33
|
int current_y = y() + (cell_height * j);
|
38
34
|
fl_line(x(), current_y, x() + w(), current_y);
|
39
35
|
}
|
@@ -42,51 +38,41 @@ void GameBoard::draw()
|
|
42
38
|
drawInnerSquares();
|
43
39
|
|
44
40
|
// highlight selected square
|
45
|
-
if (square_selected)
|
46
|
-
{
|
41
|
+
if (square_selected) {
|
47
42
|
fl_color(FL_YELLOW);
|
48
43
|
fl_rectf((x() + clicked_col * cell_width) + 1, (y() + clicked_row * cell_height) + 1, cell_width - 1, cell_height - 1);
|
49
44
|
}
|
50
45
|
|
51
46
|
// draw laser
|
52
|
-
if (laser_active)
|
53
|
-
{
|
47
|
+
if (laser_active) {
|
54
48
|
fl_color(FL_RED);
|
55
|
-
for (auto &segment : laser_path)
|
56
|
-
{
|
49
|
+
for (auto &segment : laser_path) {
|
57
50
|
fl_line(std::get<0>(segment), std::get<1>(segment), std::get<2>(segment), std::get<3>(segment));
|
58
51
|
}
|
59
52
|
}
|
60
53
|
|
61
54
|
// draw pieces
|
62
|
-
for (int i = 0; i < rows; ++i)
|
63
|
-
|
64
|
-
for (int j = 0; j < cols; ++j)
|
65
|
-
{
|
55
|
+
for (int i = 0; i < rows; ++i) {
|
56
|
+
for (int j = 0; j < cols; ++j) {
|
66
57
|
int piece_index = i * cols + j;
|
67
|
-
if (piece_images[piece_index] != nullptr)
|
68
|
-
{
|
58
|
+
if (piece_images[piece_index] != nullptr) {
|
69
59
|
piece_images[piece_index]->draw(x() + j * cell_width, y() + i * cell_height, cell_width, cell_height);
|
70
60
|
}
|
71
61
|
}
|
72
62
|
}
|
73
63
|
}
|
74
64
|
|
75
|
-
void GameBoard::drawInnerSquares()
|
76
|
-
{
|
65
|
+
void GameBoard::drawInnerSquares() {
|
77
66
|
static const Fl_Color SILVER = fl_rgb_color(160, 160, 160);
|
78
67
|
static const Fl_Color DARK_RED = fl_rgb_color(178, 34, 34);
|
79
|
-
for (int row = 0; row < rows; ++row)
|
80
|
-
|
81
|
-
for (int col = 0; col < cols; ++col)
|
82
|
-
{
|
68
|
+
for (int row = 0; row < rows; ++row) {
|
69
|
+
for (int col = 0; col < cols; ++col) {
|
83
70
|
int padding_x = cell_width / 6;
|
84
71
|
int padding_y = cell_height / 6;
|
85
72
|
int square_width = cell_width - (2 * padding_x);
|
86
73
|
int square_height = cell_height - (2 * padding_y);
|
87
74
|
|
88
|
-
switch (move_permissions[row][col])
|
89
|
-
{
|
75
|
+
switch (move_permissions[row][col]) {
|
90
76
|
case S:
|
91
77
|
fl_color(SILVER);
|
92
78
|
fl_line_style(FL_SOLID, 1);
|
@@ -111,13 +97,10 @@ void GameBoard::drawInnerSquares()
|
|
111
97
|
fl_line_style(0);
|
112
98
|
}
|
113
99
|
|
114
|
-
int GameBoard::handle(int event)
|
115
|
-
{
|
100
|
+
int GameBoard::handle(int event) {
|
116
101
|
// std::cout << "EVENT: " event << std::endl;
|
117
|
-
switch (event)
|
118
|
-
{
|
119
|
-
case FL_PUSH:
|
120
|
-
{
|
102
|
+
switch (event) {
|
103
|
+
case FL_PUSH: {
|
121
104
|
int clicked_x = Fl::event_x() - x();
|
122
105
|
int clicked_y = Fl::event_y() - y();
|
123
106
|
|
@@ -126,25 +109,17 @@ int GameBoard::handle(int event)
|
|
126
109
|
|
127
110
|
int clicked_num = (clicked_row * cols) + clicked_col;
|
128
111
|
|
129
|
-
if (square_selected && square_selected_num == clicked_num)
|
130
|
-
{
|
112
|
+
if (square_selected && square_selected_num == clicked_num) {
|
131
113
|
square_selected = false;
|
132
114
|
square_selected_num = -1;
|
133
|
-
}
|
134
|
-
|
135
|
-
|
136
|
-
{
|
137
|
-
if (squareContainsPiece(clicked_num))
|
138
|
-
{
|
115
|
+
} else if (square_selected && square_selected_num != clicked_num &&
|
116
|
+
squareContainsPiece(square_selected_num) && clicked_num != 0 && clicked_num != 79) {
|
117
|
+
if (squareContainsPiece(clicked_num)) {
|
139
118
|
swapPieces(clicked_num);
|
140
|
-
}
|
141
|
-
else
|
142
|
-
{
|
119
|
+
} else {
|
143
120
|
moveSelectedPiece(clicked_num);
|
144
121
|
}
|
145
|
-
}
|
146
|
-
else if (squareContainsPiece(clicked_num))
|
147
|
-
{
|
122
|
+
} else if (squareContainsPiece(clicked_num)) {
|
148
123
|
square_selected = true;
|
149
124
|
square_selected_num = clicked_num;
|
150
125
|
}
|
@@ -152,39 +127,32 @@ int GameBoard::handle(int event)
|
|
152
127
|
redraw();
|
153
128
|
return 1;
|
154
129
|
}
|
155
|
-
case FL_KEYUP:
|
156
|
-
{
|
130
|
+
case FL_KEYUP: {
|
157
131
|
int key = Fl::event_key();
|
158
132
|
int state = Fl::event_state();
|
159
133
|
|
160
|
-
if (key == 'r')
|
161
|
-
{
|
134
|
+
if (key == 'r') {
|
162
135
|
resetPieces();
|
163
|
-
}
|
164
|
-
else if (key == FL_Enter)
|
165
|
-
{
|
136
|
+
} else if (key == FL_Enter) {
|
166
137
|
const char *max_time_value = max_time_input->value();
|
167
|
-
if (!max_time_value || max_time_value[0] == '\0')
|
168
|
-
{
|
138
|
+
if (!max_time_value || max_time_value[0] == '\0') {
|
169
139
|
max_time_input->value("5");
|
170
140
|
max_time_value = max_time_input->value();
|
171
141
|
}
|
172
142
|
int max_time = std::atoi(max_time_value);
|
173
143
|
|
174
144
|
const char *max_depth_value = max_depth_input->value();
|
175
|
-
if (!max_depth_value || max_depth_value[0] == '\0')
|
176
|
-
|
177
|
-
max_depth_input->value("10");
|
145
|
+
if (!max_depth_value || max_depth_value[0] == '\0') {
|
146
|
+
max_depth_input->value("25");
|
178
147
|
max_depth_value = max_depth_input->value();
|
179
148
|
}
|
180
149
|
int max_depth = std::atoi(max_depth_value);
|
181
|
-
if (max_depth < 2)
|
182
|
-
{
|
150
|
+
if (max_depth < 2) {
|
183
151
|
max_depth_input->value("2");
|
184
152
|
max_depth = 2;
|
185
153
|
}
|
186
154
|
|
187
|
-
Move move = call_ai_move(ai_loader, board_pieces,
|
155
|
+
Move move = call_ai_move(ai_loader, board_pieces, Player::RED, max_depth, max_time);
|
188
156
|
int start = get_start(move);
|
189
157
|
int end = get_end(move);
|
190
158
|
int rotation = get_rotation(move);
|
@@ -198,31 +166,21 @@ int GameBoard::handle(int event)
|
|
198
166
|
|
199
167
|
square_selected_num = start_num;
|
200
168
|
|
201
|
-
if (board_pieces[end_row][end_col] == "--")
|
202
|
-
{
|
169
|
+
if (board_pieces[end_row][end_col] == "--") {
|
203
170
|
moveSelectedPiece(end_num);
|
204
|
-
}
|
205
|
-
else if (start_num != end_num && board_pieces[end_row][end_col] != "--")
|
206
|
-
{
|
171
|
+
} else if (start_num != end_num && board_pieces[end_row][end_col] != "--") {
|
207
172
|
swapPieces(end_num);
|
208
|
-
}
|
209
|
-
else if (start_num == end_num && rotation != 0)
|
210
|
-
{
|
173
|
+
} else if (start_num == end_num && rotation != 0) {
|
211
174
|
bool clockwise = rotation == 1;
|
212
175
|
rotateSelectedPiece(clockwise);
|
213
176
|
}
|
214
177
|
|
215
178
|
fireLaser(RED);
|
216
|
-
}
|
217
|
-
else if (key == 'k' && (state & FL_SHIFT))
|
218
|
-
{
|
179
|
+
} else if (key == 'k' && (state & FL_SHIFT)) {
|
219
180
|
rebuildReloadKhetAILib();
|
220
181
|
return 1;
|
221
|
-
}
|
222
|
-
|
223
|
-
{
|
224
|
-
switch (key)
|
225
|
-
{
|
182
|
+
} else if (square_selected) {
|
183
|
+
switch (key) {
|
226
184
|
case FL_Left:
|
227
185
|
rotateSelectedPiece(false);
|
228
186
|
break;
|
@@ -233,14 +191,13 @@ int GameBoard::handle(int event)
|
|
233
191
|
deletePiece();
|
234
192
|
break;
|
235
193
|
case ' ':
|
236
|
-
if (square_selected_num == 0)
|
237
|
-
{
|
194
|
+
if (square_selected_num == 0) {
|
238
195
|
fireLaser(RED);
|
239
|
-
}
|
240
|
-
else if (square_selected_num == 79)
|
241
|
-
{
|
196
|
+
} else if (square_selected_num == 79) {
|
242
197
|
fireLaser(SILVER);
|
243
198
|
}
|
199
|
+
square_selected = false;
|
200
|
+
square_selected_num = -1;
|
244
201
|
break;
|
245
202
|
}
|
246
203
|
}
|
@@ -255,16 +212,12 @@ int GameBoard::handle(int event)
|
|
255
212
|
return Fl_Widget::handle(event);
|
256
213
|
}
|
257
214
|
|
258
|
-
void GameBoard::init(const std::vector<std::vector<std::string>> &pieces)
|
259
|
-
{
|
215
|
+
void GameBoard::init(const std::vector<std::vector<std::string>> &pieces) {
|
260
216
|
board_pieces = pieces;
|
261
217
|
|
262
|
-
for (const std::vector<std::string> &row : board_pieces)
|
263
|
-
|
264
|
-
|
265
|
-
{
|
266
|
-
if (piece != "--")
|
267
|
-
{
|
218
|
+
for (const std::vector<std::string> &row : board_pieces) {
|
219
|
+
for (const std::string &piece : row) {
|
220
|
+
if (piece != "--") {
|
268
221
|
char piece_type = piece[0];
|
269
222
|
int direction = piece[1] - '0';
|
270
223
|
std::string filename;
|
@@ -275,19 +228,15 @@ void GameBoard::init(const std::vector<std::vector<std::string>> &pieces)
|
|
275
228
|
Fl_Image *resized_image = orig_image->copy(cell_width, cell_height);
|
276
229
|
delete orig_image;
|
277
230
|
piece_images.push_back(resized_image);
|
278
|
-
}
|
279
|
-
else
|
280
|
-
{
|
231
|
+
} else {
|
281
232
|
piece_images.push_back(nullptr);
|
282
233
|
}
|
283
234
|
}
|
284
235
|
}
|
285
236
|
}
|
286
237
|
|
287
|
-
void GameBoard::resetPieces()
|
288
|
-
{
|
289
|
-
for (Fl_Image *image : piece_images)
|
290
|
-
{
|
238
|
+
void GameBoard::resetPieces() {
|
239
|
+
for (Fl_Image *image : piece_images) {
|
291
240
|
delete image;
|
292
241
|
}
|
293
242
|
piece_images.clear();
|
@@ -308,13 +257,11 @@ void GameBoard::resetPieces()
|
|
308
257
|
init(init_board);
|
309
258
|
}
|
310
259
|
|
311
|
-
void GameBoard::deletePiece()
|
312
|
-
{
|
260
|
+
void GameBoard::deletePiece() {
|
313
261
|
if (square_selected_num == -1)
|
314
262
|
return;
|
315
263
|
|
316
|
-
if (square_selected_num == 0 || square_selected_num == 79)
|
317
|
-
{
|
264
|
+
if (square_selected_num == 0 || square_selected_num == 79) {
|
318
265
|
square_selected = false;
|
319
266
|
square_selected_num = -1;
|
320
267
|
return;
|
@@ -332,20 +279,17 @@ void GameBoard::deletePiece()
|
|
332
279
|
square_selected_num = -1;
|
333
280
|
}
|
334
281
|
|
335
|
-
std::string GameBoard::getPieceFilename(char piece, int direction)
|
336
|
-
{
|
282
|
+
std::string GameBoard::getPieceFilename(char piece, int direction) {
|
337
283
|
static const std::string directions[] = {"_n.png", "_e.png", "_s.png", "_w.png"};
|
338
284
|
|
339
|
-
if (piece == 'X' || piece == 'x')
|
340
|
-
{
|
285
|
+
if (piece == 'X' || piece == 'x') {
|
341
286
|
return piece_map[piece] + ".png";
|
342
287
|
}
|
343
288
|
|
344
289
|
return piece_map[piece] + directions[direction];
|
345
290
|
}
|
346
291
|
|
347
|
-
void GameBoard::rotateSelectedPiece(bool clockwise)
|
348
|
-
{
|
292
|
+
void GameBoard::rotateSelectedPiece(bool clockwise) {
|
349
293
|
if (square_selected_num == -1)
|
350
294
|
return;
|
351
295
|
|
@@ -362,12 +306,9 @@ void GameBoard::rotateSelectedPiece(bool clockwise)
|
|
362
306
|
int new_direction;
|
363
307
|
std::string new_piece;
|
364
308
|
|
365
|
-
if (clockwise)
|
366
|
-
{
|
309
|
+
if (clockwise) {
|
367
310
|
new_direction = rotate_right_map[current_direction];
|
368
|
-
}
|
369
|
-
else
|
370
|
-
{
|
311
|
+
} else {
|
371
312
|
new_direction = rotate_left_map[current_direction];
|
372
313
|
}
|
373
314
|
|
@@ -382,14 +323,12 @@ void GameBoard::rotateSelectedPiece(bool clockwise)
|
|
382
323
|
piece_images[square_selected_num] = resized_image;
|
383
324
|
}
|
384
325
|
|
385
|
-
void GameBoard::swapPieces(int swap_square)
|
386
|
-
{
|
326
|
+
void GameBoard::swapPieces(int swap_square) {
|
387
327
|
if (square_selected_num == -1)
|
388
328
|
return;
|
389
329
|
|
390
330
|
if (square_selected_num == 0 || square_selected_num == 79 ||
|
391
|
-
swap_square == 0 || swap_square == 79)
|
392
|
-
{
|
331
|
+
swap_square == 0 || swap_square == 79) {
|
393
332
|
square_selected = true;
|
394
333
|
square_selected_num = swap_square;
|
395
334
|
return;
|
@@ -439,13 +378,11 @@ void GameBoard::swapPieces(int swap_square)
|
|
439
378
|
square_selected_num = -1;
|
440
379
|
}
|
441
380
|
|
442
|
-
void GameBoard::moveSelectedPiece(int end_square)
|
443
|
-
{
|
381
|
+
void GameBoard::moveSelectedPiece(int end_square) {
|
444
382
|
if (square_selected_num == -1)
|
445
383
|
return;
|
446
384
|
|
447
|
-
if (square_selected_num == 0 || square_selected_num == 79)
|
448
|
-
{
|
385
|
+
if (square_selected_num == 0 || square_selected_num == 79) {
|
449
386
|
square_selected = false;
|
450
387
|
square_selected_num = -1;
|
451
388
|
return;
|
@@ -478,8 +415,7 @@ void GameBoard::moveSelectedPiece(int end_square)
|
|
478
415
|
square_selected_num = -1;
|
479
416
|
}
|
480
417
|
|
481
|
-
void GameBoard::fireLaser(Color color)
|
482
|
-
{
|
418
|
+
void GameBoard::fireLaser(Color color) {
|
483
419
|
laser_active = true;
|
484
420
|
laser_path.clear();
|
485
421
|
|
@@ -488,47 +424,38 @@ void GameBoard::fireLaser(Color color)
|
|
488
424
|
int end_x;
|
489
425
|
int end_y;
|
490
426
|
|
491
|
-
if (color == RED)
|
492
|
-
{
|
427
|
+
if (color == RED) {
|
493
428
|
std::string piece_str = board_pieces[0][0];
|
494
429
|
auto [piece_type, piece_orientation] = getPieceTypeAndOrientation(piece_str);
|
495
430
|
|
496
431
|
start_x = x() + (cell_width / 2);
|
497
432
|
start_y = y() + (cell_height / 2);
|
498
433
|
|
499
|
-
if (piece_orientation == ORIENT_EAST)
|
500
|
-
{
|
434
|
+
if (piece_orientation == ORIENT_EAST) {
|
501
435
|
|
502
436
|
end_x = start_x + laser_step;
|
503
437
|
end_y = start_y;
|
504
438
|
laser_direction = EAST;
|
505
439
|
laser_square_row = 0;
|
506
440
|
laser_square_col = 0;
|
507
|
-
}
|
508
|
-
else if (piece_orientation == ORIENT_SOUTH)
|
509
|
-
{
|
441
|
+
} else if (piece_orientation == ORIENT_SOUTH) {
|
510
442
|
|
511
443
|
end_x = start_x;
|
512
444
|
end_y = start_y + laser_step;
|
513
445
|
laser_direction = SOUTH;
|
514
446
|
laser_square_row = 0;
|
515
447
|
laser_square_col = 0;
|
516
|
-
}
|
517
|
-
else
|
518
|
-
{
|
448
|
+
} else {
|
519
449
|
laser_active = false;
|
520
450
|
return;
|
521
451
|
}
|
522
|
-
}
|
523
|
-
else if (color == SILVER)
|
524
|
-
{
|
452
|
+
} else if (color == SILVER) {
|
525
453
|
int current_row = rows - 1;
|
526
454
|
int current_col = cols - 1;
|
527
455
|
std::string piece_str = board_pieces[current_row][current_col];
|
528
456
|
auto [piece_type, piece_orientation] = getPieceTypeAndOrientation(piece_str);
|
529
457
|
|
530
|
-
if (piece_orientation == ORIENT_WEST)
|
531
|
-
{
|
458
|
+
if (piece_orientation == ORIENT_WEST) {
|
532
459
|
start_x = x() + (current_col * cell_width) + (cell_width / 2);
|
533
460
|
start_y = y() + (current_row * cell_height) + (cell_height / 2);
|
534
461
|
end_x = start_x - laser_step;
|
@@ -536,9 +463,7 @@ void GameBoard::fireLaser(Color color)
|
|
536
463
|
laser_direction = WEST;
|
537
464
|
laser_square_row = current_row;
|
538
465
|
laser_square_col = current_col;
|
539
|
-
}
|
540
|
-
else if (piece_orientation == ORIENT_NORTH)
|
541
|
-
{
|
466
|
+
} else if (piece_orientation == ORIENT_NORTH) {
|
542
467
|
start_x = x() + (current_col * cell_width) + (cell_width / 2);
|
543
468
|
start_y = y() + (current_row * cell_height) + (cell_height / 2);
|
544
469
|
end_x = start_x;
|
@@ -546,9 +471,7 @@ void GameBoard::fireLaser(Color color)
|
|
546
471
|
laser_direction = NORTH;
|
547
472
|
laser_square_row = current_row;
|
548
473
|
laser_square_col = current_col;
|
549
|
-
}
|
550
|
-
else
|
551
|
-
{
|
474
|
+
} else {
|
552
475
|
laser_active = false;
|
553
476
|
return;
|
554
477
|
}
|
@@ -557,16 +480,13 @@ void GameBoard::fireLaser(Color color)
|
|
557
480
|
calculateLaserPathSquares();
|
558
481
|
// print path:
|
559
482
|
std::cout << "laser_path_squares = [";
|
560
|
-
for (size_t i = 0; i < laser_path_squares.size(); ++i)
|
561
|
-
|
562
|
-
std::apply([](auto &&...args)
|
563
|
-
{
|
483
|
+
for (size_t i = 0; i < laser_path_squares.size(); ++i) {
|
484
|
+
std::apply([](auto &&...args) {
|
564
485
|
std::cout << '(';
|
565
486
|
((std::cout << args << ", "), ...);
|
566
487
|
std::cout << '\b' << '\b' << ')'; },
|
567
488
|
laser_path_squares[i]);
|
568
|
-
if (i != laser_path_squares.size() - 1)
|
569
|
-
{
|
489
|
+
if (i != laser_path_squares.size() - 1) {
|
570
490
|
std::cout << ", ";
|
571
491
|
}
|
572
492
|
}
|
@@ -583,10 +503,8 @@ void GameBoard::fireLaser(Color color)
|
|
583
503
|
Fl::add_timeout(0.01, laser_timer_cb, this);
|
584
504
|
}
|
585
505
|
|
586
|
-
void GameBoard::updateLaserPosition()
|
587
|
-
{
|
588
|
-
if (laser_y >= y() + (rows * cell_height) || laser_y <= y() || laser_x >= x() + (cols * cell_width) || laser_x <= x())
|
589
|
-
{
|
506
|
+
void GameBoard::updateLaserPosition() {
|
507
|
+
if (laser_y >= y() + (rows * cell_height) || laser_y <= y() || laser_x >= x() + (cols * cell_width) || laser_x <= x()) {
|
590
508
|
laser_active = false;
|
591
509
|
laser_path.clear();
|
592
510
|
redraw();
|
@@ -606,17 +524,14 @@ void GameBoard::updateLaserPosition()
|
|
606
524
|
(laser_direction == SOUTH && laser_y > goal_y) ||
|
607
525
|
(laser_direction == EAST && laser_x > goal_x) ||
|
608
526
|
(laser_direction == WEST && laser_x < goal_x)) &&
|
609
|
-
(l_idx < laser_path_squares.size()))
|
610
|
-
{
|
527
|
+
(l_idx < laser_path_squares.size())) {
|
611
528
|
laser_x = goal_x;
|
612
529
|
laser_y = goal_y;
|
613
530
|
}
|
614
531
|
|
615
532
|
// determine next direction if we are at the middle of a square
|
616
|
-
if (laser_x == goal_x && laser_y == goal_y)
|
617
|
-
|
618
|
-
if (l_idx >= laser_path_squares.size() - 1)
|
619
|
-
{
|
533
|
+
if (laser_x == goal_x && laser_y == goal_y) {
|
534
|
+
if (l_idx >= laser_path_squares.size() - 1) {
|
620
535
|
laser_active = false;
|
621
536
|
laser_path.clear();
|
622
537
|
redraw();
|
@@ -627,18 +542,14 @@ void GameBoard::updateLaserPosition()
|
|
627
542
|
current_segment = laser_path_squares[l_idx];
|
628
543
|
auto [cur_row, cur_col, end_row, end_col] = current_segment;
|
629
544
|
|
630
|
-
if (cur_row == end_row)
|
631
|
-
{
|
545
|
+
if (cur_row == end_row) {
|
632
546
|
laser_direction = (cur_col < end_col) ? EAST : WEST;
|
633
|
-
}
|
634
|
-
else
|
635
|
-
{
|
547
|
+
} else {
|
636
548
|
laser_direction = (cur_row < end_row) ? SOUTH : NORTH;
|
637
549
|
}
|
638
550
|
}
|
639
551
|
|
640
|
-
switch (laser_direction)
|
641
|
-
{
|
552
|
+
switch (laser_direction) {
|
642
553
|
case NORTH:
|
643
554
|
laser_y -= laser_step;
|
644
555
|
break;
|
@@ -663,18 +574,15 @@ void GameBoard::updateLaserPosition()
|
|
663
574
|
redraw();
|
664
575
|
}
|
665
576
|
|
666
|
-
void GameBoard::laser_timer_cb(void *data)
|
667
|
-
{
|
577
|
+
void GameBoard::laser_timer_cb(void *data) {
|
668
578
|
GameBoard *gb = static_cast<GameBoard *>(data);
|
669
|
-
if (gb->laser_active)
|
670
|
-
{
|
579
|
+
if (gb->laser_active) {
|
671
580
|
gb->updateLaserPosition();
|
672
581
|
Fl::repeat_timeout(0.01, laser_timer_cb, data);
|
673
582
|
}
|
674
583
|
}
|
675
584
|
|
676
|
-
void GameBoard::calculateLaserPathSquares()
|
677
|
-
{
|
585
|
+
void GameBoard::calculateLaserPathSquares() {
|
678
586
|
laser_path_squares.clear();
|
679
587
|
|
680
588
|
int current_row = laser_square_row;
|
@@ -682,15 +590,13 @@ void GameBoard::calculateLaserPathSquares()
|
|
682
590
|
LaserDirection direction = laser_direction;
|
683
591
|
|
684
592
|
bool calculating = true;
|
685
|
-
while (calculating)
|
686
|
-
{
|
593
|
+
while (calculating) {
|
687
594
|
int start_row = current_row;
|
688
595
|
int start_col = current_col;
|
689
596
|
int end_row = current_row;
|
690
597
|
int end_col = current_col;
|
691
598
|
|
692
|
-
switch (direction)
|
693
|
-
{
|
599
|
+
switch (direction) {
|
694
600
|
case NORTH:
|
695
601
|
end_row -= 1;
|
696
602
|
break;
|
@@ -706,8 +612,7 @@ void GameBoard::calculateLaserPathSquares()
|
|
706
612
|
}
|
707
613
|
|
708
614
|
// out of bounds?
|
709
|
-
if (end_row < 0 || end_row >= rows || end_col < 0 || end_col >= cols)
|
710
|
-
{
|
615
|
+
if (end_row < 0 || end_row >= rows || end_col < 0 || end_col >= cols) {
|
711
616
|
break;
|
712
617
|
}
|
713
618
|
|
@@ -719,8 +624,7 @@ void GameBoard::calculateLaserPathSquares()
|
|
719
624
|
|
720
625
|
std::string piece_str = board_pieces[current_row][current_col];
|
721
626
|
|
722
|
-
if (piece_str == "--")
|
723
|
-
{
|
627
|
+
if (piece_str == "--") {
|
724
628
|
continue;
|
725
629
|
}
|
726
630
|
|
@@ -728,8 +632,7 @@ void GameBoard::calculateLaserPathSquares()
|
|
728
632
|
auto [piece_type, piece_orientation] = getPieceTypeAndOrientation(piece_str);
|
729
633
|
auto reflection_result = reflections_map[direction][piece_type][piece_orientation];
|
730
634
|
|
731
|
-
switch (reflection_result)
|
732
|
-
{
|
635
|
+
switch (reflection_result) {
|
733
636
|
case RESULT_ABSORBED:
|
734
637
|
calculating = false;
|
735
638
|
break;
|
@@ -755,8 +658,7 @@ void GameBoard::calculateLaserPathSquares()
|
|
755
658
|
}
|
756
659
|
}
|
757
660
|
|
758
|
-
std::pair<GameBoard::PieceType, GameBoard::PieceOrientation> GameBoard::getPieceTypeAndOrientation(const std::string &piece_str)
|
759
|
-
{
|
661
|
+
std::pair<GameBoard::PieceType, GameBoard::PieceOrientation> GameBoard::getPieceTypeAndOrientation(const std::string &piece_str) {
|
760
662
|
|
761
663
|
char piece_char = std::toupper(piece_str[0]);
|
762
664
|
char orient_char = piece_str[1];
|
@@ -764,8 +666,7 @@ std::pair<GameBoard::PieceType, GameBoard::PieceOrientation> GameBoard::getPiece
|
|
764
666
|
PieceType piece_type;
|
765
667
|
PieceOrientation piece_orientation;
|
766
668
|
|
767
|
-
switch (piece_char)
|
768
|
-
{
|
669
|
+
switch (piece_char) {
|
769
670
|
case 'P':
|
770
671
|
piece_type = PYRAMID;
|
771
672
|
break;
|
@@ -785,8 +686,7 @@ std::pair<GameBoard::PieceType, GameBoard::PieceOrientation> GameBoard::getPiece
|
|
785
686
|
throw std::invalid_argument("Invalid piece type");
|
786
687
|
}
|
787
688
|
|
788
|
-
switch (orient_char)
|
789
|
-
{
|
689
|
+
switch (orient_char) {
|
790
690
|
case '0':
|
791
691
|
piece_orientation = ORIENT_NORTH;
|
792
692
|
break;
|
@@ -806,31 +706,25 @@ std::pair<GameBoard::PieceType, GameBoard::PieceOrientation> GameBoard::getPiece
|
|
806
706
|
return std::make_pair(piece_type, piece_orientation);
|
807
707
|
}
|
808
708
|
|
809
|
-
bool GameBoard::squareContainsPiece(int square_num)
|
810
|
-
{
|
709
|
+
bool GameBoard::squareContainsPiece(int square_num) {
|
811
710
|
int row = square_num / cols;
|
812
711
|
int col = square_num % cols;
|
813
712
|
return board_pieces[row][col] != "--";
|
814
713
|
}
|
815
714
|
|
816
|
-
void GameBoard::rebuildReloadKhetAILib()
|
817
|
-
{
|
715
|
+
void GameBoard::rebuildReloadKhetAILib() {
|
818
716
|
std::cout << "\nRebuilding and reloading KhetAI lib..." << std::endl;
|
819
717
|
|
820
718
|
int build_result = system("./build_khetai.sh");
|
821
|
-
if (build_result != 0)
|
822
|
-
{
|
719
|
+
if (build_result != 0) {
|
823
720
|
std::cerr << "Failed to rebuild KhetAI lib" << std::endl;
|
824
721
|
return;
|
825
722
|
}
|
826
723
|
|
827
|
-
try
|
828
|
-
{
|
724
|
+
try {
|
829
725
|
ai_loader.reload_library("./libkhetai.so");
|
830
726
|
std::cout << "KhetAI lib reloaded successfully" << std::endl;
|
831
|
-
}
|
832
|
-
catch (const std::runtime_error &e)
|
833
|
-
{
|
727
|
+
} catch (const std::runtime_error &e) {
|
834
728
|
std::cerr << "Failed to reload KhetAI lib: " << e.what() << std::endl;
|
835
729
|
}
|
836
730
|
}
|