ref: b3441b9913d4220c036f892ddb378ee8417c443a
parent: f2fbb92be6b39f4150b6729814f41e91bb64266d
author: rodri <rgl@antares-labs.eu>
date: Wed Nov 13 10:34:10 EST 2024
btsd: refactor battleproc().
--- a/btsd.c
+++ b/btsd.c
@@ -413,6 +413,113 @@
}
void
+layout(char *args, Match *m, Stands *stands, uint pidx, uint opidx)
+{
+ Player *p, *op;
+ Point2 cell;
+ uchar buf[BY2MAP];
+ char *coords[5];
+ uint n0;
+ int i, orient;
+
+ p = m->pl[pidx];
+ op = m->pl[opidx];
+
+ if(gettokens(args, coords, nelem(coords), ",") == nelem(coords)){
+ if(debug)
+ fprint(2, "rcvd layout from %s\n", p->name);
+
+ for(i = 0; i < nelem(coords); i++){
+ cell = coords2cell(coords[i]);
+ orient = coords[i][strlen(coords[i])-1] == 'h'? OH: OV;
+ settiles(p, cell, orient, shiplen(i), Tship);
+ }
+
+ p->state = Waiting;
+ bitpackmap(buf, sizeof buf, p);
+ broadcast(stands, "outlayed %d %.*[\n", pidx, sizeof buf, buf);
+
+ if(op->state == Waiting){
+ if(debug){
+ fprint(2, "%s's map:\n", p->name);
+ fprintmap(2, p);
+ fprint(2, "%s's map:\n", op->name);
+ fprintmap(2, op);
+ }
+ n0 = truerand();
+ if(debug)
+ fprint(2, "let the game begin: %s plays, %s waits\n",
+ m->pl[n0&1]->name, m->pl[(n0+1)&1]->name);
+
+ chanprint(m->pl[n0&1]->io.out, "play\n");
+ m->pl[n0&1]->state = Playing;
+
+ chanprint(m->pl[(n0+1)&1]->io.out, "wait\n");
+
+ broadcast(stands, "plays %d\n", n0&1);
+ }
+ }
+}
+
+int
+shoot(char *args, Match *m, Stands *stands, uint pidx, uint opidx)
+{
+ Player *p, *op;
+ Point2 cell;
+ char cbuf[3+1];
+
+ p = m->pl[pidx];
+ op = m->pl[opidx];
+
+ cell = coords2cell(args);
+ switch(gettile(op, cell)){
+ case Tship:
+ settile(op, cell, Thit);
+ chanprint(p->io.out, "hit\n");
+
+ cell2coords(cbuf, sizeof cbuf, cell);
+ chanprint(op->io.out, "hit %s\n", cbuf);
+
+ broadcast(stands, "hit %d %s\n", pidx, cbuf);
+
+ if(countshipcells(op) < (debug? 12: 1)){
+ chanprint(p->io.out, "win\n");
+ chanprint(op->io.out, "lose\n");
+
+ p->state = Waiting0;
+ p->battle = nil;
+
+ op->state = Waiting0;
+ op->battle = nil;
+
+ broadcast(stands, "won %d\n", pidx);
+ return 1;
+ }
+ goto Swapturn;
+ case Twater:
+ settile(op, cell, Tmiss);
+ chanprint(p->io.out, "miss\n");
+
+ cell2coords(cbuf, sizeof cbuf, cell);
+ chanprint(op->io.out, "miss %s\n", cbuf);
+
+ broadcast(stands, "miss %d %s\n", pidx, cbuf);
+Swapturn:
+ chanprint(p->io.out, "wait\n");
+ chanprint(op->io.out, "play\n");
+
+ p->state = Waiting;
+ op->state = Playing;
+
+ broadcast(stands, "plays %d\n", opidx);
+ if(debug)
+ fprint(2, "%s plays, %s waits\n", op->name, p->name);
+ break;
+ }
+ return 0;
+}
+
+void
battleproc(void *arg)
{
Msg *msg;
@@ -422,15 +529,12 @@
Player *p, *op;
Stands stands; /* TODO make this a member of Match */
uchar buf[BY2MAP];
- char cbuf[3+1];
- uint n0;
+ uint pidx, opidx;
+ int i, matchisover;
- Point2 cell;
- char *coords[5];
- int i, orient;
-
m = arg;
memset(&stands, 0, sizeof stands);
+ matchisover = 0;
threadsetname("battleproc [%d] %s ↔ %s", m->id,
m->pl[0]->nci != nil? m->pl[0]->nci->raddr: "andy",
@@ -455,7 +559,8 @@
if(debug) fprint(2, "[%d] battleproc rcvd '%s' from p(fd=%d) on data\n", getpid(), msg->body, msg->from->io.fd);
p = msg->from;
- op = p == m->pl[0]? m->pl[1]: m->pl[0];
+ pidx = p == m->pl[0]? 0: 1;
+ opidx = pidx^1;
cb = parsecmd(msg->body, strlen(msg->body));
ct = lookupcmd(cb, clcmd, nelem(clcmd));
@@ -465,93 +570,39 @@
switch(p->state){
case Outlaying:
if(ct->index == CMlayout)
- if(gettokens(cb->f[1], coords, nelem(coords), ",") == nelem(coords)){
- if(debug)
- fprint(2, "rcvd layout from %s\n", p->name);
- for(i = 0; i < nelem(coords); i++){
- cell = coords2cell(coords[i]);
- orient = coords[i][strlen(coords[i])-1] == 'h'? OH: OV;
- settiles(p, cell, orient, shiplen(i), Tship);
- }
- p->state = Waiting;
- bitpackmap(buf, sizeof buf, p);
- broadcast(&stands, "outlayed %d %.*[\n", p == m->pl[0]? 0: 1, sizeof buf, buf);
- if(op->state == Waiting){
- if(debug){
- fprint(2, "%s's map:\n", p->name);
- fprintmap(2, p);
- fprint(2, "%s's map:\n", op->name);
- fprintmap(2, op);
- }
- n0 = truerand();
- if(debug)
- fprint(2, "let the game begin: %s plays, %s waits\n", m->pl[n0&1]->name, m->pl[(n0+1)&1]->name);
- chanprint(m->pl[n0&1]->io.out, "play\n");
- m->pl[n0&1]->state = Playing;
- chanprint(m->pl[(n0+1)&1]->io.out, "wait\n");
- broadcast(&stands, "plays %d\n", n0&1);
- }
- }
+ layout(cb->f[1], m, &stands, pidx, opidx);
break;
case Playing:
- if(ct->index == CMshoot){
- cell = coords2cell(cb->f[1]);
- switch(gettile(op, cell)){
- case Tship:
- settile(op, cell, Thit);
- chanprint(p->io.out, "hit\n");
- cell2coords(cbuf, sizeof cbuf, cell);
- chanprint(op->io.out, "hit %s\n", cbuf);
- broadcast(&stands, "hit %d %s\n", p == m->pl[0]? 0: 1, cbuf);
- if(countshipcells(op) < (debug? 12: 1)){
- chanprint(p->io.out, "win\n");
- chanprint(op->io.out, "lose\n");
- p->state = Waiting0;
- p->battle = nil;
- op->state = Waiting0;
- op->battle = nil;
- broadcast(&stands, "won %d\n", p == m->pl[0]? 0: 1);
- freemsg(msg);
- goto Finish;
- }
- goto Swapturn;
- case Twater:
- settile(op, cell, Tmiss);
- chanprint(p->io.out, "miss\n");
- cell2coords(cbuf, sizeof cbuf, cell);
- chanprint(op->io.out, "miss %s\n", cbuf);
- broadcast(&stands, "miss %d %s\n", p == m->pl[0]? 0: 1, cbuf);
-Swapturn:
- chanprint(p->io.out, "wait\n");
- chanprint(op->io.out, "play\n");
- p->state = Waiting;
- op->state = Playing;
- broadcast(&stands, "plays %d\n", op == m->pl[0]? 0: 1);
- if(debug)
- fprint(2, "%s plays, %s waits\n", op->name, p->name);
- break;
- }
- }
+ if(ct->index == CMshoot)
+ matchisover = shoot(cb->f[1], m, &stands, pidx, opidx);
break;
}
Nocmd:
free(cb);
freemsg(msg);
+ if(matchisover)
+ goto Finish;
break;
case CTL:
- if(debug) fprint(2, "[%d] battleproc rcvd '%s' from p(fd=%d) on ctl\n", getpid(), msg->body, msg->from->io.fd);
+ if(debug) fprint(2, "[%d] battleproc rcvd '%s' from p(fd=%d) on ctl\n",
+ getpid(), msg->body, msg->from->io.fd);
p = msg->from;
+ pidx = p == m->pl[0]? 0: 1;
+ opidx = pidx^1;
+ op = m->pl[opidx];
+
if(strcmp(msg->body, "player left") == 0){
if(p->state == Watching){
leaveseat(&stands, p);
freeplayer(p);
}else{
- op = p == m->pl[0]? m->pl[1]: m->pl[0];
chanprint(op->io.out, "win\n");
op->state = Waiting0;
op->battle = nil;
- broadcast(&stands, "won %d\n", op == m->pl[0]? 0: 1);
+
+ broadcast(&stands, "won %d\n", opidx);
+
freeplayer(p);
freemsg(msg);
goto Finish;
@@ -562,10 +613,12 @@
p->battle = m;
chanprint(p->io.out, "watching %d %s %s\n",
m->id, m->pl[0]->name, m->pl[1]->name);
+
for(i = 0; i < nelem(m->pl); i++){
if(m->pl[i]->state != Outlaying){
bitpackmap(buf, sizeof buf, m->pl[i]);
- chanprint(p->io.out, "outlayed %d %.*[\n", i, sizeof buf, buf);
+ chanprint(p->io.out, "outlayed %d %.*[\n",
+ i, sizeof buf, buf);
}
if(m->pl[i]->state == Playing)
chanprint(p->io.out, "plays %d\n", i);