Ver código fonte

splits in internal

master
gtheler 5 anos atrás
pai
commit
dae9ddb57a
4 arquivos alterados com 105 adições e 46 exclusões
  1. +8
    -10
      src/base.h
  2. +44
    -13
      src/blackjack.cpp
  3. +5
    -0
      src/blackjack.h
  4. +48
    -23
      src/internal.cpp

+ 8
- 10
src/base.h Ver arquivo

@@ -116,23 +116,19 @@ class Card {
public:
Card(unsigned int);
~Card() { };
// TODO: delete copy & move
// TODO: decidir si conviene usar getters o public members
Libreblackjack::Suit getSuit() { return suit; };
unsigned int getNumber() { return number; };
unsigned int getValue() { return value; };
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; };
std::string getNumberASCII() { return numberASCII; };
std::string getSuitUTF8() { return suitUTF8; };
Libreblackjack::Suit suit;
unsigned int number;
unsigned int value;
std::string ascii() {
return numberASCII + suitASCII;
}
std::string ascii() { return numberASCII + suitASCII; };
std::string utf8(bool single = false) {
return single ? singleUTF8 : numberASCII + suitUTF8;
}
@@ -211,6 +207,8 @@ class Player {

int dealerValue = 0;
int playerValue = 0;
bool canDouble = false;
bool canSplit = false;
bool verbose = false;
bool flat_bet = false;

+ 44
- 13
src/blackjack.cpp Ver arquivo

@@ -128,7 +128,9 @@ void Blackjack::deal(void) {
}

info(Libreblackjack::Info::NewHand, n_hand, 1e3*playerStats.bankroll);
// std::cout << "new hand #" << n_hand << std::endl;
#ifdef BJDEBUG
std::cout << "new hand #" << n_hand << std::endl;
#endif
if (player->flat_bet) {
@@ -161,19 +163,24 @@ void Blackjack::deal(void) {
// step 3. deal the first card to each player
playerFirstCard = drawCard(&(*playerStats.currentHand));
info(Libreblackjack::Info::CardPlayer, playerFirstCard);
// std::cout << "first card " << card[playerFirstCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "first card " << card[playerFirstCard].utf8() << std::endl;
#endif
// step 4. show dealer's upcard
upCard = drawCard(&hand);
info(Libreblackjack::Info::CardDealer, upCard);
// std::cout << "up card " << card[upCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "up card " << card[upCard].utf8() << std::endl;
#endif
player->dealerValue = hand.value();

// step 5. deal the second card to each player
playerSecondCard = drawCard(&(*playerStats.currentHand));
info(Libreblackjack::Info::CardPlayer, playerSecondCard);
player->playerValue = playerStats.currentHand->value();
// std::cout << "second card " << card[playerSecondCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "second card " << card[playerSecondCard].utf8() << std::endl;
#endif
// step 6. deal the dealer's hole card
holeCard = drawCard(&hand);
@@ -210,6 +217,8 @@ void Blackjack::deal(void) {
}

// step 7.c. ask the player to play
player->canDouble = true;
player->canSplit = card[playerFirstCard].value == card[playerSecondCard].value;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
@@ -221,7 +230,9 @@ void Blackjack::deal(void) {
if (hand.blackjack()) {
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);
info(Libreblackjack::Info::DealerBlackjack);
// std::cout << "dealer blakjack " << card[holeCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "dealer blakjack " << card[holeCard].utf8() << std::endl;
#endif
playerStats.blackjacksDealer++;

if (playerStats.currentHand->insured) {
@@ -236,7 +247,9 @@ void Blackjack::deal(void) {

if (playerBlackjack) {
info(Libreblackjack::Info::PlayerBlackjackAlso);
// std::cout << "both blackjack " << card[holeCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "both blackjack " << card[holeCard].utf8() << std::endl;
#endif

// give him his (her her) money back
playerStats.bankroll += playerStats.currentHand->bet;
@@ -278,6 +291,7 @@ void Blackjack::deal(void) {
info(Libreblackjack::Info::NoBlackjacks);
}
canDoubleSplit();
nextAction = Libreblackjack::DealerAction::AskForPlay;
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
return;
@@ -285,6 +299,10 @@ void Blackjack::deal(void) {
break;
case Libreblackjack::DealerAction::AskForPlay:
#ifdef BJDEBUG
std::cout << "pistola" << std::endl;
#endif
canDoubleSplit();
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
@@ -296,13 +314,16 @@ void Blackjack::deal(void) {
unsigned int playerCard = drawCard(&(*playerStats.currentHand));
player->playerValue = playerStats.currentHand->value();
info(Libreblackjack::Info::CardPlayer, playerCard, playerStats.currentHand->id);
// std::cout << "card player " << card[playerCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "card player " << card[playerCard].utf8() << std::endl;
#endif

if (std::abs(player->playerValue) == 21) {
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return;
} else {
canDoubleSplit();
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return;
@@ -320,7 +341,9 @@ void Blackjack::deal(void) {

if (bustedAllHands) {
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);
// std::cout << "hole " << card[holeCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "hole " << card[holeCard].utf8() << std::endl;
#endif
player->actionRequired = Libreblackjack::PlayerActionRequired::None;
nextAction = Libreblackjack::DealerAction::StartNewHand;
@@ -336,14 +359,18 @@ void Blackjack::deal(void) {
case Libreblackjack::DealerAction::HitDealerHand:
info(Libreblackjack::Info::CardDealerRevealsHole, holeCard);
// std::cout << "hole " << card[holeCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "hole " << card[holeCard].utf8() << std::endl;
#endif

// hit while count is less than 17 (or equal to soft 17 if hit_soft_17 is true)
player->dealerValue = hand.value();
while ((std::abs(player->dealerValue) < 17 || (hit_soft_17 && player->dealerValue == -17)) && hand.busted() == 0) {
unsigned int dealerCard = drawCard(&hand);
info(Libreblackjack::Info::CardDealer, dealerCard);
// std::cout << "dealer " << card[dealerCard].utf8() << std::endl;
#ifdef BJDEBUG
std::cout << "dealer " << card[dealerCard].utf8() << std::endl;
#endif
player->dealerValue = hand.value();
}
@@ -574,9 +601,10 @@ int Blackjack::process(void) {
secondCard = *(++playerStats.currentHand->cards.begin());
// up to three splits (i.e. four hands)
// TODO: choose through conf
// TODO: choose through conf how many max splits are available
// TODO: check bankroll to see if player can split
if (playerStats.splits < 3 && playerStats.currentHand->cards.size() == 2 && card[firstCard].value == card[secondCard].value) {
// if (playerStats.splits < 3 && playerStats.currentHand->cards.size() == 2 && card[firstCard].value == card[secondCard].value) {
if (playerStats.currentHand->cards.size() == 2 && card[firstCard].value == card[secondCard].value) {
// take player's money
playerStats.bankroll -= playerStats.currentHand->bet;
@@ -633,6 +661,7 @@ int Blackjack::process(void) {
nextAction = Libreblackjack::DealerAction::MoveOnToNextHand;
return 1;
} else {
canDoubleSplit();
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;
@@ -643,6 +672,7 @@ int Blackjack::process(void) {
return 1;
}
} else {
canDoubleSplit();
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;
@@ -683,6 +713,7 @@ int Blackjack::process(void) {
} else {
canDoubleSplit();
player->actionRequired = Libreblackjack::PlayerActionRequired::Play;
nextAction = Libreblackjack::DealerAction::AskForPlay;
return 1;

+ 5
- 0
src/blackjack.h Ver arquivo

@@ -70,6 +70,11 @@ class Blackjack : public Dealer {
double penetration = 0.75;
double penetration_sigma = 0;
void canDoubleSplit(void) {
player->canDouble = playerStats.currentHand->cards.size() == 2;
player->canSplit = player->canDouble && (card[*(playerStats.currentHand->cards.begin())].value == card[*(++playerStats.currentHand->cards.begin())].value);
return;
}
};
#endif

+ 48
- 23
src/internal.cpp Ver arquivo

@@ -32,20 +32,17 @@ Internal::Internal(Configuration &conf) {
hard.resize(21); // 4--20
soft.resize(21); // 12--20
pair.resize(12); // 2--11
pair.resize(21); // 2*(2--10) + 11
for (int value = 0; value < 21; value++) {
hard[value].resize(12);
soft[value].resize(12);
if (value < 12) {
pair[value].resize(12);
}
pair[value].resize(12);

for (int upcard = 0; upcard < 12; upcard++) {
hard[value][upcard] = Libreblackjack::PlayerActionTaken::None;
soft[value][upcard] = Libreblackjack::PlayerActionTaken::None;
if (value < 12) {
pair[value][upcard] = Libreblackjack::PlayerActionTaken::None;
}
pair[value][upcard] = Libreblackjack::PlayerActionTaken::None;
}
}
// TODO: read a default basic strategy
@@ -76,6 +73,7 @@ Internal::Internal(Configuration &conf) {
break;
case 'p':
strategy = &pair;
// see below how we handle these two cases
if (token[1] == 'A') {
value = 11;
} else if (token[1] == 'T') {
@@ -98,9 +96,21 @@ Internal::Internal(Configuration &conf) {
} else if (token == "d") {
(*strategy)[value][upcard] = Libreblackjack::PlayerActionTaken::Double;
} else if (token == "y") {
(*strategy)[value][upcard] = Libreblackjack::PlayerActionTaken::Split;
// the pair data is different as it is not written as a function of the value
// but of the value of the individual cards,
// i.e. p8 means split a pair of eights and not a hand with two fours
// to avoid clashing a pair of aces with a pair of sixes, we treat the former differently
if (value != 11) {
(*strategy)[2*value][upcard] = Libreblackjack::PlayerActionTaken::Split;
} else {
(*strategy)[11][upcard] = Libreblackjack::PlayerActionTaken::Split;
}
} else if (token == "n") {
(*strategy)[value][upcard] = Libreblackjack::PlayerActionTaken::None;
if (value != 11) {
(*strategy)[2*value][upcard] = Libreblackjack::PlayerActionTaken::None;
} else {
(*strategy)[11][upcard] = Libreblackjack::PlayerActionTaken::None;
}
}
}
}
@@ -115,6 +125,9 @@ void Internal::info(Libreblackjack::Info msg, int p1, int p2) {

int Internal::play() {

std::size_t value;
std::size_t upcard;
switch (actionRequired) {
case Libreblackjack::PlayerActionRequired::Bet:
currentBet = 1;
@@ -127,30 +140,42 @@ int Internal::play() {
case Libreblackjack::PlayerActionRequired::Play:

// std::cout << "player " << playerValue << " dealer " << dealerValue << std::endl;
// TODO: split
// soft
{
std::size_t value = std::abs(playerValue);
std::size_t upcard = std::abs(dealerValue);
#ifdef BJDEBUG
std::cout << "player " << playerValue << " dealer " << dealerValue << std::endl;
#endif
value = std::abs(playerValue);
upcard = std::abs(dealerValue);
// first, we see if we can and shold split
if (canSplit &&
((playerValue == -12 && pair[11][upcard] == Libreblackjack::PlayerActionTaken::Split) ||
pair[value][upcard] == Libreblackjack::PlayerActionTaken::Split)) {
actionTaken = Libreblackjack::PlayerActionTaken::Split;

} else {
actionTaken = (playerValue < 0) ? soft[value][upcard] : hard[value][upcard];
// TODO: double
if (actionTaken == Libreblackjack::PlayerActionTaken::Double) {
actionTaken = Libreblackjack::PlayerActionTaken::Hit;
if (canDouble == false) {
if (actionTaken == Libreblackjack::PlayerActionTaken::Double) {
actionTaken = Libreblackjack::PlayerActionTaken::Hit;
}
}
}
/*
}
#ifdef BJDEBUG
if (actionTaken == Libreblackjack::PlayerActionTaken::Hit) {
std::cout << "hit" << std::endl;
} else if (actionTaken == Libreblackjack::PlayerActionTaken::Stand) {
std::cout << "stand" << std::endl;
} else if (actionTaken == Libreblackjack::PlayerActionTaken::Split) {
std::cout << "split" << std::endl;
} else {
std::cout << "none" << std::endl;
}
*/
#endif
break;
case Libreblackjack::PlayerActionRequired::None:

Carregando…
Cancelar
Salvar