wm: m

ref: cea57785283e17b1a05909860d12e9a7dfe99600
dir: /m.c/

View raw version
/*
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;
}