From a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a Mon Sep 17 00:00:00 2001 From: rodri Date: Sun, 17 Sep 2023 22:06:16 +0000 Subject: initial work on a menu of matches. also made some corrections and changed the tokenize(2) fields identifiers from cmd[] to f[]. --- bts.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++--------------- btsd.c | 4 +- dat.h | 27 ++++++++++++- 3 files changed, 134 insertions(+), 34 deletions(-) diff --git a/bts.c b/bts.c index 8d37354..19c760f 100644 --- a/bts.c +++ b/bts.c @@ -80,11 +80,11 @@ Ship armada[NSHIPS]; Ship *curship; int layoutdone; Point2 lastshot; +Matchlist matchlist; struct { int state; } game; - struct { Image *c; /* color */ char *s; /* banner text */ @@ -122,6 +122,29 @@ toboard(Board *b, Point p) return np; } +void +addmatch(Mlist *m, int id, char *title) +{ + m->entries = erealloc(m->entries, ++m->nentries * sizeof *m->entries); + m->entries[m->nentries-1] = (Mentry){id, title}; +} + +void +freematchlist(Mlist *m) +{ + int i; + + if(m->entries == nil) + return; + + for(i = 0; i < m->nentries; i++) + free(m->entries[i].title); + free(m->entries); + m->entries = nil; + m->nentries = 0; + m->filling = 0; +} + int rectXarmada(Rectangle r) { @@ -222,11 +245,8 @@ drawship(Image *dst, Ship *s) return; p = s->p; - switch(s->orient){ - case OH: sv = Vec2(1,0); break; - case OV: sv = Vec2(0,1); break; - default: return; - } + assert(s->orient == OH || s->orient == OV); + sv = s->orient == OH? Vec2(1,0): Vec2(0,1); for(i = 0; i < s->ncells; i++){ drawtile(dst, &localboard, p, s->hit[i]? Thit: Tship); @@ -269,6 +289,52 @@ drawgameoptions(Image *dst) string(dst, Pt(SCRW/2 - stringwidth(font, s)/2, 10*font->height+5), display->white, ZP, font, s); } +void +drawmatchlist(Image *dst) +{ + Rectangle r, scrollr; + static char title[] = "ongoing matches"; + static char nomatches[] = "no matches"; + int i; + + USED(scrollr); + + if(debug){ + fprint(2, "matchlist entries %p nentries %d filling %d\n", matchlist.entries, matchlist.nentries, matchlist.filling); + for(i = 0; i < matchlist.nentries; i++) + fprint(2, "match id %d title %s\n", matchlist.entries[i].id, matchlist.entries[i].title); + } + + if(matchlist.filling) + return; + + enum { + Vspace = 2, + Scrollwidth = 10, + Maxvisitems = 5, + }; + r.min = Pt(SCRW/2 - stringwidth(font, title)/2, 14*font->height); + r.max = addpt(r.min, Pt(stringwidth(font, title), font->height+Vspace)); + for(i = 0; i < matchlist.nentries; i++) + if(stringwidth(font, matchlist.entries[i].title) > Dx(r)) + r.max.x = r.min.x + stringwidth(font, matchlist.entries[i].title); + + draw(dst, r, display->white, nil, ZP); + string(dst, r.min, display->black, ZP, font, title); + for(i = 0; i < matchlist.nentries; i++){ + r.min.y += font->height+Vspace; + r.max.y = r.min.y + font->height+Vspace; + draw(dst, r, display->white, nil, ZP); + string(dst, r.min, display->black, ZP, font, matchlist.entries[i].title); + } + if(i == 0){ + r.min.y += font->height+Vspace; + r.max.y = r.min.y + font->height+Vspace; + draw(dst, r, display->white, nil, ZP); + string(dst, r.min, display->black, ZP, font, nomatches); + } +} + void drawinfo(Image *dst) { @@ -339,6 +405,7 @@ redraw(void) case Waiting0: drawtitle(screenb); drawgameoptions(screenb); + drawmatchlist(screenb); break; default: drawboard(screenb, &alienboard); @@ -577,7 +644,7 @@ rmb(Mousectl *mc) DONE, }; static char *items[] = { - [PLACESHIP] "place ships", + [PLACESHIP] "relocate ships", [DONE] "done", nil }; @@ -712,37 +779,47 @@ keelhaul(void) } void -processcmd(char *s) +processcmd(char *cmd) { Point2 cell; - char *cmd[2]; - int i, nc; + char *f[3]; + int i, nf; if(debug) - fprint(2, "rcvd '%s'\n", s); + fprint(2, "rcvd '%s'\n", cmd); - nc = tokenize(s, cmd, nelem(cmd)); - if(nc < 1) + nf = tokenize(cmd, f, nelem(f)); + if(nf < 1) return; - if(nc == 1 && strcmp(cmd[0], "win") == 0) + if(nf == 1 && strcmp(f[0], "win") == 0) celebrate(); - else if(nc == 1 && strcmp(cmd[0], "lose") == 0) + else if(nf == 1 && strcmp(f[0], "lose") == 0) keelhaul(); switch(game.state){ case Waiting0: - if(nc == 1 && strcmp(cmd[0], "id") == 0) + if(nf == 1 && strcmp(f[0], "id") == 0) chanprint(egress, "id %s\n", uid); - else if(nc == 1 && strcmp(cmd[0], "queued") == 0) + else if(nf == 1 && strcmp(f[0], "queued") == 0) game.state = Ready; + else if(!matchlist.filling && nf == 1 && strcmp(f[0], "matches") == 0){ + if(matchlist.nentries > 0) + freematchlist(&matchlist); + matchlist.filling++; + }else if(matchlist.filling && nf == 3) + addmatch(&matchlist, strtoul(f[0], nil, 10), smprint("%s vs %s", f[1], f[2])); + else if(matchlist.filling && nf == 1 && strcmp(f[0], "end") == 0) + matchlist.filling--; + else if(nf == 2 && strcmp(f[0], "no") == 0 && strcmp(f[1], "matches") == 0) + freematchlist(&matchlist); break; case Ready: - if(nc == 1 && strcmp(cmd[0], "layout") == 0){ + if(nf == 1 && strcmp(f[0], "layout") == 0){ game.state = Outlaying; curship = &armada[0]; - }else if(nc == 2 && strcmp(cmd[0], "oid") == 0) - snprint(oid, sizeof oid, "%s", cmd[1]); + }else if(nf == 2 && strcmp(f[0], "oid") == 0) + snprint(oid, sizeof oid, "%s", f[1]); break; case Watching: /* (hit|missed) */ @@ -751,35 +828,35 @@ processcmd(char *s) */ break; case Outlaying: - if(nc == 1 && strcmp(cmd[0], "wait") == 0){ + if(nf == 1 && strcmp(f[0], "wait") == 0){ game.state = Waiting; csetcursor(mctl, &waitcursor); - }else if(nc == 1 && strcmp(cmd[0], "play") == 0) + }else if(nf == 1 && strcmp(f[0], "play") == 0) game.state = Playing; break; case Playing: - if(nc == 1 && strcmp(cmd[0], "wait") == 0){ + if(nf == 1 && strcmp(f[0], "wait") == 0){ game.state = Waiting; csetcursor(mctl, &waitcursor); - }else if(nc == 1 && strcmp(cmd[0], "hit") == 0) + }else if(nf == 1 && strcmp(f[0], "hit") == 0) settile(&alienboard, lastshot, Thit); - else if(nc == 1 && strcmp(cmd[0], "miss") == 0) + else if(nf == 1 && strcmp(f[0], "miss") == 0) settile(&alienboard, lastshot, Tmiss); break; case Waiting: - if(nc == 1 && strcmp(cmd[0], "play") == 0){ + if(nf == 1 && strcmp(f[0], "play") == 0){ game.state = Playing; csetcursor(mctl, nil); - }else if(nc == 2 && strcmp(cmd[0], "hit") == 0){ - cell = coords2cell(cmd[1]); + }else if(nf == 2 && strcmp(f[0], "hit") == 0){ + cell = coords2cell(f[1]); for(i = 0; i < nelem(armada); i++) if(ptinrect(fromboard(&localboard, cell), armada[i].bbox)){ cell = subpt2(cell, armada[i].p); armada[i].hit[(int)vec2len(cell)] = 1; break; } - }else if(nc == 2 && strcmp(cmd[0], "miss") == 0){ - cell = coords2cell(cmd[1]); + }else if(nf == 2 && strcmp(f[0], "miss") == 0){ + cell = coords2cell(f[1]); settile(&localboard, cell, Tmiss); } break; diff --git a/btsd.c b/btsd.c index 8478b9d..c2a18bf 100644 --- a/btsd.c +++ b/btsd.c @@ -239,7 +239,7 @@ playerproc(void *arg) else{ chanprint(my->io.out, "matches\n"); for(m = theater.next; m != &theater; m = m->next) - chanprint(my->io.out, "%d %s vs. %s\n", m->id, m->pl[0]->name, m->pl[1]->name); + chanprint(my->io.out, "%d %s %s\n", m->id, m->pl[0]->name, m->pl[1]->name); chanprint(my->io.out, "end\n"); } runlock(&theaterlk); @@ -502,7 +502,7 @@ fprintmatches(int fd) if(theater.next == &theater) n += fprint(fd, "let there be peace\n"); else for(n = 0, m = theater.next; m != &theater; m = m->next) - n += fprint(fd, "%d\t%s vs. %s\n", m->id, m->pl[0]->name, m->pl[1]->name); + n += fprint(fd, "%d\t%s vs %s\n", m->id, m->pl[0]->name, m->pl[1]->name); runlock(&theaterlk); return n; } diff --git a/dat.h b/dat.h index f72296c..29eb6e0 100644 --- a/dat.h +++ b/dat.h @@ -44,11 +44,11 @@ typedef struct Stands Stands; struct Ship { - Point2 p; /* board cell */ + Point2 p; /* board cell */ Rectangle bbox; int orient; int ncells; - int *hit; /* |hit| = ncells and hitᵢ ∈ {0,1} */ + int *hit; /* |hit| = ncells and hitᵢ ∈ {0,1} */ }; struct Map @@ -105,3 +105,26 @@ struct Stands ulong nused; ulong cap; }; + +typedef struct Mentry Mentry; +typedef struct Mlist Mlist; +typedef struct Matchlist Matchlist; + +struct Mentry +{ + int id; + char *title; +}; + +struct Mlist +{ + Mentry *entries; + int nentries; + int filling; +}; + +struct Matchlist +{ + Mlist; + int selected; /* [-1,nitems) where -1 is none */ +}; -- cgit v1.2.3