mega-commit, some from now, some from months ago. added a lot of logging tonight so we can watch a game in real-time. also included slowdown for the same purpose

This commit is contained in:
Zev B Averbach
2020-11-25 19:55:13 +01:00
parent 40e94c0c43
commit c3ed6d0614
32 changed files with 2976 additions and 78 deletions

88
buy_decision_algos.py Normal file
View File

@@ -0,0 +1,88 @@
"""
from
[here](https://blog.ed.ted.com/2017/12/01/heres-how-to-win-at-monopoly-according-to-math-experts/):
'For every property (apart from the brown set — which, lets be honest, is basically pointless),
its the third house that is really worth investing in quickly. After that, build more if you have
the money, but its probably worth waiting a few turns if cash is a bit tight. Since there are a
limited number of houses in the game, building three houses on properties early and then waiting
to upgrade further has the added advantage of potentially blocking the building projects of other
players. Sneaky, huh?'
'utilities are completely pointless.'
"""
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from monopoly import Property, Player
class BuyDecision(ABC):
@abstractmethod
def __call__(self, property_: "Property", player: "Player"):
pass
class BuyEverything(BuyDecision):
def __call__(self, _, __):
return True
class BuyIfHaveThreeTimesPrice(BuyDecision):
def __call__(self, property_: "Property", player: "Player"):
return player.money >= property_.cost * 3
class BuyIfDontHaveTwoPartialMonopoliesOfOtherColors(BuyDecision):
def __call__(self, property_: "Property", player: "Player"):
num_partial_monopolies = 0
for property_type, properties in player.properties_by_type.items():
if property_type in ("railroad", "utility"):
continue
if len(properties) == 3:
num_partial_monopolies += 1
if num_partial_monopolies == 3:
print(
f"{player.name} isn't buying {property_} because "
f"they have {num_partial_monopolies} monopolies"
)
return False
return True
class BuyIfOwnFewerThanFivePropertiesOrHaveOneOfThisColor(BuyDecision):
def __call__(self, property_, player):
num_properties = len(player.properties)
if num_properties < 5:
print(f"{player} wants to buy {property_}")
return True
for property_type, properties in player.properties_by_type.items():
if property_type == property_.type:
print(f"{player} wants to buy {property_}")
return True
print(f"{player} doesn't want to buy {property_}")
return False
class BuyIfNoOneOwnsTypeAndIsOfTheOneTypeOwned(BuyDecision):
"""
ALGORITHM
---------
If nobody owns this type of property, buy it.
If only one player owns all owned property of this type, buy it.
If this player owns any of this type fo property, buy it.
"""
def __call__(self, property_, player):
properties_of_this_type = Property.instances_by_type()[property_.type]
if not any(p.owner for p in properties_of_this_type):
return True
# prevent others from getting monopolies
if (
len(set([p.owner for p in Property.instances_by_type()[property_.type]]))
== 1
):
return True
players_property_types = player.properties_by_type.keys()
if player.properties and property_.type in players_property_types:
return True
return False