diff --git a/chess/board.FCStd b/chess/board.FCStd index be21262..4bf5927 100644 Binary files a/chess/board.FCStd and b/chess/board.FCStd differ diff --git a/chess/chess.cpp b/chess/chess.cpp index 9ddc86b..778dbd9 100644 --- a/chess/chess.cpp +++ b/chess/chess.cpp @@ -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 } } diff --git a/chess/chess.hpp b/chess/chess.hpp index f4ba3fa..ed3d3f1 100644 --- a/chess/chess.hpp +++ b/chess/chess.hpp @@ -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 { diff --git a/chess/main.cpp b/chess/main.cpp index 69a419e..6ff7bfb 100644 --- a/chess/main.cpp +++ b/chess/main.cpp @@ -46,6 +46,8 @@ void cursor_update(struct render::cursor_state& cursor_state, uint32_t frame_ix) cursor.y += static_cast(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(0.f); + auto board_rotation_animator = render::animator(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(store_queue) = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); diff --git a/chess/render.cpp b/chess/render.cpp index 1efbbba..ffdc278 100644 --- a/chess/render.cpp +++ b/chess/render.cpp @@ -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]; diff --git a/chess/render.hpp b/chess/render.hpp index ec58b64..28c36e4 100644 --- a/chess/render.hpp +++ b/chess/render.hpp @@ -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); }