# -*- 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
[email protected]
https://mail.python.org/mailman/listinfo/edu-sig