From ca4af600fdad77b3c4603a62c81eee51187fafcf Mon Sep 17 00:00:00 2001 From: rodri Date: Fri, 25 Aug 2023 21:53:17 +0000 Subject: implemented most of the layout code. added a new util.c to host the cell/coordinate conversions. made the showproc a painter thread instead, to avoid problems with menuhit(2). --- bts.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- btsd.c | 2 +- fns.h | 6 +++ mkfile | 1 + util.c | 42 ++++++++++++++++++ 5 files changed, 166 insertions(+), 41 deletions(-) create mode 100644 util.c diff --git a/bts.c b/bts.c index bda3be9..a337c4f 100644 --- a/bts.c +++ b/bts.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "dat.h" @@ -20,6 +21,7 @@ Image *tiletab[NTILES]; Board alienboard; Board localboard; Ship armada[NSHIPS]; +Ship *curship; struct { int state; @@ -197,7 +199,7 @@ inittiles(void) freeimage(brush); break; case Tship: - brush = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x333333FF); + brush = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xAAAAAAFF); draw(tiletab[i], tiletab[i]->r, brush, nil, ZP); freeimage(brush); brush = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DBlack); @@ -257,7 +259,7 @@ initarmada(void) case Scruiser: /* fallthrough */ case Ssubmarine: s->ncells = 3; break; case Sdestroyer: s->ncells = 2; break; - default: sysfatal("initships: unknown ship: %d", i); + default: sysfatal("initarmada: unknown ship: %d", i); } s->orient = OH; s->hit = emalloc(s->ncells*sizeof(int)); @@ -266,35 +268,38 @@ initarmada(void) } } -void -placeship(Mousectl *mc, Ship *s) +int +confirmdone(Mousectl *mc) { - Rectangle newbbox; - - for(;;){ - if(readmouse(mc) < 0) - break; - - mc->xy = subpt(mc->xy, screen->r.min); - newbbox = mkshipbbox(toboard(&localboard, mc->xy), s->orient, s->ncells); - - if(rectinrect(newbbox, localboard.bbox)){ - s->p = toboard(&localboard, mc->xy); - s->bbox = newbbox; + Cursor yousure = { + {0, 0}, + { 0xf7, 0xfe, 0x15, 0x54, 0x1d, 0x54, 0x09, 0x54, + 0x09, 0xdc, 0x00, 0x00, 0x75, 0x77, 0x45, 0x54, + 0x75, 0x66, 0x15, 0x54, 0x77, 0x57, 0x00, 0x00, + 0x00, 0x02, 0x2a, 0x84, 0x11, 0x28, 0x2a, 0x90, + }, + { 0xea, 0x2b, 0xea, 0xab, 0xe2, 0xab, 0xf6, 0xab, + 0xf6, 0x23, 0xff, 0xff, 0x8a, 0x88, 0xba, 0xab, + 0x8a, 0x99, 0xea, 0xab, 0x88, 0xa8, 0xff, 0xff, + 0xff, 0xfd, 0xd5, 0x7b, 0xee, 0xd7, 0xd5, 0x6f, } - if(mc->buttons == 1 && ptinrect(mc->xy, localboard.bbox)) - break; - send(drawchan, nil); + }; + setcursor(mc, &yousure); + while(mc->buttons == 0) + readmouse(mc); + if(mc->buttons != 4){ + setcursor(mc, nil); + return 0; } -} - -void -placeships(Mousectl *mc) -{ - int i; - - for(i = 0; i < nelem(armada); i++) - placeship(mc, &armada[i]); + while(mc->buttons){ + if(mc->buttons != 4){ + setcursor(mc, nil); + return 0; + } + readmouse(mc); + } + setcursor(mc, nil); + return 1; } void @@ -315,10 +320,36 @@ lmb(Mousectl *mc) cell = toboard(b, mc->xy); switch(game.state){ case Outlaying: - settile(b, cell, Tship); + if(curship != nil && ++curship-armada >= nelem(armada)) + curship = nil; break; case Playing: - chanprint(egress, "shoot %d-%d", (int)cell.x, (int)cell.y); + chanprint(egress, "shoot %s", cell2coords(cell)); + break; + } + send(drawchan, nil); +} + +void +mmb(Mousectl *mc) +{ + enum { + ROTATE, + }; + static char *items[] = { + [ROTATE] "rotate ship", + nil + }; + static Menu menu = { .item = items }; + + if(game.state != Outlaying) + return; + + mc->xy = addpt(mc->xy, screen->r.min); + switch(menuhit(2, mc, &menu, _screen)){ + case ROTATE: + if(curship != nil) + curship->orient = curship->orient == OH? OV: OH; break; } send(drawchan, nil); @@ -329,31 +360,70 @@ rmb(Mousectl *mc) { enum { PLACESHIP, + DONE, }; static char *items[] = { - [PLACESHIP] "place ship", + [PLACESHIP] "place ships", + [DONE] "done", nil }; static Menu menu = { .item = items }; + char buf[5*(1+3+1)+1]; + int i, n; + + if(game.state != Outlaying) + return; + mc->xy = addpt(mc->xy, screen->r.min); switch(menuhit(3, mc, &menu, _screen)){ case PLACESHIP: - placeships(mc); + curship = &armada[0]; + break; + case DONE: + if(curship != nil) + break; + + if(!confirmdone(mc)) + break; + + buf[0] = 0; + n = 0; + for(i = 0; i < nelem(armada); i++){ + assert(sizeof buf - n > 1+3+1); + if(i != 0) + buf[n++] = ','; + n += snprint(buf+n, sizeof buf - n, "%s%c", + cell2coords(armada[i].p), armada[i].orient == OH? 'h': 'v'); + } + chanprint(egress, "layout %s", buf); break; } + send(drawchan, nil); } void mouse(Mousectl *mc) { + Rectangle newbbox; + mc->xy = subpt(mc->xy, screen->r.min); + if(game.state == Outlaying && curship != nil){ + newbbox = mkshipbbox(toboard(&localboard, mc->xy), curship->orient, curship->ncells); + + if(rectinrect(newbbox, localboard.bbox)){ + curship->p = toboard(&localboard, mc->xy); + curship->bbox = newbbox; + } + send(drawchan, nil); + } + switch(mc->buttons){ case 1: lmb(mc); break; case 2: -// mmb(mc); + mmb(mc); break; case 4: rmb(mc); @@ -372,14 +442,11 @@ key(Rune r) } void -showproc(void *) +painter(void *) { - threadsetname("showproc"); - while(recv(drawchan, nil) > 0) redraw(); - - sysfatal("showproc died"); + sysfatal("painter died"); } void @@ -426,12 +493,21 @@ netrecvthread(void *arg) while((n = ioread(io, fd, buf, sizeof(buf)-1)) > 0){ buf[n] = 0; + if(debug) fprint(2, "rcvd '%s'\n", buf); + + if(strcmp(buf, "win") == 0) + game.state = Waiting0; + else if(strcmp(buf, "lose") == 0) + game.state = Waiting0; + switch(game.state){ case Waiting0: - if(strcmp(buf, "layout") == 0) + if(strcmp(buf, "layout") == 0){ game.state = Outlaying; + curship = &armada[0]; + } break; case Outlaying: if(strcmp(buf, "wait") == 0) @@ -540,7 +616,7 @@ threadmain(int argc, char *argv[]) drawchan = chancreate(sizeof(void*), 0); ingress = chancreate(sizeof(char*), 16); egress = chancreate(sizeof(char*), 16); - proccreate(showproc, nil, mainstacksize); + threadcreate(painter, nil, mainstacksize); threadcreate(inputthread, &in, mainstacksize); threadcreate(netrecvthread, &fd, mainstacksize); threadcreate(netsendthread, &fd, mainstacksize); diff --git a/btsd.c b/btsd.c index 8178f75..6b675fd 100644 --- a/btsd.c +++ b/btsd.c @@ -115,7 +115,7 @@ serveproc(void *arg) while((i = alt(a)) >= 0){ if(a[i].err != nil){ if(debug) - fprint(2, "alt: %s\n", a[i].err); + fprint(2, "[%d] alt: %s\n", getpid(), a[i].err); write(m[i^1]->fd, "win", 3); m[i^1]->state = Waiting0; pushplayer(m[i^1]); diff --git a/fns.h b/fns.h index 67a4756..ab3d3d7 100644 --- a/fns.h +++ b/fns.h @@ -6,3 +6,9 @@ void *emalloc(ulong); void *erealloc(void*, ulong); Image *eallocimage(Display*, Rectangle, ulong, int, ulong); + +/* + * util + */ +char *cell2coords(Point2); +Point2 coords2cell(char*); diff --git a/mkfile b/mkfile index 2e7f5ac..ca7218d 100644 --- a/mkfile +++ b/mkfile @@ -8,6 +8,7 @@ TARG=\ OFILES=\ alloc.$O\ + util.$O\ HFILES=\ dat.h\ diff --git a/util.c b/util.c new file mode 100644 index 0000000..4594a9a --- /dev/null +++ b/util.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" + +static char rowtab[] = "abcdefghijklmnopq"; + + +char * +cell2coords(Point2 cell) +{ + static char s[3+1]; + + assert(cell.x < 17 && cell.x >= 0 + && cell.y < 17 && cell.y >= 0); + + snprint(s, sizeof s, "%c%d", rowtab[(int)cell.y], (int)cell.x); + return s; +} + +Point2 +coords2cell(char *s) +{ + Point2 cell; + char *p; + + assert(s[0] >= 'a' && s[0] <= 'q'); + + cell = Pt2(0,0,1); + p = strchr(rowtab, s[0]); + cell.y = p-rowtab; + cell.x = strtol(s+1, nil, 10); + + assert(cell.x < 17 && cell.x >= 0); + + return cell; +} -- cgit v1.2.3