Merging master into village, conflicts were solved
This commit is contained in:
		
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							@@ -11,7 +11,7 @@ with open("README.md", "r") as f:
 | 
			
		||||
    long_description = f.read()
 | 
			
		||||
 | 
			
		||||
# Compile messages
 | 
			
		||||
for language in ["de", "en", "fr"]:
 | 
			
		||||
for language in ["de", "fr"]:
 | 
			
		||||
    args = ["msgfmt", "--check-format",
 | 
			
		||||
            "-o", f"squirrelbattle/locale/{language}/LC_MESSAGES"
 | 
			
		||||
                  "/squirrelbattle.mo",
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ from squirrelbattle.display.display import VerticalSplit, HorizontalSplit
 | 
			
		||||
from squirrelbattle.display.mapdisplay import MapDisplay
 | 
			
		||||
from squirrelbattle.display.messagedisplay import MessageDisplay
 | 
			
		||||
from squirrelbattle.display.statsdisplay import StatsDisplay
 | 
			
		||||
from squirrelbattle.display.menudisplay import SettingsMenuDisplay, \
 | 
			
		||||
    MainMenuDisplay
 | 
			
		||||
from squirrelbattle.display.menudisplay import MainMenuDisplay, \
 | 
			
		||||
    InventoryDisplay, SettingsMenuDisplay
 | 
			
		||||
from squirrelbattle.display.logsdisplay import LogsDisplay
 | 
			
		||||
from squirrelbattle.display.texturepack import TexturePack
 | 
			
		||||
from typing import Any
 | 
			
		||||
@@ -23,10 +23,11 @@ class DisplayManager:
 | 
			
		||||
        pack = TexturePack.get_pack(self.game.settings.TEXTURE_PACK)
 | 
			
		||||
        self.mapdisplay = MapDisplay(screen, pack)
 | 
			
		||||
        self.statsdisplay = StatsDisplay(screen, pack)
 | 
			
		||||
        self.logsdisplay = LogsDisplay(screen, pack)
 | 
			
		||||
        self.inventorydisplay = InventoryDisplay(screen, pack)
 | 
			
		||||
        self.mainmenudisplay = MainMenuDisplay(self.game.main_menu,
 | 
			
		||||
                                               screen, pack)
 | 
			
		||||
        self.settingsmenudisplay = SettingsMenuDisplay(screen, pack)
 | 
			
		||||
        self.logsdisplay = LogsDisplay(screen, pack)
 | 
			
		||||
        self.messagedisplay = MessageDisplay(screen=screen, pack=None)
 | 
			
		||||
        self.hbar = HorizontalSplit(screen, pack)
 | 
			
		||||
        self.vbar = VerticalSplit(screen, pack)
 | 
			
		||||
@@ -46,12 +47,14 @@ class DisplayManager:
 | 
			
		||||
            d.pack = TexturePack.get_pack(self.game.settings.TEXTURE_PACK)
 | 
			
		||||
        self.mapdisplay.update_map(self.game.map)
 | 
			
		||||
        self.statsdisplay.update_player(self.game.player)
 | 
			
		||||
        self.inventorydisplay.update_menu(self.game.inventory_menu)
 | 
			
		||||
        self.settingsmenudisplay.update_menu(self.game.settings_menu)
 | 
			
		||||
        self.logsdisplay.update_logs(self.game.logs)
 | 
			
		||||
        self.messagedisplay.update_message(self.game.message)
 | 
			
		||||
 | 
			
		||||
    def refresh(self) -> None:
 | 
			
		||||
        if self.game.state == GameMode.PLAY:
 | 
			
		||||
        if self.game.state == GameMode.PLAY \
 | 
			
		||||
                or self.game.state == GameMode.INVENTORY:
 | 
			
		||||
            # The map pad has already the good size
 | 
			
		||||
            self.mapdisplay.refresh(0, 0, self.rows * 4 // 5,
 | 
			
		||||
                                    self.mapdisplay.pack.tile_width
 | 
			
		||||
@@ -64,10 +67,15 @@ class DisplayManager:
 | 
			
		||||
                                     self.rows // 5 - 1, self.cols * 4 // 5)
 | 
			
		||||
            self.hbar.refresh(self.rows * 4 // 5, 0, 1, self.cols * 4 // 5)
 | 
			
		||||
            self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1)
 | 
			
		||||
        if self.game.state == GameMode.MAINMENU:
 | 
			
		||||
            if self.game.state == GameMode.INVENTORY:
 | 
			
		||||
                self.inventorydisplay.refresh(self.rows // 10,
 | 
			
		||||
                                              self.cols // 2,
 | 
			
		||||
                                              8 * self.rows // 10,
 | 
			
		||||
                                              2 * self.cols // 5)
 | 
			
		||||
        elif self.game.state == GameMode.MAINMENU:
 | 
			
		||||
            self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
			
		||||
        if self.game.state == GameMode.SETTINGS:
 | 
			
		||||
            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols - 1)
 | 
			
		||||
        elif self.game.state == GameMode.SETTINGS:
 | 
			
		||||
            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
			
		||||
 | 
			
		||||
        if self.game.message:
 | 
			
		||||
            height, width = 0, 0
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import curses
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.menus import Menu, MainMenu
 | 
			
		||||
@@ -24,8 +24,6 @@ class MenuDisplay(Display):
 | 
			
		||||
 | 
			
		||||
        # Menu values are printed in pad
 | 
			
		||||
        self.pad = self.newpad(self.trueheight, self.truewidth + 2)
 | 
			
		||||
        for i in range(self.trueheight):
 | 
			
		||||
            self.addstr(self.pad, i, 0, "  " + self.values[i])
 | 
			
		||||
 | 
			
		||||
    def update_pad(self) -> None:
 | 
			
		||||
        for i in range(self.trueheight):
 | 
			
		||||
@@ -110,12 +108,22 @@ class MainMenuDisplay(Display):
 | 
			
		||||
            menuy, menux, min(self.menudisplay.preferred_height,
 | 
			
		||||
                              self.height - menuy), menuwidth)
 | 
			
		||||
 | 
			
		||||
class VariableMenuDisplay(MenuDisplay):
 | 
			
		||||
    """
 | 
			
		||||
    A class to display a menu in which each value is associated to a parameter
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
class InventoryDisplay(MenuDisplay):
 | 
			
		||||
    def update_pad(self) -> None:
 | 
			
		||||
        message = _("== INVENTORY ==")
 | 
			
		||||
        self.addstr(self.pad, 0, (self.width - len(message)) // 2, message,
 | 
			
		||||
                    curses.A_BOLD | curses.A_ITALIC)
 | 
			
		||||
        for i, item in enumerate(self.menu.values):
 | 
			
		||||
            rep = self.pack[item.name.upper()]
 | 
			
		||||
            selection = f"[{rep}]" if i == self.menu.position else f" {rep} "
 | 
			
		||||
            self.addstr(self.pad, 2 + i, 0, selection
 | 
			
		||||
                        + " " + item.translated_name.capitalize())
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def values(self) -> List[str]:
 | 
			
		||||
        return [a[1][1] + (" : "
 | 
			
		||||
                + (a[1][0])
 | 
			
		||||
            if a[1][0] else "") for a in self.menu.values]
 | 
			
		||||
    def truewidth(self) -> int:
 | 
			
		||||
        return max(1, self.height if hasattr(self, "height") else 10)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def trueheight(self) -> int:
 | 
			
		||||
        return 2 + super().trueheight
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,19 @@ class StatsDisplay(Display):
 | 
			
		||||
                    self.player.dexterity, self.player.constitution)
 | 
			
		||||
        self.addstr(self.pad, 3, 0, string3)
 | 
			
		||||
 | 
			
		||||
        inventory_str = _("Inventory:") + " " + "".join(
 | 
			
		||||
            self.pack[item.name.upper()] for item in self.player.inventory)
 | 
			
		||||
        inventory_str = _("Inventory:") + " "
 | 
			
		||||
        # Stack items by type instead of displaying each item
 | 
			
		||||
        item_types = [item.name for item in self.player.inventory]
 | 
			
		||||
        item_types.sort(key=item_types.count, reverse=True)
 | 
			
		||||
        printed_items = []
 | 
			
		||||
        for item in item_types:
 | 
			
		||||
            if item in printed_items:
 | 
			
		||||
                continue
 | 
			
		||||
            count = item_types.count(item)
 | 
			
		||||
            inventory_str += self.pack[item.upper()]
 | 
			
		||||
            if count > 1:
 | 
			
		||||
                inventory_str += f"x{count} "
 | 
			
		||||
            printed_items.append(item)
 | 
			
		||||
        self.addstr(self.pad, 8, 0, inventory_str)
 | 
			
		||||
 | 
			
		||||
        if self.player.dead:
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ TexturePack.ASCII_PACK = TexturePack(
 | 
			
		||||
    TEDDY_BEAR='8',
 | 
			
		||||
    MERCHANT='M',
 | 
			
		||||
    SUNFLOWER='I',
 | 
			
		||||
    BODY_SNATCH_POTION='S',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
TexturePack.SQUIRREL_PACK = TexturePack(
 | 
			
		||||
@@ -79,4 +80,5 @@ TexturePack.SQUIRREL_PACK = TexturePack(
 | 
			
		||||
    TEDDY_BEAR='🧸',
 | 
			
		||||
    MERCHANT='🦜',
 | 
			
		||||
    SUNFLOWER='🌻',
 | 
			
		||||
    BODY_SNATCH_POTION='🔀',
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from random import choice, randint
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
from .player import Player
 | 
			
		||||
from ..interfaces import Entity, FightingEntity, Map
 | 
			
		||||
from ..translations import gettext as _
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Item(Entity):
 | 
			
		||||
@@ -20,16 +22,26 @@ class Item(Entity):
 | 
			
		||||
        self.held = held
 | 
			
		||||
        self.held_by = held_by
 | 
			
		||||
 | 
			
		||||
    def drop(self, y: int, x: int) -> None:
 | 
			
		||||
    def drop(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        The item is dropped from the inventory onto the floor
 | 
			
		||||
        """
 | 
			
		||||
        if self.held:
 | 
			
		||||
            self.held_by.inventory.remove(self)
 | 
			
		||||
            self.map.add_entity(self)
 | 
			
		||||
            self.move(self.held_by.y, self.held_by.x)
 | 
			
		||||
            self.held = False
 | 
			
		||||
            self.held_by = None
 | 
			
		||||
        self.map.add_entity(self)
 | 
			
		||||
        self.move(y, x)
 | 
			
		||||
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Indicates what should be done when the item is used.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
    def equip(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Indicates what should be done when the item is equipped.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
    def hold(self, player: "Player") -> None:
 | 
			
		||||
        """
 | 
			
		||||
@@ -55,8 +67,8 @@ class Heart(Item):
 | 
			
		||||
    """
 | 
			
		||||
    healing: int
 | 
			
		||||
 | 
			
		||||
    def __init__(self, healing: int = 5, *args, **kwargs):
 | 
			
		||||
        super().__init__(name="heart", *args, **kwargs)
 | 
			
		||||
    def __init__(self, name: str = "heart", healing: int = 5, *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
        self.healing = healing
 | 
			
		||||
 | 
			
		||||
    def hold(self, player: "Player") -> None:
 | 
			
		||||
@@ -81,26 +93,47 @@ class Bomb(Item):
 | 
			
		||||
    """
 | 
			
		||||
    damage: int = 5
 | 
			
		||||
    exploding: bool
 | 
			
		||||
    owner: Optional["Player"]
 | 
			
		||||
    tick: int
 | 
			
		||||
 | 
			
		||||
    def __init__(self, damage: int = 5, exploding: bool = False,
 | 
			
		||||
                 *args, **kwargs):
 | 
			
		||||
        super().__init__(name="bomb", *args, **kwargs)
 | 
			
		||||
    def __init__(self, name: str = "bomb", damage: int = 5,
 | 
			
		||||
                 exploding: bool = False, *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
        self.damage = damage
 | 
			
		||||
        self.exploding = exploding
 | 
			
		||||
        self.tick = 4
 | 
			
		||||
        self.owner = None
 | 
			
		||||
 | 
			
		||||
    def drop(self, x: int, y: int) -> None:
 | 
			
		||||
        super().drop(x, y)
 | 
			
		||||
        self.exploding = True
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        When the bomb is used, throw it and explodes it.
 | 
			
		||||
        """
 | 
			
		||||
        if self.held:
 | 
			
		||||
            self.owner = self.held_by
 | 
			
		||||
            super().drop()
 | 
			
		||||
            self.exploding = True
 | 
			
		||||
 | 
			
		||||
    def act(self, m: Map) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Special exploding action of the bomb
 | 
			
		||||
        """
 | 
			
		||||
        if self.exploding:
 | 
			
		||||
            for e in m.entities.copy():
 | 
			
		||||
                if abs(e.x - self.x) + abs(e.y - self.y) <= 1 and \
 | 
			
		||||
                        isinstance(e, FightingEntity):
 | 
			
		||||
                    e.take_damage(self, self.damage)
 | 
			
		||||
            if self.tick > 0:
 | 
			
		||||
                # The bomb will explode in <tick> moves
 | 
			
		||||
                self.tick -= 1
 | 
			
		||||
            else:
 | 
			
		||||
                # The bomb is exploding.
 | 
			
		||||
                # Each entity that is close to the bomb takes damages.
 | 
			
		||||
                # The player earn XP if the entity was killed.
 | 
			
		||||
                log_message = _("Bomb is exploding.")
 | 
			
		||||
                for e in m.entities.copy():
 | 
			
		||||
                    if abs(e.x - self.x) + abs(e.y - self.y) <= 3 and \
 | 
			
		||||
                            isinstance(e, FightingEntity):
 | 
			
		||||
                        log_message += " " + e.take_damage(self, self.damage)
 | 
			
		||||
                        if e.dead:
 | 
			
		||||
                            self.owner.add_xp(randint(3, 7))
 | 
			
		||||
                m.logs.add_message(log_message)
 | 
			
		||||
                m.entities.remove(self)
 | 
			
		||||
 | 
			
		||||
    def save_state(self) -> dict:
 | 
			
		||||
        """
 | 
			
		||||
@@ -137,3 +170,34 @@ class Sword(Weapon) :
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.name = "sword"
 | 
			
		||||
        
 | 
			
		||||
class BodySnatchPotion(Item):
 | 
			
		||||
    """
 | 
			
		||||
    The body-snatch potion allows to exchange all characteristics with a random
 | 
			
		||||
    other entity.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name: str = "body_snatch_potion", *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Find a valid random entity, then exchange characteristics.
 | 
			
		||||
        """
 | 
			
		||||
        valid_entities = self.held_by.map.find_entities(FightingEntity)
 | 
			
		||||
        valid_entities.remove(self.held_by)
 | 
			
		||||
        entity = choice(valid_entities)
 | 
			
		||||
        entity_state = entity.save_state()
 | 
			
		||||
        player_state = self.held_by.save_state()
 | 
			
		||||
        self.held_by.__dict__.update(entity_state)
 | 
			
		||||
        entity.__dict__.update(player_state)
 | 
			
		||||
        self.held_by.map.currenty, self.held_by.map.currentx = self.held_by.y,\
 | 
			
		||||
            self.held_by.x
 | 
			
		||||
 | 
			
		||||
        self.held_by.map.logs.add_message(
 | 
			
		||||
            _("{player} exchanged its body with {entity}.").format(
 | 
			
		||||
                player=self.held_by.translated_name.capitalize(),
 | 
			
		||||
                entity=entity.translated_name))
 | 
			
		||||
 | 
			
		||||
        self.held_by.recalculate_paths()
 | 
			
		||||
 | 
			
		||||
        self.held_by.inventory.remove(self)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from random import choice
 | 
			
		||||
from random import shuffle
 | 
			
		||||
 | 
			
		||||
from .player import Player
 | 
			
		||||
from ..interfaces import FightingEntity, Map
 | 
			
		||||
@@ -49,9 +49,13 @@ class Monster(FightingEntity):
 | 
			
		||||
            if not moved and self.distance_squared(target) <= 1:
 | 
			
		||||
                self.map.logs.add_message(self.hit(target))
 | 
			
		||||
        else:
 | 
			
		||||
            for _ in range(100):
 | 
			
		||||
                if choice([self.move_up, self.move_down,
 | 
			
		||||
                          self.move_left, self.move_right])():
 | 
			
		||||
            # Move in a random direction
 | 
			
		||||
            # If the direction is not available, try another one
 | 
			
		||||
            moves = [self.move_up, self.move_down,
 | 
			
		||||
                     self.move_left, self.move_right]
 | 
			
		||||
            shuffle(moves)
 | 
			
		||||
            for move in moves:
 | 
			
		||||
                if move():
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -59,9 +63,9 @@ class Tiger(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A tiger monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 2, maxhealth: int = 20,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="tiger", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "tiger", strength: int = 2,
 | 
			
		||||
                 maxhealth: int = 20, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -69,9 +73,9 @@ class Hedgehog(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A really mean hedgehog monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 3, maxhealth: int = 10,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="hedgehog", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "hedgehog", strength: int = 3,
 | 
			
		||||
                 maxhealth: int = 10, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -79,9 +83,9 @@ class Rabbit(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A rabbit monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 1, maxhealth: int = 15,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="rabbit", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "rabbit", strength: int = 1,
 | 
			
		||||
                 maxhealth: int = 15, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -89,7 +93,7 @@ class TeddyBear(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A cute teddybear monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 0, maxhealth: int = 50,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="teddy_bear", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "teddy_bear", strength: int = 0,
 | 
			
		||||
                 maxhealth: int = 50, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,17 +17,24 @@ class Player(FightingEntity):
 | 
			
		||||
    paths: Dict[Tuple[int, int], Tuple[int, int]]
 | 
			
		||||
    hazel: int #It is the currency of this game
 | 
			
		||||
 | 
			
		||||
    def __init__(self, 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, hazel: int = 42, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="player", maxhealth=maxhealth, strength=strength,
 | 
			
		||||
    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) \
 | 
			
		||||
            -> None:
 | 
			
		||||
        super().__init__(name=name, maxhealth=maxhealth, strength=strength,
 | 
			
		||||
                         intelligence=intelligence, charisma=charisma,
 | 
			
		||||
                         dexterity=dexterity, constitution=constitution,
 | 
			
		||||
                         level=level, *args, **kwargs)
 | 
			
		||||
        self.current_xp = current_xp
 | 
			
		||||
        self.max_xp = max_xp
 | 
			
		||||
        self.inventory = list()
 | 
			
		||||
        self.inventory = inventory if inventory else list()
 | 
			
		||||
        for i in range(len(self.inventory)):
 | 
			
		||||
            if isinstance(self.inventory[i], dict):
 | 
			
		||||
                entity_classes = self.get_all_entity_classes_in_a_dict()
 | 
			
		||||
                item_class = entity_classes[self.inventory[i]["type"]]
 | 
			
		||||
                self.inventory[i] = item_class(**self.inventory[i])
 | 
			
		||||
        self.paths = dict()
 | 
			
		||||
        self.hazel = hazel
 | 
			
		||||
 | 
			
		||||
@@ -130,4 +137,5 @@ class Player(FightingEntity):
 | 
			
		||||
        d = super().save_state()
 | 
			
		||||
        d["current_xp"] = self.current_xp
 | 
			
		||||
        d["max_xp"] = self.max_xp
 | 
			
		||||
        d["inventory"] = [item.save_state() for item in self.inventory]
 | 
			
		||||
        return d
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,10 @@ class KeyValues(Enum):
 | 
			
		||||
    LEFT = auto()
 | 
			
		||||
    RIGHT = auto()
 | 
			
		||||
    ENTER = auto()
 | 
			
		||||
    INVENTORY = auto()
 | 
			
		||||
    USE = auto()
 | 
			
		||||
    EQUIP = auto()
 | 
			
		||||
    DROP = auto()
 | 
			
		||||
    SPACE = auto()
 | 
			
		||||
    T = auto()
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +64,14 @@ class KeyValues(Enum):
 | 
			
		||||
            return KeyValues.UP
 | 
			
		||||
        elif key == settings.KEY_ENTER:
 | 
			
		||||
            return KeyValues.ENTER
 | 
			
		||||
        elif key == settings.KEY_INVENTORY:
 | 
			
		||||
            return KeyValues.INVENTORY
 | 
			
		||||
        elif key == settings.KEY_USE:
 | 
			
		||||
            return KeyValues.USE
 | 
			
		||||
        elif key == settings.KEY_EQUIP:
 | 
			
		||||
            return KeyValues.EQUIP
 | 
			
		||||
        elif key == settings.KEY_DROP:
 | 
			
		||||
            return KeyValues.DROP
 | 
			
		||||
        elif key == ' ':
 | 
			
		||||
            return KeyValues.SPACE
 | 
			
		||||
        elif key == 't':
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ class Game:
 | 
			
		||||
        self.main_menu = menus.MainMenu()
 | 
			
		||||
        self.settings_menu = menus.SettingsMenu()
 | 
			
		||||
        self.settings_menu.update_values(self.settings)
 | 
			
		||||
        self.inventory_menu = menus.InventoryMenu()
 | 
			
		||||
        self.logs = Logs()
 | 
			
		||||
        self.message = None
 | 
			
		||||
 | 
			
		||||
@@ -48,13 +49,14 @@ class Game:
 | 
			
		||||
        Create a new game on the screen.
 | 
			
		||||
        """
 | 
			
		||||
        # TODO generate a new map procedurally
 | 
			
		||||
        self.map = Map.load(ResourceManager.get_asset_path("example_map_2.txt"))
 | 
			
		||||
        self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
 | 
			
		||||
        self.map.logs = self.logs
 | 
			
		||||
        self.logs.clear()
 | 
			
		||||
        self.player = Player()
 | 
			
		||||
        self.map.add_entity(self.player)
 | 
			
		||||
        self.player.move(self.map.start_y, self.map.start_x)
 | 
			
		||||
        self.map.spawn_random_entities(randint(3, 10))
 | 
			
		||||
        self.inventory_menu.update_player(self.player)
 | 
			
		||||
 | 
			
		||||
    def run(self, screen: Any) -> None:
 | 
			
		||||
        """
 | 
			
		||||
@@ -84,6 +86,8 @@ class Game:
 | 
			
		||||
 | 
			
		||||
        if self.state == GameMode.PLAY:
 | 
			
		||||
            self.handle_key_pressed_play(key)
 | 
			
		||||
        elif self.state == GameMode.INVENTORY:
 | 
			
		||||
            self.handle_key_pressed_inventory(key)
 | 
			
		||||
        elif self.state == GameMode.MAINMENU:
 | 
			
		||||
            self.handle_key_pressed_main_menu(key)
 | 
			
		||||
        elif self.state == GameMode.SETTINGS:
 | 
			
		||||
@@ -106,6 +110,8 @@ class Game:
 | 
			
		||||
        elif key == KeyValues.RIGHT:
 | 
			
		||||
            if self.player.move_right():
 | 
			
		||||
                self.map.tick()
 | 
			
		||||
        elif key == KeyValues.INVENTORY:
 | 
			
		||||
            self.state = GameMode.INVENTORY
 | 
			
		||||
        elif key == KeyValues.SPACE:
 | 
			
		||||
            self.state = GameMode.MAINMENU
 | 
			
		||||
        elif key == KeyValues.T :
 | 
			
		||||
@@ -134,6 +140,29 @@ class Game:
 | 
			
		||||
                            self.state = GameMode.STORE
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
    def handle_key_pressed_inventory(self, key: KeyValues) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        In the inventory menu, we can interact with items or close the menu.
 | 
			
		||||
        """
 | 
			
		||||
        if key == KeyValues.SPACE or key == KeyValues.INVENTORY:
 | 
			
		||||
            self.state = GameMode.PLAY
 | 
			
		||||
        elif key == KeyValues.UP:
 | 
			
		||||
            self.inventory_menu.go_up()
 | 
			
		||||
        elif key == KeyValues.DOWN:
 | 
			
		||||
            self.inventory_menu.go_down()
 | 
			
		||||
        if self.inventory_menu.values and not self.player.dead:
 | 
			
		||||
            if key == KeyValues.USE:
 | 
			
		||||
                self.inventory_menu.validate().use()
 | 
			
		||||
            elif key == KeyValues.EQUIP:
 | 
			
		||||
                self.inventory_menu.validate().equip()
 | 
			
		||||
            elif key == KeyValues.DROP:
 | 
			
		||||
                self.inventory_menu.validate().drop()
 | 
			
		||||
 | 
			
		||||
            # Ensure that the cursor has a good position
 | 
			
		||||
            self.inventory_menu.position = min(self.inventory_menu.position,
 | 
			
		||||
                                               len(self.inventory_menu.values)
 | 
			
		||||
                                               - 1)
 | 
			
		||||
 | 
			
		||||
    def handle_key_pressed_main_menu(self, key: KeyValues) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        In the main menu, we can navigate through options.
 | 
			
		||||
 
 | 
			
		||||
@@ -344,11 +344,11 @@ class Entity:
 | 
			
		||||
        """
 | 
			
		||||
        Returns all entities subclasses
 | 
			
		||||
        """
 | 
			
		||||
        from squirrelbattle.entities.items import Heart, Bomb
 | 
			
		||||
        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
 | 
			
		||||
        from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
 | 
			
		||||
            Rabbit, TeddyBear
 | 
			
		||||
        from squirrelbattle.entities.friendly import Merchant,Sunflower
 | 
			
		||||
        return [Tiger, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,Sunflower]
 | 
			
		||||
        return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,Sunflower,Tiger]
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_all_entity_classes_in_a_dict() -> dict:
 | 
			
		||||
@@ -358,12 +358,13 @@ class Entity:
 | 
			
		||||
        from squirrelbattle.entities.player import Player
 | 
			
		||||
        from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
 | 
			
		||||
            TeddyBear
 | 
			
		||||
        from squirrelbattle.entities.items import Bomb, Heart
 | 
			
		||||
        from squirrelbattle.entities.friendly import Merchant,Sunflower
 | 
			
		||||
        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
 | 
			
		||||
        return {
 | 
			
		||||
            "Tiger": Tiger,
 | 
			
		||||
            "Bomb": Bomb,
 | 
			
		||||
            "Heart": Heart,
 | 
			
		||||
            "BodySnatchPotion": BodySnatchPotion,
 | 
			
		||||
            "Hedgehog": Hedgehog,
 | 
			
		||||
            "Rabbit": Rabbit,
 | 
			
		||||
            "TeddyBear": TeddyBear,
 | 
			
		||||
@@ -447,7 +448,7 @@ class FightingEntity(Entity):
 | 
			
		||||
        """
 | 
			
		||||
        Returns a fighting entity's specific attributes
 | 
			
		||||
        """
 | 
			
		||||
        return ["maxhealth", "health", "level", "strength",
 | 
			
		||||
        return ["name", "maxhealth", "health", "level", "strength",
 | 
			
		||||
                "intelligence", "charisma", "dexterity", "constitution"]
 | 
			
		||||
 | 
			
		||||
    def save_state(self) -> dict:
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,11 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
"POT-Creation-Date: 2020-12-01 17:10+0100\n"
 | 
			
		||||
=======
 | 
			
		||||
"POT-Creation-Date: 2020-12-05 14:46+0100\n"
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
@@ -17,7 +21,75 @@ msgstr ""
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:284 squirrelbattle/tests/game_test.py:287
 | 
			
		||||
#: squirrelbattle/display/menudisplay.py:105
 | 
			
		||||
msgid "== INVENTORY =="
 | 
			
		||||
msgstr "== BESTAND =="
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
			
		||||
msgid "Inventory:"
 | 
			
		||||
msgstr "Bestand:"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:50
 | 
			
		||||
msgid "YOU ARE DEAD"
 | 
			
		||||
msgstr "SIE WURDEN GESTORBEN"
 | 
			
		||||
 | 
			
		||||
#. 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:128
 | 
			
		||||
msgid "Bomb is exploding."
 | 
			
		||||
msgstr "Die Bombe explodiert."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/entities/items.py:172
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{player} exchanged its body with {entity}."
 | 
			
		||||
msgstr "{player} täuscht seinem Körper mit {entity} aus."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/game.py:177
 | 
			
		||||
msgid ""
 | 
			
		||||
"Some keys are missing in your save file.\n"
 | 
			
		||||
"Your save seems to be corrupt. It got deleted."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"In Ihrer Speicherdatei fehlen einige Schlüssel.\n"
 | 
			
		||||
"Ihre Speicherung scheint korrupt zu sein. Es wird gelöscht."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/game.py:185
 | 
			
		||||
msgid ""
 | 
			
		||||
"No player was found on this map!\n"
 | 
			
		||||
"Maybe you died?"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Auf dieser Karte wurde kein Spieler gefunden!\n"
 | 
			
		||||
"Vielleicht sind Sie gestorben?"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/game.py:205
 | 
			
		||||
msgid ""
 | 
			
		||||
"The JSON file is not correct.\n"
 | 
			
		||||
"Your save seems corrupted. It got deleted."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Die JSON-Datei ist nicht korrekt.\n"
 | 
			
		||||
"Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/interfaces.py:400
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} hits {opponent}."
 | 
			
		||||
msgstr "{name} schlägt {opponent}."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/interfaces.py:412
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} takes {amount} damage."
 | 
			
		||||
msgstr "{name} nimmt {amount} Schadenspunkte."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/interfaces.py:414
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} dies."
 | 
			
		||||
msgstr "{name} stirbt."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:72
 | 
			
		||||
msgid "Back"
 | 
			
		||||
msgstr "Zurück"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:300 squirrelbattle/tests/game_test.py:303
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:306
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:16
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:290
 | 
			
		||||
msgid "New game"
 | 
			
		||||
@@ -80,40 +152,61 @@ msgid "Key to validate a menu"
 | 
			
		||||
msgstr "Menütaste"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:45
 | 
			
		||||
msgid "Key used to open the inventory"
 | 
			
		||||
msgstr "Bestandtaste"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:47
 | 
			
		||||
msgid "Key used to use an item in the inventory"
 | 
			
		||||
msgstr "Taste um eines Objekts im Bestand zu verwenden"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:49
 | 
			
		||||
msgid "Key used to equip an item in the inventory"
 | 
			
		||||
msgstr "Taste um eines Objekts im Bestand auszurüsten"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:51
 | 
			
		||||
msgid "Key used to drop an item in the inventory"
 | 
			
		||||
msgstr "Taste um eines Objekts im Bestand zu werfen"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:53
 | 
			
		||||
msgid "Texture pack"
 | 
			
		||||
msgstr "Textur-Packung"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:46
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:54
 | 
			
		||||
msgid "Language"
 | 
			
		||||
msgstr "Sprache"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:49
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:57
 | 
			
		||||
msgid "player"
 | 
			
		||||
msgstr "Spieler"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:51
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:59
 | 
			
		||||
msgid "tiger"
 | 
			
		||||
msgstr "Tiger"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:52
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:60
 | 
			
		||||
msgid "hedgehog"
 | 
			
		||||
msgstr "Igel"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:53
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:61
 | 
			
		||||
msgid "rabbit"
 | 
			
		||||
msgstr "Kanninchen"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:54
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:62
 | 
			
		||||
msgid "teddy bear"
 | 
			
		||||
msgstr "Teddybär"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:56
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:64
 | 
			
		||||
msgid "body snatch potion"
 | 
			
		||||
msgstr "Leichenfleddererzaubertrank"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:65
 | 
			
		||||
msgid "bomb"
 | 
			
		||||
msgstr "Bombe"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:57
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:66
 | 
			
		||||
msgid "heart"
 | 
			
		||||
msgstr "Herz"
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
			
		||||
msgid "Inventory:"
 | 
			
		||||
@@ -173,3 +266,5 @@ msgstr "Blumenmacht!!"
 | 
			
		||||
#: squirrelbattle/entities/friendly.py:31
 | 
			
		||||
msgid "The sun is warm today"
 | 
			
		||||
msgstr "Die Sonne ist warm heute"
 | 
			
		||||
=======
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,11 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
"POT-Creation-Date: 2020-12-01 17:10+0100\n"
 | 
			
		||||
=======
 | 
			
		||||
"POT-Creation-Date: 2020-12-05 14:46+0100\n"
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
@@ -17,63 +21,35 @@ msgstr ""
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/menudisplay.py:105
 | 
			
		||||
msgid "== INVENTORY =="
 | 
			
		||||
msgstr "== INVENTAIRE =="
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
			
		||||
msgid "Inventory:"
 | 
			
		||||
msgstr "Inventaire :"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:39
 | 
			
		||||
#: squirrelbattle/display/statsdisplay.py:50
 | 
			
		||||
msgid "YOU ARE DEAD"
 | 
			
		||||
msgstr "VOUS ÊTES MORT"
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
#: squirrelbattle/interfaces.py:394 squirrelbattle/interfaces.py:398
 | 
			
		||||
#: squirrelbattle/interfaces.py:408
 | 
			
		||||
=======
 | 
			
		||||
#. 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:128
 | 
			
		||||
msgid "Bomb is exploding."
 | 
			
		||||
msgstr "La bombe explose."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/entities/items.py:172
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} hits {opponent}."
 | 
			
		||||
msgstr "{name} frappe {opponent}."
 | 
			
		||||
msgid "{player} exchanged its body with {entity}."
 | 
			
		||||
msgstr "{player} a échangé son corps avec {entity}."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/interfaces.py:405 squirrelbattle/interfaces.py:410
 | 
			
		||||
#: squirrelbattle/interfaces.py:420
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} takes {amount} damage."
 | 
			
		||||
msgstr "{name} prend {amount} points de dégât."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:45 squirrelbattle/tests/translations_test.py:14
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:284 squirrelbattle/tests/game_test.py:287
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:16
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:290
 | 
			
		||||
msgid "New game"
 | 
			
		||||
msgstr "Nouvelle partie"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:46 squirrelbattle/tests/translations_test.py:15
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:17
 | 
			
		||||
msgid "Resume"
 | 
			
		||||
msgstr "Continuer"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:47 squirrelbattle/tests/translations_test.py:17
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:19
 | 
			
		||||
msgid "Save"
 | 
			
		||||
msgstr "Sauvegarder"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:48 squirrelbattle/tests/translations_test.py:16
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:18
 | 
			
		||||
msgid "Load"
 | 
			
		||||
msgstr "Charger"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:49 squirrelbattle/tests/translations_test.py:18
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:20
 | 
			
		||||
msgid "Settings"
 | 
			
		||||
msgstr "Paramètres"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:50 squirrelbattle/tests/translations_test.py:19
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:21
 | 
			
		||||
msgid "Exit"
 | 
			
		||||
msgstr "Quitter"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:71
 | 
			
		||||
msgid "Back"
 | 
			
		||||
msgstr "Retour"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/game.py:147 squirrelbattle/game.py:148
 | 
			
		||||
#: squirrelbattle/game.py:177
 | 
			
		||||
msgid ""
 | 
			
		||||
"Some keys are missing in your save file.\n"
 | 
			
		||||
"Your save seems to be corrupt. It got deleted."
 | 
			
		||||
@@ -81,7 +57,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:155 squirrelbattle/game.py:156
 | 
			
		||||
#: squirrelbattle/game.py:185
 | 
			
		||||
msgid ""
 | 
			
		||||
"No player was found on this map!\n"
 | 
			
		||||
"Maybe you died?"
 | 
			
		||||
@@ -89,7 +65,7 @@ msgstr ""
 | 
			
		||||
"Aucun joueur n'a été trouvé sur la carte !\n"
 | 
			
		||||
"Peut-être êtes-vous mort ?"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/game.py:175 squirrelbattle/game.py:176
 | 
			
		||||
#: squirrelbattle/game.py:205
 | 
			
		||||
msgid ""
 | 
			
		||||
"The JSON file is not correct.\n"
 | 
			
		||||
"Your save seems corrupted. It got deleted."
 | 
			
		||||
@@ -97,72 +73,119 @@ msgstr ""
 | 
			
		||||
"Le fichier JSON de sauvegarde est incorrect.\n"
 | 
			
		||||
"Votre sauvegarde semble corrompue. Elle a été supprimée."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:21 squirrelbattle/tests/translations_test.py:21
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:25
 | 
			
		||||
#: squirrelbattle/interfaces.py:400
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} hits {opponent}."
 | 
			
		||||
msgstr "{name} frappe {opponent}."
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
#: squirrelbattle/interfaces.py:405 squirrelbattle/interfaces.py:410
 | 
			
		||||
#: squirrelbattle/interfaces.py:420
 | 
			
		||||
=======
 | 
			
		||||
#: squirrelbattle/interfaces.py:412
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} takes {amount} damage."
 | 
			
		||||
msgstr "{name} prend {amount} points de dégât."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/interfaces.py:414
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "{name} dies."
 | 
			
		||||
msgstr "{name} meurt."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/menus.py:72
 | 
			
		||||
msgid "Back"
 | 
			
		||||
msgstr "Retour"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:300 squirrelbattle/tests/game_test.py:303
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:306
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:16
 | 
			
		||||
#: squirrelbattle/tests/game_test.py:290
 | 
			
		||||
msgid "New game"
 | 
			
		||||
msgstr "Nouvelle partie"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:17
 | 
			
		||||
msgid "Resume"
 | 
			
		||||
msgstr "Continuer"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:18
 | 
			
		||||
msgid "Load"
 | 
			
		||||
msgstr "Charger"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:19
 | 
			
		||||
msgid "Save"
 | 
			
		||||
msgstr "Sauvegarder"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:20
 | 
			
		||||
msgid "Settings"
 | 
			
		||||
msgstr "Paramètres"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:21
 | 
			
		||||
msgid "Exit"
 | 
			
		||||
msgstr "Quitter"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:27
 | 
			
		||||
msgid "Main key to move up"
 | 
			
		||||
msgstr "Touche principale pour aller vers le haut"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:22 squirrelbattle/tests/translations_test.py:23
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:27
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:29
 | 
			
		||||
msgid "Secondary key to move up"
 | 
			
		||||
msgstr "Touche secondaire pour aller vers le haut"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:23 squirrelbattle/tests/translations_test.py:25
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:29
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:31
 | 
			
		||||
msgid "Main key to move down"
 | 
			
		||||
msgstr "Touche principale pour aller vers le bas"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:24 squirrelbattle/tests/translations_test.py:27
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:31
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:33
 | 
			
		||||
msgid "Secondary key to move down"
 | 
			
		||||
msgstr "Touche secondaire pour aller vers le bas"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:25 squirrelbattle/tests/translations_test.py:29
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:33
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:35
 | 
			
		||||
msgid "Main key to move left"
 | 
			
		||||
msgstr "Touche principale pour aller vers la gauche"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:26 squirrelbattle/tests/translations_test.py:31
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:35
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:37
 | 
			
		||||
msgid "Secondary key to move left"
 | 
			
		||||
msgstr "Touche secondaire pour aller vers la gauche"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:27 squirrelbattle/tests/translations_test.py:33
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:37
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:39
 | 
			
		||||
msgid "Main key to move right"
 | 
			
		||||
msgstr "Touche principale pour aller vers la droite"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:29 squirrelbattle/tests/translations_test.py:35
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:39
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:41
 | 
			
		||||
msgid "Secondary key to move right"
 | 
			
		||||
msgstr "Touche secondaire pour aller vers la droite"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:30 squirrelbattle/tests/translations_test.py:37
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:41
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:43
 | 
			
		||||
msgid "Key to validate a menu"
 | 
			
		||||
msgstr "Touche pour valider un menu"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:31 squirrelbattle/tests/translations_test.py:39
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:43
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:45
 | 
			
		||||
msgid "Key used to open the inventory"
 | 
			
		||||
msgstr "Touche utilisée pour ouvrir l'inventaire"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:47
 | 
			
		||||
msgid "Key used to use an item in the inventory"
 | 
			
		||||
msgstr "Touche pour utiliser un objet de l'inventaire"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:49
 | 
			
		||||
msgid "Key used to equip an item in the inventory"
 | 
			
		||||
msgstr "Touche pour équiper un objet de l'inventaire"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:51
 | 
			
		||||
msgid "Key used to drop an item in the inventory"
 | 
			
		||||
msgstr "Touche pour jeter un objet de l'inventaire"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:53
 | 
			
		||||
msgid "Texture pack"
 | 
			
		||||
msgstr "Pack de textures"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/settings.py:32 squirrelbattle/tests/translations_test.py:40
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:44
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:46
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:54
 | 
			
		||||
msgid "Language"
 | 
			
		||||
msgstr "Langue"
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
#: squirrelbattle/interfaces.py:407 squirrelbattle/interfaces.py:412
 | 
			
		||||
#: squirrelbattle/interfaces.py:422
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
@@ -171,36 +194,37 @@ msgstr "{name} meurt."
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:47
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:49
 | 
			
		||||
=======
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:57
 | 
			
		||||
>>>>>>> master
 | 
			
		||||
msgid "player"
 | 
			
		||||
msgstr "joueur"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:49
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:51
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:59
 | 
			
		||||
msgid "tiger"
 | 
			
		||||
msgstr "tigre"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:50
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:52
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:60
 | 
			
		||||
msgid "hedgehog"
 | 
			
		||||
msgstr "hérisson"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:51
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:53
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:61
 | 
			
		||||
msgid "rabbit"
 | 
			
		||||
msgstr "lapin"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:52
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:54
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:62
 | 
			
		||||
msgid "teddy bear"
 | 
			
		||||
msgstr "nounours"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:54
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:56
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:64
 | 
			
		||||
msgid "body snatch potion"
 | 
			
		||||
msgstr "potion d'arrachage de corps"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:65
 | 
			
		||||
msgid "bomb"
 | 
			
		||||
msgstr "bombe"
 | 
			
		||||
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:55
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:57
 | 
			
		||||
#: squirrelbattle/tests/translations_test.py:66
 | 
			
		||||
msgid "heart"
 | 
			
		||||
msgstr "cœur"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ from enum import Enum
 | 
			
		||||
from typing import Any, Optional
 | 
			
		||||
 | 
			
		||||
from .display.texturepack import TexturePack
 | 
			
		||||
from .entities.player import Player
 | 
			
		||||
from .enums import GameMode, KeyValues, DisplayActions
 | 
			
		||||
from .settings import Settings
 | 
			
		||||
from .translations import gettext as _, Translator
 | 
			
		||||
@@ -115,3 +116,14 @@ class SettingsMenu(Menu):
 | 
			
		||||
            game.settings.write_settings()
 | 
			
		||||
            self.waiting_for_key = False
 | 
			
		||||
            self.update_values(game.settings)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InventoryMenu(Menu):
 | 
			
		||||
    player: Player
 | 
			
		||||
 | 
			
		||||
    def update_player(self, player: Player) -> None:
 | 
			
		||||
        self.player = player
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def values(self) -> list:
 | 
			
		||||
        return self.player.inventory
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,10 @@ class Settings:
 | 
			
		||||
        self.KEY_RIGHT_PRIMARY = ['d', 'Main key to move right']
 | 
			
		||||
        self.KEY_RIGHT_SECONDARY = ['KEY_RIGHT', 'Secondary key to move right']
 | 
			
		||||
        self.KEY_ENTER = ['\n', 'Key to validate a menu']
 | 
			
		||||
        self.KEY_INVENTORY = ['i', 'Key used to open the inventory']
 | 
			
		||||
        self.KEY_USE = ['u', 'Key used to use an item in the inventory']
 | 
			
		||||
        self.KEY_EQUIP = ['e', 'Key used to equip an item in the inventory']
 | 
			
		||||
        self.KEY_DROP = ['r', 'Key used to drop an item in the inventory']
 | 
			
		||||
        self.TEXTURE_PACK = ['ascii', 'Texture pack']
 | 
			
		||||
        self.LOCALE = [locale.getlocale()[0][:2], 'Language']
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.entities.items import Bomb, Heart, Item
 | 
			
		||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart, Item
 | 
			
		||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, TeddyBear
 | 
			
		||||
from squirrelbattle.entities.player import Player
 | 
			
		||||
from squirrelbattle.interfaces import Entity, Map
 | 
			
		||||
@@ -97,12 +97,13 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertFalse(item.held)
 | 
			
		||||
        item.hold(self.player)
 | 
			
		||||
        self.assertTrue(item.held)
 | 
			
		||||
        item.drop(2, 6)
 | 
			
		||||
        self.assertEqual(item.y, 2)
 | 
			
		||||
        item.drop()
 | 
			
		||||
        self.assertEqual(item.y, 1)
 | 
			
		||||
        self.assertEqual(item.x, 6)
 | 
			
		||||
 | 
			
		||||
        # Pick up item
 | 
			
		||||
        self.player.move_down()
 | 
			
		||||
        self.player.move_left()
 | 
			
		||||
        self.player.move_right()
 | 
			
		||||
        self.assertTrue(item.held)
 | 
			
		||||
        self.assertEqual(item.held_by, self.player)
 | 
			
		||||
        self.assertIn(item, self.player.inventory)
 | 
			
		||||
@@ -125,10 +126,14 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        item.act(self.map)
 | 
			
		||||
        self.assertFalse(hedgehog.dead)
 | 
			
		||||
        self.assertFalse(teddy_bear.dead)
 | 
			
		||||
        item.drop(42, 42)
 | 
			
		||||
        self.player.move(42, 42)
 | 
			
		||||
        item.hold(self.player)
 | 
			
		||||
        item.use()
 | 
			
		||||
        self.assertEqual(item.y, 42)
 | 
			
		||||
        self.assertEqual(item.x, 42)
 | 
			
		||||
        item.act(self.map)
 | 
			
		||||
        # Wait for the explosion
 | 
			
		||||
        for ignored in range(5):
 | 
			
		||||
            item.act(self.map)
 | 
			
		||||
        self.assertTrue(hedgehog.dead)
 | 
			
		||||
        self.assertTrue(teddy_bear.dead)
 | 
			
		||||
        bomb_state = item.save_state()
 | 
			
		||||
@@ -149,6 +154,24 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        heart_state = item.save_state()
 | 
			
		||||
        self.assertEqual(heart_state["healing"], item.healing)
 | 
			
		||||
 | 
			
		||||
    def test_body_snatch_potion(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with body snatch potions.
 | 
			
		||||
        """
 | 
			
		||||
        item = BodySnatchPotion()
 | 
			
		||||
        self.map.add_entity(item)
 | 
			
		||||
        item.hold(self.player)
 | 
			
		||||
 | 
			
		||||
        tiger = Tiger(y=42, x=42)
 | 
			
		||||
        self.map.add_entity(tiger)
 | 
			
		||||
 | 
			
		||||
        # The player becomes a tiger, and the tiger becomes a squirrel
 | 
			
		||||
        item.use()
 | 
			
		||||
        self.assertEqual(self.player.name, "tiger")
 | 
			
		||||
        self.assertEqual(tiger.name, "player")
 | 
			
		||||
        self.assertEqual(self.player.y, 42)
 | 
			
		||||
        self.assertEqual(self.player.x, 42)
 | 
			
		||||
 | 
			
		||||
    def test_players(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with players.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import unittest
 | 
			
		||||
from ..bootstrap import Bootstrap
 | 
			
		||||
from ..display.display import Display
 | 
			
		||||
from ..display.display_manager import DisplayManager
 | 
			
		||||
from ..entities.items import Bomb
 | 
			
		||||
from ..entities.player import Player
 | 
			
		||||
from ..enums import DisplayActions
 | 
			
		||||
from ..game import Game, KeyValues, GameMode
 | 
			
		||||
@@ -31,6 +32,9 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Save a game and reload it.
 | 
			
		||||
        """
 | 
			
		||||
        bomb = Bomb()
 | 
			
		||||
        self.game.map.add_entity(bomb)
 | 
			
		||||
        bomb.hold(self.game.player)
 | 
			
		||||
        old_state = self.game.save_state()
 | 
			
		||||
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
@@ -44,6 +48,9 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        new_state = self.game.save_state()
 | 
			
		||||
        self.assertEqual(old_state, new_state)
 | 
			
		||||
 | 
			
		||||
        # Ensure that the bomb is loaded
 | 
			
		||||
        self.assertTrue(self.game.player.inventory)
 | 
			
		||||
 | 
			
		||||
        # Error on loading save
 | 
			
		||||
        with open(ResourceManager.get_config_path("save.json"), "w") as f:
 | 
			
		||||
            f.write("I am not a JSON file")
 | 
			
		||||
@@ -107,6 +114,18 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_ENTER, self.game.settings),
 | 
			
		||||
            KeyValues.ENTER)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_INVENTORY, self.game.settings),
 | 
			
		||||
            KeyValues.INVENTORY)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_USE, self.game.settings),
 | 
			
		||||
            KeyValues.USE)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_EQUIP, self.game.settings),
 | 
			
		||||
            KeyValues.EQUIP)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_DROP, self.game.settings),
 | 
			
		||||
            KeyValues.DROP)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(' ', self.game.settings),
 | 
			
		||||
                         KeyValues.SPACE)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key('plop', self.game.settings),
 | 
			
		||||
@@ -261,11 +280,8 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a')
 | 
			
		||||
 | 
			
		||||
        # Navigate to "texture pack"
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        for ignored in range(9):
 | 
			
		||||
            self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
 | 
			
		||||
        # Change texture pack
 | 
			
		||||
        self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii")
 | 
			
		||||
@@ -337,3 +353,64 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.game.display_actions(DisplayActions.REFRESH)
 | 
			
		||||
        self.game.handle_key_pressed(None, "random key")
 | 
			
		||||
        self.assertIsNone(self.game.message)
 | 
			
		||||
 | 
			
		||||
    def test_inventory_menu(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Open the inventory menu and interact with items.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
        # Open and close the inventory
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.INVENTORY)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.SPACE)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.PLAY)
 | 
			
		||||
 | 
			
		||||
        # Add five bombs in the inventory
 | 
			
		||||
        for ignored in range(5):
 | 
			
		||||
            bomb = Bomb()
 | 
			
		||||
            bomb.map = self.game.map
 | 
			
		||||
            bomb.map.add_entity(bomb)
 | 
			
		||||
            bomb.hold(self.game.player)
 | 
			
		||||
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.INVENTORY)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
			
		||||
 | 
			
		||||
        # Navigate in the menu
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.position, 3)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.UP)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.position, 4)
 | 
			
		||||
 | 
			
		||||
        # Equip key does nothing
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.EQUIP)
 | 
			
		||||
 | 
			
		||||
        # Drop an item
 | 
			
		||||
        bomb = self.game.player.inventory[-1]
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.validate(), bomb)
 | 
			
		||||
        self.assertTrue(bomb.held)
 | 
			
		||||
        self.assertEqual(bomb.held_by, self.game.player)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DROP)
 | 
			
		||||
        self.assertFalse(bomb.held)
 | 
			
		||||
        self.assertIsNone(bomb.held_by)
 | 
			
		||||
        self.assertIsNone(bomb.owner)
 | 
			
		||||
        self.assertFalse(bomb.exploding)
 | 
			
		||||
        self.assertEqual(bomb.y, self.game.player.y)
 | 
			
		||||
        self.assertEqual(bomb.x, self.game.player.x)
 | 
			
		||||
 | 
			
		||||
        # Use the bomb
 | 
			
		||||
        bomb = self.game.player.inventory[-1]
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.validate(), bomb)
 | 
			
		||||
        self.assertTrue(bomb.held)
 | 
			
		||||
        self.assertEqual(bomb.held_by, self.game.player)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.USE)
 | 
			
		||||
        self.assertFalse(bomb.held)
 | 
			
		||||
        self.assertIsNone(bomb.held_by)
 | 
			
		||||
        self.assertEqual(bomb.owner, self.game.player)
 | 
			
		||||
        self.assertTrue(bomb.exploding)
 | 
			
		||||
        self.assertEqual(bomb.y, self.game.player.y)
 | 
			
		||||
        self.assertEqual(bomb.x, self.game.player.x)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,13 @@
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.settings import Settings
 | 
			
		||||
from squirrelbattle.translations import Translator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestSettings(unittest.TestCase):
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
        Translator.setlocale("en")
 | 
			
		||||
 | 
			
		||||
    def test_settings(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that settings are well loaded.
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,14 @@ class TestTranslations(unittest.TestCase):
 | 
			
		||||
                         "Touche secondaire pour aller vers la droite")
 | 
			
		||||
        self.assertEqual(_("Key to validate a menu"),
 | 
			
		||||
                         "Touche pour valider un menu")
 | 
			
		||||
        self.assertEqual(_("Key used to open the inventory"),
 | 
			
		||||
                         "Touche utilisée pour ouvrir l'inventaire")
 | 
			
		||||
        self.assertEqual(_("Key used to use an item in the inventory"),
 | 
			
		||||
                         "Touche pour utiliser un objet de l'inventaire")
 | 
			
		||||
        self.assertEqual(_("Key used to equip an item in the inventory"),
 | 
			
		||||
                         "Touche pour équiper un objet de l'inventaire")
 | 
			
		||||
        self.assertEqual(_("Key used to drop an item in the inventory"),
 | 
			
		||||
                         "Touche pour jeter un objet de l'inventaire")
 | 
			
		||||
        self.assertEqual(_("Texture pack"), "Pack de textures")
 | 
			
		||||
        self.assertEqual(_("Language"), "Langue")
 | 
			
		||||
 | 
			
		||||
@@ -53,5 +61,6 @@ class TestTranslations(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(_("rabbit"), "lapin")
 | 
			
		||||
        self.assertEqual(_("teddy bear"), "nounours")
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(_("body snatch potion"), "potion d'arrachage de corps")
 | 
			
		||||
        self.assertEqual(_("bomb"), "bombe")
 | 
			
		||||
        self.assertEqual(_("heart"), "cœur")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
import gettext as gt
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import subprocess
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from typing import Any, List
 | 
			
		||||
@@ -53,6 +54,9 @@ class Translator:
 | 
			
		||||
        Analyse all strings in the project and extract them.
 | 
			
		||||
        """
 | 
			
		||||
        for language in cls.SUPPORTED_LOCALES:
 | 
			
		||||
            if language == "en":
 | 
			
		||||
                # Don't translate the main language
 | 
			
		||||
                continue
 | 
			
		||||
            file_name = Path(__file__).parent / "locale" / language \
 | 
			
		||||
                / "LC_MESSAGES" / "squirrelbattle.po"
 | 
			
		||||
            args = ["find", "squirrelbattle", "-iname", "*.py"]
 | 
			
		||||
@@ -65,9 +69,14 @@ class Translator:
 | 
			
		||||
                    "--copyright-holder=ÿnérant, eichhornchen, "
 | 
			
		||||
                    "nicomarg, charlse",
 | 
			
		||||
                    "--msgid-bugs-address=squirrel-battle@crans.org",
 | 
			
		||||
                    "--sort-by-file",
 | 
			
		||||
                    "-o", file_name]
 | 
			
		||||
            if file_name.is_file():
 | 
			
		||||
                args.append("--join-existing")
 | 
			
		||||
                with open(file_name, "r") as f:
 | 
			
		||||
                    content = f.read()
 | 
			
		||||
                with open(file_name, "w") as f:
 | 
			
		||||
                    f.write(re.sub("#:.*\n", "", content))
 | 
			
		||||
            print(f"Make {language} messages...")
 | 
			
		||||
            subprocess.Popen(args, stdin=find.stdout).wait()
 | 
			
		||||
 | 
			
		||||
@@ -77,6 +86,8 @@ class Translator:
 | 
			
		||||
        Compile translation messages from source files.
 | 
			
		||||
        """
 | 
			
		||||
        for language in cls.SUPPORTED_LOCALES:
 | 
			
		||||
            if language == "en":
 | 
			
		||||
                continue
 | 
			
		||||
            args = ["msgfmt", "--check-format",
 | 
			
		||||
                    "-o", Path(__file__).parent / "locale" / language
 | 
			
		||||
                    / "LC_MESSAGES" / "squirrelbattle.mo",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user