shithub: battleship

Download patch

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