| flat_bet = 1 | flat_bet = 1 | ||||
| max_bet = 2 | |||||
| arranged_cards = 5,0,7,10 | |||||
| # max_bet = 2 | |||||
| arranged_cards = 2,4,11,1,7 | |||||
| AskForPlay, | AskForPlay, | ||||
| MoveOnToNextHand, | MoveOnToNextHand, | ||||
| HitDealerHand, | HitDealerHand, | ||||
| Payout | |||||
| }; | }; | ||||
| enum class PlayerActionRequired { | enum class PlayerActionRequired { |
| shuffle(); | shuffle(); | ||||
| // burn as many cards as asked | // burn as many cards as asked | ||||
| for (int i = 0; i < number_of_burnt_cards; i++) { | |||||
| for (unsigned int i = 0; i < number_of_burnt_cards; i++) { | |||||
| drawCard(); | drawCard(); | ||||
| } | } | ||||
| lastPass = false; | lastPass = false; | ||||
| break; | break; | ||||
| // ------------------------------------------------------------------------- | |||||
| case DealerAction::AskForBets: | case DealerAction::AskForBets: | ||||
| // step 1. ask for bets | |||||
| player->actionRequired = PlayerActionRequired::Bet; | |||||
| return; | |||||
| break; | break; | ||||
| // ------------------------------------------------------------------------- | |||||
| case DealerAction::DealPlayerFirstCard: | case DealerAction::DealPlayerFirstCard: | ||||
| // where's step 2? <- probably that's the player's bet | // where's step 2? <- probably that's the player's bet | ||||
| // step 3. deal the first card to each player | // step 3. deal the first card to each player | ||||
| return; | return; | ||||
| break; | break; | ||||
| // TODO: ver esto | |||||
| /* | |||||
| case DealerAction::AskForInsurance: | case DealerAction::AskForInsurance: | ||||
| std::cout << "next action do you want insurance?" << std::endl; | |||||
| return; | return; | ||||
| break; | break; | ||||
| */ | |||||
| case DealerAction::CheckforBlackjacks: | case DealerAction::CheckforBlackjacks: | ||||
| // step 8. check if there are any blackjack | // step 8. check if there are any blackjack | ||||
| playerBlackack = player->currentHand->blackjack(); | playerBlackack = player->currentHand->blackjack(); | ||||
| // hit if count is less than 17 (or equalt to soft 17 if hit_soft_17 is true) | // hit if count is less than 17 (or equalt to soft 17 if hit_soft_17 is true) | ||||
| dealerTotal = hand.total(); | dealerTotal = hand.total(); | ||||
| while (((abs(dealerTotal) < 17 || (hit_soft_17 && dealerTotal == -17))) && hand.busted() == 0) { | |||||
| while ((std::abs(dealerTotal) < 17 || (hit_soft_17 && dealerTotal == -17)) && hand.busted() == 0) { | |||||
| unsigned int dealerCard = drawCard(&hand); | unsigned int dealerCard = drawCard(&hand); | ||||
| player->info(Info::CardDealer, dealerTotal); | |||||
| player->info(Info::CardDealer, dealerCard); | |||||
| dealerTotal = std::abs(hand.total()); | dealerTotal = std::abs(hand.total()); | ||||
| } else { | } else { | ||||
| for (auto playerHand : player->hands) { | for (auto playerHand : player->hands) { | ||||
| if (playerHand.busted() == false) { // busted hands have already been solved | if (playerHand.busted() == false) { // busted hands have already been solved | ||||
| unsigned int playerTotal = std::abs(playerHand.total()); | |||||
| playerTotal = std::abs(playerHand.total()); | |||||
| if (dealerTotal > playerTotal) { | if (dealerTotal > playerTotal) { | ||||
| {NULL, 0, NULL, 0} | {NULL, 0, NULL, 0} | ||||
| }; | }; | ||||
| int i, optc; | |||||
| int optc = 0; | |||||
| int option_index = 0; | int option_index = 0; | ||||
| int opterr = 0; | |||||
| // int opterr = 0; | |||||
| while ((optc = getopt_long_only(argc, argv, "c:hvd:n:if:", longopts, &option_index)) != -1) { | while ((optc = getopt_long_only(argc, argv, "c:hvd:n:if:", longopts, &option_index)) != -1) { | ||||
| switch (optc) { | switch (optc) { | ||||
| case 'h': | case 'h': | ||||
| std::string line(argv[optind - 1]); | std::string line(argv[optind - 1]); | ||||
| std::size_t delimiterPos = line.find("="); | std::size_t delimiterPos = line.find("="); | ||||
| if (delimiterPos != std::string::npos) { | if (delimiterPos != std::string::npos) { | ||||
| auto name = line.substr(0, delimiterPos); | |||||
| std::size_t offset = 0; | |||||
| if (line.substr(0, 2) == "--") { | |||||
| offset = 2; | |||||
| } else if (line.substr(0, 1) == "-") { | |||||
| offset = 1; | |||||
| } | |||||
| auto name = line.substr(offset, delimiterPos-offset); | |||||
| auto value = line.substr(delimiterPos + 1); | auto value = line.substr(delimiterPos + 1); | ||||
| data[name] = value; | data[name] = value; | ||||
| } else { | } else { | ||||
| bool Configuration::set(bool *value, std::list<std::string> key) { | bool Configuration::set(bool *value, std::list<std::string> key) { | ||||
| for (auto it : key) { | for (auto it : key) { | ||||
| if (exists(*(&it))) { | if (exists(*(&it))) { | ||||
| if (data[*(&it)] == "true") { | |||||
| auto s = data[*(&it)]; | |||||
| if (s == "true" || s == "yes" || s == "y") { | |||||
| *value = true; | *value = true; | ||||
| } else if (data[*(&it)] == "false") { | |||||
| } else if (s == "false" || s == "no" || s == "n") { | |||||
| *value = false; | *value = false; | ||||
| } else { | } else { | ||||
| *value = std::stoi(data[*(&it)]); | |||||
| *value = std::stoi(s); | |||||
| } | } | ||||
| return true; | return true; | ||||
| } | } |
| // let the action begin! | // let the action begin! | ||||
| int unknownCommands = 0; | |||||
| unsigned int unknownCommands = 0; | |||||
| dealer->nextAction = DealerAction::StartNewHand; | dealer->nextAction = DealerAction::StartNewHand; | ||||
| while (!dealer->finished()) { | while (!dealer->finished()) { | ||||
| dealer->deal(player); | dealer->deal(player); |
| std::vector<std::string> commands; | std::vector<std::string> commands; | ||||
| // trim from start (in place) | // trim from start (in place) | ||||
| static inline void ltrim(std::string &s) { | static inline void ltrim(std::string &s) { | ||||
| s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { | ||||
| Tty::Tty(Configuration &conf) { | Tty::Tty(Configuration &conf) { | ||||
| Libreblackjack::shortversion(); | |||||
| // Libreblackjack::copyright(); | |||||
| conf.set(&flat_bet, {"flat_bet", "flatbet"}); | conf.set(&flat_bet, {"flat_bet", "flatbet"}); | ||||
| conf.set(&no_insurance, {"no_insurance", "dont_insure"}); | conf.set(&no_insurance, {"no_insurance", "dont_insure"}); | ||||
| commands.push_back("stand"); | commands.push_back("stand"); | ||||
| commands.push_back("double"); | commands.push_back("double"); | ||||
| commands.push_back("split"); | commands.push_back("split"); | ||||
| commands.push_back("pair"); | |||||
| commands.push_back("yes"); | commands.push_back("yes"); | ||||
| commands.push_back("no"); | commands.push_back("no"); | ||||
| commands.push_back("quit"); | commands.push_back("quit"); | ||||
| } | } | ||||
| // TODO: check conf for colors | |||||
| if (conf.exists("color")) { | |||||
| conf.set(&color, {"color"}); | |||||
| } | |||||
| if (color) { | |||||
| black = "\x1B[0m"; | |||||
| red = "\x1B[31m"; | |||||
| green = "\x1B[32m"; | |||||
| yellow = "\x1B[33m"; | |||||
| blue = "\x1B[34m"; | |||||
| magenta = "\x1B[35m"; | |||||
| cyan = "\x1B[36m"; | |||||
| white = "\x1B[37m"; | |||||
| reset = "\033[0m"; | |||||
| } | |||||
| prompt = cyan + " > " + reset; | prompt = cyan + " > " + reset; | ||||
| return; | |||||
| } | } | ||||
| void Tty::info(Info msg, int intData) { | void Tty::info(Info msg, int intData) { | ||||
| std::cout << "help yourself" << std::endl; | std::cout << "help yourself" << std::endl; | ||||
| break; | break; | ||||
| case Info::Bye: | case Info::Bye: | ||||
| // s = "bye"; | // s = "bye"; | ||||
| s = "Bye bye! We'll play Blackjack again next time."; | s = "Bye bye! We'll play Blackjack again next time."; | ||||
| break; | break; | ||||
| case Info::None: | |||||
| break; | |||||
| } | } | ||||
| if (delay > 0) { | if (delay > 0) { | ||||
| renderTable(); | renderTable(); | ||||
| s = "Play?"; | s = "Play?"; | ||||
| break; | break; | ||||
| case PlayerActionRequired::None: | |||||
| break; | |||||
| } | } | ||||
| if (s != "") { | if (s != "") { | ||||
| break; | break; | ||||
| case PlayerActionRequired::Play: | case PlayerActionRequired::Play: | ||||
| // TODO: sort by higher-expected response first | // TODO: sort by higher-expected response first | ||||
| if (command == "h" || command =="hit") { | if (command == "h" || command =="hit") { | ||||
| actionTaken = PlayerActionTaken::Hit; | actionTaken = PlayerActionTaken::Hit; | ||||
| actionTaken = PlayerActionTaken::None; | actionTaken = PlayerActionTaken::None; | ||||
| } | } | ||||
| break; | break; | ||||
| case PlayerActionRequired::None: | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| void Tty::renderHand(Hand *hand) { | void Tty::renderHand(Hand *hand) { | ||||
| for (auto it : hand->cards) { | |||||
| for (unsigned int i = 0; i < hand->cards.size(); i++) { | |||||
| std::cout << " _____ "; | std::cout << " _____ "; | ||||
| } | } | ||||
| std::cout << std::endl; | std::cout << std::endl; | ||||
| len = strlen(text); | len = strlen(text); | ||||
| } | } | ||||
| for (auto i = list_index; i < commands.size(); i++) { | |||||
| for (unsigned int i = list_index; i < commands.size(); i++) { | |||||
| if (commands[i].compare(0, len, text) == 0) { | if (commands[i].compare(0, len, text) == 0) { | ||||
| list_index = i+1; | list_index = i+1; | ||||
| return strdup(commands[i].c_str()); | return strdup(commands[i].c_str()); |
| int delay = 200; | int delay = 200; | ||||
| std::string black = "\x1B[0m"; | |||||
| std::string red = "\x1B[31m"; | |||||
| std::string green = "\x1B[32m"; | |||||
| std::string yellow = "\x1B[33m"; | |||||
| std::string blue = "\x1B[34m"; | |||||
| std::string magenta = "\x1B[35m"; | |||||
| std::string cyan = "\x1B[36m"; | |||||
| std::string white = "\x1B[37m"; | |||||
| std::string reset = "\033[0m"; | |||||
| bool color = true; | |||||
| std::string black; | |||||
| std::string red; | |||||
| std::string green; | |||||
| std::string yellow; | |||||
| std::string blue; | |||||
| std::string magenta; | |||||
| std::string cyan; | |||||
| std::string white; | |||||
| std::string reset; | |||||
| }; | }; | ||||
| #endif | #endif |
| *------------------- ------------ ---- -------- -- - - - | *------------------- ------------ ---- -------- -- - - - | ||||
| */ | */ | ||||
| #include <iostream> | #include <iostream> | ||||
| #include <cstring> | |||||
| #include "version-vcs.h" | #include "version-vcs.h" | ||||
| #define ENGINE "a free & open blackjack engine\n" | #define ENGINE "a free & open blackjack engine\n" | ||||
| std::cout << "LibreBlackjack "; | std::cout << "LibreBlackjack "; | ||||
| #ifdef LIBREBLACKJACK_VCS_BRANCH | #ifdef LIBREBLACKJACK_VCS_BRANCH | ||||
| std::cout << LIBREBLACKJACK_VCS_VERSION << ((LIBREBLACKJACK_VCS_CLEAN == 0) ? "" : "+Δ") << ((LIBREBLACKJACK_VCS_BRANCH != "master") ? LIBREBLACKJACK_VCS_BRANCH : "") << std::endl; | |||||
| std::cout << LIBREBLACKJACK_VCS_VERSION << ((LIBREBLACKJACK_VCS_CLEAN == 0) ? "" : "+Δ") << ((strcmp(LIBREBLACKJACK_VCS_BRANCH, "master") == 0) ? LIBREBLACKJACK_VCS_BRANCH : "") << std::endl; | |||||
| #else | #else | ||||
| std::cout << PACKAGE_VERSION << std::endl; | std::cout << PACKAGE_VERSION << std::endl; | ||||
| #endif | #endif |