wm: glendy

ref: aa0761be97fc5a0ba0fb80ca364c24d9dbd56c4d
dir: /cli.c/

View raw version
/*
 * cli glendy, based on mitrchoviski's gui for plan 9
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#include "unix.h"
#include "engine.h"

int debug = 0;
char *gface[2] = {"☹", "☺"}; /* glenda's face(es) */
Game game;

void
drawlevel(Game *g)
{
	int x, y;
	
	/* prints first row, this assumes SzX = SzY, is there a better way? */
	print("T%2d|", g->turn);
	for(int i = 0 ; i < SzX ; i++)
		print("%2d |", i);

	print("\n");

	for(x = 0; x < SzX; x++)
	{
		for(int i = 0 ; i < SzY+1 ; i++)
			print("----");
		print(x % 2 ? "\\" : "/");
		print("\n");

		/* show column number and have a zig-zag effect */
		print("%2d%s |", x, x % 2 ? "  " : "");
		// print("%2d |", x);

		for(y = 0; y < SzY; y++)
		{
			/* it's [y][x], not [x][y] */
			switch(g->grid[y][x])
			{
				case PIECE_WALL: 
					print(" * |");
					break;
				case PIECE_GLENDA:
					/* fancy effect for glenda's face */
					print(" %s |", g->turn % 2 ? gface[0] : gface[1]);
					break;
				default:
					print("   |");
					break;
			}
		}
		print("\n");
	}
	if(g->state == STATE_WON){
		print("trapper won\n");
		exits(nil);
	}
	else if(g->state == STATE_LOST){
		print("glenda won\n");
		exits(nil);
	}
}

/* p x y */
void
proc_put(Game *g, char *s)
{
	unsigned int x, y, r;

	/* replace these by better alternatives */
	sscanf(s, "%u %n", &x, &r);
	sscanf(s+r, "%u", &y);
	
	if(x > SzX || y > SzY){
		fprint(2, "proc_put(): invalid input, x = %d, y = %d\n", x, y);
		return;
	}
	r = doput(g, Pt(x, y));
	if(r == PIECE_WALL)
		fprint(2, "There is already a wall in x = %d, y = %d\n", x, y);
	else if(r == PIECE_GLENDA)
		fprint(2, "You can't put a wall on glenda!\n");
}

/* m x y */
void
proc_move(Game *g, char *s)
{
	int d;
	
	if(strcmp(s, "NE") == 0)
		d = NE;
	else if(strcmp(s, "E") == 0)
		d =  E;
	else if(strcmp(s, "SE") == 0)
		d = SE;
	else if(strcmp(s, "W") == 0)
		d =  W;
	else if(strcmp(s, "SW") == 0)
		d = SW;
	else if(strcmp(s, "NW") == 0)
		d = NW;
	else
	{
		fprint(2, "proc_move(): huh?\n");
		return;
	}
	
	/* should check if there is a wall or something this way */
	if(domove(g, d) == PIECE_WALL)
	{
		fprint(2, "There is a wall there!\n");
		return;
	}
}

/*
 * handle input, which is in the form of
 * p1> p xx yy
 * which puts a wall in xx yy
 * p2> m {NE, E, SE, W, SW, NW}
 * which moves the bunny
 * > r
 * restarts the game
 * > u
 * undos last move
 * > q
 * quits the game
 */
void
proc(Game *g, char *s)
{
	char *t;
	int oturn;

	/* skip \n, so we don't need to process it later */
	t = strchr(s, '\n');
	*t = '\0';

	oturn = g->turn;
	/* s+2 skips command and first space after it */
	switch(*s)
	{
		case 'p':
			if(g->turn % 2 == 0)
				proc_put(g, s+2);
			else if(g->turn % 2 == 1)
				fprint(2, "glendy can't put!\n");
			break;
		case 'm':
			if(g->turn % 2 == 0)
				fprint(2, "trapper can't move!\n");
			else if(g->turn % 2 == 1)
				proc_move(g, s+2);
			break;
		case 'u':
			undo(g);
			break;
		case 'r':
			/* maybe we need to put a confirm message here */
			restart(g);
			break;
		case 'q':
			exits(nil);
			break;
		case '\0':
			break;
		default:
			fprint(2, "unknown command\n");
	}
	/* only print the map if turn have changed */
	if(g->turn != oturn)
		drawlevel(g);
}

int
input(Game *g)
{	char s[32], *r;

	print("%s> ", g->turn % 2 ? "glendy" : "trapper");
	fflush(stdout); /* plan 9 */
	r = fgets(s, 32, stdin);
	if(r == nil){
		fprint(2, "input(): error\n");
		return Err;
	} else {
		proc(g, s);
		return Ok;
	}
}

int 
main(int argc, char **argv)
{
	/*
	 * todo: handle argv properly
	 */
	game.ptype[0] = Human;
	game.ptype[1] = Human;
	/* OpenBSD ignores this */
	srand(time(nil));
	 
	initlevel(&game);
	drawlevel(&game);
	while(input(&game) != Err)
		;

	return 0;
}