Random Player Class

This section will introduce a simple subclass of the Player class who bets at random.

In Random Player Analysis we’ll look at what this player does.

We’ll turn to how the player works in Random Player Design.

In Random Player Deliverables we’ll enumerate the deliverables for this player.

An important consideration is to compare this player with the player who always bets black and the player using the Martingale strategy to always bet black. Who does better? If they’re all about the same, what does that say about the house edge in this game?

Random Player Analysis

One possible betting strategy is to bet completely randomly. This serves as an interesting benchmark for other betting strategies.

We’ll write a subclass of the Player class to step through all of the bets available on the Wheel instance, selecting one or more of the available outcomes at random. This Player subclass, like others, will have a fixed initial stake and a limited amount of time to play.

The Wheel class can provide an Iterator over the collection of Bin instances. We could revise the Wheel class to provide a binIterator() method that we can use to return all of the Bin instances. From each Bin object, we will need an iterator we can use to return all of the Outcome instances. This provides the domain of possible bets.

To collect a list of all possible Outcome instances, we would use the following algorithm:

Locating All Outcomes

  1. Empty List of Outcomes. Create an empty set of all Outcome instances, all_OC.

  2. Get Bin Iterator. Get the Iterator from the Wheel object that lists all Bin instances.

  3. For each Bin.

    Get Outcome Iterator. Get the Iterator that lists all Outcome instances.

    For each Outcome.

    Save Outcome. Add each Outcome object to the set of all known outcomes, all_OC.

To create a random bet, we can use the random.choice() function to pick one of the available Outcome instances.

Random Player Design

class PlayerRandom

PlayerRandom is a Player who places bets in Roulette. This player makes random bets around the layout.

Fields

PlayerRandom.rng

A Random Number Generator which will return the next random number.

When writing unit tests, we will want to patch this with a mock object to return a known sequence of bets.

Constructors

PlayerRandom.__init__(table: Table) → None

This uses the super() construct to invoke the superclass constructor using the Table class.

Parameters

table (Table) – The Table object which will accept the bets.

This will create a random.Random random number generator.

It will also use the wheel associated with the table to get the set of bins. The set of bins is then used to create the pool of outcomes for creating bets.

Methods

PlayerRandom.placeBets(self) → None

Updates the Table object with a randomly placed Bet instance.

Random Player Deliverables

There are five deliverables from this exercise. The new classes need Python docstrings.

  • Updates to the class Bin to return an iterator over available Outcome instances. Updates to unittests for the class Bin, also.

  • Updates to the Wheel to return an iterator over available Bin instances. Updates to the unittests for the class Wheel, also.

  • The PlayerRandom class.

  • A unit test of the PlayerRandom class. This should use the NonRandom number generator to iterate through all possible Outcome instances.

  • An update to the overall Simulator that uses the PlayerRandom.

Looking Forward

It’s time to look at the algorithmically more sophisticated betting strategies. These all involve player state changes based on the wins and losses at the table. To an extent, the Martingale betting was stateful. These will involve more states and more complex rules for state transitions. In the next chapter, we’ll implement the “1-3-2-6” betting strategy.