Zhao Pengyou Rules and Strategy Guide

Zhao PengyouPlaying card aces
Rules   Statistics   Strategy

The Deal:
First card flipped

Pointless hand
Trump cards

Falling playing cards

The Deal:
First card flipped: For the standard game of five players with two decks of cards, there are 108 cards that must be dealt. Each player receives 20 cards, with the bottom 8 left over. At the start of the game, when all players are on the 2’s level, the chance that the first card drawn is a level card is: $$p_1=\frac{8}{108}\approx 7.41\%$$ For the level card to be flipped on the second card draw, the first draw must not have been a level card. These events are not independent, thus: $$p_2=(1-p_1)*\frac{8}{107}$$ To generalize for a specific card draw n, we must consider the sum probability that any previous card was a level card, and subtract this from 1 to establish that none of these events happened: $$p_n=(1-\sum_{i=1}^{n-1}p_i)*\frac{8}{108-n+1}$$ The graph below shows the probability that any given card is the first that can be flipped:

Graph first card flipped zhao pengyou
Figure 1. Probability of card n being first flipped

It takes slightly longer on average to reach the first level card when each player is on a different level. This is because when everyone is on the same level, a card that is not flipped is not anyone’s level card, so all eight of them must remain in the deck; whereas when players are on different levels, an unflipped card may be someone else’s level card, in which case there are fewer than eight remaining in the deck for them. When everyone is on the same level it is also possible, although highly unlikely, for all eight 2’s to be in the bottom eight. This occurs less than once every billion hands.

Someone receives no point cards: There are 24 point cards (84 non-point cards) in two decks. The probability that any given hand is pointless is: $$p_{pointless}=\prod_{i=0}^{19}\frac{84-i}{108-i}\approx0.3657\%$$ A deal can be redone if any player receives a pointless hand, this probability is: $$p_{redeal}=1-\left(1-\prod_{i=0}^{19}\frac{84-i}{108-i}\right)^{5}\approx0.3657\%$$

The formula takes into account that for some hands, multiple people will receive no point cards, and considers the dealer’s hand before the bottom eight are picked up. About 1 in every 55 deals will result in a pointless hand.

Number of trump cards received: There are 36 trump cards each game, thus every card dealt has a $$\frac{36}{108} \approx 33.3\%$$ chance of being one. Calculating the likelihood of getting a certain number of trump cards is a combinatorial problem. For players other than the dealer, the probability of getting 6 trump cards, for example, is: $$p_{trump}(6)=\frac{\binom{36}{6}\binom{72}{14}}{\binom{108}{20}}$$ Generalizing for k trump cards in a hand of 20 cards, the probability is: $$p_{trump}(k)=\frac{\binom{36}{k}\binom{72}{20-k}}{\binom{108}{20}}$$ For the dealer, instead of 20 cards in the hand there are 28. This is graphed below for both non-dealers and dealers:
probability of receiving k trump cards
Figure 2. Probability of receiving k trump cards

Number of pairs received: There are 54 distinct cards which may form a pair; the probability of receiving d pairs as a non-dealer is: $$p_{pairs}(d)=\frac{\binom{2}{1}^{20-2d}\binom{54}{d}\binom{54-d}{20-2d}}{\binom{108}{20}}$$ The same changes as before are made for the dealer’s probability: $$p_{dpairs}(d)=\frac{\binom{2}{1}^{28-2d}\binom{54}{d}\binom{54-d}{28-2d}}{\binom{108}{28}}$$
probability of receiving pairs
Figure 3. Probability of receiving d pairs

Python code used for Monte Carlo simulations:

# -*- coding: utf-8 -*-
Created on Mon Sep 17 13:06:22 2018

@author: R. Lucas Thomas III
import collections
import matplotlib.pyplot as plt
import numpy
import random
from scipy import stats

def deal(deck, players, cardsperplayer):
    hands = []
    for i in xrange(0,players):
        newhand = deck[i*cardsperplayer:(i*(cardsperplayer)+cardsperplayer)]
    return hands

def finddealer(hands,levels):
    ordinal = 1
    for c in xrange(0,20):
        for p in xrange(0,5):
            if hands[p][c][0] == levels[p]:
                if len(hands[p][c]) != 1:
                    return [p,c,ordinal]
                ordinal += 1
    return "No dealer"
def haspoints(hand):
    for c in hand:
        if c[0] == '5':
            return True
        elif c[0] == 'K':
            return True
    for c in hand:
        if len(c) == 3:
            return True
    return False
def countpairs(hand):
    return len(hand)-len(set(hand))
def trumpcount(hand, level):
    trump = 0
    rank = level[:1]
    suit = level[-1:]
    for c in hand:
        if c == "J":
            trump += 1
        elif c == "j":
            trump += 1
        elif c[-1:] == suit:
            trump += 1
        elif c[:1] == rank:
            trump += 1
    return trump
twodecks = []
suits = ['s','h','c','d']
ranks = ['A','K','Q','J','10','9','8','7','6','5','4','3','2']

#form cards by appending suits to ranks and adding the result to the deck
for r in ranks:
    for s in suits:

testdeals = 100000
handcount = 0
paircountlist = []
for a in xrange(0,testdeals):
    hands = deal(twodecks, 5, 20)
    for h in hands:
        handcount += 1
print paircountlist.count(4)/float(handcount)
trumpcounts = []
for a in xrange(0,testdeals):
    hands = deal(twodecks, 5, 20)
    for h in hands:
        handcount += 1
results = ""
for cnt in xrange(0,16):
    results += str(cnt) + " "
    results += str(100*trumpcounts.count(cnt)/float(handcount)) + "%    "
print results

#First Card Flipped Probability
firstflipped = []
for a in xrange(0,testdeals):

    bottomeight = twodecks[-8:]
    hands = deal(twodecks, 5, 20)

    levels = ['2','2','2','2','2']


ff = numpy.array(firstflipped)
print "Average card flipped: " + str(numpy.mean(ff))
print "Median card flipped: " + str(numpy.median(ff))
print "Mode card flipped: " + str(stats.mode(ff)[0])
print "Probability of draw flip: " + str(100*collections.Counter(firstflipped)[10]/float(testdeals)) + "%"

#Pointless Hand Probability
redeal = 0
pointlesscount = 0
handcount = 0
for a in xrange(0,testdeals):
    bottomeight = twodecks[-8:]
    hands = deal(twodecks, 5, 20)
    haspointless = 0
    for h in hands:
        handcount += 1
        if haspoints(h) == False:
            pointlesscount += 1
            haspointless = 1
    if haspointless == 1:
        redeal += 1
print "Redealt hands: " + str(redeal)
print pointlesscount
print handcount
print redeal/float(testdeals)