Skip to content

Fixb #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 41 additions & 41 deletions board.csv
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
Name,Space,Color,Position,Price,PriceBuild,Rent
Go,Go,None,0,0,0,0
Mediterranean Avenue,Street,Brown,1,60,50,2
Community Chest,Chest,None,2,0,0,0
Baltic Avenue,Street,Brown,3,60,50,4
Income Tax,Tax,None,4,200,0,200
Reading Railroad,Railroad,None,5,200,0,25
Oriental Avenue,Street,LightBlue,6,100,50,6
Chance,Chance,None,7,0,0,0
Vermont Avenue,Street,LightBlue,8,100,50,6
Connecticut Avenue,Street,LightBlue,9,120,50,8
Jail,Jail,None,10,0,0,0
St. Charles Place,Street,Pink,11,140,100,10
Electric Company,Utility,None,12,150,0,4
States Avenue,Street,Pink,13,140,100,10
Virginia Avenue,Street,Pink,14,160,100,12
Pennsylvania Railroad,Railroad,None,15,200,0,25
St. James Place,Street,Orange,16,180,100,14
Community Chest,Chest,None,17,0,0,0
Tennessee Avenue,Street,Orange,18,180,100,14
New York Avenue,Street,Orange,19,200,100,16
Free Parking,Parking,None,20,0,0,0
Kentucky Avenue,Street,Red,21,220,150,18
Chance,Chance,None,22,0,0,0
Indiana Avenue,Street,Red,23,220,150,18
Illinois Avenue,Street,Red,24,240,150,20
B. & O. Railroad,Railroad,None,25,200,0,25
Atlantic Avenue,Street,Yellow,26,260,150,22
Ventnor Avenue,Street,Yellow,27,260,150,22
Water Works,Utility,None,28,150,0,4
Marvin Gardens,Street,Yellow,29,280,150,24
Go To Jail,GoToJail,None,30,0,0,0
Pacific Avenue,Street,Green,31,300,200,26
North Carolina Avenue,Street,Green,32,300,200,26
Community Chest,Chest,None,33,0,0,0
Pennsylvania Avenue,Street,Green,34,320,200,28
Short Line,Railroad,None,35,200,0,25
Chance,Chance,None,36,0,0,0
Park Place,Street,Blue,37,350,200,35
Luxury Tax,Tax,None,38,100,0,75
Boardwalk,Street,Blue,39,400,200,50
Name,Space,Color,Position,Price,PriceBuild,Rent,Rent1,Rent2,Rent3,Rent4,Rent5
Go,Go,None,0,0,0,0,0,0,0,0,0
Mediterranean Avenue,Street,Brown,1,60,50,2,10,30,90,160,250
Community Chest,Chest,None,2,0,0,0,0,0,0,0,0
Baltic Avenue,Street,Brown,3,60,50,4,20,60,180,320,450
Income Tax,Tax,None,4,200,0,200,0,0,0,0,0
Reading Railroad,Railroad,None,5,200,0,25,0,0,0,0,0
Oriental Avenue,Street,LightBlue,6,100,50,6,30,90,270,400,550
Chance,Chance,None,7,0,0,0,0,0,0,0,0
Vermont Avenue,Street,LightBlue,8,100,50,6,30,90,270,400,550
Connecticut Avenue,Street,LightBlue,9,120,50,8,40,100,300,450,600
Jail,Jail,None,10,0,0,0,0,0,0,0,0
St. Charles Place,Street,Pink,11,140,100,10,50,150,450,625,750
Electric Company,Utility,None,12,150,0,4,0,0,0,0,0
States Avenue,Street,Pink,13,140,100,10,50,150,450,625,750
Virginia Avenue,Street,Pink,14,160,100,12,60,180,500,700,900
Pennsylvania Railroad,Railroad,None,15,200,0,25,0,0,0,0,0
St. James Place,Street,Orange,16,180,100,14,70,200,550,750,950
Community Chest,Chest,None,17,0,0,0,0,0,0,0,0
Tennessee Avenue,Street,Orange,18,180,100,14,70,200,550,750,950
New York Avenue,Street,Orange,19,200,100,16,80,220,600,800,1000
Free Parking,Parking,None,20,0,0,0,0,0,0,0,0
Kentucky Avenue,Street,Red,21,220,150,18,90,250,700,875,1050
Chance,Chance,None,22,0,0,0,0,0,0,0,0
Indiana Avenue,Street,Red,23,220,150,18,90,250,700,875,1050
Illinois Avenue,Street,Red,24,240,150,20,100,300,750,925,1100
B. & O. Railroad,Railroad,None,25,200,0,25,0,0,0,0,0
Atlantic Avenue,Street,Yellow,26,260,150,22,110,330,800,975,1150
Ventnor Avenue,Street,Yellow,27,260,150,22,110,330,800,975,1150
Water Works,Utility,None,28,150,0,4,0,0,0,0,0
Marvin Gardens,Street,Yellow,29,280,150,24,120,360,850,1025,1200
Go To Jail,GoToJail,None,30,0,0,0,0,0,0,0,0
Pacific Avenue,Street,Green,31,300,200,26,130,390,900,1100,1275
North Carolina Avenue,Street,Green,32,300,200,26,130,390,900,1100,1275
Community Chest,Chest,None,33,0,0,0,0,0,0,0,0
Pennsylvania Avenue,Street,Green,34,320,200,28,150,450,1000,1200,1400
Short Line,Railroad,None,35,200,0,25,0,0,0,0,0
Chance,Chance,None,36,0,0,0,0,0,0,0,0
Park Place,Street,Blue,37,350,200,35,175,500,1100,1300,1500
Luxury Tax,Tax,None,38,100,0,75,0,0,0,0,0
Boardwalk,Street,Blue,39,400,200,50,200,600,1400,1700,2000
13 changes: 7 additions & 6 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def chance_node(main_player: int, state: MonopolyGame, depth: int) -> tuple:
expected_utility += eval * PROBS[dice]
return expected_utility, None

