aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-08-31 10:16:12 +0000
committerrodri <rgl@antares-labs.eu>2023-08-31 10:16:12 +0000
commit68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6 (patch)
tree406f9c7c4175818285c36c6e076d08f910988433
parentbe547a2dba10292fb3191bc5fec42212d2391660 (diff)
downloadbattleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.tar.gz
battleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.tar.bz2
battleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.zip
improved playerq locking.
wrote a little how to play guide.
-rw-r--r--bts.c11
-rw-r--r--btsd.c41
-rw-r--r--readme.md27
3 files changed, 59 insertions, 20 deletions
diff --git a/bts.c b/bts.c
index 14b5c2c..1a6478e 100644
--- a/bts.c
+++ b/bts.c
@@ -63,7 +63,6 @@ Cursor aimcursor = {
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 alienboard;
Board localboard;
Ship armada[NSHIPS];
Ship *curship;
+int layoutdone;
Point2 lastshot;
struct {
int state;
- int layoutdone;
} game;
struct {
@@ -173,7 +172,7 @@ resetgame(void)
}
curship = nil;
game.state = Waiting0;
- game.layoutdone = 0;
+ layoutdone = 0;
}
Image *
@@ -546,11 +545,11 @@ rmb(Mousectl *mc)
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 @@ rmb(Mousectl *mc)
cell2coords(armada[i].p), armada[i].orient == OH? 'h': 'v');
}
chanprint(egress, "layout %s\n", buf);
- game.layoutdone++;
+ layoutdone++;
break;
}
send(drawchan, nil);
diff --git a/btsd.c b/btsd.c
index 6e4ac5e..991e359 100644
--- a/btsd.c
+++ b/btsd.c
@@ -42,6 +42,20 @@ popplayer(void)
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 @@ netrecvthread(void *arg)
}
void
-serveproc(void *arg)
+battleproc(void *arg)
{
NetConnInfo *nci[2];
Match *m;
@@ -104,7 +118,7 @@ serveproc(void *arg)
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 @@ serveproc(void *arg)
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 @@ Swapturn:
}
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 @@ reaper(void *)
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 @@ reaper(void *)
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 @@ matchmaker(void *)
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);
}
}
diff --git a/readme.md b/readme.md
index 5f11e64..99e346c 100644
--- 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.