ref: a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a
parent: 107b6625f07a2114e94d09e0ab4d825cb93740eb
author: rodri <rgl@antares-labs.eu>
date: Sun Sep 17 18:06:16 EDT 2023
initial work on a menu of matches. also made some corrections and changed the tokenize(2) fields identifiers from cmd[] to f[].
--- a/bts.c
+++ b/bts.c
@@ -80,11 +80,11 @@
Ship *curship;
int layoutdone;
Point2 lastshot;
+Matchlist matchlist;
struct {
int state;
} game;
-
struct {
Image *c; /* color */
char *s; /* banner text */
@@ -122,6 +122,29 @@
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 @@
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);
@@ -270,6 +290,52 @@
}
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)
{
static Image *c;
@@ -339,6 +405,7 @@
case Waiting0:
drawtitle(screenb);
drawgameoptions(screenb);
+ drawmatchlist(screenb);
break;
default:
drawboard(screenb, &alienboard);
@@ -577,7 +644,7 @@
DONE,
};
static char *items[] = {
- [PLACESHIP] "place ships",
+ [PLACESHIP] "relocate ships",
[DONE] "done",
nil
};
@@ -712,37 +779,47 @@
}
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:
/* <idx?> <uid> (hit|missed) <coord> */
@@ -751,27 +828,27 @@
*/
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);
@@ -778,8 +855,8 @@
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;
--- a/btsd.c
+++ b/btsd.c
@@ -239,7 +239,7 @@
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 @@
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;
}
--- a/dat.h
+++ b/dat.h
@@ -44,11 +44,11 @@
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
@@ -104,4 +104,27 @@
Player **seats;
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 */
};