def expectiminimax(main_player: int, state: MonopolyGame, depth: int=4, chance: bool=False) -> tuple:
def expectiminimax(main_player: int, state: MonopolyGame, depth: int=8, chance: bool=False) -> tuple:
# Expectiminimax algorithm to search for the best action
if state.is_terminal() or depth == 0:
return state.evaluate_utility(), None
Expand All @@ -90,13 +90,12 @@ def play(state: MonopolyGame) -> None:
curr_player = state.players[state.current_player]
print(f"{curr_player.name} is on {curr_player.position} and has {curr_player.money}$,")

if curr_player.in_jail:
if curr_player.is_in_jail:
print(f"turns in jail {curr_player.turns_in_jail}")

d1, d2 = curr_player.roll_dice()
print(f"{curr_player.name} rolls dice: {(d1, d2)},")
total_dice = curr_player.roll_dice()
# Moving the player based on the dice outcome
state.move_player(d1 + d2)
state.move_player(total_dice)
print(f"{curr_player.name} lands on {curr_player.position}!", end=" ")

# Determining the best possible action
Expand All @@ -106,14 +105,16 @@ def play(state: MonopolyGame) -> None:
state = state.take_action(best_action)
print(f"{curr_player.name} {ACTIONS[best_action]}.")
print(state.players[state.current_player])
print(f"Current net worth: {state.evaluate_utility()}")

if state.is_terminal():
state.game_over = True
else:
state.switch_player()
num_of_rounds += 1
print(f"Round: {num_of_rounds}")
print("====================================================")
print(f"{state.players[0 if state.current_player else 1].name} Won :) rounds played: {num_of_rounds}")
print(f"{state.players[0 if state.current_player else 1].name} Won!")

