WIP refactor
This commit is contained in:
221
pieces.c
Normal file
221
pieces.c
Normal file
@@ -0,0 +1,221 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static bool bishop_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
static bool cardinal_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
static bool diagonal_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
static bool king_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
static bool knight_move_ok(index_t from, index_t to);
|
||||
static bool pawn_move_ok(const tile_t board[BOARD_SIZE],
|
||||
index_t from,
|
||||
index_t to,
|
||||
int player);
|
||||
static bool queen_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
static bool rook_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to);
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid pawn move
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece starts at
|
||||
* \param to Index of board piece wants to move to
|
||||
* \param player Player to move
|
||||
*/
|
||||
bool pawn_move_ok(const tile_t board[BOARD_SIZE],
|
||||
index_t from,
|
||||
index_t to,
|
||||
int player)
|
||||
{
|
||||
const index_t diff = (to - from) * -player;
|
||||
|
||||
switch (diff) {
|
||||
default:
|
||||
return false;
|
||||
|
||||
case ROW: /* single move */
|
||||
return tile_empty(board[to]);
|
||||
|
||||
case ROW - 1:
|
||||
case ROW + 1: /* diagonal attack */
|
||||
return opposite_color(board[to], board[from]);
|
||||
|
||||
case 2 * ROW: /* double move */
|
||||
return tile_empty(board[to]) && tile_empty(board[from - ROW * player])
|
||||
&& (row(from) == 1 || row(from) == 6);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `to` is on a diagonal line of `from`, false otherwise
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool diagonal_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
const index_t col_diff = column(to) - column(from);
|
||||
const index_t row_diff = row(to) - row(from);
|
||||
|
||||
const index_t x_step = col_diff / abs_pos(col_diff);
|
||||
const index_t y_step = ROW * row_diff / abs_pos(row_diff);
|
||||
const index_t step = x_step + y_step;
|
||||
|
||||
if (abs_pos(col_diff) != abs_pos(row_diff))
|
||||
return false;
|
||||
|
||||
for (index_t p = from + step; p != to; p += step) {
|
||||
if (! tile_empty(board[p]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if index `to` is on a cardinal line of `from`, false otherwise
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool cardinal_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
const index_t col_diff = column(to) - column(from);
|
||||
const index_t row_diff = row(to) - row(from);
|
||||
|
||||
/* cardinal moves means one direction has to be zero */
|
||||
if (row_diff > 0 && col_diff > 0)
|
||||
return false;
|
||||
|
||||
index_t step = row_diff ?
|
||||
ROW * row_diff / abs_pos(row_diff)
|
||||
: col_diff / abs_pos(col_diff);
|
||||
|
||||
for (index_t p = from + step; p != to; p += step) {
|
||||
if (! tile_empty(board[p]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid bishop move
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool bishop_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
return diagonal_move_ok(board, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid rook move
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool rook_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
return cardinal_move_ok(board, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid knight move
|
||||
*
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool knight_move_ok(index_t from, index_t to)
|
||||
{
|
||||
const index_t c = abs_pos(column(to) - column(from));
|
||||
const index_t r = abs_pos(row(to - from));
|
||||
|
||||
return (c == 1 && r == 2)
|
||||
|| (c == 2 && r == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid king move
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool king_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
const index_t abs_col_diff = abs_pos(column(to) - column(from));
|
||||
const index_t abs_row_diff = abs_pos(row(to) - row(from));
|
||||
|
||||
(void)board;
|
||||
|
||||
return abs_col_diff <= 1 && abs_row_diff <= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if move is a valid queen move
|
||||
*
|
||||
* \param board Array of tiles representing chess board state
|
||||
* \param from Index of board piece is at
|
||||
* \param to Index of board piece tries to move to
|
||||
*/
|
||||
bool queen_move_ok(const tile_t board[BOARD_SIZE], index_t from, index_t to)
|
||||
{
|
||||
return diagonal_move_ok(board, from, to)
|
||||
|| cardinal_move_ok(board, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a move is valid, false otherwise
|
||||
*
|
||||
* \param board Pointer to list of tiles representing board state
|
||||
* \param from Tile to move piece from
|
||||
* \param to Tile to move piece to
|
||||
* \param player The current player to move
|
||||
* */
|
||||
bool move_ok(const tile_t board[BOARD_SIZE],
|
||||
index_t from,
|
||||
index_t to,
|
||||
int player)
|
||||
{
|
||||
/* player must own piece it moves */
|
||||
if (board[from] * player < 0)
|
||||
return false;
|
||||
|
||||
if (tile_empty(board[from]))
|
||||
return false;
|
||||
|
||||
/* player can't take own pieces or move piece onto itself*/
|
||||
if (same_color(board[from], board[to]))
|
||||
return false;
|
||||
|
||||
/* check piece specific moves */
|
||||
switch (abs_tile(board[from])) {
|
||||
case P:
|
||||
return pawn_move_ok(board, from, to, player);
|
||||
|
||||
case B:
|
||||
return bishop_move_ok(board, from, to);
|
||||
|
||||
case R:
|
||||
return rook_move_ok(board, from, to);
|
||||
|
||||
case N:
|
||||
return knight_move_ok(from, to);
|
||||
|
||||
case K:
|
||||
return king_move_ok(board, from, to);
|
||||
|
||||
case Q:
|
||||
return queen_move_ok(board, from, to);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user