From 2cf301a0a8ccc84724e8fa2c179f87e5c90f51e5 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 10:19:02 +0330 Subject: [PATCH 01/16] Modifying some of functions --- player.py | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/player.py b/player.py index 8ea5cc1..04729d6 100644 --- a/player.py +++ b/player.py @@ -1,32 +1,39 @@ 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.is_in_jail = False self.properties = [] - self.in_jail = False - self.turns_in_jail = 0 - self.rolled_doubles = False - def pay(self, amount) -> None: + def pay_money(self, amount): self.money -= amount - def receive(self, amount) -> None: + def get_money(self, amount): self.money += amount - - def roll_dice(self) -> tuple: - # Roll the dice and return the result + + def roll_dice(self): 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})" + def net_worth(self, props): + # Calculate the player's total net worth by adding their money and the total value of their properties + total_worth = self.money + sum([prop.price for prop in self.properties]) + + # Add the total rent earned from all the player's properties + total_rent = sum([prop.rent for prop in self.properties]) + + return total_worth + total_rent + def __str__(self): + # Convert the list of properties to a comma-separated string of property names + prop_names = ", ".join([prop.name for prop in self.properties]) + + # Format the string using f-strings and return it + return f"{self.name} (Position: {self.position}, Money: {self.money}$, Properties: {prop_names})" From 7cb39f88c83650aa3b59897710af1bdef8cbcc58 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 10:20:24 +0330 Subject: [PATCH 02/16] simplifying the Property class and changing the __str__ func --- property.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/property.py b/property.py index c2eb75b..5f71821 100644 --- a/property.py +++ b/property.py @@ -1,19 +1,13 @@ -# 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, rent, build_price) -> 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.ownable = 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})" - + def __str__(self): + # Format the string using f-strings and return it + return f"{self.name} - Price: {self.price}$, Rent: {self.rent}$" \ No newline at end of file From 0dec637269c9be5e4e94f86f9a8f672193bc1d95 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:04:43 +0330 Subject: [PATCH 03/16] writing comments on net_worth - getting the board using pandas --- main.py | 7 +++---- monopoly_game.py | 41 ++++++++++++++++++++++------------------- player.py | 41 ++++++++++++++++++++++------------------- property.py | 5 +++++ 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/main.py b/main.py index 03ed1b4..7fb83ff 100644 --- a/main.py +++ b/main.py @@ -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 diff --git a/monopoly_game.py b/monopoly_game.py index d1e27ae..eea7825 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -2,6 +2,7 @@ from property import * from player import * from math import ceil +import pandas as pd # Define the Monopoly game class class MonopolyGame: @@ -12,17 +13,19 @@ def __init__(self, board: list=[], players: list=[], current_player: int=0, game self.current_player = current_player # Index of the current player in the players list 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] + + self.board.append(Property(name, space, int(position), int(price), int(rent), int(build_price))) def initialize_players(self) -> None: # Initializing two players with their starting positions, money, and other attributes @@ -41,28 +44,28 @@ 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_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) @@ -71,7 +74,7 @@ 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: @@ -94,7 +97,7 @@ 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 diff --git a/player.py b/player.py index 04729d6..5aaef59 100644 --- a/player.py +++ b/player.py @@ -5,35 +5,38 @@ def __init__(self, name, position, money): self.name = name self.position = position self.money = money - self.is_in_jail = False self.properties = [] + self.is_in_jail = False + self.turns_in_jail = 0 + self.rolled_doubles = False + - def pay_money(self, amount): + def pay_money(self, amount)-> None: self.money -= amount - def get_money(self, amount): + def get_money(self, amount) -> None: self.money += amount - def roll_dice(self): + def roll_dice(self) -> int: dice1 = random.randint(1, 6) dice2 = random.randint(1, 6) total = dice1 + dice2 print(f"{self.name} rolled {dice1} and {dice2} ({total})") return total - - def net_worth(self, props): - # Calculate the player's total net worth by adding their money and the total value of their properties - total_worth = self.money + sum([prop.price for prop in self.properties]) - - # Add the total rent earned from all the player's properties - total_rent = sum([prop.rent for prop in self.properties]) - - return total_worth + total_rent + def net_worth(self, props) -> int: + # Calculate the net worth of the player, which includes money and the total value of their properties and their rent + # Money is added first + net_worth = self.money + # Then, iterate over each property owned by the player and add its price to the net worth + for i in self.properties: + net_worth += props[i].price + # Finally, iterate over each property owned by the player and add its rent to the net worth + for i in self.properties: + net_worth += props[i].rent + # Return the net worth as an integer + return net_worth + + def __str__(self) -> str: + return f"{self.name} (Position: {self.position}, Money: {self.money}$, Properties: {self.properties})" - def __str__(self): - # Convert the list of properties to a comma-separated string of property names - prop_names = ", ".join([prop.name for prop in self.properties]) - - # Format the string using f-strings and return it - return f"{self.name} (Position: {self.position}, Money: {self.money}$, Properties: {prop_names})" diff --git a/property.py b/property.py index 5f71821..78d247d 100644 --- a/property.py +++ b/property.py @@ -8,6 +8,11 @@ def __init__(self, name, space, position, price, rent, build_price) -> None: self.rent = rent self.build_price = build_price self.ownable = False + if space in ["Street", "Railroad", "Utility"]: + self.ownable = True + self.owner = None + self.level = 1 + def __str__(self): # Format the string using f-strings and return it return f"{self.name} - Price: {self.price}$, Rent: {self.rent}$" \ No newline at end of file From fd0177ae8a215202bbcd6ba5fb1c43532e8a0eed Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:16:46 +0330 Subject: [PATCH 04/16] modifying the __str__ function in player class --- player.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/player.py b/player.py index 5aaef59..78a6ac9 100644 --- a/player.py +++ b/player.py @@ -38,5 +38,8 @@ def net_worth(self, props) -> int: return net_worth def __str__(self) -> str: - return f"{self.name} (Position: {self.position}, Money: {self.money}$, Properties: {self.properties})" + return f"{self.name}\n" \ + f"Position: {self.position}\n" \ + f"Money: {self.money}$\n" \ + f"Properties: {self.properties}" \ No newline at end of file From b2e7bba37189768cf843415f1fb22ca014251094 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 12:08:28 +0330 Subject: [PATCH 05/16] adding the number of rounds to the status of the game --- main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 7fb83ff..49e5e0d 100644 --- a/main.py +++ b/main.py @@ -104,15 +104,16 @@ def play(state: MonopolyGame) -> None: # Taking the best action state = state.take_action(best_action) print(f"{curr_player.name} {ACTIONS[best_action]}.") - print(state.players[state.current_player]) + #print(state.players[state.current_player]) 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__": From 1d5c9f648a4ec2d5e56a679c0fa93dcffb6ef576 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:24:41 +0330 Subject: [PATCH 06/16] adding a line to status of the game that shows the net worth --- main.py | 5 +++-- monopoly_game.py | 8 +++++--- player.py | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index 49e5e0d..c3c7f98 100644 --- a/main.py +++ b/main.py @@ -104,14 +104,15 @@ def play(state: MonopolyGame) -> None: # Taking the best action state = state.take_action(best_action) print(f"{curr_player.name} {ACTIONS[best_action]}.") - #print(state.players[state.current_player]) + 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(f"Round: {num_of_rounds}") print("====================================================") print(f"{state.players[0 if state.current_player else 1].name} Won!") diff --git a/monopoly_game.py b/monopoly_game.py index eea7825..d8dfcf4 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -6,11 +6,12 @@ # 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): @@ -112,10 +113,11 @@ def is_terminal(self) -> bool: 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 diff --git a/player.py b/player.py index 78a6ac9..869e40a 100644 --- a/player.py +++ b/player.py @@ -36,7 +36,7 @@ def net_worth(self, props) -> int: net_worth += props[i].rent # Return the net worth as an integer return net_worth - + def __str__(self) -> str: return f"{self.name}\n" \ From 07ceea791b1d83a4569753eadaedce87aae71bdf Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:29:40 +0330 Subject: [PATCH 07/16] adding upgrade to the game --- monopoly_game.py | 4 ++-- property.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/monopoly_game.py b/monopoly_game.py index d8dfcf4..bb3b168 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -82,8 +82,8 @@ def get_possible_actions(self) -> list: 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: diff --git a/property.py b/property.py index 78d247d..f90a270 100644 --- a/property.py +++ b/property.py @@ -1,3 +1,4 @@ +from math import ceil class Property(): def __init__(self, name, space, position, price, rent, build_price) -> None: @@ -8,11 +9,21 @@ def __init__(self, name, space, position, price, rent, build_price) -> None: self.rent = rent self.build_price = build_price self.ownable = False + self.build_price = self.price // 2 + self.upgradable = True if self.build_price > 0 else False if space in ["Street", "Railroad", "Utility"]: self.ownable = True self.owner = None self.level = 1 - + + + def upgrade(self) -> None: + self.rent *= 1.5 + self.rent = ceil(self.rent) + self.level += 1 + if self.level >= 5: + self.upgradable = False + def __str__(self): # Format the string using f-strings and return it return f"{self.name} - Price: {self.price}$, Rent: {self.rent}$" \ No newline at end of file From c288e533dc8009607c0d180d63f9797434137393 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:40:33 +0330 Subject: [PATCH 08/16] modifying the net_worth function in player class --- player.py | 23 ++++++++++++----------- property.py | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/player.py b/player.py index 869e40a..03c7df2 100644 --- a/player.py +++ b/player.py @@ -25,17 +25,18 @@ def roll_dice(self) -> int: return total def net_worth(self, props) -> int: - # Calculate the net worth of the player, which includes money and the total value of their properties and their rent - # Money is added first - net_worth = self.money - # Then, iterate over each property owned by the player and add its price to the net worth - for i in self.properties: - net_worth += props[i].price - # Finally, iterate over each property owned by the player and add its rent to the net worth - for i in self.properties: - net_worth += props[i].rent - # Return the net worth as an integer - return net_worth + # 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 - current_rent) + prop_value + def __str__(self) -> str: diff --git a/property.py b/property.py index f90a270..afe15f5 100644 --- a/property.py +++ b/property.py @@ -9,6 +9,7 @@ def __init__(self, name, space, position, price, rent, build_price) -> None: self.rent = rent self.build_price = build_price self.ownable = False + self.max_rent = self.rent * 5 * 1.5 self.build_price = self.price // 2 self.upgradable = True if self.build_price > 0 else False if space in ["Street", "Railroad", "Utility"]: From c268b06915b155aa02cb5a50d9d2a90a575a2d5b Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Sat, 15 Apr 2023 12:10:07 +0330 Subject: [PATCH 09/16] fix some bugs --- player.py | 2 -- property.py | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/player.py b/player.py index 03c7df2..1a5b4dd 100644 --- a/player.py +++ b/player.py @@ -37,9 +37,7 @@ def net_worth(self, props) -> int: # Calculate net worth return self.money + current_rent + (potential_rent - current_rent) + prop_value - def __str__(self) -> str: - return f"{self.name}\n" \ f"Position: {self.position}\n" \ f"Money: {self.money}$\n" \ diff --git a/property.py b/property.py index afe15f5..d8eb1d2 100644 --- a/property.py +++ b/property.py @@ -16,7 +16,9 @@ def __init__(self, name, space, position, price, rent, build_price) -> None: self.ownable = True self.owner = None self.level = 1 - + if space in ["Community Chest", "Income Tax", "Chance", "Free Parking", "Go To Jail", "Luxury Tax"]: + self.ownable = False + self.owner = None def upgrade(self) -> None: self.rent *= 1.5 @@ -24,7 +26,7 @@ def upgrade(self) -> None: self.level += 1 if self.level >= 5: self.upgradable = False - + def __str__(self): # Format the string using f-strings and return it return f"{self.name} - Price: {self.price}$, Rent: {self.rent}$" \ No newline at end of file From 3375c587afb2ef7b7d48d027f1f5b6662f39386b Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Sun, 16 Apr 2023 19:17:54 +0330 Subject: [PATCH 10/16] fix some bugs --- property.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/property.py b/property.py index d8eb1d2..c4db413 100644 --- a/property.py +++ b/property.py @@ -1,4 +1,5 @@ from math import ceil +import numpy as np class Property(): def __init__(self, name, space, position, price, rent, build_price) -> None: @@ -9,7 +10,7 @@ def __init__(self, name, space, position, price, rent, build_price) -> None: self.rent = rent self.build_price = build_price self.ownable = False - self.max_rent = self.rent * 5 * 1.5 + self.max_rent = self.rent * np.power(1.5, 5) self.build_price = self.price // 2 self.upgradable = True if self.build_price > 0 else False if space in ["Street", "Railroad", "Utility"]: From 10fbcd875460c66186b5b9a28fb26bfd827e2647 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Sun, 16 Apr 2023 19:23:22 +0330 Subject: [PATCH 11/16] fix some bugs --- monopoly_game.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monopoly_game.py b/monopoly_game.py index bb3b168..76e3461 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -54,6 +54,7 @@ def take_action(self, action: int): elif action == 3: curr_prop.rent *= 1.5 curr_prop.rent = ceil(curr_prop.rent) + curr_player.money -= curr_prop.build_price curr_prop.level += 1 elif action == 4: curr_player.position = 10 From cd97af915b7f1a7c241e0c84a1796c4baee5fa53 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Sun, 16 Apr 2023 19:27:01 +0330 Subject: [PATCH 12/16] fix some bugs --- monopoly_game.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monopoly_game.py b/monopoly_game.py index 76e3461..68dbcd7 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -54,7 +54,7 @@ def take_action(self, action: int): elif action == 3: curr_prop.rent *= 1.5 curr_prop.rent = ceil(curr_prop.rent) - curr_player.money -= curr_prop.build_price + curr_player.pay_money(curr_prop.build_price) curr_prop.level += 1 elif action == 4: curr_player.position = 10 From f93652030e2a32328fdbf85f6967be20be738ab5 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Sun, 16 Apr 2023 21:12:21 +0330 Subject: [PATCH 13/16] a different approach and fixing soem bugs --- board2.csv | 41 +++++++++++++++++++++++++++++++++++++++++ main.py | 4 ++-- monopoly_game.py | 13 +++++++++++-- property.py | 29 +++++++++++++++-------------- 4 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 board2.csv diff --git a/board2.csv b/board2.csv new file mode 100644 index 0000000..eb388ad --- /dev/null +++ b/board2.csv @@ -0,0 +1,41 @@ +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 \ No newline at end of file diff --git a/main.py b/main.py index c3c7f98..3d238ac 100644 --- a/main.py +++ b/main.py @@ -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=5, chance: bool=False) -> tuple: # Expectiminimax algorithm to search for the best action if state.is_terminal() or depth == 0: return state.evaluate_utility(), None @@ -120,5 +120,5 @@ def play(state: MonopolyGame) -> None: if __name__ == "__main__": game = MonopolyGame() game.initialize_players() - game.initialize_board("board.csv") + game.initialize_board("board2.csv") play(game) diff --git a/monopoly_game.py b/monopoly_game.py index 68dbcd7..5f88e6c 100644 --- a/monopoly_game.py +++ b/monopoly_game.py @@ -25,8 +25,13 @@ def initialize_board(self, file_name: str): 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))) + 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 @@ -105,8 +110,12 @@ def move_player(self, dice_result:int) -> None: 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] diff --git a/property.py b/property.py index c4db413..38cbdb0 100644 --- a/property.py +++ b/property.py @@ -1,32 +1,33 @@ -from math import ceil -import numpy as np class Property(): - def __init__(self, name, space, position, price, rent, build_price) -> None: + def __init__(self, name, space, position, price, build_price, rent0, rent1, rent2, rent3, rent4, rent5) -> None: self.name = name self.space = space 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.max_rent = self.rent * np.power(1.5, 5) - self.build_price = self.price // 2 - self.upgradable = True if self.build_price > 0 else 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 - if space in ["Community Chest", "Income Tax", "Chance", "Free Parking", "Go To Jail", "Luxury Tax"]: - self.ownable = False - self.owner = None - + self.level = 0 + self.max_rent = self.rentl[5] + self.rent = self.rentl[self.level] + def upgrade(self) -> None: - self.rent *= 1.5 - self.rent = ceil(self.rent) 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 From c3b0a2629a5e09796622bbc9d475289928822cc5 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:24:05 +0330 Subject: [PATCH 14/16] using different eval function --- player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player.py b/player.py index 1a5b4dd..b127156 100644 --- a/player.py +++ b/player.py @@ -35,7 +35,7 @@ def net_worth(self, props) -> int: prop_value = sum([props[i].price for i in self.properties]) # Calculate net worth - return self.money + current_rent + (potential_rent - current_rent) + prop_value + return self.money + current_rent + potential_rent + prop_value def __str__(self) -> str: return f"{self.name}\n" \ From 6b9b4f66b6fd56015b8dc8b81334da6685f5d10a Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:55:06 +0330 Subject: [PATCH 15/16] fix some bugs --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 3d238ac..9196024 100644 --- a/main.py +++ b/main.py @@ -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=5, 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 From 4a158e8b628fb3e83777eb7ab505408573637928 Mon Sep 17 00:00:00 2001 From: Amir Khani <99316850+IAmirKhani@users.noreply.github.com> Date: Wed, 19 Apr 2023 07:47:21 +0330 Subject: [PATCH 16/16] fix some bugs --- board.csv | 82 +++++++++++++++++++++++++++--------------------------- board2.csv | 41 --------------------------- main.py | 2 +- 3 files changed, 42 insertions(+), 83 deletions(-) delete mode 100644 board2.csv diff --git a/board.csv b/board.csv index e9e81ef..eb388ad 100644 --- a/board.csv +++ b/board.csv @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/board2.csv b/board2.csv deleted file mode 100644 index eb388ad..0000000 --- a/board2.csv +++ /dev/null @@ -1,41 +0,0 @@ -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 \ No newline at end of file diff --git a/main.py b/main.py index 9196024..9494714 100644 --- a/main.py +++ b/main.py @@ -120,5 +120,5 @@ def play(state: MonopolyGame) -> None: if __name__ == "__main__": game = MonopolyGame() game.initialize_players() - game.initialize_board("board2.csv") + game.initialize_board("board.csv") play(game)