khetai 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/.clang-format +14 -0
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/ext/khetai/dev/fltk-ui/ai_loader.cpp +23 -38
- data/ext/khetai/dev/fltk-ui/ai_loader.h +5 -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 +15 -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 -256
- 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
|
}
|