| @@ -18,6 +18,7 @@ blackjack_LDADD = $(all_libraries) | |||
| blackjack_SOURCES = \ | |||
| src/main.cpp \ | |||
| src/conf.cpp \ | |||
| src/version.cpp \ | |||
| src/blackjack.cpp \ | |||
| src/cards.cpp \ | |||
| src/stdinout.cpp \ | |||
| @@ -1,3 +1,4 @@ | |||
| flat_bet = 1 | |||
| max_bet = 2 | |||
| arranged_cards = 5,0,7,10 | |||
| @@ -28,6 +28,12 @@ | |||
| #include <random> | |||
| #include <cmath> | |||
| namespace Libreblackjack { | |||
| void shortversion(void); | |||
| void help(const char *); | |||
| void copyright(void); | |||
| } | |||
| // TODO: namespace | |||
| enum class DealerAction { | |||
| @@ -53,17 +53,15 @@ Blackjack::Blackjack(Configuration &conf) : rng(dev_random()), fiftyTwoCards(0, | |||
| conf.set(&shuffle_every_hand, {"shuffle_every_hand"}); | |||
| if (conf.exists("arranged_cards")) { | |||
| std::istringstream x(conf.getString("arranged_cads")); | |||
| std::list<std::string> chunks; | |||
| std::copy(std::istream_iterator<std::string>(x), std::istream_iterator<std::string>(), std::back_inserter(chunks)); | |||
| for (auto it : chunks) { | |||
| arranged_cards.push_back(std::stoi(it)); | |||
| std::istringstream stream(conf.getString("arranged_cards")); | |||
| std::string token; | |||
| while(std::getline(stream, token, ',')) { | |||
| arranged_cards.push_back(std::stoi(token)); | |||
| } | |||
| } | |||
| // TODO: what's this? | |||
| conf.set(&infinite_decks_card_number_for_arranged_ones, {"infinite_decks_card_number_for_arranged_ones"}); | |||
| n_arranged_cards = arranged_cards.size(); | |||
| bool explicit_seed = conf.set(&rng_seed, {"rng_seed", "seed"}); | |||
| if (explicit_seed) { | |||
| @@ -104,7 +102,8 @@ void Blackjack::deal(Player *player) { | |||
| player->variance = player->M2 / (double)(n_hand); | |||
| } | |||
| infinite_decks_card_number_for_arranged_ones = 0; | |||
| // reset this index | |||
| i_arranged_cards = 0; | |||
| n_hand++; | |||
| // clear dealer's hand | |||
| @@ -143,7 +142,7 @@ void Blackjack::deal(Player *player) { | |||
| nextAction = DealerAction::AskForBets; | |||
| } | |||
| player->info(Info::NewHand, n_hand); | |||
| player->info(Info::NewHand, player->bankroll); | |||
| return; | |||
| break; | |||
| @@ -690,9 +689,14 @@ unsigned int Blackjack::drawCard(Hand *hand) { | |||
| unsigned int tag = 0; | |||
| if (n_decks == -1) { | |||
| // TODO: arranged cards | |||
| tag = fiftyTwoCards(rng); | |||
| if (n_arranged_cards != 0 && i_arranged_cards < n_arranged_cards) { | |||
| // negative (or invalid) values are placeholder for random cards | |||
| if ((tag = arranged_cards[i_arranged_cards++]) < 0 || tag > 51) { | |||
| tag = fiftyTwoCards(rng); | |||
| } | |||
| } else { | |||
| tag = fiftyTwoCards(rng); | |||
| } | |||
| } else { | |||
| // TODO: shoes | |||
| @@ -60,10 +60,11 @@ class Blackjack : public Dealer { | |||
| bool shuffle_every_hand = false; | |||
| std::vector<unsigned int> arranged_cards; | |||
| unsigned int n_arranged_cards = 0; // just to prevent calling size() each time we draw a card | |||
| unsigned int i_arranged_cards = 0; | |||
| unsigned int max_bet = 0; | |||
| unsigned int number_of_burnt_cards = 0; | |||
| unsigned int infinite_decks_card_number_for_arranged_ones = 0; | |||
| @@ -58,6 +58,8 @@ class Configuration { | |||
| unsigned int hands_per_char = false; | |||
| double error_standard_deviations; | |||
| bool show_help = false; | |||
| bool show_version = false; | |||
| private: | |||
| std::map<std::string, std::string> data; | |||
| @@ -67,8 +69,6 @@ class Configuration { | |||
| std::string dealer; | |||
| std::string player; | |||
| bool show_help = false; | |||
| bool show_version = false; | |||
| // bool show_bar = false; | |||
| // bool bar_already_alloced = false; | |||
| @@ -35,6 +35,19 @@ int main(int argc, char **argv) { | |||
| Configuration conf(argc, argv); | |||
| if (conf.show_version) { | |||
| Libreblackjack::shortversion(); | |||
| Libreblackjack::copyright(); | |||
| } | |||
| if (conf.show_help) { | |||
| Libreblackjack::help(argv[0]); | |||
| } | |||
| if (conf.show_version || conf.show_help) { | |||
| return 0; | |||
| } | |||
| if (conf.getDealerName() == "blackjack") { | |||
| dealer = new Blackjack(conf); | |||
| } else { | |||
| @@ -108,7 +108,7 @@ void Tty::info(Info msg, int intData) { | |||
| case Info::NewHand: | |||
| // s = "new_hand"; | |||
| std::cout << std::endl; | |||
| s = "Starting new hand #" + std::to_string(intData); | |||
| s = "Starting new hand, bankroll " + std::to_string(intData); | |||
| dealerHand.cards.clear(); | |||
| break; | |||
| @@ -156,20 +156,17 @@ void Tty::info(Info msg, int intData) { | |||
| // s = "card_dealer_hole"; | |||
| s = "Dealer's hole card was " + card[intData].utf8(); | |||
| *(++(dealerHand.cards.begin())) = intData; | |||
| renderTable(); | |||
| // renderTable(); | |||
| break; | |||
| case Info::DealerBlackjack: | |||
| // s = "dealer_blackjack"; | |||
| s = "Dealer has Blackjack"; | |||
| // TODO: draw dealer's hand | |||
| renderTable(); | |||
| break; | |||
| case Info::PlayerWinsInsurance: | |||
| // s = "player_wins_insurance"; | |||
| s = "Player wins insurance"; | |||
| renderTable(); | |||
| break; | |||
| case Info::PlayerBlackjackAlso: | |||
| @@ -383,7 +380,7 @@ void Tty::renderHand(Hand *hand) { | |||
| unsigned int i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it > 0) { | |||
| if (it >= 0) { | |||
| std::cout << "|" << card[it].getNumberASCII() << ((card[it].number != 10)?" ":"") << " | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| @@ -394,7 +391,7 @@ void Tty::renderHand(Hand *hand) { | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it > 0) { | |||
| if (it >= 0) { | |||
| std::cout << "| | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| @@ -405,7 +402,7 @@ void Tty::renderHand(Hand *hand) { | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it > 0) { | |||
| if (it >= 0) { | |||
| std::cout << "| " << card[it].getSuitUTF8() << " | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| @@ -416,7 +413,7 @@ void Tty::renderHand(Hand *hand) { | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it > 0) { | |||
| if (it >= 0) { | |||
| std::cout << "| | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| @@ -427,7 +424,7 @@ void Tty::renderHand(Hand *hand) { | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it > 0) { | |||
| if (it >= 0) { | |||
| std::cout << "|___" << ((card[it].number != 10)?"_":"") << card[it].getNumberASCII() << "| "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| @@ -0,0 +1,72 @@ | |||
| /*------------ -------------- -------- --- ----- --- -- - - | |||
| * Libre Blackjack - version reporting | |||
| * | |||
| * Copyright (C) 2020 jeremy theler | |||
| * | |||
| * This file is part of Libre Blackjack. | |||
| * | |||
| * Libre Blackjack is free software: you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation, either version 3 of the License, or | |||
| * (at your option) any later version. | |||
| * | |||
| * Libre Blackjack is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public License | |||
| * along with Libre Blackjack. If not, see <http://www.gnu.org/licenses/>. | |||
| *------------------- ------------ ---- -------- -- - - - | |||
| */ | |||
| #include <iostream> | |||
| #include "version-vcs.h" | |||
| #define ENGINE "a free & open blackjack engine\n" | |||
| namespace Libreblackjack { | |||
| void shortversion(void) { | |||
| std::cout << "LibreBlackjack "; | |||
| #ifdef LIBREBLACKJACK_VCS_BRANCH | |||
| std::cout << LIBREBLACKJACK_VCS_VERSION << ((LIBREBLACKJACK_VCS_CLEAN == 0) ? "" : "+Δ") << ((LIBREBLACKJACK_VCS_BRANCH != "master") ? LIBREBLACKJACK_VCS_BRANCH : "") << std::endl; | |||
| #else | |||
| std::cout << PACKAGE_VERSION << std::endl; | |||
| #endif | |||
| // std::cout << (_(ENGINE)) << std::endl; | |||
| std::cout << ENGINE << std::endl; | |||
| return; | |||
| } | |||
| void help(const char *program_name) { | |||
| std::cout << "Usage: " << program_name << "[options] [path_to_conf_file]" << std::endl; | |||
| std::cout << ENGINE << std::endl; | |||
| std::cout << std::endl; | |||
| std::cout << "If no configuration file is given, a file named blackjack.conf" << std::endl; | |||
| std::cout << "in the current directory is used, provided it exists." << std::endl; | |||
| std::cout << "See the full documentation for the available options and the default values." << std::endl; | |||
| std::cout << std::endl; | |||
| std::cout << " -h, --hands=N set the number of hands to play before quiting" << std::endl; | |||
| std::cout << " -d, --decks=N set the number of decks to use" << std::endl; | |||
| std::cout << " -f, --flatbet do not ask for the bet before each hand, use a unit flat bet" << std::endl; | |||
| std::cout << " -i, --internal use the internal player to play against the dealer (not interactive)" << std::endl; | |||
| std::cout << std::endl; | |||
| std::cout << " -h, --help display this help and exit" << std::endl; | |||
| std::cout << " -v --version output version information and exit" << std::endl; | |||
| return; | |||
| } | |||
| void copyright(void) { | |||
| std::cout << "copyright (c) " << 2016 << "--" << 2020 << " jeremy theler." << std::endl; | |||
| std::cout << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>" << std::endl; | |||
| std::cout << "This is free software: you are free to change and redistribute it." << std::endl; | |||
| std::cout << "There is NO WARRANTY, to the extent permitted by law." << std::endl << std::endl; | |||
| return; | |||
| } | |||
| } | |||