shithub: battleship

Download patch

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);