Quellcode durchsuchen

separated player data from what the dealer can modify from what the player can modify

master
gtheler vor 5 Jahren
Ursprung
Commit
f47b4e6793
9 geänderte Dateien mit 434 neuen und 400 gelöschten Zeilen
  1. +136
    -123
      src/base.h
  2. +210
    -211
      src/blackjack.cpp
  3. +2
    -2
      src/blackjack.h
  4. +5
    -5
      src/cards.cpp
  5. +7
    -4
      src/main.cpp
  6. +1
    -1
      src/stdinout.cpp
  7. +1
    -1
      src/stdinout.h
  8. +71
    -52
      src/tty.cpp
  9. +1
    -1
      src/tty.h

+ 136
- 123
src/base.h Datei anzeigen

@@ -32,86 +32,83 @@ namespace Libreblackjack {
void shortversion(void);
void help(const char *);
void copyright(void);
}

// TODO: namespace

enum class DealerAction {
None,
StartNewHand,
AskForBets,
DealPlayerFirstCard,
AskForInsurance,
CheckforBlackjacks,
AskForPlay,
MoveOnToNextHand,
HitDealerHand,
};

enum class PlayerActionRequired {
None,
Bet,
Insurance,
Play
};

enum class PlayerActionTaken {
None,
// common
Quit,
Help,
Count,
UpcardValue,
Bankroll,
Hands,
Table,
// particular
Bet,
Insure,
DontInsure,
Stand,
Double,
Split,
Hit,
};

enum class Info {
None,
InvalidBet,
NewHand,
Shuffle,
CardPlayer,
CardDealer,
CardDealerRevealsHole,
DealerBlackjack,
PlayerWinsInsurance,
PlayerBlackjackAlso,
PlayerNextHand,
PlayerPushes,
PlayerLosses,
PlayerBlackjack,
PlayerWins,
NoBlackjacks,
// PlayerBustsAllHands,
DealerBusts,
Help,
Bye,
};

// alphabetically-sorted
enum class Suit {
Clubs = 0,
Diamonds = 1,
Hearts = 2,
Spades = 3
};

enum class Color {
Black,
Red
enum class DealerAction {
None,
StartNewHand,
AskForBets,
DealPlayerFirstCard,
AskForInsurance,
CheckforBlackjacks,
AskForPlay,
MoveOnToNextHand,
HitDealerHand,
};
enum class PlayerActionRequired {
None,
Bet,
Insurance,
Play
};
enum class PlayerActionTaken {
None,
// common
Quit,
Help,
Count,
UpcardValue,
Bankroll,
Hands,
Table,
// particular
Bet,
Insure,
DontInsure,
Stand,
Double,
Split,
Hit,
};
enum class Info {
None,
InvalidBet,
NewHand,
Shuffle,
CardPlayer,
CardDealer,
CardDealerRevealsHole,
DealerBlackjack,
PlayerWinsInsurance,
PlayerBlackjackAlso,
PlayerNextHand,
PlayerPushes,
PlayerLosses,
PlayerBlackjack,
PlayerWins,
NoBlackjacks,
// PlayerBustsAllHands,
DealerBusts,
Help,
Bye,
};
// alphabetically-sorted
enum class Suit {
Clubs = 0,
Diamonds = 1,
Hearts = 2,
Spades = 3
};
enum class Color {
Black,
Red
};
};


