Yaniv is a highly addictive backpacker's card game.
For rules see the Wikipedia page.
The main objectives for this ongoing project:
- Calculate the game statistics
- Train bots with the end goal to learn strategy
- Make Interactive
In the current format yaniv
can run a game with N
players from an overlooker's point of view.
One nice feature added is calculating the statistics of a Yaniv declaration from the declarer's point of view.
It is currently correct for two players, and requires more work for N>2
.
To run a game go to the yaniv/yaniv
directory and do:
python run.py
This will yield the game results, round for round with a mention of the Yaniv success statistics, e.g:
Albert (bot) strategy: picks if min pile top min value <= 3
----------
Roland (bot) strategy: picks if min pile top min value <= 5
----------
Amos (bot) strategy: picks if min pile top min value <= 5
----------
Claude (bot) strategy: picks if min pile top min value <= 5
----------
Deck of 54 cards
['W☻', 'W☺', 'A♦', 'A♥', 'A♣', 'A♠', '2♦', '2♥', '2♣', '2♠', '3♦', '3♥', '3♣', '3♠', '4♦', '4♥', '4♣', '4♠', '5♦', '5♥', '5♣', '5♠', '6♦', '6♥', '6♣', '6♠', '7♦', '7♥', '7♣', '7♠', '8♦', '8♥', '8♣', '8♠', '9♦', '9♥', '9♣', '9♠', '10♦', '10♥', '10♣', '10♠', 'J♦', 'J♥', 'J♣', 'J♠', 'Q♦', 'Q♥', 'Q♣', 'Q♠', 'K♦', 'K♥', 'K♣', 'K♠']
Round 7:
Lucky Claude! Aggregated 100 points reduced to 50
Claude is the winner with 194 points
For more output information change verbose
(values 0 to 3).
Within stats
you will find code that can calculates at a given round:
Given a player has declared victory (yaniv!), what is the probability
that they truly have the lowest hand.
For this you will need to update within run.py
:
do_stats = True
verbose = 1
players = ['Albert','Roland'] # currently limited to two players
Example output of a round
Round: 23
Player starting the round: Roland
n_j=4, h_i=7, n_jokers=1 yields
t_nj=6
N: 36
['3c', '8c', '3h', 'Kh', 'Qd', 'Ac', '10d', '5d', 'Ks', 'Jd', 'Qc', '3s', 'Qs', 'Kd', '5h', '8h', '5s', 'Wb', '4d', '10c', '2d', 'Ad', '9h', 'As', '4h', 'Jc', 'Kc', '7d', '7c', '4c', '2c', '2h', '6d', '6c', '3d', '10s']
n: 17
['3c', '3h', 'Ac', '5d', '3s', '5h', '5s', 'Wb', '4d', '2d', 'Ad', 'As', '4h', '4c', '2c', '2h', '3d']
total: 2380
successes: 2179
P(h_j>h_i|U)=0.916
N=36, K=17, n_j=4, yields:
p(U)=0.040
P(h_j>h_i=7|n_j, cards)=0.997
~~~~~~~~~~
Round Conclusion
Albert declared Yaniv with 7
Albert 0 ['2♠', 'W☻', '4♠', 'A♥'] 185
Roland 15 ['2♥', '5♥', '3♠', '5♣'] 138
From here we learn that:
- Roland started the round,
- Albert declared yaniv
- with a hand of
h_i=7
- was unaware of
N=36
cards - (of which Roland had
n_j=4
cards in hand).
- with a hand of
- Given those facts from Albert's POV the probability of the decleration being successful is
P(h_j>h_i=7|n_j, cards)=0.997
- Roland has
h_j=15
from cards ['2♥', '5♥', '3♠', '5♣'] - Resulting in Albert not getting any points where Roland got 15 (all points are bad).
This is a work in progress.
Currently there is a working Classifier that trains on the probability
that it should pick up from the deck of cards (or top of pile):
Simulates two players, where both have basic deterministic policies (see rl_utils.basic_policy
),
and a DNN trains on the policy of the first player.
To test do:
python run_train_deck_pickup.py
There is some preliminary human playing mode, but still requires more work.
For a quick peek set one of the players to human
, like this:
players = {'<Your Name>': 'human','Roland':'bot', 'Amos':'bot','Claude':'bot'}
python 3
- numpy
- scipy
- pandas
- tensorflow 2 (for reinforcement learning)
Run bash command
py.test
(or pytest
)
- Pull card:
- bots are assigned a maximum value used to pull from pile, otherwise default from deck (currently between 3 and 5; see
game.Player.pile_pull_strategy
,game.Round.pull_card
) - if choosing from pile and there is more than one accessible card, bots hypothesise the best combination for the next round (
game.Round.pull_card_from_pile_top
)
- bots are assigned a maximum value used to pull from pile, otherwise default from deck (currently between 3 and 5; see
- Throw card: bots throw the highest valued valid combination (
game.Round.throw_cards_to_pile
)
- Jokers values are currently 0, but not used yet a s wild cards for streaks (i.e, no use in
cards.cards_to_consecutive_combinations
)
Image credit: Barak Edry from his excellent App Store game of Yaniv