# Driver code to start the Monopoly game
if __name__ == "__main__":
Expand Down
65 changes: 40 additions & 25 deletions monopoly_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,36 @@
from property import *
from player import *
from math import ceil
import pandas as pd

# Define the Monopoly game class
class MonopolyGame:
def __init__(self, board: list=[], players: list=[], current_player: int=0, game_over: bool=False):
def __init__(self, board: list=[], players: list=[], current_player: int=0, other_player: int=1, game_over: bool=False):
# Initializing the game state
self.board = board # List to represent the game board
self.players = players # List to represent the players
self.current_player = current_player # Index of the current player in the players list
self.other_player = other_player
self.game_over = game_over # Boolean flag to indicate if the game is over

def initialize_board(self, file_name: str) -> None:
def initialize_board(self, file_name: str):
# Initializing the game board from a csv file
with open(file_name) as file:
next(file)
for line in file:
name, space, color, position, price, build_price, rent = line.rstrip().split(",")
self.board.append(
Property(name, space, color, int(position), int(price), int(rent), int(build_price))
)


df = pd.read_csv(file_name)

for row in df.itertuples():
name = row[1]
space = row[2]
position = row[4]
price = row[5]
build_price = row[6]
rent = row[7]
rent1 = row[8]
rent2 = row[9]
rent3 = row[10]
rent4 = row[11]
rent5 = row[12]

self.board.append(Property(name, space, int(position), int(price), int(rent), int(build_price), int(rent1), int(rent2), int(rent3), int(rent4), int(rent5)))

def initialize_players(self) -> None:
# Initializing two players with their starting positions, money, and other attributes
Expand All @@ -41,28 +50,29 @@ def take_action(self, action: int):
if action == 0:
pass
elif action == 1:
curr_player.pay(curr_prop.price)
curr_player.pay_money(curr_prop.price)
curr_player.properties.append(curr_position)
curr_prop.owner = self.current_player
elif action == 2:
curr_player.pay(curr_prop.rent)
new_players[curr_prop.owner].receive(curr_prop.rent)
curr_player.pay_money(curr_prop.rent)
new_players[curr_prop.owner].get_money(curr_prop.rent)
elif action == 3:
curr_prop.rent *= 1.5
curr_prop.rent = ceil(curr_prop.rent)
curr_player.pay_money(curr_prop.build_price)
curr_prop.level += 1
elif action == 4:
curr_player.position = 10
curr_player.in_jail = True
curr_player.is_in_jail = True
curr_player.turns_in_jail += 1
elif action == 5:
curr_player.turns_in_jail += 1
elif action == 6:
curr_player.pay(50)
curr_player.in_jail = False
curr_player.pay_money(50)
curr_player.is_in_jail = False
curr_player.turns_in_jail = 0
elif action == 7:
curr_player.in_jail = False
curr_player.is_in_jail = False
curr_player.turns_in_jail = 0
return MonopolyGame(new_board, new_players, self.current_player, self.game_over)

Expand All @@ -71,15 +81,15 @@ def get_possible_actions(self) -> list:
curr_player = self.players[self.current_player]
curr_position = curr_player.position
curr_prop = self.board[curr_position]
if curr_player.in_jail:
if curr_player.is_in_jail:
if curr_player.rolled_doubles:
return [7]
if curr_player.turns_in_jail >= 3:
return [6]
return [5, 6]
if curr_prop.ownable:
if curr_prop.owner == self.current_player:
if curr_prop.level < 5:
if curr_prop.owner == self.current_player and curr_prop.upgradable:
if curr_player.money > curr_prop.build_price:
return [3, 0]
return [0]
elif curr_prop.owner == None:
Expand All @@ -94,25 +104,30 @@ def get_possible_actions(self) -> list:

