wm: glendy

Download patch

ref: 1986f3905eca9114442405d2b3180eea9bc709bc
parent: 440456a6f0c3e18c6a4ec4675846bd5c0a5157cc
author: mkf <mkf@cloud9p.org>
date: Mon Oct 21 03:15:57 EDT 2024

refactor engine: localize variables

--- a/engine.c
+++ b/engine.c
@@ -4,25 +4,19 @@
 #include "engine.h"
 #include "netclient.h"
 
-int difficulty = DHard;
-int state;
-int turn = 0;
-int ptype[2] = {Human, Computer};
-
-int grid[SzX][SzY];
-int pgrid[SzX][SzY]; /* for undo */
-int ogrid[SzX][SzY]; /* so we can restart levels */
-
+/*
+ * Sets up a new level
+ */
 void
-initlevel(void)
+initlevel(Game *game)
 {
 	int i, cnt, x, y;
 
 	for(x = 0; x < SzX; x++)
 		for(y = 0; y < SzY; y++)
-			ogrid[x][y] = Prev;
+			game.ogrid[x][y] = Prev;
 
-	switch(difficulty)
+	switch(game.difficulty)
 	{
 		case DEasy:
 			cnt = 10 + nrand(5);
@@ -38,7 +32,7 @@
 			cnt = 0;
 			break;
 	}
-	ogrid[SzX/2][SzY/2] = Glenda;
+	game.ogrid[SzX/2][SzY/2] = Glenda;
 
 setmap:
 	for(i = 0 ; i < cnt ; i++)
@@ -48,18 +42,21 @@
 		{
 			x = nrand(SzX);
 			y = nrand(SzY);
-		}while(ogrid[x][y] == Glenda || ogrid[x][y] == Wall);
-		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() == Won && findmin(Pt(SzX/2, SzY/2)) > 100)
+	if(checkstate(game) == Won && findmin(game, Pt(SzX/2, SzY/2)) > 100)
 		goto setmap;
 
-	memcpy(grid, ogrid, sizeof grid);
-	state = Start;
-	turn = 0;
+	memcpy(game.grid, game.ogrid, sizeof(game.grid));
+	game.state = Start;
+	game.turn = 0;
 }
 
+/*
+ * Returns position
+ */
 Point
 movedir(int dir, Point p)
 {
@@ -82,21 +79,16 @@
 			return Pt(x+(y%2?0:-1), y-1);
 		default:
 			sysfatal("andrey messed up big time: %d", dir);
-			/* should we keep that line around? it might be more useful than sysfatal */
-			// return Pt(-1, -1); 
 	}
 }
 
-/* reverse of movedir, tells the direction for a dst from src */
+/*
+ * Reverse of movedir, tells the direction for a dst from src
+ */
 int
 pointdir(Point src, Point dst)
 {
 	Point p;
-	/*
-	if(src.x < 0 || src.x > SzX || src.y < 0 || src.y > SzY)
-	||(dst.x < 0 || dst.x > SzX || dst.y < 0 || dst.y > SzY)
-		return Err;
-	*/
 	
 	/* hacky */
 	for(int i = NE ; i <= NW ; i++)
@@ -109,154 +101,101 @@
 }
 
 /*
-Point
-movedir(int dir, Point p)
-{
-	switch(dir)
-	{
-		case NE:
-			if(p.y % 2)
-				return Pt(p.x+1, p.y-1);
-			else	
-				return Pt(p.x, p.y-1);
-		case E:
-			return Pt(p.x+1, p.y);
-		case SE:
-			if(p.y % 2)
-				return Pt(p.x+1, p.y+1);
-			else
-				return Pt(p.x, p.y+1);
-		case SW:
-			if(p.y % 2)
-				return Pt(p.x, p.y+1);
-			else
-				return Pt(p.x-1, p.y+1);
-		case W:
-			return Pt(p.x-1, p.y);
-		case NW:
-			if(p.y % 2)
-				return Pt(p.x, p.y-1);
-			else
-				return Pt(p.x-1, p.y-1);
-		default:
-			return Pt(-1, -1);
-	}
-}
-*/
-
+ * Moves glenda from direction
+ */
 int
