# -*- coding: utf-8 -*-
"""
Created on Thu Feb 11 09:08:42 2016

@author: Kirby Urner

A Game of Life (c) MIT License, 2016

Die:  2 or more sides
Cup:  1 or more dice

Exceptions subclasses

Run a gauntlet of possible exceptions, with Game for scope

"""
from random import choice

#==== What Could Go Wrong? ====
class TrafficTicket(Exception):
    def __init__(self, m=""):
        self.message = m

class GoToJail(Exception):
    pass

class SecondChance(Exception):
    pass

#==== Element of Chance =======
class Die:
    """
    * As many sides as you like, suggested minimum of two (like a coin)
    * Switch on record=True to keep a record of throws
    """

    def __init__(self, sides=6, record=False):
        self.sides = range(1, sides+1)
        self._throws = [ ]
        self.record = record

    @property  # treat as a simple attribute
    def throw(self):
        v = choice(self.sides)
        if self.record:
            self._history(v)
        return v

    def _history(self, value):
        self._throws.append(value)

    @property
    def history(self):
        if not self.record:
            raise AttributeError  # no record kept!
        return self._throws

class Cup:
    """
    Put as many dice as you like in the Cup. At least one.
    The dice should be passed in positionally as in
    Cup(Die(), Die())
    """

    def __init__(self, *dice):
        self._dice = dice

    def __getitem__(self, n):
        return self._dice[n]

    @property
    def throw(self):
        total = 0
        for die in self._dice:
            total += die.throw
        return total

def some_risky_business():
    """
    Take a turn, see what fate has in store!
    """

    venture_outcome = dice_cup.throw

    if venture_outcome == 12:
        # traffic misadventure
        raise TrafficTicket("No Left Turn!")

    elif venture_outcome == 2:
        # court finds your venture a Ponzi scheme
        raise GoToJail  # Monopoly maneuver

    elif choice(range(10)) == 7:  # not from dice!
        # starting over can be a good thing
        raise SecondChance

    else:
        print("So far so good...")

class Game:
    """
    Hi, I'm a context manager, like a gatekeeper,
    with an "in" and "out" method.  Upon leaving,
    I handle all exceptions
    """
    def __enter__(self):
        return self

    def __exit__(self, *exc_data):
        if exc_data[0]:   # exception happened
            print("Oh well.  Better luck next time!")
        else:
            print("Congratulations")
            # transcript is added to the game instance by the
            # else suite in the for loop below
            print("Lucky throws", self.transcript)
        return True  # OK, we're good

if __name__ == "__main__":

    with Game() as g:  # game object available within scope
        """
        If you're lucky, you won't roll a 2 or 12 in five
        rolls.  Otherwise, the exception handling machinery
        will deal with your case.  :-D
        """
        dice_cup = Cup(Die(record=True), Die(record=True))  # two dice
        while True:    # like an ever turning wheel of fortune...
            turns = 0
            try:
                for _ in range(5):
                    some_risky_business() # returns None ...
                else:
                    print("You lucked out!")
                    # adding the two histories gives a record of Cup throws
                    # making an attribute of the game object
                    g.transcript = [sum([i,j]) for i,j in
zip(dice_cup[0].history,
                                                       dice_cup[1].history)]

            # an exception will occur...
            except TrafficTicket as exc:
                print(exc.message)
                raise  # propagate loose end!

            except GoToJail:
                print("GoToJail raised")
                raise  # re-raise same exception

            except SecondChance:
                print("Get to start over!")
                continue  # turns reset to 0

            else:
                print("You tried, and succeeded!")
                break  # escape from the Wheel of Risk

    print("There's still life after scope")
    print("The dice_cup is still with us....")
    for _ in range(4):
        print(dice_cup.throw, end=" ")
    print()
_______________________________________________
Edu-sig mailing list
Edu-sig@python.org
https://mail.python.org/mailman/listinfo/edu-sig

Reply via email to