ソースを参照

ace-five, shoes

master
gtheler 5年前
コミット
dd6ba6e896
8個のファイルの変更195行の追加13行の削除
  1. +1
    -0
      players/30-ace-five/.gitignore
  2. +164
    -0
      players/30-ace-five/ace-five.py
  3. +4
    -0
      players/30-ace-five/run.sh
  4. バイナリ
      players/30-ace-five/wizard_strategy.png
  5. +2
    -1
      src/base.h
  6. +19
    -9
      src/blackjack.cpp
  7. +2
    -0
      src/blackjack.h
  8. +3
    -3
      src/stdinout.cpp

+ 1
- 0
players/30-ace-five/.gitignore ファイルの表示

@@ -0,0 +1 @@
fifo

+ 164
- 0
players/30-ace-five/ace-five.py ファイルの表示

@@ -0,0 +1,164 @@
#!/usr/bin/python3

# plays the wizard's ace-five count
# <http://wizardofodds.com/games/blackjack/appendix/17/>
# with the simple strategy at
# <http://wizardofodds.com/games/blackjack/appendix/21/>
#
#
# Player's hand Dealer's upcard
#
# -- hard --------------------------------
# 2 to 6 7 to A
# 4 to 8 H H
# 9 D H
# 10 or 11 D with more than dealer
# 12 to 16 S H
# 17 to 21 S S
#
# -- soft --------------------------------
# 2 to 6 7 to A
# 13 to 15 H H
# 16 to 18 D H
# 19 to 21 S S
#
# -- split -------------------------------
# 2 to 6 7 to A
# 22,33,66,77,99 Y N
# 88,AA Y Y
# 44,55,TT N N
#
# Plus:
# 1. surrender 16 vs 10
# 2. never take insurance
# 3. if not allowed to double, stand with soft 18
#

import sys

max_bet = 32

n_player_cards = 0
count = 0
bet = 1

import fileinput

for linenl in fileinput.input():
line = linenl.rstrip()
#print("<- %s" % line, file = sys.stderr)
if line == "bye":
sys.exit(0)
elif line == "shuffling":
count = 0
bet = 1
elif line[:8] == "new_hand":
n_player_cards = 0

elif line == "insurance?":
print("no", flush = True)
elif line == "bet?":
#if count <= 1:
#bet = 1
#elif bet < max_bet:
#bet *= 2
#print(bet, flush = True)
print("1", flush = True)
elif line[:15] == "player_split_ok":
n_player_cards = 1

elif line[:5] == "card_":
tokens = line.split()
if (len(tokens) > 1):
card = tokens[1][0]
else:
card = ""
# count aces and fives
if card == "A":
count -= 1
elif card == "5":
count += 1

if line[:11] == "card_player":
n_player_cards += 1
if n_player_cards == 1:
card_player_first = card
elif n_player_cards == 2:
card_player_second = card
elif line[:5] == "play?":
tokens = line.split()
player = int(tokens[1])
dealer = abs(int(tokens[2]))
action = "quit"
#print("player_cards %d" % n_player_cards, file = sys.stderr)
#print("card_player_first %s" % card_player_first, file = sys.stderr)
#print("card_player_second %s" % card_player_second, file = sys.stderr)

if n_player_cards == 2 and card_player_first == card_player_second and \
((card_player_first == "8" or card_player_first == "A") or \
(dealer < 7 and \
(card_player_first == "2" or \
card_player_first == "3" or \
card_player_first == "6" or \
card_player_first == "7" or \
card_player_first == "9"))): # --- split------------------------------------
action = "split" # always split aces and 8s but 2,3,6,7 & 9 only against 6 or less
else:
if player > 0: # --- hard ------------------------------------
if player < 9:
action = "hit" # hit 4 to 8 against anything
elif player == 9:
if dealer < 7:
if n_player_cards == 2:
action = "double" # double 9 against 2 to 6
else:
action = "hit" # else hit
else:
action = "hit" # hit 9 against 7 to A
elif player < 12:
if player > dealer:
if n_player_cards == 2:
action = "double" # double with 10 or 11 and more than dealer
else:
action = "hit"
else:
action = "hit" # otherwise hit
elif player < 17:
if dealer < 7:
action = "stand" # stand with 12 to 16 against 2 to 6
else:
action = "hit" # hit with 12 to 16 against 7 to A
else:
action = "stand" # stand with hard 17 or more
else:
# soft
player = abs(player)
if player < 16:
action = "hit" # hit every soft hand less than 16
elif player < 19:
if dealer < 7:
if n_player_cards == 2:
action = "double" # double soft 16 to 18 againt 2 to 6
elif player == 18:
action = "stand" # stand with soft 18
else:
action = "hit" # hit soft 17
else:
action = "hit" # hit soft 16 to 18 against 7 to A
else:
action = "stand" # stand with soft 19 or more
print(action, flush = True)
#print("-> %s" % action, file = sys.stderr)
elif line == "invalid_command":
print("I sent an invalid command!", file = sys.stderr)


