diff options
author | rodri <rgl@antares-labs.eu> | 2023-08-31 10:16:12 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2023-08-31 10:16:12 +0000 |
commit | 68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6 (patch) | |
tree | 406f9c7c4175818285c36c6e076d08f910988433 | |
parent | be547a2dba10292fb3191bc5fec42212d2391660 (diff) | |
download | battleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.tar.gz battleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.tar.bz2 battleship-68cfdc52fa2daecdd2b4db02fe5f117a4e2329f6.zip |
improved playerq locking.
wrote a little how to play guide.
-rw-r--r-- | bts.c | 11 | ||||
-rw-r--r-- | btsd.c | 41 | ||||
-rw-r--r-- | readme.md | 27 |
3 files changed, 59 insertions, 20 deletions
@@ -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); @@ -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); } } @@ -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. |