ref: dd155881cf69b09d8e33ad2f4d6ef5a96eaa097c
parent: 1986f3905eca9114442405d2b3180eea9bc709bc
author: mkf <mkf@cloud9p.org>
date: Mon Oct 21 05:17:15 EDT 2024
fix build on plan 9 (lots of changes)
--- a/cli.c
+++ b/cli.c
@@ -10,7 +10,8 @@
#include "unix.h"
#include "engine.h"
-char *gface[2] = {"☺", "☹"}; /* glenda's face(es) */
+char *gface[2] = {"☹", "☺"}; /* glenda's face(es) */
+
int debug = 0;
void
--- a/engine.c
+++ b/engine.c
@@ -5,7 +5,7 @@
#include "netclient.h"
/*
- * Sets up a new level
+ * Sets up a new level and fills it
*/
void
initlevel(Game *game)
@@ -14,9 +14,9 @@
for(x = 0; x < SzX; x++)
for(y = 0; y < SzY; y++)
- game.ogrid[x][y] = Prev;
+ game->ogrid[x][y] = Prev;
- switch(game.difficulty)
+ switch(game->difficulty)
{
case DEasy:
cnt = 10 + nrand(5);
@@ -32,26 +32,26 @@
cnt = 0;
break;
}
- game.ogrid[SzX/2][SzY/2] = Glenda;
+ game->ogrid[SzX/2][SzY/2] = Glenda;
setmap:
for(i = 0 ; i < cnt ; i++)
{
- /* ensure we don't over place walls in glenda or walls (again) */
+ /* ensure walls dont overlap with other walls or glenda */
do
{
x = nrand(SzX);
y = nrand(SzY);
- }while(game.ogrid[x][y] == Glenda || game.ogrid[x][y] == Wall);
- game.ogrid[x][y] = Wall;
+ }while(game->ogrid[x][y] == Glenda || game->ogrid[x][y] == Wall);
+ game->ogrid[x][y] = Wall;
}
/* ensure we don't make an unfair map */
if(checkstate(game) == Won && findmin(game, Pt(SzX/2, SzY/2)) > 100)
goto setmap;
- memcpy(game.grid, game.ogrid, sizeof(game.grid));
- game.state = Start;
- game.turn = 0;
+ memcpy(game->grid, game->ogrid, sizeof(game->grid));
+ game->state = Start;
+ game->turn = 0;
}
/*
@@ -101,10 +101,10 @@
}
/*
- * Moves glenda from direction
+ * Moves glenda into direction
*/
int
-domove(Game game, int dir)
+domove(Game *game, int dir)
{
Point src, dst;
@@ -111,59 +111,62 @@
src = findglenda(game);
dst = movedir(dir, src);
- if(game.grid[dst.x][dst.y] == Wall)
+ if(game->grid[dst.x][dst.y] == Wall)
return Wall;
- if(game.networked)
- return netmove(game.dir);
+ if(game->networked)
+ return netmove(dir);
- game.grid[dst.x][dst.y] = Glenda;
- game.grid[src.x][src.y] = Prev;
+ game->grid[dst.x][dst.y] = Glenda;
+ game->grid[src.x][src.y] = Prev;
- turn++;
+ game->turn++;
/* we shouldn't guess, server should tell us */
- if(game.ptype[1] == Human && !game.networked)
+ if(game->ptype[1] == Human && !game->networked)
checkstate(game);
return Ok;
}
+/*
+ * Puts a wall inside a point
+ */
int
-doput(Game game, Point p)
+doput(Game *game, Point p)
{
/* clients are expected to do their own error checking */
if(p.x > SzX || p.x < 0 || p.y > SzY || p.y < 0)
return Err;
- if(game.grid[p.x][p.y] == Wall)
+ if(game->grid[p.x][p.y] == Wall)
return Wall;
- if(game.grid[p.x][p.y] == Glenda)
+ if(game->grid[p.x][p.y] == Glenda)
return Glenda;
- if(game.networked)
- return netput(game, p.x, p.y);
+ if(game->networked)
+ return netput(p.x, p.y);
/* take a copy for undo */
- memcpy(game.pgrid, game.grid, sizeof(game.grid));
- grid[p.x][p.y] = Wall;
+ memcpy(game->pgrid, game->grid, sizeof(game->grid));
+ game->grid[p.x][p.y] = Wall;
/* assumes defenders start game first */
- if(game.state == Start)
- game.state = Playing;
+ if(game->state == Start)
+ game->state = Playing;
- turn++;
+ game->turn++;
/* reset the board scores */
for(int x = 0; x < SzX; x++)
for(int y = 0; y < SzY; y++)
- if(game.grid[x][y] != Wall && game.grid[x][y] != Glenda)
- game.grid[x][y] = 100;
+ if(game->grid[x][y] != Wall && game->grid[x][y] != Glenda)
+ game->grid[x][y] = 100;
/* we need it to check game state, even if not playing with computer */
- if(game.ptype[1] == Computer)
+ if(game->ptype[1] == Computer)
nextglenda(game);
- else if(game.ptype[1] == Human && !networked)
+ else if(game->ptype[1] == Human && !game->networked)
checkstate(game);
return Ok;
@@ -173,11 +176,11 @@
* Returns glenda's position
*/
Point
-findglenda(Game game)
+findglenda(Game *game)
{
for(int x = 0; x < SzX; x++)
for(int y = 0; y < SzY; y++)
- if(game.grid[x][y] == 1000)
+ if(game->grid[x][y] == 1000)
return Pt(x, y);
return Pt(-1, -1);
@@ -195,7 +198,7 @@
* traversing the board
*/
int
-score1(Game game, Point p)
+score1(Game *game, Point p)
{
int min = 999;
@@ -215,14 +218,14 @@
* O(n³), but why?
*/
void
-calc(void)
+calc(Game *game)
{
/* assumes SzX = SzY */
for(int i = 0; i < SzX; i++)
for(int x = i; x < SzX-i; x++)
for(int y = i; y < SzY-i; y++)
- if(game.grid[x][y] != Wall && game.grid[x][y] != Glenda)
- game.grid[x][y] = score1(Pt(x, y));
+ if(game->grid[x][y] != Wall && game->grid[x][y] != Glenda)
+ game->grid[x][y] = score1(game, Pt(x, y));
}
/*
@@ -229,13 +232,15 @@
* finds the node with least score around the p
*/
int
-findmin(Point p)
+findmin(Game *game, Point p)
{
+ Point tmp;
int next, min = 998;
for(int dir = NE; dir <= NW; dir++)
{
- next = checknext(game, dir, p);
+ tmp = movedir(dir, p);
+ next = game->grid[tmp.x][tmp.y];
if(next < min)
min = next;
}
@@ -244,15 +249,15 @@
/*
* Makes a move for glenda
- * only use in single player
+ * only used in single player
*/
void
-nextglenda(Game game)
+nextglenda(Game *game)
{
int min = 999, next, dir, nextdir = 0, count = 0;
- Point p = findglenda(game);
+ Point tmp, p = findglenda(game);
- if(networked)
+ if(game->networked)
return;
calc(game);
@@ -261,7 +266,8 @@
for(dir = NE; dir <= NW; dir++)
{
- next = checknext(game, dir, p);
+ tmp = movedir(dir, p);
+ next = game->grid[tmp.x][tmp.y];
if(next < min)
{
min = next;
@@ -272,13 +278,13 @@
nextdir = (nrand(++count) == 0) ? dir : nextdir;
}
if(min > 100)
- state = Won;
+ game->state = Won;
else
- domove(nextdir);
+ domove(game, nextdir);
p = findglenda(game);
if(p.x == 0 || p.x == SzX-1 || p.y == 0 || p.y == SzY-1)
- game.state = Lost;
+ game->state = Lost;
}
/*
@@ -285,7 +291,7 @@
* See if game is over
*/
int
-checkstate(Game game)
+checkstate(Game *game)
{
Point p = findglenda(game);
@@ -294,11 +300,11 @@
calc(game);
if(findmin(game, p) > 100)
- game.state = Won;
+ game->state = Won;
if(p.x == 0 || p.x == SzX-1 || p.y == 0 || p.y == SzY-1)
- game.state = Lost;
+ game->state = Lost;
- return game.state;
+ return game->state;
}
/*
@@ -305,11 +311,11 @@
* Resets the game position
*/
void
-restart(Game game)
+restart(Game *game)
{
- game.turn = 0;
- memcpy(game.grid, game.ogrid, sizeof(game.grid));
- game.state = Start;
+ game->turn = 0;
+ memcpy(game->grid, game->ogrid, sizeof(game->grid));
+ game->state = Start;
}
/*
@@ -316,18 +322,24 @@
* Undos last move
*/
void
-undo(Game game)
+undo(Game *game)
{
int g[SzX][SzY];
- if(state == Start || turn < 2)
+ if(game->state == Start || game->turn < 2)
return;
/* revert turn counter, can be abused by one side */
- turn -= 2;
+ game->turn -= 2;
/* swap grids */
- memcpy(g, game.grid, sizeof g);
- memcpy(game.grid, game.pgrid, sizeof g);
- memcpy(game.pgrid, g, sizeof g);
+ memcpy(g, game->grid, sizeof g);
+ memcpy(game->grid, game->pgrid, sizeof g);
+ memcpy(game->pgrid, g, sizeof g);
+}
+
+int
+isplaying(Game *game)
+{
+ return game->state == Playing || game->state == Start;
}
--- a/engine.h
+++ b/engine.h
@@ -1,5 +1,3 @@
-#define isplaying (state == Playing || state == Start)
-
enum
{
/* difficulty levels (how many circles are initially occupied) */
@@ -63,28 +61,27 @@
/* we maybe be able to merge all this into one bit-array */
int waitbit; /* 0 is go, 1 is wait */
int networked; /* 0 is local, 1 is networked */
- int pside; /* Trapper, Glenda */
}Game;
/* client code */
int debug;
+int pside; /* Trapper, Glenda */
-void initlevel(void);
+void initlevel(Game *game);
Point movedir(int dir, Point p);
int pointdir(Point src, Point dst);
+Point findglenda(Game *game);
-int domove(int dir);
-int doput(Point p);
+int domove(Game *game, int dir);
+int doput(Game *game, Point p);
-Point findglenda(void);
-int checknext(int dir, Point p);
+int score1(Game *game, Point p);
+void calc(Game *game);
+void nextglenda(Game *game);
-int score1(Point p);
-void calc(void);
-void nextglenda(void);
+int findmin(Game *game, Point p);
+int checkstate(Game *game);
+int isplaying(Game *game);
-int findmin(Point p);
-int checkstate(void);
-
-void restart(void);
-void undo(void);
+void restart(Game *game);
+void undo(Game *game);
--- a/gui9.c
+++ b/gui9.c
@@ -2,9 +2,10 @@
#include <libc.h>
#include <draw.h>
#include <event.h>
-#include "netclient.h"
#include "engine.h"
+#include "netclient.h"
+Game game;
Font *font;
@@ -18,6 +19,7 @@
int debug;
char *server = nil;
+
enum
{
New = 0,
@@ -166,9 +168,9 @@
int x, y, rx, ry, d;
char *s = nil;
- if(state == Won)
+ if(game.state == Won)
draw(screen, screen->r, won, nil, ZP);
- else if(state == Lost)
+ else if(game.state == Lost)
draw(screen, screen->r, lost, nil, ZP);
else
draw(screen, screen->r, bg, nil, ZP);
@@ -181,7 +183,7 @@
for(y = 0; y < SzY; y++)
{
p = board2pix(x, y);
- switch(grid[x][y])
+ switch(game.grid[x][y])
{
case Wall:
fillellipse(screen, addpt(screen->r.min, p), rx, ry, cc, ZP);
@@ -197,11 +199,10 @@
USED(s);
if(debug)
{
- s = smprint("%d", grid[x][y]);
+ s = smprint("%d", game.grid[x][y]);
string(screen, addpt(screen->r.min, p), display->black, ZP, font, s);
free(s);
}
-
break;
}
}
@@ -208,6 +209,7 @@
}
flushimage(display, 1);
}
+
void
move(Point m)
{
@@ -218,15 +220,15 @@
/* figure out where the click falls */
p = pix2board(nm.x, nm.y);
- g = findglenda();
+ g = findglenda(&game);
dir = pointdir(g, p);
- if(grid[p.x][p.y] >= 999 || dir == Err)
+ if(game.grid[p.x][p.y] >= 999 || dir == Err)
return;
/* find the direction to p from our currently pos, then move */
- domove(dir);
+ domove(&game, dir);
}
void
@@ -239,10 +241,10 @@
/* figure out where the click falls */
p = pix2board(nm.x, nm.y);
- if(grid[p.x][p.y] >= 999)
+ if(game.grid[p.x][p.y] >= 999)
return;
- doput(p);
+ doput(&game, p);
}
void
@@ -286,7 +288,7 @@
Mouse m;
Event ev;
Netmsg *msg;
- int e, mousedown=0;
+ int e, mousedown = 0;
pnick = getenv("user");
/* todo, add flags for human playing */
@@ -299,7 +301,7 @@
sysfatal("No computer player for defenders yet");
break;
case 'g':
- ptype[1] = Computer;
+ game.ptype[1] = Computer;
break;
case 's':
side = EARGF(usage());
@@ -306,9 +308,9 @@
pside = atoi(side);
break;
case 'n':
- ptype[0] = Net;
- ptype[1] = Net;
- networked = 1;
+ game.ptype[0] = Net;
+ game.ptype[1] = Net;
+ game.networked = 1;
server = EARGF(usage());
break;
case 'N':
@@ -327,25 +329,24 @@
allocimages();
- if(server != nil && networked)
+ if(server != nil && game.networked)
{
srvfd = dial(server, nil, nil, nil);
if(srvfd < 0)
sysfatal("unable to connect: %r");
- netinit();
+ netinit(&game);
drawlevel();
}
else
- initlevel(); /* must happen before "eresized" */
+ initlevel(&game); /* must happen before "eresized" */
eresized(0);
for(;;)
{
- // fprint(2, "XXX %d\n", state);
- if(networked && waitbit && isplaying)
+ if(game.networked && game.waitbit && isplaying(&game))
{
- msg = netmain();
+ msg = netmain(&game);
if(msg->tokens[0] != nil && strcmp(msg->tokens[0], "SYNC"))
drawlevel();
}
@@ -358,14 +359,14 @@
m = ev.mouse;
if(m.buttons == 0)
{
- if(mousedown && isplaying)
+ if(mousedown && isplaying(&game))
{
mousedown = 0;
- if(turn % 2 == 0)
+ if(game.turn % 2 == 0)
put(m.xy);
else
move(m.xy);
- if(!networked)
+ if(!game.networked)
drawlevel();
}
}
@@ -378,20 +379,20 @@
switch(emenuhit(2, &m, &mmenu))
{
case 0:
- difficulty = DEasy;
- initlevel();
+ game.difficulty = DEasy;
+ initlevel(&game);
break;
case 1:
- difficulty = DMed;
- initlevel();
+ game.difficulty = DMed;
+ initlevel(&game);
break;
case 2:
- difficulty = DHard;
- initlevel();
+ game.difficulty = DHard;
+ initlevel(&game);
break;
case 3:
- difficulty = DImp;
- initlevel();
+ game.difficulty = DImp;
+ initlevel(&game);
break;
}
drawlevel();
@@ -401,13 +402,13 @@
switch(emenuhit(3, &m, &rmenu))
{
case New:
- initlevel();
+ initlevel(&game);
break;
case Undo:
- undo();
+ undo(&game);
break;
case Restart:
- restart();
+ restart(&game);
break;
case Exit:
exits(nil);
--- a/netclient.c
+++ b/netclient.c
@@ -62,12 +62,12 @@
}
int
-nethi(char *name, int game, int side, int opts)
+nethi(Game *game, char *name, int gameset, int side, int opts)
{
int len;
char *msg;
- msg = himsg(name, game, side, opts);
+ msg = himsg(name, gameset, side, opts);
if(msg == nil)
return Err;
@@ -78,7 +78,7 @@
/* otherwise client wont read socket to confirm */
waitbit = 1;
free(msg);
- state = Init;
+ game->state = Init;
return Ok;
}
@@ -96,9 +96,7 @@
len = strlen(msg);
if(write(srvfd, msg, len) < len)
sysfatal("netmove(): half written?");
-
- /* otherwise client wont read socket to confirm */
- waitbit = 1;
+
free(msg);
return Ok;
}
@@ -118,26 +116,27 @@
if(write(srvfd, msg, len) < len)
sysfatal("netput(): half written?: %r");
- /* otherwise client wont read socket to confirm */
- waitbit = 1;
free(msg);
return Ok;
}
static void
-netproc(Netmsg *msg, char *in)
+netproc(Game *game, Netmsg *msg, char *in)
{
- int i, dir;
+ int i = 0, dir;
char *tmp, *xpos, *ypos;
char **tokens = (char**)emalloc(64 * sizeof(char*));
Point p;
msg->omsg = strdup(in);
- dprint("msg->omsg: %s\n", in);
+ dprint("msg->omsg: %s\n", msg->omsg);
tokens[0] = strtok(in, " ");
for(i = 1 ; tokens[i-1] != nil ; i++)
+ {
tokens[i] = strtok(nil, " ");
+ fprint(2, "token[%d] = %s\n", i, tokens[i]);
+ }
msg->ntoken = i;
msg->tokens = tokens;
@@ -167,9 +166,9 @@
else if(!strcmp(tokens[0], "INIT"))
{
- dprint("INIT XXX in INIT\n");
- state = Init;
- while(state == Init)
+ waitbit = 0;
+ game->state = Init;
+ while(game->state == Init)
{
tmp = netread();
/* lots of assuming goes here,
@@ -187,7 +186,7 @@
p.x = atoi(xpos);
p.y = atoi(ypos);
- grid[p.x][p.y] = Wall;
+ game->grid[p.x][p.y] = Wall;
break;
case 'g':
xpos = strtok(nil, " ");
@@ -198,17 +197,16 @@
p.x = atoi(xpos);
p.y = atoi(ypos);
- grid[p.x][p.y] = Glenda;
+ game->grid[p.x][p.y] = Glenda;
break;
default:
if(!strcmp("SENT", tmp))
- state = Start;
+ game->state = Start;
else
dprint("netproc(): Init: unknown command: %s\n", tmp);
}
}
- dprint("XXX INIT: state = %d\n", state);
}
else if(!strcmp(tokens[0], "SENT"))
/* sent is handled in INIT */
@@ -219,41 +217,37 @@
else if(!strcmp(tokens[0], "SYNC"))
{
- if(state == Start)
- state = Playing;
+ if(game->state == Start)
+ game->state = Playing;
if(msg->ntoken < 2)
sysfatal("netproc(): not enough toknes?");
- /* TODO: very ugly hack, get rid of this */
- networked = 0;
if(atoi(msg->tokens[1]) % 2 == 0)
{
- /* glenda's turn is done */
- if(msg->ntoken < 3)
- sysfatal("netproc(): not enough tokens to SYNC glenda's move");
- dir = strtodir(tokens[2]);
- domove(dir);
- dprint("in glenda's turn\n");
- }
- else
- {
/* trapper's turn is done */
- if(msg->ntoken < 4)
+ if(msg->ntoken != 4)
sysfatal("netproc(): not enough tokens to SYNC trapper's move");
p = parseput(tokens[2], tokens[3]);
- doput(p);
+ doput(game, p);
}
- /* TODO: very ugly hack, get rid of this */
- networked = 1;
+ else
+ {
+ /* glenda's turn is done */
+ if(msg->ntoken != 3)
+ sysfatal("netproc(): not enough tokens to SYNC glenda's move");
+ dir = strtodir(tokens[2]);
+ domove(game, dir);
+ }
}
else if(!strcmp(tokens[0], "WON"))
- state = Won;
-
+ {
+ msg->err = Won;
+ }
else if(!strcmp(tokens[0], "LOST"))
- state = Lost;
- else if(!strcmp(tokens[0], ""))
- state = Finished;
+ {
+ msg->err = Lost;
+ }
else
sysfatal("netproc(): unkown message: 0x%x %s", *tokens[0], tokens[0]);
}
@@ -278,7 +272,7 @@
}
void
-netinit(void)
+netinit(Game *game)
{
Netmsg *msg;
char *s;
@@ -285,18 +279,18 @@
msg = (Netmsg*)emalloc(sizeof(Netmsg));
- state = Connect;
- nethi(pnick, 0, pside, 0);
+ game->state = Connect;
+ nethi(game, pnick, 0, pside, 0);
for(;;)
{
s = netread();
- netproc(msg, s);
+ netproc(game, msg, s);
dprint("msg->tokens[0]: %s\n", msg->tokens[0]);
-
if(msg->tokens[0] != nil && !strcmp(msg->tokens[0], "INIT"))
break;
+
free(s);
}
free(s);
@@ -303,7 +297,7 @@
}
Netmsg*
-netmain(void)
+netmain(Game *game)
{
Netmsg *msg;
char *s;
@@ -310,7 +304,7 @@
msg = (Netmsg*)emalloc(sizeof(Netmsg));
s = netread();
- netproc(msg, s);
+ netproc(game, msg, s);
free(s);
return msg;
}
--- a/netclient.h
+++ b/netclient.h
@@ -16,5 +16,5 @@
int netmove(int dir);
int netput(int x, int y);
char* netread(void);
-void netinit(void);
-Netmsg* netmain(void);
+void netinit(Game *game);
+Netmsg* netmain(Game *game);