chess: pawn promotion

For a lack of a better idea, bind board and piece rotation to X/Y

chess::do_move no longer advances the turn--prior to this change,
castle moves incorrectly double-negated turn.
This commit is contained in:
Zack Buhman 2024-06-05 00:36:06 -05:00
parent ebb1955500
commit bf9a862a43
6 changed files with 119 additions and 16 deletions

Binary file not shown.

View File

@ -82,6 +82,9 @@ move_t * moves_pawn(game_state& game_state, int8_t origin, move_t * moves)
if (other.type == 0) {
int8_t to_position = xy_to_position(x, y);
if (!speculative_check(game_state, origin, to_position, self.type)) {
if (y == 0 || y == 7) {
type = move_type::pawn_promote;
}
*moves++ = {type, to_position};
}
} else {
@ -289,6 +292,8 @@ void game_init(game_state& game_state)
game_state.interaction.selected_position = -1;
game_state.interaction.last_move.from_position = -1;
game_state.interaction.last_move.to_position = -1;
game_state.interaction.promotion_ix[0] = 0;
game_state.interaction.promotion_ix[1] = 0;
board_init(game_state);
}
@ -406,6 +411,15 @@ void do_move(game_state& game_state, int8_t from_position, move_t& move)
piece_list_delete(game_state.piece_list, en_passant_piece.piece_list_offset);
}
break;
case move_type::pawn_promote:
{
serial::string("move pawn promote\n");
if (origin.type > 0)
origin.type = promotion_types[game_state.interaction.promotion_ix[0]];
else
origin.type = -promotion_types[game_state.interaction.promotion_ix[1]];
}
break;
default: break;
}
@ -416,8 +430,6 @@ void do_move(game_state& game_state, int8_t from_position, move_t& move)
game_state.piece_list.piece[origin.piece_list_offset] = &destination;
game_state.interaction.last_move.from_position = from_position;
game_state.interaction.last_move.to_position = move.to_position;
game_state.turn = -game_state.turn;
}
void select_position(game_state& game_state, int8_t x, int8_t y)
@ -439,6 +451,7 @@ void select_position(game_state& game_state, int8_t x, int8_t y)
do_move(game_state,
game_state.interaction.selected_position, // from
game_state.interaction.moves.moves[moves_ix]); // to
game_state.turn = -game_state.turn;
// fall through to deselect
}
}

View File

@ -14,6 +14,13 @@ constexpr int8_t queen = 5;
constexpr int8_t king = 6;
};
constexpr int8_t promotion_types[4] = {
piece_type::knight,
piece_type::bishop,
piece_type::rook,
piece_type::queen,
};
namespace movement_state {
constexpr int8_t not_moved = 0;
constexpr int8_t moved = 1;
@ -45,6 +52,7 @@ enum struct move_type : int8_t {
castle_long,
pawn_double_advance,
pawn_en_passant_capture,
pawn_promote,
};
struct move_t {
@ -81,6 +89,7 @@ struct interaction_state {
int8_t selected_position;
struct moves_list moves;
struct annotation_list annotation_list;
int8_t promotion_ix[2];
};
struct game_state {

View File

@ -46,6 +46,8 @@ void cursor_update(struct render::cursor_state& cursor_state, uint32_t frame_ix)
cursor.y += static_cast<float>(data.analog_coordinate_axis[3] - 0x80) * -0.0015 * invert;
cursor.button[frame_ix].a = ft0::data_transfer::digital_button::a(data.digital_button) == 0;
cursor.button[frame_ix].b = ft0::data_transfer::digital_button::b(data.digital_button) == 0;
cursor.button[frame_ix].x = ft0::data_transfer::digital_button::x(data.digital_button) == 0;
cursor.button[frame_ix].y = ft0::data_transfer::digital_button::y(data.digital_button) == 0;
bool start = ft0::data_transfer::digital_button::start(data.digital_button) == 0;
if (start) {
cursor.x = 3.5f;
@ -70,27 +72,56 @@ void cursor_update(struct render::cursor_state& cursor_state, uint32_t frame_ix)
}
}
if (cursor.x < -1.0f) cursor.x = -1.0f;
if (cursor.x > 8.0f) cursor.x = 8.0f;
if (cursor.x < -2.0f) cursor.x = -2.0f;
if (cursor.x > 9.0f) cursor.x = 9.0f;
if (cursor.y < -0.5f) cursor.y = -0.5f;
if (cursor.y > 7.5f) cursor.y = 7.5f;
}
}
static bool piece_rotation = false;
static bool board_rotation = false;
void promotion_select(chess::game_state& game_state,
int side,
int promotion_ix)
{
if (promotion_ix < 0 || promotion_ix >= 4) {
return;
}
game_state.interaction.promotion_ix[side] = promotion_ix;
}
void cursor_events(chess::game_state& game_state, struct render::cursor_state& cursor_state, uint32_t frame_ix)
{
for (int cursor_ix = 0; cursor_ix < render::cursor_state::num_cursors; cursor_ix++) {
auto& cursor = cursor_state.cur[cursor_ix];
const uint32_t last_frame = (frame_ix + 1) & 1;
const int8_t x = cursor.x + 0.5f;
const float x = cursor.x + 0.5f;
const int8_t y = cursor.y + 0.5f;
if (cursor.button[last_frame].a != cursor.button[frame_ix].a && cursor.button[frame_ix].a) {
chess::clear_annotations(game_state);
chess::select_position(game_state, x, y);
if (x > 8.5) {
serial::string("white side\n");
int8_t promotion_ix = y;
promotion_select(game_state, 0, promotion_ix);
} else if (x < -0.5) {
serial::string("black side\n");
int8_t promotion_ix = 7 - y;
promotion_select(game_state, 1, promotion_ix);
} else {
chess::select_position(game_state, x, y);
}
}
if (cursor.button[last_frame].b != cursor.button[frame_ix].b && cursor.button[frame_ix].b) {
chess::annotate_position(game_state, x, y);
}
if (cursor.button[last_frame].x != cursor.button[frame_ix].x && cursor.button[frame_ix].x) {
piece_rotation = !piece_rotation;
}
if (cursor.button[last_frame].y != cursor.button[frame_ix].y && cursor.button[frame_ix].y) {
board_rotation = !board_rotation;
}
}
}
@ -134,27 +165,31 @@ void main()
vt.board_rotation = 0.f;
auto piece_rotation_animator = render::animator<float>(0.f);
auto board_rotation_animator = render::animator<float>(0.f);
struct render::cursor_state cursor_state = render::cursor_state();
constexpr float pi = 3.141592653589793f;
piece_rotation = false;
board_rotation = false;
while (true) {
input::state_update(send_buf, recv_buf);
cursor_update(cursor_state, frame_ix);
cursor_events(game_state, cursor_state, frame_ix);
float target = game_state.turn == 1 ? 0.f : pi;
piece_rotation_animator.set_target(target, 60);
//vt.board_rotation = piece_rotation_animator.interpolate();
//vt.piece_rotation = piece_rotation_animator.interpolate();
//float target = game_state.turn == 1 ? 0.f : pi;
piece_rotation_animator.set_target(piece_rotation ? pi : 0.f, 60);
board_rotation_animator.set_target(board_rotation ? pi : 0.f, 60);
vt.board_rotation = board_rotation_animator.interpolate();
vt.piece_rotation = piece_rotation_animator.interpolate();
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
640 / 32,
480 / 32);
render::render(game_state, vt, cursor_state);
render::render(vt, game_state, cursor_state);
*reinterpret_cast<ta_global_parameter::end_of_list *>(store_queue) =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);

