# -*- python -*- class Food: def __init__(self, name, energy): self.name = name self.energy = energy def eaten(self): return self.energy class Meat(Food): def __init__(self, name, energy): self.valid = True Food.__init__(self, name, energy) def eaten(self): if not self.valid: raise "bad food" self.valid = False return Food.eaten(self) class Animal: def __init__(self, name, energy, when_slaughtered, food_accepted): self.valid = True self.name = name self.energy = energy self.food_accepted = food_accepted self.when_slaughtered = when_slaughtered def eat(self, food): if not self.valid: raise "bad animal" if self.food_accepted(food.name): self.energy += food.eaten() else: raise "%s doesn't accept food %s" % (self.name, food.name) def slaughter(self): if not self.valid: raise "bad animal" self.valid = False return Meat(self.when_slaughtered, self.energy) meats = [ "beef", "dead_rabbit", "dead_human" ] def is_meat(food_name): return food_name in meats def new_grass(energy): return Food("grass", energy) def new_carrot(energy): return Food("carrot", energy) def new_cow(energy): return Animal("cow", energy, "beef", lambda n: n == "grass") def new_rabbit(energy): return Animal("rabbit", energy, "dead_rabbit", lambda n: n == "carrot") def new_human(energy): return Animal("human", energy, "dead_human", lambda n: n == "carrot" or is_meat(n)) grass = new_grass(5) carrot = new_carrot(10) a_rabbit = new_rabbit(100) a_cow = new_cow(1000) a_human = new_human(300) another_human = new_human(350) for o in [ a_rabbit, a_cow, a_human ]: print "%s -> %d" % (o.name, o.energy) a_rabbit.eat(carrot) a_cow.eat(grass) a_dead_rabbit = a_rabbit.slaughter() a_beef = a_cow.slaughter() a_human.eat(carrot) a_human.eat(carrot) a_human.eat(a_beef) a_human.eat(a_dead_rabbit) a_human.eat(another_human.slaughter()) if a_human.energy != 1785: raise "failed" should_fail = """ new_cow(10).slaughter().eat(grass) # meat (food) can't eat new_cow(10).slaughter().slaughter() # meat (food) can't be slaughtered carrot.eat(grass) # vegetable (food) can't eat carrot.slaughter() # vegetable (food) can't be slaughtered new_cow(10).eat(carrot) # cow do not eat carrot new_cow(10).eat(new_cow(10).slaughter()) # cow do not eat beef a_human.eat(new_cow(10)) # can't eat live animals a_human.eat(grass) # human do not eat grass a_human.eat(a_beef) # a_beef is already eaten a_cow.eat(grass) # a_cow is dead, it can't eat a_cow.slaughter() # a_cow is dead, it can't be slaughtered again """ for i in should_fail.split("\n"): try: eval(i) except: continue raise "%s should_have_failed" % i