wm: libmarkus

ref: 0cca37a43310c04d62de099d6337d276064848c3
dir: /libmarkus.h/

View raw version
/* this libmarkus only supports static M_MAX_BOARD_ROW and M_MAX_BOARD_COL */
#ifndef __LIBMARKUS__H
#define __LIBMARKUS__H

#define M_MAX_BOARD_ROW 6
#define M_MAX_BOARD_COL 6
#define M_EMPTY_CELL ' '
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>


typedef struct {
	int free_pieces[2];
	char player;
	int direction;
	int ecode;
	char winner;
	uint64_t ad_pieces;
	uint64_t tag_pieces;
} m_game_t;

typedef struct
{
	int row;
	int col;
	// y = col, x = row
} m_point_t;

typedef struct
{
	m_point_t src;
	m_point_t dst;
} m_swap_t;

enum m_ply_type {M_PLY_TYPE_MOVE, M_PLY_TYPE_PUT, M_PLY_TYPE_SWAP};
typedef struct 
{
	enum m_ply_type ply_type;
	m_swap_t ply_data;
} m_ply_t;



/* initializes a m_game_t, you should always call this function before any 
 * other function on that m_game_t instance */
void m_init_game(m_game_t* game);

/* check if the game is over, return ' ' if it isn't, 
 * and the winner's char (game->winner) if it is, it also
 * set's game->winner. */
char m_game_state(m_game_t* game);

/* these functions are the three main operations of the game, 
 * they also check if the game is over and refuse to do anything to 
 * the game structure if it is(M_ECODE_GAMEOVER). */
int m_put(m_game_t* game, m_point_t* point); 
int m_move(m_game_t*  game, m_point_t* point);
int m_swap(m_game_t* game, m_swap_t* swap);

/* Parses "string" and passes it to m_swap/m_move/m_put 
 * "string" should be null-terminated. string's format should
 * be a single command charachter (m|p|s) followed by 
 * its arguments, 'm' and 'p' require only one argument
 * indicating the square that you wish to move/fill, and 
 * 's' requires two arguments, a source and a destination square.
 * squares are addressed as ROWCOL without any space in between,
 * for example '45' represents the 4th row, 5th column. 
 * examples:
 * "m50"   => move the piece in 5th row, 0th column one square forward.
 * "p00"   => put a free piece on the 0th row, 0th column, and decrement free_pieces[player] by 1.
 * "s2040" => swap the piece on the 2nd row, 0th column with the piece on the 4th row, 0th column*/
int m_play_notation(m_game_t* game, char* string);

/* returns a null-terminated string describing game.ecode, every library function
 * should and does set game.ecode.*/
char* m_error_str(m_game_t* game);

enum {
	M_ECODE_OUTOFRANGE = INT_MIN,
	M_ECODE_INVALIDINPUT,
	M_ECODE_DSTNOTEMPTY,
	M_ECODE_SRCNOTYOURS,
	M_ECODE_NOTFIRSTROWS,
	M_ECODE_NOTADJECENT,
	M_ECODE_SRCORDSTEMPTY,
	M_ECODE_SRCDSTSAMEPIECE,
	M_ECODE_SRCDSTSAME,
	M_ECODE_GAMEOVER,
	M_ECODE_SUCCESS = 1
};

int m_is_move_legal(m_game_t* game, m_point_t* point);
int m_is_swap_legal(m_game_t* game, m_swap_t* swap);
int m_is_put_legal(m_game_t* game, m_point_t* point);
int m_is_ply_legal(m_game_t* game, m_ply_t* p);
//setters and getters
int m_set_square(m_game_t*, int row, int col, char);
char m_get_square(m_game_t*, int row, int col);

char* m_get_board(m_game_t*); // returns a heap-allocated string representing the board.

int m_get_free_pieces(m_game_t*, char player);
int m_get_turn(m_game_t*);
int m_game_is_over(m_game_t*);
void m_ply_set_move(m_ply_t* p, int row, int col);
void m_ply_set_put(m_ply_t* p, int row, int col);
void m_ply_set_swap(m_ply_t*, int row1, int col1, int row2, int col2);

m_swap_t m_ply_get_swap(m_ply_t* p);
m_point_t m_ply_get_move(m_ply_t* p);
m_point_t m_ply_get_put(m_ply_t* p);

bool m_tag_wins(m_game_t* game); 
bool m_ad_wins(m_game_t* game); 
enum m_ply_type m_ply_get_type(m_ply_t* p);
int m_undo_move(m_game_t*, m_point_t*);
int m_undo_put(m_game_t*, m_point_t*);
int m_undo_swap(m_game_t*, m_swap_t*);
int m_do_ply(m_game_t* game, m_ply_t* ply);
int m_undo_ply(m_game_t* game, m_ply_t* ply); 
#endif