View File

@ -190,7 +190,7 @@ void draw_moves(const view_transform vt,
}
void draw_piece(const view_transform vt,
int8_t type, int8_t x, int8_t y)
int8_t type, float x, float y)
{
bool white = type > 0;
uint32_t color = white ? 0xffdddddd : 0xff444444;
@ -337,8 +337,50 @@ void draw_interaction(const view_transform vt,
render::draw_illumination(vt, interaction.last_move.to_position, yellow_highlight);
}
void render(const chess::game_state& game_state,
const view_transform vt,
void draw_promotion_selection(const view_transform vt,
const chess::game_state& game_state)
{
constexpr uint32_t yellow_highlight = 0x7fffff33;
draw_model(vt,
square::vertices,
square::faces,
square::num_faces,
yellow_highlight,
8.5f, game_state.interaction.promotion_ix[0],
illumination_z,
1.0f, // scale
0.0f, // rotation
true, // always
true); // alpha
for (int i = 0; i < 4; i++) {
draw_piece(vt,
chess::promotion_types[i],
8.5f, i);
}
draw_model(vt,
square::vertices,
square::faces,
square::num_faces,
yellow_highlight,
-1.5f, 7 - game_state.interaction.promotion_ix[1],
illumination_z,
1.0f, // scale
0.0f, // rotation
true, // always
true); // alpha
for (int i = 0; i < 4; i++) {
draw_piece(vt,
-chess::promotion_types[i],
-1.5f, 7 - i);
}
}
void render(const view_transform vt,
const chess::game_state& game_state,
const cursor_state cursor_state)
{
render::draw_board(vt);
@ -347,6 +389,8 @@ void render(const chess::game_state& game_state,
render::draw_annotation(vt, game_state.interaction.annotation_list);
render::draw_pieces(vt, game_state);
render::draw_promotion_selection(vt, game_state);
render::draw_moves(vt, game_state.interaction.moves);
for (int i = 0; i < cursor_state::num_cursors; i++) {
auto& cursor = cursor_state.cur[i];

View File

@ -46,6 +46,8 @@ struct animator {
struct button {
bool a;
bool b;
bool x;
bool y;
};
struct cursor {
@ -78,8 +80,8 @@ struct cursor_state {
}
};
void render(const chess::game_state& game_state,
const view_transform vt,
void render(const view_transform vt,
const chess::game_state& game_state,
const cursor_state cursor_state);
}