def move_player(self, dice_result:int) -> None:
# Pass if the player is in jail
if self.players[self.current_player].in_jail:
if self.players[self.current_player].is_in_jail:
return
curr_player = self.players[self.current_player]
curr_position = curr_player.position
# Update the player's position based on the dice roll result
curr_position = (curr_position + dice_result) % len(self.board)
# Add 200 to the player's balance if they passed the "Go" cell
if curr_position < curr_player.position:
curr_player.money += 200
#print(f"{curr_player.name} collect 200$")
curr_player.position = curr_position

def is_terminal(self) -> bool:
# Check if the game has reached a terminal state
curr_player = self.players[self.current_player]
if curr_player.money <= 0:
return True
return False

def evaluate_utility(self):
def evaluate_utility(self) -> int:
curr_player = self.players[self.current_player]
curr_net_worth = curr_player.net_worth(self.board)
# Evaluate the utility of the current game state for the current player
return curr_player.net_worth(self.board)
return curr_net_worth

def switch_player(self):
# Switch to the next player's turn
Expand Down
42 changes: 27 additions & 15 deletions player.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
import random

# Define the Player class
class Player:
def __init__(self, name: str, position: int, money: int):
class Player():
def __init__(self, name, position, money):
self.name = name
self.position = position
self.money = money
self.properties = []
self.in_jail = False
self.is_in_jail = False
self.turns_in_jail = 0
self.rolled_doubles = False


def pay(self, amount) -> None:
def pay_money(self, amount)-> None:
self.money -= amount

def receive(self, amount) -> None:
def get_money(self, amount) -> None:
self.money += amount

def roll_dice(self) -> tuple:
# Roll the dice and return the result

def roll_dice(self) -> int:
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
self.rolled_doubles = True if dice1 == dice2 else False
return (dice1, dice2)
total = dice1 + dice2
print(f"{self.name} rolled {dice1} and {dice2} ({total})")
return total

def net_worth(self, props) -> int:
return self.money + sum([props[i].price for i in self.properties]) + sum([props[i].rent for i in self.properties])

def __str__(self) -> str:
return f"{self.name} (Position: {self.position}, Money: {self.money}$, Properties: {self.properties})"
# Calculate current rent
current_rent = sum([props[i].rent for i in self.properties])

# Calculate potential rent with all properties fully developed
potential_rent = sum([props[i].max_rent for i in self.properties])

# Calculate current property value
prop_value = sum([props[i].price for i in self.properties])

# Calculate net worth
return self.money + current_rent + potential_rent + prop_value

def __str__(self) -> str:
return f"{self.name}\n" \
f"Position: {self.position}\n" \
f"Money: {self.money}$\n" \
f"Properties: {self.properties}"
33 changes: 24 additions & 9 deletions property.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
# Define the Property class
class Property:
def __init__(self, name: str, space: str, color: str, position: int, price: int, rent: int, build_price: int):

class Property():
def __init__(self, name, space, position, price, build_price, rent0, rent1, rent2, rent3, rent4, rent5) -> None:
self.name = name
self.space = space
self.color = color
self.position = position
self.price = price
self.rent = rent
self.build_price = build_price
self.rentl = []
self.rentl.append(rent0)
self.rentl.append(rent1)
self.rentl.append(rent2)
self.rentl.append(rent3)
self.rentl.append(rent4)
self.rentl.append(rent5)
self.level = 0
self.ownable = False
self.upgradable = True if space in ["Street"] else False
if space in ["Street", "Railroad", "Utility"]:
self.ownable = True
self.owner = None
self.level = 1

def __str__(self) -> str:
return f"{self.name} (Price: {self.price}, Rent: {self.rent})"
self.level = 0
self.max_rent = self.rentl[5]
self.rent = self.rentl[self.level]

def upgrade(self) -> None:
self.level += 1
if self.level >= 5:
self.upgradable = False
self.rent = self.rentl[self.level]

def __str__(self):
# Format the string using f-strings and return it
return f"{self.name} - Price: {self.price}$, Rent: {self.rent}$"