From fe769c4488a360d6562ec3bcdf9399fc99aac723 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 18 Dec 2020 17:30:03 +0100 Subject: [PATCH 01/19] We can equip items --- squirrelbattle/display/statsdisplay.py | 17 +++++++++++++---- squirrelbattle/entities/items.py | 20 +++++++++++++++----- squirrelbattle/entities/player.py | 14 ++++++++++++-- squirrelbattle/game.py | 1 + squirrelbattle/interfaces.py | 10 ++++++---- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/squirrelbattle/display/statsdisplay.py b/squirrelbattle/display/statsdisplay.py index ef358bb..00f6675 100644 --- a/squirrelbattle/display/statsdisplay.py +++ b/squirrelbattle/display/statsdisplay.py @@ -20,7 +20,7 @@ class StatsDisplay(Display): self.player = game.player def update_pad(self) -> None: - string2 = "Player -- LVL {}\nEXP {}/{}\nHP {}/{}"\ + string2 = _("player").capitalize() + " -- LVL {}\nEXP {}/{}\nHP {}/{}"\ .format(self.player.level, self.player.current_xp, self.player.max_xp, self.player.health, self.player.maxhealth) @@ -46,11 +46,20 @@ class StatsDisplay(Display): printed_items.append(item) self.addstr(self.pad, 8, 0, inventory_str) - self.addstr(self.pad, 9, 0, f"{self.pack.HAZELNUT} " - f"x{self.player.hazel}") + if self.player.equipped_item: + self.addstr(self.pad, 9, 0, + _("Equipped item:") + " " + f"{self.pack[self.player.equipped_item.name.upper()]}") + if self.player.equipped_armor: + self.addstr(self.pad, 10, 0, + _("Equipped armor:") + " " + f"{self.pack[self.player.equipped_armor.name.upper()]}") + + self.addstr(self.pad, 11, 0, f"{self.pack.HAZELNUT} " + f"x{self.player.hazel}") if self.player.dead: - self.addstr(self.pad, 11, 0, _("YOU ARE DEAD"), curses.COLOR_RED, + self.addstr(self.pad, 13, 0, _("YOU ARE DEAD"), curses.COLOR_RED, bold=True, blink=True, standout=True) def display(self) -> None: diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 865a703..9719e3a 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -4,7 +4,6 @@ from random import choice, randint from typing import Optional -from .player import Player from ..interfaces import Entity, FightingEntity, Map, InventoryHolder from ..translations import gettext as _ @@ -45,15 +44,26 @@ class Item(Entity): """ Indicates what should be done when the item is equipped. """ + if self.held_by.equipped_item: + self.held_by.equipped_item.unequip() + self.held_by.equipped_item = self + self.held_by.remove_from_inventory(self) - def hold(self, player: InventoryHolder) -> None: + def unequip(self) -> None: + """ + Indicates what should be done when the item is unequipped. + """ + self.held_by.add_to_inventory(self) + self.held_by.equipped_item = None + + def hold(self, holder: InventoryHolder) -> None: """ The item is taken from the floor and put into the inventory """ self.held = True - self.held_by = player + self.held_by = holder self.held_by.map.remove_entity(self) - player.add_to_inventory(self) + holder.add_to_inventory(self) def save_state(self) -> dict: """ @@ -116,7 +126,7 @@ class Bomb(Item): """ damage: int = 5 exploding: bool - owner: Optional["Player"] + owner: Optional["InventoryHolder"] tick: int def __init__(self, name: str = "bomb", damage: int = 5, diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 19c8348..d7c9e28 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -4,8 +4,9 @@ from functools import reduce from queue import PriorityQueue from random import randint -from typing import Dict, Tuple +from typing import Dict, Optional, Tuple +from .items import Item from ..interfaces import FightingEntity, InventoryHolder @@ -16,12 +17,15 @@ class Player(InventoryHolder, FightingEntity): current_xp: int = 0 max_xp: int = 10 paths: Dict[Tuple[int, int], Tuple[int, int]] + equipped_item: Optional[Item] + equipped_armor: Optional[Item] def __init__(self, name: str = "player", maxhealth: int = 20, strength: int = 5, intelligence: int = 1, charisma: int = 1, dexterity: int = 1, constitution: int = 1, level: int = 1, current_xp: int = 0, max_xp: int = 10, inventory: list = None, - hazel: int = 42, *args, **kwargs) \ + hazel: int = 42, equipped_item: Optional[Item] = None, + equipped_armor: Optional[Item] = None, *args, **kwargs) \ -> None: super().__init__(name=name, maxhealth=maxhealth, strength=strength, intelligence=intelligence, charisma=charisma, @@ -32,6 +36,12 @@ class Player(InventoryHolder, FightingEntity): self.inventory = self.translate_inventory(inventory or []) self.paths = dict() self.hazel = hazel + if isinstance(equipped_item, dict): + equipped_item = self.dict_to_item(equipped_item) + if isinstance(equipped_armor, dict): + equipped_armor = self.dict_to_item(equipped_armor) + self.equipped_item = equipped_item + self.equipped_armor = equipped_armor def move(self, y: int, x: int) -> None: """ diff --git a/squirrelbattle/game.py b/squirrelbattle/game.py index 0553d2e..e0f3df9 100644 --- a/squirrelbattle/game.py +++ b/squirrelbattle/game.py @@ -126,6 +126,7 @@ class Game: self.map.tick() elif key == KeyValues.INVENTORY: self.state = GameMode.INVENTORY + self.display_actions(DisplayActions.UPDATE) elif key == KeyValues.SPACE: self.state = GameMode.MAINMENU elif key == KeyValues.CHAT: diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index 94025bd..c5d9e0e 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -496,10 +496,10 @@ class InventoryHolder(Entity): """ for i in range(len(inventory)): if isinstance(inventory[i], dict): - inventory[i] = self.dict_to_inventory(inventory[i]) + inventory[i] = self.dict_to_item(inventory[i]) return inventory - def dict_to_inventory(self, item_dict: dict) -> Entity: + def dict_to_item(self, item_dict: dict) -> Entity: """ Translate a dict object that contains the state of an item into an item object. @@ -522,13 +522,15 @@ class InventoryHolder(Entity): """ Adds an object to inventory """ - self.inventory.append(obj) + if obj not in self.inventory: + self.inventory.append(obj) def remove_from_inventory(self, obj: Any) -> None: """ Removes an object from the inventory """ - self.inventory.remove(obj) + if obj in self.inventory: + self.inventory.remove(obj) def change_hazel_balance(self, hz: int) -> None: """ From 1b4612afd05991a62f0ea75308e986f500ae996e Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 18 Dec 2020 17:39:11 +0100 Subject: [PATCH 02/19] Swords add strength --- squirrelbattle/entities/items.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 9719e3a..5564cb0 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -225,9 +225,28 @@ class Sword(Weapon): """ A basic weapon """ - def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs): + strength: int + + def __init__(self, name: str = "sword", price: int = 20, strength: int = 3, + *args, **kwargs): super().__init__(name=name, price=price, *args, **kwargs) self.name = name + self.strength = strength + + def equip(self) -> None: + """ + When a sword is equipped, the player gains strength. + """ + super().equip() + self.held_by.strength += self.strength + + def unequip(self) -> None: + """ + Remove the strength earned by the sword. + :return: + """ + super().unequip() + self.held_by.strength -= self.strength class BodySnatchPotion(Item): From 947572522842624d9ad3882d5c8d115a1037f7a3 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 18 Dec 2020 17:50:26 +0100 Subject: [PATCH 03/19] Save equipped item and armor --- squirrelbattle/entities/player.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index d7c9e28..a370264 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -154,4 +154,8 @@ class Player(InventoryHolder, FightingEntity): d = super().save_state() d["current_xp"] = self.current_xp d["max_xp"] = self.max_xp + d["equipped_item"] = self.equipped_item.save_state()\ + if self.equipped_item else None + d["equipped_armor"] = self.equipped_armor.save_state()\ + if self.equipped_armor else None return d From 9aa684fb7741e3fc3c188d9ff42bb4db853e07c8 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 18 Dec 2020 17:57:42 +0100 Subject: [PATCH 04/19] Use directly equipped items outside the inventory --- squirrelbattle/entities/items.py | 4 ++-- squirrelbattle/entities/player.py | 11 +++++++++++ squirrelbattle/game.py | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 5564cb0..4da4a8c 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -29,7 +29,7 @@ class Item(Entity): The item is dropped from the inventory onto the floor """ if self.held: - self.held_by.inventory.remove(self) + self.held_by.remove_from_inventory(self) self.held_by.map.add_entity(self) self.move(self.held_by.y, self.held_by.x) self.held = False @@ -46,8 +46,8 @@ class Item(Entity): """ if self.held_by.equipped_item: self.held_by.equipped_item.unequip() - self.held_by.equipped_item = self self.held_by.remove_from_inventory(self) + self.held_by.equipped_item = self def unequip(self) -> None: """ diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index a370264..89f16c7 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -75,6 +75,17 @@ class Player(InventoryHolder, FightingEntity): self.current_xp += xp self.level_up() + def remove_from_inventory(self, obj: Item) -> None: + """ + Remove the given item from the inventory, even if the item is equipped. + """ + if obj == self.equipped_item: + self.equipped_item = None + elif obj == self.equipped_armor: + self.equipped_armor = None + else: + return super().remove_from_inventory(obj) + # noinspection PyTypeChecker,PyUnresolvedReferences def check_move(self, y: int, x: int, move_if_possible: bool = False) \ -> bool: diff --git a/squirrelbattle/game.py b/squirrelbattle/game.py index e0f3df9..d0aaf84 100644 --- a/squirrelbattle/game.py +++ b/squirrelbattle/game.py @@ -127,6 +127,8 @@ class Game: elif key == KeyValues.INVENTORY: self.state = GameMode.INVENTORY self.display_actions(DisplayActions.UPDATE) + elif key == KeyValues.USE and self.player.equipped_item: + self.player.equipped_item.use() elif key == KeyValues.SPACE: self.state = GameMode.MAINMENU elif key == KeyValues.CHAT: From c01307202a8125a222b2600b4cbcaa746591164d Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 18 Dec 2020 20:01:52 +0100 Subject: [PATCH 05/19] Add shields to be more protected, see #48 --- squirrelbattle/display/texturepack.py | 2 ++ squirrelbattle/entities/items.py | 50 ++++++++++++++++++++------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/squirrelbattle/display/texturepack.py b/squirrelbattle/display/texturepack.py index 1f6dc76..2295667 100644 --- a/squirrelbattle/display/texturepack.py +++ b/squirrelbattle/display/texturepack.py @@ -70,6 +70,7 @@ TexturePack.ASCII_PACK = TexturePack( MERCHANT='M', PLAYER='@', RABBIT='Y', + SHIELD='D', SUNFLOWER='I', SWORD='\u2020', TEDDY_BEAR='8', @@ -96,6 +97,7 @@ TexturePack.SQUIRREL_PACK = TexturePack( PLAYER='🐿️ ️', MERCHANT='🦜', RABBIT='🐇', + SHIELD='🛡️ ', SUNFLOWER='🌻', SWORD='🗡️ ', TEDDY_BEAR='🧸', diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 4da4a8c..b3f8a84 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -40,14 +40,20 @@ class Item(Entity): Indicates what should be done when the item is used. """ - def equip(self) -> None: + def equip(self, armor: bool = False) -> None: """ Indicates what should be done when the item is equipped. """ - if self.held_by.equipped_item: - self.held_by.equipped_item.unequip() - self.held_by.remove_from_inventory(self) - self.held_by.equipped_item = self + if armor: + if self.held_by.equipped_armor: + self.held_by.equipped_armor.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_armor = self + else: + if self.held_by.equipped_item: + self.held_by.equipped_item.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_item = self def unequip(self) -> None: """ @@ -75,7 +81,7 @@ class Item(Entity): @staticmethod def get_all_items() -> list: - return [BodySnatchPotion, Bomb, Heart, Sword] + return [BodySnatchPotion, Bomb, Heart, Shield, Sword] def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: """ @@ -225,20 +231,17 @@ class Sword(Weapon): """ A basic weapon """ - strength: int - - def __init__(self, name: str = "sword", price: int = 20, strength: int = 3, + def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs): super().__init__(name=name, price=price, *args, **kwargs) self.name = name - self.strength = strength - def equip(self) -> None: + def equip(self, armor: bool = False) -> None: """ When a sword is equipped, the player gains strength. """ super().equip() - self.held_by.strength += self.strength + self.held_by.strength += self.damage def unequip(self) -> None: """ @@ -246,7 +249,28 @@ class Sword(Weapon): :return: """ super().unequip() - self.held_by.strength -= self.strength + self.held_by.strength -= self.damage + + +class Shield(Item): + constitution: int + + def __init__(self, constitution: int = 2, *args, **kwargs): + super().__init__(name="shield", *args, **kwargs) + self.constitution = constitution + + def equip(self, armor: bool = True) -> None: + super().equip(armor) + self.held_by.constitution += self.constitution + + def unequip(self) -> None: + super().unequip() + self.held_by.constitution -= self.constitution + + def save_state(self) -> dict: + d = super().save_state() + d["constitution"] = self.constitution + return d class BodySnatchPotion(Item): From 9b8dfb00da8cfa38f9ad5abca3a95defa4ebc7e2 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Tue, 5 Jan 2021 19:07:15 +0100 Subject: [PATCH 06/19] Added critical hit system: the player and rabbit entities have a chance of making x4 damage! Closes #52 --- squirrelbattle/entities/monsters.py | 4 ++-- squirrelbattle/entities/player.py | 6 +++--- squirrelbattle/interfaces.py | 14 +++++++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/squirrelbattle/entities/monsters.py b/squirrelbattle/entities/monsters.py index 34cd4bf..e50fad0 100644 --- a/squirrelbattle/entities/monsters.py +++ b/squirrelbattle/entities/monsters.py @@ -87,9 +87,9 @@ class Rabbit(Monster): A rabbit monster """ def __init__(self, name: str = "rabbit", strength: int = 1, - maxhealth: int = 15, *args, **kwargs) -> None: + maxhealth: int = 15, critical: int = 30, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, - maxhealth=maxhealth, *args, **kwargs) + maxhealth=maxhealth, critical=critical, *args, **kwargs) class TeddyBear(Monster): diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 89f16c7..2a023d8 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -25,12 +25,12 @@ class Player(InventoryHolder, FightingEntity): dexterity: int = 1, constitution: int = 1, level: int = 1, current_xp: int = 0, max_xp: int = 10, inventory: list = None, hazel: int = 42, equipped_item: Optional[Item] = None, - equipped_armor: Optional[Item] = None, *args, **kwargs) \ - -> None: + equipped_armor: Optional[Item] = None, critical: int = 5,\ + *args, **kwargs) -> None: super().__init__(name=name, maxhealth=maxhealth, strength=strength, intelligence=intelligence, charisma=charisma, dexterity=dexterity, constitution=constitution, - level=level, *args, **kwargs) + level=level, critical=critical, *args, **kwargs) self.current_xp = current_xp self.max_xp = max_xp self.inventory = self.translate_inventory(inventory or []) diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index c5d9e0e..599f546 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -403,11 +403,12 @@ class FightingEntity(Entity): dexterity: int constitution: int level: int + critical: int def __init__(self, maxhealth: int = 0, health: Optional[int] = None, strength: int = 0, intelligence: int = 0, charisma: int = 0, dexterity: int = 0, constitution: int = 0, level: int = 0, - *args, **kwargs) -> None: + critical: int = 0, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.maxhealth = maxhealth self.health = maxhealth if health is None else health @@ -417,6 +418,7 @@ class FightingEntity(Entity): self.dexterity = dexterity self.constitution = constitution self.level = level + self.critical = critical @property def dead(self) -> bool: @@ -426,10 +428,16 @@ class FightingEntity(Entity): """ Deals damage to the opponent, based on the stats """ + diceroll = randint(0, 100) + damage = self.strength + string = " " + if diceroll <= self.critical: # It is a critical hit + damage *= 4 + string = _(" It's a critical hit! ") return _("{name} hits {opponent}.")\ .format(name=_(self.translated_name.capitalize()), - opponent=_(opponent.translated_name)) + " " + \ - opponent.take_damage(self, self.strength) + opponent=_(opponent.translated_name)) + string + \ + opponent.take_damage(self, damage) def take_damage(self, attacker: "Entity", amount: int) -> str: """ From 4bddf076ea5de4efdd80cf26184cd444059a1be0 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Tue, 5 Jan 2021 19:18:25 +0100 Subject: [PATCH 07/19] Fighting now takes into account the constitution. Closes #51 --- squirrelbattle/entities/items.py | 30 +++++++++++++++--------------- squirrelbattle/interfaces.py | 7 ++++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index b3f8a84..6c54fef 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -226,6 +226,21 @@ class Weapon(Item): d["damage"] = self.damage return d + def equip(self, armor: bool = False) -> None: + """ + When a weapon is equipped, the player gains strength. + """ + super().equip() + self.held_by.strength += self.damage + + def unequip(self) -> None: + """ + Remove the strength earned by the weapon. + :return: + """ + super().unequip() + self.held_by.strength -= self.damage + class Sword(Weapon): """ @@ -236,21 +251,6 @@ class Sword(Weapon): super().__init__(name=name, price=price, *args, **kwargs) self.name = name - def equip(self, armor: bool = False) -> None: - """ - When a sword is equipped, the player gains strength. - """ - super().equip() - self.held_by.strength += self.damage - - def unequip(self) -> None: - """ - Remove the strength earned by the sword. - :return: - """ - super().unequip() - self.held_by.strength -= self.damage - class Shield(Item): constitution: int diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index 599f546..dceea6a 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -443,11 +443,12 @@ class FightingEntity(Entity): """ Take damage from the attacker, based on the stats """ - self.health -= amount + damage = max(0, amount - self.constitution) + self.health -= damage if self.health <= 0: self.die() - return _("{name} takes {amount} damage.")\ - .format(name=self.translated_name.capitalize(), amount=str(amount))\ + return _("{name} takes {damage} damage.")\ + .format(name=self.translated_name.capitalize(), damage=str(damage))\ + (" " + _("{name} dies.") .format(name=self.translated_name.capitalize()) if self.health <= 0 else "") From 3ace133037f62e511d7cd021e530fc5259aaf751 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Tue, 5 Jan 2021 19:23:25 +0100 Subject: [PATCH 08/19] Critical hit chance is now displayed along with the other stats. --- squirrelbattle/display/statsdisplay.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/squirrelbattle/display/statsdisplay.py b/squirrelbattle/display/statsdisplay.py index 00f6675..b3ae831 100644 --- a/squirrelbattle/display/statsdisplay.py +++ b/squirrelbattle/display/statsdisplay.py @@ -25,10 +25,11 @@ class StatsDisplay(Display): self.player.max_xp, self.player.health, self.player.maxhealth) self.addstr(self.pad, 0, 0, string2) - string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}"\ + string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}\nCRI {}%"\ .format(self.player.strength, self.player.intelligence, self.player.charisma, - self.player.dexterity, self.player.constitution) + self.player.dexterity, self.player.constitution,\ + self.player.critical) self.addstr(self.pad, 3, 0, string3) inventory_str = _("Inventory:") + " " @@ -44,22 +45,22 @@ class StatsDisplay(Display): if count > 1: inventory_str += f"x{count} " printed_items.append(item) - self.addstr(self.pad, 8, 0, inventory_str) + self.addstr(self.pad, 9, 0, inventory_str) if self.player.equipped_item: - self.addstr(self.pad, 9, 0, + self.addstr(self.pad, 10, 0, _("Equipped item:") + " " f"{self.pack[self.player.equipped_item.name.upper()]}") if self.player.equipped_armor: - self.addstr(self.pad, 10, 0, + self.addstr(self.pad, 11, 0, _("Equipped armor:") + " " f"{self.pack[self.player.equipped_armor.name.upper()]}") - self.addstr(self.pad, 11, 0, f"{self.pack.HAZELNUT} " + self.addstr(self.pad, 12, 0, f"{self.pack.HAZELNUT} " f"x{self.player.hazel}") if self.player.dead: - self.addstr(self.pad, 13, 0, _("YOU ARE DEAD"), curses.COLOR_RED, + self.addstr(self.pad, 14, 0, _("YOU ARE DEAD"), curses.COLOR_RED, bold=True, blink=True, standout=True) def display(self) -> None: From 424044a5e4f1998d2c2949f895bf631d8a370d67 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Tue, 5 Jan 2021 19:40:11 +0100 Subject: [PATCH 09/19] Added an overpowered eagle boss. To avoid seing it too often, entities now have a certain chance of being spawned. Closes #19. --- squirrelbattle/display/texturepack.py | 3 +++ squirrelbattle/entities/monsters.py | 9 +++++++++ squirrelbattle/interfaces.py | 21 ++++++++++++++++----- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/squirrelbattle/display/texturepack.py b/squirrelbattle/display/texturepack.py index 2295667..ed89be6 100644 --- a/squirrelbattle/display/texturepack.py +++ b/squirrelbattle/display/texturepack.py @@ -30,6 +30,7 @@ class TexturePack: TEDDY_BEAR: str TIGER: str WALL: str + EAGLE: str ASCII_PACK: "TexturePack" SQUIRREL_PACK: "TexturePack" @@ -76,6 +77,7 @@ TexturePack.ASCII_PACK = TexturePack( TEDDY_BEAR='8', TIGER='n', WALL='#', + EAGLE='µ', ) TexturePack.SQUIRREL_PACK = TexturePack( @@ -103,4 +105,5 @@ TexturePack.SQUIRREL_PACK = TexturePack( TEDDY_BEAR='🧸', TIGER='🐅', WALL='🧱', + EAGLE='🦅', ) diff --git a/squirrelbattle/entities/monsters.py b/squirrelbattle/entities/monsters.py index e50fad0..bcdff11 100644 --- a/squirrelbattle/entities/monsters.py +++ b/squirrelbattle/entities/monsters.py @@ -100,3 +100,12 @@ class TeddyBear(Monster): maxhealth: int = 50, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, maxhealth=maxhealth, *args, **kwargs) + +class GiantSeaEagle(Monster): + """ + An eagle boss + """ + def __init__(self, name: str = "eagle", strength: int = 1000, + maxhealth: int = 5000, *args, **kwargs) -> None: + super().__init__(name=name, strength=strength, + maxhealth=maxhealth, *args, **kwargs) diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index dceea6a..25a8baa 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -3,7 +3,7 @@ from enum import Enum, auto from math import sqrt -from random import choice, randint +from random import choice, randint, choices from typing import List, Optional, Any from .display.texturepack import TexturePack @@ -146,7 +146,8 @@ class Map: tile = self.tiles[y][x] if tile.can_walk(): break - entity = choice(Entity.get_all_entity_classes())() + entity = choices(Entity.get_all_entity_classes(),\ + weights = Entity.get_weights(), k=1)[0]() entity.move(y, x) self.add_entity(entity) @@ -349,10 +350,19 @@ class Entity: """ from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart from squirrelbattle.entities.monsters import Tiger, Hedgehog, \ - Rabbit, TeddyBear + Rabbit, TeddyBear, GiantSeaEagle from squirrelbattle.entities.friendly import Merchant, Sunflower return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear, - Sunflower, Tiger, Merchant] + Sunflower, Tiger, Merchant, GiantSeaEagle] + + @staticmethod + def get_weights() -> list: + """ + Returns a weigth list associated to the above function, to + be used to spawn random entities with a certain probability. + """ + return [3, 5, 6, 5, 5, 5, + 5, 4, 4, 1] @staticmethod def get_all_entity_classes_in_a_dict() -> dict: @@ -361,7 +371,7 @@ class Entity: """ from squirrelbattle.entities.player import Player from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \ - TeddyBear + TeddyBear, GiantSeaEagle from squirrelbattle.entities.friendly import Merchant, Sunflower from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \ Heart, Sword @@ -377,6 +387,7 @@ class Entity: "Merchant": Merchant, "Sunflower": Sunflower, "Sword": Sword, + "Eagle": GiantSeaEagle, } def save_state(self) -> dict: From 601062237db8ffa1de7bb026d874eba68a2834be Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Tue, 5 Jan 2021 19:50:25 +0100 Subject: [PATCH 10/19] Repairing part of the tests. --- squirrelbattle/tests/entities_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/squirrelbattle/tests/entities_test.py b/squirrelbattle/tests/entities_test.py index 70e3748..1d7a7a9 100644 --- a/squirrelbattle/tests/entities_test.py +++ b/squirrelbattle/tests/entities_test.py @@ -18,6 +18,7 @@ class TestEntities(unittest.TestCase): """ self.map = Map.load(ResourceManager.get_asset_path("example_map.txt")) self.player = Player() + self.player.constitution = 0 self.map.add_entity(self.player) self.player.move(self.map.start_y, self.map.start_x) @@ -54,6 +55,7 @@ class TestEntities(unittest.TestCase): self.assertTrue(entity.dead) entity = Rabbit() + entity.critical = 0 self.map.add_entity(entity) entity.move(15, 44) # Move randomly From f3fe04e13a217c1251310438f726e7bb06aff158 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Wed, 6 Jan 2021 10:46:36 +0100 Subject: [PATCH 11/19] The player now has two hands and a slot for a helmet and a chestplate. Accordingly, new classes of items have been added. --- squirrelbattle/display/statsdisplay.py | 22 ++++--- squirrelbattle/display/texturepack.py | 7 +++ squirrelbattle/entities/items.py | 84 +++++++++++++++++++++----- squirrelbattle/entities/player.py | 36 ++++++++--- 4 files changed, 118 insertions(+), 31 deletions(-) diff --git a/squirrelbattle/display/statsdisplay.py b/squirrelbattle/display/statsdisplay.py index b3ae831..e24c969 100644 --- a/squirrelbattle/display/statsdisplay.py +++ b/squirrelbattle/display/statsdisplay.py @@ -47,20 +47,28 @@ class StatsDisplay(Display): printed_items.append(item) self.addstr(self.pad, 9, 0, inventory_str) - if self.player.equipped_item: + if self.player.equipped_main: self.addstr(self.pad, 10, 0, - _("Equipped item:") + " " - f"{self.pack[self.player.equipped_item.name.upper()]}") - if self.player.equipped_armor: + _("Equipped main:") + " " + f"{self.pack[self.player.equipped_main.name.upper()]}") + if self.player.equipped_secondary: self.addstr(self.pad, 11, 0, - _("Equipped armor:") + " " + _("Equipped secondary:") + " " + f"{self.pack[self.player.equipped_secondary.name.upper()]}") + if self.player.equipped_armor: + self.addstr(self.pad, 12, 0, + _("Equipped chestplate:") + " " f"{self.pack[self.player.equipped_armor.name.upper()]}") + if self.player.equipped_helmet: + self.addstr(self.pad, 13, 0, + _("Equipped helmet:") + " " + f"{self.pack[self.player.equipped_helmet.name.upper()]}") - self.addstr(self.pad, 12, 0, f"{self.pack.HAZELNUT} " + self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} " f"x{self.player.hazel}") if self.player.dead: - self.addstr(self.pad, 14, 0, _("YOU ARE DEAD"), curses.COLOR_RED, + self.addstr(self.pad, 15, 0, _("YOU ARE DEAD"), curses.COLOR_RED, bold=True, blink=True, standout=True) def display(self) -> None: diff --git a/squirrelbattle/display/texturepack.py b/squirrelbattle/display/texturepack.py index ed89be6..8d4e785 100644 --- a/squirrelbattle/display/texturepack.py +++ b/squirrelbattle/display/texturepack.py @@ -31,6 +31,9 @@ class TexturePack: TIGER: str WALL: str EAGLE: str + SHIELD: str + CHESTPLATE: str + HELMET: str ASCII_PACK: "TexturePack" SQUIRREL_PACK: "TexturePack" @@ -78,6 +81,8 @@ TexturePack.ASCII_PACK = TexturePack( TIGER='n', WALL='#', EAGLE='µ', + CHESTPLATE='(', + HELMET='0', ) TexturePack.SQUIRREL_PACK = TexturePack( @@ -106,4 +111,6 @@ TexturePack.SQUIRREL_PACK = TexturePack( TIGER='🐅', WALL='🧱', EAGLE='🦅', + CHESTPLATE='🦺', + HELMET='⛑️', ) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 6c54fef..8b99a8d 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -40,27 +40,53 @@ class Item(Entity): Indicates what should be done when the item is used. """ - def equip(self, armor: bool = False) -> None: + def equip(self) -> None: """ Indicates what should be done when the item is equipped. """ - if armor: + if isinstance(self, Chestplate): if self.held_by.equipped_armor: self.held_by.equipped_armor.unequip() self.held_by.remove_from_inventory(self) self.held_by.equipped_armor = self - else: - if self.held_by.equipped_item: - self.held_by.equipped_item.unequip() + elif isinstance(self, Helmet): + if self.held_by.equipped_helmet: + self.held_by.equipped_helmet.unequip() self.held_by.remove_from_inventory(self) - self.held_by.equipped_item = self + self.held_by.equipped_helmet = self + elif isinstance(self, Weapon): + if self.held_by.equipped_main: + if self.held_by.equipped_secondary: + self.held_by.equipped_secondary.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_secondary = self + # For weapons, they are equipped as main only if main is empty. + else: + self.held_by.remove_from_inventory(self) + self.held_by.equipped_main = self + else: + # Other objects are only equipped as secondary. + if self.held_by.equipped_secondary: + self.held_by.equipped_secondary.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_secondary = self def unequip(self) -> None: """ Indicates what should be done when the item is unequipped. """ + if isinstance(self, Chestplate): + self.held_by.equipped_armor = None + elif isinstance(self, Helmet): + self.held_by.equipped_helmet = None + elif isinstance(self, Weapon): + if self.held_by.equipped_main == self: + self.held_by.equipped_main = None + else: + self.held_by.equipped_secondary = None + else: + self.held_by.equipped_secondary = None self.held_by.add_to_inventory(self) - self.held_by.equipped_item = None def hold(self, holder: InventoryHolder) -> None: """ @@ -81,7 +107,8 @@ class Item(Entity): @staticmethod def get_all_items() -> list: - return [BodySnatchPotion, Bomb, Heart, Shield, Sword] + return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\ + Chestplate, Helmet] def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: """ @@ -226,7 +253,7 @@ class Weapon(Item): d["damage"] = self.damage return d - def equip(self, armor: bool = False) -> None: + def equip(self) -> None: """ When a weapon is equipped, the player gains strength. """ @@ -252,15 +279,18 @@ class Sword(Weapon): self.name = name -class Shield(Item): +class Armor(Item): + """ + Class of items that increase the player's constitution. + """ constitution: int - - def __init__(self, constitution: int = 2, *args, **kwargs): - super().__init__(name="shield", *args, **kwargs) + + def __init__(self, constitution: int, *args, **kwargs): + super().__init__(*args, **kwargs) self.constitution = constitution - def equip(self, armor: bool = True) -> None: - super().equip(armor) + def equip(self) -> None: + super().equip() self.held_by.constitution += self.constitution def unequip(self) -> None: @@ -272,6 +302,30 @@ class Shield(Item): d["constitution"] = self.constitution return d +class Shield(Armor): + """ + Class of shield items, they can be equipped in the other hand. + """ + + def __init__(self, constitution: int = 2, *args, **kwargs): + super().__init__(name="shield", constitution=constitution, *args, **kwargs) + +class Helmet(Armor): + """ + Class of helmet items, they can be equipped on the head. + """ + + def __init__(self, constitution: int = 2, *args, **kwargs): + super().__init__(name="helmet", constitution=constitution, *args, **kwargs) + +class Chestplate(Armor): + """ + Class of chestplate items, they can be equipped on the body. + """ + + def __init__(self, constitution: int = 4, *args, **kwargs): + super().__init__(name="chestplate", constitution=constitution, *args, **kwargs) + class BodySnatchPotion(Item): """ diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 2a023d8..a0ddd6c 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -17,15 +17,19 @@ class Player(InventoryHolder, FightingEntity): current_xp: int = 0 max_xp: int = 10 paths: Dict[Tuple[int, int], Tuple[int, int]] - equipped_item: Optional[Item] + equipped_main: Optional[Item] + equipped_secondary: Optional[Item] + equipped_helmet: Optional[Item] equipped_armor: Optional[Item] def __init__(self, name: str = "player", maxhealth: int = 20, strength: int = 5, intelligence: int = 1, charisma: int = 1, dexterity: int = 1, constitution: int = 1, level: int = 1, current_xp: int = 0, max_xp: int = 10, inventory: list = None, - hazel: int = 42, equipped_item: Optional[Item] = None, + hazel: int = 42, equipped_main: Optional[Item] = None, equipped_armor: Optional[Item] = None, critical: int = 5,\ + equipped_secondary: Optional[Item] = None, \ + equipped_helmet: Optional[Item] = None, \ *args, **kwargs) -> None: super().__init__(name=name, maxhealth=maxhealth, strength=strength, intelligence=intelligence, charisma=charisma, @@ -36,12 +40,18 @@ class Player(InventoryHolder, FightingEntity): self.inventory = self.translate_inventory(inventory or []) self.paths = dict() self.hazel = hazel - if isinstance(equipped_item, dict): - equipped_item = self.dict_to_item(equipped_item) + if isinstance(equipped_main, dict): + equipped_main = self.dict_to_item(equipped_main) if isinstance(equipped_armor, dict): equipped_armor = self.dict_to_item(equipped_armor) - self.equipped_item = equipped_item + if isinstance(equipped_secondary, dict): + equipped_secondary = self.dict_to_item(equipped_secondary) + if isinstance(equipped_helmet, dict): + equipped_helmet = self.dict_to_item(equipped_helmet) + self.equipped_main = equipped_main self.equipped_armor = equipped_armor + self.equipped_secondary = equipped_secondary + self.equipped_helmet = equipped_helmet def move(self, y: int, x: int) -> None: """ @@ -79,10 +89,14 @@ class Player(InventoryHolder, FightingEntity): """ Remove the given item from the inventory, even if the item is equipped. """ - if obj == self.equipped_item: - self.equipped_item = None + if obj == self.equipped_main: + self.equipped_main = None elif obj == self.equipped_armor: self.equipped_armor = None + elif obj == self.equipped_secondary: + self.equipped_secondary = None + elif obj == self.equipped_helmet: + self.equipped_helmet = None else: return super().remove_from_inventory(obj) @@ -165,8 +179,12 @@ class Player(InventoryHolder, FightingEntity): d = super().save_state() d["current_xp"] = self.current_xp d["max_xp"] = self.max_xp - d["equipped_item"] = self.equipped_item.save_state()\ - if self.equipped_item else None + d["equipped_main"] = self.equipped_main.save_state()\ + if self.equipped_main else None d["equipped_armor"] = self.equipped_armor.save_state()\ if self.equipped_armor else None + d["equipped_secondary"] = self.equipped_secondary.save_state()\ + if self.equipped_secondary else None + d["equipped_helmet"] = self.equipped_helmet.save_state()\ + if self.equipped_helmet else None return d From a9aeb9ca3a9748234166a45771bb67c16a1da131 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Wed, 6 Jan 2021 11:13:17 +0100 Subject: [PATCH 12/19] Repaired the use functionnality of the main item, as well as the load system for Armor items. --- squirrelbattle/entities/items.py | 16 +++++++++------- squirrelbattle/game.py | 4 ++-- squirrelbattle/interfaces.py | 5 ++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 8b99a8d..05654e9 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -276,7 +276,6 @@ class Sword(Weapon): def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs): super().__init__(name=name, price=price, *args, **kwargs) - self.name = name class Armor(Item): @@ -307,24 +306,27 @@ class Shield(Armor): Class of shield items, they can be equipped in the other hand. """ - def __init__(self, constitution: int = 2, *args, **kwargs): - super().__init__(name="shield", constitution=constitution, *args, **kwargs) + def __init__(self, name: str = "shield", constitution: int = 2,\ + price: int = 6, *args, **kwargs): + super().__init__(name=name, constitution=constitution, *args, **kwargs) class Helmet(Armor): """ Class of helmet items, they can be equipped on the head. """ - def __init__(self, constitution: int = 2, *args, **kwargs): - super().__init__(name="helmet", constitution=constitution, *args, **kwargs) + def __init__(self, name: str = "helmet", constitution: int = 2, \ + price: int = 8, *args, **kwargs): + super().__init__(name=name, constitution=constitution, *args, **kwargs) class Chestplate(Armor): """ Class of chestplate items, they can be equipped on the body. """ - def __init__(self, constitution: int = 4, *args, **kwargs): - super().__init__(name="chestplate", constitution=constitution, *args, **kwargs) + def __init__(self, name: str = "chestplate", constitution: int = 4,\ + price: int = 15, *args, **kwargs): + super().__init__(name=name, constitution=constitution, *args, **kwargs) class BodySnatchPotion(Item): diff --git a/squirrelbattle/game.py b/squirrelbattle/game.py index d0aaf84..939325c 100644 --- a/squirrelbattle/game.py +++ b/squirrelbattle/game.py @@ -127,8 +127,8 @@ class Game: elif key == KeyValues.INVENTORY: self.state = GameMode.INVENTORY self.display_actions(DisplayActions.UPDATE) - elif key == KeyValues.USE and self.player.equipped_item: - self.player.equipped_item.use() + elif key == KeyValues.USE and self.player.equipped_main: + self.player.equipped_main.use() elif key == KeyValues.SPACE: self.state = GameMode.MAINMENU elif key == KeyValues.CHAT: diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index 25a8baa..cc5b36e 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -374,7 +374,7 @@ class Entity: TeddyBear, GiantSeaEagle from squirrelbattle.entities.friendly import Merchant, Sunflower from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \ - Heart, Sword + Heart, Sword, Shield, Chestplate, Helmet return { "Tiger": Tiger, "Bomb": Bomb, @@ -388,6 +388,9 @@ class Entity: "Sunflower": Sunflower, "Sword": Sword, "Eagle": GiantSeaEagle, + "Shield": Shield, + "Chestplate": Chestplate, + "Helmet": Helmet, } def save_state(self) -> dict: From 4ad7d6c37cca74080536c9a1f684d6138ce664b7 Mon Sep 17 00:00:00 2001 From: eichhornchen Date: Wed, 6 Jan 2021 11:44:52 +0100 Subject: [PATCH 13/19] Added rings that can augment the player's statistics. Also added a new statistic : xp_buff, which helps the player level up sooner. --- squirrelbattle/display/texturepack.py | 8 +++- squirrelbattle/entities/items.py | 68 ++++++++++++++++++++++++++- squirrelbattle/entities/player.py | 6 ++- squirrelbattle/interfaces.py | 4 +- 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/squirrelbattle/display/texturepack.py b/squirrelbattle/display/texturepack.py index 8d4e785..bd4b563 100644 --- a/squirrelbattle/display/texturepack.py +++ b/squirrelbattle/display/texturepack.py @@ -34,6 +34,8 @@ class TexturePack: SHIELD: str CHESTPLATE: str HELMET: str + RING_OF_MORE_EXPERIENCE: str + RING_OF_CRITICAL_DAMAGE: str ASCII_PACK: "TexturePack" SQUIRREL_PACK: "TexturePack" @@ -64,7 +66,7 @@ TexturePack.ASCII_PACK = TexturePack( entity_bg_color=curses.COLOR_BLACK, BODY_SNATCH_POTION='S', - BOMB='o', + BOMB='ç', EMPTY=' ', EXPLOSION='%', FLOOR='.', @@ -83,6 +85,8 @@ TexturePack.ASCII_PACK = TexturePack( EAGLE='µ', CHESTPLATE='(', HELMET='0', + RING_OF_MORE_EXPERIENCE='o', + RING_OF_CRITICAL_DAMAGE='o', ) TexturePack.SQUIRREL_PACK = TexturePack( @@ -113,4 +117,6 @@ TexturePack.SQUIRREL_PACK = TexturePack( EAGLE='🦅', CHESTPLATE='🦺', HELMET='⛑️', + RING_OF_MORE_EXPERIENCE='💍', + RING_OF_CRITICAL_DAMAGE='💍', ) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 05654e9..336d3e5 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -108,7 +108,7 @@ class Item(Entity): @staticmethod def get_all_items() -> list: return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\ - Chestplate, Helmet] + Chestplate, Helmet, RingCritical, RingXP] def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: """ @@ -361,3 +361,69 @@ class BodySnatchPotion(Item): self.held_by.recalculate_paths() self.held_by.inventory.remove(self) + +class Ring(Item): + """ + A class of rings that boost the player's statistics. + """ + maxhealth: int + strength: int + intelligence: int + charisma: int + dexterity: int + constitution: int + critical: int + experience: float + + def __init__(self, maxhealth: int = 0, strength: int = 0,\ + intelligence: int = 0, charisma: int = 0,\ + dexterity: int = 0, constitution: int = 0,\ + critical: int = 0, experience: float = 0, *args, **kwargs): + super().__init__(*args, **kwargs) + self.maxhealth = maxhealth + self.strength = strength + self.intelligence = intelligence + self.charisma = charisma + self.dexterity = dexterity + self.constitution = constitution + self.critical = critical + self.experience = experience + + def equip(self) -> None: + super().equip() + self.held_by.maxhealth += self.maxhealth + self.held_by.strength += self.strength + self.held_by.intelligence += self.intelligence + self.held_by.charisma += self.charisma + self.held_by.dexterity += self.dexterity + self.held_by.constitution += self.constitution + self.held_by.critical += self.critical + self.held_by.xp_buff += self.experience + + def unequip(self) -> None: + super().unequip() + self.held_by.maxhealth -= self.maxhealth + self.held_by.strength -= self.strength + self.held_by.intelligence -= self.intelligence + self.held_by.charisma -= self.charisma + self.held_by.dexterity -= self.dexterity + self.held_by.constitution -= self.constitution + self.held_by.critical -= self.critical + self.held_by.xp_buff -= self.experience + + def save_state(self) -> dict: + d = super().save_state() + d["constitution"] = self.constitution + return d + +class RingCritical(Ring): + def __init__(self, name: str = "ring_of_critical_damage", price: int = 15, + critical: int = 20, *args, **kwargs): + super().__init__(name=name, price=price, critical=critical, \ + *args, **kwargs) + +class RingXP(Ring): + def __init__(self, name: str = "ring_of_more_experience", price: int = 25, + experience: float = 2, *args, **kwargs): + super().__init__(name=name, price=price, experience=experience, \ + *args, **kwargs) diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index a0ddd6c..854bd93 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -16,6 +16,7 @@ class Player(InventoryHolder, FightingEntity): """ current_xp: int = 0 max_xp: int = 10 + xp_buff: float = 1 paths: Dict[Tuple[int, int], Tuple[int, int]] equipped_main: Optional[Item] equipped_secondary: Optional[Item] @@ -29,7 +30,7 @@ class Player(InventoryHolder, FightingEntity): hazel: int = 42, equipped_main: Optional[Item] = None, equipped_armor: Optional[Item] = None, critical: int = 5,\ equipped_secondary: Optional[Item] = None, \ - equipped_helmet: Optional[Item] = None, \ + equipped_helmet: Optional[Item] = None, xp_buff: float = 1,\ *args, **kwargs) -> None: super().__init__(name=name, maxhealth=maxhealth, strength=strength, intelligence=intelligence, charisma=charisma, @@ -37,6 +38,7 @@ class Player(InventoryHolder, FightingEntity): level=level, critical=critical, *args, **kwargs) self.current_xp = current_xp self.max_xp = max_xp + self.xp_buff = xp_buff self.inventory = self.translate_inventory(inventory or []) self.paths = dict() self.hazel = hazel @@ -82,7 +84,7 @@ class Player(InventoryHolder, FightingEntity): Add some experience to the player. If the required amount is reached, level up. """ - self.current_xp += xp + self.current_xp += int(xp*self.xp_buff) self.level_up() def remove_from_inventory(self, obj: Item) -> None: diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index cc5b36e..b6a3a51 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -374,7 +374,7 @@ class Entity: TeddyBear, GiantSeaEagle from squirrelbattle.entities.friendly import Merchant, Sunflower from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \ - Heart, Sword, Shield, Chestplate, Helmet + Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP return { "Tiger": Tiger, "Bomb": Bomb, @@ -391,6 +391,8 @@ class Entity: "Shield": Shield, "Chestplate": Chestplate, "Helmet": Helmet, + "RingCritical": RingCritical, + "RingXP": RingXP, } def save_state(self) -> dict: From ae505166b7815ef4acc4fb5d552f7367643492ef Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 6 Jan 2021 17:39:13 +0100 Subject: [PATCH 14/19] Disable critical hits during tests --- squirrelbattle/interfaces.py | 4 ++-- squirrelbattle/tests/entities_test.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index b6a3a51..e4557d1 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -444,10 +444,10 @@ class FightingEntity(Entity): """ Deals damage to the opponent, based on the stats """ - diceroll = randint(0, 100) + diceroll = randint(1, 100) damage = self.strength string = " " - if diceroll <= self.critical: # It is a critical hit + if diceroll <= self.critical: # It is a critical hit damage *= 4 string = _(" It's a critical hit! ") return _("{name} hits {opponent}.")\ diff --git a/squirrelbattle/tests/entities_test.py b/squirrelbattle/tests/entities_test.py index 1d7a7a9..97f0ef8 100644 --- a/squirrelbattle/tests/entities_test.py +++ b/squirrelbattle/tests/entities_test.py @@ -77,6 +77,7 @@ class TestEntities(unittest.TestCase): {self.player.name.capitalize()} takes {entity.strength} damage.") # Fight the rabbit + self.player.critical = 0 old_health = entity.health self.player.move_down() self.assertEqual(entity.health, old_health - self.player.strength) From a8c0c197ed86b2b9947ac0e906f5b153d6126a13 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 6 Jan 2021 18:02:58 +0100 Subject: [PATCH 15/19] Linting --- squirrelbattle/display/statsdisplay.py | 9 +++++---- squirrelbattle/entities/items.py | 26 ++++++++++++++++---------- squirrelbattle/entities/monsters.py | 7 +++++-- squirrelbattle/entities/player.py | 8 ++++---- squirrelbattle/interfaces.py | 4 ++-- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/squirrelbattle/display/statsdisplay.py b/squirrelbattle/display/statsdisplay.py index e24c969..c74b63f 100644 --- a/squirrelbattle/display/statsdisplay.py +++ b/squirrelbattle/display/statsdisplay.py @@ -28,7 +28,7 @@ class StatsDisplay(Display): string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}\nCRI {}%"\ .format(self.player.strength, self.player.intelligence, self.player.charisma, - self.player.dexterity, self.player.constitution,\ + self.player.dexterity, self.player.constitution, self.player.critical) self.addstr(self.pad, 3, 0, string3) @@ -54,15 +54,16 @@ class StatsDisplay(Display): if self.player.equipped_secondary: self.addstr(self.pad, 11, 0, _("Equipped secondary:") + " " - f"{self.pack[self.player.equipped_secondary.name.upper()]}") + + self.pack[self.player.equipped_secondary + .name.upper()]) if self.player.equipped_armor: self.addstr(self.pad, 12, 0, _("Equipped chestplate:") + " " - f"{self.pack[self.player.equipped_armor.name.upper()]}") + + self.pack[self.player.equipped_armor.name.upper()]) if self.player.equipped_helmet: self.addstr(self.pad, 13, 0, _("Equipped helmet:") + " " - f"{self.pack[self.player.equipped_helmet.name.upper()]}") + + self.pack[self.player.equipped_helmet.name.upper()]) self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} " f"x{self.player.hazel}") diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 336d3e5..3eb3530 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -107,7 +107,7 @@ class Item(Entity): @staticmethod def get_all_items() -> list: - return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\ + return [BodySnatchPotion, Bomb, Heart, Shield, Sword, Chestplate, Helmet, RingCritical, RingXP] def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: @@ -283,7 +283,7 @@ class Armor(Item): Class of items that increase the player's constitution. """ constitution: int - + def __init__(self, constitution: int, *args, **kwargs): super().__init__(*args, **kwargs) self.constitution = constitution @@ -301,30 +301,33 @@ class Armor(Item): d["constitution"] = self.constitution return d + class Shield(Armor): """ Class of shield items, they can be equipped in the other hand. """ - def __init__(self, name: str = "shield", constitution: int = 2,\ + def __init__(self, name: str = "shield", constitution: int = 2, price: int = 6, *args, **kwargs): super().__init__(name=name, constitution=constitution, *args, **kwargs) + class Helmet(Armor): """ Class of helmet items, they can be equipped on the head. """ - def __init__(self, name: str = "helmet", constitution: int = 2, \ + def __init__(self, name: str = "helmet", constitution: int = 2, price: int = 8, *args, **kwargs): super().__init__(name=name, constitution=constitution, *args, **kwargs) + class Chestplate(Armor): """ Class of chestplate items, they can be equipped on the body. """ - def __init__(self, name: str = "chestplate", constitution: int = 4,\ + def __init__(self, name: str = "chestplate", constitution: int = 4, price: int = 15, *args, **kwargs): super().__init__(name=name, constitution=constitution, *args, **kwargs) @@ -362,6 +365,7 @@ class BodySnatchPotion(Item): self.held_by.inventory.remove(self) + class Ring(Item): """ A class of rings that boost the player's statistics. @@ -375,9 +379,9 @@ class Ring(Item): critical: int experience: float - def __init__(self, maxhealth: int = 0, strength: int = 0,\ - intelligence: int = 0, charisma: int = 0,\ - dexterity: int = 0, constitution: int = 0,\ + def __init__(self, maxhealth: int = 0, strength: int = 0, + intelligence: int = 0, charisma: int = 0, + dexterity: int = 0, constitution: int = 0, critical: int = 0, experience: float = 0, *args, **kwargs): super().__init__(*args, **kwargs) self.maxhealth = maxhealth @@ -416,14 +420,16 @@ class Ring(Item): d["constitution"] = self.constitution return d + class RingCritical(Ring): def __init__(self, name: str = "ring_of_critical_damage", price: int = 15, critical: int = 20, *args, **kwargs): - super().__init__(name=name, price=price, critical=critical, \ + super().__init__(name=name, price=price, critical=critical, *args, **kwargs) + class RingXP(Ring): def __init__(self, name: str = "ring_of_more_experience", price: int = 25, experience: float = 2, *args, **kwargs): - super().__init__(name=name, price=price, experience=experience, \ + super().__init__(name=name, price=price, experience=experience, *args, **kwargs) diff --git a/squirrelbattle/entities/monsters.py b/squirrelbattle/entities/monsters.py index bcdff11..d93b24b 100644 --- a/squirrelbattle/entities/monsters.py +++ b/squirrelbattle/entities/monsters.py @@ -87,9 +87,11 @@ class Rabbit(Monster): A rabbit monster """ def __init__(self, name: str = "rabbit", strength: int = 1, - maxhealth: int = 15, critical: int = 30, *args, **kwargs) -> None: + maxhealth: int = 15, critical: int = 30, + *args, **kwargs) -> None: super().__init__(name=name, strength=strength, - maxhealth=maxhealth, critical=critical, *args, **kwargs) + maxhealth=maxhealth, critical=critical, + *args, **kwargs) class TeddyBear(Monster): @@ -101,6 +103,7 @@ class TeddyBear(Monster): super().__init__(name=name, strength=strength, maxhealth=maxhealth, *args, **kwargs) + class GiantSeaEagle(Monster): """ An eagle boss diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 854bd93..63d6536 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -28,9 +28,9 @@ class Player(InventoryHolder, FightingEntity): dexterity: int = 1, constitution: int = 1, level: int = 1, current_xp: int = 0, max_xp: int = 10, inventory: list = None, hazel: int = 42, equipped_main: Optional[Item] = None, - equipped_armor: Optional[Item] = None, critical: int = 5,\ - equipped_secondary: Optional[Item] = None, \ - equipped_helmet: Optional[Item] = None, xp_buff: float = 1,\ + equipped_armor: Optional[Item] = None, critical: int = 5, + equipped_secondary: Optional[Item] = None, + equipped_helmet: Optional[Item] = None, xp_buff: float = 1, *args, **kwargs) -> None: super().__init__(name=name, maxhealth=maxhealth, strength=strength, intelligence=intelligence, charisma=charisma, @@ -84,7 +84,7 @@ class Player(InventoryHolder, FightingEntity): Add some experience to the player. If the required amount is reached, level up. """ - self.current_xp += int(xp*self.xp_buff) + self.current_xp += int(xp * self.xp_buff) self.level_up() def remove_from_inventory(self, obj: Item) -> None: diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index e4557d1..556051c 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -146,8 +146,8 @@ class Map: tile = self.tiles[y][x] if tile.can_walk(): break - entity = choices(Entity.get_all_entity_classes(),\ - weights = Entity.get_weights(), k=1)[0]() + entity = choices(Entity.get_all_entity_classes(), + weights=Entity.get_weights(), k=1)[0]() entity.move(y, x) self.add_entity(entity) From 1a78ad584cd4c973a9de48d0bd87c374cc165b91 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 6 Jan 2021 18:31:28 +0100 Subject: [PATCH 16/19] Move equip functions for items --- squirrelbattle/entities/items.py | 57 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 3eb3530..ee5f4a9 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -44,32 +44,11 @@ class Item(Entity): """ Indicates what should be done when the item is equipped. """ - if isinstance(self, Chestplate): - if self.held_by.equipped_armor: - self.held_by.equipped_armor.unequip() - self.held_by.remove_from_inventory(self) - self.held_by.equipped_armor = self - elif isinstance(self, Helmet): - if self.held_by.equipped_helmet: - self.held_by.equipped_helmet.unequip() - self.held_by.remove_from_inventory(self) - self.held_by.equipped_helmet = self - elif isinstance(self, Weapon): - if self.held_by.equipped_main: - if self.held_by.equipped_secondary: - self.held_by.equipped_secondary.unequip() - self.held_by.remove_from_inventory(self) - self.held_by.equipped_secondary = self - # For weapons, they are equipped as main only if main is empty. - else: - self.held_by.remove_from_inventory(self) - self.held_by.equipped_main = self - else: - # Other objects are only equipped as secondary. - if self.held_by.equipped_secondary: - self.held_by.equipped_secondary.unequip() - self.held_by.remove_from_inventory(self) - self.held_by.equipped_secondary = self + # Other objects are only equipped as secondary. + if self.held_by.equipped_secondary: + self.held_by.equipped_secondary.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_secondary = self def unequip(self) -> None: """ @@ -257,7 +236,8 @@ class Weapon(Item): """ When a weapon is equipped, the player gains strength. """ - super().equip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_main = self self.held_by.strength += self.damage def unequip(self) -> None: @@ -309,7 +289,8 @@ class Shield(Armor): def __init__(self, name: str = "shield", constitution: int = 2, price: int = 6, *args, **kwargs): - super().__init__(name=name, constitution=constitution, *args, **kwargs) + super().__init__(name=name, constitution=constitution, price=price, + *args, **kwargs) class Helmet(Armor): @@ -319,7 +300,15 @@ class Helmet(Armor): def __init__(self, name: str = "helmet", constitution: int = 2, price: int = 8, *args, **kwargs): - super().__init__(name=name, constitution=constitution, *args, **kwargs) + super().__init__(name=name, constitution=constitution, price=price, + *args, **kwargs) + + def equip(self) -> None: + super().equip() + if self.held_by.equipped_helmet: + self.held_by.equipped_helmet.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_helmet = self class Chestplate(Armor): @@ -329,7 +318,15 @@ class Chestplate(Armor): def __init__(self, name: str = "chestplate", constitution: int = 4, price: int = 15, *args, **kwargs): - super().__init__(name=name, constitution=constitution, *args, **kwargs) + super().__init__(name=name, constitution=constitution, price=price, + *args, **kwargs) + + def equip(self) -> None: + super().equip() + if self.held_by.equipped_armor: + self.held_by.equipped_armor.unequip() + self.held_by.remove_from_inventory(self) + self.held_by.equipped_armor = self class BodySnatchPotion(Item): From 6c6a44fb18d4d5bc329fd41018a123599c632fda Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 8 Jan 2021 01:56:54 +0100 Subject: [PATCH 17/19] More tests --- squirrelbattle/entities/items.py | 22 +++---- squirrelbattle/entities/player.py | 20 +++---- squirrelbattle/game.py | 7 ++- squirrelbattle/tests/game_test.py | 99 ++++++++++++++++++++++++++++++- 4 files changed, 119 insertions(+), 29 deletions(-) diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index ee5f4a9..7775f74 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -54,17 +54,7 @@ class Item(Entity): """ Indicates what should be done when the item is unequipped. """ - if isinstance(self, Chestplate): - self.held_by.equipped_armor = None - elif isinstance(self, Helmet): - self.held_by.equipped_helmet = None - elif isinstance(self, Weapon): - if self.held_by.equipped_main == self: - self.held_by.equipped_main = None - else: - self.held_by.equipped_secondary = None - else: - self.held_by.equipped_secondary = None + self.held_by.remove_from_inventory(self) self.held_by.add_to_inventory(self) def hold(self, holder: InventoryHolder) -> None: @@ -211,7 +201,6 @@ class Explosion(Item): """ The player can't hold any explosion. """ - pass class Weapon(Item): @@ -304,7 +293,6 @@ class Helmet(Armor): *args, **kwargs) def equip(self) -> None: - super().equip() if self.held_by.equipped_helmet: self.held_by.equipped_helmet.unequip() self.held_by.remove_from_inventory(self) @@ -322,7 +310,6 @@ class Chestplate(Armor): *args, **kwargs) def equip(self) -> None: - super().equip() if self.held_by.equipped_armor: self.held_by.equipped_armor.unequip() self.held_by.remove_from_inventory(self) @@ -414,7 +401,14 @@ class Ring(Item): def save_state(self) -> dict: d = super().save_state() + d["maxhealth"] = self.maxhealth + d["strength"] = self.strength + d["intelligence"] = self.intelligence + d["charisma"] = self.charisma + d["dexterity"] = self.dexterity d["constitution"] = self.constitution + d["critical"] = self.critical + d["experience"] = self.experience return d diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 63d6536..0d939ae 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -42,18 +42,14 @@ class Player(InventoryHolder, FightingEntity): self.inventory = self.translate_inventory(inventory or []) self.paths = dict() self.hazel = hazel - if isinstance(equipped_main, dict): - equipped_main = self.dict_to_item(equipped_main) - if isinstance(equipped_armor, dict): - equipped_armor = self.dict_to_item(equipped_armor) - if isinstance(equipped_secondary, dict): - equipped_secondary = self.dict_to_item(equipped_secondary) - if isinstance(equipped_helmet, dict): - equipped_helmet = self.dict_to_item(equipped_helmet) - self.equipped_main = equipped_main - self.equipped_armor = equipped_armor - self.equipped_secondary = equipped_secondary - self.equipped_helmet = equipped_helmet + self.equipped_main = self.dict_to_item(equipped_main) \ + if isinstance(equipped_main, dict) else equipped_main + self.equipped_armor = self.dict_to_item(equipped_armor) \ + if isinstance(equipped_armor, dict) else equipped_armor + self.equipped_secondary = self.dict_to_item(equipped_secondary) \ + if isinstance(equipped_secondary, dict) else equipped_secondary + self.equipped_helmet = self.dict_to_item(equipped_helmet) \ + if isinstance(equipped_helmet, dict) else equipped_helmet def move(self, y: int, x: int) -> None: """ diff --git a/squirrelbattle/game.py b/squirrelbattle/game.py index 939325c..17adb7d 100644 --- a/squirrelbattle/game.py +++ b/squirrelbattle/game.py @@ -108,7 +108,7 @@ class Game: self.handle_key_pressed_store(key) self.display_actions(DisplayActions.REFRESH) - def handle_key_pressed_play(self, key: KeyValues) -> None: + def handle_key_pressed_play(self, key: KeyValues) -> None: # noqa: C901 """ In play mode, arrows or zqsd move the main character. """ @@ -128,7 +128,10 @@ class Game: self.state = GameMode.INVENTORY self.display_actions(DisplayActions.UPDATE) elif key == KeyValues.USE and self.player.equipped_main: - self.player.equipped_main.use() + if self.player.equipped_main: + self.player.equipped_main.use() + if self.player.equipped_secondary: + self.player.equipped_secondary.use() elif key == KeyValues.SPACE: self.state = GameMode.MAINMENU elif key == KeyValues.CHAT: diff --git a/squirrelbattle/tests/game_test.py b/squirrelbattle/tests/game_test.py index 6751016..06ddcf6 100644 --- a/squirrelbattle/tests/game_test.py +++ b/squirrelbattle/tests/game_test.py @@ -2,13 +2,16 @@ # SPDX-License-Identifier: GPL-3.0-or-later import os +import random import unittest from ..bootstrap import Bootstrap from ..display.display import Display from ..display.display_manager import DisplayManager from ..entities.friendly import Merchant, Sunflower -from ..entities.items import Bomb, Heart, Sword, Explosion +from ..entities.items import Bomb, Heart, Sword, Explosion, Shield, Helmet, \ + Chestplate, RingCritical +from ..entities.monsters import GiantSeaEagle from ..entities.player import Player from ..enums import DisplayActions from ..game import Game, KeyValues, GameMode @@ -609,3 +612,97 @@ class TestGame(unittest.TestCase): # Exit the menu self.game.handle_key_pressed(KeyValues.SPACE) self.assertEqual(self.game.state, GameMode.PLAY) + + def test_equipment(self) -> None: + """ + Ensure that equipment is working. + """ + self.game.state = GameMode.INVENTORY + + # sword goes into the main equipment slot + sword = Sword() + sword.hold(self.game.player) + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_main, sword) + self.assertFalse(self.game.player.inventory) + + # shield goes into the secondary equipment slot + shield = Shield() + shield.hold(self.game.player) + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_secondary, shield) + self.assertFalse(self.game.player.inventory) + + # helmet goes into the helmet slot + helmet = Helmet() + helmet.hold(self.game.player) + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_helmet, helmet) + self.assertFalse(self.game.player.inventory) + + # helmet goes into the armor slot + chestplate = Chestplate() + chestplate.hold(self.game.player) + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_armor, chestplate) + self.assertFalse(self.game.player.inventory) + + # Use bomb + bomb = Bomb() + bomb.hold(self.game.player) + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_secondary, bomb) + self.assertIn(shield, self.game.player.inventory) + self.game.state = GameMode.PLAY + self.game.handle_key_pressed(KeyValues.USE) + self.assertIsNone(self.game.player.equipped_secondary) + self.game.state = GameMode.INVENTORY + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.equipped_secondary, shield) + self.assertFalse(self.game.player.inventory) + + # Reequip, which is useless but covers code + sword.equip() + shield.equip() + helmet.equip() + chestplate.equip() + self.game.save_state() + + # Unequip all + sword.unequip() + shield.unequip() + helmet.unequip() + chestplate.unequip() + self.assertIsNone(self.game.player.equipped_main) + self.assertIsNone(self.game.player.equipped_secondary) + self.assertIsNone(self.game.player.equipped_helmet) + self.assertIsNone(self.game.player.equipped_armor) + self.assertIn(sword, self.game.player.inventory) + self.assertIn(shield, self.game.player.inventory) + self.assertIn(helmet, self.game.player.inventory) + self.assertIn(chestplate, self.game.player.inventory) + + # Test rings + self.game.player.inventory.clear() + ring = RingCritical() + ring.hold(self.game.player) + old_critical = self.game.player.critical + self.game.handle_key_pressed(KeyValues.EQUIP) + self.assertEqual(self.game.player.critical, + old_critical + ring.critical) + self.game.save_state() + ring.unequip() + + def test_critical_hit(self) -> None: + """ + Ensure that critical hits are working. + """ + random.seed(2) # Next random.randint(1, 100) will output 8 + self.game.player.critical = 10 + sea_eagle = GiantSeaEagle() + self.game.map.add_entity(sea_eagle) + sea_eagle.move(2, 6) + old_health = sea_eagle.health + self.game.player.hit(sea_eagle) + self.assertEqual(sea_eagle.health, + old_health - self.game.player.strength * 4) From 7aeb659cf5cff18f0b69245886fcb319ecb79c0d Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 8 Jan 2021 02:00:22 +0100 Subject: [PATCH 18/19] Fix french translation --- squirrelbattle/interfaces.py | 2 +- .../locale/de/LC_MESSAGES/squirrelbattle.po | 69 ++++++++++++------ .../locale/es/LC_MESSAGES/squirrelbattle.po | 69 ++++++++++++------ .../locale/fr/LC_MESSAGES/squirrelbattle.po | 71 +++++++++++++------ 4 files changed, 143 insertions(+), 68 deletions(-) diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index 556051c..bbac3a1 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -449,7 +449,7 @@ class FightingEntity(Entity): string = " " if diceroll <= self.critical: # It is a critical hit damage *= 4 - string = _(" It's a critical hit! ") + string = " " + _("It's a critical hit!") + " " return _("{name} hits {opponent}.")\ .format(name=_(self.translated_name.capitalize()), opponent=_(opponent.translated_name)) + string + \ diff --git a/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po index 29bf10e..2765985 100644 --- a/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: squirrelbattle 3.14.1\n" "Report-Msgid-Bugs-To: squirrel-battle@crans.org\n" -"POT-Creation-Date: 2020-12-12 18:02+0100\n" +"POT-Creation-Date: 2021-01-08 01:57+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,19 +17,44 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: squirrelbattle/display/menudisplay.py:139 +#, python-brace-format +msgid "{name} takes {amount} damage." +msgstr "{name} nimmt {amount} Schadenspunkte." + +#: squirrelbattle/display/menudisplay.py:160 msgid "INVENTORY" msgstr "BESTAND" -#: squirrelbattle/display/menudisplay.py:164 +#: squirrelbattle/display/menudisplay.py:202 msgid "STALL" msgstr "STAND" -#: squirrelbattle/display/statsdisplay.py:33 +#: squirrelbattle/display/statsdisplay.py:23 +#: squirrelbattle/tests/translations_test.py:60 +msgid "player" +msgstr "Spieler" + +#: squirrelbattle/display/statsdisplay.py:35 msgid "Inventory:" msgstr "Bestand:" #: squirrelbattle/display/statsdisplay.py:52 +msgid "Equipped main:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:56 +msgid "Equipped secondary:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:61 +msgid "Equipped chestplate:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:65 +msgid "Equipped helmet:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:72 msgid "YOU ARE DEAD" msgstr "SIE WURDEN GESTORBEN" @@ -49,20 +74,20 @@ msgstr "Die Sonne ist warm heute" #. The bomb is exploding. #. Each entity that is close to the bomb takes damages. #. The player earn XP if the entity was killed. -#: squirrelbattle/entities/items.py:151 +#: squirrelbattle/entities/items.py:163 msgid "Bomb is exploding." msgstr "Die Bombe explodiert." -#: squirrelbattle/entities/items.py:248 +#: squirrelbattle/entities/items.py:344 #, python-brace-format msgid "{player} exchanged its body with {entity}." msgstr "{player} täuscht seinem Körper mit {entity} aus." -#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573 +#: squirrelbattle/game.py:228 squirrelbattle/tests/game_test.py:595 msgid "The buyer does not have enough money" msgstr "Der Kaufer hat nicht genug Geld" -#: squirrelbattle/game.py:249 +#: squirrelbattle/game.py:271 msgid "" "Some keys are missing in your save file.\n" "Your save seems to be corrupt. It got deleted." @@ -70,7 +95,7 @@ msgstr "" "In Ihrer Speicherdatei fehlen einige Schlüssel.\n" "Ihre Speicherung scheint korrupt zu sein. Es wird gelöscht." -#: squirrelbattle/game.py:257 +#: squirrelbattle/game.py:279 msgid "" "No player was found on this map!\n" "Maybe you died?" @@ -78,7 +103,7 @@ msgstr "" "Auf dieser Karte wurde kein Spieler gefunden!\n" "Vielleicht sind Sie gestorben?" -#: squirrelbattle/game.py:277 +#: squirrelbattle/game.py:299 msgid "" "The JSON file is not correct.\n" "Your save seems corrupted. It got deleted." @@ -86,22 +111,26 @@ msgstr "" "Die JSON-Datei ist nicht korrekt.\n" "Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht." -#: squirrelbattle/interfaces.py:429 +#: squirrelbattle/interfaces.py:452 +msgid "It's a critical hit!" +msgstr "" + +#: squirrelbattle/interfaces.py:453 #, python-brace-format msgid "{name} hits {opponent}." msgstr "{name} schlägt {opponent}." -#: squirrelbattle/interfaces.py:441 +#: squirrelbattle/interfaces.py:466 #, python-brace-format -msgid "{name} takes {amount} damage." -msgstr "{name} nimmt {amount} Schadenspunkte." +msgid "{name} takes {damage} damage." +msgstr "" -#: squirrelbattle/interfaces.py:443 +#: squirrelbattle/interfaces.py:468 #, python-brace-format msgid "{name} dies." msgstr "{name} stirbt." -#: squirrelbattle/interfaces.py:477 +#: squirrelbattle/interfaces.py:502 #, python-brace-format msgid "{entity} said: {message}" msgstr "{entity} hat gesagt: {message}" @@ -110,8 +139,8 @@ msgstr "{entity} hat gesagt: {message}" msgid "Back" msgstr "Zurück" -#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347 -#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353 +#: squirrelbattle/tests/game_test.py:361 squirrelbattle/tests/game_test.py:364 +#: squirrelbattle/tests/game_test.py:367 squirrelbattle/tests/game_test.py:370 #: squirrelbattle/tests/translations_test.py:16 msgid "New game" msgstr "Neu Spiel" @@ -204,10 +233,6 @@ msgstr "Textur-Packung" msgid "Language" msgstr "Sprache" -#: squirrelbattle/tests/translations_test.py:60 -msgid "player" -msgstr "Spieler" - #: squirrelbattle/tests/translations_test.py:62 msgid "hedgehog" msgstr "Igel" diff --git a/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po index 8a7bc3e..d4d34db 100644 --- a/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: squirrelbattle 3.14.1\n" "Report-Msgid-Bugs-To: squirrel-battle@crans.org\n" -"POT-Creation-Date: 2020-12-12 18:02+0100\n" +"POT-Creation-Date: 2021-01-08 01:57+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,19 +17,44 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: squirrelbattle/display/menudisplay.py:139 +#, python-brace-format +msgid "{name} takes {amount} damage." +msgstr "{name} recibe {amount} daño." + +#: squirrelbattle/display/menudisplay.py:160 msgid "INVENTORY" msgstr "INVENTORIO" -#: squirrelbattle/display/menudisplay.py:164 +#: squirrelbattle/display/menudisplay.py:202 msgid "STALL" msgstr "PUESTO" -#: squirrelbattle/display/statsdisplay.py:33 +#: squirrelbattle/display/statsdisplay.py:23 +#: squirrelbattle/tests/translations_test.py:60 +msgid "player" +msgstr "jugador" + +#: squirrelbattle/display/statsdisplay.py:35 msgid "Inventory:" msgstr "Inventorio :" #: squirrelbattle/display/statsdisplay.py:52 +msgid "Equipped main:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:56 +msgid "Equipped secondary:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:61 +msgid "Equipped chestplate:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:65 +msgid "Equipped helmet:" +msgstr "" + +#: squirrelbattle/display/statsdisplay.py:72 msgid "YOU ARE DEAD" msgstr "ERES MUERTO" @@ -48,20 +73,20 @@ msgstr "El sol está caliente hoy" #. The bomb is exploding. #. Each entity that is close to the bomb takes damages. #. The player earn XP if the entity was killed. -#: squirrelbattle/entities/items.py:151 +#: squirrelbattle/entities/items.py:163 msgid "Bomb is exploding." msgstr "La bomba está explotando." -#: squirrelbattle/entities/items.py:248 +#: squirrelbattle/entities/items.py:344 #, python-brace-format msgid "{player} exchanged its body with {entity}." msgstr "{player} intercambió su cuerpo con {entity}." -#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573 +#: squirrelbattle/game.py:228 squirrelbattle/tests/game_test.py:595 msgid "The buyer does not have enough money" msgstr "El comprador no tiene suficiente dinero" -#: squirrelbattle/game.py:249 +#: squirrelbattle/game.py:271 msgid "" "Some keys are missing in your save file.\n" "Your save seems to be corrupt. It got deleted." @@ -69,7 +94,7 @@ msgstr "" "Algunas claves faltan en su archivo de guarda.\n" "Su guarda parece a ser corruptido. Fue eliminado." -#: squirrelbattle/game.py:257 +#: squirrelbattle/game.py:279 msgid "" "No player was found on this map!\n" "Maybe you died?" @@ -77,7 +102,7 @@ msgstr "" "No jugador encontrado sobre la carta !\n" "¿ Quizas murió ?" -#: squirrelbattle/game.py:277 +#: squirrelbattle/game.py:299 msgid "" "The JSON file is not correct.\n" "Your save seems corrupted. It got deleted." @@ -85,22 +110,26 @@ msgstr "" "El JSON archivo no es correcto.\n" "Su guarda parece corrupta. Fue eliminada." -#: squirrelbattle/interfaces.py:429 +#: squirrelbattle/interfaces.py:452 +msgid "It's a critical hit!" +msgstr "" + +#: squirrelbattle/interfaces.py:453 #, python-brace-format msgid "{name} hits {opponent}." msgstr "{name} golpea a {opponent}." -#: squirrelbattle/interfaces.py:441 +#: squirrelbattle/interfaces.py:466 #, python-brace-format -msgid "{name} takes {amount} damage." -msgstr "{name} recibe {amount} daño." +msgid "{name} takes {damage} damage." +msgstr "" -#: squirrelbattle/interfaces.py:443 +#: squirrelbattle/interfaces.py:468 #, python-brace-format msgid "{name} dies." msgstr "{name} se muere." -#: squirrelbattle/interfaces.py:477 +#: squirrelbattle/interfaces.py:502 #, python-brace-format msgid "{entity} said: {message}" msgstr "{entity} dijo : {message}" @@ -109,8 +138,8 @@ msgstr "{entity} dijo : {message}" msgid "Back" msgstr "Volver" -#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347 -#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353 +#: squirrelbattle/tests/game_test.py:361 squirrelbattle/tests/game_test.py:364 +#: squirrelbattle/tests/game_test.py:367 squirrelbattle/tests/game_test.py:370 #: squirrelbattle/tests/translations_test.py:16 msgid "New game" msgstr "Nuevo partido" @@ -203,10 +232,6 @@ msgstr "Paquete de texturas" msgid "Language" msgstr "Languaje" -#: squirrelbattle/tests/translations_test.py:60 -msgid "player" -msgstr "jugador" - #: squirrelbattle/tests/translations_test.py:62 msgid "hedgehog" msgstr "erizo" diff --git a/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po index ffbfdce..a9385a6 100644 --- a/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: squirrelbattle 3.14.1\n" "Report-Msgid-Bugs-To: squirrel-battle@crans.org\n" -"POT-Creation-Date: 2020-12-12 18:02+0100\n" +"POT-Creation-Date: 2021-01-08 01:57+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,19 +17,44 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: squirrelbattle/display/menudisplay.py:139 +#, python-brace-format +msgid "{name} takes {amount} damage." +msgstr "{name} prend {amount} points de dégât." + +#: squirrelbattle/display/menudisplay.py:160 msgid "INVENTORY" msgstr "INVENTAIRE" -#: squirrelbattle/display/menudisplay.py:164 +#: squirrelbattle/display/menudisplay.py:202 msgid "STALL" msgstr "STAND" -#: squirrelbattle/display/statsdisplay.py:33 +#: squirrelbattle/display/statsdisplay.py:23 +#: squirrelbattle/tests/translations_test.py:60 +msgid "player" +msgstr "joueur" + +#: squirrelbattle/display/statsdisplay.py:35 msgid "Inventory:" msgstr "Inventaire :" #: squirrelbattle/display/statsdisplay.py:52 +msgid "Equipped main:" +msgstr "Équipement principal :" + +#: squirrelbattle/display/statsdisplay.py:56 +msgid "Equipped secondary:" +msgstr "Équipement secondaire :" + +#: squirrelbattle/display/statsdisplay.py:61 +msgid "Equipped chestplate:" +msgstr "Plastron équipé :" + +#: squirrelbattle/display/statsdisplay.py:65 +msgid "Equipped helmet:" +msgstr "Casque équipé :" + +#: squirrelbattle/display/statsdisplay.py:72 msgid "YOU ARE DEAD" msgstr "VOUS ÊTES MORT" @@ -49,20 +74,20 @@ msgstr "Le soleil est chaud aujourd'hui" #. The bomb is exploding. #. Each entity that is close to the bomb takes damages. #. The player earn XP if the entity was killed. -#: squirrelbattle/entities/items.py:151 +#: squirrelbattle/entities/items.py:163 msgid "Bomb is exploding." msgstr "La bombe explose." -#: squirrelbattle/entities/items.py:248 +#: squirrelbattle/entities/items.py:344 #, python-brace-format msgid "{player} exchanged its body with {entity}." msgstr "{player} a échangé son corps avec {entity}." -#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573 +#: squirrelbattle/game.py:228 squirrelbattle/tests/game_test.py:595 msgid "The buyer does not have enough money" msgstr "L'acheteur n'a pas assez d'argent" -#: squirrelbattle/game.py:249 +#: squirrelbattle/game.py:271 msgid "" "Some keys are missing in your save file.\n" "Your save seems to be corrupt. It got deleted." @@ -70,7 +95,7 @@ msgstr "" "Certaines clés de votre ficher de sauvegarde sont manquantes.\n" "Votre sauvegarde semble corrompue. Elle a été supprimée." -#: squirrelbattle/game.py:257 +#: squirrelbattle/game.py:279 msgid "" "No player was found on this map!\n" "Maybe you died?" @@ -78,7 +103,7 @@ msgstr "" "Aucun joueur n'a été trouvé sur la carte !\n" "Peut-être êtes-vous mort ?" -#: squirrelbattle/game.py:277 +#: squirrelbattle/game.py:299 msgid "" "The JSON file is not correct.\n" "Your save seems corrupted. It got deleted." @@ -86,22 +111,26 @@ msgstr "" "Le fichier JSON de sauvegarde est incorrect.\n" "Votre sauvegarde semble corrompue. Elle a été supprimée." -#: squirrelbattle/interfaces.py:429 +#: squirrelbattle/interfaces.py:452 +msgid "It's a critical hit!" +msgstr "C'est un coup critique !" + +#: squirrelbattle/interfaces.py:453 #, python-brace-format msgid "{name} hits {opponent}." msgstr "{name} frappe {opponent}." -#: squirrelbattle/interfaces.py:441 +#: squirrelbattle/interfaces.py:466 #, python-brace-format -msgid "{name} takes {amount} damage." -msgstr "{name} prend {amount} points de dégât." +msgid "{name} takes {damage} damage." +msgstr "{name} prend {damage} dégâts." -#: squirrelbattle/interfaces.py:443 +#: squirrelbattle/interfaces.py:468 #, python-brace-format msgid "{name} dies." msgstr "{name} meurt." -#: squirrelbattle/interfaces.py:477 +#: squirrelbattle/interfaces.py:502 #, python-brace-format msgid "{entity} said: {message}" msgstr "{entity} a dit : {message}" @@ -110,8 +139,8 @@ msgstr "{entity} a dit : {message}" msgid "Back" msgstr "Retour" -#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347 -#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353 +#: squirrelbattle/tests/game_test.py:361 squirrelbattle/tests/game_test.py:364 +#: squirrelbattle/tests/game_test.py:367 squirrelbattle/tests/game_test.py:370 #: squirrelbattle/tests/translations_test.py:16 msgid "New game" msgstr "Nouvelle partie" @@ -204,10 +233,6 @@ msgstr "Pack de textures" msgid "Language" msgstr "Langue" -#: squirrelbattle/tests/translations_test.py:60 -msgid "player" -msgstr "joueur" - #: squirrelbattle/tests/translations_test.py:62 msgid "hedgehog" msgstr "hérisson" @@ -242,7 +267,7 @@ msgstr "bombe" #: squirrelbattle/tests/translations_test.py:71 msgid "explosion" -msgstr "" +msgstr "explosion" #: squirrelbattle/tests/translations_test.py:72 msgid "heart" From affc1bae59858a0567e19a1ba0c5e245fef57b01 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 8 Jan 2021 02:15:13 +0100 Subject: [PATCH 19/19] Fix merge --- squirrelbattle/entities/player.py | 3 --- squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po | 4 ---- squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po | 4 ---- squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po | 4 ---- 4 files changed, 15 deletions(-) diff --git a/squirrelbattle/entities/player.py b/squirrelbattle/entities/player.py index 8d7898c..615dfd5 100644 --- a/squirrelbattle/entities/player.py +++ b/squirrelbattle/entities/player.py @@ -2,10 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later from random import randint -<<<<<<< squirrelbattle/entities/player.py from typing import Dict, Optional, Tuple -======= ->>>>>>> squirrelbattle/entities/player.py from .items import Item from ..interfaces import FightingEntity, InventoryHolder diff --git a/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po index 9c5dbc4..20aa2a7 100644 --- a/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po @@ -247,10 +247,6 @@ msgstr "Textur-Packung" msgid "Language" msgstr "Sprache" -#: squirrelbattle/tests/translations_test.py:62 -msgid "player" -msgstr "Spieler" - #: squirrelbattle/tests/translations_test.py:64 msgid "hedgehog" msgstr "Igel" diff --git a/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po index 74f6a65..0bfdac6 100644 --- a/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/es/LC_MESSAGES/squirrelbattle.po @@ -246,10 +246,6 @@ msgstr "Paquete de texturas" msgid "Language" msgstr "Languaje" -#: squirrelbattle/tests/translations_test.py:62 -msgid "player" -msgstr "jugador" - #: squirrelbattle/tests/translations_test.py:64 msgid "hedgehog" msgstr "erizo" diff --git a/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po b/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po index 5028b07..42172c3 100644 --- a/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po +++ b/squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po @@ -247,10 +247,6 @@ msgstr "Pack de textures" msgid "Language" msgstr "Langue" -#: squirrelbattle/tests/translations_test.py:62 -msgid "player" -msgstr "joueur" - #: squirrelbattle/tests/translations_test.py:64 msgid "hedgehog" msgstr "hérisson"