moth/packages/gs/generalstatics.com/ttt.cgi.c

199 lines
3.7 KiB
C
Raw Normal View History

2012-06-27 13:46:32 -06:00
#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;
}