Quellcode durchsuchen

no readline support

master
gtheler vor 5 Jahren
Ursprung
Commit
bf5da69ace
4 geänderte Dateien mit 379 neuen und 87 gelöschten Zeilen
  1. +143
    -1
      README.md
  2. +5
    -4
      autogen.sh
  3. +162
    -0
      doc/interactive.cast
  4. +69
    -82
      src/tty.cpp

+ 143
- 1
README.md Datei anzeigen

@@ -1 +1,143 @@
# LibreBlackjack
---
title: Libre Blackjack, a free blackjack back end
lang: en-US
...


# Libre Blackjack

> A [free](https://www.gnu.org/philosophy/free-sw.html) [Blackjack](https://en.wikipedia.org/wiki/Blackjack) back end inspired by [GNU Chess](https://www.gnu.org/software/chess/).

[Libre Blackjack](https://www.seamplex.com/blackjack) is a blackjack engine that emulates a dealer, deals (digital) cards and understands plain-text commands such as `hit` or `stand`. The basic idea is that one or more players can talk to Libre Blackjack either in an interactive or in an automated way through
* the standard input and/or output (optionally using named pipes or TCP (web)sockets with `netcat` or `gwsocket`), or
* C++ methods (optionally loaded at runtime from shared objects TBD).
These players can be actual human players playing in real-time through a front end (a GUI application, a web-based interface, a mobile app, etc.) or robots that implement a certain betting and playing strategy playing (i.e. card counting) as fast as possible to study and analyze game statistics. There is an internal player that reads the strategy from a text file and plays accordingly. It can also be used to play interactive [ASCII blackjack](#play):

```{=html}
<asciinema-player src="doc/interactive.cast" cols="89" rows="28" preload="true" poster="npt:0:20"></asciinema-player>
```



## Why

:::{.alert .alert-light}
> “I am often surprised that when people drive down two-lane roads, they will trust complete strangers in the oncoming lane not to swerve into their lane causing a head-on collision; but they will not trust mathematicians to create the correct strategy for Blackjack.”
>
> [Norman Wattenberger, Modern Blackjack, 2009]{.blockquote-footer}
:::

With Libre Blackjack you do not have to trust other people anymore. You have a free blackjack engine which you can

0. run as you wish, to see the results of billions of blackjack hands,
1. study to see how it works and change it if you do not like it,
2. share it with your friends and colleagues, and
3. distribute copies of your modified versions.

If you do not know how to program, you have the _freedom_ to hire a programmer to do it for you. That is why [Libre Blackjack](https://www.seamplex.com/blackjack) is [free software](https://www.gnu.org/philosophy/free-sw.html).


## How

Once you trust the blackjack engine is fair, you can model and simulate any blackjack situation you want, playing millions of times a certain hand (say a sixteen against a ten) in different ways (say hitting or standing) to obtain you own conclusions. You can even build the [basic strategy charts](https://wizardofodds.com/games/blackjack/strategy/4-decks/) from scratch to convince yourself there is no [flaw](https://wizardofodds.com/ask-the-wizard/blackjack/).

The main objective is research and optimization of playing and betting strategies depending on

* particular table rules (number of decks, hit on soft 17, double after split, etc.),
* card counting strategies
* risk of ruin
* removal of cards
* arranged shoes
These automatic players can range from simple no-bust or mimic-the-dealer hitters or standers, up to neural-networks trained players taking into account every card being dealt passing through basic strategy modified by traditional card counting mechanisms.

# Quick start


```
sudo apt-get install git autoconf make gcc
git clone https://github.com/seamplex/libreblackjack.git
cd libreblackjack
./autogen.sh
./configure
make
sudo make install
```

If you wan tab completion of commands and browseable history, make sure you also have [GNU Readline](http://tiswww.case.edu/php/chet/readline/rltop.html) available at compilation time.


## Test suite

Run as test suite to check the code work as expected.

```
$ make check
```

The subdirectory `players` contains some automatic players that play against Libre Blackjack. These players are coded in different languages and communicate with Libre Blackjack in a variety of ways in order to illustrate the design basis:

* [00-internal](players/00-internal) uses the internal player that defaults to playing one million hands of basic strategy
* [02-always-stand](players/02-always-stand), using the UNIX tool `yes` this player always says “stand” into the standard output (which is piped to `blackjack`’s standard input) no matter what the cards are
* [05-no-bust](players/05-no-bust) is a PERL-based player does not bust (i.e. hits if the hard total is less than twelve) that receives the cards through the standard input but draws or stands using a FIFO to talk back to the dealer
* [08-mimic-the-dealer](players/08-mimic-the-dealer) follows what the dealer does (i.e. hits soft seventeens). It is implemented in AWK using two FIFOs.
* [20-basic-strategy](players/20-basic-strategy) derives the basic strategy from scratch in less than one minute by creating all the possible combination of hitting/standing/doubling/pairing strategies in an ASCII text file that the internal player can read and use.


# Play

Run Libre Blackjack with no arguments to play Blackjack interactively in ASCII mode.

```{=html}
<asciinema-player src="doc/libreblackjack2.cast" cols="89" rows="28" preload="true" poster="npt:0:20"></asciinema-player>
```

Edit the file [`blackjack.conf`](https://github.com/seamplex/libreblackjack/blob/master/blackjack.conf) in the same directory where the executable is run to set up rules, arranged shoes and other options. Type `help` at the prompt to get it.

## Automatic playing

The differential value of Libre Blackjack is that players can be programmed to play employing different strategies, card-counting techniques or even state-of-the-art AI algorithms.

See the directory [`players`](players) for examples of how to write players in

* [a pure UNIX way using the `yes` tool](players/02-always-stand)
* [Perl](players/05-no-bust)
* [Awk](players/08-mimic-the-dealer)
* [Bash](players/20-basic-strategy)
* C
* Python
## TCP Sockets

To play through a TCP socket, call `blackjack` from `netcat`. On one host, do

```
nc -l -p1234 -e blackjack
```

On the other one, connect to the first host on port 1234:

```
nc host 1234
```

# Licensing

Libre Blackjack is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

# Further information

Home page: <https://www.seamplex.com/blackjack>
Repository: <https://github.com/seamplex/blackjack>
Mailing list and bug reports: <wasora@seamplex.com> (you need to subscribe first at <wasora+subscribe@seamplex.com>)
Follow us: [Twitter](https://twitter.com/seamplex/) [YouTube](https://www.youtube.com/channel/UCC6SzVLxO8h6j5rLlfCQPhA) [LinkedIn](https://www.linkedin.com/company/seamplex/) [GitHub](https://github.com/seamplex/)

----------------------------------------------------

Libre Blackjack is copyright (C) 2016,2020 Jeremy Theler
Libre Blackjack is licensed under [GNU GPL version 3](http://www.gnu.org/copyleft/gpl.html) or (at your option) any later version.
Libre Blackjack is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
See the file `COPYING` for copying conditions.

+ 5
- 4
autogen.sh Datei anzeigen

@@ -8,7 +8,7 @@

# check for needed tools
for i in git autoreconf make m4 fmt; do
if test -z "`which ${i}`"; then
if test -z "$(which ${i})"; then
echo "error: ${i} is not installed"
exit 1
fi
@@ -26,15 +26,15 @@ fi

if test ${vcs} = "git"; then
# major version is equal to the latest tag
version=`git describe --always | sed 's/-/./'`
version=$(git describe --tags | sed 's/-/./')

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
commitdate=`git log -1 --pretty=format:"%ad"`
commitdate=$(git log -1 --pretty=format:"%ad")
cat << EOF > src/version-vcs.h
#define LIBREBLACKJACK_VCS_BRANCH "${branch}"
#define LIBREBLACKJACK_VCS_VERSION "${version}"
#define LIBREBLACKJACK_VCS_DATE "${commitdate}"
#define LIBREBLACKJACK_VCS_CLEAN `git status --porcelain | wc -l`
#define LIBREBLACKJACK_VCS_CLEAN $(git status --porcelain | wc -l)
EOF

else
@@ -58,3 +58,4 @@ fi
git log --oneline --decorate > ChangeLog

autoreconf --install
automake --add-missing

+ 162
- 0
doc/interactive.cast Datei anzeigen

@@ -0,0 +1,162 @@
{"version": 2, "width": 134, "height": 32, "timestamp": 1607450770, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
[0.03823, "o", "Beauty and harmony are as necessary to you as the very breath of life.\r\n"]
[0.039713, "o", "\u001b]0;gtheler@tom: ~/codigos/libreblackjack++\u0007\u001b[01;30mgtheler\u001b[00m@\u001b[01;33mtom\u001b[00m:~/codigos/libreblackjack++$ "]
[0.942721, "o", "b"]
[1.056397, "o", "l"]
[1.246982, "o", "a"]
[1.367887, "o", "ckjack "]
[1.968783, "o", "\r\n"]
[1.973649, "o", "LibreBlackjack v0.2+Δ\r\na free & open blackjack engine\r\n\r\n\r\n"]
[2.17389, "o", "\u001b[32mStarting new hand #1 with bankroll 0\u001b[0m\r\n"]
[2.37401, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n"]
[2.37498, "o", "\u001b[36m > \u001b[0m"]
[3.256665, "o", "1"]
[3.542573, "o", "\r\n"]
[3.74283, "o", "\u001b[32mPlayer's card is 3♥\u001b[0m\r\n"]
[3.942982, "o", "\u001b[32mDealer's up card is J♥\u001b[0m\r\n"]
[4.143235, "o", "\u001b[32mPlayer's card is 6♦\u001b[0m\r\n"]
[4.343398, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n"]
[4.543544, "o", "\u001b[32mNo blackjacks\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|\u001b[31mJ \u001b[0m | |#####| \r\n| | |#####| \r\n| \u001b[31m♥\u001b[0m | |#####| \r\n| | |#####| \r\n|___\u001b[31m_J\u001b[0m| |#####| \r\n Value: 10\r\n -- Player's hand --------\r\n _____ _____ \r\n|\u001b[31m3 \u001b[0m | |\u001b[31m6 \u001b[0m | \r\n| | | | \r\n| \u001b[31m♥\u001b[0m | | \u001b[31m♦\u001b[0m | \r\n| | | | \r\n|___\u001b[31m_3\u001b[0m| |___\u001b[31m_6\u001b[0m| \r\n Value: 9\r\n"]
[4.743741, "o", "\u001b[33m <-- Play? 9 10\u001b[0m\r\n"]
[4.743861, "o", "\u001b[36m > \u001b[0m"]
[6.215948, "o", "h"]
[6.7363, "o", "\r\n"]
[6.936555, "o", "\u001b[32mPlayer's card is Q♥\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|\u001b[31mJ \u001b[0m | |#####| \r\n| | |#####| \r\n| \u001b[31m♥\u001b[0m | |#####| \r\n| | |#####| \r\n|___\u001b[31m_J\u001b[0m| |#####| \r\n Value: 10\r\n -- Player's hand --------\r\n _____ _____ _____ \r\n|\u001b[31m3 \u001b[0m | |\u001b[31m6 \u001b[0m | |\u001b[31mQ \u001b[0m | \r\n| | | | | | \r\n| \u001b[31m♥\u001b[0m | | \u001b[31m♦\u001b[0m | | \u001b[31m♥\u001b[0m | \r\n| | | | | | \r\n|___\u001b[31m_3\u001b[0m| |___\u001b[31m_6\u001b[0m| |___\u001b[31m_Q\u001b[0m| \r\n Value: 19\r\n"]
[7.136879, "o", "\u001b[33m <-- Play? 19 10\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[8.439001, "o", "s"]
[8.566025, "o", "t"]
[8.648098, "o", "a"]
[8.726963, "o", "n"]
[8.854859, "o", "d"]
[9.158869, "o", "\r\n"]
[9.359051, "o", "\u001b[32mDealer's hole card was 10♥\u001b[0m\r\n"]
[9.559206, "o", "\u001b[32mPlayer losses 1 with 19\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|\u001b[31mJ \u001b[0m | |\u001b[31m10\u001b[0m | \r\n| | | | \r\n| \u001b[31m♥\u001b[0m | | \u001b[31m♥\u001b[0m | \r\n| | | | \r\n|___\u001b[31m_J\u001b[0m| |___\u001b[31m10\u001b[0m| \r\n Value: 20\r\n -- Player's hand --------\r\n _____ _____ _____ \r\n|\u001b[31m3 \u001b[0m | |\u001b[31m6 \u001b[0m | |\u001b[31mQ \u001b[0m | \r\n| | | | | | \r\n| \u001b[31m♥\u001b[0m | | \u001b[31m♦\u001b[0m | | \u001b[31m♥\u001b[0m | \r\n| | | | | | "]
[9.559524, "o", "\r\n|___\u001b[31m_3\u001b[0m| |___\u001b[31m_6\u001b[0m| |___\u001b[31m_Q\u001b[0m| \r\n Value: 19\r\n\r\n"]
[9.759547, "o", "\u001b[32mStarting new hand #2 with bankroll -1\u001b[0m\r\n"]
[9.959613, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[13.879874, "o", "1"]
[14.288058, "o", "\r\n"]
[14.488246, "o", "\u001b[32mPlayer's card is 9♣\u001b[0m\r\n"]
[14.6884, "o", "\u001b[32mDealer's up card is 3♥\u001b[0m\r\n"]
[14.888549, "o", "\u001b[32mPlayer's card is 6♠\u001b[0m\r\n"]
[15.088702, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|\u001b[31m3 \u001b[0m | |#####| \r\n| | |#####| \r\n| \u001b[31m♥\u001b[0m | |#####| \r\n| | |#####| \r\n|___\u001b[31m_3\u001b[0m| |#####| \r\n Value: 3\r\n -- Player's hand --------\r\n _____ _____ \r\n|9 | |6 | \r\n| | | | \r\n| ♣ | | ♠ | \r\n| | | | \r\n|____9| |____6| \r\n Value: 15\r\n"]
[15.288906, "o", "\u001b[33m <-- Play? 15 3\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[17.447909, "o", "s"]
[17.623619, "o", "t"]
[17.71056, "o", "a"]
[17.82285, "o", "n"]
[17.952334, "o", "d"]
[18.32668, "o", "\r\n"]
[18.526868, "o", "\u001b[32mDealer's hole card was 9♠\u001b[0m\r\n"]
[18.727105, "o", "\u001b[32mDealer's card is 5♦\u001b[0m\r\n"]
[18.927365, "o", "\u001b[32mPlayer losses 1 with 15\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ _____ \r\n|\u001b[31m3 \u001b[0m | |9 | |\u001b[31m5 \u001b[0m | \r\n| | | | | | \r\n| \u001b[31m♥\u001b[0m | | ♠ | | \u001b[31m♦\u001b[0m | \r\n| | | | | | \r\n|___\u001b[31m_3\u001b[0m| |____9| |___\u001b[31m_5\u001b[0m| \r\n Value: 17\r\n -- Player's hand --------\r\n _____ _____ \r\n|9 | |6 | \r\n| | | | \r\n| ♣ | | ♠ | \r\n| | | | \r\n|____9| |____6| \r\n Value: 15\r\n\r\n"]
[19.127548, "o", "\u001b[32mStarting new hand #3 with bankroll -2\u001b[0m\r\n"]
[19.327709, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n"]
[19.327802, "o", "\u001b[36m > \u001b[0m"]
[22.079828, "o", "1"]
[22.336372, "o", "\r\n"]
[22.536642, "o", "\u001b[32mPlayer's card is J♠\u001b[0m\r\n"]
[22.736827, "o", "\u001b[32mDealer's up card is 6♠\u001b[0m\r\n"]
[22.936966, "o", "\u001b[32mPlayer's card is K♣\u001b[0m\r\n"]
[23.13713, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|6 | |#####| \r\n| | |#####| \r\n| ♠ | |#####| \r\n| | |#####| \r\n|____6| |#####| \r\n Value: 6\r\n -- Player's hand --------\r\n _____ _____ \r\n|J | |K | \r\n| | | | \r\n| ♠ | | ♣ | \r\n| | | | \r\n|____J| |____K| \r\n Value: 20\r\n"]
[23.337345, "o", "\u001b[33m <-- Play? 20 6\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[24.91073, "o", "s"]
[25.023675, "o", "t"]
[25.1266, "o", "a"]
[25.262516, "o", "n"]
[25.375376, "o", "d"]
[25.64658, "o", "\r\n"]
[25.846783, "o", "\u001b[32mDealer's hole card was 8♥\u001b[0m\r\n"]
[26.04702, "o", "\u001b[32mDealer's card is 10♠\u001b[0m\r\n"]
[26.24724, "o", "\u001b[32mDealer busts with 24\u001b[0m\r\n"]
[26.447365, "o", "\u001b[32mPlayer wins 1\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ _____ \r\n|6 | |\u001b[31m8 \u001b[0m | |10 | \r\n| | | | | | \r\n| ♠ | | \u001b[31m♥\u001b[0m | | ♠ | \r\n| | | | | | \r\n|____6| |___\u001b[31m_8\u001b[0m| |___10| \r\n Value: 24\r\n -- Player's hand --------\r\n _____ _____ \r\n|J | |K | \r\n| | | | \r\n| ♠ | | ♣ | \r\n| | | | \r\n|____J| |____K| \r\n Value: 20\r\n\r\n"]
[26.64779, "o", "\u001b[32mStarting new hand #4 with bankroll -1\u001b[0m\r\n"]
[26.847867, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[30.136475, "o", "q"]
[30.255044, "o", "\r\n"]
[30.455249, "o", "\u001b[32mBye bye! We'll play Blackjack again next time\u001b[0m\r\n"]
[30.455493, "o", "---\r\nresult: \"(-25 ± 124) %\"\r\nmean: -0.25\r\nerror: 1.24373\r\nhands: 4\r\nbankroll: -1\r\nbustsPlayer: 0\r\nbustsDealer: 0.25\r\nwins: 0.25\r\npushes: 0\r\nlosses: 0.5\r\n...\r\n"]
[30.456459, "o", "\u001b]0;gtheler@tom: ~/codigos/libreblackjack++\u0007\u001b[01;30mgtheler\u001b[00m@\u001b[01;33mtom\u001b[00m:~/codigos/libreblackjack++$ "]
[30.871232, "o", "blackjack "]
[31.184265, "o", "\r\n"]
[31.190137, "o", "LibreBlackjack v0.2+Δ\r\na free & open blackjack engine\r\n\r\n\r\n"]
[31.390323, "o", "\u001b[32mStarting new hand #1 with bankroll 0\u001b[0m\r\n"]
[31.590482, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n"]
[31.591531, "o", "\u001b[36m > \u001b[0m"]
[32.510512, "o", "1"]
[32.758407, "o", "\r\n"]
[32.958656, "o", "\u001b[32mPlayer's card is 4♣\u001b[0m\r\n"]
[33.1588, "o", "\u001b[32mDealer's up card is 8♣\u001b[0m\r\n"]
[33.35896, "o", "\u001b[32mPlayer's card is 6♣\u001b[0m\r\n"]
[33.559052, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|8 | |#####| \r\n| | |#####| \r\n| ♣ | |#####| \r\n| | |#####| \r\n|____8| |#####| \r\n Value: 8\r\n -- Player's hand --------\r\n _____ _____ \r\n|4 | |6 | \r\n| | | | \r\n| ♣ | | ♣ | \r\n| | | | \r\n|____4| |____6| \r\n Value: 10\r\n"]
[33.759289, "o", "\u001b[33m <-- Play? 10 8\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[36.216385, "o", "d"]
[36.310828, "o", "o"]
[36.494899, "o", "u"]
[36.606426, "o", "b"]
[36.719533, "o", "l"]
[36.838564, "o", "e"]
[37.016818, "o", "\r\n"]
[37.217167, "o", "\u001b[32mPlayer's card is K♥\u001b[0m\r\n"]
[37.417235, "o", "\u001b[32mDealer's hole card was 6♠\u001b[0m\r\n"]
[37.617352, "o", "\u001b[32mDealer's card is 9♦\u001b[0m\r\n"]
[37.817494, "o", "\u001b[32mDealer busts with 23\u001b[0m\r\n"]
[38.017849, "o", "\u001b[32mPlayer wins 2\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ _____ \r\n|8 | |6 | |\u001b[31m9 \u001b[0m | \r\n| | | | | | \r\n| ♣ | | ♠ | | \u001b[31m♦\u001b[0m | \r\n| | | | | | \r\n|____8| |____6| |___\u001b[31m_9\u001b[0m| \r\n Value: 23\r\n -- Player's hand --------\r\n _____ _____ _____ \r\n|4 | |6 | |\u001b[31mK \u001b[0m | \r\n| | | | | | \r\n| ♣ | | ♣ | | \u001b[31m♥\u001b[0m | \r\n| | | | | | \r\n|____4| |____6| |___\u001b[31m_K\u001b[0m| \r\n Value: 20\r\n\r\n"]
[38.218069, "o", "\u001b[32mStarting new hand #2 with bankroll 2\u001b[0m\r\n"]
[38.418319, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[40.278452, "o", "1"]
[41.288143, "o", "\r\n"]
[41.488387, "o", "\u001b[32mPlayer's card is 2♠\u001b[0m\r\n"]
[41.688456, "o", "\u001b[32mDealer's up card is 2♠\u001b[0m\r\n"]
[41.888529, "o", "\u001b[32mPlayer's card is J♦\u001b[0m\r\n"]
[42.088692, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|2 | |#####| \r\n| | |#####| \r\n| ♠ | |#####| \r\n| | |#####| \r\n|____2| |#####| \r\n Value: 2\r\n -- Player's hand --------\r\n _____ _____ \r\n|2 | |\u001b[31mJ \u001b[0m | \r\n| | | | \r\n| ♠ | | \u001b[31m♦\u001b[0m | \r\n| | | | \r\n"]
[42.088957, "o", "|____2| |___\u001b[31m_J\u001b[0m| \r\n Value: 12\r\n"]
[42.288956, "o", "\u001b[33m <-- Play? 12 2\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[44.142738, "o", "h"]
[44.246719, "o", "i"]
[44.376198, "o", "t"]
[44.587953, "o", "\r\n"]
[44.78816, "o", "\u001b[32mPlayer's card is 2♣\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|2 | |#####| \r\n| | |#####| \r\n| ♠ | |#####| \r\n| | |#####| \r\n|____2| |#####| \r\n Value: 2\r\n -- Player's hand --------\r\n _____ _____ _____ \r\n|2 | |\u001b[31mJ \u001b[0m | |2 | \r\n| | | | | | \r\n| ♠ | | \u001b[31m♦\u001b[0m | | ♣ | \r\n| | | | | | \r\n|____2| |___\u001b[31m_J\u001b[0m| |____2| \r\n Value: 14\r\n"]
[44.988424, "o", "\u001b[33m <-- Play? 14 2\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[46.579747, "o", "sd"]
[46.983933, "o", "t"]
[47.368377, "o", "\b\u001b[K"]
[47.504379, "o", "\b\u001b[K"]
[47.656278, "o", "t"]
[47.984774, "o", "and "]
[48.391477, "o", "\r\n"]
[48.591767, "o", "\u001b[32mDealer's hole card was 2♠\u001b[0m\r\n"]
[48.791914, "o", "\u001b[32mDealer's card is 10♠\u001b[0m\r\n"]
[48.991989, "o", "\u001b[32mDealer's card is 2♠\u001b[0m\r\n"]
[49.192131, "o", "\u001b[32mDealer's card is 9♣\u001b[0m\r\n"]
[49.392297, "o", "\u001b[32mDealer busts with 25\u001b[0m\r\n"]
[49.592446, "o", "\u001b[32mPlayer wins 1\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ _____ _____ _____ \r\n|2 | |2 | |10 | |2 | |9 | \r\n| | | | | | | | | | \r\n| ♠ | | ♠ | | ♠ | | ♠ | | ♣ | \r\n| | | | | | | | | | \r\n|____2| |____2| |___10| |____2| |____9| \r\n Value: 25\r\n -- Player's hand --------\r\n _____ _____ _____ \r\n|2 | |\u001b[31mJ \u001b[0m | |2 | \r\n| | | | | | \r\n"]
[49.592741, "o", "| ♠ | | \u001b[31m♦\u001b[0m | | ♣ | \r\n| | | | | | \r\n|____2| |___\u001b[31m_J\u001b[0m| |____2| \r\n Value: 14\r\n\r\n"]
[49.792804, "o", "\u001b[32mStarting new hand #3 with bankroll 3\u001b[0m\r\n"]
[49.992827, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n\u001b[36m > \u001b[0m"]
[52.423624, "o", "1"]
[52.527471, "o", "\r\n"]
[52.727689, "o", "\u001b[32mPlayer's card is J♦\u001b[0m\r\n"]
[52.927838, "o", "\u001b[32mDealer's up card is 2♠\u001b[0m\r\n"]
[53.127977, "o", "\u001b[32mPlayer's card is K♥\u001b[0m\r\n"]
[53.328143, "o", "\u001b[32mDealer's hole card is dealt\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ \r\n|2 | |#####| \r\n| | |#####| \r\n| ♠ | |#####| \r\n| | |#####| \r\n|____2| |#####| \r\n Value: 2\r\n -- Player's hand --------\r\n _____ _____ \r\n|\u001b[31mJ \u001b[0m | |\u001b[31mK \u001b[0m | \r\n| | | | \r\n| \u001b[31m♦\u001b[0m | | \u001b[31m♥\u001b[0m | \r\n| | | | \r\n|___\u001b[31m_J\u001b[0m| |___\u001b[31m_K\u001b[0m| \r\n Value: 20\r\n"]
[53.528331, "o", "\u001b[33m <-- Play? 20 2\u001b[0m\r\n"]
[53.528616, "o", "\u001b[36m > \u001b[0m"]
[54.71967, "o", "s"]
[54.910345, "o", "t"]
[55.167876, "o", "and "]
[55.52768, "o", "\r\n"]
[55.728013, "o", "\u001b[32mDealer's hole card was 2♥\u001b[0m\r\n"]
[55.928123, "o", "\u001b[32mDealer's card is 9♥\u001b[0m\r\n"]
[56.128202, "o", "\u001b[32mDealer's card is Q♠\u001b[0m\r\n"]
[56.328283, "o", "\u001b[32mDealer busts with 23\u001b[0m\r\n"]
[56.528449, "o", "\u001b[32mPlayer wins 1\u001b[0m\r\n -- Dealer's hand: --------\r\n _____ _____ _____ _____ \r\n|2 | |\u001b[31m2 \u001b[0m | |\u001b[31m9 \u001b[0m | |Q | \r\n| | | | | | | | \r\n| ♠ | | \u001b[31m♥\u001b[0m | | \u001b[31m♥\u001b[0m | | ♠ | \r\n| | | | | | | | \r\n|____2| |___\u001b[31m_2\u001b[0m| |___\u001b[31m_9\u001b[0m| |____Q| \r\n Value: 23\r\n -- Player's hand --------\r\n _____ _____ \r\n|\u001b[31mJ \u001b[0m | |\u001b[31mK \u001b[0m | \r\n| | | | \r\n| \u001b[31m♦\u001b[0m | | \u001b[31m♥\u001b[0m | \r\n| | | | \r\n|___\u001b[31m_J\u001b[0m| |___\u001b[31m_K\u001b[0m| \r\n Value: 20\r\n\r\n"]
[56.728639, "o", "\u001b[32mStarting new hand #4 with bankroll 4\u001b[0m\r\n"]
[56.928813, "o", "\u001b[33m <-- Bet?\u001b[0m\r\n"]
[56.929131, "o", "\u001b[36m > \u001b[0m"]
[58.430447, "o", "q"]
[58.566828, "o", "\r\n"]
[58.767039, "o", "\u001b[32mBye bye! We'll play Blackjack again next time\u001b[0m\r\n---\r\n"]
[58.76736, "o", "result: \"(+100 ± 106) %\"\r\nmean: 1\r\nerror: 1.06066\r\nhands: 4\r\nbankroll: 4\r\nbustsPlayer: 0\r\nbustsDealer: 0.75\r\nwins: 0.75\r\npushes: 0\r\nlosses: 0\r\n...\r\n"]
[58.768426, "o", "\u001b]0;gtheler@tom: ~/codigos/libreblackjack++\u0007\u001b[01;30mgtheler\u001b[00m@\u001b[01;33mtom\u001b[00m:~/codigos/libreblackjack++$ "]
[60.877796, "o", "exit\r\n"]

+ 69
- 82
src/tty.cpp Datei anzeigen

@@ -334,89 +334,78 @@ int Tty::play() {
// EOF means "quit"
actionTaken = Libreblackjack::PlayerActionTaken::Quit;
std::cout << std::endl;
return 0;
}
add_history(input_buffer);
std::string command = input_buffer;
free(input_buffer);
trim(command);
#else
std::cout << prompt;
std::string command;
std::cin >> command;
} else {
#endif
actionTaken = Libreblackjack::PlayerActionTaken::None;

add_history(input_buffer);
actionTaken = Libreblackjack::PlayerActionTaken::None;
// check common commands first
if (command == "quit" || command == "q") {
actionTaken = Libreblackjack::PlayerActionTaken::Quit;
} else if (command == "help") {
actionTaken = Libreblackjack::PlayerActionTaken::Help;
// } else if (command == "count" || command == "c") {
// actionTaken = Libreblackjack::PlayerActionTaken::Count;
} else if (command == "upcard" || command == "u") {
actionTaken = Libreblackjack::PlayerActionTaken::UpcardValue;
} else if (command == "bankroll" || command == "b") {
actionTaken = Libreblackjack::PlayerActionTaken::Bankroll;
} else if (command == "hands") {
actionTaken = Libreblackjack::PlayerActionTaken::Hands;
}

if (actionTaken == Libreblackjack::PlayerActionTaken::None) {
switch (actionRequired) {

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

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

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

case Libreblackjack::PlayerActionRequired::None:
break;

// TODO: better solution
std::string command = input_buffer;
free(input_buffer);
trim(command);
// check common commands first
if (command == "quit" || command == "q") {
actionTaken = Libreblackjack::PlayerActionTaken::Quit;
} else if (command == "help") {
actionTaken = Libreblackjack::PlayerActionTaken::Help;
// } else if (command == "count" || command == "c") {
// actionTaken = Libreblackjack::PlayerActionTaken::Count;
} else if (command == "upcard" || command == "u") {
actionTaken = Libreblackjack::PlayerActionTaken::UpcardValue;
} else if (command == "bankroll" || command == "b") {
actionTaken = Libreblackjack::PlayerActionTaken::Bankroll;
} else if (command == "hands") {
actionTaken = Libreblackjack::PlayerActionTaken::Hands;
}
if (actionTaken == Libreblackjack::PlayerActionTaken::None) {
switch (actionRequired) {

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

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

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

std::cout << prompt;
std::cin >> input_buffer;

// TODO: check EOF
// TODO: esto puede ir en algo comun para tty y stdout
if (input_buffer == "hit" || input_buffer == "h") {
*command = Command::Hit;
} else {
*command = Command::None;
}
#endif
return 0;
}

@@ -521,11 +510,11 @@ void Tty::renderHand(Hand *hand, bool current) {
}


int Tty::list_index = 0;
int Tty::len = 0;

char *Tty::rl_command_generator(const char *text, int state) {
#ifdef HAVE_READLINE
if (!state) {
list_index = 0;
@@ -538,16 +527,14 @@ char *Tty::rl_command_generator(const char *text, int state) {
return strdup(commands[i].c_str());
}
}
#endif
return NULL;
}

char **Tty::rl_completion(const char *text, int start, int end) {
char **matches = NULL;

#ifdef HAVE_LIBREADLINE
#ifdef HAVE_READLINE
matches = rl_completion_matches(text, rl_command_generator);
#endif

return matches;
}

Laden…
Abbrechen
Speichern