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 }