ref: cea57785283e17b1a05909860d12e9a7dfe99600
dir: /m.c/
/*
note that program isn't well tested on boardx != 6, boardy != 6
*/
#include <stdio.h>
#define boardx 6
#define boardy 6
#define empty ' '
char board[boardx * boardy];
int pieces[2] = { (boardx / 2 - 1)* boardy, (boardx / 2 - 1) * boardy };
char piece[2] = { '@', '#' };
int player = 0;
int direction = -1;
typedef struct
{
int x;
int y;
} point_t;
typedef struct
{
point_t src;
point_t dst;
} swap_t;
int pindex(int, int);
void setupboard(void);
void showrules(void);
void showboard(void);
void showhelp(void);
char check(void);
int check_put(point_t);
int check_move(point_t);
int check_swap(swap_t);
int put(point_t);
int move(point_t);
int swap(swap_t);
typedef struct
{
char act;
point_t pos1;
point_t pos2;
} cmd_t;
/* why y and x, and not x and y?
C does it as YX, doing it otherwise would make code
way too complex */
int pindex(int y, int x)
{
if(x < 0 || x > boardx || y < 0 || y > boardy)
{
fprintf(stderr, "pindex(%d, %d) out of range\n", x, y);
return -1;
}
return (x * boardy) + y;
}
void setupboard(void)
{
for(int x = 0; x < boardx; x++)
{
for(int y = 0; y < boardy; y++)
{
if(x == 0)
board[pindex(x, y)] = piece[1];
else if(x == boardx - 1)
board[pindex(x, y)] = piece[0];
else
board[pindex(x, y)] = empty;
}
}
}
void showboard(void)
{
printf("\n");
printf("free %c: %d, free %c: %d\n", piece[0], pieces[0], piece[1], pieces[1]);
for(int i = -1; i < boardx; i++)
{
if(i != -1) // makes top most sqaure ugly
printf(" %d |", i);
else
printf(" * |");
for(int j = 0; j < boardy; j++)
{
if(i == -1)
printf(" %d |", j);
else
printf(" %c |", board[pindex(i, j)]);
}
printf("\n");
}
}
void showrules(void)
{
printf("The goal is make a 4 in a row, where\n"
"at least half (2) of them are other side.\n"
"commands:\n"
"h: show this help, b: show board, #: comment, NOP \n"
"pXY: put a piece on XY, you may only do it for your first two rows.\n"
"mXY: move the piece on XY one square forward.\n"
"sXYXY: swap first two pieces, only if they are adjecnet.\n");
}
void chplayer(void)
{
player = !player;
direction *= -1;
}
cmd_t getcmd(void)
{
char string[6];
point_t pos1, pos2;
cmd_t cmd;
printf("\n%c turn> ", piece[player]);
scanf("%s", string);
switch(string[0])
{
case 'm':
case 'p':
sscanf(&string[1], "%1d%1d", &pos1.x, &pos1.y);
cmd.pos1 = pos1;
break;
case 's':
sscanf(&string[1],"%1d%1d%1d%1d", &pos1.x, &pos1.y, &pos2.x, &pos2.y);
cmd.pos1 = pos1;
cmd.pos2 = pos2;
break;
}
cmd.act = string[0];
return cmd;
}
int proccmd(cmd_t cmd)
{
switch(cmd.act)
{
case 'm':
{
if(pindex(cmd.pos1.x, cmd.pos1.y) == -1)
return -1;
return move(cmd.pos1);
}
case 's':
{
if(pindex(cmd.pos1.x, cmd.pos1.y) == -1
|| pindex(cmd.pos2.x, cmd.pos2.y) == -1)
return -1;
swap_t s;
s.src = cmd.pos1;
s.dst = cmd.pos2;
return swap(s);
}
case 'p':
{
if(pindex(cmd.pos1.x, cmd.pos1.y) == -1)
return -1;
return put(cmd.pos1);
}
case 'b':
{
showboard();
break;
}
case 'h':
{
showrules();
break;
}
case '#':
{
break;
}
default:
{
fprintf(stderr, "unkown command.\n");
break;
}
}
return -1;
}
char check(void)
{
for(int x = 0 ; x < boardx ; x++)
{
for(int y = 0 ; y < boardy - 3 ; y++)
{
if(board[pindex(x, y)] != empty)
{
// horzictal
if((board[pindex(x, y)] == piece[0] && x < (boardx / 2 + 1))
|| (board[pindex(x, y)] == piece[1] && x >= (boardx / 2)))
if(board[pindex(x, y)] == board[pindex(x, y+1)]
&& board[pindex(x, y)] == board[pindex(x, y+2)]
&& board[pindex(x, y)] == board[pindex(x, y+3)])
{
printf("deb\n");
return board[pindex(x, y)];
}
// vertical
if((player == 0 && x < ( boardx / 2 + 1 ))
|| (player == 1 && x >= ( boardx / 2 + 1)))
if(board[pindex(x, y)] == board[pindex(x - direction, y)]
&& board[pindex(x, y)] == board[pindex(x - direction * 2, y)]
&& board[pindex(x, y)] == board[pindex(x - direction * 3, y)])
return board[pindex(x, y)];
// diagonal rtl
if(y == 1 || y == 2)
if(board[pindex(x, y)] == board[pindex(x+1, y+1)]
&& board[pindex(x, y)] == board[pindex(x+2, y+2)]
&& board[pindex(x, y)] == board[pindex(x+3, y+3)])
return board[pindex(x, y)];
// diagonal ltr
if(y == 3 || y == 4)
if(board[pindex(x, y)] == board[pindex(x+1, y-1)]
&& board[pindex(x, y)] == board[pindex(x+2, y-2)]
&& board[pindex(x, y)] == board[pindex(x+3, y-3)])
return board[pindex(x, y)];
}
}
}
return empty;
}
int check_swap(swap_t swap)
{
if((pindex(swap.src.x, swap.src.y) < 0)
|| (pindex(swap.dst.x, swap.dst.y) < 0))
{
fprintf(stderr, "invalid input\n");
return -1;
}
if(swap.src.x - swap.dst.x > 1
|| swap.src.x - swap.dst.x < -1
|| swap.src.y - swap.dst.y > 1
|| swap.src.y - swap.dst.y < -1)
{
fprintf(stderr, "src and dst aren't adjecent\n");
return -2;
}
if(board[pindex(swap.src.x, swap.src.y)] == empty
|| board[pindex(swap.dst.x, swap.dst.y)] == empty)
{
fprintf(stderr, "src or dst is empty\n");
return -3;
}
if(board[pindex(swap.src.x, swap.src.y)]
== board[pindex(swap.dst.x, swap.dst.y)])
{
fprintf(stderr, "src and dst have the same piece\n");
return -4;
}
if(pindex(swap.src.x, swap.src.y)
== pindex(swap.dst.x, swap.dst.y))
{
fprintf(stderr, "src and dst are the same square\n");
return -5;
}
return 0;
}
int swap(swap_t swap)
{
if(check_swap(swap) < 0)
return -1;
char temp = board[pindex(swap.src.x, swap.src.y)];
board[pindex(swap.src.x, swap.src.y)] = board[pindex(swap.dst.x, swap.dst.y)];
board[pindex(swap.dst.x, swap.dst.y)] = temp;
return 0;
}
int check_move(point_t point) // todo: add checks for last row
{
if(pindex(point.x, point.y) == -1)
{
fprintf(stderr, "invalid input\n");
return -1;
}
if(board[pindex(point.x, point.y)] != piece[player])
{
fprintf(stderr, "src is not your piece\n");
return -2;
}
if(board[pindex(point.x + direction, point.y )] != empty)
{
fprintf(stderr, "dst is not empty\n");
return -3;
}
return 0;
}
int move(point_t point)
{
if(check_move(point) < 0)
return -1;
board[pindex(point.x + direction, point.y)] = piece[player];
board[pindex(point.x, point.y)] = empty;
return 0;
}
int check_put(point_t point)
{
if(pindex(point.x, point.y) == -1)
{
fprintf(stderr, "invalid input\n");
return -1;
}
if(board[pindex(point.x, point.y)] != empty)
{
fprintf(stderr, "dst is not empty\n");
return -2;
}
if((player == 0 && point.x < 4)
|| (player == 1 && point.x > 1))
{
fprintf(stderr, "it's not on your first two rows\n");
return -3;
}
return 0;
}
int put(point_t point)
{
if(check_put(point) < 0)
return -1;
board[pindex(point.x, point.y)] = piece[player];
pieces[player]--;
return 0;
}
int main(void)
{
showrules();
setupboard();
showboard();
while(check() == empty)
{
if(proccmd(getcmd()) == 0)
{
chplayer();
showboard();
}
}
return 0;
}