mirror of https://github.com/dirtbags/moth.git
199 lines
3.7 KiB
C
199 lines
3.7 KiB
C
|
#include <stdlib.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
#include "cgi.h"
|
|||
|
|
|||
|
const char *b64_aleph = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@";
|
|||
|
|
|||
|
typedef int board_t[3][3];
|
|||
|
|
|||
|
void
|
|||
|
b64_of_board(char *out, board_t board)
|
|||
|
{
|
|||
|
int y, x;
|
|||
|
|
|||
|
for (y = 0; y < 3; y += 1) {
|
|||
|
int acc = 0;
|
|||
|
|
|||
|
for (x = 0; x < 3; x += 1) {
|
|||
|
acc <<= 2;
|
|||
|
acc += board[y][x];
|
|||
|
}
|
|||
|
out[y] = b64_aleph[acc];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
board_of_b64(board_t out, char *b64)
|
|||
|
{
|
|||
|
int y, x;
|
|||
|
|
|||
|
for (y = 0; y < 3; y += 1) {
|
|||
|
char *p = strchr(b64_aleph, b64[y]);
|
|||
|
int acc = 0;
|
|||
|
|
|||
|
if (p) {
|
|||
|
acc = p - b64_aleph;
|
|||
|
}
|
|||
|
|
|||
|
for (x = 2; x >= 0; x -= 1) {
|
|||
|
out[y][x] = acc & 3;
|
|||
|
acc >>= 2;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_board(board_t board)
|
|||
|
{
|
|||
|
int y, x;
|
|||
|
|
|||
|
for (y = 0; y < 3; y += 1) {
|
|||
|
for (x = 0; x < 3; x += 1) {
|
|||
|
printf("%d", board[y][x]);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
winner(board_t board)
|
|||
|
{
|
|||
|
int i, j, k;
|
|||
|
|
|||
|
for (i = 0; i < 3; i += 1) {
|
|||
|
for (k = 0; k < 3; k += 1) {
|
|||
|
int winner = -1;
|
|||
|
|
|||
|
for (j = 0; j < 3; j += 1) {
|
|||
|
int b;
|
|||
|
|
|||
|
switch (k) {
|
|||
|
case 0:
|
|||
|
b = board[i][j];
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
b = board[j][i];
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
/* This will happen 3× as often as it needs to. Who cares. */
|
|||
|
b = board[j][j];
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (winner == -1) {
|
|||
|
winner = b;
|
|||
|
} else if (winner != b) {
|
|||
|
winner = -1;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (winner > 0) {
|
|||
|
return winner;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
claim(board_t board, int x, int y, int whom)
|
|||
|
{
|
|||
|
int prev = board[x][y];
|
|||
|
int i;
|
|||
|
|
|||
|
if (prev == whom) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < 9; i += 1) {
|
|||
|
if (! board[i/3][i%3]) {
|
|||
|
board[i/3][i%3] = prev;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
board[x][y] = whom;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
make_move(board_t board)
|
|||
|
{
|
|||
|
switch (winner(board)) {
|
|||
|
case 1:
|
|||
|
printf("A WINNER IS YOU\n");
|
|||
|
exit(0);
|
|||
|
case 2:
|
|||
|
/* I win; we can keep playing though, because I (neale)
|
|||
|
don't want to write any more code to handle this. */
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
printf("A WINNER IS WHO?\n");
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
/* Reserve our final space */
|
|||
|
claim(board, 2, 2, 0);
|
|||
|
|
|||
|
/* First move */
|
|||
|
if (board[1][1] != 2) {
|
|||
|
claim(board, 1, 1, 2);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* Second move */
|
|||
|
if (board[0][0] != 2) {
|
|||
|
|
|||
|
/* Prevent them from winning legally */
|
|||
|
if (board[0][2]) {
|
|||
|
claim(board, 1, 2, 0);
|
|||
|
}
|
|||
|
if (board[2][0]) {
|
|||
|
claim(board, 2, 1, 0);
|
|||
|
}
|
|||
|
claim(board, 0, 0, 2);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* Third move */
|
|||
|
claim(board, 2, 2, 2);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
main(int argc, char *argv[])
|
|||
|
{
|
|||
|
char b64[4] = {0};
|
|||
|
board_t board = {0};
|
|||
|
|
|||
|
if (-1 == cgi_init(argv)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
while (1) {
|
|||
|
size_t len;
|
|||
|
char key[20];
|
|||
|
|
|||
|
len = cgi_item(key, sizeof key);
|
|||
|
if (0 == len) break;
|
|||
|
switch (key[0]) {
|
|||
|
case 'b':
|
|||
|
cgi_item(b64, sizeof b64);
|
|||
|
break;
|
|||
|
default:
|
|||
|
cgi_item(key, 0);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("Content-type: text/plain\r\n\r\n");
|
|||
|
board_of_b64(board, b64);
|
|||
|
make_move(board);
|
|||
|
b64_of_board(b64, board);
|
|||
|
fwrite(b64, 1, 3, stdout);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|