shithub: gofs

ref: 895af3a6c0ece7ed089ee2a5356cb1933a30cca3
dir: /game.c/

View raw version
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "dat.h"
#include "fns.h"

static void validateboard(Gogame *game);

static int
getarrpos(Gogame *game, Vec pos)
{
	if (pos.x < 0 || pos.x >= game->size.x)
		goto Err;
	if (pos.y < 0 || pos.y >= game->size.y)
		goto Err;
	return pos.y * game->size.x + pos.x;
Err:
	werrstr("invalid position (%d, %d)", pos.x, pos.y);
	return -1;
}

Gogame*
newgame(Vec size)
{
	Gogame *game;
	
	game = mallocz(sizeof(Gogame), 1);
	assert(game);
	
	game->board = mallocz(sizeof(Gostone) * size.x * size.y, 1);
	assert(game->board);
	game->size = size;
	game->state = GBLACK;
	return game;
}

void
freegame(Gogame *game)
{
	assert(game);
	if (game->board)
		free(game->board);
	free(game);
}

Gostone
getcurrent(Gogame *game, Vec pos)
{
	int apos;
	assert(game && game->board);
	
	apos = getarrpos(game, pos);
	if (apos < 0)
		return -1;
	return game->board[apos];
}

static int
isfree(Gogame *game, Vec pos, Gostone stone, Gostone opposite)
{
	Gostone s;
	int nfreedoms = 4;
	Vec v;
	
	for (int i = 0; i < 4; i++) {
		switch (i) {
		case 0:
			v = pos + V(1, 0);
			break;
		case 1:
			v = pos + V(0, 1);
			break;
		case 2:
			v = pos - V(1, 0);
			break;
		case 3:
			v = pos - V(0, 1);
			break;
		}
		s = getcurrent(game, v);
		if (s == opposite) {
			nfreedoms--;
			continue;
		}
		if (!isfree(game, v, stone, opposite))
			return 0;
	}
	
	return !!nfreedoms;
}

static int
validmove(Gogame *game, Vec pos, Gostone stone)
{
	Gostone opposite = EMPTY;
	
	if (stone == WHITE)
		opposite = BLACK;
	if (stone == BLACK)
		opposite = WHITE;
	
	if (opposite == EMPTY) {
		werrstr("no valid stone");
		return 0;
	}
	
	switch (getcurrent(game, pos)) {
		case BLACK:
		case WHITE:
			werrstr("there's already a stone");
			return 0;
		case WASBLACK:
			if (stone == WHITE)
				break;
			werrstr("white on ex-white");
			return 0;
		case WASWHITE:
			if (stone == BLACK)
				break;
			werrstr("black on ex-black");
			return 0;
		default:
			return 1;
	}
	
	return isfree(game, pos, stone, opposite);
}

int
setstone(Gogame *game, Vec pos, Gostone stone)
{
	int apos;
	assert(game && game->board);
	
	if (game->state != stone) {
		werrstr("Can't set: It's not your turn");
		return 0;
	}
	
	apos = getarrpos(game, pos);
	if (apos < 0)
		return 0;
	
	if (!validmove(game, pos, stone))
		return 0;
	
	game->board[apos] = stone;
	validateboard(game);
	
	switch (stone) {
	case WHITE:
		game->state = GBLACK;
		break;
	case BLACK:
		game->state = GWHITE;
		break;
	}
	
	return 1;
}

int
passround(Gogame *game, Gostone stone)
{
	assert(game && game->board);
	
	print("state: %d, stone: %d\n", game->state, stone);
	
	if (game->state != stone) {
		werrstr("Can't pass: It's not your turn");
		return 0;
	}
	
	switch (stone) {
	case WHITE:
		game->state = GBLACK;
		break;
	case BLACK:
		game->state = GWHITE;
		break;
	default:
		werrstr("bad move");
		return 0;
	}
	return 1;
}

static void
validateboard(Gogame *game)
{
}