ref: b106a4c0a8e8fc1bedce0a25a5c9a7be4a1c06a2
parent: 7104ef7c8cf505cc5be1c2c5e28a745b929af1b3
author: rodri <rgl@antares-labs.eu>
date: Tue Aug 29 18:13:43 EDT 2023
implemented match conclusion logic and notification. made the window un-resizable.
--- a/bts.c
+++ b/bts.c
@@ -28,7 +28,12 @@
int state;
} game;
+struct {
+ Image *c; /* color */
+ char *s; /* banner text */
+} conclusion;
+
Point
fromworld(Point2 p)
{
@@ -167,7 +172,7 @@
if(s == nil)
return;
p = Pt(SCRW/2 - stringwidth(font, s)/2, SCRH-Boardmargin);
- stringbg(dst, p, display->white, ZP, font, s, display->black, ZP);
+ string(dst, p, display->white, ZP, font, s);
}
void
@@ -181,22 +186,40 @@
drawships(screenb);
drawinfo(screenb);
+ if(conclusion.s != nil)
+ string(screenb, Pt(SCRW/2 - stringwidth(font, conclusion.s)/2, 0), conclusion.c, ZP, font, conclusion.s);
+
draw(screen, screen->r, screenb, nil, ZP);
flushimage(display, 1);
unlockdisplay(display);
+
+ if(conclusion.s != nil){
+ sleep(5000);
+ conclusion.s = nil;
+ redraw();
+ }
}
void
resize(void)
{
+ int fd;
+
lockdisplay(display);
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed");
unlockdisplay(display);
- freeimage(screenb);
- screenb = eallocimage(display, rectsubpt(screen->r, screen->r.min), screen->chan, 0, DNofill);
+ /* ignore move events */
+ if(Dx(screen->r) != SCRW || Dy(screen->r) != SCRH){
+ fd = open("/dev/wctl", OWRITE);
+ if(fd >= 0){
+ fprint(fd, "resize %s", winspec);
+ close(fd);
+ }
+ }
+
send(drawchan, nil);
}
@@ -354,7 +377,7 @@
switch(game.state){
case Outlaying:
if(b == &localboard)
- if(curship != nil)
+ if(curship != nil && rectinrect(curship->bbox, localboard.bbox))
if(++curship-armada >= nelem(armada))
curship = nil;
else if(curship != &armada[0])
@@ -405,7 +428,9 @@
break;
}
curship->p = toboard(&localboard, curship->bbox.min);
- /* TODO check for collision with other ships */
+
+ if(rectXarmada(curship->bbox))
+ curship->bbox = ZR;
}
break;
}
@@ -536,6 +561,30 @@
}
void
+celebrate(void)
+{
+ static Image *c;
+ static char s[] = "YOU WON!";
+
+ if(c == nil)
+ c = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreen);
+ conclusion.c = c;
+ conclusion.s = s;
+}
+
+void
+keelhaul(void)
+{
+ static Image *c;
+ static char s[] = "…YOU LOST";
+
+ if(c == nil)
+ c = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
+ conclusion.c = c;
+ conclusion.s = s;
+}
+
+void
processcmd(char *cmd)
{
Point2 cell;
@@ -545,11 +594,11 @@
fprint(2, "rcvd '%s'\n", cmd);
if(strcmp(cmd, "win") == 0){
-// celebrate();
+ celebrate();
resetgame();
game.state = Waiting0;
}else if(strcmp(cmd, "lose") == 0){
-// keelhaul();
+ keelhaul();
resetgame();
game.state = Waiting0;
}
--- a/btsd.c
+++ b/btsd.c
@@ -179,6 +179,13 @@
settile(op, cell, Thit);
write(p->fd, "hit\n", 4);
fprint(op->fd, "hit %s\n", cell2coords(cell));
+ if(countshipcells(op) < 1){
+ write(p->fd, "win\n", 4);
+ write(op->fd, "lose\n", 5);
+ pushplayer(p);
+ pushplayer(op);
+ goto Finish;
+ }
goto Swapturn;
case Twater:
settile(op, cell, Tmiss);
@@ -192,12 +199,13 @@
break;
}
if(debug)
- fprint(2, "%d waits, %d plays\n", i, i^1);
+ fprint(2, "%d plays, %d waits\n", i^1, i);
}
break;
}
free(s);
}
+Finish:
if(debug)
fprint(2, "[%d] serveproc ending\n", getpid());
free(m);
--- a/fns.h
+++ b/fns.h
@@ -16,4 +16,5 @@
void settile(Map*, Point2, int);
void settiles(Map*, Point2, int, int, int);
void fprintmap(int, Map*);
+int countshipcells(Map*);
int shiplen(int);
--- a/util.c
+++ b/util.c
@@ -94,6 +94,19 @@
}
int
+countshipcells(Map *m)
+{
+ int i, j, n;
+
+ n = 0;
+ for(i = 0; i < MAPW; i++)
+ for(j = 0; j < MAPH; j++)
+ if(gettile(m, Pt2(i,j,1)) == Tship)
+ n++;
+ return n;
+}
+
+int
shiplen(int stype)
{
assert(stype >= 0 && stype < NSHIPS);