diff --git a/images/board_layout/CLI/board_template.txt b/images/board_layout/CLI/board_template.txt deleted file mode 100644 index 3f984c0..0000000 --- a/images/board_layout/CLI/board_template.txt +++ /dev/null @@ -1,17 +0,0 @@ -This is made to see the output of the while loop we used to create the boardgame with, also to check if it prints out correctly. - -We could also just print this out as one print statement but what was the fun in that. - ROW C - _________________________________________________ - | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | - | 17 | | 28 | -R | 16 | | 29 | R -O | 15 | | 30 | O -W | 14 | | 31 | W - | 13 | | 32 | -B | 12 | | 33 | D - | 11 | | 34 | - | 10 |_______________________________________| 35 | - | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - - ROW A \ No newline at end of file diff --git a/images/board_layout/CLI/layout_game_board.PNG b/images/board_layout/CLI/layout_game_board.PNG deleted file mode 100644 index d23cc64..0000000 Binary files a/images/board_layout/CLI/layout_game_board.PNG and /dev/null differ diff --git a/main.py b/main.py index cd9ac52..0491984 100644 --- a/main.py +++ b/main.py @@ -21,28 +21,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - # import Pygame specific objects, functions and functionality from src.game_manager import GameStateManager if __name__ == "__main__": - # version choice is disabled for debugging reasons game = GameStateManager() game.run() - - # print( - # """ - # Welcome to Pyseas! - # Please select a version to play: - # 1. CLI version - # 2. GUI version""" - # ) - # choice: str = input("Enter the number of your choice: ") - # while choice not in ['1', '2']: - # choice = input("Enter the number of your choice: ") - - # if choice == "1": - # CLI().run() - # elif choice == "2": - # GUI().run() diff --git a/src/CLI/board.py b/src/CLI/board.py deleted file mode 100644 index 753c628..0000000 --- a/src/CLI/board.py +++ /dev/null @@ -1,521 +0,0 @@ -from random import randrange, choice - -from .inventory import Inventory -from .money import Money -from .selling import ( - chest_wealth, - chest_ancient, - chest_volcanic, - chest_captain, - chest_cursed, - chest_greg, - chest_legend, - chest_mermaid, - chest_rage, - chest_strong, -) -from .buying import basic_quest, medium_quest, hard_quest, drunken_quest - - -player_inventory = Inventory() -player_wallet = Money(currency="", worth=0) - - -class Board: - def __init__(self, players): - - # all the sea of thieves inspired locations you can visit on the board - self.locations: list[str] = [ - "start", - "isle", - "event", - "isle", - "harbor", - "pirate_king", - "isle", - "captain_blazeheart", - "harbor", - "the_syndicate", - "harbor", - "change", - "isle", - "isle", - "pirate_king", - "isle", - "wreckage_isle", - "harbor", - "ghost_brig", - "harbor", - "event", - "isle", - "isle", - "pirate_king", - "harbor", - "captain_blazeheart", - "harbor", - "the_syndicate", - "isle", - "chance", - "harbor", - "harbor", - "pirate_king", - "wreckage_isle", - "dangerous_sea", - "dangerous_sea", - "dangerous_sea", - ] - - # created a list with an index and locations in a dict to handle the game logic of landing on a tile on the board to call a function - self.locations_with_index: list[dict[str, int | str]] = [] - for i, c in enumerate(self.locations): - self.locations_with_index.append({"index": i, "location": c}) - self.current_position = self.locations_with_index[0]["index"] - - # when a player rolls the dice he/she lands on one of these tiles and a function gets called - - # we had the idea to color all the tiles later on but due to time constrains we did not had the time to implement this - self.locations_actions = { - "start": self.visit_start, # yellow - "isle": self.visit_isle, # white - "event": self.visit_event, # green - "harbor": self.visit_harbor, # white - "pirate_king": self.visit_pirate_king, # grey - "captain_blazeheart": self.visit_captain_blazeheart, # grey - "the_syndicate": self.visit_the_syndicate, # red - "change": self.visit_change, # purple - "wreckage_isle": self.visit_wreckage_isle, # brown - "ghost_brig": self.visit_ghost_brig, # black - "dangerous_sea": self.visit_dangerous_sea, # white - } - self.players = {player.player_id: 0 for player in players} - - def visit_locations_by_index(self, index: int): - """ - This handles all the functions in self.locations_actions - When a player lands on a tile the action variable gets called and via that logic a function gets called when it is in the self.locations list - """ - location = self.locations[index] - action = self.locations_actions.get(location) - if action: - action() - - def update_player_position(self, player, total_roll): - """Logic of the game that updates the current player pos to a new player pos when the dices are throwed""" - # current position of the player - current_position = self.players[player.player_id] - # new position after roll - new_position = (current_position + total_roll) % len(self.locations_with_index) - # update current position of the player - self.players[player.player_id] = new_position - return new_position - - def test(self): - """ - This is an old function cause before I was still busy by implementing the logic when you throw the dice, land on a tile, a function gets called - """ - pass - - # print("Board is working!") - - def visit_start(self): - print("You are at the start.") - # self.test() - - # added a randomizer to call different isles you could visit as player - def visit_isle(self): - """The idea was that you could get a random item on the islands you visit, because of time constraints we had no time to implement this.""" - print("You arrived at an isle.") - # isle = "Island" - # isles = [can_cove, cres_isle, lone_cove, m_hide, s_bounty, smug_bay, wand_ref] - # rand_isle = random.randrange(len(isles)) - # print(f"You arrived at {isles[rand_isle]}") - # print("\nThere is a chest on the isle.") - - # we had events you could encounter like sea of thieves does - def visit_event(self): - """You get a little story event which gets you a random reward to your inventory.""" - # print("You encountered an event.\n") - loc_1 = "Red Tornado" - loc_2 = "Green Tornado" - - sea_events = [loc_1, loc_2] - event = choice(sea_events) - print(f"\nYou sail with your crew and on the horizon you see {event}") - - if event == loc_1: - player_inventory.extension(chest_rage.name) - print( - """You see a specific storming red tornado on a horizon and decide to sail and confront it! Uppon arrival you see the legendary Ghost Casper. - You emmidiatly engage in a battle with the Ashen Lord. Its a truely hellish battle. She summons her troops to help her fight you off. - It rains fire balls out of the red sky! Everywhere it shoots fire! You barely survive that fight but in the end you kill the ruthless Lord - and het your reward...""" - ) - print("\nYou get a dangerous Doom Chest!") - return - elif event == loc_2: - player_inventory.extension(chest_cursed.name) - print( - """You see a specific storming green tornado on a horizon and decide to sail and confront it! - You arrive and what you see is a frightening sight. Ghost ships come out of portals appearing on the sea! - You fight them off. You fight them all off! Heaps and heaps of waves of ghos ships appear and you and your - crew fight them until they're all sunk! - You see your price on the see!""" - ) - print("\nYou get a dangerous Cursed Chest!") - return event - - # just as sea of thieves you could visit the different sea posts in the game. - def visit_harbor(self): - """I came up with some star constellations to name these harbors""" - aquila = "The Aquila" - north_star = "The North Star Constellation" - great_har = "The Great Trade Harbor" - steph_spoils = "Stephan's Spoils" - great_bear = "The Great Bear" - phoenix_store = "The Phoenix Store" - orion = "Orion the Hunter" - mermaid = "Mermaid Twins" - - harbors = [ - aquila, - north_star, - great_har, - steph_spoils, - great_bear, - phoenix_store, - orion, - mermaid, - ] - rand_harbor = randrange(len(harbors)) - print(f"You arrived at {harbors[rand_harbor]}") - - # a randomizer of questions the pirate king could ask you if you landed on his tile - def visit_pirate_king(self): - print("You encountered the Pirate King.") - q1 = """What is the main objective in PySeas? - A. Collecting treasure - B. Battling mythical creatures - C. Exploring ancient ruins """ - pirate_king = [q1] - - question = choice(pirate_king) - print(f"Let me ask ye a question, matey! \n{question}") - is_valid_choice = False - while not is_valid_choice: - inp_choice: str = input("So what is it then? ").lower() - is_valid_choice = inp_choice in ['a', 'b', 'c'] - if not is_valid_choice: - print("Didn't they learn you to read, fool? Try again! ") - if question == q1: - if inp_choice == "c": - print( - "I've never heard that one in me life! Piss off! No gold for you..." - ) - elif inp_choice == "b": - print( - "Mate, you'll walk the plank next time if ya give such a pathetic answer again!" - ) - elif inp_choice == "a": - player_inventory.extension(chest_captain.name) - print("Well done, privateer! I'll reward you good for this one.") - # self.test() - - # just as the pirate lord tile, this logic was the same on here - def visit_captain_blazeheart(self): - print("You encountered Captain Blazeheart.") - q1 = """Which of the following is not a type of ship available in PySeas? - A) Brigantine - B) Galleon - C) Sloop """ - - cap_blaze = [q1] - - question = choice(cap_blaze) - print(f"Let me ask ye a question, matey! \n{question}") - is_valid_choice = False - while not is_valid_choice: - inp_choice = input("So what is it then? ").lower() - is_valid_choice = inp_choice in ['a', 'b', 'c'] - if not is_valid_choice: - print("Didn't they learn you to read, sea dog? Try again! ") - if question == q1: - if inp_choice.lower() == "c": - print( - "I've never heard that one in me life! Piss off! No gold for you..." - ) - elif inp_choice.lower() == "b": - print( - "Mate, you'll walk the plank next time if ya give such a pathetic answer again!" - ) - elif inp_choice.lower() == "a": - player_inventory.extension(chest_captain.name) - print("Well done, privateer! I'll reward you good for this one.") - - def visit_the_syndicate(self): - """This is the shop where you can buy quests, sell chests you found or got via events etc""" - - print("You visit the Syndicate.") - while True: - print( - """Welcome to the shop, privateer! There are a couple of actions you could do!: - 1. Choose and buy a quest for a chest! - 2. Check your inventory to see if you have enough gold! - 3. If you have something you'd like to sell, sell it here! - 4. Check how much gold you have! - 5. If you don't mean no bussiness, I'll welcome you another round! Farewell! - """ - ) - choice = input("So, what are ya wating for? What is it?: ") - - if choice == "1": - print( - """Available Quests: - 1. Quest for the burried treasure - 200 gold - 2. Quest for the Lost Chest - 1000 gold - 3. Quest for the Drunken Sailor - 1250 gold - 4. Quest for the The Vault - 1750 gold - """ - ) - quest_choice = input("Wich one would you like to buy, privateer? ") - if quest_choice == "1": - player_wallet.buy_quest(basic_quest) - player_inventory.extension(chest_captain.name) - print( - """You've got a map that leads to the burried treasure. - You make your way all the way to Cutlass Cay and dig out a wonderfull Captain's Chest - """ - ) - elif quest_choice == "2": - player_wallet.buy_quest(medium_quest) - player_inventory.extension(chest_strong.name) - print( - """You got a misterious compass. Although your facing north, the compass doesnt point that way. - It seems that the misterious compass shows you the way to the Lost Treasure! - You quickly gather your crew and sail to the location given by the misterious compass. - You arrive at a vulcanic isle and you see the treasure but its guarded by skeletons. - You and your crew quickly fight them of and take whats yours!""" - ) - elif quest_choice == "3": - player_wallet.buy_quest(hard_quest) - player_inventory.extension(chest_ancient.name) - print( - """The Pirate gives you a location of the Drunken Sailor. The Hoarder adds that he is in a possession of a great price! - You sail forth to the location and you find a port. You ask the locals of they know about the Drunken Sailor. - They tell you about the local tavern. There you find the drunken bastard sleeping with a barrel under his foot. - You slowly but quietly take the barrel out of his possession and you take it onto your ship. You notice that when - holding the treasure your view is distorted and you can’t walk straight. You’re drunk! - It seems to be the effect of holding the barrel. You also hear in your head the famous sea shanty “Drunken Sailor”... - Great! Now you have the chest of thousands Grogs and a shanty in your head...""" - ) - elif quest_choice == "4": - player_wallet.buy_quest(drunken_quest) - player_inventory.extension(chest_greg.name) - print( - """You raise your sails and sail forth to the location. - Uppon arrival it seems that there is no treasure but only another map that leads to a new locations. - You sail to a couple isles with your new maps you keep finding and you arrive at a fort where you find a burned compas. - It leeds you to a isle and the vault on it. You open the vault and see all the treasure it contains. - You take the first chest and suddenly the vault starts to close. You panic and run away with only one chest.""" - ) - else: - print("I don't have that quest in me shop! Try again!") - - elif choice == "2": - player_inventory.show_eq() - - elif choice == "3": - print("This is what you can sell: ") - player_inventory.show_eq() - print( - """Chest's overwiev: - 1. Chest of Wealth - 9500 gold - 2. Legendary Chest - 8600 gold - 3. Captain's Chest - 560 gold - 4. Chest of the Cursed One - 1160 gold - 5. Chest of a the drunken Greg - 2500 gold - 6. Mermaid's Chest - 910 gold - 7. Volcanic Chest - 520 gold - 8. Stronghold's Chest - 2000 gold - 9. Chest of Doom - 3500 gold - 10. Chest of the Ancient - 3000 gold - """ - ) - - while True: - chest_choice = input( - "What would you like to sell? (Press q to quit selling): " - ).lower() - if chest_choice == "q": - break - if chest_choice == "1": - player_wallet.sell_chest(chest_wealth) - player_inventory.remove_item(chest_wealth.name) - elif chest_choice == "2": - player_wallet.sell_chest(chest_legend) - player_inventory.remove_item(chest_legend.name) - elif chest_choice == "3": - player_wallet.sell_chest(chest_captain) - player_inventory.remove_item(chest_captain.name) - elif chest_choice == "4": - player_wallet.sell_chest(chest_cursed) - player_inventory.remove_item(chest_cursed.name) - elif chest_choice == "5": - player_wallet.sell_chest(chest_greg) - player_inventory.remove_item(chest_greg.name) - elif chest_choice == "6": - player_wallet.sell_chest(chest_mermaid) - player_inventory.remove_item(chest_mermaid.name) - elif chest_choice == "7": - player_wallet.sell_chest(chest_volcanic) - player_inventory.remove_item(chest_volcanic.name) - elif chest_choice == "8": - player_wallet.sell_chest(chest_strong) - player_inventory.remove_item(chest_strong.name) - elif chest_choice == "9": - player_wallet.sell_chest(chest_rage) - player_inventory.remove_item(chest_rage.name) - elif chest_choice == "10": - player_wallet.sell_chest(chest_ancient) - player_inventory.remove_item(chest_ancient.name) - print( - "Something else you'd like to sell? (Press q to quit selling) " - ) - - elif choice == "4": - player_wallet.show_money() - elif choice == "5": - print("Farewell, bloody Pirate!") - else: - print("There is no choice like that, try again!") - break - # self.test() - - # just like monopoly you could get a change card, because of time constraints couldn't we get this finished in time - def visit_change(self): - print("You landed on change.") - # self.test() - - # on the board you can land on shipwreck isles, these are also randomized - def visit_wreckage_isle(self): - # print(f"You found {wreck_land[rand_land]}") - wreck_1 = "La Dama Negra" - wreck_2 = "El Impulto" - wreck_3 = "The Black Pearl" - land = "Nassau" - - wreck_land = [wreck_1, wreck_2, wreck_3, land] - # rand_land = random.randrange(len(wreck_land)) - random_item = choice(wreck_land) - print("You dwell with your crew through the sea and find", random_item) - - if random_item == wreck_1: - player_inventory.extension(chest_mermaid.name) - print( - """A great man'o'war galleon that once was feared on the seas... - Now, its just a wreck. It seems a Pirate King has defeated the Legendary ship. - You dive into the water and swim into the shipwreck.!""" - ) - print("\nYou find a Coral Marauder's Chest!") - elif random_item == wreck_2: - player_inventory.extension(chest_strong.name) - print( - """Once the most powerfull ship that these seas have ever seen. Fast, a strong fire power and mighty ram attack. - Now it's just shipwreck with many others, but its legend goes on... - You dive into the water and swim into the shipwreck.""" - ) - print("\nYou find a Stronghold chest!") - elif random_item == wreck_3: - player_inventory.extension(chest_legend.name) - print( - """Every Pirate knows the legend of the Black Pearl! Once the fastest ship on the seas, a ghost ship, with black sails, - a damned crew and a Captain so evil that hell itself spat him back out... - It has been told that people entering the black pearl never came back, but then, where are the stories comming from? - You dive into the water and swim into the shipwreck.""" - ) - print("\n You find a Chest of the Damned!") - - # we wanted to have this as a jail, we could not get to this and hope we may get it later if we refactor the game to pygame for instance - def visit_ghost_brig(self): - print("You are visting the Ghost Brig.") - # self.test() - - # in sea of thieves you have boundaries, we made some tiles the red sea, maybe redundant but in practice it is okay for what you do with it - def visit_dangerous_sea(self): - """We need another name for red sea.""" - print("You are sailing in the dangerous sea.") - # self.test() - - # this is an higher order function that calls the other functions to print out the board - def print(self): - # After the function gets called it prints out this format of the board - # ROW C - # _________________________________________________ - # | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | - # | 17 | | 28 | - # R | 16 | | 29 | R - # O | 15 | | 30 | O - # W | 14 | | 31 | W - # | 13 | | 32 | - # B | 12 | | 33 | D - # | 11 | | 34 | - # | 10 |_______________________________________| 35 | - # | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - - # ROW A - self.print_header_board() - self.print_left_right_board() - self.print_footer_board() - - def print_header_board(self) -> None: - """Prints out the header of the board""" - - row_c = self.locations_with_index[18:28] - print(" ._________________________________________________. ") - - # creates a new list with all the index numbers - new_row_c = [str(cell["index"]) for cell in row_c] - # print(new_row_c) - - # print a '|' between every index number - header = " | ".join(new_row_c) - - # print the header with a '|' on both ends - print(" | " + header + " | ") - - def print_left_right_board(self) -> None: - """Prints the left/right border of the board""" - - # haal de rijen met indexnummers op - row_b = self.locations_with_index[10:18] - row_d = self.locations_with_index[28:36] - - # for row_b we had to make it reverse, because of in the assignment we had to make the board clockwise, otherwise it could not work. - # reverse de list - row_b.reverse() - - # loops through all the index numbers - for i in range(len(row_b)): - cell_column_b = row_b[i]["index"] - cell_column_d = row_d[i]["index"] - - board_row = f" | {cell_column_b} | | {cell_column_d} |" - print(board_row) - - def print_footer_board(self) -> None: - """Prints the footer of the board""" - - # gets the first row of all index numbers - row_a = self.locations_with_index[0:10] - - row_a.reverse() - - # new list with index numbers only - new_row_a = [] - - # format the index numbers and append them to the list - for cell in row_a: - new_row_a.append(f"{cell['index']:>02}") - - # create a formatted str from the formatted index numbers - formatted_row = " | ".join(new_row_a) - print(f" | {formatted_row} | ") \ No newline at end of file diff --git a/src/CLI/buying.py b/src/CLI/buying.py deleted file mode 100644 index 70b88a5..0000000 --- a/src/CLI/buying.py +++ /dev/null @@ -1,27 +0,0 @@ -from dataclasses import dataclass - - -@dataclass -class Buying: - """There are some problems with how the game perceives buying items. it needs to be fixed or it needs to be reworked entirely.""" - - name: str - quest_type: str - quest_worth: int - - -basic_quest = Buying( - name="Quest for the burried treasure", quest_type="Basic Quest", quest_worth=200 -) - -medium_quest = Buying( - name="Quest to the Lost Treasure", quest_type="Medium Quest", quest_worth=1000 -) - -drunken_quest = Buying( - name="Quest for the Drunken Sailor", quest_type="Drunken Quest", quest_worth=1250 -) - -hard_quest = Buying( - name="Quest for the Secret Vault", quest_type="Hard Quest", quest_worth=1750 -) diff --git a/src/CLI/gameloop.py b/src/CLI/gameloop.py deleted file mode 100644 index 818ce42..0000000 --- a/src/CLI/gameloop.py +++ /dev/null @@ -1,112 +0,0 @@ -import os - -# import dataclasses and typchecking -from dataclasses import dataclass, field -from typing import List - -from src.CLI.board import Board -from src.CLI.player import Player - - -@dataclass -class CLI: - """Command Line Interface, only using print statements""" - - players: List[Player] = field(init=False) - board: Board = field(init=False) - current_player_index: int = 0 - running: bool = False - - def __post_init__(self): - self.clear_screen() - self.players = [ - Player(name_of_player="player 1", player_id=0), - Player(name_of_player="player 2", player_id=1), - ] - self.board = Board(self.players) - - # logic which players turn it is - def toggle_player_index(self): - if self.current_player_index == 0: - self.current_player_index = 1 - else: - self.current_player_index = 0 - - @staticmethod - def clear_screen(): - """A function made to clear the screen in the Python boardgame. - Could be used or altered in Pygame if needed.""" - - os.system("cls" if os.name == "nt" else "clear") - - def run(self): - self.initialize_game() - self.running = True - while self.running: - start_the_game = input( - "Would you like to start the game? Press enter to continue. " - ) - if start_the_game == "": - self.clear_screen() - break - self.board.print() - self.player_switch(self.players) - - def player_switch(self, players): - """This decides what the current player pos is and then switch to the other player, when the player gets asked to end the turn""" - - while True: - current_player = players[self.current_player_index] - print( - f"\nIt's {current_player.name_of_player.capitalize()}'s turn! Current position is {self.board.players[self.current_player_index]}" - ) - - # end_turn = False - - while True: - roll_dice = input("\nDo you want to roll the dice? (yes/y) \n") - if roll_dice.lower() in ["yes", "y"]: - # current_player.dice_roll() - current_player.move_player(self.board) - if current_player: - current_player.perform_action( - self.board, - new_position=self.board.players[self.current_player_index], - ) - break - else: - print( - "You made a mistake, you can only answer yes to roll the dice!" - ) - continue - - stop_turn = input("\nDo you want to end your turn? (yes/no) \n") - if stop_turn.lower() in ["yes", "y"]: - self.toggle_player_index() - Board(players).print() - elif stop_turn.lower() in ["no", "n"]: - print("\nYou must continue your turn.") - self.toggle_player_index() - Board(players).print() - else: - print("Input error. Please answer yes or no.") - - def initialize_game(self): - print("Ahoy Mateyy To PySeas!\n") - - for player in self.players: - while True: - name = input(f"Enter player {player.player_id+1} name: ").strip() - if 2 <= len(name) <= 10 and name.isalpha(): - player.name_of_player = name - break - else: - print( - "Input error. Player name should be between two characters and maximum ten characters containing only alphabets." - ) - continue - - # print(f"\nAhoy {self.players[0].name_of_player.capitalize()} & {self.players[1].name_of_player.capitalize()} to the start of the game!\n") - for player in self.players: - player.print_info() - return self.players diff --git a/src/CLI/inventory.py b/src/CLI/inventory.py deleted file mode 100644 index 4196700..0000000 --- a/src/CLI/inventory.py +++ /dev/null @@ -1,26 +0,0 @@ -from dataclasses import dataclass, field -from typing import List - - -@dataclass -class Inventory: - """The inventory has some problems with appending the right items, also because we use lists it can become a bit disorganised to store those items""" - - items: List[str] = field(default_factory=list) - - def extension(self, new_item: str) -> None: - self.items.append(new_item) - - def remove_item(self, sell_item: str) -> None: - if sell_item in self.items: - self.items.remove(sell_item) - else: - print("There is no such item in your inventory!") - - def show_eq(self) -> None: - if not self.items: - print("Your inventory is empty!") - else: - print("Your inventory:") - for item in self.items: - print(item) diff --git a/src/CLI/money.py b/src/CLI/money.py deleted file mode 100644 index b3a0fc8..0000000 --- a/src/CLI/money.py +++ /dev/null @@ -1,37 +0,0 @@ -from dataclasses import dataclass - - -@dataclass -class Money: - """The money class should be called something else perhaps, we should""" - - currency: str - worth: int - max_worth: int = 1500000 - # self.purchase = basic_quest - - def buy(self, purchase_amount) -> None: - self.worth -= purchase_amount - self.worth = max(self.worth, 0) - - def buy_quest(self, quest) -> None: - if self.worth >= quest.quest_worth: - print( - f"You have purchesed {quest.name} for {quest.quest_worth} {self.currency}" - ) - self.buy(quest.quest_worth) - else: - print("You don't have enough gold to buy a quest!") - - def sell(self, sell_amount) -> None: - self.worth += sell_amount - - def sell_chest(self, chest) -> None: - if self.worth <= chest.chest_worth and self.worth >= chest.chest_worth: - print(f"You sold {chest.name} for {chest.chest_worth} {self.currency}") - self.sell(chest.chest_worth) - else: - ("You don't have the items to sell!") - - def show_money(self) -> None: - print(f"You have now an impressive amount of {self.worth} {self.currency}") diff --git a/src/CLI/player.py b/src/CLI/player.py deleted file mode 100644 index 74a38eb..0000000 --- a/src/CLI/player.py +++ /dev/null @@ -1,63 +0,0 @@ -from random import randint -from dataclasses import dataclass, field -from typing import List - -from .money import Money -from .inventory import Inventory - - -@dataclass -class Player: - - name_of_player: str - player_id: int - inventory: List[str] = field(default_factory=list) - wallet: int = 0 - board_index: int = 0 - - def __post_init__(self): - self.inventory = Inventory().items - self.wallet = Money(currency="gold", worth=0).worth - - # self.roll_history_p1 = [] - # self.roll_history_p2 = [] - - def print_info(self): - print( - f"Arrr.. Mateyy {self.name_of_player.capitalize()} Down below you can see your stats:\n" - ) - print( - f"Player: {self.name_of_player.capitalize()}\nInventory: {self.inventory}\nWallet: {self.wallet}\nBoard index: {self.board_index}\n" - ) - - def dice_roll(self): - roll_results = [randint(1, 6) for _ in range(2)] - total_roll = sum(roll_results) - print( - f"\n{self.name_of_player.capitalize()} throws the dices {roll_results[0]} and {roll_results[1]}. You rolled a total of {sum(roll_results)}\n" - ) - # if self.player_id == 1: - # self.roll_history_p1.append(roll_results) - # elif self.player_id == 2: - # self.roll_history_p2.append(roll_results) - # print(f"Roll results p1: {self.roll_history_p1}\nRoll results p2: {self.roll_history_p2}") - return total_roll - - def move_player(self, board): - """ - This is the logic of the game, it moves the player when dices are throwed, - and updates the player pos to the new pos - """ - new_position = board.update_player_position( - player=self, total_roll=self.dice_roll() - ) - print( - f"{self.name_of_player.capitalize()} moves to {board.locations_with_index[new_position]}\n" - ) - return new_position - - def perform_action(self, board, new_position): - """Made this function to call the board everytime the player got on a tile to call the function""" - board.visit_locations_by_index(new_position) - if new_position in board.locations_actions: - board.locations_actions[new_position]() diff --git a/src/CLI/selling.py b/src/CLI/selling.py deleted file mode 100644 index 93387a1..0000000 --- a/src/CLI/selling.py +++ /dev/null @@ -1,19 +0,0 @@ -class Selling: - def __init__(self, name: str, chest_worth: str) -> None: - self.name = name - self.chest_worth = chest_worth - - def __str__(self): - return f"{self.name}" - - -chest_wealth = Selling(name="Chest of Wealth", chest_worth="9500") -chest_legend = Selling(name="Legendary Chest", chest_worth="8600") -chest_captain = Selling(name="Captain's Chest", chest_worth="560") -chest_cursed = Selling(name="Chest of the Cursed One", chest_worth="1160") -chest_greg = Selling(name="Chest of the drunken Greg", chest_worth="2500") -chest_mermaid = Selling(name="Mermaid's Chest", chest_worth="910") -chest_volcanic = Selling(name="Volcanic Chest", chest_worth="520") -chest_strong = Selling(name="Stronghold Chest", chest_worth="2000") -chest_rage = Selling(name="Chest of Doom", chest_worth="3500") -chest_ancient = Selling(name="Chest of the Ancients", chest_worth="3000") diff --git a/src/game_manager.py b/src/game_manager.py index 2c82a9f..a02072f 100644 --- a/src/game_manager.py +++ b/src/game_manager.py @@ -3,7 +3,6 @@ structure of the game, using a stack of states """ - import sys import pygame @@ -24,8 +23,8 @@ class GameStateManager: - Handling Pygame events and delegating them to the active state. - Running the main game loop with controlled frame rate. """ - def __init__(self) -> None: + def __init__(self) -> None: # init pygame pygame.init() self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) @@ -44,9 +43,9 @@ def __str__(self) -> str: return a string representing the stack e.g. : >MainMenu>GameRunning>Paused """ - stack_repr:str = "" + stack_repr: str = "" for state in self.states_stack: - stack_repr += '>' + str(state) + stack_repr += ">" + str(state) return stack_repr def enter_state(self, state: BaseState) -> None: diff --git a/src/inventory_gui.py b/src/inventory_gui.py index 81f63c2..abb1776 100644 --- a/src/inventory_gui.py +++ b/src/inventory_gui.py @@ -18,7 +18,7 @@ def __init__(self, screen: pygame.Surface, inventory: Inventory) -> None: self.item_height = 60 # Load sprite sheet and extract the icons (Testing purposes) - # To be replaced when: + # To be replaced when: # 1) Spritesheet has been decide. 2) A 'Buy', 'Found' or 'Add' in-game feature has been implemented self.sprite_sheet = pygame.image.load( "images/tilesets/Treasure+.png" @@ -92,7 +92,9 @@ def extract_icon(self, x, y, size=16): """Extract a single icon from the sprite sheet.""" return self.sprite_sheet.subsurface((x, y, size, size)) - def draw_buttons(self, x: int, y: int, item: str) -> Tuple[pygame.Rect, pygame.Rect]: + def draw_buttons( + self, x: int, y: int, item: str + ) -> Tuple[pygame.Rect, pygame.Rect]: """Draw Use and Discard buttons for a specific item.""" use_button = pygame.Rect(x, y, self.button_width, self.button_height) discard_button = pygame.Rect( @@ -181,7 +183,9 @@ def handle_mouse_click(self, mouse_pos) -> None: """Handle mouse clicks on buttons.""" for item, (use_button, discard_button) in self.button_actions.items(): if use_button.collidepoint(mouse_pos): - self.message = self.inventory.use_item(item) # `self.message` stores strings + self.message = self.inventory.use_item( + item + ) # `self.message` stores strings self.message_end_time = pygame.time.get_ticks() + 3000 # 3 seconds elif discard_button.collidepoint(mouse_pos): self.message = self.inventory.remove_item(item, 1) diff --git a/src/sprites.py b/src/sprites.py index 9008089..9ad2a02 100644 --- a/src/sprites.py +++ b/src/sprites.py @@ -7,7 +7,7 @@ # class Entity(pygame.sprite.Sprite): -'''Will be later used on all entities, classes as Player will inherit from this class''' +"""Will be later used on all entities, classes as Player will inherit from this class""" # def __init__(self, pos, surf, groups): # super().__init__(groups) @@ -16,7 +16,8 @@ class AllSprites(pygame.sprite.Group): - '''A sprite group that handles every sprite and handles the camera logic''' + """A sprite group that handles every sprite and handles the camera logic""" + def __init__(self): super().__init__() @@ -32,7 +33,9 @@ def draw(self, player_center, player_preview, player_preview_rect): for sprite in self: self.display_surface.blit(sprite.image, sprite.rect.topleft + self.offset) - self.display_surface.blit(player_preview, player_preview_rect.topleft + self.offset) + self.display_surface.blit( + player_preview, player_preview_rect.topleft + self.offset + ) class Player(pygame.sprite.Sprite): diff --git a/src/states/base_state.py b/src/states/base_state.py index f3db083..94c892e 100644 --- a/src/states/base_state.py +++ b/src/states/base_state.py @@ -4,6 +4,7 @@ - `update`: A method that loops through and handles events. - `render`: A method responsible for drawing the state on the given surface. """ + from abc import ABC, abstractmethod import pygame @@ -12,6 +13,7 @@ class BaseState(ABC): """ using an abstract class to ensure each state has the right methods """ + def __init__(self, game_state_manager) -> None: self.game_state_manager = game_state_manager @@ -19,7 +21,7 @@ def __str__(self): return self.__class__.__name__ @abstractmethod - def update(self, events): # return self + def update(self, events): # return self """ update current state handle events diff --git a/src/states/game_running.py b/src/states/game_running.py index 33cf9a4..911e1c6 100644 --- a/src/states/game_running.py +++ b/src/states/game_running.py @@ -1,6 +1,7 @@ """ Represents the GameRunning state, where the player controls a ship and interacts with the game world. """ + import os import json import pygame @@ -24,10 +25,10 @@ class GameRunning(BaseState): - Updates game entities. - Renders the game world on the screen. """ + def __init__(self, game_state_manager) -> None: super().__init__(game_state_manager) - # Initialize player inventory self.player_inventory = Inventory() self.load_inventory_from_json("data/inventory.json") @@ -46,7 +47,7 @@ def setup(self, player_start_pos): } # Islands - islands = self.tmx_map['map'].get_layer_by_name("Islands") + islands = self.tmx_map["map"].get_layer_by_name("Islands") for x, y, surface in islands.tiles(): src.sprites.Tile( self.all_sprites, @@ -55,7 +56,7 @@ def setup(self, player_start_pos): ) # Objects - for obj in self.tmx_map['map'].get_layer_by_name("Ships"): + for obj in self.tmx_map["map"].get_layer_by_name("Ships"): if obj.name == "Player" and obj.properties["pos"] == player_start_pos: self.player = src.sprites.Player((obj.x, obj.y), self.all_sprites) @@ -91,7 +92,7 @@ def render(self, screen) -> None: self.all_sprites.draw( self.player.rect.center, self.player.player_preview, - self.player.player_preview_rect + self.player.player_preview_rect, ) pygame.display.update() diff --git a/src/states/paused.py b/src/states/paused.py index 8565ca1..5711b96 100644 --- a/src/states/paused.py +++ b/src/states/paused.py @@ -2,6 +2,7 @@ paused state holding the inventory """ + from typing import Dict, Tuple import pygame @@ -16,6 +17,7 @@ class Paused(BaseState): paused state holding the inventory """ + def __init__(self, game_state_manager, inventory: Inventory) -> None: super().__init__(game_state_manager) @@ -97,7 +99,9 @@ def handle_mouse_click(self, mouse_pos) -> None: """Handle mouse clicks on buttons.""" for item, (use_button, discard_button) in self.button_actions.items(): if use_button.collidepoint(mouse_pos): - self.message = self.inventory.use_item(item) # `self.message` stores strings + self.message = self.inventory.use_item( + item + ) # `self.message` stores strings self.message_end_time = pygame.time.get_ticks() + 3000 # 3 seconds elif discard_button.collidepoint(mouse_pos): self.message = self.inventory.remove_item(item, 1) @@ -107,7 +111,9 @@ def extract_icon(self, x, y, size=16): """Extract a single icon from the sprite sheet.""" return self.sprite_sheet.subsurface((x, y, size, size)) - def draw_buttons(self, x: int, y: int, item: str) -> Tuple[pygame.Rect, pygame.Rect]: + def draw_buttons( + self, x: int, y: int, item: str + ) -> Tuple[pygame.Rect, pygame.Rect]: """Draw Use and Discard buttons for a specific item.""" use_button = pygame.Rect(x, y, self.button_width, self.button_height) discard_button = pygame.Rect( diff --git a/tests/test_inventory.py b/tests/test_inventory.py index 8e5f3fd..01649f7 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -8,7 +8,6 @@ from src.GUI.inventory import Inventory, Chest, Quest - class TestInventory(unittest.TestCase): def setUp(self): """Set up a new Inventory object before each test.""" diff --git a/tests/test_py_version.py b/tests/test_py_version.py deleted file mode 100644 index 498e093..0000000 --- a/tests/test_py_version.py +++ /dev/null @@ -1,44 +0,0 @@ -import sys -import os -from unittest.mock import patch -import pytest - - -def setup_path(): - # Ensure the src directory is given a higher priority - current_dir = os.path.abspath(os.path.dirname(__file__)) - src_dir = os.path.abspath(os.path.join(current_dir, "..", "src")) - sys.path.append(src_dir) - - -setup_path() - - -@patch("random.randint") -def test_dice_roll(mock_randint): - from CLI.player import Player # Import after updating sys.path - - """ - Test that the dice_roll method of the Player class only uses the numbers 3 and 4 to achieve a total roll of 7. - Mocks random.randint to return the sequence [3, 4] repeatedly and asserts the total roll is 7. - """ - print("Running test_dice_roll...") # Debug statement - - # Define the sequence of values to mock - mock_randint.side_effect = [3, 4, 3, 4] # Repeat the sequence if needed - - instance = Player(name_of_player="TestPlayer", player_id=1) - - roll_results = [] - total_roll = 0 - - while total_roll != 7: - total_roll = instance.dice_roll() - roll_results.append(total_roll) - print(f"Generated roll: {total_roll}") - - assert total_roll == 7 - - -if __name__ == "__main__": - pytest.main()