more implementations, having trouble with Property.instances

This commit is contained in:
2020-05-21 01:54:54 +02:00
parent 453274e7bc
commit 6eb56cd873

View File

@@ -11,11 +11,14 @@ http://www.tkcs-collins.com/truman/monopoly/monopoly.shtml
# TODO: maybe instead of all these classmethods, instances?
# TODO: something more graceful than Game.games[0]
"""
from abc import abstractmethod, ABC
from collections import defaultdict
from itertools import cycle
from pprint import pprint
from random import shuffle, choice
from typing import Type, NewType, Tuple, cast
from typing import Type, NewType, Tuple, cast, List
from exceptions import TooManyPlayers, NotEnough, DidntFind, Argument, NoOwner
@@ -228,29 +231,41 @@ def shuffle_decks():
deck.shuffle()
def buy_decision(property: Type["Property"], player: "Player"):
if property.cost > player.assets:
print(f"{player} doesn't have enough to buy {property}.")
if Game.games[0].buy_decision_algorithm(property, player):
player.buy(property)
class Decision:
pass
class BuyDecision(Decision):
def __init__(self, property: "Property", player: "Player"):
pass
class Property(Space):
mortgaged = False
owner = None
cost = 0
instances = []
type = None
def __init__(self, _name):
self._name = _name
self.instances.append(self)
@classmethod
def action(cls, player: "Player", last_roll=None):
if not cls.owner:
return BuyDecision(cls, player)
if cls.mortgaged:
def instances_by_type(cls):
ibt = defaultdict(list)
for i in cls.instances:
print(i)
ibt[i.type].append(i)
def action(self, player: "Player", last_roll=None):
if not self.owner:
return buy_decision(self, player)
if self.mortgaged:
return
return player.pay(cls.owner, cls.calculate_rent(last_roll=last_roll))
return player.pay(self.owner, self.calculate_rent(last_roll=last_roll))
def calculate_rent(self, last_roll):
if not self.owner:
@@ -313,7 +328,7 @@ class BuildableProperty(Property):
self.mortgaged = False
def calculate_rent(self, last_roll=None):
super().calculate_rent()
super().calculate_rent(last_roll)
if self.buildings:
key = self.buildings
elif self.owner.owns_all_type(self.type):
@@ -324,7 +339,6 @@ class BuildableProperty(Property):
class Board:
spaces = [
Go,
BuildableProperty(
@@ -333,7 +347,6 @@ class Board:
color="brown",
rent={0: 2, "monopoly": 4, 1: 10, 2: 30, 3: 90, 4: 160, "hotel": 250},
house_and_hotel_cost=50,
# TODO
mortgage_cost=30,
unmortgage_cost=33,
),
@@ -705,7 +718,7 @@ class Player(EconomicActor):
def __repr__(self):
return f"<Player name='{self.name}' money={self.money}"
def pay(cls, actor: "EconomicActor", amount: int):
def pay(cls, actor: Type["EconomicActor"], amount: int):
if isinstance(actor, str):
actor = eval(actor)
if amount > cls.money:
@@ -713,6 +726,10 @@ class Player(EconomicActor):
cls.money -= amount
actor.money += amount
def buy(self, property: Type["Property"], from_=Bank, cost=None):
property.owner = self
self.pay(from_, cost or property.cost)
def take_a_turn(self):
if self.in_jail:
return GetOutOfJailDecision(self)
@@ -724,6 +741,20 @@ class Player(EconomicActor):
self.advance(num_spaces, just_rolled=True)
def owns_x_of_type(self, type_):
return len(self.properties_by_type.get(type_))
def owns_all_type(self, type_):
num_of_type = len(Property.instances_by_type()[type])
return self.owns_x_of_type(type_) == num_of_type
@property
def properties_by_type(self):
pbt = defaultdict(list)
for property in self.properties:
pbt[property.type].append(property)
return pbt
@staticmethod
def roll_the_dice() -> Tuple[int, Doubles]:
die_one, die_two = choice(range(1, 7)), choice(range(1, 7))
@@ -732,6 +763,20 @@ class Player(EconomicActor):
return total, cast(Doubles, True)
return total, cast(Doubles, False)
@property
def assets(self):
return self.money + self.total_property_mortgage_value
@property
def total_property_mortgage_value(self):
return sum(property.mortgage_cost for property in self.properties)
@property
def properties(self) -> List["Property"]:
# TODO: create an `instances` class attribute on `Property` that keeps track of them all
# then iterate through those instances to see which ones have an owner equal to `self`
return [p for p in Property.instances if p.owner == self]
def advance(
self,
num_spaces=None,
@@ -778,7 +823,11 @@ class Player(EconomicActor):
class Game:
games = []
def __init__(self, *player_names):
def __init__(self, *player_names, buy_decision_algorithm=None):
def return_true(_, __):
return True
self.buy_decision_algorithm = buy_decision_algorithm or return_true
self.games.append(self)
if len(player_names) > 8:
raise TooManyPlayers
@@ -805,4 +854,4 @@ class Game:
print(self.active_players[0], "is the winner!")
game = Game("Bot", "Ro")
game = Game("Bot", "Ro", buy_decision_algorithm=None)