aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-09-17 22:06:16 +0000
committerrodri <rgl@antares-labs.eu>2023-09-17 22:06:16 +0000
commita99916512365d68d130c7dfdb3f7ac5e2e0bbe8a (patch)
tree62c329d7bb55ab66b11a206810001c34544015e1
parent107b6625f07a2114e94d09e0ab4d825cb93740eb (diff)
downloadbattleship-a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a.tar.gz
battleship-a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a.tar.bz2
battleship-a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a.zip
initial work on a menu of matches.
also made some corrections and changed the tokenize(2) fields identifiers from cmd[] to f[].
-rw-r--r--bts.c137
-rw-r--r--btsd.c4
-rw-r--r--dat.h27
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);
@@ -270,6 +290,52 @@ drawgameoptions(Image *dst)
}
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 @@ 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:
/* <idx?> <uid> (hit|missed) <coord> */
@@ -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 */
+};