juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

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 }