game.c (41115B)
1 /* game.c - reglas: validacion (game_check) y aplicacion (game_apply) de movidas. */ 2 #include <string.h> 3 #include "catan.h" 4 5 const uint8_t COST_ROAD[NRES] = { 1, 1, 0, 0, 0 }; 6 const uint8_t COST_SETTLE[NRES] = { 1, 1, 1, 1, 0 }; 7 const uint8_t COST_CITY[NRES] = { 0, 0, 0, 2, 3 }; 8 const uint8_t COST_DEV[NRES] = { 0, 0, 1, 1, 1 }; 9 const uint8_t COST_SHIP[NRES] = { 0, 1, 1, 0, 0 }; 10 11 void opts_default(Opts *o, int players, bool variant2p) 12 { 13 memset(o, 0, sizeof *o); 14 o->variant2p = variant2p && players == 2; 15 o->np = o->variant2p ? 4 : (uint8_t)players; 16 o->vp_target = 10; 17 o->friendly_robber = o->variant2p; 18 o->tokens_start = 2; 19 o->neutral_setup = 2; 20 o->beginner = 0; 21 } 22 23 int opts_family(const Opts *o) 24 { 25 #ifdef CATAN_SMALL 26 (void)o; 27 return BF_CLASSIC; 28 #else 29 if (o->scenario && o->np <= 4) return BF_SEA1 + o->scenario - SCEN_SEA1; 30 return o->np > 4 ? BF_LARGE : BF_CLASSIC; 31 #endif 32 } 33 34 int opts_board(const Opts *o) 35 { 36 #ifdef CATAN_SMALL 37 (void)o; 38 return BOARD_CLASSIC; 39 #else 40 return opts_family(o) * NMAPS + (o->map < NMAPS ? o->map : 0); 41 #endif 42 } 43 44 void opts_scenario(Opts *o, int scenario) 45 { 46 o->scenario = (uint8_t)(scenario > SCEN_NONE && scenario < SCEN__COUNT ? scenario : SCEN_NONE); 47 if (o->scenario) { o->vp_target = 13; o->beginner = 0; } 48 } 49 50 bool game_has_sea(const Game *g) { return game_topo(g)->sea; } 51 52 int bank_start(const Opts *o) { return opts_family(o) == BF_LARGE ? 24 : 19; } 53 54 int dev_counts(const Opts *o, uint8_t out[]) 55 { 56 static const uint8_t C[2][NDEV] = { { 14, 2, 2, 2, 5 }, { 20, 3, 3, 3, 5 } }; 57 int big = opts_family(o) == BF_LARGE, n = 0; 58 for (int d = 0; d < NDEV; d++) { out[d] = C[big][d]; n += out[d]; } 59 return n; 60 } 61 62 int res_total(const uint8_t r[NRES]) 63 { 64 int n = 0; 65 for (int i = 0; i < NRES; i++) n += r[i]; 66 return n; 67 } 68 69 int hand_size(const Game *g, int p) { return res_total(g->p[p].res); } 70 71 bool game_is_neutral(const Game *g, int p) { return p >= 0 && p < g->o.np && g->p[p].neutral; } 72 73 static int desert_hex(const Game *g) 74 { 75 for (int h = 0; h < game_topo(g)->nhex; h++) 76 if (g->terrain[h] == T_DESERT) return h; 77 return 0; 78 } 79 80 /* el pueblo que p pone ahora en el setup es el segundo (cobra recursos) */ 81 static bool setup_second(const Game *g, int p) 82 { 83 for (int i = 0; i < g->setup_i; i++) 84 if (g->setup_order[i] == p) return true; 85 return false; 86 } 87 88 void game_init(Game *g, const Opts *o) 89 { 90 uint8_t ter[NHEX], num[NHEX], port[NPORT]; 91 memcpy(ter, g->terrain, sizeof ter); 92 memcpy(num, g->num, sizeof num); 93 memcpy(port, g->port, sizeof port); 94 memset(g, 0, sizeof *g); 95 memcpy(g->terrain, ter, sizeof ter); 96 memcpy(g->num, num, sizeof num); 97 memcpy(g->port, port, sizeof port); 98 99 g->o = *o; 100 for (int v = 0; v < NVERT; v++) g->vown[v] = -1; 101 for (int e = 0; e < NEDGE; e++) g->eown[e] = -1; 102 g->o.board = (uint8_t)opts_board(o); 103 { /* lo que este tablero no usa queda en cero */ 104 const Topo *t = game_topo(g); 105 for (int h = t->nhex; h < NHEX; h++) g->terrain[h] = g->num[h] = 0; 106 for (int i = t->nport; i < NPORT; i++) g->port[i] = 0; 107 } 108 uint8_t cnt[NDEV]; 109 for (int r = 0; r < NRES; r++) g->bank[r] = (uint8_t)bank_start(&g->o); 110 g->deck_n = (uint8_t)dev_counts(&g->o, cnt); 111 g->robber = (uint8_t)desert_hex(g); 112 g->pirate = game_has_sea(g) ? (uint8_t)game_topo(g)->sea_start : 0xFF; 113 for (int i = 0; i < o->np; i++) { 114 Player *pl = &g->p[i]; 115 pl->roads = MAX_ROADS; pl->settles = MAX_SETTLES; pl->cities = MAX_CITIES; 116 pl->ships = game_has_sea(g) ? MAX_SHIPS : 0; 117 pl->neutral = o->variant2p && i >= 2; 118 pl->tokens = o->variant2p && !pl->neutral ? o->tokens_start : 0; 119 } 120 g->longest = g->army = g->winner = -1; 121 g->phase = PH_SETUP; 122 /* serpiente (1 2 3 4 4 3 2 1); con setup_first, primero la serpiente de esos 123 * asientos y despues la del resto (ej. humano contra bots: 1 1 2 3 4 4 3 2) */ 124 int n = 0, first = o->first < o->np ? o->first : 0; /* desde que asiento se da la vuelta a la mesa */ 125 for (int grp = 0; grp < 2; grp++) { 126 int real[MAXP], nr = 0; 127 for (int k = 0; k < o->np; k++) { 128 int i = (first + k) % o->np; 129 if (!g->p[i].neutral && ((o->setup_first >> i & 1) == (grp == 0))) real[nr++] = i; 130 } 131 for (int i = 0; i < nr; i++) { 132 g->setup_order[n + i] = (uint8_t)real[i]; 133 g->setup_order[n + 2 * nr - 1 - i] = (uint8_t)real[i]; 134 } 135 n += 2 * nr; 136 } 137 g->setup_n = (uint8_t)n; 138 g->cur = g->setup_order[0]; 139 g->setup_v = -1; 140 } 141 142 int game_next_player(const Game *g, int p) 143 { 144 for (int i = 1; i <= g->o.np; i++) { 145 int q = (p + i) % g->o.np; 146 if (!g->p[q].neutral) return q; 147 } 148 return p; 149 } 150 151 uint8_t game_offer_candidates(const Game *g, int p) 152 { 153 uint8_t m = 0; 154 for (int q = 0; q < g->o.np; q++) 155 if (q != p && !g->p[q].neutral) m |= (uint8_t)(1 << q); 156 return m; 157 } 158 159 int game_rival(const Game *g, int p) 160 { 161 for (int q = 0; q < g->o.np; q++) 162 if (q != p && !g->p[q].neutral) return q; 163 return -1; 164 } 165 166 /* ------------------------------------------------------------------ puntos */ 167 168 int game_vp_public(const Game *g, int p) 169 { 170 const Player *pl = &g->p[p]; 171 int vp = (MAX_SETTLES - pl->settles) + 2 * (MAX_CITIES - pl->cities) + pl->bonus; 172 if (g->longest == p) vp += 2; 173 if (g->army == p) vp += 2; 174 return vp; 175 } 176 177 int game_vp(const Game *g, int p) 178 { 179 return game_vp_public(g, p) + g->p[p].dev[D_VP] + g->p[p].dev_new[D_VP]; 180 } 181 182 int game_token_cost(const Game *g, int p) 183 { 184 int r = game_rival(g, p); 185 return (r >= 0 && game_vp_public(g, p) > game_vp_public(g, r)) ? 2 : 1; 186 } 187 188 /* -------------------------------------------------------------- colocacion */ 189 190 static bool vert_free_dist(const Game *g, int v) 191 { 192 const Topo *t = game_topo(g); 193 if (g->vown[v] >= 0) return false; 194 for (int k = 0; k < 3; k++) { 195 int u = t->vert_adj[v][k]; 196 if (u >= 0 && g->vown[u] >= 0) return false; 197 } 198 return true; 199 } 200 201 /* el vertice toca tierra (con mar, hay vertices rodeados de agua); region: -1 cualquiera, 202 * -2 alguna de arranque */ 203 static bool vert_land(const Game *g, int v, int region) 204 { 205 const Topo *t = game_topo(g); 206 for (int k = 0; k < 3; k++) { 207 int h = t->vert_hex[v][k]; 208 if (h < 0 || !ter_land(g->terrain[h])) continue; 209 if (region == -1 || t->region[h] == region) return true; 210 if (region == -2 && t->region[h] >= 0 && t->region[h] < 8 && ((t->home >> t->region[h]) & 1)) return true; 211 } 212 return false; 213 } 214 215 /* arista con tierra de algun lado (rutas) / con mar de algun lado (barcos) */ 216 static bool edge_land(const Game *g, int e) 217 { 218 const Topo *t = game_topo(g); 219 for (int s = 0; s < 2; s++) { 220 int h = t->edge_hex[e][s]; 221 if (h >= 0 && ter_land(g->terrain[h])) return true; 222 } 223 return false; 224 } 225 226 static bool edge_sea(const Game *g, int e) 227 { 228 const Topo *t = game_topo(g); 229 for (int s = 0; s < 2; s++) { 230 int h = t->edge_hex[e][s]; 231 if (h >= 0 && !ter_land(g->terrain[h])) return true; 232 } 233 return false; 234 } 235 236 bool game_can_settle(const Game *g, int p, int v, bool setup) 237 { 238 const Topo *t = game_topo(g); 239 if (v < 0 || v >= t->nvert || !vert_free_dist(g, v)) return false; 240 if (game_has_sea(g) && !vert_land(g, v, setup ? -2 : -1)) return false; /* el setup, en tierra de arranque */ 241 if (setup) return true; 242 for (int k = 0; k < 3; k++) { 243 int e = t->vert_edge[v][k]; 244 if (e >= 0 && g->eown[e] == p) return true; 245 } 246 return false; 247 } 248 249 /* Rutas por tierra y barcos por agua; una ruta sigue a otra ruta y un barco a otro 250 * barco, pero para pasar de ruta a barco hace falta un edificio propio en el medio. */ 251 static bool edge_connects(const Game *g, int p, int e, bool ship) 252 { 253 const Topo *t = game_topo(g); 254 for (int s = 0; s < 2; s++) { 255 int v = t->edge_v[e][s]; 256 if (g->vown[v] == p) return true; 257 if (g->vown[v] >= 0) continue; /* edificio ajeno corta la conexion */ 258 for (int k = 0; k < 3; k++) { 259 int f = t->vert_edge[v][k]; 260 if (f >= 0 && f != e && g->eown[f] == p && (g->ship[f] != 0) == ship) return true; 261 } 262 } 263 return false; 264 } 265 266 bool game_can_road(const Game *g, int p, int e) 267 { 268 const Topo *t = game_topo(g); 269 if (e < 0 || e >= t->nedge || g->eown[e] >= 0) return false; 270 if (game_has_sea(g) && !edge_land(g, e)) return false; 271 return edge_connects(g, p, e, false); 272 } 273 274 static bool pirate_next(const Game *g, int e) 275 { 276 const Topo *t = game_topo(g); 277 return t->edge_hex[e][0] == g->pirate || t->edge_hex[e][1] == g->pirate; 278 } 279 280 bool game_can_ship(const Game *g, int p, int e, bool setup) 281 { 282 const Topo *t = game_topo(g); 283 if (!game_has_sea(g) || e < 0 || e >= t->nedge || g->eown[e] >= 0) return false; 284 if (!edge_sea(g, e) || pirate_next(g, e)) return false; 285 if (setup) return t->edge_v[e][0] == g->setup_v || t->edge_v[e][1] == g->setup_v; 286 return edge_connects(g, p, e, true); 287 } 288 289 /* Un barco se puede mover si esta en una punta de la cadena: en uno de sus extremos 290 * no hay edificio propio ni otro barco propio. No el que se puso en este turno. */ 291 bool game_ship_movable(const Game *g, int p, int e) 292 { 293 const Topo *t = game_topo(g); 294 if (e < 0 || e >= t->nedge || g->eown[e] != p || !g->ship[e]) return false; 295 if ((g->ship_new[e / 8] >> (e % 8)) & 1 || pirate_next(g, e)) return false; 296 for (int s = 0; s < 2; s++) { 297 int v = t->edge_v[e][s]; 298 if (g->vown[v] == p) continue; 299 bool more = false; 300 for (int k = 0; k < 3; k++) { 301 int f = t->vert_edge[v][k]; 302 if (f >= 0 && f != e && g->eown[f] == p && g->ship[f]) more = true; 303 } 304 if (!more) return true; 305 } 306 return false; 307 } 308 309 bool game_can_moveship(const Game *g, int p, int from, int to) 310 { 311 if (from == to || !game_ship_movable(g, p, from)) return false; 312 static Game tmp; /* sin el barco que se mueve */ 313 tmp = *g; 314 tmp.eown[from] = -1; 315 tmp.ship[from] = 0; 316 return game_can_ship(&tmp, p, to, false); 317 } 318 319 bool game_can_city(const Game *g, int p, int v) 320 { 321 return v >= 0 && v < game_topo(g)->nvert && g->vown[v] == p && g->vlev[v] == 1; 322 } 323 324 static bool any_road(const Game *g, int p) 325 { 326 for (int e = 0; e < game_topo(g)->nedge; e++) 327 if (game_can_road(g, p, e)) return true; 328 return false; 329 } 330 331 bool game_neutral_possible(const Game *g, int kind) 332 { 333 for (int n = 0; n < g->o.np; n++) { 334 if (!g->p[n].neutral) continue; 335 if (kind == NEED_SETTLE) { 336 if (g->p[n].settles == 0) continue; 337 for (int v = 0; v < game_topo(g)->nvert; v++) 338 if (game_can_settle(g, n, v, false)) return true; 339 } else if (g->p[n].roads > 0 && any_road(g, n)) { 340 return true; 341 } 342 } 343 return false; 344 } 345 346 /* ------------------------------------------------------------------- ladron */ 347 348 static bool friendly_blocked(const Game *g, int p, int h) 349 { 350 const Topo *t = game_topo(g); 351 if (g->terrain[h] == T_DESERT) return false; 352 for (int k = 0; k < 6; k++) { 353 int o = g->vown[t->hex_vert[h][k]]; 354 if (o >= 0 && o != p && !g->p[o].neutral && game_vp_public(g, o) <= 2) return true; 355 } 356 return false; 357 } 358 359 bool game_can_robber(const Game *g, int p, int h) 360 { 361 if (h < 0 || h >= game_topo(g)->nhex || h == g->robber) return false; 362 if (!ter_land(g->terrain[h])) return h != g->pirate; /* al mar va el pirata */ 363 if (!g->o.friendly_robber || !friendly_blocked(g, p, h)) return true; 364 /* si la regla amistosa bloquea todo, no se aplica */ 365 for (int i = 0; i < game_topo(g)->nhex; i++) 366 if (i != g->robber && !friendly_blocked(g, p, i)) return false; 367 return true; 368 } 369 370 bool game_robber_victim_ok(const Game *g, int p, int h, int victim) 371 { 372 const Topo *t = game_topo(g); 373 bool any = false, found = false; 374 bool sea = !ter_land(g->terrain[h]); /* el pirata le roba a los barcos de alrededor */ 375 for (int k = 0; k < 6; k++) { 376 int e = t->hex_edge[h][k]; 377 int o = sea ? (g->ship[e] ? g->eown[e] : -1) : g->vown[t->hex_vert[h][k]]; 378 if (o < 0 || o == p || g->p[o].neutral || hand_size(g, o) == 0) continue; 379 any = true; 380 if (o == victim) found = true; 381 } 382 return any ? found : victim < 0; 383 } 384 385 /* ---------------------------------------------------------- camino y ejercito */ 386 387 /* camino comercial: rutas y barcos; cambiar de uno a otro solo en un edificio propio */ 388 static int road_dfs(const Game *g, int p, int v, uint8_t *used, bool first, int prev_ship) 389 { 390 const Topo *t = game_topo(g); 391 if (!first && g->vown[v] >= 0 && g->vown[v] != p) return 0; 392 int best = 0; 393 for (int k = 0; k < 3; k++) { 394 int e = t->vert_edge[v][k]; 395 if (e < 0 || used[e] || g->eown[e] != p) continue; 396 if (!first && g->vown[v] != p && g->ship[e] != prev_ship) continue; 397 used[e] = 1; 398 int u = t->edge_v[e][0] == v ? t->edge_v[e][1] : t->edge_v[e][0]; 399 int l = 1 + road_dfs(g, p, u, used, false, g->ship[e]); 400 used[e] = 0; 401 if (l > best) best = l; 402 } 403 return best; 404 } 405 406 int game_road_len(const Game *g, int p) 407 { 408 const Topo *t = game_topo(g); 409 uint8_t used[NEDGE]; 410 memset(used, 0, sizeof used); 411 int best = 0; 412 for (int v = 0; v < t->nvert; v++) { 413 bool mine = false; 414 for (int k = 0; k < 3; k++) { 415 int e = t->vert_edge[v][k]; 416 if (e >= 0 && g->eown[e] == p) mine = true; 417 } 418 if (!mine) continue; 419 int l = road_dfs(g, p, v, used, true, 0); 420 if (l > best) best = l; 421 } 422 return best; 423 } 424 425 static void update_longest(Game *g) 426 { 427 int m = 0; 428 for (int p = 0; p < g->o.np; p++) { 429 g->p[p].road_len = (uint8_t)game_road_len(g, p); 430 if (!g->p[p].neutral && g->p[p].road_len > m) m = g->p[p].road_len; 431 } 432 int h = g->longest; 433 if (h >= 0 && g->p[h].road_len == m && m >= 5) return; 434 if (m < 5) { g->longest = -1; return; } 435 int who = -1, cnt = 0; 436 for (int p = 0; p < g->o.np; p++) 437 if (!g->p[p].neutral && g->p[p].road_len == m) { who = p; cnt++; } 438 g->longest = (int8_t)(cnt == 1 ? who : -1); 439 } 440 441 static void update_army(Game *g, int p) 442 { 443 if (g->p[p].knights >= 3 && (g->army < 0 || g->p[p].knights > g->p[g->army].knights)) 444 g->army = (int8_t)p; 445 } 446 447 /* ----------------------------------------------------------------- recursos */ 448 449 bool game_can_afford(const Game *g, int p, const uint8_t cost[NRES]) 450 { 451 for (int r = 0; r < NRES; r++) 452 if (g->p[p].res[r] < cost[r]) return false; 453 return true; 454 } 455 456 static void pay(Game *g, int p, const uint8_t cost[NRES]) 457 { 458 for (int r = 0; r < NRES; r++) { 459 g->p[p].res[r] -= cost[r]; 460 g->bank[r] += cost[r]; 461 } 462 } 463 464 static void take_bank(Game *g, int p, int r, int n) 465 { 466 if (n > g->bank[r]) n = g->bank[r]; 467 g->bank[r] -= (uint8_t)n; 468 g->p[p].res[r] += (uint8_t)n; 469 } 470 471 static void transfer(Game *g, int from, int to, int r, int n) 472 { 473 if (n > g->p[from].res[r]) n = g->p[from].res[r]; 474 g->p[from].res[r] -= (uint8_t)n; 475 g->p[to].res[r] += (uint8_t)n; 476 } 477 478 int game_bank_ratio(const Game *g, int p, int res) 479 { 480 const Topo *t = game_topo(g); 481 int best = 4; 482 for (int i = 0; i < t->nport; i++) { 483 int e = t->port_edge[i]; 484 if (g->vown[t->edge_v[e][0]] != p && g->vown[t->edge_v[e][1]] != p) continue; 485 if (g->port[i] == res) return 2; 486 if (g->port[i] == PORT_ANY) best = 3; 487 } 488 return best; 489 } 490 491 static void produce(Game *g, int roll) 492 { 493 const Topo *t = game_topo(g); 494 uint8_t want[MAXP][NRES]; 495 memset(want, 0, sizeof want); 496 for (int h = 0; h < t->nhex; h++) { 497 if (g->num[h] != roll || h == g->robber) continue; 498 bool gold = g->terrain[h] == T_GOLD; 499 if (!gold && !ter_res(g->terrain[h])) continue; 500 for (int k = 0; k < 6; k++) { 501 int v = t->hex_vert[h][k], o = g->vown[v]; 502 if (o < 0 || g->p[o].neutral) continue; 503 if (gold) g->p[o].gold = (uint8_t)(g->p[o].gold + g->vlev[v]); /* elige despues (PH_GOLD) */ 504 else want[o][g->terrain[h]] += g->vlev[v]; 505 } 506 } 507 for (int r = 0; r < NRES; r++) { 508 int total = 0, who = -1, cnt = 0; 509 for (int p = 0; p < g->o.np; p++) 510 if (want[p][r]) { total += want[p][r]; who = p; cnt++; } 511 if (!total) continue; 512 if (total <= g->bank[r]) { 513 for (int p = 0; p < g->o.np; p++) take_bank(g, p, r, want[p][r]); 514 } else if (cnt == 1) { 515 take_bank(g, who, r, g->bank[r]); /* uno solo: se lleva lo que queda */ 516 } 517 } 518 } 519 520 static void start_seven(Game *g) 521 { 522 bool any = false; 523 for (int p = 0; p < g->o.np; p++) { 524 int n = hand_size(g, p); 525 g->p[p].discard = n > 7 ? (uint8_t)(n / 2) : 0; 526 if (g->p[p].discard) any = true; 527 } 528 g->phase = any ? PH_DISCARD : PH_ROBBER; 529 } 530 531 static void use_dev(Game *g, int p, int d) 532 { 533 Player *pl = &g->p[p]; 534 if (pl->dev[d]) pl->dev[d]--; 535 else if (pl->dev_hidden) pl->dev_hidden--; 536 g->dev_played = 1; 537 } 538 539 /* Tras construir una ruta o pueblo en la variante 2p: construccion neutral. */ 540 static void maybe_neutral(Game *g, int p, int kind, int next_phase) 541 { 542 g->phase = (uint8_t)next_phase; 543 if (!g->o.variant2p || g->p[p].neutral) return; 544 if (kind == NEED_SETTLE && !game_neutral_possible(g, NEED_SETTLE)) kind = NEED_ROAD; 545 if (!game_neutral_possible(g, kind)) return; 546 g->neutral_need = (uint8_t)kind; 547 g->ret_phase = (uint8_t)next_phase; 548 g->phase = PH_NEUTRAL; 549 } 550 551 static bool any_ship(const Game *g, int p) 552 { 553 if (!g->p[p].ships) return false; 554 for (int e = 0; e < game_topo(g)->nedge; e++) 555 if (game_can_ship(g, p, e, false)) return true; 556 return false; 557 } 558 559 static int after_free_road(const Game *g) 560 { 561 int p = g->cur; 562 bool more = (g->p[p].roads > 0 && any_road(g, p)) || any_ship(g, p); 563 return g->free_roads > 0 && more ? PH_ROADBUILD : PH_MAIN; 564 } 565 566 static bool adj_desert(const Game *g, int v) 567 { 568 const Topo *t = game_topo(g); 569 for (int k = 0; k < 3; k++) { 570 int h = t->vert_hex[v][k]; 571 if (h >= 0 && g->terrain[h] == T_DESERT) return true; 572 } 573 return false; 574 } 575 576 /* --------------------------------------------------------------- validacion */ 577 578 static bool res_valid(const uint8_t r[NRES], const uint8_t have[NRES]) 579 { 580 for (int i = 0; i < NRES; i++) 581 if (r[i] > have[i]) return false; 582 return true; 583 } 584 585 static int check_dev(const Game *g, int p, int d) 586 { 587 if (p != g->cur) return E_TURN; 588 if (g->dev_played) return E_DEVPLAYED; 589 if (g->p[p].dev[d] == 0) return E_NODEV; 590 return E_OK; 591 } 592 593 /* construir, comprar y cambiar con el banco: en el turno propio o en el de pareja */ 594 static bool build_phase(const Game *g) { return g->phase == PH_MAIN || g->phase == PH_PAIRED; } 595 596 int game_check(const Game *g, const Move *m) 597 { 598 int p = m->p; 599 if (p < 0 || p >= g->o.np) return E_ARGS; 600 if (g->phase == PH_OVER) return E_PHASE; 601 const Player *pl = &g->p[p]; 602 const Topo *t = game_topo(g); 603 604 switch (m->type) { 605 case M_SETTLE: 606 if (p != g->cur) return E_TURN; 607 if (g->phase == PH_SETUP) { 608 if (g->setup_sub != 0) return E_PHASE; 609 return game_can_settle(g, p, m->a, true) ? E_OK : E_PLACE; 610 } 611 if (!build_phase(g)) return E_PHASE; 612 if (!pl->settles) return E_PIECES; 613 if (!game_can_afford(g, p, COST_SETTLE)) return E_RES; 614 return game_can_settle(g, p, m->a, false) ? E_OK : E_PLACE; 615 616 case M_ROAD: 617 if (p != g->cur) return E_TURN; 618 if (m->a < 0 || m->a >= game_topo(g)->nedge) return E_ARGS; 619 if (!pl->roads) return E_PIECES; 620 if (g->phase == PH_SETUP) { 621 if (g->setup_sub != 1) return E_PHASE; 622 if (g->eown[m->a] >= 0 || (game_has_sea(g) && !edge_land(g, m->a))) return E_PLACE; 623 return (t->edge_v[m->a][0] == g->setup_v || t->edge_v[m->a][1] == g->setup_v) ? E_OK : E_PLACE; 624 } 625 if (g->phase == PH_ROADBUILD) return game_can_road(g, p, m->a) ? E_OK : E_PLACE; 626 if (!build_phase(g)) return E_PHASE; 627 if (!game_can_afford(g, p, COST_ROAD)) return E_RES; 628 return game_can_road(g, p, m->a) ? E_OK : E_PLACE; 629 630 case M_SHIP: 631 if (p != g->cur) return E_TURN; 632 if (m->a < 0 || m->a >= t->nedge) return E_ARGS; 633 if (!pl->ships) return E_PIECES; 634 if (g->phase == PH_SETUP) { 635 if (g->setup_sub != 1) return E_PHASE; 636 return game_can_ship(g, p, m->a, true) ? E_OK : E_PLACE; 637 } 638 if (g->phase == PH_ROADBUILD) return game_can_ship(g, p, m->a, false) ? E_OK : E_PLACE; 639 if (!build_phase(g)) return E_PHASE; 640 if (!game_can_afford(g, p, COST_SHIP)) return E_RES; 641 return game_can_ship(g, p, m->a, false) ? E_OK : E_PLACE; 642 643 case M_MOVESHIP: 644 if (p != g->cur) return E_TURN; 645 if (g->phase != PH_MAIN) return E_PHASE; 646 if (g->ship_moved) return E_PIECES; 647 return game_can_moveship(g, p, m->a, m->b) ? E_OK : E_PLACE; 648 649 case M_GOLD: { 650 if (g->phase != PH_GOLD) return E_PHASE; 651 if (!pl->gold) return E_TURN; 652 if (res_total(m->r) != pl->gold) return E_ARGS; 653 for (int r = 0; r < NRES; r++) if (m->r[r] > g->bank[r]) return E_BANK; 654 return E_OK; 655 } 656 657 case M_CITY: 658 if (p != g->cur) return E_TURN; 659 if (!build_phase(g)) return E_PHASE; 660 if (!pl->cities) return E_PIECES; 661 if (!game_can_afford(g, p, COST_CITY)) return E_RES; 662 return game_can_city(g, p, m->a) ? E_OK : E_PLACE; 663 664 case M_ROLL: 665 if (p != g->cur) return E_TURN; 666 return g->phase == PH_ROLL ? E_OK : E_PHASE; 667 668 case M_DISCARD: 669 if (g->phase != PH_DISCARD) return E_PHASE; 670 if (!pl->discard) return E_TURN; 671 if (res_total(m->r) != pl->discard || !res_valid(m->r, pl->res)) return E_ARGS; 672 return E_OK; 673 674 case M_ROBBER: 675 if (p != g->cur) return E_TURN; 676 if (g->phase != PH_ROBBER) return E_PHASE; 677 if (!game_can_robber(g, p, m->a)) return E_ROBBER; 678 return game_robber_victim_ok(g, p, m->a, m->b) ? E_OK : E_ARGS; 679 680 case M_BUYDEV: 681 if (p != g->cur) return E_TURN; 682 if (!build_phase(g)) return E_PHASE; 683 if (!g->deck_n) return E_BANK; 684 return game_can_afford(g, p, COST_DEV) ? E_OK : E_RES; 685 686 case M_KNIGHT: 687 if (g->phase != PH_ROLL && g->phase != PH_MAIN) return E_PHASE; 688 return check_dev(g, p, D_KNIGHT); 689 690 case M_ROADS: 691 if (g->phase != PH_MAIN) return E_PHASE; 692 if (!pl->roads) return E_PIECES; 693 return check_dev(g, p, D_ROADS); 694 695 case M_PLENTY: { 696 if (g->phase != PH_MAIN) return E_PHASE; 697 int e = check_dev(g, p, D_PLENTY); 698 if (e) return e; 699 if (m->a < 0 || m->a >= NRES || m->b < 0 || m->b >= NRES) return E_ARGS; 700 if (m->a == m->b ? g->bank[m->a] < 2 : (!g->bank[m->a] || !g->bank[m->b])) return E_BANK; 701 return E_OK; 702 } 703 704 case M_MONO: 705 if (g->phase != PH_MAIN) return E_PHASE; 706 if (m->a < 0 || m->a >= NRES) return E_ARGS; 707 return check_dev(g, p, D_MONO); 708 709 case M_BANK: { 710 if (p != g->cur) return E_TURN; 711 if (!build_phase(g)) return E_PHASE; 712 if (m->a < 0 || m->a >= NRES || m->b < 0 || m->b >= NRES || m->a == m->b || m->c < 1) return E_ARGS; 713 if (pl->res[m->a] < game_bank_ratio(g, p, m->a) * m->c) return E_RES; 714 return g->bank[m->b] >= m->c ? E_OK : E_BANK; 715 } 716 717 case M_OFFER: 718 if (p != g->cur) return E_TURN; 719 if (g->phase != PH_MAIN) return E_PHASE; 720 if (!res_total(m->r) || !res_total(m->r2)) return E_ARGS; 721 for (int r = 0; r < NRES; r++) 722 if (m->r[r] && m->r2[r]) return E_ARGS; 723 if (m->a != -1 && (m->a <= 0 || (m->a & ~game_offer_candidates(g, p)))) return E_ARGS; 724 return res_valid(m->r, pl->res) ? E_OK : E_RES; 725 726 case M_ACCEPT: 727 if (!g->offer.active || g->phase != PH_MAIN) return E_OFFER; 728 if (p == g->offer.from || pl->neutral) return E_TURN; 729 if (!((g->offer.tomask >> p) & 1)) return E_TURN; 730 return res_valid(g->offer.get, pl->res) ? E_OK : E_RES; 731 732 case M_REJECT: 733 if (!g->offer.active) return E_OFFER; 734 return (p != g->offer.from && !pl->neutral) ? E_OK : E_TURN; 735 736 case M_CONFIRM: { 737 if (!g->offer.active || g->phase != PH_MAIN) return E_OFFER; 738 if (p != g->offer.from) return E_TURN; 739 if (m->a < 0 || m->a >= g->o.np) return E_OFFER; 740 int q = m->a, rs = g->offer.resp[q]; 741 if (rs == 1) 742 return res_valid(g->offer.give, pl->res) && res_valid(g->offer.get, g->p[q].res) ? E_OK : E_RES; 743 if (rs == 2) /* con los terminos de la contraoferta */ 744 return res_valid(g->offer.cget[q], pl->res) && res_valid(g->offer.cgive[q], g->p[q].res) ? E_OK : E_RES; 745 return E_OFFER; 746 } 747 748 case M_COUNTER: 749 if (!g->offer.active || g->phase != PH_MAIN) return E_OFFER; 750 if (p == g->offer.from || pl->neutral || !((g->offer.tomask >> p) & 1)) return E_TURN; 751 if (!res_total(m->r) || !res_total(m->r2)) return E_ARGS; 752 for (int r = 0; r < NRES; r++) 753 if (m->r[r] && m->r2[r]) return E_ARGS; 754 return res_valid(m->r, pl->res) ? E_OK : E_RES; 755 756 case M_CANCEL: 757 if (!g->offer.active) return E_OFFER; 758 return p == g->offer.from ? E_OK : E_TURN; 759 760 case M_END: 761 if (p != g->cur) return E_TURN; 762 return (g->phase == PH_MAIN || g->phase == PH_ROADBUILD || g->phase == PH_PAIRED) ? E_OK : E_PHASE; 763 764 case M_NEUTRAL: { 765 int n = m->a; 766 if (!game_is_neutral(g, n) || (m->b != 0 && m->b != 1)) return E_ARGS; 767 const Player *np = &g->p[n]; 768 if (g->phase == PH_SETUP) { 769 if (p != n || g->setup_i != 0 || g->setup_sub != 0) return E_PHASE; 770 int placed = MAX_SETTLES - np->settles, roads = MAX_ROADS - np->roads; 771 if (m->b == 1) { 772 if (placed >= g->o.neutral_setup) return E_PIECES; 773 return game_can_settle(g, n, m->c, true) ? E_OK : E_PLACE; 774 } 775 if (roads >= placed) return E_PIECES; 776 return game_can_road(g, n, m->c) ? E_OK : E_PLACE; 777 } 778 if (g->phase != PH_NEUTRAL) return E_PHASE; 779 if (p != g->cur) return E_TURN; 780 if (m->b == 1) { 781 if (g->neutral_need != NEED_SETTLE || !np->settles) return E_ARGS; 782 return game_can_settle(g, n, m->c, false) ? E_OK : E_PLACE; 783 } 784 if (g->neutral_need == NEED_SETTLE && game_neutral_possible(g, NEED_SETTLE)) return E_ARGS; 785 if (!np->roads) return E_PIECES; 786 return game_can_road(g, n, m->c) ? E_OK : E_PLACE; 787 } 788 789 case M_TOKTRADE: 790 if (!g->o.variant2p) return E_PHASE; 791 if (p != g->cur) return E_TURN; 792 if (g->phase != PH_MAIN) return E_PHASE; 793 return pl->tokens >= game_token_cost(g, p) ? E_OK : E_TOKENS; 794 795 case M_GIVEBACK: 796 if (p != g->cur) return E_TURN; 797 if (g->phase != PH_GIVEBACK) return E_PHASE; 798 if (res_total(m->r) != g->give_back || !res_valid(m->r, pl->res)) return E_ARGS; 799 return E_OK; 800 801 case M_TOKROBBER: 802 if (!g->o.variant2p) return E_PHASE; 803 if (p != g->cur) return E_TURN; 804 if (g->phase != PH_ROLL && g->phase != PH_MAIN) return E_PHASE; 805 if (g->terrain[g->robber] == T_DESERT) return E_ROBBER; 806 return pl->tokens >= game_token_cost(g, p) ? E_OK : E_TOKENS; 807 808 case M_WIN: 809 return E_OK; 810 811 case M_UNDO: 812 if (p != g->cur) return E_TURN; 813 if (g->phase != PH_MAIN && g->phase != PH_NEUTRAL && g->phase != PH_ROADBUILD && g->phase != PH_PAIRED) return E_PHASE; 814 return g->undo_n ? E_OK : E_PHASE; 815 } 816 return E_ARGS; 817 } 818 819 /* ---------------------------------------------------------------- aplicacion */ 820 821 int game_pair(const Game *g, int p) 822 { 823 if (game_topo(g)->family != BF_LARGE || g->o.np < 5) return -1; 824 int q = (p + 3) % g->o.np; 825 return g->p[q].neutral ? -1 : q; 826 } 827 828 /* la pareja juega solo si algo le alcanza: construir, comprar o cambiar con el banco */ 829 static bool pair_can_act(const Game *g, int q) 830 { 831 const Player *pl = &g->p[q]; 832 if (pl->roads && game_can_afford(g, q, COST_ROAD) && any_road(g, q)) return true; 833 if (pl->cities && game_can_afford(g, q, COST_CITY)) 834 for (int v = 0; v < game_topo(g)->nvert; v++) if (game_can_city(g, q, v)) return true; 835 if (pl->settles && game_can_afford(g, q, COST_SETTLE)) 836 for (int v = 0; v < game_topo(g)->nvert; v++) if (game_can_settle(g, q, v, false)) return true; 837 if (g->deck_n && game_can_afford(g, q, COST_DEV)) return true; 838 for (int r = 0; r < NRES; r++) if (pl->res[r] >= game_bank_ratio(g, q, r)) return true; 839 return false; 840 } 841 842 void game_apply(Game *g, const Move *m) 843 { 844 const Topo *t = game_topo(g); 845 int p = m->p; 846 Player *pl = &g->p[p]; 847 g->nmoves++; 848 849 if (game_undoable(g, m)) { if (g->undo_n < UNDO_MAX) g->undo_n++; } 850 else if (m->type != M_OFFER && m->type != M_ACCEPT && m->type != M_REJECT && m->type != M_CANCEL && m->type != M_COUNTER) 851 g->undo_n = 0; 852 853 /* si quien ofrecio hace cualquier otra cosa, la oferta se retira */ 854 if (g->offer.active && p == g->offer.from && 855 m->type != M_OFFER && m->type != M_CONFIRM && m->type != M_CANCEL) 856 g->offer.active = 0; 857 858 switch (m->type) { 859 case M_SETTLE: 860 g->vown[m->a] = (int8_t)p; 861 g->vlev[m->a] = 1; 862 pl->settles--; 863 if (g->phase == PH_SETUP) { 864 g->setup_v = (int16_t)m->a; 865 g->setup_sub = 1; 866 if (setup_second(g, p)) 867 for (int k = 0; k < 3; k++) { 868 int h = t->vert_hex[m->a][k]; 869 if (h >= 0 && ter_res(g->terrain[h])) take_bank(g, p, g->terrain[h], 1); 870 } 871 if (g->o.variant2p && adj_desert(g, m->a)) pl->tokens++; 872 for (int k = 0; k < 3; k++) { /* Navegantes: las islas donde arranca no dan puntos */ 873 int h = t->vert_hex[m->a][k], r = h >= 0 ? t->region[h] : -1; 874 if (r >= 0 && r < 8) pl->isles |= (uint8_t)(1 << r); 875 } 876 update_longest(g); 877 break; 878 } 879 pay(g, p, COST_SETTLE); 880 if (g->o.variant2p && adj_desert(g, m->a)) pl->tokens++; 881 for (int k = 0; k < 3 && t->sea; k++) { /* Navegantes: primer pueblo en una isla nueva, +2 */ 882 int h = t->vert_hex[m->a][k], r = h >= 0 ? t->region[h] : -1; 883 if (r >= 0 && r < 8 && !((pl->isles >> r) & 1)) { pl->isles |= (uint8_t)(1 << r); pl->bonus += 2; } 884 } 885 update_longest(g); 886 maybe_neutral(g, p, NEED_SETTLE, g->phase == PH_PAIRED ? PH_PAIRED : PH_MAIN); 887 break; 888 889 case M_ROAD: 890 g->eown[m->a] = (int8_t)p; 891 pl->roads--; 892 if (g->phase == PH_SETUP) { 893 g->setup_sub = 0; 894 g->setup_v = -1; 895 g->setup_i++; 896 if (g->setup_i >= g->setup_n) { 897 g->phase = PH_ROLL; 898 g->cur = g->setup_order[0]; 899 } else { 900 g->cur = g->setup_order[g->setup_i]; 901 } 902 update_longest(g); 903 break; 904 } 905 if (g->phase == PH_ROADBUILD) { 906 if (g->free_roads) g->free_roads--; 907 update_longest(g); 908 maybe_neutral(g, p, NEED_ROAD, after_free_road(g)); 909 break; 910 } 911 pay(g, p, COST_ROAD); 912 update_longest(g); 913 maybe_neutral(g, p, NEED_ROAD, g->phase == PH_PAIRED ? PH_PAIRED : PH_MAIN); 914 break; 915 916 case M_SHIP: 917 g->eown[m->a] = (int8_t)p; 918 g->ship[m->a] = 1; 919 pl->ships--; 920 g->ship_new[m->a / 8] |= (uint8_t)(1 << (m->a % 8)); 921 if (g->phase == PH_SETUP) { 922 g->setup_sub = 0; 923 g->setup_v = -1; 924 g->setup_i++; 925 if (g->setup_i >= g->setup_n) { g->phase = PH_ROLL; g->cur = g->setup_order[0]; } 926 else g->cur = g->setup_order[g->setup_i]; 927 update_longest(g); 928 break; 929 } 930 if (g->phase == PH_ROADBUILD) { 931 if (g->free_roads) g->free_roads--; 932 update_longest(g); 933 g->phase = (uint8_t)after_free_road(g); 934 break; 935 } 936 pay(g, p, COST_SHIP); 937 update_longest(g); 938 break; 939 940 case M_MOVESHIP: 941 g->eown[m->a] = -1; 942 g->ship[m->a] = 0; 943 g->eown[m->b] = (int8_t)p; 944 g->ship[m->b] = 1; 945 g->ship_moved = 1; 946 update_longest(g); 947 break; 948 949 case M_GOLD: { 950 for (int r = 0; r < NRES; r++) take_bank(g, p, r, m->r[r]); 951 pl->gold = 0; 952 bool left = false; 953 for (int q = 0; q < g->o.np; q++) if (g->p[q].gold) left = true; 954 if (!left) g->phase = PH_MAIN; 955 break; 956 } 957 958 case M_CITY: 959 g->vlev[m->a] = 2; 960 pl->cities--; 961 pl->settles++; 962 pay(g, p, COST_CITY); 963 break; 964 965 case M_ROLL: { 966 for (int i = 0; i < 4; i++) g->dice[i] = m->r[i]; 967 g->rolled = 1; 968 int s1 = m->r[0] + m->r[1], s2 = m->r[2] + m->r[3]; 969 bool seven = s1 == 7; 970 if (s1 != 7) produce(g, s1); 971 if (s2) { 972 if (s2 == 7) seven = true; 973 else produce(g, s2); 974 } 975 if (seven) start_seven(g); 976 else g->phase = PH_MAIN; 977 if (!seven) { /* oro: cada uno elige, si el banco tiene */ 978 int bank = 0; 979 for (int r = 0; r < NRES; r++) bank += g->bank[r]; 980 bool any = false; 981 for (int q = 0; q < g->o.np; q++) { 982 if (g->p[q].gold > bank) g->p[q].gold = (uint8_t)bank; 983 if (g->p[q].gold) any = true; 984 } 985 if (any) g->phase = PH_GOLD; 986 } 987 break; 988 } 989 990 case M_DISCARD: { 991 for (int r = 0; r < NRES; r++) { 992 pl->res[r] -= m->r[r]; 993 g->bank[r] += m->r[r]; 994 } 995 pl->discard = 0; 996 bool left = false; 997 for (int q = 0; q < g->o.np; q++) 998 if (g->p[q].discard) left = true; 999 if (!left) g->phase = PH_ROBBER; 1000 break; 1001 } 1002 1003 case M_ROBBER: 1004 if (ter_land(g->terrain[m->a])) g->robber = (uint8_t)m->a; 1005 else g->pirate = (uint8_t)m->a; 1006 if (m->b >= 0 && m->c >= 0) transfer(g, m->b, p, m->c, 1); 1007 g->phase = g->rolled ? PH_MAIN : PH_ROLL; 1008 break; 1009 1010 case M_BUYDEV: 1011 pay(g, p, COST_DEV); 1012 if (g->deck_n) g->deck_n--; 1013 if (m->a >= 0 && m->a < NDEV) pl->dev_new[m->a]++; 1014 else pl->dev_hidden++; 1015 break; 1016 1017 case M_KNIGHT: 1018 use_dev(g, p, D_KNIGHT); 1019 pl->knights++; 1020 if (g->o.variant2p) pl->tokens++; 1021 update_army(g, p); 1022 g->phase = PH_ROBBER; 1023 break; 1024 1025 case M_ROADS: 1026 use_dev(g, p, D_ROADS); 1027 g->free_roads = 2; 1028 g->phase = (uint8_t)after_free_road(g); 1029 break; 1030 1031 case M_PLENTY: 1032 use_dev(g, p, D_PLENTY); 1033 take_bank(g, p, m->a, 1); 1034 take_bank(g, p, m->b, 1); 1035 break; 1036 1037 case M_MONO: 1038 use_dev(g, p, D_MONO); 1039 for (int q = 0; q < g->o.np; q++) 1040 if (q != p) transfer(g, q, p, m->a, g->p[q].res[m->a]); 1041 break; 1042 1043 case M_BANK: { 1044 int n = game_bank_ratio(g, p, m->a) * m->c; 1045 pl->res[m->a] -= (uint8_t)n; 1046 g->bank[m->a] += (uint8_t)n; 1047 take_bank(g, p, m->b, m->c); 1048 break; 1049 } 1050 1051 case M_OFFER: 1052 if (g->offers < 255) g->offers++; 1053 memset(&g->offer, 0, sizeof g->offer); 1054 g->offer.active = 1; 1055 g->offer.from = (uint8_t)p; 1056 g->offer.tomask = m->a == -1 ? game_offer_candidates(g, p) : (uint8_t)m->a; 1057 memcpy(g->offer.give, m->r, NRES); 1058 memcpy(g->offer.get, m->r2, NRES); 1059 break; 1060 1061 case M_ACCEPT: g->offer.resp[p] = 1; break; 1062 case M_REJECT: g->offer.resp[p] = -1; break; 1063 1064 case M_CONFIRM: { 1065 bool counter = g->offer.resp[m->a] == 2; 1066 for (int r = 0; r < NRES; r++) { 1067 transfer(g, p, m->a, r, counter ? g->offer.cget[m->a][r] : g->offer.give[r]); 1068 transfer(g, m->a, p, r, counter ? g->offer.cgive[m->a][r] : g->offer.get[r]); 1069 } 1070 g->offer.active = 0; 1071 break; 1072 } 1073 1074 case M_COUNTER: 1075 g->offer.resp[p] = 2; 1076 memcpy(g->offer.cgive[p], m->r, NRES); 1077 memcpy(g->offer.cget[p], m->r2, NRES); 1078 break; 1079 1080 case M_CANCEL: g->offer.active = 0; break; 1081 1082 case M_END: 1083 if (g->phase == PH_ROADBUILD) { 1084 g->free_roads = 0; 1085 g->phase = PH_MAIN; 1086 break; 1087 } 1088 g->offer.active = 0; 1089 for (int d = 0; d < NDEV; d++) { 1090 pl->dev[d] += pl->dev_new[d]; 1091 pl->dev_new[d] = 0; 1092 } 1093 if (g->phase == PH_MAIN) { /* 5-6: ahora juega la pareja, si puede hacer algo */ 1094 int q = game_pair(g, p); 1095 if (q >= 0 && pair_can_act(g, q)) { 1096 g->owner = (uint8_t)p; 1097 g->cur = (uint8_t)q; 1098 g->phase = PH_PAIRED; 1099 break; 1100 } 1101 } 1102 if (g->phase == PH_PAIRED) p = g->owner; 1103 g->cur = (uint8_t)game_next_player(g, p); 1104 g->phase = PH_ROLL; 1105 g->rolled = g->dev_played = g->free_roads = g->offers = g->ship_moved = 0; 1106 memset(g->ship_new, 0, sizeof g->ship_new); 1107 memset(g->dice, 0, sizeof g->dice); 1108 g->turn++; 1109 break; 1110 1111 case M_NEUTRAL: { 1112 Player *np = &g->p[m->a]; 1113 if (m->b == 1) { 1114 g->vown[m->c] = (int8_t)m->a; 1115 g->vlev[m->c] = 1; 1116 np->settles--; 1117 } else { 1118 g->eown[m->c] = (int8_t)m->a; 1119 np->roads--; 1120 } 1121 update_longest(g); 1122 if (g->phase == PH_NEUTRAL) { 1123 g->neutral_need = NEED_NONE; 1124 g->phase = g->ret_phase; 1125 if (g->phase == PH_ROADBUILD) g->phase = (uint8_t)after_free_road(g); 1126 } 1127 break; 1128 } 1129 1130 case M_TOKTRADE: { 1131 int r = game_rival(g, p); 1132 pl->tokens -= (uint8_t)game_token_cost(g, p); 1133 g->give_back = 0; 1134 if (r >= 0) { 1135 if (m->a >= 0) { transfer(g, r, p, m->a, 1); g->give_back++; } 1136 if (m->b >= 0) { transfer(g, r, p, m->b, 1); g->give_back++; } 1137 } 1138 if (g->give_back) g->phase = PH_GIVEBACK; 1139 break; 1140 } 1141 1142 case M_GIVEBACK: { 1143 int r = game_rival(g, p); 1144 for (int i = 0; i < NRES; i++) transfer(g, p, r, i, m->r[i]); 1145 g->give_back = 0; 1146 g->phase = PH_MAIN; 1147 break; 1148 } 1149 1150 case M_TOKROBBER: 1151 pl->tokens -= (uint8_t)game_token_cost(g, p); 1152 g->robber = (uint8_t)desert_hex(g); 1153 break; 1154 1155 case M_WIN: { 1156 int known = pl->dev[D_VP] + pl->dev_new[D_VP]; 1157 if (m->a > known) { 1158 int extra = m->a - known; 1159 if (extra > pl->dev_hidden) extra = pl->dev_hidden; 1160 pl->dev_hidden -= (uint8_t)extra; 1161 pl->dev[D_VP] += (uint8_t)extra; 1162 } 1163 g->winner = (int8_t)p; 1164 if (!g->o.freeplay) g->phase = PH_OVER; 1165 break; 1166 } 1167 } 1168 } 1169 1170 bool game_undoable(const Game *g, const Move *m) 1171 { 1172 if (m->p != g->cur) return false; 1173 switch (m->type) { 1174 case M_ROAD: case M_SHIP: return g->phase == PH_MAIN || g->phase == PH_ROADBUILD || g->phase == PH_PAIRED; 1175 case M_MOVESHIP: return g->phase == PH_MAIN; 1176 case M_SETTLE: case M_CITY: case M_BANK: return g->phase == PH_MAIN || g->phase == PH_PAIRED; 1177 case M_NEUTRAL: return g->phase == PH_NEUTRAL; 1178 } 1179 return false; 1180 } 1181 1182 void game_apply_u(Game *g, Undo *u, const Move *m) 1183 { 1184 if (m->type == M_UNDO) { 1185 if (u->n) { 1186 uint32_t nm = g->nmoves; 1187 *g = u->snap[--u->n]; 1188 g->nmoves = nm + 1; 1189 } 1190 return; 1191 } 1192 if (game_undoable(g, m)) { 1193 if (u->n == UNDO_MAX) { /* se olvida la mas vieja */ 1194 memmove(&u->snap[0], &u->snap[1], sizeof(Game) * (UNDO_MAX - 1)); 1195 u->n--; 1196 for (int i = 0; i < u->n; i++) u->snap[i].undo_n--; 1197 } 1198 g->undo_n = u->n; 1199 u->snap[u->n++] = *g; 1200 } else if (m->type != M_OFFER && m->type != M_ACCEPT && m->type != M_REJECT && m->type != M_CANCEL && m->type != M_COUNTER) { 1201 u->n = 0; 1202 } 1203 game_apply(g, m); 1204 } 1205 1206 /* ¿seat tiene que (o puede) hacer algo ahora? */ 1207 bool game_needs(const Game *g, int seat) 1208 { 1209 if (seat < 0 || seat >= g->o.np || g->phase == PH_OVER || g->p[seat].neutral) return false; 1210 if (g->phase == PH_DISCARD) return g->p[seat].discard > 0; 1211 if (g->phase == PH_GOLD) return g->p[seat].gold > 0; 1212 if (g->offer.active && seat != g->offer.from && ((g->offer.tomask >> seat) & 1) && g->offer.resp[seat] == 0) 1213 return true; 1214 return seat == g->cur; 1215 }