From 373393825b27f5a7d012d37d9aefdda60cbd2644 Mon Sep 17 00:00:00 2001 From: r3w0p Date: Thu, 24 Oct 2024 22:57:22 +0100 Subject: [PATCH] clean-up progress for new idea on ai train player ABC only; DEF makes purely random decisions; no need for bot player to do all of this; did some additional clean-up on close() and smart pointers etc. --- CMakeLists.txt | 4 +- README | 2 +- include/caravan/core/common.h | 2 + include/caravan/core/training.h | 13 +- include/caravan/model/caravan.h | 5 +- include/caravan/model/game.h | 7 +- include/caravan/model/player.h | 3 +- include/caravan/model/table.h | 6 +- include/caravan/user/bot/factory.h | 1 + include/caravan/user/bot/normal.h | 1 - include/caravan/user/bot/train.h | 21 --- include/caravan/user/user.h | 14 +- include/caravan/view/view.h | 4 +- include/caravan/view/view_tui.h | 2 - src/caravan/core/common.cpp | 242 +++++++++++++++++++++++++++ src/caravan/core/training.cpp | 112 +++++++++++-- src/caravan/main.cpp | 6 +- src/caravan/model/caravan.cpp | 51 ------ src/caravan/model/game.cpp | 41 +---- src/caravan/model/player.cpp | 21 +-- src/caravan/model/table.cpp | 44 +---- src/caravan/train.cpp | 51 +++--- src/caravan/user/bot/ai.cpp | 4 +- src/caravan/user/bot/factory.cpp | 2 +- src/caravan/user/bot/friendly.cpp | 2 - src/caravan/user/bot/normal.cpp | 8 - src/caravan/user/bot/train.cpp | 65 -------- src/caravan/view/view.cpp | 1 - src/caravan/view/view_tui.cpp | 259 +---------------------------- test/caravan/model/test_game.cpp | 119 ------------- test/caravan/model/test_player.cpp | 14 +- 31 files changed, 418 insertions(+), 709 deletions(-) delete mode 100644 include/caravan/user/bot/train.h delete mode 100644 src/caravan/user/bot/train.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 164572a..8cca6b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(PROJECT_VERSION 1.3.0) +set(PROJECT_VERSION 2.0.0) set(PROJECT_DESCRIPTION "A command-line version of the Caravan card game from Fallout: New Vegas.") set(PROJECT_COPYRIGHT "Copyright (c) 2022-2024 r3w0p") set(PROJECT_URL "https://github.com/r3w0p/caravan") @@ -55,9 +55,11 @@ include_directories(include) add_library(core "include/caravan/core/common.h" "include/caravan/core/exceptions.h" + "include/caravan/core/training.h" "src/caravan/core/common.cpp" "src/caravan/core/exceptions.cpp" + "src/caravan/core/training.cpp" ) add_library(model diff --git a/README b/README index 000950f..df67fc5 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ | (_| (_| | | | (_| |\ \/ / (_| | | | | \___\__,_|_| \__,_| \__/ \__,_|_| |_| -| v1.3.0 | GPL-3.0 | (c) 2022-2024 r3w0p | +| v2.0.0 | GPL-3.0 | (c) 2022-2024 r3w0p | A command-line version of the Caravan card game from Fallout: New Vegas. diff --git a/include/caravan/core/common.h b/include/caravan/core/common.h index fcdb237..7c0aa80 100644 --- a/include/caravan/core/common.h +++ b/include/caravan/core/common.h @@ -139,4 +139,6 @@ std::string caravan_letter(CaravanName caravan_name); uint8_t numeral_rank_value(Card c); +GameCommand generate_command(std::string input, bool confirmed); + #endif //CARAVAN_CORE_COMMON_H diff --git a/include/caravan/core/training.h b/include/caravan/core/training.h index aeb5c88..87fc6aa 100644 --- a/include/caravan/core/training.h +++ b/include/caravan/core/training.h @@ -15,7 +15,10 @@ */ const uint16_t SIZE_ACTION_SPACE = 299; -const uint16_t SIZE_GAME_STATE = 201; +const uint16_t SIZE_GAME_STATE = 200; + +const uint8_t NUM_PLAYER_ABC = 1; +const uint8_t NUM_PLAYER_DEF = 2; /* * TYPES @@ -23,7 +26,7 @@ const uint16_t SIZE_GAME_STATE = 201; typedef std::array ActionSpace; typedef std::array GameState; -typedef std::map> QTable; +typedef std::map> QTable; typedef struct TrainConfig { float discount{0.0}; @@ -33,6 +36,10 @@ typedef struct TrainConfig { uint32_t episode{0}; } TrainConfig; +std::uniform_int_distribution dist_first_player(NUM_PLAYER_ABC, NUM_PLAYER_DEF); +std::uniform_int_distribution dist_action(0, SIZE_ACTION_SPACE - 1); +std::uniform_real_distribution dist_explore(0, 1); + /* * FUNCTIONS */ @@ -41,4 +48,6 @@ uint8_t card_to_uint8_t(Card c); void get_game_state(GameState *gs, Game *game, PlayerName pname); void populate_action_space(ActionSpace *as); +void train_on_game(Game *game, QTable &q_table, ActionSpace &action_space, TrainConfig &tc, std::mt19937 &gen); + #endif //CARAVAN_CORE_TRAINING_H diff --git a/include/caravan/model/caravan.h b/include/caravan/model/caravan.h index b25036f..f6e0daf 100644 --- a/include/caravan/model/caravan.h +++ b/include/caravan/model/caravan.h @@ -17,7 +17,6 @@ class Caravan { CaravanName name; Track track; uint8_t i_track; - bool closed; static uint8_t numeral_rank_to_uint8_t(Rank rank); @@ -32,7 +31,7 @@ class Caravan { * @param cvname The caravan name. */ explicit Caravan(CaravanName cvname) : - name(cvname), track({}), i_track(0), closed(false) {}; + name(cvname), track({}), i_track(0) {}; void clear(); @@ -55,8 +54,6 @@ class Caravan { void remove_rank(Rank rank, uint8_t pos_exclude); void remove_suit(Suit suit, uint8_t pos_exclude); - - void close(); }; #endif //CARAVAN_MODEL_CARAVAN_H diff --git a/include/caravan/model/game.h b/include/caravan/model/game.h index b04a9c5..de928f7 100644 --- a/include/caravan/model/game.h +++ b/include/caravan/model/game.h @@ -16,7 +16,6 @@ class Game { Player *pa_ptr{}; Player *pb_ptr{}; Player *p_turn; - bool closed; int8_t compare_bids(CaravanName cvname1, CaravanName cvname2); @@ -33,9 +32,9 @@ class Game { public: explicit Game(GameConfig *gc); - static CaravanName get_opposite_caravan_name(CaravanName cvname); + ~Game(); - void close(); + static CaravanName get_opposite_caravan_name(CaravanName cvname); Player *get_player(PlayerName pname); @@ -51,8 +50,6 @@ class Game { PlayerName get_winner(); - bool is_closed(); - void play_option(GameCommand *command); bool check_option(GameCommand *command); // TODO diff --git a/include/caravan/model/player.h b/include/caravan/model/player.h index 038b6c2..902d811 100644 --- a/include/caravan/model/player.h +++ b/include/caravan/model/player.h @@ -16,12 +16,11 @@ class Player { Hand hand; uint8_t i_hand; uint16_t moves; - bool closed; public: explicit Player(PlayerName pn, Deck *d); - void close(); + ~Player(); Card get_from_hand_at(uint8_t pos); diff --git a/include/caravan/model/table.h b/include/caravan/model/table.h index b78418a..f13d282 100644 --- a/include/caravan/model/table.h +++ b/include/caravan/model/table.h @@ -9,7 +9,6 @@ #include #include "caravan/model/caravan.h" - class Table { protected: Caravan *a = new Caravan(CARAVAN_A); @@ -20,12 +19,11 @@ class Table { Caravan *f = new Caravan(CARAVAN_F); std::array caravans = {a, b, c, d, e, f}; - bool closed; public: - explicit Table(); + explicit Table() = default; - void close(); + ~Table(); Caravan *get_caravan(CaravanName cvname); diff --git a/include/caravan/user/bot/factory.h b/include/caravan/user/bot/factory.h index 9a764e8..b0af88e 100644 --- a/include/caravan/user/bot/factory.h +++ b/include/caravan/user/bot/factory.h @@ -10,6 +10,7 @@ class BotFactory { public: BotFactory() = delete; + static UserBot *get(std::string name, PlayerName player_name); }; diff --git a/include/caravan/user/bot/normal.h b/include/caravan/user/bot/normal.h index 4cb4c5a..6907e96 100644 --- a/include/caravan/user/bot/normal.h +++ b/include/caravan/user/bot/normal.h @@ -13,7 +13,6 @@ class UserBotNormal : public UserBot { public: explicit UserBotNormal(PlayerName pn) : UserBot(pn){}; - void close() override; std::string request_move(Game *game) override; }; diff --git a/include/caravan/user/bot/train.h b/include/caravan/user/bot/train.h deleted file mode 100644 index 4044fdb..0000000 --- a/include/caravan/user/bot/train.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2022-2024 r3w0p -// The following code can be redistributed and/or -// modified under the terms of the GPL-3.0 License. - -#ifndef CARAVAN_USER_BOT_TRAIN_H -#define CARAVAN_USER_BOT_TRAIN_H - -#include "caravan/user/bot/ai.h" -#include "caravan/core/training.h" - -class UserBotTrain : public UserBot { -protected: - ActionSpace action_space; - QTable q_table; -public: - explicit UserBotTrain(); - - std::string make_move_train(Game *game, TrainConfig *tc); -}; - -#endif //CARAVAN_USER_BOT_TRAIN_H diff --git a/include/caravan/user/user.h b/include/caravan/user/user.h index fe74ed1..50abe9b 100644 --- a/include/caravan/user/user.h +++ b/include/caravan/user/user.h @@ -11,24 +11,20 @@ class User { protected: PlayerName name; - bool closed; public: - virtual ~User() = default; - - explicit User(PlayerName pn) : name(pn), closed(false) {}; - - PlayerName get_name() { return name; } + explicit User(PlayerName pn) : name(pn) {}; - virtual void close() = 0; + virtual ~User() = default; virtual bool is_human() = 0; virtual std::string request_move(Game *game) = 0; + + PlayerName get_name() { return name; } }; class UserHuman : public User { public: explicit UserHuman(PlayerName pn) : User(pn) {}; - void close() override { closed = true; } bool is_human() override { return true; } std::string request_move(Game *game) override { return {}; } }; @@ -37,9 +33,7 @@ class UserBot : public User { public: explicit UserBot(PlayerName pn) : User(pn) {}; - void close() override { closed = true; } bool is_human() override { return false; } - std::string request_move(Game *game) override { return {}; } }; #endif //CARAVAN_USER_H diff --git a/include/caravan/view/view.h b/include/caravan/view/view.h index d705124..15da34c 100644 --- a/include/caravan/view/view.h +++ b/include/caravan/view/view.h @@ -52,13 +52,11 @@ class View { protected: ViewConfig *vc; Game *game; - bool closed; public: explicit View(ViewConfig *vc, Game *game); + virtual ~View() = default; virtual void run() = 0; - - virtual void close() = 0; }; #endif //CARAVAN_VIEW_H diff --git a/include/caravan/view/view_tui.h b/include/caravan/view/view_tui.h index 488a19a..219c13b 100644 --- a/include/caravan/view/view_tui.h +++ b/include/caravan/view/view_tui.h @@ -16,8 +16,6 @@ class ViewTUI : public View { explicit ViewTUI(ViewConfig *vc, Game *game) : View(vc, game) {}; void run() override; - - void close() override; }; #endif //CARAVAN_VIEW_TUI_H diff --git a/src/caravan/core/common.cpp b/src/caravan/core/common.cpp index 96d950f..4d5109f 100644 --- a/src/caravan/core/common.cpp +++ b/src/caravan/core/common.cpp @@ -5,6 +5,248 @@ #include "caravan/core/common.h" #include "caravan/core/exceptions.h" +void process_first(std::string input, GameCommand *command) { + char c = input.at(0); // minimum input size already checked elsewhere + + switch (c) { + case 'P': + case 'p': + command->option = OPTION_PLAY; + /* + * P2F + * "Play numeral card at hand pos 2 onto caravan F" + * + * P4F8 + * "Play face card at hand pos 4 onto caravan F, slot 8" + */ + break; + + case 'D': + case 'd': + command->option = OPTION_DISCARD; + /* + * D3 + * "Discard card at hand pos 3" + */ + break; + + case 'C': + case 'c': + /* + * CE + * "Clear caravan E" + */ + command->option = OPTION_CLEAR; + break; + + default: + throw CaravanInputException( + "Invalid option '" + std::string(1, c) + "', must be one of: (P)lay, (D)iscard, (C)lear."); + } +} + +void process_second(std::string input, GameCommand *command) { + if (command->option == OPTION_PLAY or command->option == OPTION_DISCARD) { + + if (input.size() < 2) { + throw CaravanInputException("A hand position has not been entered."); + } + + char c = input.at(1); + + switch (c) { + case '1': + command->pos_hand = 1; + break; + case '2': + command->pos_hand = 2; + break; + case '3': + command->pos_hand = 3; + break; + case '4': + command->pos_hand = 4; + break; + case '5': + command->pos_hand = 5; + break; + case '6': + command->pos_hand = 6; + break; + case '7': + command->pos_hand = 7; + break; + case '8': + command->pos_hand = 8; + break; + default: + throw CaravanInputException("Invalid hand position '" + std::string(1, c) + "'."); + } + + } else if (command->option == OPTION_CLEAR) { + + if (input.size() < 2) { + throw CaravanInputException("A caravan name has not been entered."); + } + + char c = input.at(1); + + switch (c) { + case 'A': + case 'a': + command->caravan_name = CARAVAN_A; + break; + case 'B': + case 'b': + command->caravan_name = CARAVAN_B; + break; + case 'C': + case 'c': + command->caravan_name = CARAVAN_C; + break; + case 'D': + case 'd': + command->caravan_name = CARAVAN_D; + break; + case 'E': + case 'e': + command->caravan_name = CARAVAN_E; + break; + case 'F': + case 'f': + command->caravan_name = CARAVAN_F; + break; + default: + throw CaravanInputException("Invalid caravan name '" + std::string(1, c) + "', must be between: A-F."); + } + + } // else invalid command type, handled during parse of first character +} + +void process_third(std::string input, GameCommand *command) { + if (command->option == OPTION_PLAY) { + + if (input.size() < 3) { + throw CaravanInputException("A caravan name has not been entered."); + } + + char c = input.at(2); + + switch (c) { + case 'A': + case 'a': + command->caravan_name = CARAVAN_A; + break; + case 'B': + case 'b': + command->caravan_name = CARAVAN_B; + break; + case 'C': + case 'c': + command->caravan_name = CARAVAN_C; + break; + case 'D': + case 'd': + command->caravan_name = CARAVAN_D; + break; + case 'E': + case 'e': + command->caravan_name = CARAVAN_E; + break; + case 'F': + case 'f': + command->caravan_name = CARAVAN_F; + break; + default: + throw CaravanInputException("Invalid caravan name '" + std::string(1, c) + "', must be between: A-F."); + } + } +} + +void process_fourth(std::string input, GameCommand *command) { + if (command->option == OPTION_PLAY) { + + if (input.size() < 4) { return; } // optional, not an error + + char c = input.at(3); + + switch (c) { + case '1': + command->pos_caravan = 1; + break; + case '2': + command->pos_caravan = 2; + break; + case '3': + command->pos_caravan = 3; + break; + case '4': + command->pos_caravan = 4; + break; + case '5': + command->pos_caravan = 5; + break; + case '6': + command->pos_caravan = 6; + break; + case '7': + command->pos_caravan = 7; + break; + case '8': + command->pos_caravan = 8; + break; + default: + throw CaravanInputException("Invalid caravan position '" + std::string(1, c) + "'."); + } + } +} + +GameCommand generate_command(std::string input, bool confirmed) { + GameCommand command; + + if (input.empty()) { return command; } + + try { + /* + * FIRST + * - COMMAND TYPE + */ + process_first(input, &command); + + /* + * SECOND + * - HAND POSITION or + * - CARAVAN NAME + */ + process_second(input, &command); + + /* + * THIRD + * - CARAVAN NAME + */ + process_third(input, &command); + + /* + * FOURTH + * - CARAVAN POSITION (used when selecting Face card only) + */ + process_fourth(input, &command); + + } catch (CaravanInputException &e) { + if (confirmed) { + // For confirmed commands: throw to other handling that prints + // command errors to the player + throw; + } else { + // For unconfirmed commands: accept whatever was able to be parsed + // so that it can be used for highlighting the game board + return command; + } + } + + return command; +} + bool is_numeral_card(Card c) { return (c.rank >= ACE and c.rank <= TEN); } diff --git a/src/caravan/core/training.cpp b/src/caravan/core/training.cpp index ffdbeda..f092c7b 100644 --- a/src/caravan/core/training.cpp +++ b/src/caravan/core/training.cpp @@ -2,11 +2,19 @@ // The following code can be redistributed and/or // modified under the terms of the GPL-3.0 License. +#include +#include +#include +#include +#include +#include +#include +#include #include "caravan/core/exceptions.h" #include "caravan/core/common.h" -#include "caravan/core/training.h" #include "caravan/model/game.h" -#include +#include "caravan/core/training.h" + uint8_t card_to_uint8_t(Card c) { if (c.rank == JOKER) { return 1; } @@ -33,17 +41,6 @@ void get_game_state(GameState *gs, Game *game, PlayerName pname) { Hand hand = player->get_hand(); uint8_t size_hand = player->get_size_hand(); - // Get player indicator - if (pname == PLAYER_ABC) { - (*gs)[i++] = 1; - } else if (pname == PLAYER_DEF) { - (*gs)[i++] = 2; - } else { - throw CaravanFatalException( - "Invalid player name when getting game state: " - "must be either ABC or DEF."); - } - // Get state from player's hand // {AC, 2D, 8S, 8S, JO, 0, 0, 0} (all ints, with 0 for empty slot) for (uint8_t i_hand = 0; i_hand < HAND_SIZE_MAX_START; i_hand++) { @@ -128,3 +125,92 @@ void populate_action_space(ActionSpace *as) { } } } + +void train_on_game(Game *game, QTable &q_table, ActionSpace &action_space, TrainConfig &tc, std::mt19937 &gen) { + // Get player names + PlayerName pturn = game->get_player_turn(); + PlayerName popp = pturn == PLAYER_ABC ? PLAYER_DEF : PLAYER_ABC; + + // Read game state and maybe add to the q-table if state not present + GameState gs; + get_game_state(&gs, game, pturn); + + if (!q_table.contains(gs)) { + // TODO maybe is this needed: q_table[gs] = {}; + for (uint16_t i = 0; i < SIZE_ACTION_SPACE; i++) { + q_table[gs][action_space[i]] = 0; + } + } + + // Choose an action + std::string action; + GameCommand command; + std::vector invalid; + bool explore = dist_explore(gen) < tc.explore; + + while (true) { + if (explore) { + // If exploring, fetch a random action from the action space + action = action_space[dist_action(gen)]; + + } else { + // Otherwise, pick the optimal action from the q-table + uint16_t pick_index = 0; + float pick_value = q_table[gs][action_space[pick_index]]; + + for (uint16_t i_action = 1; i_action < SIZE_ACTION_SPACE; i_action++) { + // Ignore if already found to be invalid + if (std::count(invalid.begin(), invalid.end(), action_space[i_action]) > 0) { + continue; + } + + if (q_table[gs][action_space[i_action]] > pick_value) { + pick_index = i_action; + pick_value = q_table[gs][action_space[pick_index]]; + } + } + + action = action_space[pick_index]; + } + + // If action in invalid list, ignore it and try another + if (std::count(invalid.begin(), invalid.end(), action) > 0) { + continue; + } + + // Generate command for action + command = generate_command(action, true); + + // Check action is valid + if (!game->check_option(&command)) { + // If invalid action for state, add to invalid list and try again + invalid.push_back(action); + continue; + + } else { + // Pick action + break; + } + } + + // Perform action + // (Exceptions intentionally not handled) + game->play_option(&command); + + // Measure reward (1 = win, -1 = loss, 0 = neither) + uint16_t reward; + + if (game->get_winner() == pturn) { + reward = 1; + } else if (game->get_winner() == popp) { + reward = -1; + } else { + reward = 0; + } + + // TODO update q_table + float q_value_former = q_table[gs][action]; + GameState gs_new; + get_game_state(&gs_new, game, pturn); + // if a winner: +1 for winning player, -1 for losing player +} diff --git a/src/caravan/main.cpp b/src/caravan/main.cpp index 3af94ff..0aa1b61 100644 --- a/src/caravan/main.cpp +++ b/src/caravan/main.cpp @@ -148,11 +148,7 @@ int main(int argc, char *argv[]) { view->run(); - view->close(); - user_abc->close(); - user_def->close(); - game->close(); - + // TODO smart pointers delete view; delete user_abc; delete user_def; diff --git a/src/caravan/model/caravan.cpp b/src/caravan/model/caravan.cpp index 74a0236..ae9ad8f 100644 --- a/src/caravan/model/caravan.cpp +++ b/src/caravan/model/caravan.cpp @@ -6,17 +6,13 @@ #include "caravan/core/common.h" #include "caravan/core/exceptions.h" -const std::string EXC_CLOSED = "Caravan is closed."; /** * Remove all cards from the caravan. * * @throws CaravanGameException Caravan track is empty. - * @throws CaravanFatalException Caravan is closed. */ void Caravan::clear() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (i_track == 0) { throw CaravanGameException("Cannot clear empty caravan."); } @@ -26,12 +22,8 @@ void Caravan::clear() { /** * @return Current bid. - * - * @throws CaravanFatalException Caravan is closed. */ uint16_t Caravan::get_bid() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - uint16_t bid; uint8_t value; uint8_t value_final; @@ -59,11 +51,8 @@ uint16_t Caravan::get_bid() { * @return Slot at position. * * @throws CaravanGameException Chosen card position is out of range. - * @throws CaravanFatalException Caravan is closed. */ Slot Caravan::get_slot(uint8_t pos) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (pos < TRACK_NUMERIC_MIN or pos > i_track) { throw CaravanGameException( "The chosen card position is out of range."); @@ -74,12 +63,8 @@ Slot Caravan::get_slot(uint8_t pos) { /** * @return Current caravan direction. - * - * @throws CaravanFatalException Caravan is closed. */ Direction Caravan::get_direction() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - Direction dir; int t_latest; int t_pen; @@ -127,34 +112,22 @@ Direction Caravan::get_direction() { /** * @return Caravan name. - * - * @throws CaravanFatalException Caravan is closed. */ CaravanName Caravan::get_name() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - return name; } /** * @return Current number of numeral cards in caravan. - * - * @throws CaravanFatalException Caravan is closed. */ uint8_t Caravan::get_size() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - return i_track; } /** * @return Current caravan suit. - * - * @throws CaravanFatalException Caravan is closed. */ Suit Caravan::get_suit() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - Suit last; int t; int f; @@ -189,11 +162,8 @@ Suit Caravan::get_suit() { * @throws CaravanGameException Caravan is at maximum numeral card capacity. * @throws CaravanGameException Numeral card has same rank as most recent card in caravan. * @throws CaravanGameException Numeral card does not follow direction of caravan. - * @throws CaravanFatalException Caravan is closed. */ void Caravan::put_numeral_card(Card card) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - Direction dir; Suit suit; bool ascends; @@ -247,11 +217,8 @@ void Caravan::put_numeral_card(Card card) { * @throws CaravanGameException No numeral card at chosen position. * @throws CaravanGameException Chosen card is not a face card. * @throws CaravanGameException Numeral card is at maximum face card capacity. - * @throws CaravanFatalException Caravan is closed. */ Card Caravan::put_face_card(Card card, uint8_t pos) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - uint8_t i; Card c_on; @@ -297,11 +264,8 @@ Card Caravan::put_face_card(Card card, uint8_t pos) { * removal. If 0, no card is excluded. * * @throws CaravanFatalException Exclude position is out of range. - * @throws CaravanFatalException Caravan is closed. */ void Caravan::remove_rank(Rank rank, uint8_t pos_exclude) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - uint8_t i_track_original; if (i_track == 0) { @@ -334,11 +298,8 @@ void Caravan::remove_rank(Rank rank, uint8_t pos_exclude) { * removal. If 0, no card is excluded. * * @throws CaravanFatalException Exclude position is out of range. - * @throws CaravanFatalException Caravan is closed. */ void Caravan::remove_suit(Suit suit, uint8_t pos_exclude) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - uint8_t i_track_original; if (i_track == 0) { @@ -363,17 +324,6 @@ void Caravan::remove_suit(Suit suit, uint8_t pos_exclude) { } } -/** - * Closes the caravan. - * - * @throws CaravanFatalException Caravan is closed. - */ -void Caravan::close() { - if (!closed) { - closed = true; - } -} - /* * PROTECTED */ @@ -383,7 +333,6 @@ void Caravan::close() { * @return An integer equivalent of the numeral, range: 1-10. * * @throws CaravanFatalException If a non-numeral rank is provided. - * @throws CaravanFatalException Caravan is closed. */ uint8_t Caravan::numeral_rank_to_uint8_t(Rank rank) { switch (rank) { diff --git a/src/caravan/model/game.cpp b/src/caravan/model/game.cpp index 0cf2edd..6770615 100644 --- a/src/caravan/model/game.cpp +++ b/src/caravan/model/game.cpp @@ -5,8 +5,6 @@ #include "caravan/model/game.h" #include "caravan/core/common.h" -const std::string EXC_CLOSED = "Game is closed."; - /** * @param config Game configuration. * @@ -31,27 +29,16 @@ Game::Game(GameConfig *gc) { pa_ptr = new Player(PLAYER_ABC, deck_bottom); pb_ptr = new Player(PLAYER_DEF, deck_top); - closed = false; p_turn = gc->player_first == pa_ptr->get_name() ? pa_ptr : pb_ptr; } -void Game::close() { - if (!closed) { - table_ptr->close(); - pa_ptr->close(); - pb_ptr->close(); - - delete table_ptr; - delete pa_ptr; - delete pb_ptr; - - closed = true; - } +Game::~Game() { + delete table_ptr; + delete pa_ptr; + delete pb_ptr; } Player *Game::get_player(PlayerName pname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (pa_ptr->get_name() == pname) { return pa_ptr; } @@ -64,8 +51,6 @@ Player *Game::get_player(PlayerName pname) { } PlayerCaravanNames Game::get_player_caravan_names(PlayerName pname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (pa_ptr->get_name() == pname) { return PlayerCaravanNames{CARAVAN_A, CARAVAN_B, CARAVAN_C}; } @@ -78,20 +63,14 @@ PlayerCaravanNames Game::get_player_caravan_names(PlayerName pname) { } PlayerName Game::get_player_turn() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - return p_turn->get_name(); } Table *Game::get_table() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - return table_ptr; } PlayerName Game::get_winner() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - uint8_t won_pa = 0; uint8_t won_pb = 0; int8_t comp[3]; @@ -141,13 +120,7 @@ PlayerName Game::get_winner() { return NO_PLAYER; } -bool Game::is_closed() { - return closed; -} - void Game::play_option(GameCommand *command) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (get_winner() != NO_PLAYER) { throw CaravanFatalException( "The game has already been won."); @@ -193,8 +166,6 @@ void Game::play_option(GameCommand *command) { } bool Game::is_caravan_winning(CaravanName cvname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if(cvname == NO_CARAVAN) { return false; } else { @@ -203,8 +174,6 @@ bool Game::is_caravan_winning(CaravanName cvname) { } bool Game::is_caravan_bust(CaravanName cvname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (cvname == NO_CARAVAN) { return false; } else { @@ -265,8 +234,6 @@ int8_t Game::compare_bids(CaravanName cvname1, CaravanName cvname2) { } CaravanName Game::winning_bid(CaravanName cvname1, CaravanName cvname2) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - int8_t bidcomp = compare_bids(cvname1, cvname2); if (bidcomp < 0) { diff --git a/src/caravan/model/player.cpp b/src/caravan/model/player.cpp index 27dad07..634b202 100644 --- a/src/caravan/model/player.cpp +++ b/src/caravan/model/player.cpp @@ -5,15 +5,12 @@ #include "caravan/model/player.h" #include "caravan/core/exceptions.h" -const std::string EXC_CLOSED = "Player is closed."; - Player::Player(PlayerName pn, Deck *d) { name = pn; deck = d; hand = {}; i_hand = 0; moves = 0; - closed = false; for (; i_hand < HAND_SIZE_MAX_START; i_hand++) { hand[i_hand] = deck->back(); @@ -21,17 +18,11 @@ Player::Player(PlayerName pn, Deck *d) { } } -void Player::close() { - if (!closed) { - delete deck; - - closed = true; - } +Player::~Player() { + delete deck; } Card Player::get_from_hand_at(uint8_t pos) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } - if (i_hand == 0) { throw CaravanFatalException("Player's hand is empty."); } @@ -44,37 +35,30 @@ Card Player::get_from_hand_at(uint8_t pos) { } Hand Player::get_hand() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } return hand; } uint16_t Player::get_moves_count() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } return moves; } PlayerName Player::get_name() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } return name; } uint8_t Player::get_size_deck() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } return deck->size(); } uint8_t Player::get_size_hand() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } return i_hand; } void Player::increment_moves() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } moves += 1; } void Player::maybe_add_card_to_hand() { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } // If more cards in the deck if (!deck->empty()) { // If post-Start and hand not at post-Start max (5 cards) @@ -88,7 +72,6 @@ void Player::maybe_add_card_to_hand() { } Card Player::discard_from_hand_at(uint8_t pos) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } uint8_t i; Card c_ret; diff --git a/src/caravan/model/table.cpp b/src/caravan/model/table.cpp index 8484604..f84fef3 100644 --- a/src/caravan/model/table.cpp +++ b/src/caravan/model/table.cpp @@ -5,33 +5,13 @@ #include "caravan/model/table.h" #include "caravan/core/exceptions.h" -const std::string EXC_CLOSED = "Table is closed."; - -/** - * The table on which caravan tracks are placed, as well as the decks and hands of both players. - */ -Table::Table() { - closed = false; -} - -void Table::close() { - if (!closed) { - a->close(); - b->close(); - c->close(); - d->close(); - e->close(); - f->close(); - - delete a; - delete b; - delete c; - delete d; - delete e; - delete f; - - closed = true; - } +Table::~Table() { + delete a; + delete b; + delete c; + delete d; + delete e; + delete f; } /** @@ -39,10 +19,8 @@ void Table::close() { * @return Pointer to the caravan. * * @throws CaravanFatalException Invalid caravan name. - * @throws CaravanFatalException Table is closed. */ Caravan *Table::get_caravan(CaravanName cvname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } switch (cvname) { case CARAVAN_A: return a; @@ -63,11 +41,8 @@ Caravan *Table::get_caravan(CaravanName cvname) { /** * @param cvname The caravan to clear. - * - * @throws CaravanFatalException Table is closed. */ void Table::clear_caravan(CaravanName cvname) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } get_caravan(cvname)->clear(); } @@ -77,10 +52,8 @@ void Table::clear_caravan(CaravanName cvname) { * @param pos The position of the numeral card on which to place the face card. * * @throws CaravanGameException QUEEN not played on latest numeral card in caravan. - * @throws CaravanFatalException Table is closed. */ void Table::play_face_card(CaravanName cvname, Card card, uint8_t pos) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } Caravan *cvn_target = get_caravan(cvname); if (card.rank == QUEEN and pos != cvn_target->get_size()) { @@ -122,10 +95,7 @@ void Table::play_face_card(CaravanName cvname, Card card, uint8_t pos) { /** * @param cvname A caravan name. * @param card A numeral card to place in the caravan. - * - * @throws CaravanFatalException Table is closed. */ void Table::play_numeral_card(CaravanName cvname, Card card) { - if (closed) { throw CaravanFatalException(EXC_CLOSED); } get_caravan(cvname)->put_numeral_card(card); } diff --git a/src/caravan/train.cpp b/src/caravan/train.cpp index 3409b55..64b5b7d 100644 --- a/src/caravan/train.cpp +++ b/src/caravan/train.cpp @@ -4,30 +4,34 @@ #include #include +#include #include #include #include "cxxopts.hpp" -#include "caravan/user/bot/train.h" - -const uint8_t FIRST_ABC = 1; -const uint8_t FIRST_DEF = 2; +#include "caravan/core/common.h" +#include "caravan/model/game.h" +#include "caravan/core/training.h" int main(int argc, char *argv[]) { - UserBotTrain *user_train; - PlayerName player_turn; - Game *game; + // Game and config + std::unique_ptr game; GameConfig gc; TrainConfig tc; uint8_t rand_first; - // Random player selector + // Training + QTable q_table; + ActionSpace action_space; + + // Random number generator std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> distr_first(FIRST_ABC, FIRST_DEF); try { - // Training parameters - // TODO user-defined arguments for these + // Fill action space with all possible actions + populate_action_space(&action_space); + + // Training parameters TODO user-defined arguments float discount = 0.95; float learning = 0.75; uint32_t episode_max = 10; @@ -49,13 +53,11 @@ int main(int argc, char *argv[]) { .episode = 1 }; - // Single bot plays as both players and is trained on both. - user_train = new UserBotTrain(); - for(; tc.episode <= tc.episode_max; tc.episode++) { // Random first player - rand_first = distr_first(gen); - gc.player_first = rand_first == FIRST_ABC ? PLAYER_ABC : PLAYER_DEF; + rand_first = dist_first_player(gen); + gc.player_first = rand_first == NUM_PLAYER_ABC ? + PLAYER_ABC : PLAYER_DEF; // Set training parameters tc.discount = discount; @@ -65,16 +67,13 @@ int main(int argc, char *argv[]) { tc.learning = learning; // Start a new game - game = new Game(&gc); + game = std::make_unique(&gc); - // Take turns until a winner is declared - while(game->get_winner() != NO_PLAYER) { - user_train->make_move_train(game, &tc); - } + // Train on game until completion + train_on_game(game.get(), q_table, action_space, tc, gen); - // Finish game - game->close(); - delete game; + // Close game + game.reset(); } } catch (CaravanException &e) { @@ -85,8 +84,4 @@ int main(int argc, char *argv[]) { printf("%s\n", e.what()); exit(EXIT_FAILURE); } - - user_train->close(); - - delete user_train; } diff --git a/src/caravan/user/bot/ai.cpp b/src/caravan/user/bot/ai.cpp index 52fe42d..33e363d 100644 --- a/src/caravan/user/bot/ai.cpp +++ b/src/caravan/user/bot/ai.cpp @@ -9,7 +9,5 @@ UserBotAI::UserBotAI(PlayerName pn) : UserBot(pn) { } std::string UserBotAI::request_move(Game *game) { - if (closed) { throw CaravanFatalException("Bot is closed."); } - - return "D1"; // TODO use q_table + return "D1"; // TODO use q_table, or random if state not in there } diff --git a/src/caravan/user/bot/factory.cpp b/src/caravan/user/bot/factory.cpp index 3d7f1a4..52597a1 100644 --- a/src/caravan/user/bot/factory.cpp +++ b/src/caravan/user/bot/factory.cpp @@ -28,4 +28,4 @@ UserBot* BotFactory::get(std::string name, PlayerName player_name) { else { throw CaravanFatalException("Unknown bot name '" + name + "'."); } -} \ No newline at end of file +} diff --git a/src/caravan/user/bot/friendly.cpp b/src/caravan/user/bot/friendly.cpp index 8fe4a41..d55fba3 100644 --- a/src/caravan/user/bot/friendly.cpp +++ b/src/caravan/user/bot/friendly.cpp @@ -10,8 +10,6 @@ */ std::string UserBotFriendly::request_move(Game *game) { - if (closed) { throw CaravanFatalException("Bot is closed."); } - std::string move = generate_move(game, true, false, true); // Return move if able to generate one diff --git a/src/caravan/user/bot/normal.cpp b/src/caravan/user/bot/normal.cpp index 912127b..8a399fc 100644 --- a/src/caravan/user/bot/normal.cpp +++ b/src/caravan/user/bot/normal.cpp @@ -195,15 +195,7 @@ std::string UserBotNormal::generate_move( * PUBLIC */ -void UserBotNormal::close() { - if (!closed) { - closed = true; - } -} - std::string UserBotNormal::request_move(Game *game) { - if (closed) { throw CaravanFatalException("Bot is closed."); } - std::string move = generate_move(game, true, true, true); // Return move if able to generate one diff --git a/src/caravan/user/bot/train.cpp b/src/caravan/user/bot/train.cpp deleted file mode 100644 index b12e96b..0000000 --- a/src/caravan/user/bot/train.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2022-2024 r3w0p -// The following code can be redistributed and/or -// modified under the terms of the GPL-3.0 License. - -#include -#include -#include -#include -#include -#include -#include "caravan/user/bot/train.h" -#include "caravan/core/training.h" - -UserBotTrain::UserBotTrain() : UserBot(NO_PLAYER) { - // Empty by default and populated during training - q_table = {}; - populate_action_space(&action_space); -} - -std::string UserBotTrain::make_move_train(Game *game, TrainConfig *tc) { - if (closed) { throw CaravanFatalException("Bot is closed."); } - - // Get name of player whose turn it is - PlayerName pname = game->get_player_turn(); - - // Read game state and maybe add to the q-table if not present - GameState gs; - get_game_state(&gs, game, pname); - - if (!q_table.contains(gs)) { - // TODO maybe is this needed: q_table[gs] = {}; - for(uint16_t i = 0; i < SIZE_ACTION_SPACE; i++) { - q_table[gs][action_space[i]] = 0; - } - } - - // Choose an action - std::random_device rd; - std::mt19937 gen(rd()); - - std::uniform_real_distribution<> distr_explore(0, 1); - std::uniform_int_distribution<> distr_action(0, SIZE_ACTION_SPACE-1); - - bool explore = distr_explore(gen) < tc->explore; - std::string action; - - if(explore) { - // If exploring, fetch a random action from the action space - action = action_space[distr_action(gen)]; - - } else { - // Otherwise, pick the optimal action from the q-table - // (Or random action if all actions are equal in value) - // TODO - } - - // TODO perform action - - // TODO measure reward (1 = win, -1 = loss, 0 = neither) - - // TODO update q_table - // if a winner: +1 for winning player, -1 for losing player - - return "D1"; // TODO -} diff --git a/src/caravan/view/view.cpp b/src/caravan/view/view.cpp index 91be48a..9978005 100644 --- a/src/caravan/view/view.cpp +++ b/src/caravan/view/view.cpp @@ -8,7 +8,6 @@ View::View(ViewConfig *vc, Game *game) { this->vc = vc; this->game = game; - this->closed = false; if(vc->user_abc == nullptr || vc->user_def == nullptr) { throw CaravanFatalException("Users must be provided to view."); diff --git a/src/caravan/view/view_tui.cpp b/src/caravan/view/view_tui.cpp index 32d3749..080b4fc 100644 --- a/src/caravan/view/view_tui.cpp +++ b/src/caravan/view/view_tui.cpp @@ -172,249 +172,6 @@ void push_card(ViewConfig *vc, ftxui::Elements *e, Card card, bool lead) { } } -void process_first(std::string input, GameCommand *command) { - char c = input.at(0); // minimum input size already checked elsewhere - - switch (c) { - case 'P': - case 'p': - command->option = OPTION_PLAY; - /* - * P2F - * "Play numeral card at hand pos 2 onto caravan F" - * - * P4F8 - * "Play face card at hand pos 4 onto caravan F, slot 8" - */ - break; - - case 'D': - case 'd': - command->option = OPTION_DISCARD; - /* - * D3 - * "Discard card at hand pos 3" - */ - break; - - case 'C': - case 'c': - /* - * CE - * "Clear caravan E" - */ - command->option = OPTION_CLEAR; - break; - - default: - throw CaravanInputException( - "Invalid option '" + std::string(1, c) + "', must be one of: (P)lay, (D)iscard, (C)lear."); - } -} - -void process_second(std::string input, GameCommand *command) { - if (command->option == OPTION_PLAY or command->option == OPTION_DISCARD) { - - if (input.size() < 2) { - throw CaravanInputException("A hand position has not been entered."); - } - - char c = input.at(1); - - switch (c) { - case '1': - command->pos_hand = 1; - break; - case '2': - command->pos_hand = 2; - break; - case '3': - command->pos_hand = 3; - break; - case '4': - command->pos_hand = 4; - break; - case '5': - command->pos_hand = 5; - break; - case '6': - command->pos_hand = 6; - break; - case '7': - command->pos_hand = 7; - break; - case '8': - command->pos_hand = 8; - break; - default: - throw CaravanInputException("Invalid hand position '" + std::string(1, c) + "'."); - } - - } else if (command->option == OPTION_CLEAR) { - - if (input.size() < 2) { - throw CaravanInputException("A caravan name has not been entered."); - } - - char c = input.at(1); - - switch (c) { - case 'A': - case 'a': - command->caravan_name = CARAVAN_A; - break; - case 'B': - case 'b': - command->caravan_name = CARAVAN_B; - break; - case 'C': - case 'c': - command->caravan_name = CARAVAN_C; - break; - case 'D': - case 'd': - command->caravan_name = CARAVAN_D; - break; - case 'E': - case 'e': - command->caravan_name = CARAVAN_E; - break; - case 'F': - case 'f': - command->caravan_name = CARAVAN_F; - break; - default: - throw CaravanInputException("Invalid caravan name '" + std::string(1, c) + "', must be between: A-F."); - } - - } // else invalid command type, handled during parse of first character -} - -void process_third(std::string input, GameCommand *command) { - if (command->option == OPTION_PLAY) { - - if (input.size() < 3) { - throw CaravanInputException("A caravan name has not been entered."); - } - - char c = input.at(2); - - switch (c) { - case 'A': - case 'a': - command->caravan_name = CARAVAN_A; - break; - case 'B': - case 'b': - command->caravan_name = CARAVAN_B; - break; - case 'C': - case 'c': - command->caravan_name = CARAVAN_C; - break; - case 'D': - case 'd': - command->caravan_name = CARAVAN_D; - break; - case 'E': - case 'e': - command->caravan_name = CARAVAN_E; - break; - case 'F': - case 'f': - command->caravan_name = CARAVAN_F; - break; - default: - throw CaravanInputException("Invalid caravan name '" + std::string(1, c) + "', must be between: A-F."); - } - } -} - -void process_fourth(std::string input, GameCommand *command) { - if (command->option == OPTION_PLAY) { - - if (input.size() < 4) { return; } // optional, not an error - - char c = input.at(3); - - switch (c) { - case '1': - command->pos_caravan = 1; - break; - case '2': - command->pos_caravan = 2; - break; - case '3': - command->pos_caravan = 3; - break; - case '4': - command->pos_caravan = 4; - break; - case '5': - command->pos_caravan = 5; - break; - case '6': - command->pos_caravan = 6; - break; - case '7': - command->pos_caravan = 7; - break; - case '8': - command->pos_caravan = 8; - break; - default: - throw CaravanInputException("Invalid caravan position '" + std::string(1, c) + "'."); - } - } -} - -GameCommand ViewTUI::parse_user_input(std::string input, bool confirmed) { - GameCommand command; - - if (closed) { return command; } - if (input.empty()) { return command; } - - try { - /* - * FIRST - * - COMMAND TYPE - */ - process_first(input, &command); - - /* - * SECOND - * - HAND POSITION or - * - CARAVAN NAME - */ - process_second(input, &command); - - /* - * THIRD - * - CARAVAN NAME - */ - process_third(input, &command); - - /* - * FOURTH - * - CARAVAN POSITION (used when selecting Face card only) - */ - process_fourth(input, &command); - - } catch(CaravanInputException &e) { - if(confirmed) { - // For confirmed commands: throw to other handling that prints - // command errors to the player - throw; - } else { - // For unconfirmed commands: accept whatever was able to be parsed - // so that it can be used for highlighting the game board - return command; - } - } - - return command; -} - std::shared_ptr gen_position(uint8_t position, bool blank = false) { using namespace ftxui; return text(blank ? "" : std::to_string(position)) | borderEmpty | color(Color::Default) | size(WIDTH, EQUAL, WIDTH_POSITION) | size(HEIGHT, EQUAL, HEIGHT_POSITION); @@ -858,8 +615,6 @@ void set_current_turn(ViewConfig *vc, Game *game) { void ViewTUI::run() { using namespace ftxui; - if (closed) { return; } - // Screen config Dimensions terminal_size{}; @@ -924,8 +679,6 @@ void ViewTUI::run() { screen.SetCursor(Screen::Cursor({.shape=Screen::Cursor::Hidden})); try { - if (closed) { return gen_closed(vc); } - // Reset values terminal_size = Terminal::Size(); set_current_turn(vc, game); @@ -985,11 +738,11 @@ void ViewTUI::run() { try { if(confirmed) { // Parse raw command to get usable command - vc->command = parse_user_input(raw_command, confirmed); + vc->command = generate_command(raw_command, confirmed); } else { // An incomplete command that can be used to highlight // areas of the board as a hint to the player - vc->highlight = parse_user_input(raw_command, confirmed); + vc->highlight = generate_command(raw_command, confirmed); } raw_command = ""; @@ -1031,13 +784,11 @@ void ViewTUI::run() { } catch (CaravanException &e) { // Close gracefully on any unhandled exceptions - closed = true; vc->msg_fatal = e.what(); return gen_closed(vc); } catch (std::exception &e) { // Close gracefully on any unhandled exceptions - closed = true; vc->msg_fatal = "A fatal error occurred."; return gen_closed(vc); } @@ -1054,9 +805,3 @@ void ViewTUI::run() { screen.Loop(renderer); screen.Clear(); } - -void ViewTUI::close() { - if (!closed) { - closed = true; - } -} diff --git a/test/caravan/model/test_game.cpp b/test/caravan/model/test_game.cpp index a88d7d4..edbfa49 100644 --- a/test/caravan/model/test_game.cpp +++ b/test/caravan/model/test_game.cpp @@ -6,19 +6,6 @@ #include "caravan/model/game.h" -TEST (TestGame, Close) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - Game g{&gc}; - - ASSERT_FALSE(g.is_closed()); - g.close(); - ASSERT_TRUE(g.is_closed()); -} - TEST (TestGame, GetPlayer_Both) { GameConfig gc = { 30, 1, true, @@ -31,27 +18,6 @@ TEST (TestGame, GetPlayer_Both) { ASSERT_EQ(g.get_player(PLAYER_DEF)->get_name(), PLAYER_DEF); } -TEST (TestGame, GetPlayer_Error_AlreadyClosed) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - Game g{&gc}; - - g.close(); - - try { - g.get_player(PLAYER_ABC); - FAIL(); - - } catch (CaravanFatalException &e) { - - } catch (...) { - FAIL(); - } -} - TEST (TestGame, GetPlayer_Error_InvalidName) { GameConfig gc = { 30, 1, true, @@ -82,48 +48,6 @@ TEST (TestGame, GetPlayerTurn) { ASSERT_EQ(g.get_player_turn(), PLAYER_ABC); } -TEST (TestGame, GetPlayerTurn_Error_AlreadyClosed) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - Game g{&gc}; - - g.close(); - - try { - g.get_player_turn(); - FAIL(); - - } catch (CaravanFatalException &e) { - - } catch (...) { - FAIL(); - } -} - -TEST (TestGame, GetTable_Error_AlreadyClosed) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - Game g{&gc}; - - g.close(); - - try { - g.get_table(); - FAIL(); - - } catch (CaravanFatalException &e) { - - } catch (...) { - FAIL(); - } -} - TEST (TestGame, GetWinner_NoMoves) { GameConfig gc = { 30, 1, true, @@ -135,49 +59,6 @@ TEST (TestGame, GetWinner_NoMoves) { ASSERT_EQ(g.get_winner(), NO_PLAYER); } -TEST (TestGame, GetWinner_Error_AlreadyClosed) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - Game g{&gc}; - - g.close(); - - try { - g.get_winner(); - FAIL(); - - } catch (CaravanFatalException &e) { - - } catch (...) { - FAIL(); - } -} - -TEST (TestGame, PlayOption_Error_AlreadyClosed) { - GameConfig gc = { - 30, 1, true, - 30, 1, true, - PLAYER_ABC - }; - GameCommand command = {OPTION_DISCARD, 1, NO_CARAVAN, 0}; - Game g{&gc}; - - g.close(); - - try { - g.play_option(&command); - FAIL(); - - } catch (CaravanFatalException &e) { - - } catch (...) { - FAIL(); - } -} - TEST (TestGame, PlayOption_Error_StartRound_Remove) { GameConfig gc = { 30, 1, true, diff --git a/test/caravan/model/test_player.cpp b/test/caravan/model/test_player.cpp index 364105c..c9b9351 100644 --- a/test/caravan/model/test_player.cpp +++ b/test/caravan/model/test_player.cpp @@ -12,7 +12,7 @@ TEST (TestPlayer, GetFromHandAt_Position1) { Player pl = Player(PLAYER_ABC, d); Card c_get; Card c_take; - Card c_getagain; + Card c_get_again; ASSERT_EQ(pl.get_size_hand(), 8); @@ -22,9 +22,9 @@ TEST (TestPlayer, GetFromHandAt_Position1) { ASSERT_EQ(pl.get_size_hand(), 8); ASSERT_TRUE(c_get.suit == c_take.suit and c_get.rank == c_take.rank); - c_getagain = pl.get_hand()[0]; + c_get_again = pl.get_hand()[0]; ASSERT_TRUE( - c_getagain.suit == c_take.suit and c_getagain.rank == c_take.rank); + c_get_again.suit == c_take.suit and c_get_again.rank == c_take.rank); } TEST (TestPlayer, GetName) { @@ -119,7 +119,7 @@ TEST (TestPlayer, RemoveFromHandAt_Position1_StartRound) { Player pl = Player(PLAYER_ABC, d); Card c_get; Card c_take; - Card c_getagain; + Card c_get_again; ASSERT_EQ(pl.get_size_hand(), 8); @@ -132,9 +132,9 @@ TEST (TestPlayer, RemoveFromHandAt_Position1_StartRound) { ASSERT_TRUE(c_get.suit == c_take.suit and c_get.rank == c_take.rank); - c_getagain = pl.get_hand()[0]; - ASSERT_TRUE(c_getagain.suit != c_take.suit or - c_getagain.rank != c_take.rank); + c_get_again = pl.get_hand()[0]; + ASSERT_TRUE(c_get_again.suit != c_take.suit or + c_get_again.rank != c_take.rank); } TEST (TestPlayer, RemoveFromHandAt_Error_HandEmpty) {