-domove(int dir)
+domove(Game game, int dir)
 {
 	Point src, dst;
 		
-	src = findglenda();
+	src = findglenda(game);
 	dst = movedir(dir, src);
 
-	if(grid[dst.x][dst.y] == Wall)
+	if(game.grid[dst.x][dst.y] == Wall)
 		return Wall;
 
-	if(networked)
-		return netmove(dir);
+	if(game.networked)
+		return netmove(game.dir);
 	
-	grid[dst.x][dst.y] = Glenda;
-	grid[src.x][src.y] = Prev;
+	game.grid[dst.x][dst.y] = Glenda;
+	game.grid[src.x][src.y] = Prev;
 
 	turn++;
-	/* server should tell us */
-	if(ptype[1] == Human && !networked)
-		checkstate();
+	
+	/* we shouldn't guess, server should tell us */
+	if(game.ptype[1] == Human && !game.networked)
+		checkstate(game);
 	return Ok;
 }
 
 int
-doput(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(grid[p.x][p.y] == Wall)
+	if(game.grid[p.x][p.y] == Wall)
 		return Wall;
 
-	if(grid[p.x][p.y] == Glenda)
+	if(game.grid[p.x][p.y] == Glenda)
 		return Glenda;
 
-	if(networked)
-		return netput(p.x, p.y);
+	if(game.networked)
+		return netput(game, p.x, p.y);
 	
 	/* take a copy for undo */
-	memcpy(pgrid, grid, sizeof grid);
+	memcpy(game.pgrid, game.grid, sizeof(game.grid));
 	grid[p.x][p.y] = Wall;
 
 
 	/* assumes defenders start game first */
-	if(state == Start)
-		state = Playing;
+	if(game.state == Start)
+		game.state = Playing;
 
 	turn++;
 	/* reset the board scores */
 	for(int x = 0; x < SzX; x++)
 		for(int y = 0; y < SzY; y++)
-			if(grid[x][y] != Wall && grid[x][y] != Glenda)
-				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(ptype[1] == Computer)
-		nextglenda();
-	else if(ptype[1] == Human && !networked)
-		checkstate();
+	if(game.ptype[1] == Computer)
+		nextglenda(game);
+	else if(game.ptype[1] == Human && !networked)
+		checkstate(game);
 
 	return Ok;
 }
 
+/*
+ * Returns glenda's position
+ */
 Point
-findglenda(void)
+findglenda(Game game)
 {
 	for(int x = 0; x < SzX; x++)
 		for(int y = 0; y < SzY; y++)
-			if(grid[x][y] == 1000)
+			if(game.grid[x][y] == 1000)
 				return Pt(x, y);
 	
 	return Pt(-1, -1);
 }
 
-int
-checknext(int dir, Point p)
-{
-	int x = p.x;
-	int y = p.y;
-	
-	switch(dir)
-	{
-		case NE: 
-			return grid[x+(y%2?1:0)][y-1];
-		case E:
-			return grid[x+1][y];
-		case SE:
-			return grid[x+(y%2?1:0)][y+1];
-		case SW:
-			return grid[x+(y%2?0:-1)][y+1];
-		case W:
-			return grid[x-1][y];
-		case NW:
-			return grid[x+(y%2?0:-1)][y-1];
-		default:
-			sysfatal("andrey messed up big time");
-	}
-}
-
-/* the following two routines constitute the "game AI"
-* they score the field based on the number of moves
-* required to reach the edge from a particular point
-* scores > 100 are "dead spots" (this assumes the field 
-* is not larger than ~100*2
-* 
-* routines need to run at least twice to ensure a field is properly
-* scored: there are errors that creep up due to the nature of 
-* traversing the board
-*/
+/*
+ * the following two routines constitute the "game AI"
+ * they score the field based on the number of moves
+ * required to reach the edge from a particular point
+ * scores > 100 are "dead spots" (this assumes the field 
+ * is not larger than ~100*2
+ * 
+ * routines need to run at least twice to ensure a field is properly
+ * scored: there are errors that creep up due to the nature of 
+ * traversing the board
+ */
 int 
-score1(Point p)
+score1(Game game, Point p)
 {
 	int min = 999;
 
@@ -263,8 +202,8 @@
 	if(p.x == 0 || p.x == SzX-1 || p.y == 0 || p.y == SzY-1)
 		return 1; 		/* we can always escape from the edges */
 
-	if(findmin(p) < min)
-		min = findmin(p);
+	if(findmin(game, p) < min)
+		min = findmin(game, p);
 
 	if(min >= 998)
 		return 998;
@@ -271,16 +210,24 @@
 	return 1+min;
 }
 
