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

host.c (2662B)


      1 /* host.c - autoridad + bots + asientos. */
      2 #include <string.h>
      3 #include "host.h"
      4 
      5 /* pasos de bot (cada ~0.5 s) que un bot espera respuestas a su oferta */
      6 #define HOST_OFFER_WAIT 30
      7 
      8 static void forward(void *ctx, const Move *m)
      9 {
     10     Host *h = ctx;
     11     if (h->on_move) h->on_move(h->ctx, m);
     12 }
     13 
     14 void host_init(Host *h, const Opts *o, uint64_t seed, const uint8_t kinds[MAXP],
     15                void (*on_move)(void *, const Move *), void *ctx)
     16 {
     17     memset(h, 0, sizeof *h);
     18     h->on_move = on_move;
     19     h->ctx = ctx;
     20     Opts oo = *o;
     21     if (oo.first == OPTS_FIRST_RANDOM) {     /* quien empieza se sortea con la semilla: igual en todos los nodos */
     22         int nreal = oo.variant2p ? 2 : oo.np;
     23         oo.first = (uint8_t)(seed % (uint64_t)nreal);
     24     }
     25     o = &oo;
     26     for (int s = 0; s < MAXP; s++) h->kind[s] = kinds[s];
     27     for (int s = 0; s < MAXP; s++) {
     28         char def[2] = { (char)('1' + s), 0 };
     29         str_put(h->name[s], sizeof h->name[s], 0, def);
     30     }
     31     rng_seed(&h->brng, seed ^ 0x5DEECE66DULL, 11);
     32     auth_new(&h->a, o, seed, forward, h);
     33     for (int s = 0; s < MAXP; s++)
     34         if (s < o->np && h->a.g.p[s].neutral) h->kind[s] = SEAT_NEUTRAL;
     35         else if (s >= o->np) h->kind[s] = SEAT_OPEN;
     36 }
     37 
     38 int host_submit(Host *h, int seat, Move *m)
     39 {
     40     if (seat < 0 || seat >= h->a.g.o.np || m->p != seat) return E_TURN;
     41     return auth_submit(&h->a, m);
     42 }
     43 
     44 bool host_bot_pending(const Host *h)
     45 {
     46     for (int s = 0; s < h->a.g.o.np; s++)
     47         if (h->kind[s] == SEAT_BOT && game_needs(&h->a.g, s)) return true;
     48     return false;
     49 }
     50 
     51 bool host_bot_step(Host *h)
     52 {
     53     Game *g = &h->a.g;
     54     for (int s = 0; s < g->o.np; s++) {
     55         if (h->kind[s] != SEAT_BOT) continue;
     56         Move m;
     57         bool ok = h->bot.iters > 0 ? search_decide(g, s, &h->brng, &h->bot, &m)
     58                                    : bot_decide(g, s, &h->brng, &m);
     59         if (!ok && bot_offer_pending(g, s)) {
     60             /* espera a que contesten las personas, pero no para siempre */
     61             if (++h->offer_wait < HOST_OFFER_WAIT) continue;
     62             ok = bot_close_offer(g, s, &m);
     63         }
     64         if (!ok) continue;
     65         h->offer_wait = 0;
     66         if (auth_submit(&h->a, &m) == E_OK) return true;
     67         /* no deberia pasar: salida de emergencia para no trabar la partida */
     68         Move f;
     69         memset(&f, 0, sizeof f);
     70         f.p = (int8_t)s;
     71         f.type = g->offer.active && s != g->offer.from ? M_REJECT : M_END;
     72         if (auth_submit(&h->a, &f) == E_OK) return true;
     73     }
     74     return false;
     75 }
     76 
     77 int host_replay(Host *h, const Move *m)
     78 {
     79     if (move_is_auto(m)) return E_OK;
     80     Move c = *m;
     81     return auth_submit(&h->a, &c);
     82 }