class Card {
public:
Card(unsigned int);
@@ -119,14 +116,14 @@ class Card {
// TODO: delete copy & move
// TODO: decidir si conviene usar getters o public members
Suit getSuit() { return suit; };
Libreblackjack::Suit getSuit() { return suit; };
unsigned int getNumber() { return number; };
unsigned int getValue() { return value; };

std::string getNumberASCII() { return numberASCII; };
std::string getSuitUTF8() { return suitUTF8; };
Suit suit;
Libreblackjack::Suit suit;
unsigned int number;
unsigned int value;
@@ -154,7 +151,7 @@ class Hand {
std::list<unsigned int> cards;

// inline on purpose
int total() {
int value() {
unsigned int soft = 0;
unsigned int n = 0;
unsigned int value = 0;
@@ -175,19 +172,19 @@ class Hand {
// inline on purpose
bool blackjack() {
return (std::abs(total()) == 21 && cards.size() == 2);
return (std::abs(value()) == 21 && cards.size() == 2);
};
// inline on purpose
bool busted() {
return (std::abs(total()) > 21);
return (std::abs(value()) > 21);
}
};
class PlayerHand : public Hand {
public:
int bet = 0;
int id = 0;
std::size_t id;
unsigned int bet = 0;
bool insured = false;
bool doubled = false;
};
@@ -203,53 +200,61 @@ class Player {
Player(const Player &&) = delete;

virtual int play() = 0;
virtual void info(Info = Info::None, int = 0, int = 0) = 0;
virtual void info(Libreblackjack::Info = Libreblackjack::Info::None, int = 0, int = 0) = 0;
PlayerActionRequired actionRequired = PlayerActionRequired::None;
PlayerActionTaken actionTaken = PlayerActionTaken::None;

// TODO: one for the dealer and one for the player
unsigned int currentSplits = 0;
unsigned int currentBet = 0;
unsigned int n_hands = 0; // this is different from the dealer's due to splitting

unsigned int handsInsured = 0;
unsigned int handsDoubled = 0;
unsigned int blackjacksPlayer = 0;
unsigned int blackjacksDealer = 0;
Libreblackjack::PlayerActionRequired actionRequired = Libreblackjack::PlayerActionRequired::None;
Libreblackjack::PlayerActionTaken actionTaken = Libreblackjack::PlayerActionTaken::None;

unsigned int bustsPlayer = 0;
unsigned int bustsDealer = 0;
unsigned int wins = 0;
unsigned int winsInsured = 0;
unsigned int winsDoubled = 0;
unsigned int winsBlackjack = 0;
unsigned int pushes = 0;
unsigned int losses = 0;
// TODO: blackjack_pushes?
bool verbose = false;
bool flat_bet = false;
bool no_insurance = false;
bool always_insure = false;
double bankroll = 0;
double worst_bankroll = 0;
double total_money_waged = 0;
double current_result = 0;
double mean = 0;
double M2 = 0;
double variance = 0;
unsigned int currentBet;
std::list<PlayerHand> hands;
std::list<PlayerHand>::iterator currentHand;
std::size_t currentHandId = 0;

Hand dealerHand;
};

struct PlayerInfo {

std::list<PlayerHand> hands;
std::list<PlayerHand>::iterator currentHand;

unsigned int currentSplits = 0;
// unsigned int currentBet = 0;
unsigned int n_hands = 0; // this is different from the dealer's due to splitting

unsigned int handsInsured = 0;
unsigned int handsDoubled = 0;
unsigned int blackjacksPlayer = 0;
unsigned int blackjacksDealer = 0;

unsigned int bustsPlayer = 0;
unsigned int bustsDealer = 0;
unsigned int wins = 0;
unsigned int winsInsured = 0;
unsigned int winsDoubled = 0;
unsigned int winsBlackjack = 0;
unsigned int pushes = 0;
unsigned int losses = 0;
// TODO: blackjack_pushes?
double bankroll = 0;
double worstBankroll = 0;
double totalMoneyWaged = 0;
double currentResult = 0;
double mean = 0;
double M2 = 0;
double variance = 0;
};

class Dealer {
@@ -263,12 +268,16 @@ class Dealer {
Dealer(const Dealer &&) = delete;

// maybe this first one does not need to be deleted
virtual void shuffle() = 0;
virtual void deal(Player *) = 0;
virtual void shuffle(void) = 0;
virtual void deal(void) = 0;
virtual unsigned int drawCard(Hand * = nullptr) = 0;
virtual int process(Player *) = 0;
virtual int process(void) = 0;
void info(Player *player, Info msg, int p1 = 0, int p2 = 0) {
void setPlayer(Player *p) {
player = p;
}
void info(Libreblackjack::Info msg, int p1 = 0, int p2 = 0) {
if (player->verbose) {
player->info(msg, p1, p2);
}
@@ -283,13 +292,17 @@ class Dealer {
return (done = d);
}
DealerAction nextAction = DealerAction::None;
Libreblackjack::DealerAction nextAction = Libreblackjack::DealerAction::None;
// TODO: most of the games will have a single element, but maybe
// there are games where the dealer has more than one hand
// std::list <Hand> hands;
Hand hand;

// TODO: multiple players
Player *player;
PlayerInfo playerInfo;
private:
bool done = false;


+ 210
- 211
src/blackjack.cpp Datei anzeigen

@@ -73,17 +73,17 @@ Blackjack::~Blackjack() {
return;
}

void Blackjack::deal(Player *player) {
void Blackjack::deal(void) {
int playerTotal = 0;
int dealerTotal = 0;
bool playerBlackack = false;
// let's start by assuming the player does not need to do anything
player->actionRequired = PlayerActionRequired::None;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
switch(nextAction) {
// -------------------------------------------------------------------------
case DealerAction::StartNewHand:
case Libreblackjack::DealerAction::StartNewHand:
// check if we are done
if (n_hands > 0 && n_hand >= n_hands) {
@@ -96,13 +96,12 @@ void Blackjack::deal(Player *player) {
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm

if (n_hand != 0) {
double delta = player->current_result - player->mean;
player->mean += delta / (double)(n_hand);
player->M2 += delta * (player->current_result - player->mean);
player->variance = player->M2 / (double)(n_hand);
double delta = playerInfo.currentResult - playerInfo.mean;
playerInfo.mean += delta / (double)(n_hand);
playerInfo.M2 += delta * (playerInfo.currentResult - playerInfo.mean);
playerInfo.variance = playerInfo.M2 / (double)(n_hand);
}

// reset this index
i_arranged_cards = 0;
n_hand++;
@@ -110,19 +109,19 @@ void Blackjack::deal(Player *player) {
hand.cards.clear();

// erase all the player's hands, create one, add and make it the current one
for (auto playerHand : player->hands) {
for (auto playerHand : playerInfo.hands) {
playerHand.cards.clear();
}
player->hands.clear();
player->hands.push_back(std::move(PlayerHand()));
player->currentHand = player->hands.begin();
playerInfo.hands.clear();
playerInfo.hands.push_back(std::move(PlayerHand()));
playerInfo.currentHand = playerInfo.hands.begin();
// state that the player did not win anything nor splitted nor doubled down
player->current_result = 0;
player->currentSplits = 0;
playerInfo.currentResult = 0;
playerInfo.currentSplits = 0;
if (lastPass) {
info(player, Info::Shuffle);
info(Libreblackjack::Info::Shuffle);
// shuffle the cards
shuffle();
@@ -135,162 +134,161 @@ void Blackjack::deal(Player *player) {
}
if (player->flat_bet) {
player->currentHand->bet = player->flat_bet;
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::DealPlayerFirstCard;
playerInfo.currentHand->bet = player->flat_bet;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::DealPlayerFirstCard;
} else {
player->actionRequired = PlayerActionRequired::Bet;
nextAction = DealerAction::AskForBets;

player->actionRequired = Libreblackjack::PlayerActionRequired::Bet;
nextAction = Libreblackjack::DealerAction::AskForBets;
}

info(player, Info::NewHand, n_hand, 1e3*player->bankroll);
info(Libreblackjack::Info::NewHand, n_hand, 1e3*playerInfo.bankroll);
return;
break;
case DealerAction::AskForBets:
case Libreblackjack::DealerAction::AskForBets:
break;
// -------------------------------------------------------------------------
case DealerAction::DealPlayerFirstCard:
case Libreblackjack::DealerAction::DealPlayerFirstCard:
// where's step 2? <- probably that's the player's bet
// step 3. deal the first card to each player
player->n_hands++; // splits are counted as a single hand
player->total_money_waged += player->currentHand->bet;
playerInfo.n_hands++; // splits are counted as a single hand
playerInfo.totalMoneyWaged += playerInfo.currentHand->bet;

playerFirstCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerFirstCard);
playerFirstCard = drawCard(&(*playerInfo.currentHand));
info(Libreblackjack::Info::CardPlayer, playerFirstCard);
// step 4. show dealer's upcard
upCard = drawCard(&hand);
info(player, Info::CardDealer, upCard);
info(Libreblackjack::Info::CardDealer, upCard);

// step 5. deal the second card to each player
playerSecondCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerSecondCard);
playerSecondCard = drawCard(&(*playerInfo.currentHand));
info(Libreblackjack::Info::CardPlayer, playerSecondCard);
// step 6. deal the dealer's hole card
holeCard = drawCard(&hand);
info(player, Info::CardDealer);
info(Libreblackjack::Info::CardDealer);

// step 7.a. if the upcard is an ace ask for insurance
if (card[upCard].value == 11) {
if (player->no_insurance == false && player->always_insure == false) {
player->actionRequired = PlayerActionRequired::Insurance;
nextAction = DealerAction::AskForInsurance;
player->actionRequired = Libreblackjack::PlayerActionRequired::Insurance;
nextAction = Libreblackjack::DealerAction::AskForInsurance;
return;
} else if (player->always_insure) {
player->currentHand->insured = true;
playerInfo.currentHand->insured = true;
// TODO: allow insurance for less than one half of the original bet
player->current_result -= 0.5 * player->currentHand->bet;
player->bankroll -= 0.5 * player->currentHand->bet;
player->handsInsured++;
playerInfo.currentResult -= 0.5 * playerInfo.currentHand->bet;
playerInfo.bankroll -= 0.5 * playerInfo.currentHand->bet;
playerInfo.handsInsured++;
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::CheckforBlackjacks;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::CheckforBlackjacks;
return;
}
}
// step 7.b. if either the dealer or the player has a chance to have a blackjack, check
playerTotal = player->currentHand->total();
playerTotal = playerInfo.currentHand->value();
if ((card[upCard].value == 10 || card[upCard].value == 11) || std::abs(playerTotal) == 21) {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::CheckforBlackjacks;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::CheckforBlackjacks;
return;
}

// step 7.c. ask the player to play
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
break;
case DealerAction::AskForInsurance:
case Libreblackjack::DealerAction::AskForInsurance:
return;
break;

case DealerAction::CheckforBlackjacks:
case Libreblackjack::DealerAction::CheckforBlackjacks:
// step 8. check if there are any blackjack
playerBlackack = player->currentHand->blackjack();
if (hand.blackjack()) {
info(player, Info::CardDealerRevealsHole, holeCard);
info(player, Info::DealerBlackjack);
player->blackjacksDealer++;
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);
info(Libreblackjack::Info::DealerBlackjack);
playerInfo.blackjacksDealer++;

if (player->currentHand->insured) {
info(player, Info::PlayerWinsInsurance, 1e3*player->currentHand->bet);
player->current_result += player->currentHand->bet;
player->bankroll += player->currentHand->bet;
player->winsInsured++;
info(Libreblackjack::Info::PlayerWinsInsurance, 1e3*player->currentHand->bet);
playerInfo.currentResult += player->currentHand->bet;
playerInfo.bankroll += player->currentHand->bet;
playerInfo.winsInsured++;
}

if (playerBlackack) {
info(player, Info::PlayerBlackjackAlso);
info(player, Info::PlayerPushes, 1e3*player->currentHand->bet);
player->blackjacksPlayer++;
player->pushes++;
info(Libreblackjack::Info::PlayerBlackjackAlso);
info(Libreblackjack::Info::PlayerPushes, 1e3*player->currentHand->bet);
playerInfo.blackjacksPlayer++;
playerInfo.pushes++;
} else {
info(player, Info::PlayerLosses, 1e3*player->currentHand->bet);
player->current_result -= player->currentHand->bet;
player->bankroll -= player->currentHand->bet;
if (player->bankroll < player->worst_bankroll) {
player->worst_bankroll = player->bankroll;
info(Libreblackjack::Info::PlayerLosses, 1e3*player->currentHand->bet);
playerInfo.currentResult -= player->currentHand->bet;
playerInfo.bankroll -= player->currentHand->bet;
if (playerInfo.bankroll < playerInfo.worstBankroll) {
playerInfo.worstBankroll = playerInfo.bankroll;
}
player->losses++;
playerInfo.losses++;
}

nextAction = DealerAction::StartNewHand;
player->actionRequired = PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::StartNewHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
return;
} else if (playerBlackack) {
player->current_result += blackjack_pays * player->currentHand->bet;
player->bankroll += blackjack_pays * player->currentHand->bet;
player->blackjacksPlayer++;
playerInfo.currentResult += blackjack_pays * player->currentHand->bet;
playerInfo.bankroll += blackjack_pays * player->currentHand->bet;
playerInfo.blackjacksPlayer++;
info(player, Info::PlayerWins, 1e3 * blackjack_pays*player->currentHand->bet);
player->wins++;
player->winsBlackjack++;
info(Libreblackjack::Info::PlayerWins, 1e3 * blackjack_pays*player->currentHand->bet);
playerInfo.wins++;
playerInfo.winsBlackjack++;

nextAction = DealerAction::StartNewHand;
player->actionRequired = PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::StartNewHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
return;
} else {
// only if the dealer had the chance to have a blackjack we say "no_blackjacks"
if (card[upCard].value == 10 || card[upCard].value == 11) {
info(player, Info::NoBlackjacks);
info(Libreblackjack::Info::NoBlackjacks);
}
nextAction = DealerAction::AskForPlay;
player->actionRequired = PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
return;
}
break;
case DealerAction::AskForPlay:
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
case Libreblackjack::DealerAction::AskForPlay:
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
break;
case DealerAction::MoveOnToNextHand:
case Libreblackjack::DealerAction::MoveOnToNextHand:
// see if we finished all the player's hands
if (++player->currentHand != player->hands.end()) {
unsigned int playerCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerCard, player->currentHand->id);
info(Libreblackjack::Info::CardPlayer, playerCard, player->currentHand->id);

if (std::abs(player->currentHand->total()) == 21) {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
if (std::abs(player->currentHand->value()) == 21) {
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return;
} else {
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
}
} else {
@@ -304,74 +302,74 @@ void Blackjack::deal(Player *player) {
}

if (bustedAllHands) {
info(player, Info::CardDealerRevealsHole, holeCard);
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::StartNewHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::StartNewHand;
return;
} else {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::HitDealerHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::HitDealerHand;
return;
}
}
break;
case DealerAction::HitDealerHand:
case Libreblackjack::DealerAction::HitDealerHand:
info(player, Info::CardDealerRevealsHole, holeCard);
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);

// hit while count is less than 17 (or equal to soft 17 if hit_soft_17 is true)
dealerTotal = hand.total();
dealerTotal = hand.value();
while ((std::abs(dealerTotal) < 17 || (hit_soft_17 && dealerTotal == -17)) && hand.busted() == 0) {
unsigned int dealerCard = drawCard(&hand);
info(player, Info::CardDealer, dealerCard);
dealerTotal = hand.total();
info(Libreblackjack::Info::CardDealer, dealerCard);
dealerTotal = hand.value();
}

if (hand.busted()) {
info(player, Info::DealerBusts, dealerTotal);
player->bustsDealer++;
info(Libreblackjack::Info::DealerBusts, dealerTotal);
playerInfo.bustsDealer++;
for (auto playerHand : player->hands) {
if (playerHand.busted() == false) {
info(player, Info::PlayerWins, 1e3*playerHand.bet);
player->current_result += playerHand.bet;
player->bankroll += playerHand.bet;
player->wins++;
player->winsDoubled += playerHand.doubled;
info(Libreblackjack::Info::PlayerWins, 1e3*playerHand.bet);
playerInfo.currentResult += playerHand.bet;
playerInfo.bankroll += playerHand.bet;
playerInfo.wins++;
playerInfo.winsDoubled += playerHand.doubled;
}
}
} else {
for (auto playerHand : player->hands) {
if (playerHand.busted() == false) { // busted hands have already been solved
playerTotal = std::abs(playerHand.total());
playerTotal = std::abs(playerHand.value());
if (dealerTotal > playerTotal) {
info(player, Info::PlayerLosses, 1e3*playerHand.bet, playerTotal);
player->bankroll -= playerHand.bet;
if (player->bankroll < player->worst_bankroll) {
player->worst_bankroll = player->bankroll;
info(Libreblackjack::Info::PlayerLosses, 1e3*playerHand.bet, playerTotal);
playerInfo.bankroll -= playerHand.bet;
if (playerInfo.bankroll < playerInfo.worstBankroll) {
playerInfo.worstBankroll = playerInfo.bankroll;
}
player->losses++;
playerInfo.losses++;
} else if (dealerTotal == playerTotal) {
info(player, Info::PlayerPushes, 1e3*playerHand.bet);
player->pushes++;
info(Libreblackjack::Info::PlayerPushes, 1e3*playerHand.bet);
playerInfo.pushes++;
} else {
info(player, Info::PlayerWins, 1e3*playerHand.bet, playerTotal);
player->current_result += playerHand.bet;
player->bankroll += playerHand.bet;
player->wins++;
info(Libreblackjack::Info::PlayerWins, 1e3*playerHand.bet, playerTotal);
playerInfo.currentResult += playerHand.bet;
playerInfo.bankroll += playerHand.bet;
playerInfo.wins++;

if (playerHand.doubled) {
player->winsDoubled++;
playerInfo.winsDoubled++;
} else {
player->wins++;
playerInfo.wins++;
}
}
}
@@ -379,12 +377,12 @@ void Blackjack::deal(Player *player) {
}

player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::StartNewHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::StartNewHand;
return;
break;

case DealerAction::None:
case Libreblackjack::DealerAction::None:
break;

}
@@ -394,7 +392,7 @@ void Blackjack::deal(Player *player) {
// returns zero if it is a common command and we need to ask again
// returns positive if what was asked was answered
// returns negative if what was aked was not asnwered or the command does not apply
int Blackjack::process(Player *player) {
int Blackjack::process(void) {
unsigned int playerCard;
unsigned int firstCard;
@@ -409,7 +407,7 @@ int Blackjack::process(Player *player) {
///ig+quit+detail immediately without even finishing the hand.
///ig+quit+detail All IPC resources are unlocked, removed and/or destroyed.
///ig+quit+detail The YAML report is written before exiting.
case PlayerActionTaken::Quit:
case Libreblackjack::PlayerActionTaken::Quit:
finished(true);
return 1;
break;
@@ -418,52 +416,53 @@ int Blackjack::process(Player *player) {
///ig+help+desc Ask for help
///ig+help+detail A succinct help message is written on the standard output.
///ig+help+detail This command makes sense only when issued by a human player.
case PlayerActionTaken::Help:
info(player, Info::Help);
case Libreblackjack::PlayerActionTaken::Help:
info(Libreblackjack::Info::Help);
return 0;
break;
case PlayerActionTaken::None:
case Libreblackjack::PlayerActionTaken::None:
return 0;
break;
// if we made it this far, the command is particular
case PlayerActionTaken::Bet:
case Libreblackjack::PlayerActionTaken::Bet:
// TODO: bet = 0 -> wonging
if (player->currentBet == 0) {
info(player, Info::InvalidBet, player->currentBet);
info(Libreblackjack::Info::InvalidBet, player->currentBet);
return 0;
} else if (player->currentBet < 0) {
info(player, Info::InvalidBet, player->currentBet);
info(Libreblackjack::Info::InvalidBet, player->currentBet);
return 0;
} else if (max_bet != 0 && player->currentBet > max_bet) {
info(player, Info::InvalidBet, player->currentBet);
info(Libreblackjack::Info::InvalidBet, player->currentBet);
return 0;
} else {
// ok, valid bet
player->currentHand->bet = player->currentBet;
nextAction = DealerAction::DealPlayerFirstCard;
// ok, valid bet, copy the player's bet and use the local copy
// (to prevent cheating players from changing the bet after dealing)
playerInfo.currentHand->bet = player->currentBet;
nextAction = Libreblackjack::DealerAction::DealPlayerFirstCard;
return 1;
}
break;

case PlayerActionTaken::Insure:
case Libreblackjack::PlayerActionTaken::Insure:
// TODO: allow insurance for less than one half of the original bet
player->currentHand->insured = true;
player->current_result -= 0.5 * player->currentHand->bet;
player->bankroll -= 0.5 * player->currentHand->bet;
player->handsInsured++;
playerInfo.currentHand->insured = true;
playerInfo.currentResult -= 0.5 * playerInfo.currentHand->bet;
playerInfo.bankroll -= 0.5 * playerInfo.currentHand->bet;
playerInfo.handsInsured++;
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::CheckforBlackjacks;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::CheckforBlackjacks;
return 1;
break;

case PlayerActionTaken::DontInsure:
case Libreblackjack::PlayerActionTaken::DontInsure:
player->currentHand->insured = false;
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::CheckforBlackjacks;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::CheckforBlackjacks;
return 1;
break;

@@ -475,9 +474,9 @@ int Blackjack::process(Player *player) {
///ip+stand+detail Otherwise the dealer reveals his hole card and deals
///ip+stand+detail himself more cards if needed.
///ip+stand+detail This command can be abbreviated as `s`.
case PlayerActionTaken::Stand:
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
case Libreblackjack::PlayerActionTaken::Stand:
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
break;
@@ -488,29 +487,29 @@ int Blackjack::process(Player *player) {
///ip+double+detail Doubling down is allowed only after receiving the first
///ip+double+detail two cards.
///ip+double+detail This command can be abbreviated as `d`.
case PlayerActionTaken::Double:
if (player->currentHand->cards.size() == 2) {
case Libreblackjack::PlayerActionTaken::Double:
if (playerInfo.currentHand->cards.size() == 2) {

// TODO: check bankroll
player->total_money_waged += player->currentHand->bet;
player->currentHand->bet *= 2;
player->currentHand->doubled = true;
player->handsDoubled++;
playerCard = drawCard(&(*player->currentHand));
unsigned int playerTotal = player->currentHand->total();
info(player, Info::CardPlayer, playerCard, player->currentHand->id);
if (player->currentHand->busted()) {
info(player, Info::PlayerLosses, 1e3*player->currentHand->bet, playerTotal);
player->current_result -= player->currentHand->bet;
player->bankroll -= player->currentHand->bet;
player->bustsPlayer++;
player->losses++;
playerInfo.totalMoneyWaged += playerInfo.currentHand->bet;
playerInfo.currentHand->bet *= 2;
playerInfo.currentHand->doubled = true;
playerInfo.handsDoubled++;
playerCard = drawCard(&(*playerInfo.currentHand));
unsigned int playerTotal = playerInfo.currentHand->value();
info(Libreblackjack::Info::CardPlayer, playerCard, playerInfo.currentHand->id);
if (playerInfo.currentHand->busted()) {
info(Libreblackjack::Info::PlayerLosses, 1e3*playerInfo.currentHand->bet, playerTotal);
playerInfo.currentResult -= playerInfo.currentHand->bet;
playerInfo.bankroll -= playerInfo.currentHand->bet;
playerInfo.bustsPlayer++;
playerInfo.losses++;
}

player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
} else {
@@ -525,68 +524,68 @@ int Blackjack::process(Player *player) {
///ip+split+desc Split the current hand
///ip+split+detail
///ip+split+detail This command can be abbreviated as `p` (for pair).
case PlayerActionTaken::Split:
case Libreblackjack::PlayerActionTaken::Split:

firstCard = *(player->currentHand->cards.begin());
secondCard = *(++player->currentHand->cards.begin());
firstCard = *(playerInfo.currentHand->cards.begin());
secondCard = *(++playerInfo.currentHand->cards.begin());
// up to three splits (i.e. four hands)
// 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) {
if (playerInfo.currentSplits < 3 && playerInfo.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++;
playerInfo.currentSplits++;

// the first hand is id=1, then we add one
if (player->currentHand == player->hands.begin()) {
player->currentHand->id = 1;
if (playerInfo.currentHand == playerInfo.hands.begin()) {
playerInfo.currentHand->id = 1;
}
// create a new hand
PlayerHand newHand;
newHand.id = player->hands.size() + 1;
newHand.bet = player->currentHand->bet;
player->total_money_waged += player->currentHand->bet;
newHand.id = playerInfo.hands.size() + 1;
newHand.bet = playerInfo.currentHand->bet;
playerInfo.totalMoneyWaged += playerInfo.currentHand->bet;
// remove second the card from the first hand
player->currentHand->cards.pop_back();
playerInfo.currentHand->cards.pop_back();
// and put it into the second hand
newHand.cards.push_back(secondCard);

// add the new hand to the list of hands
player->hands.push_back(std::move(newHand));
playerInfo.hands.push_back(std::move(newHand));

// deal a card to the first hand
playerCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerCard, player->currentHand->id);
playerCard = drawCard(&(*playerInfo.currentHand));
info(Libreblackjack::Info::CardPlayer, playerCard, playerInfo.currentHand->id);

// aces get dealt only one card
// also, if the player gets 21 then we move on to the next hand
if (card[*player->currentHand->cards.begin()].value == 11 || std::abs(player->currentHand->total()) == 21) {
if (++player->currentHand != player->hands.end()) {
info(player, Info::PlayerNextHand, (*player->currentHand).id);
playerCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerCard, player->currentHand->id);
if (card[*playerInfo.currentHand->cards.begin()].value == 11 || std::abs(playerInfo.currentHand->value()) == 21) {
if (++playerInfo.currentHand != playerInfo.hands.end()) {
info(Libreblackjack::Info::PlayerNextHand, (*playerInfo.currentHand).id);
playerCard = drawCard(&(*playerInfo.currentHand));
info(Libreblackjack::Info::CardPlayer, playerCard, playerInfo.currentHand->id);

// if the player got an ace or 21 again, we are done
if (card[*player->currentHand->cards.begin()].value == 11 || std::abs(player->currentHand->total()) == 21) {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
if (card[*playerInfo.currentHand->cards.begin()].value == 11 || std::abs(playerInfo.currentHand->value()) == 21) {
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
} else {
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;
}
} else {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
}
} else {
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;
}
} else {
@@ -597,32 +596,32 @@ int Blackjack::process(Player *player) {
}
break;
case PlayerActionTaken::Hit:
case Libreblackjack::PlayerActionTaken::Hit:
///ip+hit+name hit
///ip+hit+desc Hit on the current hand
///ip+hit+detail
///ip+hit+detail This command can be abbreviated as `h`.
playerCard = drawCard(&(*player->currentHand));
info(player, Info::CardPlayer, playerCard, player->currentHand->id);
if (player->currentHand->busted()) {
info(player, Info::PlayerLosses, 1e3*player->currentHand->bet);
player->current_result -= player->currentHand->bet;
player->bankroll -= player->currentHand->bet;
player->bustsPlayer++;
player->losses++;
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
playerCard = drawCard(&(*playerInfo.currentHand));
info(Libreblackjack::Info::CardPlayer, playerCard, playerInfo.currentHand->id);
if (playerInfo.currentHand->busted()) {
info(Libreblackjack::Info::PlayerLosses, 1e3*playerInfo.currentHand->bet);
playerInfo.currentResult -= playerInfo.currentHand->bet;
playerInfo.bankroll -= playerInfo.currentHand->bet;
playerInfo.bustsPlayer++;
playerInfo.losses++;
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
} else if (std::abs(player->currentHand->total()) == 21) {
player->actionRequired = PlayerActionRequired::None;
nextAction = DealerAction::MoveOnToNextHand;
} else if (std::abs(playerInfo.currentHand->value()) == 21) {
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
} else {
player->actionRequired = PlayerActionRequired::Play;
nextAction = DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;
}
break;

+ 2
- 2
src/blackjack.h Datei anzeigen

@@ -34,8 +34,8 @@ class Blackjack : public Dealer {
void shuffle() override;
unsigned int drawCard(Hand * = nullptr) override;
void deal(Player *) override;
int process(Player *) override;
void deal(void) override;
int process(void) override;
private:

+ 5
- 5
src/cards.cpp Datei anzeigen

@@ -32,27 +32,27 @@ Card::Card(unsigned int tag) {
}
number = 1 + ((tag-1) % 13);
suit = static_cast<Suit>((tag-1)/13);
suit = static_cast<Libreblackjack::Suit>((tag-1)/13);
value = (number == 1) ? 11 : ((number > 10) ? 10 : number);
numberASCII = (number == 1) ? "A" : ((number < 11) ? std::to_string(number) : TJQK[number-10]);
switch (suit){
case Suit::Clubs:
case Libreblackjack::Suit::Clubs:
suitName = "clubs";
suitASCII = "C";
suitUTF8 = "♣";
break;
case Suit::Diamonds:
case Libreblackjack::Suit::Diamonds:
suitName = "diamonds";
suitASCII = "D";
suitUTF8 = "♦";
break;
case Suit::Hearts:
case Libreblackjack::Suit::Hearts:
suitName = "hearts";
suitASCII = "H";
suitUTF8 = "♥";
break;
case Suit::Spades:
case Libreblackjack::Suit::Spades:
suitName = "spades";
suitASCII = "S";
suitUTF8 = "♠";

+ 7
- 4
src/main.cpp Datei anzeigen

@@ -65,14 +65,17 @@ int main(int argc, char **argv) {
std::cerr << "Unknown player '" << conf.getPlayerName() <<".'" << std::endl;
return -1;
}
// assign player to dealer
dealer->setPlayer(player);

// let the action begin!
unsigned int unknownCommands = 0;
dealer->nextAction = DealerAction::StartNewHand;
dealer->nextAction = Libreblackjack::DealerAction::StartNewHand;
while (!dealer->finished()) {
dealer->deal(player);
if (player->actionRequired != PlayerActionRequired::None) {
dealer->deal();
if (player->actionRequired != Libreblackjack::PlayerActionRequired::None) {
unknownCommands = 0;
do {
if (unknownCommands++ > conf.max_incorrect_commands) {
@@ -80,7 +83,7 @@ int main(int argc, char **argv) {
return -2;
}
player->play();
} while (dealer->process(player) <= 0);
} while (dealer->process() <= 0);
}
}

+ 1
- 1
src/stdinout.cpp Datei anzeigen

@@ -34,7 +34,7 @@
StdInOut::StdInOut(void) {
}

void StdInOut::info(Info msg, int p1, int p2) {
void StdInOut::info(Libreblackjack::Info msg, int p1, int p2) {
return;
}


+ 1
- 1
src/stdinout.h Datei anzeigen

@@ -30,7 +30,7 @@ class StdInOut : public Player {
~StdInOut() { };
int play(void) override;
void info(Info = Info::None, int = 0, int = 0) override;
void info(Libreblackjack::Info = Libreblackjack::Info::None, int = 0, int = 0) override;
private:
std::string input_buffer;

+ 71
- 52
src/tty.cpp Datei anzeigen

@@ -85,7 +85,7 @@ Tty::Tty(Configuration &conf) {
return;
}

void Tty::info(Info msg, int p1, int p2) {
void Tty::info(Libreblackjack::Info msg, int p1, int p2) {
std::string s;
bool render = false;
@@ -93,7 +93,7 @@ void Tty::info(Info msg, int p1, int p2) {
switch (msg) {

case Info::InvalidBet:
case Libreblackjack::Info::InvalidBet:
if (p1 < 0) {
// s = "bet_negative";
s = "Your bet is negative (" + std::to_string(p1) + ")";
@@ -106,27 +106,46 @@ void Tty::info(Info msg, int p1, int p2) {
}
break;

case Info::NewHand:
case Libreblackjack::Info::NewHand:
// s = "new_hand";
std::cout << std::endl;
s = "Starting new hand #" + std::to_string(p1) + " with bankroll " + std::to_string(1e-3*p2);
// clear dealer's hand
dealerHand.cards.clear();

// erase all of our hands, create one, add and make it the current one
for (auto hand : hands) {
hand.cards.clear();
}
hands.clear();
hands.push_back(std::move(PlayerHand()));
currentHand = hands.begin();
currentHandId = 0;
break;
case Info::Shuffle:
case Libreblackjack::Info::Shuffle:
// TODO: ask the user to cut
// s = "shuffle";
s = "Deck needs to be shuffled.";
break;
case Info::CardPlayer:
case Libreblackjack::Info::CardPlayer:
// s = "card_player";
currentHandId = p2;
if (p2 != static_cast<int>(currentHandId)) {
for (currentHand = hands.begin(); currentHand != hands.end(); ++currentHand) {
if (static_cast<int>(currentHand->id) == p2) {
break;
}
}
currentHandId = p2;
}
currentHand->cards.push_back(p1);
s = "Player's card" + ((p2 != 0)?(" in hand #"+std::to_string(p2)):"") + " is " + card[p1].utf8();
break;
break;
case Info::CardDealer:
case Libreblackjack::Info::CardDealer:
if (p1 > 0) {
switch (dealerHand.cards.size()) {
case 0:
@@ -144,77 +163,77 @@ void Tty::info(Info msg, int p1, int p2) {
dealerHand.cards.push_back(p1);
break;
case Info::CardDealerRevealsHole:
case Libreblackjack::Info::CardDealerRevealsHole:
// s = "card_dealer_hole";
s = "Dealer's hole card was " + card[p1].utf8();
*(++(dealerHand.cards.begin())) = p1;
break;
case Info::DealerBlackjack:
case Libreblackjack::Info::DealerBlackjack:
// s = "dealer_blackjack";
s = "Dealer has Blackjack";
break;
case Info::PlayerWinsInsurance:
case Libreblackjack::Info::PlayerWinsInsurance:
// s = "player_wins_insurance";
s = "Player wins insurance";
break;
case Info::PlayerBlackjackAlso:
case Libreblackjack::Info::PlayerBlackjackAlso:
// s = "player_blackjack_also";
s = "Player also has Blackjack";
render = true;
break;

case Info::PlayerNextHand:
case Libreblackjack::Info::PlayerNextHand:
// s = "player_next_hand";
s = "Playing next hand #" + std::to_string(p1);
render = true;
break;
case Info::PlayerPushes:
case Libreblackjack::Info::PlayerPushes:
// s = "player_pushes";
s = "Player pushes " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : "");
render = true;
break;
case Info::PlayerLosses:
case Libreblackjack::Info::PlayerLosses:
// s = "player_losses";
s = "Player losses " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : "");
render = true;
break;
case Info::PlayerBlackjack:
case Libreblackjack::Info::PlayerBlackjack:
// s = "blackjack_player";
s = "Player has Blackjack";
render = true;
break;
case Info::PlayerWins:
case Libreblackjack::Info::PlayerWins:
// s = "player_wins";
s = "Player wins " + std::to_string(1e-3*p1) + ((p2 > 0) ? (" with " + std::to_string(p2)) : "");
render = true;
break;
case Info::NoBlackjacks:
case Libreblackjack::Info::NoBlackjacks:
// s = "no_blackjacks";
s = "No blackjacks";
break;

case Info::DealerBusts:
case Libreblackjack::Info::DealerBusts:
// s = "no_blackjacks";
s = "Dealer busts with " + std::to_string(p1);
break;
case Info::Help:
case Libreblackjack::Info::Help:
std::cout << "help yourself" << std::endl;
break;
case Info::Bye:
case Libreblackjack::Info::Bye:
// s = "bye";
s = "Bye bye! We'll play Blackjack again next time.";
break;
case Info::None:
case Libreblackjack::Info::None:
break;
}
@@ -235,21 +254,21 @@ int Tty::play() {

std::string s;
switch (actionRequired) {
case PlayerActionRequired::Bet:
case Libreblackjack::PlayerActionRequired::Bet:
s = "Bet?";
break;

case PlayerActionRequired::Insurance:
case Libreblackjack::PlayerActionRequired::Insurance:
renderTable();
s = "Insurance?";
break;
case PlayerActionRequired::Play:
case Libreblackjack::PlayerActionRequired::Play:
renderTable();
s = "Play?";
break;
case PlayerActionRequired::None:
case Libreblackjack::PlayerActionRequired::None:
break;
}
@@ -266,13 +285,13 @@ int Tty::play() {
if ((input_buffer = readline(prompt.c_str())) == nullptr) {
// EOF means "quit"
actionTaken = PlayerActionTaken::Quit;
actionTaken = Libreblackjack::PlayerActionTaken::Quit;
std::cout << std::endl;
} else {

add_history(input_buffer);
actionTaken = PlayerActionTaken::None;
actionTaken = Libreblackjack::PlayerActionTaken::None;

// TODO: better solution
std::string command = input_buffer;
@@ -282,54 +301,54 @@ int Tty::play() {
// check common commands first
if (command == "quit" || command == "q") {
actionTaken = PlayerActionTaken::Quit;
actionTaken = Libreblackjack::PlayerActionTaken::Quit;
} else if (command == "help") {
actionTaken = PlayerActionTaken::Help;
actionTaken = Libreblackjack::PlayerActionTaken::Help;
} else if (command == "count" || command == "c") {
actionTaken = PlayerActionTaken::Count;
actionTaken = Libreblackjack::PlayerActionTaken::Count;
} else if (command == "upcard" || command == "u") {
actionTaken = PlayerActionTaken::UpcardValue;
actionTaken = Libreblackjack::PlayerActionTaken::UpcardValue;
} else if (command == "bankroll" || command == "b") {
actionTaken = PlayerActionTaken::Bankroll;
actionTaken = Libreblackjack::PlayerActionTaken::Bankroll;
} else if (command == "hands") {
actionTaken = PlayerActionTaken::Hands;
actionTaken = Libreblackjack::PlayerActionTaken::Hands;
}
if (actionTaken == PlayerActionTaken::None) {
if (actionTaken == Libreblackjack::PlayerActionTaken::None) {
switch (actionRequired) {

case PlayerActionRequired::Bet:
case Libreblackjack::PlayerActionRequired::Bet:
currentBet = std::stoi(command);
actionTaken = PlayerActionTaken::Bet;
actionTaken = Libreblackjack::PlayerActionTaken::Bet;
break;

case PlayerActionRequired::Insurance:
case Libreblackjack::PlayerActionRequired::Insurance:
if (command == "y" || command == "yes") {
actionTaken = PlayerActionTaken::Insure;
actionTaken = Libreblackjack::PlayerActionTaken::Insure;
} else if (command == "n" || command == "no") {
actionTaken = PlayerActionTaken::DontInsure;
actionTaken = Libreblackjack::PlayerActionTaken::DontInsure;
} else {
// TODO: chosse if we allow not(yes) == no
actionTaken = PlayerActionTaken::None;
actionTaken = Libreblackjack::PlayerActionTaken::None;
}
break;

case PlayerActionRequired::Play:
case Libreblackjack::PlayerActionRequired::Play:
// TODO: sort by higher-expected response first
if (command == "h" || command =="hit") {
actionTaken = PlayerActionTaken::Hit;
actionTaken = Libreblackjack::PlayerActionTaken::Hit;
} else if (command == "s" || command == "stand") {
actionTaken = PlayerActionTaken::Stand;
actionTaken = Libreblackjack::PlayerActionTaken::Stand;
} else if (command == "d" || command == "double") {
actionTaken = PlayerActionTaken::Double;
actionTaken = Libreblackjack::PlayerActionTaken::Double;
} else if (command == "p" || command == "split" || command == "pair") {
actionTaken = PlayerActionTaken::Split;
actionTaken = Libreblackjack::PlayerActionTaken::Split;
} else {
actionTaken = PlayerActionTaken::None;
actionTaken = Libreblackjack::PlayerActionTaken::None;
}
break;
case PlayerActionRequired::None:
case Libreblackjack::PlayerActionRequired::None:
break;
}
@@ -358,12 +377,12 @@ void Tty::renderTable(void) {

std::cout << " -- Dealer's hand: --------" << std::endl;
renderHand(&dealerHand);
std::cout << " Total: " << ((dealerHand.total() < 0)?"soft ":"") << std::abs(dealerHand.total()) << std::endl;
std::cout << " Value: " << ((dealerHand.value() < 0)?"soft ":"") << std::abs(dealerHand.value()) << std::endl;

std::cout << " -- Player's hand --------" << std::endl;
for (auto hand : hands) {
renderHand(&hand, (hand.id != 0) && (hand.id == currentHandId));
std::cout << " Total: " << ((hand.total() < 0)?"soft ":"") << std::abs(hand.total()) << std::endl;
std::cout << " Value: " << ((hand.value() < 0)?"soft ":"") << std::abs(hand.value()) << std::endl;
}

return;
@@ -382,7 +401,7 @@ void Tty::renderHand(Hand *hand, bool current) {
// std::cout << "hand id = " << hand->id << std::endl;
for (auto c : hand->cards) {
if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) {
if (color && (card[c].suit == Libreblackjack::Suit::Diamonds || card[c].suit == Libreblackjack::Suit::Hearts)) {
ansiColor = red;
ansiReset = reset;
} else {
@@ -408,7 +427,7 @@ void Tty::renderHand(Hand *hand, bool current) {
std::cout << std::endl;
for (auto c : hand->cards) {
if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) {
if (color && (card[c].suit == Libreblackjack::Suit::Diamonds || card[c].suit == Libreblackjack::Suit::Hearts)) {
ansiColor = red;
ansiReset = reset;
} else {
@@ -437,7 +456,7 @@ void Tty::renderHand(Hand *hand, bool current) {
std::cout << std::endl;

for (auto c : hand->cards) {
if (color && (card[c].suit == Suit::Diamonds || card[c].suit == Suit::Hearts)) {
if (color && (card[c].suit == Libreblackjack::Suit::Diamonds || card[c].suit == Libreblackjack::Suit::Hearts)) {
ansiColor = red;
ansiReset = reset;
} else {

+ 1
- 1
src/tty.h Datei anzeigen

@@ -37,7 +37,7 @@ class Tty : public Player {
~Tty() { };
int play() override;
void info(Info = Info::None, int = 0, int = 0) override;
void info(Libreblackjack::Info = Libreblackjack::Info::None, int = 0, int = 0) override;

// for readline's autocompletion
static char *rl_command_generator(const char *, int);

Laden…
Abbrechen
Speichern