+ 4
- 0
players/30-ace-five/run.sh ファイルの表示

@@ -0,0 +1,4 @@
if test ! -e fifo; then
mkfifo fifo
fi
blackjack --player=stdio --verbose=true -n10000 < fifo | ./ace-five.py > fifo

バイナリ
players/30-ace-five/wizard_strategy.png ファイルの表示

変更前 変更後
幅: 304  |  高さ: 546  |  サイズ: 7.3KB

+ 2
- 1
src/base.h ファイルの表示

@@ -287,7 +287,8 @@ class Dealer {
// how many standard deviations does the reported error mean?
double error_standard_deviations = 3.0;
// default infinite number of decks (it's faster)
int n_decks = -1;
unsigned int n_decks = 0;
unsigned int n_shuffles = 0;
// default one million hands
unsigned long int n_hands = 1000000;

+ 19
- 9
src/blackjack.cpp ファイルの表示

@@ -73,6 +73,15 @@ Blackjack::Blackjack(Configuration &conf) : rng(dev_random()), fiftyTwoCards(1,
if (explicit_seed) {
rng = std::mt19937(rng_seed);
}
if (n_decks > 0) {
shoe.resize(52*n_decks);
for (unsigned int deck = 0; deck < n_decks; deck++) {
for (unsigned int c = 1; c <= 52; c++) {
shoe.push_back(c);
}
}
}
}

Blackjack::~Blackjack() {
@@ -742,15 +751,12 @@ void Blackjack::shuffle() {
// for infinite decks there is no need to shuffle (how would one do it?)
// we just pick a random card when we need to deal and that's it
if (n_decks == -1) {
return;
if (n_decks > 0) {
std::shuffle(shoe.begin(), shoe.end(), rng);
n_shuffles++;
}
// TODO: shuffle shoe
return;
}


@@ -758,7 +764,7 @@ unsigned int Blackjack::drawCard(Hand *hand) {
unsigned int tag = 0;

if (n_decks == -1) {
if (n_decks == 0) {
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 > 52) {
@@ -769,8 +775,12 @@ unsigned int Blackjack::drawCard(Hand *hand) {
}
} else {
// TODO: shoes
tag = 0;
if (pos >= 52 * n_decks) {
return 0;
}
// lastPass = pos >= cutCardPos || shuffle_every_hand;
tag = shoe[pos++];
}
if (hand != nullptr) {

+ 2
- 0
src/blackjack.h ファイルの表示

@@ -45,6 +45,8 @@ class Blackjack : public Dealer {
std::uniform_int_distribution<unsigned int> fiftyTwoCards;
bool lastPass = false;
std::vector<unsigned int> shoe;
size_t pos;
unsigned int upCard;
unsigned int holeCard;

+ 3
- 3
src/stdinout.cpp ファイルの表示

@@ -81,7 +81,7 @@ void StdInOut::info(Libreblackjack::Info msg, int p1, int p2) {
break;
case Libreblackjack::Info::CardPlayer:
s = "card_player " + ((p2 != 0)?(std::to_string(p2)+ " "):"") + card[p1].ascii();
s = "card_player " + card[p1].ascii() + " " + ((p2 != 0)?(std::to_string(p2)+ " "):"") ;
if (p2 != static_cast<int>(currentHandId)) {
for (currentHand = hands.begin(); currentHand != hands.end(); ++currentHand) {
if (static_cast<int>(currentHand->id) == p2) {
@@ -134,7 +134,7 @@ void StdInOut::info(Libreblackjack::Info msg, int p1, int p2) {
break;

case Libreblackjack::Info::PlayerSplitOk:
s = "player_split_ok" + ((p1 != 0)?(" #" + std::to_string(p1)):"");
s = "player_split_ok" + ((p1 != 0)?std::to_string(p1):"");
handToSplit = p1;
break;

@@ -163,7 +163,7 @@ void StdInOut::info(Libreblackjack::Info msg, int p1, int p2) {
}
currentHandId = p1;
s = "new_hand " + std::to_string(p2) + " " + card[cardToSplit].ascii();
s = "new_split_hand " + std::to_string(p2) + " " + card[cardToSplit].ascii();
break;

case Libreblackjack::Info::PlayerDoubleInvalid:

読み込み中…
キャンセル
保存