Repository navigation
Expand file tree
/
Copy pathgraph_board.cpp
More file actions
124 lines (99 loc) · 3.76 KB
/
Copy pathgraph_board.cpp
File metadata and controls
124 lines (99 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "game_board.hpp"
game_board::game_board(level_grid level) {
n_rows = level.rows;
n_cols = level.cols;
constraints = level.constraints;
saturation_limit = level.saturation_limit;
cells.resize(n_rows, std::vector<cell_type>(n_cols, cell_type::empty));
board_graph = new graph(n_rows, n_cols, &cells);
}
game_board::~game_board() {
delete board_graph;
}
int game_board::count_consecutive(int r, int c, int dr, int dc, cell_type type) {
int count = 0;
int curr_r = r + dr;
int curr_c = c + dc;
while(curr_r >= 0 && curr_r < n_rows && curr_c >= 0 && curr_c < n_cols) {
if(cells[curr_r][curr_c] == type) {
count++;
curr_r += dr;
curr_c += dc;
} else {
break;
}
}
return count;
}
bool game_board::is_valid_move(int row, int col, cell_type type) {
if(row < 0 || row >= n_rows || col < 0 || col >= n_cols) return false;
if(cells[row][col] != cell_type::empty) return false;
int r1, c1, r2, c2;
if(type == cell_type::forward_slash) {
r1 = row + 1; c1 = col;
r2 = row; c2 = col + 1;
} else {
r1 = row; c1 = col;
r2 = row + 1; c2 = col + 1;
}
// 1. Check Constraints
int lim1 = constraints[r1][c1];
if(lim1 != -1 && board_graph->get_degree(r1, c1) >= lim1) return false;
int lim2 = constraints[r2][c2];
if(lim2 != -1 && board_graph->get_degree(r2, c2) >= lim2) return false;
// 2. Check Cycles
if(board_graph->has_path(r1, c1, r2, c2)) return false;
// 3. NEW: Check Straight Line Saturation
int current_len = 1; // The move itself
if(type == cell_type::forward_slash) {
// Check Up-Right (-1, +1) and Bottom-Left (+1, -1)
current_len += count_consecutive(row, col, -1, 1, type);
current_len += count_consecutive(row, col, 1, -1, type);
} else {
// Check Up-Left (-1, -1) and Bottom-Right (+1, +1)
current_len += count_consecutive(row, col, -1, -1, type);
current_len += count_consecutive(row, col, 1, 1, type);
}
if(current_len > saturation_limit) return false;
return true;
}
void game_board::apply_move(int row, int col, cell_type type) {
cells[row][col] = type;
}
bool game_board::has_valid_moves() {
for(int r = 0; r < n_rows; r++) {
for(int c = 0; c < n_cols; c++) {
if(cells[r][c] == cell_type::empty) {
if(is_valid_move(r, c, cell_type::forward_slash)) return true;
if(is_valid_move(r, c, cell_type::back_slash)) return true;
}
}
}
return false;
}
std::string game_board::get_invalid_reason(int row, int col, cell_type type) {
if(cells[row][col] != cell_type::empty) return "Cell occupied!";
int r1, c1, r2, c2;
if(type == cell_type::forward_slash) {
r1 = row + 1; c1 = col;
r2 = row; c2 = col + 1;
} else {
r1 = row; c1 = col;
r2 = row + 1; c2 = col + 1;
}
int lim1 = constraints[r1][c1];
if(lim1 != -1 && board_graph->get_degree(r1, c1) >= lim1) return "Node Full!";
int lim2 = constraints[r2][c2];
if(lim2 != -1 && board_graph->get_degree(r2, c2) >= lim2) return "Node Full!";
if(board_graph->has_path(r1, c1, r2, c2)) return "Loops not allowed!";
int current_len = 1;
if(type == cell_type::forward_slash) {
current_len += count_consecutive(row, col, -1, 1, type);
current_len += count_consecutive(row, col, 1, -1, type);
} else {
current_len += count_consecutive(row, col, -1, -1, type);
current_len += count_consecutive(row, col, 1, 1, type);
}
if(current_len > saturation_limit) return "Line too long!";
return "Invalid Move";
}