From d73c93b4c783edfc6f3afe19d35b9409953c7323 Mon Sep 17 00:00:00 2001 From: Stephen Enders Date: Wed, 27 Jan 2021 22:15:08 -0500 Subject: Legal placement logic and capturing Use board_t for board and prevent illegal placements. And allow for piece capture --- src/helper.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/helper.hpp | 25 +++++++++++++++++-- src/ur.cpp | 72 +++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 142 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/helper.cpp b/src/helper.cpp index 96eb919..11374e8 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -36,10 +36,10 @@ next(int* p, int max) return i; } -std::shared_ptr> +std::shared_ptr> createBoard(std::shared_ptr> textures) { - auto board = std::make_shared>(); + auto board = std::make_shared>(); sf::Texture& star_texture = (*textures)[STAR_TILE]; int blank_idx = 0; int sp_idx = 0; @@ -53,12 +53,12 @@ createBoard(std::shared_ptr> textures) // p1 pieces // p1 star // id's don't matter - int id = 0; { sf::Sprite s; s.setTexture(star_texture); s.setPosition(pos(3, 5)); - board->push_back({ id++, 3, s }); + struct board_t bp = { P1_ID, 3, s }; + board->push_back(bp); } // p1 start for (int i = 0; i < 3; i++) { @@ -66,25 +66,29 @@ createBoard(std::shared_ptr> textures) sf::Sprite s; s.setTexture(t); s.setPosition(pos(4 + i, 5)); - board->push_back({ id++, 2 - i, s }); + struct board_t bp = { P1_ID, 2 - i, s }; + board->push_back(bp); } // p1 end { sf::Sprite goal; goal.setTexture((*textures)[P1_END]); goal.setPosition(pos(8, 5)); - board->push_back({ id++, EXIT_SPACE, goal }); + struct board_t exit_p = { P1_ID, EXIT_SPACE, goal }; + board->push_back(exit_p); sf::Sprite end_star; end_star.setTexture(star_texture); end_star.setPosition(pos(9, 5)); - board->push_back({ id++, EXIT_SPACE - 1, end_star }); + struct board_t end_p = { P1_ID, EXIT_SPACE - 1, end_star }; + board->push_back(end_p); sf::Texture& t = (*textures)[P1_BOARD_TILES[next(&sp_idx, 2)]]; sf::Sprite s; s.setTexture(t); s.setPosition(pos(10, 5)); - board->push_back({ id++, EXIT_SPACE - 2, s }); + struct board_t bp = { P1_ID, EXIT_SPACE - 2, s }; + board->push_back(bp); } // center pieces for (int i = 0; i < 8; i++) { @@ -96,7 +100,8 @@ createBoard(std::shared_ptr> textures) s.setTexture(t); } s.setPosition(pos(3 + i, 4)); - board->push_back({ id++, 4 + i, s }); + struct board_t bp = { SHARED_ID, 4 + i, s }; + board->push_back(bp); } // p2 pieces // p2 star @@ -104,7 +109,8 @@ createBoard(std::shared_ptr> textures) sf::Sprite s; s.setTexture(star_texture); s.setPosition(pos(3, 3)); - board->push_back({ id++, 3, s }); + struct board_t bp = { P2_ID, 3, s }; + board->push_back(bp); } // p2 start for (int i = 0; i < 3; i++) { @@ -112,25 +118,29 @@ createBoard(std::shared_ptr> textures) sf::Sprite s; s.setTexture(t); s.setPosition(pos(4 + i, 3)); - board->push_back({ id++, 2 - i, s }); + struct board_t bp = { P2_ID, 2 - i, s }; + board->push_back(bp); } // p2 end { sf::Sprite goal; goal.setTexture((*textures)[P2_END]); goal.setPosition(pos(8, 3)); - board->push_back({ id++, EXIT_SPACE, goal }); + struct board_t goal_p = { P2_ID, EXIT_SPACE, goal }; + board->push_back(goal_p); sf::Sprite end_star; end_star.setTexture(star_texture); end_star.setPosition(pos(9, 3)); - board->push_back({ id++, EXIT_SPACE - 1, end_star }); + struct board_t end_p = { P2_ID, EXIT_SPACE - 1, end_star }; + board->push_back(end_p); sf::Texture& t = (*textures)[P2_BOARD_TILES[next(&sp_idx, 2)]]; sf::Sprite end_tile; end_tile.setTexture(t); end_tile.setPosition(pos(10, 3)); - board->push_back({ id++, EXIT_SPACE - 2, end_tile }); + struct board_t bp = { P2_ID, EXIT_SPACE - 2, end_tile }; + board->push_back(bp); } return board; @@ -161,9 +171,10 @@ createPiece(int id, sf::Texture& texture) } std::shared_ptr -createPlayer(sf::Texture& texture) +createPlayer(const int pid, sf::Texture& texture) { std::shared_ptr player = std::make_shared(); + player->pid = pid; player->score = 0; player->pieces = std::make_shared>(); for (int i = 0; i < NUM_PIECES; i++) { @@ -273,3 +284,41 @@ pos(float c, float r) { return { c * SPRITE_SIZE, r * SPRITE_SIZE }; } + +bool +canPlace(struct piece_t* piece, + int turn_pid, + struct board_t board_tile, + std::shared_ptr> myPieces, + std::shared_ptr> opponentPieces, + int& takenPieceId) +{ + if (board_tile.pid != turn_pid && board_tile.pid != SHARED_ID) + return false; + int position = board_tile.position; + if (position == EXIT_SPACE) + return true; // can always place in the exit + + // can never collide with your own pieces + for (auto& p : (*myPieces)) { + if ((p.id != piece->id) // not the same + && (p.position == position)) { + return false; // collides with own pieces + } + } + // can collide with an enemy + if (position >= 4 && position <= 11) { + for (auto& p : (*opponentPieces)) { + // collided + if (p.position == position) { + // can not capture on safe space + if (position == SAFE_SPACE) + return false; + takenPieceId = p.id; + return true; + } + } + } + + return true; +} diff --git a/src/helper.hpp b/src/helper.hpp index 9495791..2ff8b24 100644 --- a/src/helper.hpp +++ b/src/helper.hpp @@ -16,6 +16,9 @@ static const float SPRITE_ROWS = 9.f; static const float SPRITE_COLS = 14.f; static const float SCR_W = SPRITE_SIZE / ZOOM * SPRITE_COLS / ZOOM; static const float SCR_H = SPRITE_SIZE / ZOOM * SPRITE_ROWS / ZOOM; +static const int SHARED_ID = -1; +static const int P1_ID = 0; +static const int P2_ID = 1; static const int P1_PIECE = 19; static const int P2_PIECE = 18; static const int P1_BOARD_TILES[2] = { 0, 1 }; @@ -45,10 +48,19 @@ struct piece_t int id; int position; sf::Sprite sprite; + sf::Vector2f origin; +}; + +struct board_t +{ + int pid; // owning players space -1 for shared + int position; + sf::Sprite sprite; }; struct player_t { + int pid; int score; std::shared_ptr> pieces; }; @@ -63,14 +75,14 @@ struct dice_t std::shared_ptr> loadTextures(const char* path); -std::shared_ptr> +std::shared_ptr> createBoard(std::shared_ptr> textures); sf::Font loadFont(); std::shared_ptr -createPlayer(sf::Texture& pieceTexture); +createPlayer(const int pid, sf::Texture& pieceTexture); std::shared_ptr createPiece(int id, sf::Texture& texture); @@ -101,4 +113,13 @@ getLegalMoves(std::shared_ptr activePlayer, sf::Vector2f pos(float c, float r); + +bool +canPlace(struct piece_t* piece, + int turn_pid, + struct board_t board_tile, + std::shared_ptr> myPieces, + std::shared_ptr> opponentPieces, + int& takenPieceId); + #endif diff --git a/src/ur.cpp b/src/ur.cpp index 6bd27f4..f406623 100644 --- a/src/ur.cpp +++ b/src/ur.cpp @@ -30,8 +30,8 @@ change_state(GameState next) state = next; } -// p1 = false, p2 = true -bool turn_tracker = false; +// tracks the turn pids +int turn_pid = P1_ID; int rolling_frame = 0; inline void @@ -43,20 +43,20 @@ next(int* i, int max) inline void next_turn() { - turn_tracker = !turn_tracker; + turn_pid = turn_pid == P1_ID ? P2_ID : P1_ID; change_state(GameState::WAITING); } inline bool p1_turn() { - return !turn_tracker; + return turn_pid == P1_ID; } inline bool p2_turn() { - return turn_tracker; + return turn_pid == P2_ID; } inline void @@ -160,14 +160,14 @@ main() const std::shared_ptr> textures = loadTextures(TEXTURE_PATH); - const std::shared_ptr> board = + const std::shared_ptr> board = createBoard(textures); const std::shared_ptr p1 = - createPlayer((*textures)[P1_PIECE]); + createPlayer(P1_ID, (*textures)[P1_PIECE]); const std::shared_ptr p2 = - createPlayer((*textures)[P2_PIECE]); + createPlayer(P2_ID, (*textures)[P2_PIECE]); const std::shared_ptr> roll_sprites = createRollSprites((*textures)[ROLL_TILES[0]], (*textures)[ROLL_TILES[1]]); @@ -187,11 +187,13 @@ main() int p_num = (SPRITE_COLS / 2) - (p1->pieces->size() / 2) - 1; for (auto& p : *(p1->pieces)) { p.sprite.setPosition(pos(p_num++, SPRITE_ROWS - 1)); + p.origin = p.sprite.getPosition(); } p_num = (SPRITE_COLS / 2) - (p2->pieces->size() / 2) - 1; for (auto& p : *(p2->pieces)) { p.sprite.setPosition(pos(p_num++, 0)); + p.origin = p.sprite.getPosition(); } sf::Sprite roll_result; @@ -263,6 +265,15 @@ main() window.setView(window.getDefaultView()); // reset back to main view } else if (!sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) { mouse_left_locked = false; + // is a piece being clicked + std::shared_ptr> pieces, enemyPieces; + if (p1_turn()) { + pieces = p1->pieces; + enemyPieces = p2->pieces; + } else { + pieces = p2->pieces; + enemyPieces = p1->pieces; + } if (state == GameState::PLACING && grabbed_piece != nullptr) { // did the piece drop into place bool in_place = false; @@ -274,9 +285,27 @@ main() if (intersect.width > SPRITE_SIZE / 2 && intersect.height > SPRITE_SIZE / 2) { // check valid placement - grabbed_piece->sprite.setPosition(s.getPosition()); - in_place = true; - break; + int takenPieceId = -1; + if (canPlace(grabbed_piece, + turn_pid, + bp, + pieces, + enemyPieces, + takenPieceId)) { + // did we take a piece + if (takenPieceId >= 0) { + for (auto& ep : (*enemyPieces)) { + if (ep.id = takenPieceId) { + ep.sprite.setPosition(ep.origin); + ep.position = -1; + } + } + } + grabbed_piece->sprite.setPosition(s.getPosition()); + grabbed_piece->position = bp.position; + in_place = true; + break; + } } } } @@ -308,12 +337,21 @@ main() float y = mPos.y - (grabbed_piece->sprite.getGlobalBounds().height / 2); grabbed_piece->sprite.setPosition(x, y); } - // draw unused pieces - for (auto& p : *(p1->pieces)) { - window.draw(p.sprite); - } - for (auto& p : *(p2->pieces)) { - window.draw(p.sprite); + // draw pieces (draw own pieces last to ensure "on top") + if (p1_turn()) { + for (auto& p : *(p2->pieces)) { + window.draw(p.sprite); + } + for (auto& p : *(p1->pieces)) { + window.draw(p.sprite); + } + } else { + for (auto& p : *(p1->pieces)) { + window.draw(p.sprite); + } + for (auto& p : *(p2->pieces)) { + window.draw(p.sprite); + } } render_dice(&window, -- cgit v1.2.3-54-g00ecf