From 7ed3882f0148538f7bd1b1fa61ef3aa9afc2b64f Mon Sep 17 00:00:00 2001 From: r3w0p Date: Tue, 28 May 2024 15:57:03 +0100 Subject: [PATCH 1/4] -v --version and help update --- CMakeLists.txt | 14 +++++++++++--- README | 2 +- src/caravan/main.cpp | 26 +++++++++++++++++++------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bb7ec2..f908b08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,14 @@ cmake_minimum_required(VERSION 3.27) -project(caravan LANGUAGES C CXX) +project(Caravan LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(PROJECT_VERSION 1.0.1) -set(PROJECT_COPYRIGHT "Copyright (c) 2022-2024 r3w0p") +set(PROJECT_VERSION 1.1.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") IF (WIN32 OR WIN64) @@ -105,6 +105,14 @@ add_executable(caravan "src/caravan/main.cpp" ) +target_compile_definitions(caravan + PRIVATE CARAVAN_NAME="${PROJECT_NAME}" + PRIVATE CARAVAN_VERSION="${PROJECT_VERSION}" + PRIVATE CARAVAN_DESCRIPTION="${PROJECT_DESCRIPTION}" + PRIVATE CARAVAN_COPYRIGHT="${PROJECT_COPYRIGHT}" + PRIVATE CARAVAN_URL="${PROJECT_URL}" +) + target_link_libraries(caravan PRIVATE core PRIVATE model diff --git a/README b/README index 6d8a8d9..b79fd72 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ | (_| (_| | | | (_| |\ \/ / (_| | | | | \___\__,_|_| \__,_| \__/ \__,_|_| |_| -| v1.0.1 | GPL-3.0 | (c) 2022-2024 r3w0p | +| v1.1.0 | GPL-3.0 | (c) 2022-2024 r3w0p | A command-line version of the Caravan card game from Fallout: New Vegas. diff --git a/src/caravan/main.cpp b/src/caravan/main.cpp index 49e1cdc..85ee1ee 100644 --- a/src/caravan/main.cpp +++ b/src/caravan/main.cpp @@ -3,10 +3,15 @@ // modified under the terms of the GPL-3.0 License. #include -#include +#include "cxxopts.hpp" #include "caravan/view/view_tui.h" #include "caravan/user/bot/factory.h" +const std::string OPTS_HELP = "h,help"; +const std::string OPTS_VERSION = "v,version"; + +const std::string KEY_HELP = "help"; +const std::string KEY_VERSION = "version"; const uint8_t FIRST_ABC = 1; const uint8_t FIRST_DEF = 2; @@ -19,13 +24,11 @@ int main(int argc, char *argv[]) { ViewTUI *view; try { - cxxopts::Options options( - "caravan", - "Caravan: A command-line version of " - "the Caravan card game from Fallout: New Vegas."); + cxxopts::Options options(CARAVAN_NAME); options.add_options() - ("h,help", "Print help instructions.") + (OPTS_HELP, "Print help instructions.") + (OPTS_VERSION, "Print help instructions.") ("pvp", "A Player vs Player game.") ("bvb", "A Bot vs Bot game.") ("b,bot", "Which bot to play with.", cxxopts::value()->default_value("normal")) @@ -42,11 +45,20 @@ int main(int argc, char *argv[]) { auto result = options.parse(argc, argv); // Print help instructions. - if (result.count("help")) { + if (result.count(KEY_HELP)) { + printf("%s v%s\n\n", CARAVAN_NAME, CARAVAN_VERSION); + printf("%s\n", CARAVAN_DESCRIPTION); + printf("%s\n", CARAVAN_COPYRIGHT); + printf("%s\n", CARAVAN_URL); printf("%s", options.help().c_str()); exit(EXIT_SUCCESS); } + if (result.count(KEY_VERSION)) { + printf("%s\n", CARAVAN_VERSION); + exit(EXIT_SUCCESS); + } + bool pvp = result["pvp"].as(); bool bots = result["bvb"].as(); std::string bot = result["bot"].as(); From 3ec338580f85f31504a9b50d39759029eb3ab35b Mon Sep 17 00:00:00 2001 From: r3w0p Date: Wed, 29 May 2024 13:07:55 +0100 Subject: [PATCH 2/4] tests --- .github/workflows/build.yml | 10 ---------- .github/workflows/tests.yml | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76327a8..b12aff6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,11 +14,6 @@ jobs: strategy: matrix: include: - - name: Linux Clang - os: ubuntu-latest - compiler_cc: clang - compiler_cpp: clang++ - - name: Linux GCC os: ubuntu-latest compiler_cc: gcc @@ -32,11 +27,6 @@ jobs: # compiler_c: clang # compiler_cpp: clang++ - - name: Windows Clang - os: windows-latest - compiler_cc: clang - compiler_cpp: clang++ - - name: Windows GCC os: windows-latest compiler_cc: gcc diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..53e555c --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,40 @@ +name: Tests + +on: + push: + branches: [ "1.1.0" ] + +env: + BUILD_TYPE: Debug + +jobs: + tests: + name: Tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - name: Linux GCC + os: ubuntu-latest + compiler_cc: gcc + compiler_cpp: g++ + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install CMake and Ninja + uses: lukka/get-cmake@latest + with: + cmakeVersion: "~3.27.0" # use most recent 3.27.x version + ninjaVersion: "^1.0" # use most recent 1.x version + + - name: CMake Setup + run: cmake -S . -B ${{github.workspace}}/build -G Ninja -D CMAKE_C_COMPILER=${{matrix.compiler_cc}} CMAKE_CXX_COMPILER=${{matrix.compiler_cpp}} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: CMake Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target tests + + - name: Run Tests + working-directory: ./build + run: ctest --output-on-failure From 26d20e69dbbc075d3b6a72d709602d0cf7902cd2 Mon Sep 17 00:00:00 2001 From: r3w0p Date: Wed, 29 May 2024 13:16:10 +0100 Subject: [PATCH 3/4] windows / linux / testing --- .github/workflows/linux.yml | 41 ++++++++++++++++++++ .github/workflows/{tests.yml => testing.yml} | 6 +-- .github/workflows/{build.yml => windows.yml} | 20 +++------- 3 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/linux.yml rename .github/workflows/{tests.yml => testing.yml} (95%) rename .github/workflows/{build.yml => windows.yml} (65%) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..1f0f524 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,41 @@ +name: Linux + +on: + push: + branches: [ "1.1.0" ] + +env: + BUILD_TYPE: Release + +jobs: + build: + name: Build + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - name: Linux Clang + os: ubuntu-latest + compiler_cc: clang + compiler_cpp: clang++ + + - name: Linux GCC + os: ubuntu-latest + compiler_cc: gcc + compiler_cpp: g++ + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install CMake and Ninja + uses: lukka/get-cmake@latest + with: + cmakeVersion: "~3.27.0" # use most recent 3.27.x version + ninjaVersion: "^1.0" # use most recent 1.x version + + - name: CMake Setup + run: cmake -S . -B ${{github.workspace}}/build -G Ninja -D CMAKE_C_COMPILER=${{matrix.compiler_cc}} CMAKE_CXX_COMPILER=${{matrix.compiler_cpp}} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: CMake Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target caravan diff --git a/.github/workflows/tests.yml b/.github/workflows/testing.yml similarity index 95% rename from .github/workflows/tests.yml rename to .github/workflows/testing.yml index 53e555c..f88620c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/testing.yml @@ -1,4 +1,4 @@ -name: Tests +name: Testing on: push: @@ -8,8 +8,8 @@ env: BUILD_TYPE: Debug jobs: - tests: - name: Tests + testing: + name: Testing runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/.github/workflows/build.yml b/.github/workflows/windows.yml similarity index 65% rename from .github/workflows/build.yml rename to .github/workflows/windows.yml index b12aff6..6443710 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/windows.yml @@ -1,8 +1,8 @@ -name: Build +name: Windows on: push: - branches: [ main ] + branches: [ "1.1.0" ] env: BUILD_TYPE: Release @@ -14,18 +14,10 @@ jobs: strategy: matrix: include: - - name: Linux GCC - os: ubuntu-latest - compiler_cc: gcc - compiler_cpp: g++ - - # Commented out due to seemingly unresolvable issue possibly caused by FTXUI: - # "Target "component" links to Threads::Threads but the target was not found." - # - #- name: MacOS Clang - # os: macos-latest - # compiler_c: clang - # compiler_cpp: clang++ + - name: Windows Clang + os: windows-latest + compiler_cc: clang + compiler_cpp: clang++ - name: Windows GCC os: windows-latest From 47ab34cfba554f20c59a9923f75e1b6dfb1cfb82 Mon Sep 17 00:00:00 2001 From: r3w0p Date: Wed, 29 May 2024 21:25:21 +0100 Subject: [PATCH 4/4] 1.1.0 --- .github/workflows/linux.yml | 19 +++++---- .github/workflows/testing.yml | 2 +- .github/workflows/windows.yml | 19 +++++---- CMakeLists.txt | 2 + include/caravan/user/bot/friendly.h | 17 ++++++++ include/caravan/user/bot/normal.h | 2 + src/caravan/main.cpp | 2 +- src/caravan/user/bot/factory.cpp | 3 ++ src/caravan/user/bot/friendly.cpp | 22 ++++++++++ src/caravan/user/bot/normal.cpp | 62 ++++++++++++++++++----------- 10 files changed, 111 insertions(+), 39 deletions(-) create mode 100644 include/caravan/user/bot/friendly.h create mode 100644 src/caravan/user/bot/friendly.cpp diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 1f0f524..51f3669 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,8 +1,8 @@ name: Linux on: - push: - branches: [ "1.1.0" ] + release: + types: [ created ] env: BUILD_TYPE: Release @@ -14,11 +14,6 @@ jobs: strategy: matrix: include: - - name: Linux Clang - os: ubuntu-latest - compiler_cc: clang - compiler_cpp: clang++ - - name: Linux GCC os: ubuntu-latest compiler_cc: gcc @@ -39,3 +34,13 @@ jobs: - name: CMake Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target caravan + + - name: Rename Executable + working-directory: ./build + run: mv caravan.exe caravan_linux_x64 + + - name: Upload Executable to Release + uses: AButler/upload-release-assets@v3.0 + with: + files: ./build/caravan_linux_x64 + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index f88620c..dddccf9 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -2,7 +2,7 @@ name: Testing on: push: - branches: [ "1.1.0" ] + branches: [ main ] env: BUILD_TYPE: Debug diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 6443710..d8f3a4d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,8 +1,8 @@ name: Windows on: - push: - branches: [ "1.1.0" ] + release: + types: [ created ] env: BUILD_TYPE: Release @@ -14,11 +14,6 @@ jobs: strategy: matrix: include: - - name: Windows Clang - os: windows-latest - compiler_cc: clang - compiler_cpp: clang++ - - name: Windows GCC os: windows-latest compiler_cc: gcc @@ -39,3 +34,13 @@ jobs: - name: CMake Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target caravan + + - name: Rename Executable + working-directory: ./build + run: mv caravan.exe caravan_windows_x64.exe + + - name: Upload Executable to Release + uses: AButler/upload-release-assets@v3.0 + with: + files: ./build/caravan_windows_x64.exe + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index f908b08..fa5c837 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,9 +80,11 @@ add_library(user "include/caravan/user/user.h" "include/caravan/user/bot/factory.h" "include/caravan/user/bot/normal.h" + "include/caravan/user/bot/friendly.h" "src/caravan/user/bot/factory.cpp" "src/caravan/user/bot/normal.cpp" + "src/caravan/user/bot/friendly.cpp" ) add_library(view diff --git a/include/caravan/user/bot/friendly.h b/include/caravan/user/bot/friendly.h new file mode 100644 index 0000000..f1c9ac7 --- /dev/null +++ b/include/caravan/user/bot/friendly.h @@ -0,0 +1,17 @@ +// 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_FRIENDLY_H +#define CARAVAN_USER_BOT_FRIENDLY_H + +#include "caravan/user/bot/normal.h" + +class UserBotFriendly : public UserBotNormal { +public: + explicit UserBotFriendly(PlayerName pn) : UserBotNormal(pn){}; + + std::string request_move(Game *game) override; +}; + +#endif //CARAVAN_USER_BOT_FRIENDLY_H diff --git a/include/caravan/user/bot/normal.h b/include/caravan/user/bot/normal.h index 2680aea..4cb4c5a 100644 --- a/include/caravan/user/bot/normal.h +++ b/include/caravan/user/bot/normal.h @@ -8,6 +8,8 @@ #include "caravan/user/user.h" class UserBotNormal : public UserBot { +protected: + std::string generate_move(Game *game, bool allow_numeral, bool allow_face, bool allow_clear); public: explicit UserBotNormal(PlayerName pn) : UserBot(pn){}; diff --git a/src/caravan/main.cpp b/src/caravan/main.cpp index 85ee1ee..6d52423 100644 --- a/src/caravan/main.cpp +++ b/src/caravan/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { (OPTS_VERSION, "Print help instructions.") ("pvp", "A Player vs Player game.") ("bvb", "A Bot vs Bot game.") - ("b,bot", "Which bot to play with.", cxxopts::value()->default_value("normal")) + ("b,bot", "Which bot to play with (normal, friendly).", cxxopts::value()->default_value("normal")) ("d,delay", "Delay before bot makes its move (in seconds).", cxxopts::value()->default_value("1.0")) ("f,first", "Which player goes first (1 or 2).", cxxopts::value()->default_value("1")) ("c,cards", "Number of cards for each caravan deck (30-162, inclusive).", cxxopts::value()->default_value("54")) diff --git a/src/caravan/user/bot/factory.cpp b/src/caravan/user/bot/factory.cpp index 65991f5..ff24969 100644 --- a/src/caravan/user/bot/factory.cpp +++ b/src/caravan/user/bot/factory.cpp @@ -8,8 +8,10 @@ #include "caravan/user/user.h" #include "caravan/user/bot/factory.h" #include "caravan/user/bot/normal.h" +#include "caravan/user/bot/friendly.h" const std::string NAME_NORMAL = "normal"; +const std::string NAME_FRIENDLY = "friendly"; UserBot* BotFactory::get(std::string name, PlayerName player_name) { // Set name to lowercase @@ -19,6 +21,7 @@ UserBot* BotFactory::get(std::string name, PlayerName player_name) { // Return bot that matches name, or fail if(name == NAME_NORMAL) { return new UserBotNormal(player_name); } + if(name == NAME_FRIENDLY) { return new UserBotFriendly(player_name); } else { throw CaravanFatalException("Unknown bot name '" + name + "'."); } diff --git a/src/caravan/user/bot/friendly.cpp b/src/caravan/user/bot/friendly.cpp new file mode 100644 index 0000000..8fe4a41 --- /dev/null +++ b/src/caravan/user/bot/friendly.cpp @@ -0,0 +1,22 @@ +// 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 "caravan/user/bot/friendly.h" + +/* + * PUBLIC + */ + +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 + if (!move.empty()) { return move; } + + // If no useful move could be made, discard first card in hand + return "D1"; +} diff --git a/src/caravan/user/bot/normal.cpp b/src/caravan/user/bot/normal.cpp index 0612133..912127b 100644 --- a/src/caravan/user/bot/normal.cpp +++ b/src/caravan/user/bot/normal.cpp @@ -10,7 +10,6 @@ */ const std::string PLAY = "P"; -const std::string DISCARD = "D"; const std::string CLEAR = "C"; uint8_t pos_card_numeral(Player *p) { @@ -27,20 +26,14 @@ uint8_t pos_card_numeral(Player *p) { } /* - * PUBLIC + * PROTECTED */ -void UserBotNormal::close() { - if (!closed) { - closed = true; - } -} - -std::string UserBotNormal::request_move(Game *game) { - if (game->is_closed()) { - throw CaravanFatalException("The game has already closed."); - } - +std::string UserBotNormal::generate_move( + Game *game, + bool allow_numeral, + bool allow_face, + bool allow_clear) { Player *me = game->get_player(name); uint8_t my_hand_size = me->get_size_hand(); @@ -72,12 +65,14 @@ std::string UserBotNormal::request_move(Game *game) { Table *table = game->get_table(); // Clear any caravans that are bust or full of cards - for (uint8_t i_cvn = 0; i_cvn < PLAYER_CARAVANS_MAX; i_cvn++) { - Caravan *cvn = table->get_caravan(my_cvns[i_cvn]); + if(allow_clear) { + for (uint8_t i_cvn = 0; i_cvn < PLAYER_CARAVANS_MAX; i_cvn++) { + Caravan *cvn = table->get_caravan(my_cvns[i_cvn]); - if (cvn->get_bid() > CARAVAN_SOLD_MAX || - cvn->get_size() == TRACK_NUMERIC_MAX) { - return CLEAR + caravan_letter(my_cvns[i_cvn]); + if (cvn->get_bid() > CARAVAN_SOLD_MAX || + cvn->get_size() == TRACK_NUMERIC_MAX) { + return CLEAR + caravan_letter(my_cvns[i_cvn]); + } } } @@ -85,7 +80,7 @@ std::string UserBotNormal::request_move(Game *game) { for (uint8_t pos_hand = 1; pos_hand <= my_hand_size; pos_hand++) { Card c_hand = me->get_from_hand_at(pos_hand); - if (is_numeral_card(c_hand)) { + if (is_numeral_card(c_hand) && allow_numeral) { // If numeral, look through caravans for (uint8_t i = 0; i < PLAYER_CARAVANS_MAX; ++i) { Caravan *my_cvn = table->get_caravan(my_cvns[i]); @@ -154,7 +149,7 @@ std::string UserBotNormal::request_move(Game *game) { } } - } else { // is face card + } else if(allow_face) { // is face card uint8_t i_opp_cvn_most_cards = PLAYER_CARAVANS_MAX; uint8_t n_opp_cvn_most_cards = 0; @@ -193,6 +188,27 @@ std::string UserBotNormal::request_move(Game *game) { } } - // Bot cannot make any of the other moves, so discard first card in hand - return DISCARD + "1"; -} \ No newline at end of file + return ""; +} + +/* + * 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 + if(!move.empty()) { return move; } + + // If no useful move could be made, discard first card in hand + return "D1"; +}