From 05825e751d69cde554c21ddfd00e646049425e31 Mon Sep 17 00:00:00 2001 From: rodri Date: Tue, 26 Sep 2023 18:39:02 +0000 Subject: initial work towards spectator mode. --- bts.c | 30 ++++++++++++++++++++++++++---- btsd.c | 9 ++++++++- dat.h | 12 ++++++++++++ fns.h | 2 ++ util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/bts.c b/bts.c index cac8f22..296fa5f 100644 --- a/bts.c +++ b/bts.c @@ -23,6 +23,7 @@ enum { CMmatchesb, /* list header */ CMmatch, /* list entry */ CMmatchese, /* list tail */ + CMwatching, CMwin, CMlose, }; @@ -40,6 +41,7 @@ Cmdtab svcmd[] = { CMmatchesb, "matches", 1, CMmatch, "m", 4, CMmatchese, "end", 1, + CMwatching, "watching", 6, CMwin, "win", 1, CMlose, "lose", 1, }; @@ -116,6 +118,7 @@ Ship *curship; int layoutdone; Point2 lastshot; Menulist *matches; +MatchInfo match; /* of which we are an spectator */ struct { int state; @@ -310,6 +313,10 @@ drawinfo(Image *dst) s = ""; switch(game.state){ + case Watching: + snprint(aux, sizeof aux, "watching %s vs. %s", match.pl[0], match.pl[1]); + s = aux; + break; case Ready: s = "looking for players"; break; case Outlaying: s = "place the fleet"; break; case Waiting: s = "wait for your turn"; break; @@ -326,9 +333,9 @@ drawinfo(Image *dst) vstring(dst, p, display->white, ZP, font, s); p = Pt(alienboard.bbox.max.x+2, alienboard.bbox.min.y); - vstring(dst, p, display->white, ZP, font, oid); + vstring(dst, p, display->white, ZP, font, game.state == Watching? match.pl[1]: oid); p = subpt(localboard.bbox.min, Pt(font->width+2,0)); - vstring(dst, p, display->white, ZP, font, uid); + vstring(dst, p, display->white, ZP, font, game.state == Watching? match.pl[0]: uid); if(game.state == Outlaying){ if(c == nil) @@ -656,8 +663,10 @@ mouse(Mousectl *mc) mc->xy = subpt(mc->xy, screen->r.min); if(game.state == Waiting0) - if((selmatch = matches->update(matches, mc, drawchan)) >= 0) - if(debug) fprint(2, "selected match id %d title %s\n", selmatch, matches->entries[selmatch].title); + if((selmatch = matches->update(matches, mc, drawchan)) >= 0){ + if(debug) fprint(2, "selected match id %d title %s\n", matches->entries[selmatch].id, matches->entries[selmatch].title); + chanprint(egress, "watch %d\n", matches->entries[selmatch].id); + } if(game.state == Outlaying && curship != nil){ newbbox = mkshipbbox(toboard(&localboard, mc->xy), curship->orient, curship->ncells); @@ -752,6 +761,7 @@ processcmd(char *cmd) Cmdbuf *cb; Cmdtab *ct; Point2 cell; + uchar buf[BY2MAP]; int i; if(debug) @@ -783,6 +793,18 @@ processcmd(char *cmd) matches->add(matches, strtoul(cb->f[1], nil, 10), smprint("%s vs %s", cb->f[2], cb->f[3])); else if(matches->filling && ct->index == CMmatchese) matches->filling = 0; + else if(ct->index == CMwatching){ + match.id = strtoul(cb->f[1], nil, 10); + match.pl[0] = estrdup(cb->f[2]); + match.pl[1] = estrdup(cb->f[3]); + match.bl[0] = &localboard; + match.bl[1] = &alienboard; + dec64(buf, sizeof buf, cb->f[4], strlen(cb->f[4])); + bitunpackmap(match.bl[0], buf, sizeof buf); + dec64(buf, sizeof buf, cb->f[5], strlen(cb->f[5])); + bitunpackmap(match.bl[1], buf, sizeof buf); + game.state = Watching; + } break; case Ready: if(ct->index == CMlayout){ diff --git a/btsd.c b/btsd.c index fd6b003..0df1c52 100644 --- a/btsd.c +++ b/btsd.c @@ -317,6 +317,7 @@ battleproc(void *arg) Cmdtab *ct; Player *p, *op; Stands stands; + uchar buf1[BY2MAP], buf2[BY2MAP]; uint n0; Point2 cell; @@ -432,8 +433,8 @@ Nocmd: }else{ op = p == m->pl[0]? m->pl[1]: m->pl[0]; chanprint(op->io.out, "win\n"); - op->state = Waiting0; op->battle = nil; + op->state = Waiting0; freeplayer(p); freemsg(msg); goto Finish; @@ -442,6 +443,11 @@ Nocmd: takeseat(&stands, p); p->battle = m; p->state = Watching; + bitpackmap(buf1, sizeof buf1, m->pl[0]); + bitpackmap(buf2, sizeof buf2, m->pl[1]); + chanprint(p->io.out, "watching %d %s %s %.*[ %.*[\n", + m->id, m->pl[0]->name, m->pl[1]->name, + sizeof buf1, buf1, sizeof buf2, buf2); }else if(strcmp(msg->body, "leave seat") == 0){ leaveseat(&stands, p); p->battle = nil; @@ -642,6 +648,7 @@ threadmain(int argc, char *argv[]) char *addr; GEOMfmtinstall(); + fmtinstall('[', encodefmt); addr = "tcp!*!3047"; ARGBEGIN{ case 'd': diff --git a/dat.h b/dat.h index dad541d..bef3596 100644 --- a/dat.h +++ b/dat.h @@ -5,6 +5,9 @@ enum { Tmiss, NTILES, + TBITS = 2, /* ceil(log(NTILES)/log(2)) */ + TMASK = (1<map[j][i]){ case Twater: fprint(fd, "W"); break; case Tship: fprint(fd, "S"); break; + case Thit: fprint(fd, "X"); break; + case Tmiss: fprint(fd, "O"); break; + default: fprint(fd, "?"); break; } fprint(fd, "\n"); } @@ -153,3 +156,44 @@ min(int a, int b) { return a < b? a: b; } + +int +bitpackmap(uchar *buf, ulong len, Map *m) +{ + int i, j, off, n; + + assert(len >= BY2MAP); + + off = n = 0; + *buf = 0; + for(i = 0; i < MAPW; i++) + for(j = 0; j < MAPH; j++){ + if(off >= 8){ + buf[++n] = 0; + off = 0; + } + buf[n] |= (m->map[i][j] & TMASK) << off; + off += TBITS; + } + return n+1; +} + +int +bitunpackmap(Map *m, uchar *buf, ulong len) +{ + int i, j, off, n; + + assert(len >= BY2MAP); + + off = n = 0; + for(i = 0; i < MAPW; i++) + for(j = 0; j < MAPH; j++){ + if(off >= 8){ + n++; + off = 0; + } + m->map[i][j] = buf[n] >> off & TMASK; + off += TBITS; + } + return n+1; +} -- cgit v1.2.3