| @@ -1,9 +1,10 @@ | |||
| * version and copyright | |||
| * messages implemented on the player's side | |||
| * arranged shoes | |||
| * handle no readline | |||
| * to_string() para floats | |||
| * max_splits through conf (default 3) | |||
| * DAS | |||
| * shoes (and arranged shoes) | |||
| * name of the game the dealer deals | |||
| * name of the games the player can play | |||
| * delays? | |||
| * dealers | |||
| * ENHC | |||
| * blackjack switch | |||
| @@ -24,5 +25,3 @@ | |||
| * multithreading | |||
| * use of const and restrict | |||
| @@ -1,5 +1,4 @@ | |||
| # flat_bet = 1 | |||
| # max_bet = 2 | |||
| arranged_cards = 9,8,13,12 | |||
| delay = 0 | |||
| ; flat_bet = 1 | |||
| ; arranged_cards = 3,8,3,13,4,13,11,7 | |||
| ; delay = 0 | |||
| @@ -92,7 +92,7 @@ enum class Info { | |||
| PlayerBlackjack, | |||
| PlayerWins, | |||
| NoBlackjacks, | |||
| PlayerBustsAllHands, | |||
| // PlayerBustsAllHands, | |||
| DealerBusts, | |||
| Help, | |||
| Bye, | |||
| @@ -106,6 +106,11 @@ enum class Suit { | |||
| Spades = 3 | |||
| }; | |||
| enum class Color { | |||
| Black, | |||
| Red | |||
| }; | |||
| class Card { | |||
| public: | |||
| @@ -146,7 +151,7 @@ extern Card card[53]; | |||
| class Hand { | |||
| public: | |||
| std::list<int> cards; | |||
| std::list<unsigned int> cards; | |||
| // inline on purpose | |||
| int total() { | |||
| @@ -198,7 +203,7 @@ class Player { | |||
| Player(const Player &&) = delete; | |||
| virtual int play() = 0; | |||
| virtual void info(Info = Info::None, int = 0) = 0; | |||
| virtual void info(Info = Info::None, int = 0, int = 0) = 0; | |||
| PlayerActionRequired actionRequired = PlayerActionRequired::None; | |||
| PlayerActionTaken actionTaken = PlayerActionTaken::None; | |||
| @@ -144,7 +144,7 @@ void Blackjack::deal(Player *player) { | |||
| } | |||
| player->info(Info::NewHand, player->bankroll); | |||
| player->info(Info::NewHand, n_hand, 1e3*player->bankroll); | |||
| return; | |||
| break; | |||
| @@ -172,7 +172,7 @@ void Blackjack::deal(Player *player) { | |||
| // step 6. deal the dealer's hole card | |||
| holeCard = drawCard(&hand); | |||
| player->info(Info::CardDealer, -1); | |||
| player->info(Info::CardDealer); | |||
| // step 7.a. if the upcard is an ace ask for insurance | |||
| if (card[upCard].value == 11) { | |||
| @@ -221,7 +221,7 @@ void Blackjack::deal(Player *player) { | |||
| player->blackjacksDealer++; | |||
| if (player->currentHand->insured) { | |||
| player->info(Info::PlayerWinsInsurance, player->currentHand->bet); | |||
| player->info(Info::PlayerWinsInsurance, 1e3*player->currentHand->bet); | |||
| player->current_result += player->currentHand->bet; | |||
| player->bankroll += player->currentHand->bet; | |||
| player->winsInsured++; | |||
| @@ -229,12 +229,12 @@ void Blackjack::deal(Player *player) { | |||
| if (playerBlackack) { | |||
| player->info(Info::PlayerBlackjackAlso); | |||
| player->info(Info::PlayerPushes); | |||
| player->info(Info::PlayerPushes, 1e3*player->currentHand->bet); | |||
| player->blackjacksPlayer++; | |||
| player->pushes++; | |||
| } else { | |||
| player->info(Info::PlayerLosses); | |||
| player->info(Info::PlayerLosses, 1e3*player->currentHand->bet); | |||
| player->current_result -= player->currentHand->bet; | |||
| player->bankroll -= player->currentHand->bet; | |||
| if (player->bankroll < player->worst_bankroll) { | |||
| @@ -252,7 +252,7 @@ void Blackjack::deal(Player *player) { | |||
| player->bankroll += blackjack_pays * player->currentHand->bet; | |||
| player->blackjacksPlayer++; | |||
| player->info(Info::PlayerWins, blackjack_pays * player->currentHand->bet); | |||
| player->info(Info::PlayerWins, 1e3 * blackjack_pays*player->currentHand->bet); | |||
| player->wins++; | |||
| player->winsBlackjack++; | |||
| @@ -304,10 +304,7 @@ void Blackjack::deal(Player *player) { | |||
| } | |||
| if (player->bustedAllHands) { | |||
| player->info(Info::PlayerBustsAllHands); | |||
| player->info(Info::CardDealerRevealsHole, holeCard); | |||
| // TODO: no tengo que sacarle todo el dinero? | |||
| player->actionRequired = PlayerActionRequired::None; | |||
| nextAction = DealerAction::StartNewHand; | |||
| @@ -324,23 +321,53 @@ void Blackjack::deal(Player *player) { | |||
| player->info(Info::CardDealerRevealsHole, holeCard); | |||
| // hit if count is less than 17 (or equalt to soft 17 if hit_soft_17 is true) | |||
| // hit while count is less than 17 (or equal to soft 17 if hit_soft_17 is true) | |||
| dealerTotal = hand.total(); | |||
| while ((std::abs(dealerTotal) < 17 || (hit_soft_17 && dealerTotal == -17)) && hand.busted() == 0) { | |||
| unsigned int dealerCard = drawCard(&hand); | |||
| player->info(Info::CardDealer, dealerCard); | |||
| dealerTotal = hand.total(); | |||
| } | |||
| dealerTotal = std::abs(hand.total()); | |||
| if (hand.busted()) { | |||
| player->info(Info::DealerBusts); | |||
| player->bustsDealer++; | |||
| for (auto playerHand : player->hands) { | |||
| if (playerHand.busted() == false) { | |||
| player->info(Info::PlayerWins, playerHand.bet); | |||
| if (hand.busted()) { | |||
| player->info(Info::DealerBusts, dealerTotal); | |||
| player->bustsDealer++; | |||
| for (auto playerHand : player->hands) { | |||
| if (playerHand.busted() == false) { | |||
| player->info(Info::PlayerWins, 1e3*playerHand.bet); | |||
| player->current_result += playerHand.bet; | |||
| player->bankroll += playerHand.bet; | |||
| player->wins++; | |||
| player->winsDoubled += playerHand.doubled; | |||
| } | |||
| } | |||
| } else { | |||
| for (auto playerHand : player->hands) { | |||
| if (playerHand.busted() == false) { // busted hands have already been solved | |||
| playerTotal = std::abs(playerHand.total()); | |||
| if (dealerTotal > playerTotal) { | |||
| player->info(Info::PlayerLosses, 1e3*playerHand.bet, playerTotal); | |||
| player->bankroll -= playerHand.bet; | |||
| if (player->bankroll < player->worst_bankroll) { | |||
| player->worst_bankroll = player->bankroll; | |||
| } | |||
| player->losses++; | |||
| } else if (dealerTotal == playerTotal) { | |||
| player->info(Info::PlayerPushes, 1e3*playerHand.bet); | |||
| player->pushes++; | |||
| } else { | |||
| player->info(Info::PlayerWins, 1e3*playerHand.bet, playerTotal); | |||
| player->current_result += playerHand.bet; | |||
| player->bankroll += playerHand.bet; | |||
| player->wins++; | |||
| if (playerHand.doubled) { | |||
| player->winsDoubled++; | |||
| } else { | |||
| @@ -348,40 +375,6 @@ void Blackjack::deal(Player *player) { | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| for (auto playerHand : player->hands) { | |||
| if (playerHand.busted() == false) { // busted hands have already been solved | |||
| playerTotal = std::abs(playerHand.total()); | |||
| if (dealerTotal > playerTotal) { | |||
| player->info(Info::PlayerLosses, playerHand.bet); | |||
| player->bankroll -= playerHand.bet; | |||
| if (player->bankroll < player->worst_bankroll) { | |||
| player->worst_bankroll = player->bankroll; | |||
| } | |||
| player->losses++; | |||
| } else if (dealerTotal == playerTotal) { | |||
| player->info(Info::PlayerPushes, playerHand.bet); | |||
| player->pushes++; | |||
| } else { | |||
| player->info(Info::PlayerWins, playerHand.bet); | |||
| player->current_result += playerHand.bet; | |||
| player->bankroll += playerHand.bet; | |||
| player->wins++; | |||
| if (playerHand.doubled) { | |||
| player->winsDoubled++; | |||
| } else { | |||
| player->wins++; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -409,8 +402,6 @@ int Blackjack::process(Player *player) { | |||
| switch (player->actionTaken) { | |||
| // TODO: maybe we have to call a basic method with common commands? | |||
| // we first check common commands | |||
| ///ig+quit+name quit | |||
| ///ig+quit+desc Finish the game | |||
| @@ -431,19 +422,7 @@ int Blackjack::process(Player *player) { | |||
| player->info(Info::Help); | |||
| return 0; | |||
| break; | |||
| case PlayerActionTaken::Count: | |||
| std::cout << "count " << (*player->currentHand).total() <<std::endl; | |||
| return 0; | |||
| break; | |||
| case PlayerActionTaken::UpcardValue: | |||
| std::cout << "upcard " << card[upCard].utf8() <<std::endl; | |||
| return 0; | |||
| break; | |||
| case PlayerActionTaken::Bankroll: | |||
| std::cout << "bankroll " << player->bankroll <<std::endl; | |||
| return 0; | |||
| break; | |||
| case PlayerActionTaken::None: | |||
| return 0; | |||
| break; | |||
| @@ -511,22 +490,19 @@ int Blackjack::process(Player *player) { | |||
| ///ip+double+detail This command can be abbreviated as `d`. | |||
| case PlayerActionTaken::Double: | |||
| if (player->currentHand->cards.size() == 2) { | |||
| std::cout << "double_down" << std::endl; | |||
| // TODO: check bankroll | |||
| player->total_money_waged += player->currentHand->bet; | |||
| player->total_money_waged += player->currentHand->bet; | |||
| player->currentHand->bet *= 2; | |||
| player->currentHand->doubled = true; | |||
| player->currentHand->doubled = true; | |||
| player->handsDoubled++; | |||
| playerCard = drawCard(&(*player->currentHand)); | |||
| unsigned int playerTotal = player->currentHand->total(); | |||
| std::cout << "card_player" << card[playerCard].utf8() << std::endl; | |||
| std::cout << "player_total " << playerTotal << std::endl; | |||
| player->info(Info::CardPlayer, playerCard); | |||
| if (player->currentHand->busted()) { | |||
| std::cout << "player_busted" << std::endl; | |||
| player->info(Info::PlayerLosses, 1e3*player->currentHand->bet, playerTotal); | |||
| player->current_result -= player->currentHand->bet; | |||
| player->bankroll -= player->currentHand->bet; | |||
| player->bustsPlayer++; | |||
| @@ -555,9 +531,9 @@ int Blackjack::process(Player *player) { | |||
| secondCard = *(++player->currentHand->cards.begin()); | |||
| // up to three splits (i.e. four hands) | |||
| // TODO: choose | |||
| if (player->currentSplits < 3 && player->currentHand->cards.size() == 2 && | |||
| card[firstCard].value == card[secondCard].value) { | |||
| // TODO: choose through conf | |||
| // TODO: check bankroll to see if player can split | |||
| if (player->currentSplits < 3 && player->currentHand->cards.size() == 2 && card[firstCard].value == card[secondCard].value) { | |||
| // mark that we split to put ids in the hands and to limi the number of spltis | |||
| player->currentSplits++; | |||
| @@ -569,7 +545,6 @@ int Blackjack::process(Player *player) { | |||
| // create a new hand | |||
| PlayerHand newHand; | |||
| newHand.id = player->currentHand->id + 1; | |||
| // TODO: check bankroll | |||
| newHand.bet = player->currentHand->bet; | |||
| player->total_money_waged += player->currentHand->bet; | |||
| @@ -629,10 +604,10 @@ int Blackjack::process(Player *player) { | |||
| ///ip+hit+detail | |||
| ///ip+hit+detail This command can be abbreviated as `h`. | |||
| playerCard = drawCard(&(*player->currentHand)); | |||
| std::cout << "card_player " << card[playerCard].utf8() << std::endl; | |||
| player->info(Info::CardPlayer, playerCard); | |||
| if (player->currentHand->busted()) { | |||
| std::cout << "busted_player " << player->currentHand->total() << std::endl; | |||
| player->info(Info::PlayerLosses, 1e3*player->currentHand->bet); | |||
| player->current_result -= player->currentHand->bet; | |||
| player->bankroll -= player->currentHand->bet; | |||
| player->bustsPlayer++; | |||
| @@ -73,6 +73,7 @@ int main(int argc, char **argv) { | |||
| while (!dealer->finished()) { | |||
| dealer->deal(player); | |||
| if (player->actionRequired != PlayerActionRequired::None) { | |||
| unknownCommands = 0; | |||
| do { | |||
| if (unknownCommands++ > conf.max_incorrect_commands) { | |||
| std::cerr << "Too many unknown commands." << std::endl; | |||
| @@ -34,7 +34,7 @@ | |||
| StdInOut::StdInOut(void) { | |||
| } | |||
| void StdInOut::info(Info msg, int data) { | |||
| void StdInOut::info(Info msg, int p1, int p2) { | |||
| return; | |||
| } | |||
| @@ -30,7 +30,7 @@ class StdInOut : public Player { | |||
| ~StdInOut() { }; | |||
| int play(void) override; | |||
| void info(Info = Info::None, int = 0) override; | |||
| void info(Info = Info::None, int = 0, int = 0) override; | |||
| private: | |||
| std::string input_buffer; | |||
| @@ -80,20 +80,21 @@ Tty::Tty(Configuration &conf) { | |||
| return; | |||
| } | |||
| void Tty::info(Info msg, int p) { | |||
| void Tty::info(Info msg, int p1, int p2) { | |||
| std::string s; | |||
| bool render = false; | |||
| // TODO: choose utf8 or other representation | |||
| switch (msg) { | |||
| case Info::InvalidBet: | |||
| if (p < 0) { | |||
| if (p1 < 0) { | |||
| // s = "bet_negative"; | |||
| s = "Your bet is negative (" + std::to_string(p) + ")"; | |||
| } else if (p > 0) { | |||
| s = "Your bet is negative (" + std::to_string(p1) + ")"; | |||
| } else if (p1 > 0) { | |||
| // s = "bet_maximum"; | |||
| s = "Your bet is larger than the maximum allowed (" + std::to_string(p) + ")"; | |||
| s = "Your bet is larger than the maximum allowed (" + std::to_string(p1) + ")"; | |||
| } else { | |||
| // s = "bet_zero"; | |||
| s = "Your bet is zero"; | |||
| @@ -103,11 +104,12 @@ void Tty::info(Info msg, int p) { | |||
| case Info::NewHand: | |||
| // s = "new_hand"; | |||
| std::cout << std::endl; | |||
| s = "Starting new hand, bankroll " + std::to_string(p); | |||
| s = "Starting new hand #" + std::to_string(p1) + " with bankroll " + std::to_string(1e-3*p2); | |||
| dealerHand.cards.clear(); | |||
| break; | |||
| case Info::Shuffle: | |||
| // TODO: ask the user to cut | |||
| // s = "shuffle"; | |||
| s = "Deck needs to be shuffled."; | |||
| break; | |||
| @@ -116,42 +118,41 @@ void Tty::info(Info msg, int p) { | |||
| switch (currentHand->cards.size()) { | |||
| case 1: | |||
| // s = "card_player_first"; | |||
| s = "Player's first card is " + card[p].utf8(); | |||
| s = "Player's first card is " + card[p1].utf8(); | |||
| break; | |||
| case 2: | |||
| // s = "card_player_second"; | |||
| s = "Player's second card is " + card[p].utf8(); | |||
| s = "Player's second card is " + card[p1].utf8(); | |||
| break; | |||
| default: | |||
| // s = "card_player"; | |||
| s = "Player's card is " + card[p].utf8(); | |||
| s = "Player's card is " + card[p1].utf8(); | |||
| break; | |||
| } | |||
| break; | |||
| case Info::CardDealer: | |||
| if (p != -1) { | |||
| if (p1 > 0) { | |||
| switch (dealerHand.cards.size()) { | |||
| case 0: | |||
| // s = "card_dealer_up"; | |||
| s = "Dealer's up card is " + card[p].utf8(); | |||
| s = "Dealer's up card is " + card[p1].utf8(); | |||
| break; | |||
| default: | |||
| // s = "card_dealer"; | |||
| s = "Dealer's card is " + card[p].utf8(); | |||
| s = "Dealer's card is " + card[p1].utf8(); | |||
| break; | |||
| } | |||
| } else { | |||
| s = "Dealer's hole card is dealt"; | |||
| } | |||
| dealerHand.cards.push_back(p); | |||
| dealerHand.cards.push_back(p1); | |||
| break; | |||
| case Info::CardDealerRevealsHole: | |||
| // s = "card_dealer_hole"; | |||
| s = "Dealer's hole card was " + card[p].utf8(); | |||
| *(++(dealerHand.cards.begin())) = p; | |||
| // renderTable(); | |||
| s = "Dealer's hole card was " + card[p1].utf8(); | |||
| *(++(dealerHand.cards.begin())) = p1; | |||
| break; | |||
| case Info::DealerBlackjack: | |||
| @@ -167,42 +168,43 @@ void Tty::info(Info msg, int p) { | |||
| case Info::PlayerBlackjackAlso: | |||
| // s = "player_blackjack_also"; | |||
| s = "Player also has Blackjack"; | |||
| renderTable(); | |||
| render = true; | |||
| break; | |||
| case Info::PlayerNextHand: | |||
| // s = "player_pushes"; | |||
| s = "Playing next hand #" + std::to_string(p); | |||
| renderTable(); | |||
| // s = "player_next_hand"; | |||
| s = "Playing next hand #" + std::to_string(p1); | |||
| render = true; | |||
| break; | |||
| case Info::PlayerPushes: | |||
| // s = "player_pushes"; | |||
| s = "Player pushes"; | |||
| renderTable(); | |||
| s = "Player pushes " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : ""); | |||
| render = true; | |||
| break; | |||
| case Info::PlayerLosses: | |||
| // s = "player_losses"; | |||
| s = "Player losses"; | |||
| renderTable(); | |||
| s = "Player losses " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : ""); | |||
| render = true; | |||
| break; | |||
| case Info::PlayerBlackjack: | |||
| // s = "blackjack_player"; | |||
| s = "Player has Blackjack"; | |||
| renderTable(); | |||
| render = true; | |||
| break; | |||
| case Info::PlayerWins: | |||
| // s = "player_wins"; | |||
| s = "Player wins " + std::to_string(p); | |||
| renderTable(); | |||
| s = "Player wins " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : ""); | |||
| render = true; | |||
| break; | |||
| case Info::NoBlackjacks: | |||
| // s = "no_blackjacks"; | |||
| s = "No blackjacks"; | |||
| break; | |||
| /* | |||
| case Info::PlayerBustsAllHands: | |||
| // s = "player_busted_all_hands"; | |||
| if (hands.size() == 1) { | |||
| @@ -212,11 +214,10 @@ void Tty::info(Info msg, int p) { | |||
| } | |||
| renderTable(); | |||
| break; | |||
| */ | |||
| case Info::DealerBusts: | |||
| // s = "no_blackjacks"; | |||
| s = "Dealer busts!"; | |||
| renderTable(); | |||
| s = "Dealer busts with " + std::to_string(p1); | |||
| break; | |||
| case Info::Help: | |||
| @@ -238,6 +239,10 @@ void Tty::info(Info msg, int p) { | |||
| std::this_thread::sleep_for(std::chrono::milliseconds(delay)); | |||
| } | |||
| std::cout << green << s << reset << std::endl; | |||
| if (render) { | |||
| renderTable(); | |||
| } | |||
| return; | |||
| } | |||
| @@ -287,6 +292,7 @@ int Tty::play() { | |||
| // TODO: better solution | |||
| std::string command = input_buffer; | |||
| free(input_buffer); | |||
| trim(command); | |||
| @@ -309,7 +315,7 @@ int Tty::play() { | |||
| switch (actionRequired) { | |||
| case PlayerActionRequired::Bet: | |||
| currentBet = std::stoi(input_buffer); | |||
| currentBet = std::stoi(command); | |||
| actionTaken = PlayerActionTaken::Bet; | |||
| break; | |||
| @@ -344,8 +350,6 @@ int Tty::play() { | |||
| } | |||
| } | |||
| free(input_buffer); | |||
| } | |||
| #else | |||
| @@ -383,63 +387,80 @@ void Tty::renderTable(void) { | |||
| void Tty::renderHand(Hand *hand) { | |||
| std::string ansiColor; | |||
| std::string ansiReset; | |||
| for (unsigned int i = 0; i < hand->cards.size(); i++) { | |||
| std::cout << " _____ "; | |||
| } | |||
| std::cout << std::endl; | |||
| unsigned int i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it >= 0) { | |||
| std::cout << "|" << card[it].getNumberASCII() << ((card[it].number != 10)?" ":"") << " | "; | |||
| for (auto c : hand->cards) { | |||
| if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) { | |||
| ansiColor = red; | |||
| ansiReset = reset; | |||
| } else { | |||
| ansiColor = ""; | |||
| ansiReset = ""; | |||
| } | |||
| if (c > 0) { | |||
| std::cout << "|" << ansiColor << card[c].getNumberASCII() << ((card[c].number != 10)?" ":"") << ansiReset << " | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| } | |||
| i++; | |||
| } | |||
| std::cout << std::endl; | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it >= 0) { | |||
| for (auto c : hand->cards) { | |||
| if (c > 0) { | |||
| std::cout << "| | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| } | |||
| i++; | |||
| } | |||
| std::cout << std::endl; | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it >= 0) { | |||
| std::cout << "| " << card[it].getSuitUTF8() << " | "; | |||
| for (auto c : hand->cards) { | |||
| if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) { | |||
| ansiColor = red; | |||
| ansiReset = reset; | |||
| } else { | |||
| ansiColor = ""; | |||
| ansiReset = ""; | |||
| } | |||
| if (c > 0) { | |||
| std::cout << "| " << ansiColor << card[c].getSuitUTF8() << ansiReset << " | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| } | |||
| i++; | |||
| } | |||
| std::cout << std::endl; | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it >= 0) { | |||
| for (auto c : hand->cards) { | |||
| if (c > 0) { | |||
| std::cout << "| | "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| } | |||
| i++; | |||
| } | |||
| std::cout << std::endl; | |||
| i = 0; | |||
| for (auto it : hand->cards) { | |||
| if (it >= 0) { | |||
| std::cout << "|___" << ((card[it].number != 10)?"_":"") << card[it].getNumberASCII() << "| "; | |||
| for (auto c : hand->cards) { | |||
| if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) { | |||
| ansiColor = red; | |||
| ansiReset = reset; | |||
| } else { | |||
| ansiColor = ""; | |||
| ansiReset = ""; | |||
| } | |||
| if (c > 0) { | |||
| std::cout << "|___" << ansiColor << ((card[c].number != 10)?"_":"") << card[c].getNumberASCII() << ansiReset<< "| "; | |||
| } else { | |||
| std::cout << "|#####| "; | |||
| } | |||
| i++; | |||
| } | |||
| std::cout << std::endl; | |||
| @@ -37,7 +37,7 @@ class Tty : public Player { | |||
| ~Tty() { }; | |||
| int play() override; | |||
| void info(Info = Info::None, int = 0) override; | |||
| void info(Info = Info::None, int = 0, int = 0) override; | |||
| // for readline's autocompletion | |||
| static char *rl_command_generator(const char *, int); | |||