ref: 895af3a6c0ece7ed089ee2a5356cb1933a30cca3
dir: /game.c/
#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)
{
}