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

199 lines
3.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}