A Mah Jongg Hand object, then, is a list of
Tiles. The mahjongg creates
an assignment of individual Sets. It checks these
sets to see if all of them are full, if there are five of them and if
one of the five is a pair. If so, it returns True
because the hand is a winning hand.

If we sort the tiles by name or suit, we can more effectively
assign tiles to sets. The first step in the
mahjongg function is to sort the tiles into order.
Then the tiles can be broken into sets based on what matches between the
tiles.

Procedure 41.1. Hand Scoring

The mahjongg function examines a hand to
determine if the tiles can be assigned to five scoring sets, one of
which is a pair.

Sort Tiles. Sort the tiles by name (or suit) and by rank for suit tiles
where the suit matches. We will treat the hand of tiles as a the
tile stack, popping and pushing tiles from position 0 using
pop(0) and insert(0,tile).

Stack of Sets. The candidate set definition is a stack of
Set objects. Create an empty list to be
used as the candidate stack. Create a new, empty
FourSet and push this onto the top of the
candidate stack.

Examine Tiles. Use the examine function to examine the
tiles of the hand, assigning tiles to Sets
in the candidate stack. When this operation is complete, we may
have a candidate assignment that will contain a number of
Sets, some of which are full, and some are
incomplete. We may also have an empty stack because we have run
out of fallback Sets.

While Not A Winner. While we have Sets in the candidate
stack, use the allFull to see if all
Sets are full, there are five sets, and
there is exactly one pair. If we do not have five full
Sets and a single pair, then we must
fallback to another subclass of Set.

Retry. Use the retry method to pop the
last candidate Set, and use that
Set's fallback to
create a different Set for examination.
Save this Set in
n.

Any More Assignments? If the result of retry is
None, there are no more fallbacks; we can
return False.

Examine Tiles. Append the Set,
n, returned by retry to the candidate
stack. Use the examine function to
examine the tiles of the hand, assigning tiles to
Sets. When this operation is complete,
we may have a candidate assignment that will contain a number
of Sets, some of which are full, and
some are incomplete.

Winner? If we finish the loop normally, it means we have a candidate
set assignment which has five full sets, one of which is a pair.
For some hands, there can be multiple winners; however, we won't
continue the examination to locate additional winning
assignments.

The allFull function checks three conditions:
all Sets are full, there are five
Sets, and is one Set is a
pair. The first test, all Sets full, is an
“and-reduce”, using something like the following
reduce( lambda a,b: a and b, [s.full() for s in
sets], True ).

Procedure 41.2. Examine All Tiles

The examine function requires a non-empty
stack of candidate Sets, created by the
mahjongg method. It assigns all of the remaining
tiles beginning with the top-most candidate
Set. Initially, the entire hand is examined.
After each retry, some number of tiles will have been pushed back into
the hand for re-examination.

While More Tiles. If the tile stack is empty, we are done.

Next Tile. Pop the next unexamined tile from the tile stack,
assigning it to the variable t.

Topmost Set Full? If the topmost set on the set stack is full, push a new,
empty FourSet onto the top of the set
stack. This is also a handy place to use a
print statement to watch the progress of
the evaluation.

Topmost Set Can Contain? If the top-most Set can contain
t, add this tile to the set. We're done
examining this tile.

Topmost Set Can't Contain. Put the tile t back into the stack of
tiles to be examined. Use the retry
function to pop the Set from the stack,
and fallback to another subclass of
Set.

Another Retry? If the result of the retry is
None, we've run of alternatives, return
from this function. Otherwise, append the new
Set created by
retry to the stack of candidate
sets.

Procedure 41.3. Retry a Set Assignment

The retry function requires at least one
Set in the assignments. This will pop that
Set, pushing the tiles back into the hand. It
will then use the popped Set's
fallback method to get another flavor of
Set to try.

Pop. Pop the top-most set from the set stack, assign it to
s. Call sfallback method to get a new top-most
Set, assign this to
n.

Out Of Fallbacks? While the set stack is not empty and n is
None, there was no fallback.

Pop Another. Pop the top-most set from the set stack, assign it to
s. Call sfallback method to get a new top-most
Set, assign this to
n.

Done? If n is None and the
set stack is empty, the hand is incomplete and we are out of
fallback sets. Otherwise, append n to the stack
of sets.

Published under the terms of the Open Publication License