@jutge.org/toolkit 4.2.24 → 4.2.26

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.
@@ -2,107 +2,117 @@
2
2
 
3
3
  #include "Board.hh"
4
4
  #include "Action.hh"
5
-
6
5
 
7
- Board::Board (istream& is, int seed) {
6
+ Board::Board(istream &is, int seed)
7
+ {
8
8
  set_random_seed(seed);
9
- *static_cast<Settings*>(this) = Settings::read_settings(is);
9
+ *static_cast<Settings *>(this) = Settings::read_settings(is);
10
10
 
11
11
  player2alive_units = vector<set<int>>(num_players());
12
- player2dead_units = vector<set<int>>(num_players());
13
- zombies_ = set<int>();
14
-
15
- names = vector<string>(num_players());
16
- scr = vector<int> (num_players(), 0);
17
- scr_accumulated = vector<int> (num_players(), 0);
18
- nb_cells = vector<int> (num_players(), 0); // Is computed in read grid
19
- overall_strength = vector<int> (num_players(), clan_ini_strength());
20
-
21
- stats = vector<double> (num_players(), 0);
12
+ player2dead_units = vector<set<int>>(num_players());
13
+ zombies_ = set<int>();
14
+
15
+ names = vector<string>(num_players());
16
+ scr = vector<int>(num_players(), 0);
17
+ scr_accumulated = vector<int>(num_players(), 0);
18
+ nb_cells = vector<int>(num_players(), 0); // Is computed in read grid
19
+ overall_strength = vector<int>(num_players(), clan_ini_strength());
20
+
21
+ stats = vector<double>(num_players(), 0);
22
22
 
23
23
  rnd = 0;
24
24
 
25
25
  fresh_id = 0;
26
26
  read_generator_and_grid(is);
27
27
 
28
- for (auto& p : units) fresh_id = max(fresh_id,p.first);
28
+ for (auto &p : units)
29
+ fresh_id = max(fresh_id, p.first);
29
30
  ++fresh_id;
30
-
31
+
31
32
  _my_assert(ok(), "Invariants are not satisfied.");
32
33
  }
33
34
 
34
- void Board::check_is_good_initial_fixed_board () const {
35
- vector<int> num_units(num_players(),0);
35
+ void Board::check_is_good_initial_fixed_board() const
36
+ {
37
+ vector<int> num_units(num_players(), 0);
36
38
  int num_zombies = 0;
37
39
  int num_food = 0;
38
40
 
39
41
  _my_assert(int(grid.size()) == board_rows(), "Fixed board has wrong number of rows.");
40
42
  _my_assert(int(grid[0].size()) == board_cols(), "Fixed board has wrong number of cols.");
41
-
43
+
42
44
  for (int i = 0; i < board_rows(); ++i)
43
- for (int j = 0; j < board_cols(); ++j) {
45
+ for (int j = 0; j < board_cols(); ++j)
46
+ {
44
47
  Cell c = grid[i][j];
45
- if (c.food) ++num_food;
46
- if (c.id != -1) {
47
- int id = c.id;
48
- _my_assert(units.count(id) != 0, "Unit places in grid does noe appear in units");
49
- const Unit& u = units.find(id)->second;
50
- _my_assert(u.type != Dead, "Initial unit already dead");
51
- if (u.type == Alive) {
52
- _my_assert(player_ok(u.player), "Player not ok in check_is_good_initial_fixed_board");
53
- _my_assert(c.owner == u.player, "Unit placed in a cell but player does not own it");
54
- _my_assert(u.pos == Pos(i,j), "Live unit does not have right position");
55
- _my_assert(player2alive_units[u.player].count(id) != 0, "Live unit not in player2alive_units");
56
- ++num_units[u.player];
57
- }
58
- else { // We know it is a zombie
59
- ++num_zombies;
60
- _my_assert(u.player == -1, "Zombies should have player -1");
61
- _my_assert(u.pos == Pos(i,j), "Zombie does not have right position");
62
- _my_assert(zombies_.count(id) != 0, "Live unit not in zombies_");
63
- }
48
+ if (c.food)
49
+ ++num_food;
50
+ if (c.id != -1)
51
+ {
52
+ int id = c.id;
53
+ _my_assert(units.count(id) != 0, "Unit places in grid does noe appear in units");
54
+ const Unit &u = units.find(id)->second;
55
+ _my_assert(u.type != Dead, "Initial unit already dead");
56
+ if (u.type == Alive)
57
+ {
58
+ _my_assert(player_ok(u.player), "Player not ok in check_is_good_initial_fixed_board");
59
+ _my_assert(c.owner == u.player, "Unit placed in a cell but player does not own it");
60
+ _my_assert(u.pos == Pos(i, j), "Live unit does not have right position");
61
+ _my_assert(player2alive_units[u.player].count(id) != 0, "Live unit not in player2alive_units");
62
+ ++num_units[u.player];
63
+ }
64
+ else
65
+ { // We know it is a zombie
66
+ ++num_zombies;
67
+ _my_assert(u.player == -1, "Zombies should have player -1");
68
+ _my_assert(u.pos == Pos(i, j), "Zombie does not have right position");
69
+ _my_assert(zombies_.count(id) != 0, "Live unit not in zombies_");
70
+ }
64
71
  }
65
72
  }
66
-
67
- _my_assert(num_food == num_ini_food(),"Fixed board has wrong number of initial food.");
68
- _my_assert(num_zombies == num_ini_zombies(),"Fixed board has wrong number of initial zombies.");
73
+
74
+ _my_assert(num_food == num_ini_food(), "Fixed board has wrong number of initial food.");
75
+ _my_assert(num_zombies == num_ini_zombies(), "Fixed board has wrong number of initial zombies.");
69
76
  for (int p = 0; p < num_players(); ++p)
70
77
  _my_assert(int(player2alive_units[p].size()) == num_units[p], "Fixed board has wrong number of initial live units.");
71
78
  }
72
79
 
73
- void Board::print_settings (ostream& os) const {
80
+ void Board::print_settings(ostream &os) const
81
+ {
74
82
 
75
- os << version() << endl;
76
- os << endl;
77
- os << "NUM_PLAYERS" << "\t\t\t" << num_players() << endl;
78
- os << "NUM_ROUNDS" << "\t\t\t" << num_rounds() << endl;
79
- os << "BOARD_ROWS" << "\t\t\t" << board_rows() << endl;
80
- os << "BOARD_COLS" << "\t\t\t" << board_cols() << endl;
81
- os << "NUM_INI_UNITS_PER_CLAN" << "\t\t" << num_ini_units_per_clan() << endl;
82
- os << "NUM_INI_ZOMBIES" << "\t\t\t" << num_ini_zombies() << endl;
83
- os << "NUM_INI_FOOD" << "\t\t\t" << num_ini_food() << endl;
84
- os << "CLAN_INI_STRENGTH" << "\t\t" << clan_ini_strength() << endl;
85
- os << "POINTS_FOR_KILLING_PERSON" << "\t" << points_for_killing_person() << endl;
86
- os << "POINTS_FOR_KILLING_ZOMBIE" << "\t" << points_for_killing_zombie() << endl;
87
- os << "POINTS_PER_OWNED_CELL" << "\t\t" << points_per_owned_cell() << endl;
88
- os << "FOOD_STRENGTH" << "\t\t\t" << food_strength() << endl;
89
- os << "ROUNDS_BEFORE_BECOMING_ZOMBIE" << "\t" << rounds_before_becoming_zombie() << endl;
83
+ os << version() << endl;
84
+ os << endl;
85
+ os << "NUM_PLAYERS" << "\t\t\t" << num_players() << endl;
86
+ os << "NUM_ROUNDS" << "\t\t\t" << num_rounds() << endl;
87
+ os << "BOARD_ROWS" << "\t\t\t" << board_rows() << endl;
88
+ os << "BOARD_COLS" << "\t\t\t" << board_cols() << endl;
89
+ os << "NUM_INI_UNITS_PER_CLAN" << "\t\t" << num_ini_units_per_clan() << endl;
90
+ os << "NUM_INI_ZOMBIES" << "\t\t\t" << num_ini_zombies() << endl;
91
+ os << "NUM_INI_FOOD" << "\t\t\t" << num_ini_food() << endl;
92
+ os << "CLAN_INI_STRENGTH" << "\t\t" << clan_ini_strength() << endl;
93
+ os << "POINTS_FOR_KILLING_PERSON" << "\t" << points_for_killing_person() << endl;
94
+ os << "POINTS_FOR_KILLING_ZOMBIE" << "\t" << points_for_killing_zombie() << endl;
95
+ os << "POINTS_PER_OWNED_CELL" << "\t\t" << points_per_owned_cell() << endl;
96
+ os << "FOOD_STRENGTH" << "\t\t\t" << food_strength() << endl;
97
+ os << "ROUNDS_BEFORE_BECOMING_ZOMBIE" << "\t" << rounds_before_becoming_zombie() << endl;
90
98
  }
91
99
 
92
-
93
- void Board::print_names (ostream& os) const {
100
+ void Board::print_names(ostream &os) const
101
+ {
94
102
  os << "names ";
95
- for (int pl = 0; pl < num_players(); ++pl) os << ' ' << name(pl);
103
+ for (int pl = 0; pl < num_players(); ++pl)
104
+ os << ' ' << name(pl);
96
105
  os << endl;
97
106
  }
98
107
 
99
-
100
- void Board::print_state (ostream& os) {
108
+ void Board::print_state(ostream &os)
109
+ {
101
110
 
102
111
  // Should start with the same format of Info::read_grid.
103
112
  // Then other data describing the state.
104
113
 
105
- os << endl << endl;
114
+ os << endl
115
+ << endl;
106
116
 
107
117
  os << " ";
108
118
  for (int j = 0; j < board_cols(); ++j)
@@ -114,24 +124,34 @@ void Board::print_state (ostream& os) {
114
124
  os << j % 10;
115
125
  os << endl;
116
126
 
117
- for (int i = 0; i < board_rows(); ++i) {
127
+ for (int i = 0; i < board_rows(); ++i)
128
+ {
118
129
  os << i / 10 << i % 10 << " ";
119
- for (int j = 0; j < board_cols(); ++j) {
120
- const Cell& c = grid[i][j];
121
- if (c.type == Waste) os << 'W';
122
- else if (c.owner == 0) os << '0';
123
- else if (c.owner == 1) os << '1';
124
- else if (c.owner == 2) os << '2';
125
- else if (c.owner == 3) os << '3';
126
- else os << '.';
130
+ for (int j = 0; j < board_cols(); ++j)
131
+ {
132
+ const Cell &c = grid[i][j];
133
+ if (c.type == Waste)
134
+ os << 'W';
135
+ else if (c.owner == 0)
136
+ os << '0';
137
+ else if (c.owner == 1)
138
+ os << '1';
139
+ else if (c.owner == 2)
140
+ os << '2';
141
+ else if (c.owner == 3)
142
+ os << '3';
143
+ else
144
+ os << '.';
127
145
  }
128
146
  os << endl;
129
147
  }
130
148
 
131
- os << endl << "units" << endl;
149
+ os << endl
150
+ << "units" << endl;
132
151
  os << units.size() << endl;
133
152
  os << "type\tid\tplayer\trow\tcolumn\trounds" << endl;
134
- for (const auto& ci : units) {
153
+ for (const auto &ci : units)
154
+ {
135
155
  os << UnitType2char(ci.second.type) << "\t";
136
156
  os << ci.second.id << "\t";
137
157
  os << ci.second.player << "\t";
@@ -140,15 +160,18 @@ void Board::print_state (ostream& os) {
140
160
  os << ci.second.rounds_for_zombie << endl;
141
161
  }
142
162
 
143
- os << endl << "food" << endl;
163
+ os << endl
164
+ << "food" << endl;
144
165
  // Collect them
145
166
  vector<Pos> food;
146
167
  for (int i = 0; i < board_rows(); ++i)
147
168
  for (int j = 0; j < board_cols(); ++j)
148
- if (grid[i][j].food) food.push_back(Pos(i,j));
169
+ if (grid[i][j].food)
170
+ food.push_back(Pos(i, j));
149
171
  os << food.size() << endl;
150
172
  os << "row\tcolumn" << endl;
151
- for (const auto& p : food) {
173
+ for (const auto &p : food)
174
+ {
152
175
  os << p.i << "\t";
153
176
  os << p.j << endl;
154
177
  }
@@ -159,178 +182,210 @@ void Board::print_state (ostream& os) {
159
182
  os << endl;
160
183
 
161
184
  os << "score";
162
- for (auto s : scr) os << "\t" << s;
185
+ for (auto s : scr)
186
+ os << "\t" << s;
163
187
  os << endl;
164
188
  os << endl;
165
189
 
166
190
  os << "scr_acc";
167
- for (auto s : scr_accumulated) os << "\t" << s;
191
+ for (auto s : scr_accumulated)
192
+ os << "\t" << s;
168
193
  os << endl;
169
194
  os << endl;
170
195
 
171
196
  os << "strength";
172
- for (auto s : overall_strength) os << "\t" << s;
197
+ for (auto s : overall_strength)
198
+ os << "\t" << s;
173
199
  os << endl;
174
200
  os << endl;
175
201
 
176
202
  os << "status";
177
- for (auto s : stats) os << "\t" << s;
203
+ for (auto s : stats)
204
+ os << "\t" << s;
178
205
  os << endl;
179
206
  os << endl;
180
207
  }
181
208
 
182
-
183
- void Board::print_results () const {
209
+ void Board::print_results() const
210
+ {
184
211
  int max_score = 0;
185
212
  vector<int> v;
186
- for (int pl = 0; pl < num_players(); ++pl) {
213
+ for (int pl = 0; pl < num_players(); ++pl)
214
+ {
187
215
 
188
- cerr << "info: player " << name(pl)
189
- << " got score " << score(pl) << endl;
216
+ cerr << "info: player " << name(pl)
217
+ << " got score " << score(pl) << endl;
190
218
 
191
- if (score(pl) == max_score) v.push_back(pl);
192
- else if (score(pl) > max_score) {
219
+ if (score(pl) == max_score)
220
+ v.push_back(pl);
221
+ else if (score(pl) > max_score)
222
+ {
193
223
  max_score = score(pl);
194
224
  v = vector<int>(1, pl);
195
225
  }
196
226
  }
197
227
 
198
228
  cerr << "info: player(s)";
199
- for (int pl : v) cerr << " " << name(pl);
229
+ for (int pl : v)
230
+ cerr << " " << name(pl);
200
231
  cerr << " got top score" << endl;
201
232
  }
202
233
 
203
234
  // Returns whether c1 wins
204
- bool Board::first_unit_wins_attack (const Unit& u1, const Unit& u2) {
235
+ bool Board::first_unit_wins_attack(const Unit &u1, const Unit &u2)
236
+ {
205
237
  int S = 30; // 30% vegades attack is a surprise and u1 wins
206
- if (random(0,100) < S) return true;
238
+ if (random(0, 100) < S)
239
+ return true;
207
240
 
208
241
  // Otherwise, it depend on the strength
209
242
  int u1_strength = strength(u1.player);
210
243
  int u2_strength = strength(u2.player);
211
244
 
212
- if (u1_strength + u2_strength == 0) return random(0,1) == 0; // If both no strength --> 50-50
245
+ if (u1_strength + u2_strength == 0)
246
+ return random(0, 1) == 0; // If both no strength --> 50-50
213
247
  int M = 1000;
214
- int num = random(0,M);
215
- double threshold = double(u1_strength)/(u1_strength + u2_strength)*M;
248
+ int num = random(0, M);
249
+ double threshold = double(u1_strength) / (u1_strength + u2_strength) * M;
216
250
  return num < threshold;
217
251
  }
218
252
 
219
- void Board::perform_attack (Unit& orig_u, Unit& dest_u, vector<vector<int>>& alive_to_dead){
220
- bool first_wins = first_unit_wins_attack(orig_u,dest_u);
221
- Unit& winner = (first_wins ? orig_u : dest_u);
222
- Unit& loser = (first_wins ? dest_u : orig_u );
253
+ void Board::perform_attack(Unit &orig_u, Unit &dest_u, vector<vector<int>> &alive_to_dead)
254
+ {
255
+ bool first_wins = first_unit_wins_attack(orig_u, dest_u);
256
+ Unit &winner = (first_wins ? orig_u : dest_u);
257
+ Unit &loser = (first_wins ? dest_u : orig_u);
223
258
 
224
259
  alive_to_dead[loser.player].push_back(loser.id);
225
260
  loser.type = Dead;
226
261
  loser.rounds_for_zombie = rounds_before_becoming_zombie();
227
- scr_accumulated[winner.player] += points_for_killing_person();
228
- }
229
-
230
- bool Board::execute (const Command& m,
231
- vector<int>& food_to_regenerate,
232
- vector<vector<int>>& zombie_to_unit,
233
- vector<vector<int>>& alive_to_dead
234
- ) {
235
- int id = m.id;
236
- Dir dir = Dir(m.dir);
237
- CommandType c_type = CommandType(m.c_type);
262
+ scr_accumulated[winner.player] += points_for_killing_person();
263
+ }
238
264
 
265
+ bool Board::execute(const Command &m,
266
+ vector<int> &food_to_regenerate,
267
+ vector<vector<int>> &zombie_to_unit,
268
+ vector<vector<int>> &alive_to_dead)
269
+ {
270
+ int id = m.id;
271
+ Dir dir = Dir(m.dir);
272
+ CommandType c_type = CommandType(m.c_type);
239
273
 
240
- if (not command_type_ok(c_type)) {
274
+ if (not command_type_ok(c_type))
275
+ {
241
276
  cerr << "warning: invalid command type in command: " << c_type << endl;
242
277
  return false;
243
278
  }
244
279
 
245
- if (not dir_ok(dir)) {
280
+ if (not dir_ok(dir))
281
+ {
246
282
  cerr << "warning: invalid dir in command: " << dir << endl;
247
283
  return false;
248
284
  }
249
285
 
250
- Unit& un = units[id];
251
- UnitType type = un.type;
252
- int pl = un.player;
253
- Pos op = un.pos;
254
- Cell& oc = grid[op.i][op.j];
286
+ Unit &un = units[id];
287
+ UnitType type = un.type;
288
+ int pl = un.player;
289
+ Pos op = un.pos;
290
+ Cell &oc = grid[op.i][op.j];
255
291
 
256
- if (type == Alive and (dir == DR or dir == RU or dir == UL or dir == LD)) return false; // Alive not diagonal
257
-
258
- if (type == Dead) return false; // Unit is dead (maybe has been dead in this round)
292
+ if (type == Alive and (dir == DR or dir == RU or dir == UL or dir == LD))
293
+ return false; // Alive not diagonal
294
+
295
+ if (type == Dead)
296
+ return false; // Unit is dead (maybe has been dead in this round)
259
297
 
260
298
  Pos np = op + dir;
261
- if (not pos_ok(np)) {
299
+ if (not pos_ok(np))
300
+ {
262
301
  cerr << "warning: cannot move to position " << np << " out of the board." << endl;
263
302
  return false;
264
303
  }
265
304
 
266
- Cell& nc = grid[np.i][np.j];
267
-
305
+ Cell &nc = grid[np.i][np.j];
268
306
 
269
- if (type == Zombie) {
270
- if (nc.type == Waste) {
307
+ if (type == Zombie)
308
+ {
309
+ if (nc.type == Waste)
310
+ {
271
311
  return false;
272
312
  }
273
- else if (nc.food) { // Cell with food
313
+ else if (nc.food)
314
+ { // Cell with food
274
315
  ++food_to_regenerate[num_players()]; // last position is for zombies
275
316
  nc.food = false;
276
317
  nc.owner = -1;
277
318
  nc.id = id;
278
319
  un.pos = np;
279
- oc.id = -1;
320
+ oc.id = -1;
280
321
  }
281
- else if (nc.id == -1){ // Cell with no unit
322
+ else if (nc.id == -1)
323
+ { // Cell with no unit
282
324
  nc.owner = -1;
283
325
  nc.id = id;
284
326
  un.pos = np;
285
327
  oc.id = -1;
286
328
  }
287
- else { // Cell with unit
288
- Unit& au = units[nc.id]; // attacked unit
289
- if (au.type == Zombie or au.type == Dead){ // Zombie attacks zombie
290
- return false;
329
+ else
330
+ { // Cell with unit
331
+ Unit &au = units[nc.id]; // attacked unit
332
+ if (au.type == Zombie or au.type == Dead)
333
+ { // Zombie attacks zombie
334
+ return false;
291
335
  }
292
- else { // Attack and bite a live unit
293
- if (au.rounds_for_zombie == -1) {
294
- au.rounds_for_zombie = rounds_before_becoming_zombie() + 1;
295
- }
296
- }
297
- }
298
- }
299
- else if (type == Alive) {
300
- if (nc.type == Waste) {
336
+ else
337
+ { // Attack and bite a live unit
338
+ if (au.rounds_for_zombie == -1)
339
+ {
340
+ au.rounds_for_zombie = rounds_before_becoming_zombie() + 1;
341
+ }
342
+ }
343
+ }
344
+ }
345
+ else if (type == Alive)
346
+ {
347
+ if (nc.type == Waste)
348
+ {
301
349
  cerr << "warning: cannot move to position " << np << " with waste." << endl;
302
350
  return false;
303
351
  }
304
- else if (nc.food) { // Cell with food
352
+ else if (nc.food)
353
+ { // Cell with food
305
354
  ++food_to_regenerate[pl];
306
355
  nc.food = false;
307
356
  nc.owner = pl;
308
357
  nc.id = id;
309
358
  un.pos = np;
310
- oc.id = -1;
359
+ oc.id = -1;
311
360
  }
312
- else if (nc.id == -1){ // Cell with no unit
361
+ else if (nc.id == -1)
362
+ { // Cell with no unit
313
363
  nc.owner = pl;
314
364
  nc.id = id;
315
365
  un.pos = np;
316
366
  oc.id = -1;
317
367
  }
318
- else { // Cell with unit
319
- Unit& au = units[nc.id]; // attacked unit
320
- if (au.type == Zombie) { // Kill a zombie
321
- zombie_to_unit[pl].push_back(nc.id); // zombie will be regenerated as unit of this clan
322
- nc.id = -1; // nobody is in the cell previouly occupied by the zombie
323
- au.pos = {-1,-1}; // no position (pending to be regenerated)
324
- scr_accumulated[pl] += points_for_killing_zombie();
368
+ else
369
+ { // Cell with unit
370
+ Unit &au = units[nc.id]; // attacked unit
371
+ if (au.type == Zombie)
372
+ { // Kill a zombie
373
+ zombie_to_unit[pl].push_back(nc.id); // zombie will be regenerated as unit of this clan
374
+ nc.id = -1; // nobody is in the cell previouly occupied by the zombie
375
+ au.pos = {-1, -1}; // no position (pending to be regenerated)
376
+ scr_accumulated[pl] += points_for_killing_zombie();
325
377
  }
326
- else if (au.type == Dead) {
327
- return false;
378
+ else if (au.type == Dead)
379
+ {
380
+ return false;
328
381
  }
329
- else if (au.player == pl) { // attacks among same clan not allowed
330
- return false;
382
+ else if (au.player == pl)
383
+ { // attacks among same clan not allowed
384
+ return false;
331
385
  }
332
- else { // attacks among different clans
333
- perform_attack(un,au,alive_to_dead);
386
+ else
387
+ { // attacks among different clans
388
+ perform_attack(un, au, alive_to_dead);
334
389
  }
335
390
  }
336
391
  }
@@ -338,31 +393,40 @@ bool Board::execute (const Command& m,
338
393
  return true;
339
394
  }
340
395
 
396
+ bool Board::is_good_pos_to_regen(const Pos &p) const
397
+ {
341
398
 
342
- bool Board::is_good_pos_to_regen ( const Pos& p) const {
399
+ if (not grid[p.i][p.j].is_empty())
400
+ return false;
343
401
 
344
- if (not grid[p.i][p.j].is_empty()) return false;
345
-
346
- for (int i = p.i - 2; i <= p.i + 2; ++i) { // Check nobody is nearby
347
- for (int j = p.j - 2; j <= p.j + 2; ++j) {
348
- if (pos_ok(Pos(i,j)) and grid[i][j].id != -1) return false;
402
+ for (int i = p.i - 2; i <= p.i + 2; ++i)
403
+ { // Check nobody is nearby
404
+ for (int j = p.j - 2; j <= p.j + 2; ++j)
405
+ {
406
+ if (pos_ok(Pos(i, j)) and grid[i][j].id != -1)
407
+ return false;
349
408
  }
350
409
  }
351
410
  return true;
352
411
  }
353
412
 
354
- Pos Board::get_random_pos_where_regenerate ( ) {
413
+ Pos Board::get_random_pos_where_regenerate()
414
+ {
355
415
  vector<Pos> res;
356
- for (int i = 0; i < board_rows(); ++i){
357
- for (int j = 0; j < board_cols(); ++j) {
358
- if (is_good_pos_to_regen(Pos(i,j))) res.push_back(Pos(i,j));
416
+ for (int i = 0; i < board_rows(); ++i)
417
+ {
418
+ for (int j = 0; j < board_cols(); ++j)
419
+ {
420
+ if (is_good_pos_to_regen(Pos(i, j)))
421
+ res.push_back(Pos(i, j));
359
422
  }
360
423
  }
361
-
362
- if (res.size() != 0) return res[random(0,res.size()-1)];
363
- else return get_empty_pos();
364
- }
365
424
 
425
+ if (res.size() != 0)
426
+ return res[random(0, res.size() - 1)];
427
+ else
428
+ return get_empty_pos();
429
+ }
366
430
 
367
431
  // pair<bool,Pos> Board::get_random_pos_where_regenerate ( ) {
368
432
  // vector<Pos> res;
@@ -371,12 +435,13 @@ Pos Board::get_random_pos_where_regenerate ( ) {
371
435
  // if (is_good_pos_to_regen(Pos(i,j))) res.push_back(Pos(i,j));
372
436
  // }
373
437
  // }
374
-
438
+
375
439
  // if (res.size() != 0) return {true,res[random(0,res.size()-1)]};
376
440
  // else return {false,Pos()};
377
441
  // }
378
442
 
379
- void Board::next (const vector<Action>& act, ostream& os) {
443
+ void Board::next(const vector<Action> &act, ostream &os)
444
+ {
380
445
 
381
446
  _my_assert(ok(), "Invariants are not satisfied.");
382
447
 
@@ -384,26 +449,29 @@ void Board::next (const vector<Action>& act, ostream& os) {
384
449
  _my_assert(int(act.size()) == npl, "Size should be number of players.");
385
450
 
386
451
  // Elements to be regenerated
387
- vector<int> food_to_regenerate(num_players()+1,0); // we know how much food each clan has collected, in order to change overall_strength at the end of the round. Last position is for food eaten by zombies
452
+ vector<int> food_to_regenerate(num_players() + 1, 0); // we know how much food each clan has collected, in order to change overall_strength at the end of the round. Last position is for food eaten by zombies
388
453
  vector<vector<int>> zombie_to_unit(num_players());
389
454
  vector<vector<int>> alive_to_dead(num_players());
390
-
455
+
391
456
  // Chooses (at most) one command per unit.
392
457
  set<int> seen;
393
458
  vector<vector<Command>> v(npl);
394
459
  for (int pl = 0; pl < npl; ++pl)
395
- for (const Command& m : act[pl].v) {
396
- int id = m.id;
460
+ for (const Command &m : act[pl].v)
461
+ {
462
+ int id = m.id;
397
463
  int c_type = m.c_type;
398
- int dir = m.dir;
464
+ int dir = m.dir;
399
465
 
400
466
  auto it = units.find(id);
401
467
 
402
- if (it == units.end()) cerr << "warning: invalid id : " << id << endl;
468
+ if (it == units.end())
469
+ cerr << "warning: invalid id : " << id << endl;
403
470
  else if (it->second.player != pl)
404
471
  cerr << "warning: unit " << id << " of player " << it->second.player
405
472
  << " not owned by " << pl << endl;
406
- else {
473
+ else
474
+ {
407
475
  // Here an assert as repetitions should have already been filtered out.
408
476
  _my_assert(not seen.count(id), "More than one command for the same unit.");
409
477
  seen.insert(id);
@@ -412,39 +480,41 @@ void Board::next (const vector<Action>& act, ostream& os) {
412
480
  }
413
481
  }
414
482
 
415
-
416
483
  // Makes all players' commands using a random order,
417
484
  // but respecting the relative order of the units of the same player.
418
485
  // Permutations are not equally likely to avoid favoring leading clans.
419
486
  int num = 0; // Counts number of pending commands
420
- for (int pl = 0; pl < npl; ++pl) num += v[pl].size();
487
+ for (int pl = 0; pl < npl; ++pl)
488
+ num += v[pl].size();
421
489
 
422
490
  set<int> killed;
423
491
  vector<Command> commands_done;
424
492
  vector<int> index(npl, 0);
425
- while (num--) {
493
+ while (num--)
494
+ {
426
495
  int q = 0; // Counts number of players with some action pending
427
- for (int pl = 0; pl < npl; ++pl) q += index[pl] < (int)v[pl].size();
496
+ for (int pl = 0; pl < npl; ++pl)
497
+ q += index[pl] < (int)v[pl].size();
428
498
  _my_assert(q > 0, "q > 0 in next.");
429
- int ran = random(1,q); // Decide whether 1st, 2nd, 3rd,, player with something pending is chosen
499
+ int ran = random(1, q); // Decide whether 1st, 2nd, 3rd,, player with something pending is chosen
430
500
  int pl = -1;
431
501
  int acum = 0;
432
- while (acum < ran) {
502
+ while (acum < ran)
503
+ {
433
504
  ++pl;
434
505
  acum += index[pl] < (int)v[pl].size(); // If index > ..., then player has nothing pending
435
506
  // and does not count
436
507
  }
437
508
 
438
- const Command& m = v[pl][index[pl]++];
509
+ const Command &m = v[pl][index[pl]++];
439
510
  if (execute(m, food_to_regenerate, zombie_to_unit, alive_to_dead))
440
511
  commands_done.push_back(m);
441
-
442
512
  }
443
513
 
444
514
  move_zombies(food_to_regenerate, zombie_to_unit, alive_to_dead, commands_done);
445
515
  // Es mouen els zombies (de moment, que facin moviments random, ja els farem intel·ligents)
446
516
  // Mirar com es fa a Moria (pel que sembla, s'execute un move i es posar a la llista de commands_done)
447
-
517
+
448
518
  os << "commands" << endl;
449
519
  Action::print(commands_done, os);
450
520
 
@@ -464,55 +534,63 @@ void Board::next (const vector<Action>& act, ostream& os) {
464
534
 
465
535
  execute_conversion_alive_to_dead(alive_to_dead);
466
536
 
467
- execute_random_conversion_live_unit( );
468
-
537
+ execute_random_conversion_live_unit();
538
+
469
539
  regenerate_food_and_update_strength(food_to_regenerate); // also substracts the food consumed per round
470
540
 
471
541
  update_nb_cells();
472
542
 
473
543
  update_score();
474
-
544
+
475
545
  ++rnd;
476
546
 
477
547
  _my_assert(ok(), "Invariants are not satisfied.");
478
548
  }
479
549
 
480
- void Board::execute_conversion_to_zombie ( ) {
481
- for (auto& p : units) {
482
- Unit& u = p.second;
483
- if (u.rounds_for_zombie == 0) {
550
+ void Board::execute_conversion_to_zombie()
551
+ {
552
+ for (auto &p : units)
553
+ {
554
+ Unit &u = p.second;
555
+ if (u.rounds_for_zombie == 0)
556
+ {
484
557
  _my_assert(u.type != Zombie, "Cannot convert zombie to zombie");
485
- if (u.type == Alive) { // Alive to zombie
486
- _my_assert(player2alive_units[u.player].count(u.id), "Alive unit not found in player2alive_units");
487
- player2alive_units[u.player].erase(u.id);
488
- zombies_.insert(u.id);
489
- u.type = Zombie;
490
- u.player = -1;
491
- u.rounds_for_zombie = -1;
492
- grid[u.pos.i][u.pos.j].owner = -1;
558
+ if (u.type == Alive)
559
+ { // Alive to zombie
560
+ _my_assert(player2alive_units[u.player].count(u.id), "Alive unit not found in player2alive_units");
561
+ player2alive_units[u.player].erase(u.id);
562
+ zombies_.insert(u.id);
563
+ u.type = Zombie;
564
+ u.player = -1;
565
+ u.rounds_for_zombie = -1;
566
+ grid[u.pos.i][u.pos.j].owner = -1;
493
567
  }
494
- else {
495
- _my_assert(u.type == Dead, "If not zombie or alive, should be dead");
496
- _my_assert(player2dead_units[u.player].count(u.id), "Dead unit not found in player2dead_units");
497
- player2dead_units[u.player].erase(u.id);
498
- zombies_.insert(u.id);
499
- u.type = Zombie;
500
- u.player = -1;
501
- u.rounds_for_zombie = -1;
502
- grid[u.pos.i][u.pos.j].owner = -1;
568
+ else
569
+ {
570
+ _my_assert(u.type == Dead, "If not zombie or alive, should be dead");
571
+ _my_assert(player2dead_units[u.player].count(u.id), "Dead unit not found in player2dead_units");
572
+ player2dead_units[u.player].erase(u.id);
573
+ zombies_.insert(u.id);
574
+ u.type = Zombie;
575
+ u.player = -1;
576
+ u.rounds_for_zombie = -1;
577
+ grid[u.pos.i][u.pos.j].owner = -1;
503
578
  }
504
579
  }
505
580
  }
506
581
  }
507
582
 
508
- void Board::execute_conversion_zombie_to_alive (vector<vector<int>>& zombie_to_unit) {
509
- for (int p = 0; p < num_players(); ++p) {
510
- for (int id : zombie_to_unit[p]) {
583
+ void Board::execute_conversion_zombie_to_alive(vector<vector<int>> &zombie_to_unit)
584
+ {
585
+ for (int p = 0; p < num_players(); ++p)
586
+ {
587
+ for (int id : zombie_to_unit[p])
588
+ {
511
589
  _my_assert(units.count(id) != 0, "Unit which should be converted zombie->unit not found in units");
512
590
  _my_assert(zombies_.count(id) != 0, "Unit which should be converted zombie->unit not found in zombies_");
513
591
  _my_assert(units[id].type == Zombie, "Unit in zombie_to_unit is not a zombie");
514
- Pos new_pos = get_random_pos_where_regenerate( );
515
- Unit& u = units[id];
592
+ Pos new_pos = get_random_pos_where_regenerate();
593
+ Unit &u = units[id];
516
594
  u.type = Alive;
517
595
  u.player = p;
518
596
  u.pos = new_pos;
@@ -520,211 +598,250 @@ void Board::execute_conversion_zombie_to_alive (vector<vector<int>>& zombie_to_u
520
598
  zombies_.erase(id);
521
599
  player2alive_units[p].insert(id);
522
600
 
523
- Cell& c = grid[new_pos.i][new_pos.j];
601
+ Cell &c = grid[new_pos.i][new_pos.j];
524
602
  c.owner = p;
525
603
  c.id = id;
526
604
  }
527
605
  }
528
606
  }
529
607
 
530
- void Board::execute_conversion_alive_to_dead (vector<vector<int>>& alive_to_dead) {
531
- for (int p = 0; p < num_players(); ++p) {
532
- for (int id : alive_to_dead[p]) {
608
+ void Board::execute_conversion_alive_to_dead(vector<vector<int>> &alive_to_dead)
609
+ {
610
+ for (int p = 0; p < num_players(); ++p)
611
+ {
612
+ for (int id : alive_to_dead[p])
613
+ {
533
614
  _my_assert(units.count(id) != 0, "Unit which should be converted alive->dead not found in units");
534
615
  _my_assert(player2alive_units[p].count(id) != 0, "Unit which should be converted alive->dead not found in player2alive_units");
535
616
  _my_assert(units[id].type == Dead, "Unit in alive_to_dead should have already been markes as dead");
536
- Unit& u = units[id];
617
+ Unit &u = units[id];
537
618
  u.type = Dead;
538
619
  u.player = p;
539
620
  u.rounds_for_zombie = rounds_before_becoming_zombie();
540
621
  player2alive_units[p].erase(id);
541
622
  player2dead_units[p].insert(id);
542
623
  }
543
- }
624
+ }
544
625
  }
545
626
 
546
- pair<int,int> Board::selectLargestSmallestClan ( ) {
547
- vector<pair<int,int>> alive_clan(num_players());
548
- for (uint p = 0; p < alive_clan.size(); ++p) alive_clan[p] = {player2alive_units[p].size(),p};
549
- sort(alive_clan.begin(),alive_clan.end(),greater<pair<int,int>>()); // sort descending
550
-
551
- if (alive_clan[0].first == alive_clan.back().first) { // All clans same number of alive units
552
- int clan_wins = random(0,3);
553
- int clan_loses = random(0,3);
554
- while (clan_loses == clan_wins) clan_loses = random(0,3);
627
+ pair<int, int> Board::selectLargestSmallestClan()
628
+ {
629
+ vector<pair<int, int>> alive_clan(num_players());
630
+ for (uint p = 0; p < alive_clan.size(); ++p)
631
+ alive_clan[p] = {player2alive_units[p].size(), p};
632
+ sort(alive_clan.begin(), alive_clan.end(), greater<pair<int, int>>()); // sort descending
633
+
634
+ if (alive_clan[0].first == alive_clan.back().first)
635
+ { // All clans same number of alive units
636
+ int clan_wins = random(0, 3);
637
+ int clan_loses = random(0, 3);
638
+ while (clan_loses == clan_wins)
639
+ clan_loses = random(0, 3);
555
640
  return {clan_wins, clan_loses};
556
641
  }
557
642
 
558
643
  vector<int> largest_clans = {alive_clan[0].second};
559
644
  int i = 1;
560
- while (i < int(alive_clan.size()) and alive_clan[i].first == alive_clan[0].first) {
645
+ while (i < int(alive_clan.size()) and alive_clan[i].first == alive_clan[0].first)
646
+ {
561
647
  largest_clans.push_back(alive_clan[i].second);
562
648
  ++i;
563
649
  }
564
650
 
565
-
566
- int clan_that_loses_unit = largest_clans[random(0,largest_clans.size()-1)];
651
+ int clan_that_loses_unit = largest_clans[random(0, largest_clans.size() - 1)];
567
652
 
568
653
  vector<int> smallest_clans = {alive_clan.back().second};
569
654
  i = int(alive_clan.size()) - 2;
570
- while (i >= 0 and alive_clan[i].first == alive_clan.back().first) {
655
+ while (i >= 0 and alive_clan[i].first == alive_clan.back().first)
656
+ {
571
657
  smallest_clans.push_back(alive_clan[i].second);
572
658
  --i;
573
659
  }
574
660
 
575
- int clan_that_wins_unit = smallest_clans[random(0,smallest_clans.size()-1)];
661
+ int clan_that_wins_unit = smallest_clans[random(0, smallest_clans.size() - 1)];
576
662
  return {clan_that_wins_unit, clan_that_loses_unit};
577
663
  }
578
664
 
579
- void Board::execute_random_conversion_live_unit ( ) {
580
- if (random(0,4) != 0) return; // 20% probability of conversion
665
+ void Board::execute_random_conversion_live_unit()
666
+ {
667
+ if (random(0, 4) != 0)
668
+ return; // 20% probability of conversion
581
669
 
582
- pair<int,int> tmp = selectLargestSmallestClan();
670
+ pair<int, int> tmp = selectLargestSmallestClan();
583
671
  int wins = tmp.first;
584
672
  int loses = tmp.second;
585
-
673
+
586
674
  _my_assert(wins != loses, "A clan cannot win and lose a unit");
587
675
 
588
- if (player2alive_units[loses].size() == 0) return; // No alive unit (very strange)
589
-
676
+ if (player2alive_units[loses].size() == 0)
677
+ return; // No alive unit (very strange)
678
+
590
679
  // Choose randomly a unit from clan "loses"
591
- int k = random(0,player2alive_units[loses].size()-1);
680
+ int k = random(0, player2alive_units[loses].size() - 1);
592
681
  auto it = player2alive_units[loses].begin();
593
- advance(it,k);
682
+ advance(it, k);
594
683
  int u_t = *it; // unit transferred
595
684
 
596
685
  player2alive_units[loses].erase(it);
597
686
  player2alive_units[wins].insert(u_t);
598
- Unit& u = units[u_t];
687
+ Unit &u = units[u_t];
599
688
  _my_assert(u.type == Alive, "Transferred unit should be alive");
600
689
  u.player = wins;
601
- grid[u.pos.i][u.pos.j].owner = wins;
690
+ grid[u.pos.i][u.pos.j].owner = wins;
602
691
  }
603
692
 
604
- void Board::decrement_rounds_for_becoming_zombie ( ) {
605
- for (auto& p : units) {
606
- Unit& u = p.second;
607
- if (u.rounds_for_zombie > 0)
693
+ void Board::decrement_rounds_for_becoming_zombie()
694
+ {
695
+ for (auto &p : units)
696
+ {
697
+ Unit &u = p.second;
698
+ if (u.rounds_for_zombie > 0)
608
699
  --u.rounds_for_zombie;
609
700
  }
610
701
  }
611
702
 
612
- void Board::generate_food_item ( ){
613
- Pos p = get_random_pos_where_regenerate( );
614
- Cell& c = grid[p.i][p.j];
703
+ void Board::generate_food_item()
704
+ {
705
+ Pos p = get_random_pos_where_regenerate();
706
+ Cell &c = grid[p.i][p.j];
615
707
  c.food = true;
616
- _my_assert(c.id == -1 and c.type == Street, "Generated food in already full cell");
708
+ _my_assert(c.id == -1 and c.type == Street, "Generated food in already full cell");
617
709
  }
618
710
 
619
- void Board::regenerate_food_and_update_strength (vector<int>& food_to_regenerate) {
620
- for (int p = 0; p < num_players(); ++p) {
621
- overall_strength[p] += food_strength()*food_to_regenerate[p];
711
+ void Board::regenerate_food_and_update_strength(vector<int> &food_to_regenerate)
712
+ {
713
+ for (int p = 0; p < num_players(); ++p)
714
+ {
715
+ overall_strength[p] += food_strength() * food_to_regenerate[p];
622
716
  overall_strength[p] -= player2alive_units[p].size(); // One unit of food is eaten by each alive unit
623
- overall_strength[p] = max(0,overall_strength[p]); // Strength >= 0
624
- for (int k = 0; k < food_to_regenerate[p];++k)
717
+ overall_strength[p] = max(0, overall_strength[p]); // Strength >= 0
718
+ for (int k = 0; k < food_to_regenerate[p]; ++k)
625
719
  generate_food_item();
626
720
  }
627
721
 
628
722
  // Food items eaten by zombies
629
- for (int k = 0; k < food_to_regenerate.back();++k)
630
- generate_food_item();
723
+ for (int k = 0; k < food_to_regenerate.back(); ++k)
724
+ generate_food_item();
631
725
  }
632
726
 
633
- void Board::update_nb_cells ( ) {
727
+ void Board::update_nb_cells()
728
+ {
634
729
  // Set all to zero
635
- for (auto& x : nb_cells) x = 0;
730
+ for (auto &x : nb_cells)
731
+ x = 0;
636
732
 
637
733
  // Add the ones in the grid
638
734
  for (int i = 0; i < board_rows(); ++i)
639
- for (int j = 0; j < board_cols(); ++j)
640
- if (grid[i][j].owner != -1)
641
- ++nb_cells[grid[i][j].owner];
735
+ for (int j = 0; j < board_cols(); ++j)
736
+ if (grid[i][j].owner != -1)
737
+ ++nb_cells[grid[i][j].owner];
642
738
  }
643
739
 
644
- void Board::update_score ( ) {
740
+ void Board::update_score()
741
+ {
645
742
  for (int p = 0; p < num_players(); ++p)
646
- scr[p] = scr_accumulated[p] + nb_cells[p]*1;
743
+ scr[p] = scr_accumulated[p] + nb_cells[p] * 1;
647
744
  }
648
745
 
649
- bool Board::cell_has_dead_unit (int i, int j){
650
- if (grid[i][j].id == -1) return false;
651
- Unit& u = units[grid[i][j].id];
746
+ bool Board::cell_has_dead_unit(int i, int j)
747
+ {
748
+ if (grid[i][j].id == -1)
749
+ return false;
750
+ Unit &u = units[grid[i][j].id];
652
751
  return (u.type == Dead);
653
752
  }
654
753
 
655
- bool Board::cell_has_zombie (int i, int j){
656
- if (grid[i][j].id == -1) return false;
657
- Unit& u = units[grid[i][j].id];
754
+ bool Board::cell_has_zombie(int i, int j)
755
+ {
756
+ if (grid[i][j].id == -1)
757
+ return false;
758
+ Unit &u = units[grid[i][j].id];
658
759
  return (u.type == Zombie);
659
760
  }
660
761
 
661
- void Board::move_zombies (vector<int>& food_to_regenerate, vector<vector<int>>& zombie_to_unit, vector<vector<int>>& alive_to_dead, vector<Command>& commands_done) {
762
+ void Board::move_zombies(vector<int> &food_to_regenerate, vector<vector<int>> &zombie_to_unit, vector<vector<int>> &alive_to_dead, vector<Command> &commands_done)
763
+ {
662
764
  // First compute distances
663
765
  int r = board_rows();
664
766
  int c = board_cols();
665
767
 
666
768
  int inf = 1e9;
667
- vector<vector<int>> T(r,vector<int>(c,inf));
769
+ vector<vector<int>> T(r, vector<int>(c, inf));
668
770
  queue<Pos> Q;
669
771
  for (int i = 0; i < r; ++i)
670
- for (int j = 0; j < c; ++j) {
671
- const Cell& c = grid[i][j];
672
- if (c.id != -1 and units[c.id].type == Alive) {
673
- Q.push(Pos(i,j));
674
- T[i][j] = 0;
772
+ for (int j = 0; j < c; ++j)
773
+ {
774
+ const Cell &c = grid[i][j];
775
+ if (c.id != -1 and units[c.id].type == Alive)
776
+ {
777
+ Q.push(Pos(i, j));
778
+ T[i][j] = 0;
675
779
  }
676
780
  }
677
-
678
- while (not Q.empty()) {
679
- Pos p = Q.front(); Q.pop();
680
- for (auto d : {Down, DR, Right, RU, Up, UL, Left, LD}) {
781
+
782
+ while (not Q.empty())
783
+ {
784
+ Pos p = Q.front();
785
+ Q.pop();
786
+ for (auto d : {Down, DR, Right, RU, Up, UL, Left, LD})
787
+ {
681
788
  Pos np = p + d;
682
789
  if (pos_ok(np) and
683
- not cell_has_dead_unit(np.i,np.j) and
684
- not cell_has_zombie(np.i, np.j) and
685
- grid[np.i][np.j].type != Waste and
686
- T[np.i][np.j] == inf
687
- ) {
688
- T[np.i][np.j] = T[p.i][p.j] + 1;
689
- Q.push(np);
790
+ not cell_has_dead_unit(np.i, np.j) and
791
+ not cell_has_zombie(np.i, np.j) and
792
+ grid[np.i][np.j].type != Waste and
793
+ T[np.i][np.j] == inf)
794
+ {
795
+ T[np.i][np.j] = T[p.i][p.j] + 1;
796
+ Q.push(np);
690
797
  }
691
798
  }
692
799
  }
693
800
 
694
- for (int z_id : zombies_) {
695
- if (units[z_id].pos != Pos(-1,-1)) { // Not dead
696
- const Unit& u = units[z_id];
801
+ for (int z_id : zombies_)
802
+ {
803
+ if (units[z_id].pos != Pos(-1, -1))
804
+ { // Not dead
805
+ const Unit &u = units[z_id];
697
806
  Pos p1 = u.pos;
698
807
  vector<int> C;
699
808
  int minim = 1e8;
700
- for (int d = 0; d < 8; ++d) {
701
- Pos p2 = p1 + Dir(d);
702
- if (pos_ok(p2)) {
703
- int dist = T[p2.i][p2.j];
704
- if (dist < minim) {
705
- minim = dist;
706
- C = {d};
707
- }
708
- else if (dist == minim) C.push_back(d);
709
- }
809
+ for (int d = 0; d < 8; ++d)
810
+ {
811
+ Pos p2 = p1 + Dir(d);
812
+ if (pos_ok(p2))
813
+ {
814
+ int dist = T[p2.i][p2.j];
815
+ if (dist < minim)
816
+ {
817
+ minim = dist;
818
+ C = {d};
819
+ }
820
+ else if (dist == minim)
821
+ C.push_back(d);
822
+ }
710
823
  }
711
824
 
712
- if (not C.empty()){
713
- Dir dir = Dir(C[random(0, C.size() - 1)]);
714
- Command com(z_id,Move,dir);
715
- if (execute(com, food_to_regenerate, zombie_to_unit, alive_to_dead)){
716
- commands_done.push_back(com);
717
- }
825
+ if (not C.empty())
826
+ {
827
+ Dir dir = Dir(C[random(0, C.size() - 1)]);
828
+ Command com(z_id, Move, dir);
829
+ if (execute(com, food_to_regenerate, zombie_to_unit, alive_to_dead))
830
+ {
831
+ commands_done.push_back(com);
832
+ }
718
833
  }
719
834
  }
720
835
  }
721
836
  }
722
837
 
723
- vector<Dir> Board::dir_permutation ( ) {
838
+ vector<Dir> Board::dir_permutation()
839
+ {
724
840
  vector<Dir> dirs = {Up, Down, Left, Right};
725
841
  vector<int> p = random_permutation(4);
726
842
  vector<Dir> new_dirs(4);
727
- for (int i = 0; i < 4; ++i) new_dirs[i] = dirs[p[i]];
843
+ for (int i = 0; i < 4; ++i)
844
+ new_dirs[i] = dirs[p[i]];
728
845
  return new_dirs;
729
846
  }
730
847
 
@@ -732,37 +849,43 @@ vector<Dir> Board::dir_permutation ( ) {
732
849
  // BOARD GENERATION
733
850
  //************************************************************
734
851
 
735
- int Board::generate_waste (int s_id, int length) {
852
+ int Board::generate_waste(int s_id, int length)
853
+ {
736
854
  int filled = 0;
737
855
  vector<Dir> dirs = {Up, Down, Left, Right};
738
- Dir last_dir = dirs[random(0,dirs.size()-1)];
856
+ Dir last_dir = dirs[random(0, dirs.size() - 1)];
739
857
  Pos p = get_ok_pos_for_initial_street();
740
858
  street_plan[p.i][p.j] = s_id;
741
859
  ++filled;
742
- while (length > 0) {
743
- random_shuffle(dirs.begin(),dirs.end()); // Careful: this does not behave the same in MAC
744
- //dirs = dir_permutation();
860
+ while (length > 0)
861
+ {
862
+ shuffle_vector(dirs);
863
+ // dirs = dir_permutation();
745
864
  Dir new_possible_dir = Up; // Explore the possibility of turning
746
865
  bool dir_found = false;
747
- for (auto& d:dirs) {
748
- if (pos_ok_for_street(s_id,p+d)){
749
- new_possible_dir = d;
750
- dir_found = true;
751
- break;
866
+ for (auto &d : dirs)
867
+ {
868
+ if (pos_ok_for_street(s_id, p + d))
869
+ {
870
+ new_possible_dir = d;
871
+ dir_found = true;
872
+ break;
752
873
  }
753
874
  }
754
-
755
- if (random(1,8) != 1 and pos_ok_for_street(s_id,p+last_dir)){ // Continue same direction
875
+
876
+ if (random(1, 8) != 1 and pos_ok_for_street(s_id, p + last_dir))
877
+ { // Continue same direction
756
878
  p += last_dir;
757
879
  street_plan[p.i][p.j] = s_id;
758
880
  --length;
759
881
  ++filled;
760
882
  }
761
- else if (dir_found){ // Turn
883
+ else if (dir_found)
884
+ { // Turn
762
885
  last_dir = new_possible_dir;
763
- _my_assert(cell(p+new_possible_dir).is_empty(), "Cell no empty");
886
+ _my_assert(cell(p + new_possible_dir).is_empty(), "Cell no empty");
764
887
  p += new_possible_dir;
765
- _my_assert(pos_ok_for_street(s_id,p), "Pos not ok for street.");
888
+ _my_assert(pos_ok_for_street(s_id, p), "Pos not ok for street.");
766
889
  street_plan[p.i][p.j] = s_id;
767
890
  --length;
768
891
  ++filled;
@@ -773,129 +896,176 @@ int Board::generate_waste (int s_id, int length) {
773
896
  return filled;
774
897
  }
775
898
 
776
- void Board::generate_all_waste (int num_waste_cells, int num_streets){
777
- street_plan = vector<vector<int>>(board_rows(),vector<int>(board_cols(),0));
778
-
899
+ void Board::generate_all_waste(int num_waste_cells, int num_streets)
900
+ {
901
+ street_plan = vector<vector<int>>(board_rows(), vector<int>(board_cols(), 0));
902
+
779
903
  int num_streets_pending = num_streets;
780
- while (num_streets_pending > 0) {
904
+ while (num_streets_pending > 0)
905
+ {
781
906
  int length;
782
- if (num_streets_pending != 1) length = num_waste_cells/num_streets_pending;
783
- else length = num_waste_cells;
784
- num_waste_cells -= generate_waste(num_streets_pending,length);
907
+ if (num_streets_pending != 1)
908
+ length = num_waste_cells / num_streets_pending;
909
+ else
910
+ length = num_waste_cells;
911
+ num_waste_cells -= generate_waste(num_streets_pending, length);
785
912
  --num_streets_pending;
786
913
  }
787
914
 
788
- for (int i = 0; i < board_rows(); ++i) {
789
- for (int j = 0; j < board_cols(); ++j){
790
- if (street_plan[i][j] != 0) {
791
- grid[i][j].type = Waste;
915
+ for (int i = 0; i < board_rows(); ++i)
916
+ {
917
+ for (int j = 0; j < board_cols(); ++j)
918
+ {
919
+ if (street_plan[i][j] != 0)
920
+ {
921
+ grid[i][j].type = Waste;
792
922
  }
793
923
  }
794
924
  }
795
-
796
925
  }
797
926
 
798
- Pos Board::get_empty_pos ( ){
799
- while (true) {
800
- int i = random(0,board_rows()-1);
801
- int j = random(0,board_cols()-1);
802
- if (cell(i,j).is_empty()) return Pos(i,j);
927
+ Pos Board::get_empty_pos()
928
+ {
929
+ while (true)
930
+ {
931
+ int i = random(0, board_rows() - 1);
932
+ int j = random(0, board_cols() - 1);
933
+ if (cell(i, j).is_empty())
934
+ return Pos(i, j);
803
935
  }
804
936
  }
805
937
 
806
- Pos Board::get_ok_pos_for_street(int s_id) {
807
- while (true) {
808
- int i = random(1,board_rows()-2);
809
- int j = random(1,board_cols()-2);
810
- if (pos_ok_for_street(s_id, Pos(i,j))) return Pos(i,j);
938
+ Pos Board::get_ok_pos_for_street(int s_id)
939
+ {
940
+ while (true)
941
+ {
942
+ int i = random(1, board_rows() - 2);
943
+ int j = random(1, board_cols() - 2);
944
+ if (pos_ok_for_street(s_id, Pos(i, j)))
945
+ return Pos(i, j);
811
946
  }
812
947
  }
813
948
 
814
- Pos Board::get_ok_pos_for_initial_street() {
815
- while (true) {
816
- int i = random(1,board_rows()-2);
817
- int j = random(1,board_cols()-2);
818
- if (pos_ok_for_initial_street(Pos(i,j))) return Pos(i,j);
949
+ Pos Board::get_ok_pos_for_initial_street()
950
+ {
951
+ while (true)
952
+ {
953
+ int i = random(1, board_rows() - 2);
954
+ int j = random(1, board_cols() - 2);
955
+ if (pos_ok_for_initial_street(Pos(i, j)))
956
+ return Pos(i, j);
819
957
  }
820
958
  }
821
959
 
822
- bool Board::pos_ok_for_street(int s_id, const Pos& p){
960
+ bool Board::pos_ok_for_street(int s_id, const Pos &p)
961
+ {
823
962
  int i = p.i, j = p.j;
824
- if (not pos_ok(p)) return false;
825
- if (street_plan[i][j] != 0) return false;
826
- if (i == 0) return false;
827
- if (i == board_rows() -1) return false;
828
- if (j == 0) return false;
829
- if (j == board_cols() -1) return false;
963
+ if (not pos_ok(p))
964
+ return false;
965
+ if (street_plan[i][j] != 0)
966
+ return false;
967
+ if (i == 0)
968
+ return false;
969
+ if (i == board_rows() - 1)
970
+ return false;
971
+ if (j == 0)
972
+ return false;
973
+ if (j == board_cols() - 1)
974
+ return false;
830
975
 
831
976
  int num_occupied = 0;
832
977
  vector<Dir> dirs = {Up, Down, Left, Right};
833
- for (auto& d: dirs) {
978
+ for (auto &d : dirs)
979
+ {
834
980
  Pos newPos = p + d; // Will exists because p is not on a border
835
981
  int ni = newPos.i, nj = newPos.j;
836
- if (street_plan[ni][nj] != 0 and street_plan[ni][nj] != s_id) return false;
837
- else if (street_plan[ni][nj] == s_id) ++num_occupied;
982
+ if (street_plan[ni][nj] != 0 and street_plan[ni][nj] != s_id)
983
+ return false;
984
+ else if (street_plan[ni][nj] == s_id)
985
+ ++num_occupied;
838
986
  }
839
987
 
840
- vector<pair<int,int>> diags = {{1,1},{1,-1},{-1,1},{-1,-1}};
841
- for (auto& d : diags) {
988
+ vector<pair<int, int>> diags = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
989
+ for (auto &d : diags)
990
+ {
842
991
  Pos newPos = Pos(p.i + d.first, p.j + d.second);
843
992
  int ni = newPos.i, nj = newPos.j;
844
- if (street_plan[ni][nj] != 0 and street_plan[ni][nj] != s_id) return false;
845
- else if (street_plan[ni][nj] == s_id) ++num_occupied;
993
+ if (street_plan[ni][nj] != 0 and street_plan[ni][nj] != s_id)
994
+ return false;
995
+ else if (street_plan[ni][nj] == s_id)
996
+ ++num_occupied;
846
997
  }
847
-
998
+
848
999
  return num_occupied <= 2;
849
1000
  }
850
1001
 
851
- bool Board::pos_ok_for_initial_street(const Pos& p){
1002
+ bool Board::pos_ok_for_initial_street(const Pos &p)
1003
+ {
852
1004
  int i = p.i, j = p.j;
853
- if (not pos_ok(p)) return false;
854
- if (street_plan[i][j] != 0) return false;
855
- if (i == 0) return false;
856
- if (i == board_rows() -1) return false;
857
- if (j == 0) return false;
858
- if (j == board_cols() -1) return false;
1005
+ if (not pos_ok(p))
1006
+ return false;
1007
+ if (street_plan[i][j] != 0)
1008
+ return false;
1009
+ if (i == 0)
1010
+ return false;
1011
+ if (i == board_rows() - 1)
1012
+ return false;
1013
+ if (j == 0)
1014
+ return false;
1015
+ if (j == board_cols() - 1)
1016
+ return false;
859
1017
 
860
1018
  int num_occupied = 0;
861
1019
  vector<Dir> dirs = {Up, Down, Left, Right};
862
- for (auto& d: dirs) {
1020
+ for (auto &d : dirs)
1021
+ {
863
1022
  Pos newPos = p + d; // Will exists because p is not on a border
864
1023
  int n_i = newPos.i, n_j = newPos.j;
865
- if (street_plan[n_i][n_j] != 0) return false;
1024
+ if (street_plan[n_i][n_j] != 0)
1025
+ return false;
866
1026
  }
867
1027
 
868
- vector<pair<int,int>> diags = {{1,1},{1,-1},{-1,1},{-1,-1}};
869
- for (auto& d : diags) {
1028
+ vector<pair<int, int>> diags = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
1029
+ for (auto &d : diags)
1030
+ {
870
1031
  Pos newPos = Pos(p.i + d.first, p.j + d.second);
871
1032
  int n_i = newPos.i, n_j = newPos.j;
872
- if (street_plan[n_i][n_j] != 0) return false;
1033
+ if (street_plan[n_i][n_j] != 0)
1034
+ return false;
873
1035
  }
874
-
1036
+
875
1037
  return true;
876
1038
  }
877
1039
 
878
- void Board::explore_from(vector<vector<int>>& G, int i, int j, int n) {
1040
+ void Board::explore_from(vector<vector<int>> &G, int i, int j, int n)
1041
+ {
879
1042
  G[i][j] = n;
880
- for (auto& d:{Up,Down,Left,Right}) {
881
- Pos np = Pos(i,j) + d;
882
- if (pos_ok(np) and G[np.i][np.j] == -1) explore_from(G,np.i,np.j,n);
1043
+ for (auto &d : {Up, Down, Left, Right})
1044
+ {
1045
+ Pos np = Pos(i, j) + d;
1046
+ if (pos_ok(np) and G[np.i][np.j] == -1)
1047
+ explore_from(G, np.i, np.j, n);
883
1048
  }
884
1049
  }
885
1050
 
886
- int Board::num_connected_components( ){
887
- vector<vector<int>> G(board_rows(),vector<int>(board_cols(),-1));
1051
+ int Board::num_connected_components()
1052
+ {
1053
+ vector<vector<int>> G(board_rows(), vector<int>(board_cols(), -1));
888
1054
 
889
- for (int i = 0; i < board_rows(); ++i)
1055
+ for (int i = 0; i < board_rows(); ++i)
890
1056
  for (int j = 0; j < board_cols(); ++j)
891
- if (grid[i][j].type == Waste) G[i][j] = -2;
892
-
893
- int n = 0;
894
- for (int i = 0; i < board_rows(); ++i) {
895
- for (int j = 0; j < board_cols(); ++j){
896
- if (G[i][j] == -1) {
897
- explore_from(G,i,j,n);
898
- ++n;
1057
+ if (grid[i][j].type == Waste)
1058
+ G[i][j] = -2;
1059
+
1060
+ int n = 0;
1061
+ for (int i = 0; i < board_rows(); ++i)
1062
+ {
1063
+ for (int j = 0; j < board_cols(); ++j)
1064
+ {
1065
+ if (G[i][j] == -1)
1066
+ {
1067
+ explore_from(G, i, j, n);
1068
+ ++n;
899
1069
  }
900
1070
  }
901
1071
  }
@@ -903,73 +1073,77 @@ int Board::num_connected_components( ){
903
1073
  return n;
904
1074
  }
905
1075
 
906
- void Board::create_new_unit (Pos& p, int player) {
1076
+ void Board::create_new_unit(Pos &p, int player)
1077
+ {
907
1078
  int id = fresh_id;
908
1079
  ++fresh_id;
909
1080
  _my_assert(not units.count(id), "Identifier is not fresh.");
910
1081
 
911
1082
  units[id] = Unit(Alive, id, player, p, -1);
912
1083
  player2alive_units[player].insert(id);
913
-
914
- _my_assert(grid[p.i][p.j].is_empty(), "Cell is already full.");
1084
+
1085
+ _my_assert(grid[p.i][p.j].is_empty(), "Cell is already full.");
915
1086
 
916
1087
  grid[p.i][p.j].id = id;
917
1088
  grid[p.i][p.j].owner = player;
918
1089
  }
919
1090
 
920
- void Board::create_new_zombie (Pos& p) {
1091
+ void Board::create_new_zombie(Pos &p)
1092
+ {
921
1093
  int id = fresh_id;
922
1094
  ++fresh_id;
923
1095
  _my_assert(not units.count(id), "Identifier is not fresh.");
924
- _my_assert(grid[p.i][p.j].is_empty(), "Cell is already full.");
925
-
1096
+ _my_assert(grid[p.i][p.j].is_empty(), "Cell is already full.");
1097
+
926
1098
  units[id] = Unit(Zombie, id, -1, p, -1);
927
1099
  zombies_.insert(id);
928
1100
 
929
1101
  grid[p.i][p.j].id = id;
930
-
931
1102
  }
932
1103
 
933
- void Board::generate_random_board ( ){
1104
+ void Board::generate_random_board()
1105
+ {
934
1106
  int rows = board_rows();
935
1107
  int cols = board_cols();
936
1108
 
937
-
938
- // Generate buildings (leaving space for citizens)
939
- static const int num_waste_cells = 0.5*rows*cols; // goal of 50% waste
1109
+ // Generate buildings (leaving space for citizens)
1110
+ static const int num_waste_cells = 0.5 * rows * cols; // goal of 50% waste
940
1111
  static const int num_streets = 8;
941
1112
 
942
- do {
1113
+ do
1114
+ {
943
1115
  // Create grid
944
1116
  grid = vector<vector<Cell>>(rows, vector<Cell>(cols));
945
1117
  generate_all_waste(num_waste_cells, num_streets);
946
1118
  } while (num_connected_components() != 1);
947
1119
 
948
- for (int i = 0; i < board_rows(); ++i)
1120
+ for (int i = 0; i < board_rows(); ++i)
949
1121
  for (int j = 0; j < board_cols(); ++j)
950
- if (street_plan[i][j] != 0)
951
- grid[i][j].type = Waste;
952
-
953
-
1122
+ if (street_plan[i][j] != 0)
1123
+ grid[i][j].type = Waste;
1124
+
954
1125
  // Generate units
955
- for (int pl = 0; pl < num_players(); ++pl) {
956
- for (int i = 0; i < num_ini_units_per_clan(); ++i) {
957
- Pos p = get_random_pos_where_regenerate( );
958
- create_new_unit(p,pl);
1126
+ for (int pl = 0; pl < num_players(); ++pl)
1127
+ {
1128
+ for (int i = 0; i < num_ini_units_per_clan(); ++i)
1129
+ {
1130
+ Pos p = get_random_pos_where_regenerate();
1131
+ create_new_unit(p, pl);
959
1132
  ++nb_cells[pl];
960
1133
  }
961
1134
  }
962
1135
 
963
1136
  // Generate zombies
964
- for (int i = 0; i < num_ini_zombies(); ++i) {
965
- Pos p = get_random_pos_where_regenerate( );
1137
+ for (int i = 0; i < num_ini_zombies(); ++i)
1138
+ {
1139
+ Pos p = get_random_pos_where_regenerate();
966
1140
  create_new_zombie(p);
967
1141
  }
968
1142
 
969
1143
  // Generate food
970
- for (int i = 0; i < num_ini_food(); ++i) {
971
- Pos p = get_random_pos_where_regenerate( );
1144
+ for (int i = 0; i < num_ini_food(); ++i)
1145
+ {
1146
+ Pos p = get_random_pos_where_regenerate();
972
1147
  grid[p.i][p.j].food = true;
973
1148
  }
974
1149
  }
975
-