shithub: battleship

Download patch

ref: 68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6
parent: be547a2dba10292fb3191bc5fec42212d2391660
author: rodri <rgl@antares-labs.eu>
date: Thu Aug 31 06:16:12 EDT 2023

improved playerq locking.
wrote a little how to play guide.

--- a/bts.c
+++ b/bts.c
@@ -63,7 +63,6 @@
 	  0x21, 0x84, 0x31, 0x8c, 0x0f, 0xf0, 0x00, 0x00,
 	}
 };
-
 char deffont[] = "/lib/font/bit/pelm/unicode.9.font";
 char winspec[32];
 Channel *drawchan;
@@ -76,11 +75,11 @@
 Board localboard;
 Ship armada[NSHIPS];
 Ship *curship;
+int layoutdone;
 Point2 lastshot;
 
 struct {
 	int state;
-	int layoutdone;
 } game;
 
 struct {
@@ -173,7 +172,7 @@
 	}
 	curship = nil;
 	game.state = Waiting0;
-	game.layoutdone = 0;
+	layoutdone = 0;
 }
 
 Image *
@@ -546,11 +545,11 @@
 	mc->xy = addpt(mc->xy, screen->r.min);
 	switch(menuhit(3, mc, &menu, _screen)){
 	case PLACESHIP:
-		if(!game.layoutdone)
+		if(!layoutdone)
 			curship = &armada[0];
 		break;
 	case DONE:
-		if(curship != nil || game.layoutdone)
+		if(curship != nil || layoutdone)
 			break;
 
 		if(!confirmdone(mc))
@@ -565,7 +564,7 @@
 				cell2coords(armada[i].p), armada[i].orient == OH? 'h': 'v');
 		}
 		chanprint(egress, "layout %s\n", buf);
-		game.layoutdone++;
+		layoutdone++;
 		break;
 	}
 	send(drawchan, nil);
--- a/btsd.c
+++ b/btsd.c
@@ -42,6 +42,20 @@
 	return p;
 }
 
+/* non-locking version */
+Player *
+nlpopplayer(void)
+{
+	Player *p;
+
+	p = nil;
+	if(playerq.nplayers > 0)
+		p = playerq.players[--playerq.nplayers];
+	if(debug)
+		fprint(2, "poppin fd %d sfd %d state %d\n", p->fd, p->sfd, p->state);
+	return p;
+}
+
 void
 freeplayer(Player *p)
 {
@@ -82,7 +96,7 @@
 }
 
 void
-serveproc(void *arg)
+battleproc(void *arg)
 {
 	NetConnInfo *nci[2];
 	Match *m;
@@ -104,7 +118,7 @@
 	nci[1] = getnetconninfo(nil, m->pl[1]->fd);
 	if(nci[0] == nil || nci[1] == nil)
 		sysfatal("getnetconninfo: %r");
-	threadsetname("serveproc %s ↔ %s", nci[0]->raddr, nci[1]->raddr);
+	threadsetname("battleproc %s ↔ %s", nci[0]->raddr, nci[1]->raddr);
 	freenetconninfo(nci[0]);
 	freenetconninfo(nci[1]);
 
@@ -157,9 +171,9 @@
 						fprint(2, "curstates [%d] %d / [%d] %d\n", i, p->state, i^1, op->state);
 					if(op->state == Waiting){
 						if(debug){
-							fprint(2, "map0:\n");
+							fprint(2, "map%d:\n", i);
 							fprintmap(2, p);
-							fprint(2, "map1:\n");
+							fprint(2, "map%d:\n", i^1);
 							fprintmap(2, op);
 						}
 						n0 = truerand();
@@ -207,7 +221,7 @@
 	}
 Finish:
 	if(debug)
-		fprint(2, "[%d] serveproc ending\n", getpid());
+		fprint(2, "[%d] battleproc ending\n", getpid());
 	free(m);
 	chanfree(cp[0].c);
 	chanfree(cp[1].c);
@@ -225,6 +239,7 @@
 	threadsetname("reaper");
 
 	for(;;){
+		qlock(&playerq);
 		for(i = 0; i < playerq.nplayers; i++){
 			if(debug)
 				fprint(2, "reapin fd %d sfd %d state %d?",
@@ -233,13 +248,12 @@
 			if(n < 0 || strncmp(buf, "Close", 5) == 0){
 				if(debug)
 					fprint(2, " yes\n");
-				qlock(&playerq);
 				freeplayer(playerq.players[i]);
 				memmove(&playerq.players[i], &playerq.players[i+1], (--playerq.nplayers-i)*sizeof(Player*));
-				qunlock(&playerq);
 			}else if(debug)
 					fprint(2, " no\n");
 		}
+		qunlock(&playerq);
 		sleep(HZ2MS(1));
 	}
 }
@@ -252,24 +266,23 @@
 	threadsetname("matchmaker");
 
 	for(;;){
-		/*
-		 * TODO make fairer matches
-		 * locking playerq while checking nplayers and popping the couple.
-		 */
+		qlock(&playerq);
 		if(playerq.nplayers < 2){
+			qunlock(&playerq);
 			sleep(100);
 			continue;
 		}
 
 		m = emalloc(sizeof *m);
-		m->pl[0] = popplayer();
-		m->pl[1] = popplayer();
+		m->pl[0] = nlpopplayer();
+		m->pl[1] = nlpopplayer();
+		qunlock(&playerq);
 		m->pl[0]->state = Waiting0;
 		m->pl[1]->state = Waiting0;
 		memset(m->pl[0]->map, Twater, MAPW*MAPH);
 		memset(m->pl[1]->map, Twater, MAPW*MAPH);
 
-		proccreate(serveproc, m, mainstacksize);
+		proccreate(battleproc, m, mainstacksize);
 	}
 }
 
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,30 @@
 # Battleship
 
 An on-line multi-player implementation of Battleship (a.k.a. Sink the Fleet).
+
+# How to play
+
+Join a server
+
+	% bts antares-labs.eu
+
+Then wait for another player to show up (admire the velero).  When
+they do, you'll have to place your ships in the lower (local) board by
+clicking LMB when the ship is at the right location; you can also
+change the orientation of the ship by pressing MMB and selecting
+“rotate ship”.  If you are not happy with the current layout, press
+RMB and select “place ships” to start all over again (tip: if you
+don't want to move a ship, click LMB without moving the mouse.) Once
+you are done—a banner at the bottom will inform you—, press RMB and
+choose “done”.
+
+At this moment the battle will begin.  Each of you has a turn (read
+[battleship.pdf](battleship.pdf)), and if you are the one shooting you
+have to aim at a tile at the upper (target) board—which will show a
+reticle—and press LMB to fire a shot.  If you hit an enemy ship, the
+tile will show an X, otherwise a O. If you are the one waiting, well,
+just do that.
+
+There's no turn timeout so the battles can get as long as any of the
+players's will.  If you quit or your connection is lost, your opponent
+wins.