+/*
+ * calculates scores of whole graph
+ * O(n³), but why?
+ */
 void
 calc(void)
 {
-	for(int i = 0; i < SzX; i++) /* assumes SzX = SzY */
+	/* 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(grid[x][y] != Wall && grid[x][y] != Glenda)
-					grid[x][y] = score1(Pt(x, y));
+				if(game.grid[x][y] != Wall && game.grid[x][y] != Glenda)
+					game.grid[x][y] = score1(Pt(x, y));
 }
 
+/*
+ * finds the node with least score around the p
+ */
 int
 findmin(Point p)
 {
@@ -288,28 +235,33 @@
 
 	for(int dir = NE; dir <= NW; dir++)
 	{
-		next = checknext(dir, p);
+		next = checknext(game, dir, p);
 		if(next < min)
 			min = next;
 	}
 	return min;
 }
+
+/*
+ * Makes a move for glenda
+ * only use in single player
+ */
 void
-nextglenda(void)
+nextglenda(Game game)
 {
 	int min = 999, next, dir, nextdir = 0, count = 0;
-	Point p = findglenda();
+	Point p = findglenda(game);
 
 	if(networked)
 		return;
 
-	calc();
-	calc();
-	calc();
+	calc(game);
+	calc(game);
+	calc(game);
 
 	for(dir = NE; dir <= NW; dir++)
 	{
-		next = checknext(dir, p);
+		next = checknext(game, dir, p);
 		if(next < min)
 		{
 			min = next;
@@ -324,38 +276,47 @@
 	else
 		domove(nextdir);
 
-	p = findglenda();
+	p = findglenda(game);
 	if(p.x == 0 || p.x == SzX-1 || p.y == 0 || p.y == SzY-1)
-		state = Lost;
+		game.state = Lost;
 }
 
+/*
+ * See if game is over
+ */
 int
-checkstate(void)
+checkstate(Game game)
 {
-	Point p = findglenda();
+	Point p = findglenda(game);
 
-	calc();
-	calc();
-	calc();
+	calc(game);
+	calc(game);
+	calc(game);
 
-	if(findmin(p) > 100)
-		state = Won;
+	if(findmin(game, p) > 100)
+		game.state = Won;
 	if(p.x == 0 || p.x == SzX-1 || p.y == 0 || p.y == SzY-1)
-		state = Lost;
+		game.state = Lost;
 
-	return state;
+	return game.state;
 }
 
+/*
+ * Resets the game position
+ */
 void
-restart(void)
+restart(Game game)
 {
-	turn = 0;
-	memcpy(grid, ogrid, sizeof grid);
-	state = Start;
+	game.turn = 0;
+	memcpy(game.grid, game.ogrid, sizeof(game.grid));
+	game.state = Start;
 }
 
+/*
+ * Undos last move
+ */
 void
-undo(void)
+undo(Game game)
 {
 	int g[SzX][SzY];
 
@@ -366,7 +327,7 @@
 	turn -= 2;
 
 	/* swap grids */
-	memcpy(g, grid, sizeof grid);
-	memcpy(grid, pgrid, sizeof grid);
-	memcpy(pgrid, g, sizeof grid);
+	memcpy(g, game.grid, sizeof g);
+	memcpy(game.grid, game.pgrid, sizeof g);
+	memcpy(game.pgrid, g, sizeof g);
 }
--- a/engine.h
+++ b/engine.h
@@ -46,24 +46,28 @@
 	Ok,
 };
 
-/* engine.c */
-extern int difficulty;
-extern int state;
-extern int turn;
-extern int ptype[2]; /* Human or Computer? */
 
-extern int grid[SzX][SzY];
-extern int pgrid[SzX][SzY]; /* for undo */
-extern int ogrid[SzX][SzY]; /* so we can restart levels */
+typedef struct Game
+{
+	/* engine.c */
+	int difficulty;
+	int state;
+	int turn;
+	int ptype[2]; /* Human or Computer? */
+	
+	int grid[SzX][SzY];
+	int pgrid[SzX][SzY]; /* for undo */
+	int ogrid[SzX][SzY]; /* so we can restart levels */
+	
+	/* net.c */
+	/* 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 */
-extern int debug;
-
-/* net.c */
-/* we maybe be able to merge all this into one bit-array */
-extern int waitbit; /* 0 is go, 1 is wait */
-extern int networked; /* 0 is local, 1 is networked */
-extern int pside; /* Trapper, Glenda */
+int debug;
 
 void initlevel(void);
 Point movedir(int dir, Point p);