Merge remote-tracking branch 'origin/master' into lighting
This commit is contained in:
		@@ -2,9 +2,10 @@
 | 
				
			|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
					# SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import curses
 | 
					import curses
 | 
				
			||||||
from typing import Any, Optional, Union
 | 
					from typing import Any, Optional, Tuple, Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from squirrelbattle.display.texturepack import TexturePack
 | 
					from squirrelbattle.display.texturepack import TexturePack
 | 
				
			||||||
 | 
					from squirrelbattle.game import Game
 | 
				
			||||||
from squirrelbattle.tests.screen import FakePad
 | 
					from squirrelbattle.tests.screen import FakePad
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,6 +16,9 @@ class Display:
 | 
				
			|||||||
    height: int
 | 
					    height: int
 | 
				
			||||||
    pad: Any
 | 
					    pad: Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _color_pairs = {(curses.COLOR_WHITE, curses.COLOR_BLACK): 0}
 | 
				
			||||||
 | 
					    _colors_rgb = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, screen: Any, pack: Optional[TexturePack] = None):
 | 
					    def __init__(self, screen: Any, pack: Optional[TexturePack] = None):
 | 
				
			||||||
        self.screen = screen
 | 
					        self.screen = screen
 | 
				
			||||||
        self.pack = pack or TexturePack.get_pack("ascii")
 | 
					        self.pack = pack or TexturePack.get_pack("ascii")
 | 
				
			||||||
@@ -30,15 +34,84 @@ class Display:
 | 
				
			|||||||
        lines = [line[:width] for line in lines]
 | 
					        lines = [line[:width] for line in lines]
 | 
				
			||||||
        return "\n".join(lines)
 | 
					        return "\n".join(lines)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def addstr(self, pad: Any, y: int, x: int, msg: str, *options) -> None:
 | 
					    def translate_color(self, color: Union[int, Tuple[int, int, int]]) -> int:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Translate a tuple (R, G, B) into a curses color index.
 | 
				
			||||||
 | 
					        If we have already a color index, then nothing is processed.
 | 
				
			||||||
 | 
					        If this is a tuple, we construct a new color index if non-existing
 | 
				
			||||||
 | 
					        and we return this index.
 | 
				
			||||||
 | 
					        The values of R, G and B must be between 0 and 1000, and not
 | 
				
			||||||
 | 
					        between 0 and 255.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if isinstance(color, tuple):
 | 
				
			||||||
 | 
					            # The color is a tuple (R, G, B), that is potentially unknown.
 | 
				
			||||||
 | 
					            # We translate it into a curses color number.
 | 
				
			||||||
 | 
					            if color not in self._colors_rgb:
 | 
				
			||||||
 | 
					                # The color does not exist, we create it.
 | 
				
			||||||
 | 
					                color_nb = len(self._colors_rgb) + 8
 | 
				
			||||||
 | 
					                self.init_color(color_nb, color[0], color[1], color[2])
 | 
				
			||||||
 | 
					                self._colors_rgb[color] = color_nb
 | 
				
			||||||
 | 
					            color = self._colors_rgb[color]
 | 
				
			||||||
 | 
					        return color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def addstr(self, pad: Any, y: int, x: int, msg: str,
 | 
				
			||||||
 | 
					               fg_color: Union[int, Tuple[int, int, int]] = curses.COLOR_WHITE,
 | 
				
			||||||
 | 
					               bg_color: Union[int, Tuple[int, int, int]] = curses.COLOR_BLACK,
 | 
				
			||||||
 | 
					               *, altcharset: bool = False, blink: bool = False,
 | 
				
			||||||
 | 
					               bold: bool = False, dim: bool = False, invis: bool = False,
 | 
				
			||||||
 | 
					               italic: bool = False, normal: bool = False,
 | 
				
			||||||
 | 
					               protect: bool = False, reverse: bool = False,
 | 
				
			||||||
 | 
					               standout: bool = False, underline: bool = False,
 | 
				
			||||||
 | 
					               horizontal: bool = False, left: bool = False,
 | 
				
			||||||
 | 
					               low: bool = False, right: bool = False, top: bool = False,
 | 
				
			||||||
 | 
					               vertical: bool = False, chartext: bool = False) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Display a message onto the pad.
 | 
					        Display a message onto the pad.
 | 
				
			||||||
        If the message is too large, it is truncated vertically and horizontally
 | 
					        If the message is too large, it is truncated vertically and horizontally
 | 
				
			||||||
 | 
					        The text can be bold, italic, blinking, ... if the good parameters are
 | 
				
			||||||
 | 
					        given. These parameters are translated into curses attributes.
 | 
				
			||||||
 | 
					        The foreground and background colors can be given as curses constants
 | 
				
			||||||
 | 
					        (curses.COLOR_*), or by giving a tuple (R, G, B) that corresponds to
 | 
				
			||||||
 | 
					        the color. R, G, B must be between 0 and 1000, and not 0 and 255.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        height, width = pad.getmaxyx()
 | 
					        height, width = pad.getmaxyx()
 | 
				
			||||||
 | 
					        # Truncate message if it is too large
 | 
				
			||||||
        msg = self.truncate(msg, height - y, width - x - 1)
 | 
					        msg = self.truncate(msg, height - y, width - x - 1)
 | 
				
			||||||
        if msg.replace("\n", "") and x >= 0 and y >= 0:
 | 
					        if msg.replace("\n", "") and x >= 0 and y >= 0:
 | 
				
			||||||
            return pad.addstr(y, x, msg, *options)
 | 
					            fg_color = self.translate_color(fg_color)
 | 
				
			||||||
 | 
					            bg_color = self.translate_color(bg_color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Get the pair number for the tuple (fg, bg)
 | 
				
			||||||
 | 
					            # If it does not exist, create it and give a new unique id.
 | 
				
			||||||
 | 
					            if (fg_color, bg_color) in self._color_pairs:
 | 
				
			||||||
 | 
					                pair_nb = self._color_pairs[(fg_color, bg_color)]
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                pair_nb = len(self._color_pairs)
 | 
				
			||||||
 | 
					                self.init_pair(pair_nb, fg_color, bg_color)
 | 
				
			||||||
 | 
					                self._color_pairs[(fg_color, bg_color)] = pair_nb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Compute curses attributes from the parameters
 | 
				
			||||||
 | 
					            attr = self.color_pair(pair_nb)
 | 
				
			||||||
 | 
					            attr |= curses.A_ALTCHARSET if altcharset else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_BLINK if blink else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_BOLD if bold else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_DIM if dim else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_INVIS if invis else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_ITALIC if italic else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_NORMAL if normal else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_PROTECT if protect else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_REVERSE if reverse else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_STANDOUT if standout else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_UNDERLINE if underline else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_HORIZONTAL if horizontal else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_LEFT if left else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_LOW if low else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_RIGHT if right else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_TOP if top else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_VERTICAL if vertical else 0
 | 
				
			||||||
 | 
					            attr |= curses.A_CHARTEXT if chartext else 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return pad.addstr(y, x, msg, attr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init_pair(self, number: int, foreground: int, background: int) -> None:
 | 
					    def init_pair(self, number: int, foreground: int, background: int) -> None:
 | 
				
			||||||
        return curses.init_pair(number, foreground, background) \
 | 
					        return curses.init_pair(number, foreground, background) \
 | 
				
			||||||
@@ -47,6 +120,10 @@ class Display:
 | 
				
			|||||||
    def color_pair(self, number: int) -> int:
 | 
					    def color_pair(self, number: int) -> int:
 | 
				
			||||||
        return curses.color_pair(number) if self.screen else 0
 | 
					        return curses.color_pair(number) if self.screen else 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def init_color(self, number: int, red: int, green: int, blue: int) -> None:
 | 
				
			||||||
 | 
					        return curses.init_color(number, red, green, blue) \
 | 
				
			||||||
 | 
					            if self.screen else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resize(self, y: int, x: int, height: int, width: int,
 | 
					    def resize(self, y: int, x: int, height: int, width: int,
 | 
				
			||||||
               resize_pad: bool = True) -> None:
 | 
					               resize_pad: bool = True) -> None:
 | 
				
			||||||
        self.x = x
 | 
					        self.x = x
 | 
				
			||||||
@@ -55,6 +132,7 @@ class Display:
 | 
				
			|||||||
        self.height = height
 | 
					        self.height = height
 | 
				
			||||||
        if hasattr(self, "pad") and resize_pad and \
 | 
					        if hasattr(self, "pad") and resize_pad and \
 | 
				
			||||||
                self.height >= 0 and self.width >= 0:
 | 
					                self.height >= 0 and self.width >= 0:
 | 
				
			||||||
 | 
					            self.pad.erase()
 | 
				
			||||||
            self.pad.resize(self.height + 1, self.width + 1)
 | 
					            self.pad.resize(self.height + 1, self.width + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def refresh(self, *args, resize_pad: bool = True) -> None:
 | 
					    def refresh(self, *args, resize_pad: bool = True) -> None:
 | 
				
			||||||
@@ -86,6 +164,13 @@ class Display:
 | 
				
			|||||||
    def display(self) -> None:
 | 
					    def display(self) -> None:
 | 
				
			||||||
        raise NotImplementedError
 | 
					        raise NotImplementedError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_click(self, y: int, x: int, game: Game) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        A mouse click was performed on the coordinates (y, x) of the pad.
 | 
				
			||||||
 | 
					        Maybe it can do something.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def rows(self) -> int:
 | 
					    def rows(self) -> int:
 | 
				
			||||||
        return curses.LINES if self.screen else 42
 | 
					        return curses.LINES if self.screen else 42
 | 
				
			||||||
@@ -138,23 +223,29 @@ class HorizontalSplit(Display):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Box(Display):
 | 
					class Box(Display):
 | 
				
			||||||
 | 
					    title: str = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_title(self, title: str) -> None:
 | 
				
			||||||
 | 
					        self.title = title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, fg_border_color: Optional[int] = None, **kwargs):
 | 
					    def __init__(self, *args, fg_border_color: Optional[int] = None, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
        self.pad = self.newpad(self.rows, self.cols)
 | 
					        self.pad = self.newpad(self.rows, self.cols)
 | 
				
			||||||
        self.fg_border_color = fg_border_color or curses.COLOR_WHITE
 | 
					        self.fg_border_color = fg_border_color or curses.COLOR_WHITE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pair_number = 4 + self.fg_border_color
 | 
					 | 
				
			||||||
        self.init_pair(pair_number, self.fg_border_color, curses.COLOR_BLACK)
 | 
					 | 
				
			||||||
        self.pair = self.color_pair(pair_number)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def display(self) -> None:
 | 
					    def display(self) -> None:
 | 
				
			||||||
        self.addstr(self.pad, 0, 0, "┏" + "━" * (self.width - 2) + "┓",
 | 
					        self.addstr(self.pad, 0, 0, "┏" + "━" * (self.width - 2) + "┓",
 | 
				
			||||||
                    self.pair)
 | 
					                    self.fg_border_color)
 | 
				
			||||||
        for i in range(1, self.height - 1):
 | 
					        for i in range(1, self.height - 1):
 | 
				
			||||||
            self.addstr(self.pad, i, 0, "┃", self.pair)
 | 
					            self.addstr(self.pad, i, 0, "┃", self.fg_border_color)
 | 
				
			||||||
            self.addstr(self.pad, i, self.width - 1, "┃", self.pair)
 | 
					            self.addstr(self.pad, i, self.width - 1, "┃", self.fg_border_color)
 | 
				
			||||||
        self.addstr(self.pad, self.height - 1, 0,
 | 
					        self.addstr(self.pad, self.height - 1, 0,
 | 
				
			||||||
                    "┗" + "━" * (self.width - 2) + "┛", self.pair)
 | 
					                    "┗" + "━" * (self.width - 2) + "┛", self.fg_border_color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.title:
 | 
				
			||||||
 | 
					            self.addstr(self.pad, 0, (self.width - len(self.title) - 8) // 2,
 | 
				
			||||||
 | 
					                        f" == {self.title} == ", curses.COLOR_GREEN,
 | 
				
			||||||
 | 
					                        italic=True, bold=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
					        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
				
			||||||
                         self.y + self.height - 1, self.x + self.width - 1)
 | 
					                         self.y + self.height - 1, self.x + self.width - 1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,15 +2,16 @@
 | 
				
			|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
					# SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import curses
 | 
					import curses
 | 
				
			||||||
from squirrelbattle.display.display import VerticalSplit, HorizontalSplit
 | 
					from squirrelbattle.display.display import VerticalSplit, HorizontalSplit, \
 | 
				
			||||||
 | 
					    Display
 | 
				
			||||||
from squirrelbattle.display.mapdisplay import MapDisplay
 | 
					from squirrelbattle.display.mapdisplay import MapDisplay
 | 
				
			||||||
from squirrelbattle.display.messagedisplay import MessageDisplay
 | 
					from squirrelbattle.display.messagedisplay import MessageDisplay
 | 
				
			||||||
from squirrelbattle.display.statsdisplay import StatsDisplay
 | 
					from squirrelbattle.display.statsdisplay import StatsDisplay
 | 
				
			||||||
from squirrelbattle.display.menudisplay import MainMenuDisplay, \
 | 
					from squirrelbattle.display.menudisplay import MainMenuDisplay, \
 | 
				
			||||||
    InventoryDisplay, SettingsMenuDisplay
 | 
					    PlayerInventoryDisplay, StoreInventoryDisplay, SettingsMenuDisplay
 | 
				
			||||||
from squirrelbattle.display.logsdisplay import LogsDisplay
 | 
					from squirrelbattle.display.logsdisplay import LogsDisplay
 | 
				
			||||||
from squirrelbattle.display.texturepack import TexturePack
 | 
					from squirrelbattle.display.texturepack import TexturePack
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any, List
 | 
				
			||||||
from squirrelbattle.game import Game, GameMode
 | 
					from squirrelbattle.game import Game, GameMode
 | 
				
			||||||
from squirrelbattle.enums import DisplayActions
 | 
					from squirrelbattle.enums import DisplayActions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,7 +25,8 @@ class DisplayManager:
 | 
				
			|||||||
        self.mapdisplay = MapDisplay(screen, pack)
 | 
					        self.mapdisplay = MapDisplay(screen, pack)
 | 
				
			||||||
        self.statsdisplay = StatsDisplay(screen, pack)
 | 
					        self.statsdisplay = StatsDisplay(screen, pack)
 | 
				
			||||||
        self.logsdisplay = LogsDisplay(screen, pack)
 | 
					        self.logsdisplay = LogsDisplay(screen, pack)
 | 
				
			||||||
        self.inventorydisplay = InventoryDisplay(screen, pack)
 | 
					        self.playerinventorydisplay = PlayerInventoryDisplay(screen, pack)
 | 
				
			||||||
 | 
					        self.storeinventorydisplay = StoreInventoryDisplay(screen, pack)
 | 
				
			||||||
        self.mainmenudisplay = MainMenuDisplay(self.game.main_menu,
 | 
					        self.mainmenudisplay = MainMenuDisplay(self.game.main_menu,
 | 
				
			||||||
                                               screen, pack)
 | 
					                                               screen, pack)
 | 
				
			||||||
        self.settingsmenudisplay = SettingsMenuDisplay(screen, pack)
 | 
					        self.settingsmenudisplay = SettingsMenuDisplay(screen, pack)
 | 
				
			||||||
@@ -33,28 +35,50 @@ class DisplayManager:
 | 
				
			|||||||
        self.vbar = VerticalSplit(screen, pack)
 | 
					        self.vbar = VerticalSplit(screen, pack)
 | 
				
			||||||
        self.displays = [self.statsdisplay, self.mapdisplay,
 | 
					        self.displays = [self.statsdisplay, self.mapdisplay,
 | 
				
			||||||
                         self.mainmenudisplay, self.settingsmenudisplay,
 | 
					                         self.mainmenudisplay, self.settingsmenudisplay,
 | 
				
			||||||
                         self.logsdisplay, self.messagedisplay]
 | 
					                         self.logsdisplay, self.messagedisplay,
 | 
				
			||||||
 | 
					                         self.playerinventorydisplay,
 | 
				
			||||||
 | 
					                         self.storeinventorydisplay]
 | 
				
			||||||
        self.update_game_components()
 | 
					        self.update_game_components()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_display_action(self, action: DisplayActions) -> None:
 | 
					    def handle_display_action(self, action: DisplayActions, *params) -> None:
 | 
				
			||||||
        if action == DisplayActions.REFRESH:
 | 
					        if action == DisplayActions.REFRESH:
 | 
				
			||||||
            self.refresh()
 | 
					            self.refresh()
 | 
				
			||||||
        elif action == DisplayActions.UPDATE:
 | 
					        elif action == DisplayActions.UPDATE:
 | 
				
			||||||
            self.update_game_components()
 | 
					            self.update_game_components()
 | 
				
			||||||
 | 
					        elif action == DisplayActions.MOUSE:
 | 
				
			||||||
 | 
					            self.handle_mouse_click(*params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_game_components(self) -> None:
 | 
					    def update_game_components(self) -> None:
 | 
				
			||||||
        for d in self.displays:
 | 
					        for d in self.displays:
 | 
				
			||||||
            d.pack = TexturePack.get_pack(self.game.settings.TEXTURE_PACK)
 | 
					            d.pack = TexturePack.get_pack(self.game.settings.TEXTURE_PACK)
 | 
				
			||||||
        self.mapdisplay.update_map(self.game.map)
 | 
					        self.mapdisplay.update_map(self.game.map)
 | 
				
			||||||
        self.statsdisplay.update_player(self.game.player)
 | 
					        self.statsdisplay.update_player(self.game.player)
 | 
				
			||||||
        self.inventorydisplay.update_menu(self.game.inventory_menu)
 | 
					        self.game.inventory_menu.update_player(self.game.player)
 | 
				
			||||||
 | 
					        self.game.store_menu.update_merchant(self.game.player)
 | 
				
			||||||
 | 
					        self.playerinventorydisplay.update_menu(self.game.inventory_menu)
 | 
				
			||||||
 | 
					        self.storeinventorydisplay.update_menu(self.game.store_menu)
 | 
				
			||||||
        self.settingsmenudisplay.update_menu(self.game.settings_menu)
 | 
					        self.settingsmenudisplay.update_menu(self.game.settings_menu)
 | 
				
			||||||
        self.logsdisplay.update_logs(self.game.logs)
 | 
					        self.logsdisplay.update_logs(self.game.logs)
 | 
				
			||||||
        self.messagedisplay.update_message(self.game.message)
 | 
					        self.messagedisplay.update_message(self.game.message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def refresh(self) -> None:
 | 
					    def handle_mouse_click(self, y: int, x: int) -> None:
 | 
				
			||||||
 | 
					        displays = self.refresh()
 | 
				
			||||||
 | 
					        display = None
 | 
				
			||||||
 | 
					        for d in displays:
 | 
				
			||||||
 | 
					            top_y, top_x, height, width = d.y, d.x, d.height, d.width
 | 
				
			||||||
 | 
					            if top_y <= y < top_y + height and top_x <= x < top_x + width:
 | 
				
			||||||
 | 
					                # The click coordinates correspond to the coordinates
 | 
				
			||||||
 | 
					                # of that display
 | 
				
			||||||
 | 
					                display = d
 | 
				
			||||||
 | 
					        if display:
 | 
				
			||||||
 | 
					            display.handle_click(y - display.y, x - display.x, self.game)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def refresh(self) -> List[Display]:
 | 
				
			||||||
 | 
					        displays = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.game.state == GameMode.PLAY \
 | 
					        if self.game.state == GameMode.PLAY \
 | 
				
			||||||
                or self.game.state == GameMode.INVENTORY:
 | 
					                or self.game.state == GameMode.INVENTORY \
 | 
				
			||||||
 | 
					                or self.game.state == GameMode.STORE:
 | 
				
			||||||
            # The map pad has already the good size
 | 
					            # The map pad has already the good size
 | 
				
			||||||
            self.mapdisplay.refresh(0, 0, self.rows * 4 // 5,
 | 
					            self.mapdisplay.refresh(0, 0, self.rows * 4 // 5,
 | 
				
			||||||
                                    self.mapdisplay.pack.tile_width
 | 
					                                    self.mapdisplay.pack.tile_width
 | 
				
			||||||
@@ -67,15 +91,26 @@ class DisplayManager:
 | 
				
			|||||||
                                     self.rows // 5 - 1, self.cols * 4 // 5)
 | 
					                                     self.rows // 5 - 1, self.cols * 4 // 5)
 | 
				
			||||||
            self.hbar.refresh(self.rows * 4 // 5, 0, 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)
 | 
					            self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            displays += [self.mapdisplay, self.statsdisplay, self.logsdisplay,
 | 
				
			||||||
 | 
					                         self.hbar, self.vbar]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.game.state == GameMode.INVENTORY:
 | 
					            if self.game.state == GameMode.INVENTORY:
 | 
				
			||||||
                self.inventorydisplay.refresh(self.rows // 10,
 | 
					                self.playerinventorydisplay.refresh(
 | 
				
			||||||
                                              self.cols // 2,
 | 
					                    self.rows // 10, self.cols // 2,
 | 
				
			||||||
                                              8 * self.rows // 10,
 | 
					                    8 * self.rows // 10, 2 * self.cols // 5)
 | 
				
			||||||
                                              2 * self.cols // 5)
 | 
					                displays.append(self.playerinventorydisplay)
 | 
				
			||||||
 | 
					            elif self.game.state == GameMode.STORE:
 | 
				
			||||||
 | 
					                self.storeinventorydisplay.refresh(
 | 
				
			||||||
 | 
					                    self.rows // 10, self.cols // 2,
 | 
				
			||||||
 | 
					                    8 * self.rows // 10, 2 * self.cols // 5)
 | 
				
			||||||
 | 
					                displays.append(self.storeinventorydisplay)
 | 
				
			||||||
        elif self.game.state == GameMode.MAINMENU:
 | 
					        elif self.game.state == GameMode.MAINMENU:
 | 
				
			||||||
            self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
					            self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
				
			||||||
 | 
					            displays.append(self.mainmenudisplay)
 | 
				
			||||||
        elif self.game.state == GameMode.SETTINGS:
 | 
					        elif self.game.state == GameMode.SETTINGS:
 | 
				
			||||||
            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
					            self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
 | 
				
			||||||
 | 
					            displays.append(self.settingsmenudisplay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.game.message:
 | 
					        if self.game.message:
 | 
				
			||||||
            height, width = 0, 0
 | 
					            height, width = 0, 0
 | 
				
			||||||
@@ -84,9 +119,12 @@ class DisplayManager:
 | 
				
			|||||||
                width = max(width, len(line))
 | 
					                width = max(width, len(line))
 | 
				
			||||||
            y, x = (self.rows - height) // 2, (self.cols - width) // 2
 | 
					            y, x = (self.rows - height) // 2, (self.cols - width) // 2
 | 
				
			||||||
            self.messagedisplay.refresh(y, x, height, width)
 | 
					            self.messagedisplay.refresh(y, x, height, width)
 | 
				
			||||||
 | 
					            displays.append(self.messagedisplay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.resize_window()
 | 
					        self.resize_window()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return displays
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resize_window(self) -> bool:
 | 
					    def resize_window(self) -> bool:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        If the window got resized, ensure that the screen size got updated.
 | 
					        If the window got resized, ensure that the screen size got updated.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,15 +15,14 @@ class MapDisplay(Display):
 | 
				
			|||||||
        self.pad = self.newpad(m.height, self.pack.tile_width * m.width + 1)
 | 
					        self.pad = self.newpad(m.height, self.pack.tile_width * m.width + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_pad(self) -> None:
 | 
					    def update_pad(self) -> None:
 | 
				
			||||||
        self.init_pair(1, self.pack.tile_fg_color, self.pack.tile_bg_color)
 | 
					 | 
				
			||||||
        self.init_pair(2, self.pack.entity_fg_color, self.pack.entity_bg_color)
 | 
					 | 
				
			||||||
        self.addstr(self.pad, 0, 0, self.map.draw_string(self.pack),
 | 
					        self.addstr(self.pad, 0, 0, self.map.draw_string(self.pack),
 | 
				
			||||||
                    self.color_pair(1))
 | 
					                    self.pack.tile_fg_color, self.pack.tile_bg_color)
 | 
				
			||||||
        for e in self.map.entities:
 | 
					        for e in self.map.entities:
 | 
				
			||||||
            self.addstr(self.pad, e.y, self.pack.tile_width * e.x,
 | 
					            self.addstr(self.pad, e.y, self.pack.tile_width * e.x,
 | 
				
			||||||
                        self.pack[e.name.upper()], self.color_pair(2))
 | 
					                        self.pack[e.name.upper()],
 | 
				
			||||||
 | 
					                        self.pack.entity_fg_color, self.pack.entity_bg_color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Display Path map for deubg purposes
 | 
					        # Display Path map for debug purposes
 | 
				
			||||||
        # from squirrelbattle.entities.player import Player
 | 
					        # from squirrelbattle.entities.player import Player
 | 
				
			||||||
        # players = [ p for p in self.map.entities if isinstance(p,Player) ]
 | 
					        # players = [ p for p in self.map.entities if isinstance(p,Player) ]
 | 
				
			||||||
        # player = players[0] if len(players) > 0 else None
 | 
					        # player = players[0] if len(players) > 0 else None
 | 
				
			||||||
@@ -42,7 +41,8 @@ class MapDisplay(Display):
 | 
				
			|||||||
        #                 else:
 | 
					        #                 else:
 | 
				
			||||||
        #                     character = '←'
 | 
					        #                     character = '←'
 | 
				
			||||||
        #                 self.addstr(self.pad, y, self.pack.tile_width * x,
 | 
					        #                 self.addstr(self.pad, y, self.pack.tile_width * x,
 | 
				
			||||||
        #                     character, self.color_pair(1))
 | 
					        #                     character, self.pack.tile_fg_color,
 | 
				
			||||||
 | 
					        #                     self.pack.tile_bg_color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def display(self) -> None:
 | 
					    def display(self) -> None:
 | 
				
			||||||
        y, x = self.map.currenty, self.pack.tile_width * self.map.currentx
 | 
					        y, x = self.map.currenty, self.pack.tile_width * self.map.currentx
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,22 @@
 | 
				
			|||||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
					# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
				
			||||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
					# SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import curses
 | 
					import curses
 | 
				
			||||||
 | 
					from random import randint
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from squirrelbattle.menus import Menu, MainMenu
 | 
					from squirrelbattle.menus import Menu, MainMenu
 | 
				
			||||||
from .display import Display, Box
 | 
					from .display import Box, Display
 | 
				
			||||||
 | 
					from ..enums import KeyValues
 | 
				
			||||||
 | 
					from ..game import Game
 | 
				
			||||||
from ..resources import ResourceManager
 | 
					from ..resources import ResourceManager
 | 
				
			||||||
from ..translations import gettext as _
 | 
					from ..translations import gettext as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MenuDisplay(Display):
 | 
					class MenuDisplay(Display):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A class to display the menu objects
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    position: int
 | 
					    position: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
@@ -37,10 +44,17 @@ class MenuDisplay(Display):
 | 
				
			|||||||
        self.menubox.refresh(self.y, self.x, self.height, self.width)
 | 
					        self.menubox.refresh(self.y, self.x, self.height, self.width)
 | 
				
			||||||
        self.pad.erase()
 | 
					        self.pad.erase()
 | 
				
			||||||
        self.update_pad()
 | 
					        self.update_pad()
 | 
				
			||||||
        self.refresh_pad(self.pad, cornery, 0, self.y + 1, self.x + 2,
 | 
					        self.refresh_pad(self.pad, cornery, 0, self.y + 1, self.x + 1,
 | 
				
			||||||
                         self.height - 2 + self.y,
 | 
					                         self.height - 2 + self.y,
 | 
				
			||||||
                         self.width - 2 + self.x)
 | 
					                         self.width - 2 + self.x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_click(self, y: int, x: int, game: Game) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        We can select a menu item with the mouse.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.menu.position = max(0, min(len(self.menu.values) - 1, y - 1))
 | 
				
			||||||
 | 
					        game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def truewidth(self) -> int:
 | 
					    def truewidth(self) -> int:
 | 
				
			||||||
        return max([len(str(a)) for a in self.values])
 | 
					        return max([len(str(a)) for a in self.values])
 | 
				
			||||||
@@ -63,6 +77,9 @@ class MenuDisplay(Display):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SettingsMenuDisplay(MenuDisplay):
 | 
					class SettingsMenuDisplay(MenuDisplay):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A class to display specifically a settingsmenu object
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def values(self) -> List[str]:
 | 
					    def values(self) -> List[str]:
 | 
				
			||||||
        return [_(a[1][1]) + (" : "
 | 
					        return [_(a[1][1]) + (" : "
 | 
				
			||||||
@@ -73,6 +90,9 @@ class SettingsMenuDisplay(MenuDisplay):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MainMenuDisplay(Display):
 | 
					class MainMenuDisplay(Display):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A class to display specifically a mainmenu object
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    def __init__(self, menu: MainMenu, *args):
 | 
					    def __init__(self, menu: MainMenu, *args):
 | 
				
			||||||
        super().__init__(*args)
 | 
					        super().__init__(*args)
 | 
				
			||||||
        self.menu = menu
 | 
					        self.menu = menu
 | 
				
			||||||
@@ -83,13 +103,16 @@ class MainMenuDisplay(Display):
 | 
				
			|||||||
        self.pad = self.newpad(max(self.rows, len(self.title) + 30),
 | 
					        self.pad = self.newpad(max(self.rows, len(self.title) + 30),
 | 
				
			||||||
                               max(len(self.title[0]) + 5, self.cols))
 | 
					                               max(len(self.title[0]) + 5, self.cols))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.fg_color = curses.COLOR_WHITE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.menudisplay = MenuDisplay(self.screen, self.pack)
 | 
					        self.menudisplay = MenuDisplay(self.screen, self.pack)
 | 
				
			||||||
        self.menudisplay.update_menu(self.menu)
 | 
					        self.menudisplay.update_menu(self.menu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def display(self) -> None:
 | 
					    def display(self) -> None:
 | 
				
			||||||
        for i in range(len(self.title)):
 | 
					        for i in range(len(self.title)):
 | 
				
			||||||
            self.addstr(self.pad, 4 + i, max(self.width // 2
 | 
					            self.addstr(self.pad, 4 + i, max(self.width // 2
 | 
				
			||||||
                        - len(self.title[0]) // 2 - 1, 0), self.title[i])
 | 
					                        - len(self.title[0]) // 2 - 1, 0), self.title[i],
 | 
				
			||||||
 | 
					                        self.fg_color)
 | 
				
			||||||
        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
					        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
				
			||||||
                         self.height + self.y - 1,
 | 
					                         self.height + self.y - 1,
 | 
				
			||||||
                         self.width + self.x - 1)
 | 
					                         self.width + self.x - 1)
 | 
				
			||||||
@@ -99,16 +122,25 @@ class MainMenuDisplay(Display):
 | 
				
			|||||||
            menuy, menux, min(self.menudisplay.preferred_height,
 | 
					            menuy, menux, min(self.menudisplay.preferred_height,
 | 
				
			||||||
                              self.height - menuy), menuwidth)
 | 
					                              self.height - menuy), menuwidth)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_click(self, y: int, x: int, game: Game) -> None:
 | 
				
			||||||
 | 
					        menuwidth = min(self.menudisplay.preferred_width, self.width)
 | 
				
			||||||
 | 
					        menuy, menux = len(self.title) + 8, self.width // 2 - menuwidth // 2 - 1
 | 
				
			||||||
 | 
					        menuheight = min(self.menudisplay.preferred_height, self.height - menuy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InventoryDisplay(MenuDisplay):
 | 
					        if menuy <= y < menuy + menuheight and menux <= x < menux + menuwidth:
 | 
				
			||||||
 | 
					            self.menudisplay.handle_click(y - menuy, x - menux, game)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if y <= len(self.title):
 | 
				
			||||||
 | 
					            self.fg_color = randint(0, 1000), randint(0, 1000), randint(0, 1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PlayerInventoryDisplay(MenuDisplay):
 | 
				
			||||||
    def update_pad(self) -> None:
 | 
					    def update_pad(self) -> None:
 | 
				
			||||||
        message = _("== INVENTORY ==")
 | 
					        self.menubox.update_title(_("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):
 | 
					        for i, item in enumerate(self.menu.values):
 | 
				
			||||||
            rep = self.pack[item.name.upper()]
 | 
					            rep = self.pack[item.name.upper()]
 | 
				
			||||||
            selection = f"[{rep}]" if i == self.menu.position else f" {rep} "
 | 
					            selection = f"[{rep}]" if i == self.menu.position else f" {rep} "
 | 
				
			||||||
            self.addstr(self.pad, 2 + i, 0, selection
 | 
					            self.addstr(self.pad, i + 1, 0, selection
 | 
				
			||||||
                        + " " + item.translated_name.capitalize())
 | 
					                        + " " + item.translated_name.capitalize())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
@@ -118,3 +150,36 @@ class InventoryDisplay(MenuDisplay):
 | 
				
			|||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def trueheight(self) -> int:
 | 
					    def trueheight(self) -> int:
 | 
				
			||||||
        return 2 + super().trueheight
 | 
					        return 2 + super().trueheight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_click(self, y: int, x: int, game: Game) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        We can select a menu item with the mouse.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2))
 | 
				
			||||||
 | 
					        game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StoreInventoryDisplay(MenuDisplay):
 | 
				
			||||||
 | 
					    def update_pad(self) -> None:
 | 
				
			||||||
 | 
					        self.menubox.update_title(_("STALL"))
 | 
				
			||||||
 | 
					        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, i + 1, 0, selection
 | 
				
			||||||
 | 
					                        + " " + item.translated_name.capitalize()
 | 
				
			||||||
 | 
					                        + ": " + str(item.price) + " Hazels")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def truewidth(self) -> int:
 | 
				
			||||||
 | 
					        return max(1, self.height if hasattr(self, "height") else 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def trueheight(self) -> int:
 | 
				
			||||||
 | 
					        return 2 + super().trueheight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_click(self, y: int, x: int, game: Game) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        We can select a menu item with the mouse.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2))
 | 
				
			||||||
 | 
					        game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,7 @@ class MessageDisplay(Display):
 | 
				
			|||||||
                         self.height + 2, self.width + 4)
 | 
					                         self.height + 2, self.width + 4)
 | 
				
			||||||
        self.box.display()
 | 
					        self.box.display()
 | 
				
			||||||
        self.pad.erase()
 | 
					        self.pad.erase()
 | 
				
			||||||
        self.addstr(self.pad, 0, 0, self.message, curses.A_BOLD)
 | 
					        self.addstr(self.pad, 0, 0, self.message, bold=True)
 | 
				
			||||||
        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
					        self.refresh_pad(self.pad, 0, 0, self.y, self.x,
 | 
				
			||||||
                         self.height + self.y - 1,
 | 
					                         self.height + self.y - 1,
 | 
				
			||||||
                         self.width + self.x - 1)
 | 
					                         self.width + self.x - 1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ class StatsDisplay(Display):
 | 
				
			|||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
        self.pad = self.newpad(self.rows, self.cols)
 | 
					        self.pad = self.newpad(self.rows, self.cols)
 | 
				
			||||||
        self.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_player(self, p: Player) -> None:
 | 
					    def update_player(self, p: Player) -> None:
 | 
				
			||||||
        self.player = p
 | 
					        self.player = p
 | 
				
			||||||
@@ -46,10 +45,12 @@ class StatsDisplay(Display):
 | 
				
			|||||||
            printed_items.append(item)
 | 
					            printed_items.append(item)
 | 
				
			||||||
        self.addstr(self.pad, 8, 0, inventory_str)
 | 
					        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.dead:
 | 
					        if self.player.dead:
 | 
				
			||||||
            self.addstr(self.pad, 10, 0, _("YOU ARE DEAD"),
 | 
					            self.addstr(self.pad, 11, 0, _("YOU ARE DEAD"), curses.COLOR_RED,
 | 
				
			||||||
                        curses.A_BOLD | curses.A_BLINK | curses.A_STANDOUT
 | 
					                        bold=True, blink=True, standout=True)
 | 
				
			||||||
                        | self.color_pair(3))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def display(self) -> None:
 | 
					    def display(self) -> None:
 | 
				
			||||||
        self.pad.erase()
 | 
					        self.pad.erase()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,10 +14,22 @@ class TexturePack:
 | 
				
			|||||||
    tile_bg_color: int
 | 
					    tile_bg_color: int
 | 
				
			||||||
    entity_fg_color: int
 | 
					    entity_fg_color: int
 | 
				
			||||||
    entity_bg_color: int
 | 
					    entity_bg_color: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BODY_SNATCH_POTION: str
 | 
				
			||||||
 | 
					    BOMB: str
 | 
				
			||||||
 | 
					    HEART: str
 | 
				
			||||||
 | 
					    HEDGEHOG: str
 | 
				
			||||||
    EMPTY: str
 | 
					    EMPTY: str
 | 
				
			||||||
    WALL: str
 | 
					 | 
				
			||||||
    FLOOR: str
 | 
					    FLOOR: str
 | 
				
			||||||
 | 
					    HAZELNUT: str
 | 
				
			||||||
 | 
					    MERCHANT: str
 | 
				
			||||||
    PLAYER: str
 | 
					    PLAYER: str
 | 
				
			||||||
 | 
					    RABBIT: str
 | 
				
			||||||
 | 
					    SUNFLOWER: str
 | 
				
			||||||
 | 
					    SWORD: str
 | 
				
			||||||
 | 
					    TEDDY_BEAR: str
 | 
				
			||||||
 | 
					    TIGER: str
 | 
				
			||||||
 | 
					    WALL: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ASCII_PACK: "TexturePack"
 | 
					    ASCII_PACK: "TexturePack"
 | 
				
			||||||
    SQUIRREL_PACK: "TexturePack"
 | 
					    SQUIRREL_PACK: "TexturePack"
 | 
				
			||||||
@@ -46,17 +58,23 @@ TexturePack.ASCII_PACK = TexturePack(
 | 
				
			|||||||
    tile_bg_color=curses.COLOR_BLACK,
 | 
					    tile_bg_color=curses.COLOR_BLACK,
 | 
				
			||||||
    entity_fg_color=curses.COLOR_WHITE,
 | 
					    entity_fg_color=curses.COLOR_WHITE,
 | 
				
			||||||
    entity_bg_color=curses.COLOR_BLACK,
 | 
					    entity_bg_color=curses.COLOR_BLACK,
 | 
				
			||||||
    EMPTY=' ',
 | 
					
 | 
				
			||||||
    WALL='#',
 | 
					 | 
				
			||||||
    FLOOR='.',
 | 
					 | 
				
			||||||
    PLAYER='@',
 | 
					 | 
				
			||||||
    HEDGEHOG='*',
 | 
					 | 
				
			||||||
    HEART='❤',
 | 
					 | 
				
			||||||
    BOMB='o',
 | 
					 | 
				
			||||||
    RABBIT='Y',
 | 
					 | 
				
			||||||
    TIGER='n',
 | 
					 | 
				
			||||||
    TEDDY_BEAR='8',
 | 
					 | 
				
			||||||
    BODY_SNATCH_POTION='S',
 | 
					    BODY_SNATCH_POTION='S',
 | 
				
			||||||
 | 
					    BOMB='o',
 | 
				
			||||||
 | 
					    EMPTY=' ',
 | 
				
			||||||
 | 
					    EXPLOSION='%',
 | 
				
			||||||
 | 
					    FLOOR='.',
 | 
				
			||||||
 | 
					    HAZELNUT='¤',
 | 
				
			||||||
 | 
					    HEART='❤',
 | 
				
			||||||
 | 
					    HEDGEHOG='*',
 | 
				
			||||||
 | 
					    MERCHANT='M',
 | 
				
			||||||
 | 
					    PLAYER='@',
 | 
				
			||||||
 | 
					    RABBIT='Y',
 | 
				
			||||||
 | 
					    SUNFLOWER='I',
 | 
				
			||||||
 | 
					    SWORD='\u2020',
 | 
				
			||||||
 | 
					    TEDDY_BEAR='8',
 | 
				
			||||||
 | 
					    TIGER='n',
 | 
				
			||||||
 | 
					    WALL='#',
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TexturePack.SQUIRREL_PACK = TexturePack(
 | 
					TexturePack.SQUIRREL_PACK = TexturePack(
 | 
				
			||||||
@@ -66,15 +84,21 @@ TexturePack.SQUIRREL_PACK = TexturePack(
 | 
				
			|||||||
    tile_bg_color=curses.COLOR_BLACK,
 | 
					    tile_bg_color=curses.COLOR_BLACK,
 | 
				
			||||||
    entity_fg_color=curses.COLOR_WHITE,
 | 
					    entity_fg_color=curses.COLOR_WHITE,
 | 
				
			||||||
    entity_bg_color=curses.COLOR_WHITE,
 | 
					    entity_bg_color=curses.COLOR_WHITE,
 | 
				
			||||||
    EMPTY='  ',
 | 
					
 | 
				
			||||||
    WALL='🧱',
 | 
					 | 
				
			||||||
    FLOOR='██',
 | 
					 | 
				
			||||||
    PLAYER='🐿️ ️',
 | 
					 | 
				
			||||||
    HEDGEHOG='🦔',
 | 
					 | 
				
			||||||
    HEART='💜',
 | 
					 | 
				
			||||||
    BOMB='💣',
 | 
					 | 
				
			||||||
    RABBIT='🐇',
 | 
					 | 
				
			||||||
    TIGER='🐅',
 | 
					 | 
				
			||||||
    TEDDY_BEAR='🧸',
 | 
					 | 
				
			||||||
    BODY_SNATCH_POTION='🔀',
 | 
					    BODY_SNATCH_POTION='🔀',
 | 
				
			||||||
 | 
					    BOMB='💣',
 | 
				
			||||||
 | 
					    EMPTY='  ',
 | 
				
			||||||
 | 
					    EXPLOSION='💥',
 | 
				
			||||||
 | 
					    FLOOR='██',
 | 
				
			||||||
 | 
					    HAZELNUT='🌰',
 | 
				
			||||||
 | 
					    HEART='💜',
 | 
				
			||||||
 | 
					    HEDGEHOG='🦔',
 | 
				
			||||||
 | 
					    PLAYER='🐿️ ️',
 | 
				
			||||||
 | 
					    MERCHANT='🦜',
 | 
				
			||||||
 | 
					    RABBIT='🐇',
 | 
				
			||||||
 | 
					    SUNFLOWER='🌻',
 | 
				
			||||||
 | 
					    SWORD='🗡️',
 | 
				
			||||||
 | 
					    TEDDY_BEAR='🧸',
 | 
				
			||||||
 | 
					    TIGER='🐅',
 | 
				
			||||||
 | 
					    WALL='🧱',
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								squirrelbattle/entities/friendly.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								squirrelbattle/entities/friendly.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					from ..interfaces import FriendlyEntity, InventoryHolder
 | 
				
			||||||
 | 
					from ..translations import gettext as _
 | 
				
			||||||
 | 
					from .player import Player
 | 
				
			||||||
 | 
					from .items import Item
 | 
				
			||||||
 | 
					from random import choice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Merchant(InventoryHolder, FriendlyEntity):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    The class for merchants in the dungeon
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def keys(self) -> list:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns a friendly entitie's specific attributes
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return super().keys() + ["inventory", "hazel"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, name: str = "merchant", inventory: list = None,
 | 
				
			||||||
 | 
					                 hazel: int = 75, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(name=name, *args, **kwargs)
 | 
				
			||||||
 | 
					        self.inventory = self.translate_inventory(inventory or [])
 | 
				
			||||||
 | 
					        self.hazel = hazel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not self.inventory:
 | 
				
			||||||
 | 
					            for i in range(5):
 | 
				
			||||||
 | 
					                self.inventory.append(choice(Item.get_all_items())())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def talk_to(self, player: Player) -> str:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function is used to open the merchant's inventory in a menu,
 | 
				
			||||||
 | 
					        and allow the player to buy/sell objects
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return _("I don't sell any squirrel")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def change_hazel_balance(self, hz: int) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Change the number of hazel the merchant has by hz.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.hazel += hz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Sunflower(FriendlyEntity):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A friendly sunflower
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, maxhealth: int = 15,
 | 
				
			||||||
 | 
					                 *args, **kwargs) -> None:
 | 
				
			||||||
 | 
					        super().__init__(name="sunflower", maxhealth=maxhealth, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def dialogue_option(self) -> list:
 | 
				
			||||||
 | 
					        return [_("Flower power!!"), _("The sun is warm today")]
 | 
				
			||||||
@@ -5,7 +5,7 @@ from random import choice, randint
 | 
				
			|||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .player import Player
 | 
					from .player import Player
 | 
				
			||||||
from ..interfaces import Entity, FightingEntity, Map
 | 
					from ..interfaces import Entity, FightingEntity, Map, InventoryHolder
 | 
				
			||||||
from ..translations import gettext as _
 | 
					from ..translations import gettext as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,13 +14,16 @@ class Item(Entity):
 | 
				
			|||||||
    A class for items
 | 
					    A class for items
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    held: bool
 | 
					    held: bool
 | 
				
			||||||
    held_by: Optional[Player]
 | 
					    held_by: Optional[InventoryHolder]
 | 
				
			||||||
 | 
					    price: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, held: bool = False, held_by: Optional[Player] = None,
 | 
					    def __init__(self, held: bool = False,
 | 
				
			||||||
                 *args, **kwargs):
 | 
					                 held_by: Optional[InventoryHolder] = None,
 | 
				
			||||||
 | 
					                 price: int = 2, *args, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
        self.held = held
 | 
					        self.held = held
 | 
				
			||||||
        self.held_by = held_by
 | 
					        self.held_by = held_by
 | 
				
			||||||
 | 
					        self.price = price
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def drop(self) -> None:
 | 
					    def drop(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -28,7 +31,7 @@ class Item(Entity):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        if self.held:
 | 
					        if self.held:
 | 
				
			||||||
            self.held_by.inventory.remove(self)
 | 
					            self.held_by.inventory.remove(self)
 | 
				
			||||||
            self.map.add_entity(self)
 | 
					            self.held_by.map.add_entity(self)
 | 
				
			||||||
            self.move(self.held_by.y, self.held_by.x)
 | 
					            self.move(self.held_by.y, self.held_by.x)
 | 
				
			||||||
            self.held = False
 | 
					            self.held = False
 | 
				
			||||||
            self.held_by = None
 | 
					            self.held_by = None
 | 
				
			||||||
@@ -43,14 +46,14 @@ class Item(Entity):
 | 
				
			|||||||
        Indicates what should be done when the item is equipped.
 | 
					        Indicates what should be done when the item is equipped.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hold(self, player: "Player") -> None:
 | 
					    def hold(self, player: InventoryHolder) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        The item is taken from the floor and put into the inventory
 | 
					        The item is taken from the floor and put into the inventory
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.held = True
 | 
					        self.held = True
 | 
				
			||||||
        self.held_by = player
 | 
					        self.held_by = player
 | 
				
			||||||
        self.map.remove_entity(self)
 | 
					        self.held_by.map.remove_entity(self)
 | 
				
			||||||
        player.inventory.append(self)
 | 
					        player.add_to_inventory(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save_state(self) -> dict:
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -60,6 +63,25 @@ class Item(Entity):
 | 
				
			|||||||
        d["held"] = self.held
 | 
					        d["held"] = self.held
 | 
				
			||||||
        return d
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_all_items() -> list:
 | 
				
			||||||
 | 
					        return [BodySnatchPotion, Bomb, Heart, Sword]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Does all necessary actions when an object is to be sold.
 | 
				
			||||||
 | 
					        Is overwritten by some classes that cannot exist in the player's
 | 
				
			||||||
 | 
					        inventory
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if buyer.hazel >= self.price:
 | 
				
			||||||
 | 
					            self.hold(buyer)
 | 
				
			||||||
 | 
					            seller.remove_from_inventory(self)
 | 
				
			||||||
 | 
					            buyer.change_hazel_balance(-self.price)
 | 
				
			||||||
 | 
					            seller.change_hazel_balance(self.price)
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Heart(Item):
 | 
					class Heart(Item):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
@@ -67,16 +89,17 @@ class Heart(Item):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    healing: int
 | 
					    healing: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, name: str = "heart", healing: int = 5, *args, **kwargs):
 | 
					    def __init__(self, name: str = "heart", healing: int = 5, price: int = 3,
 | 
				
			||||||
        super().__init__(name=name, *args, **kwargs)
 | 
					                 *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(name=name, price=price, *args, **kwargs)
 | 
				
			||||||
        self.healing = healing
 | 
					        self.healing = healing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hold(self, player: "Player") -> None:
 | 
					    def hold(self, entity: InventoryHolder) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        When holding a heart, heal the player and don't put item in inventory.
 | 
					        When holding a heart, heal the player and don't put item in inventory.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        player.health = min(player.maxhealth, player.health + self.healing)
 | 
					        entity.health = min(entity.maxhealth, entity.health + self.healing)
 | 
				
			||||||
        self.map.remove_entity(self)
 | 
					        entity.map.remove_entity(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save_state(self) -> dict:
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -97,8 +120,8 @@ class Bomb(Item):
 | 
				
			|||||||
    tick: int
 | 
					    tick: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, name: str = "bomb", damage: int = 5,
 | 
					    def __init__(self, name: str = "bomb", damage: int = 5,
 | 
				
			||||||
                 exploding: bool = False, *args, **kwargs):
 | 
					                 exploding: bool = False, price: int = 4, *args, **kwargs):
 | 
				
			||||||
        super().__init__(name=name, *args, **kwargs)
 | 
					        super().__init__(name=name, price=price, *args, **kwargs)
 | 
				
			||||||
        self.damage = damage
 | 
					        self.damage = damage
 | 
				
			||||||
        self.exploding = exploding
 | 
					        self.exploding = exploding
 | 
				
			||||||
        self.tick = 4
 | 
					        self.tick = 4
 | 
				
			||||||
@@ -135,6 +158,10 @@ class Bomb(Item):
 | 
				
			|||||||
                m.logs.add_message(log_message)
 | 
					                m.logs.add_message(log_message)
 | 
				
			||||||
                m.entities.remove(self)
 | 
					                m.entities.remove(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Add sparkles where the bomb exploded.
 | 
				
			||||||
 | 
					                explosion = Explosion(y=self.y, x=self.x)
 | 
				
			||||||
 | 
					                self.map.add_entity(explosion)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save_state(self) -> dict:
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Saves the state of the bomb into a dictionary
 | 
					        Saves the state of the bomb into a dictionary
 | 
				
			||||||
@@ -145,14 +172,63 @@ class Bomb(Item):
 | 
				
			|||||||
        return d
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Explosion(Item):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    When a bomb explodes, the explosion is displayed.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(name="explosion", *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def act(self, m: Map) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        The explosion instant dies.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        m.remove_entity(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hold(self, player: InventoryHolder) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        The player can't hold any explosion.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Weapon(Item):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Non-throwable items that improve player damage
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    damage: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, damage: int = 3, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.damage = damage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Saves the state of the weapon into a dictionary
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d = super().save_state()
 | 
				
			||||||
 | 
					        d["damage"] = self.damage
 | 
				
			||||||
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Sword(Weapon):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A basic weapon
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(name=name, price=price, *args, **kwargs)
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BodySnatchPotion(Item):
 | 
					class BodySnatchPotion(Item):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    The body-snatch potion allows to exchange all characteristics with a random
 | 
					    The body-snatch potion allows to exchange all characteristics with a random
 | 
				
			||||||
    other entity.
 | 
					    other entity.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, name: str = "body_snatch_potion", *args, **kwargs):
 | 
					    def __init__(self, name: str = "body_snatch_potion", price: int = 14,
 | 
				
			||||||
        super().__init__(name=name, *args, **kwargs)
 | 
					                 *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(name=name, price=price, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def use(self) -> None:
 | 
					    def use(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,23 +6,22 @@ from queue import PriorityQueue
 | 
				
			|||||||
from random import randint
 | 
					from random import randint
 | 
				
			||||||
from typing import Dict, Tuple
 | 
					from typing import Dict, Tuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ..interfaces import FightingEntity
 | 
					from ..interfaces import FightingEntity, InventoryHolder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Player(FightingEntity):
 | 
					class Player(InventoryHolder, FightingEntity):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    The class of the player
 | 
					    The class of the player
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    current_xp: int = 0
 | 
					    current_xp: int = 0
 | 
				
			||||||
    max_xp: int = 10
 | 
					    max_xp: int = 10
 | 
				
			||||||
    inventory: list
 | 
					 | 
				
			||||||
    paths: Dict[Tuple[int, int], Tuple[int, int]]
 | 
					    paths: Dict[Tuple[int, int], Tuple[int, int]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, name: str = "player", maxhealth: int = 20,
 | 
					    def __init__(self, name: str = "player", maxhealth: int = 20,
 | 
				
			||||||
                 strength: int = 5, intelligence: int = 1, charisma: int = 1,
 | 
					                 strength: int = 5, intelligence: int = 1, charisma: int = 1,
 | 
				
			||||||
                 dexterity: int = 1, constitution: int = 1, level: int = 1,
 | 
					                 dexterity: int = 1, constitution: int = 1, level: int = 1,
 | 
				
			||||||
                 current_xp: int = 0, max_xp: int = 10, inventory: list = None,
 | 
					                 current_xp: int = 0, max_xp: int = 10, inventory: list = None,
 | 
				
			||||||
                 *args, **kwargs) \
 | 
					                 hazel: int = 42, *args, **kwargs) \
 | 
				
			||||||
            -> None:
 | 
					            -> None:
 | 
				
			||||||
        super().__init__(name=name, maxhealth=maxhealth, strength=strength,
 | 
					        super().__init__(name=name, maxhealth=maxhealth, strength=strength,
 | 
				
			||||||
                         intelligence=intelligence, charisma=charisma,
 | 
					                         intelligence=intelligence, charisma=charisma,
 | 
				
			||||||
@@ -30,13 +29,9 @@ class Player(FightingEntity):
 | 
				
			|||||||
                         level=level, *args, **kwargs)
 | 
					                         level=level, *args, **kwargs)
 | 
				
			||||||
        self.current_xp = current_xp
 | 
					        self.current_xp = current_xp
 | 
				
			||||||
        self.max_xp = max_xp
 | 
					        self.max_xp = max_xp
 | 
				
			||||||
        self.inventory = inventory if inventory else list()
 | 
					        self.inventory = self.translate_inventory(inventory or [])
 | 
				
			||||||
        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.paths = dict()
 | 
				
			||||||
 | 
					        self.hazel = hazel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def move(self, y: int, x: int) -> None:
 | 
					    def move(self, y: int, x: int) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -149,5 +144,4 @@ class Player(FightingEntity):
 | 
				
			|||||||
        d = super().save_state()
 | 
					        d = super().save_state()
 | 
				
			||||||
        d["current_xp"] = self.current_xp
 | 
					        d["current_xp"] = self.current_xp
 | 
				
			||||||
        d["max_xp"] = self.max_xp
 | 
					        d["max_xp"] = self.max_xp
 | 
				
			||||||
        d["inventory"] = [item.save_state() for item in self.inventory]
 | 
					 | 
				
			||||||
        return d
 | 
					        return d
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ class DisplayActions(Enum):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    REFRESH = auto()
 | 
					    REFRESH = auto()
 | 
				
			||||||
    UPDATE = auto()
 | 
					    UPDATE = auto()
 | 
				
			||||||
 | 
					    MOUSE = auto()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GameMode(Enum):
 | 
					class GameMode(Enum):
 | 
				
			||||||
@@ -26,12 +27,14 @@ class GameMode(Enum):
 | 
				
			|||||||
    PLAY = auto()
 | 
					    PLAY = auto()
 | 
				
			||||||
    SETTINGS = auto()
 | 
					    SETTINGS = auto()
 | 
				
			||||||
    INVENTORY = auto()
 | 
					    INVENTORY = auto()
 | 
				
			||||||
 | 
					    STORE = auto()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class KeyValues(Enum):
 | 
					class KeyValues(Enum):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Key values options used in the game
 | 
					    Key values options used in the game
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    MOUSE = auto()
 | 
				
			||||||
    UP = auto()
 | 
					    UP = auto()
 | 
				
			||||||
    DOWN = auto()
 | 
					    DOWN = auto()
 | 
				
			||||||
    LEFT = auto()
 | 
					    LEFT = auto()
 | 
				
			||||||
@@ -42,6 +45,8 @@ class KeyValues(Enum):
 | 
				
			|||||||
    EQUIP = auto()
 | 
					    EQUIP = auto()
 | 
				
			||||||
    DROP = auto()
 | 
					    DROP = auto()
 | 
				
			||||||
    SPACE = auto()
 | 
					    SPACE = auto()
 | 
				
			||||||
 | 
					    CHAT = auto()
 | 
				
			||||||
 | 
					    WAIT = auto()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]:
 | 
					    def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]:
 | 
				
			||||||
@@ -72,4 +77,8 @@ class KeyValues(Enum):
 | 
				
			|||||||
            return KeyValues.DROP
 | 
					            return KeyValues.DROP
 | 
				
			||||||
        elif key == ' ':
 | 
					        elif key == ' ':
 | 
				
			||||||
            return KeyValues.SPACE
 | 
					            return KeyValues.SPACE
 | 
				
			||||||
 | 
					        elif key == settings.KEY_CHAT:
 | 
				
			||||||
 | 
					            return KeyValues.CHAT
 | 
				
			||||||
 | 
					        elif key == settings.KEY_WAIT:
 | 
				
			||||||
 | 
					            return KeyValues.WAIT
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
from json import JSONDecodeError
 | 
					from json import JSONDecodeError
 | 
				
			||||||
from random import randint
 | 
					from random import randint
 | 
				
			||||||
from typing import Any, Optional
 | 
					from typing import Any, Optional
 | 
				
			||||||
 | 
					import curses
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
@@ -15,7 +16,6 @@ from .resources import ResourceManager
 | 
				
			|||||||
from .settings import Settings
 | 
					from .settings import Settings
 | 
				
			||||||
from . import menus
 | 
					from . import menus
 | 
				
			||||||
from .translations import gettext as _, Translator
 | 
					from .translations import gettext as _, Translator
 | 
				
			||||||
from typing import Callable
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Game:
 | 
					class Game:
 | 
				
			||||||
@@ -24,14 +24,16 @@ class Game:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    map: Map
 | 
					    map: Map
 | 
				
			||||||
    player: Player
 | 
					    player: Player
 | 
				
			||||||
 | 
					    screen: Any
 | 
				
			||||||
    # display_actions is a display interface set by the bootstrapper
 | 
					    # display_actions is a display interface set by the bootstrapper
 | 
				
			||||||
    display_actions: Callable[[DisplayActions], None]
 | 
					    display_actions: callable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self) -> None:
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Init the game.
 | 
					        Init the game.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.state = GameMode.MAINMENU
 | 
					        self.state = GameMode.MAINMENU
 | 
				
			||||||
 | 
					        self.waiting_for_friendly_key = False
 | 
				
			||||||
        self.settings = Settings()
 | 
					        self.settings = Settings()
 | 
				
			||||||
        self.settings.load_settings()
 | 
					        self.settings.load_settings()
 | 
				
			||||||
        self.settings.write_settings()
 | 
					        self.settings.write_settings()
 | 
				
			||||||
@@ -40,6 +42,7 @@ class Game:
 | 
				
			|||||||
        self.settings_menu = menus.SettingsMenu()
 | 
					        self.settings_menu = menus.SettingsMenu()
 | 
				
			||||||
        self.settings_menu.update_values(self.settings)
 | 
					        self.settings_menu.update_values(self.settings)
 | 
				
			||||||
        self.inventory_menu = menus.InventoryMenu()
 | 
					        self.inventory_menu = menus.InventoryMenu()
 | 
				
			||||||
 | 
					        self.store_menu = menus.StoreMenu()
 | 
				
			||||||
        self.logs = Logs()
 | 
					        self.logs = Logs()
 | 
				
			||||||
        self.message = None
 | 
					        self.message = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,6 +71,10 @@ class Game:
 | 
				
			|||||||
            screen.refresh()
 | 
					            screen.refresh()
 | 
				
			||||||
            self.display_actions(DisplayActions.REFRESH)
 | 
					            self.display_actions(DisplayActions.REFRESH)
 | 
				
			||||||
            key = screen.getkey()
 | 
					            key = screen.getkey()
 | 
				
			||||||
 | 
					            if key == "KEY_MOUSE":
 | 
				
			||||||
 | 
					                _ignored1, x, y, _ignored2, _ignored3 = curses.getmouse()
 | 
				
			||||||
 | 
					                self.display_actions(DisplayActions.MOUSE, y, x)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
                self.handle_key_pressed(
 | 
					                self.handle_key_pressed(
 | 
				
			||||||
                    KeyValues.translate_key(key, self.settings), key)
 | 
					                    KeyValues.translate_key(key, self.settings), key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,6 +90,10 @@ class Game:
 | 
				
			|||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.state == GameMode.PLAY:
 | 
					        if self.state == GameMode.PLAY:
 | 
				
			||||||
 | 
					            if self.waiting_for_friendly_key:
 | 
				
			||||||
 | 
					                # The player requested to talk with a friendly entity
 | 
				
			||||||
 | 
					                self.handle_friendly_entity_chat(key)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
                self.handle_key_pressed_play(key)
 | 
					                self.handle_key_pressed_play(key)
 | 
				
			||||||
        elif self.state == GameMode.INVENTORY:
 | 
					        elif self.state == GameMode.INVENTORY:
 | 
				
			||||||
            self.handle_key_pressed_inventory(key)
 | 
					            self.handle_key_pressed_inventory(key)
 | 
				
			||||||
@@ -90,6 +101,8 @@ class Game:
 | 
				
			|||||||
            self.handle_key_pressed_main_menu(key)
 | 
					            self.handle_key_pressed_main_menu(key)
 | 
				
			||||||
        elif self.state == GameMode.SETTINGS:
 | 
					        elif self.state == GameMode.SETTINGS:
 | 
				
			||||||
            self.settings_menu.handle_key_pressed(key, raw_key, self)
 | 
					            self.settings_menu.handle_key_pressed(key, raw_key, self)
 | 
				
			||||||
 | 
					        elif self.state == GameMode.STORE:
 | 
				
			||||||
 | 
					            self.handle_key_pressed_store(key)
 | 
				
			||||||
        self.display_actions(DisplayActions.REFRESH)
 | 
					        self.display_actions(DisplayActions.REFRESH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_key_pressed_play(self, key: KeyValues) -> None:
 | 
					    def handle_key_pressed_play(self, key: KeyValues) -> None:
 | 
				
			||||||
@@ -112,6 +125,44 @@ class Game:
 | 
				
			|||||||
            self.state = GameMode.INVENTORY
 | 
					            self.state = GameMode.INVENTORY
 | 
				
			||||||
        elif key == KeyValues.SPACE:
 | 
					        elif key == KeyValues.SPACE:
 | 
				
			||||||
            self.state = GameMode.MAINMENU
 | 
					            self.state = GameMode.MAINMENU
 | 
				
			||||||
 | 
					        elif key == KeyValues.CHAT:
 | 
				
			||||||
 | 
					            # Wait for the direction of the friendly entity
 | 
				
			||||||
 | 
					            self.waiting_for_friendly_key = True
 | 
				
			||||||
 | 
					        elif key == KeyValues.WAIT:
 | 
				
			||||||
 | 
					            self.map.tick()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_friendly_entity_chat(self, key: KeyValues) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        If the player is talking to a friendly entity, we get the direction
 | 
				
			||||||
 | 
					        where the entity is, then we interact with it.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if not self.waiting_for_friendly_key:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self.waiting_for_friendly_key = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if key == KeyValues.UP:
 | 
				
			||||||
 | 
					            xp = self.player.x
 | 
				
			||||||
 | 
					            yp = self.player.y - 1
 | 
				
			||||||
 | 
					        elif key == KeyValues.DOWN:
 | 
				
			||||||
 | 
					            xp = self.player.x
 | 
				
			||||||
 | 
					            yp = self.player.y + 1
 | 
				
			||||||
 | 
					        elif key == KeyValues.LEFT:
 | 
				
			||||||
 | 
					            xp = self.player.x - 1
 | 
				
			||||||
 | 
					            yp = self.player.y
 | 
				
			||||||
 | 
					        elif key == KeyValues.RIGHT:
 | 
				
			||||||
 | 
					            xp = self.player.x + 1
 | 
				
			||||||
 | 
					            yp = self.player.y
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        if self.map.entity_is_present(yp, xp):
 | 
				
			||||||
 | 
					            for entity in self.map.entities:
 | 
				
			||||||
 | 
					                if entity.is_friendly() and entity.x == xp and \
 | 
				
			||||||
 | 
					                        entity.y == yp:
 | 
				
			||||||
 | 
					                    msg = entity.talk_to(self.player)
 | 
				
			||||||
 | 
					                    self.logs.add_message(msg)
 | 
				
			||||||
 | 
					                    if entity.is_merchant():
 | 
				
			||||||
 | 
					                        self.state = GameMode.STORE
 | 
				
			||||||
 | 
					                        self.store_menu.update_merchant(entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_key_pressed_inventory(self, key: KeyValues) -> None:
 | 
					    def handle_key_pressed_inventory(self, key: KeyValues) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -136,6 +187,27 @@ class Game:
 | 
				
			|||||||
                                               len(self.inventory_menu.values)
 | 
					                                               len(self.inventory_menu.values)
 | 
				
			||||||
                                               - 1)
 | 
					                                               - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_key_pressed_store(self, key: KeyValues) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        In a store menu, we can buy items or close the menu.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if key == KeyValues.SPACE:
 | 
				
			||||||
 | 
					            self.state = GameMode.PLAY
 | 
				
			||||||
 | 
					        elif key == KeyValues.UP:
 | 
				
			||||||
 | 
					            self.store_menu.go_up()
 | 
				
			||||||
 | 
					        elif key == KeyValues.DOWN:
 | 
				
			||||||
 | 
					            self.store_menu.go_down()
 | 
				
			||||||
 | 
					        if self.store_menu.values and not self.player.dead:
 | 
				
			||||||
 | 
					            if key == KeyValues.ENTER:
 | 
				
			||||||
 | 
					                item = self.store_menu.validate()
 | 
				
			||||||
 | 
					                flag = item.be_sold(self.player, self.store_menu.merchant)
 | 
				
			||||||
 | 
					                if not flag:
 | 
				
			||||||
 | 
					                    self.message = _("You do not have enough money")
 | 
				
			||||||
 | 
					                    self.display_actions(DisplayActions.UPDATE)
 | 
				
			||||||
 | 
					            # Ensure that the cursor has a good position
 | 
				
			||||||
 | 
					            self.store_menu.position = min(self.store_menu.position,
 | 
				
			||||||
 | 
					                                           len(self.store_menu.values) - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_key_pressed_main_menu(self, key: KeyValues) -> None:
 | 
					    def handle_key_pressed_main_menu(self, key: KeyValues) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        In the main menu, we can navigate through options.
 | 
					        In the main menu, we can navigate through options.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
from enum import Enum, auto
 | 
					from enum import Enum, auto
 | 
				
			||||||
from math import sqrt
 | 
					from math import sqrt
 | 
				
			||||||
from random import choice, randint
 | 
					from random import choice, randint
 | 
				
			||||||
from typing import List, Optional, Union, Tuple
 | 
					from typing import List, Optional, Union, Tuple, Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .display.texturepack import TexturePack
 | 
					from .display.texturepack import TexturePack
 | 
				
			||||||
from .translations import gettext as _
 | 
					from .translations import gettext as _
 | 
				
			||||||
@@ -93,6 +93,7 @@ class Map:
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        Unregister an entity from the map.
 | 
					        Unregister an entity from the map.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        if entity in self.entities:
 | 
				
			||||||
            self.entities.remove(entity)
 | 
					            self.entities.remove(entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_entities(self, entity_class: type) -> list:
 | 
					    def find_entities(self, entity_class: type) -> list:
 | 
				
			||||||
@@ -101,12 +102,21 @@ class Map:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def is_free(self, y: int, x: int) -> bool:
 | 
					    def is_free(self, y: int, x: int) -> bool:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Indicates that the case at the coordinates (y, x) is empty.
 | 
					        Indicates that the tile at the coordinates (y, x) is empty.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return 0 <= y < self.height and 0 <= x < self.width and \
 | 
					        return 0 <= y < self.height and 0 <= x < self.width and \
 | 
				
			||||||
            self.tiles[y][x].can_walk() and \
 | 
					            self.tiles[y][x].can_walk() and \
 | 
				
			||||||
            not any(entity.x == x and entity.y == y for entity in self.entities)
 | 
					            not any(entity.x == x and entity.y == y for entity in self.entities)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def entity_is_present(self, y: int, x: int) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Indicates that the tile at the coordinates (y, x) contains a killable
 | 
				
			||||||
 | 
					        entity
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return 0 <= y < self.height and 0 <= x < self.width and \
 | 
				
			||||||
 | 
					            any(entity.x == x and entity.y == y and entity.is_friendly()
 | 
				
			||||||
 | 
					                for entity in self.entities)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def load(filename: str) -> "Map":
 | 
					    def load(filename: str) -> "Map":
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -152,7 +162,7 @@ class Map:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def spawn_random_entities(self, count: int) -> None:
 | 
					    def spawn_random_entities(self, count: int) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Put randomly {count} hedgehogs on the map, where it is available.
 | 
					        Put randomly {count} entities on the map, where it is available.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        for _ignored in range(count):
 | 
					        for _ignored in range(count):
 | 
				
			||||||
            y, x = 0, 0
 | 
					            y, x = 0, 0
 | 
				
			||||||
@@ -459,20 +469,34 @@ class Entity:
 | 
				
			|||||||
        from squirrelbattle.entities.items import Item
 | 
					        from squirrelbattle.entities.items import Item
 | 
				
			||||||
        return isinstance(self, Item)
 | 
					        return isinstance(self, Item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_friendly(self) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Is this entity a friendly entity?
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return isinstance(self, FriendlyEntity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_merchant(self) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Is this entity a merchant?
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        from squirrelbattle.entities.friendly import Merchant
 | 
				
			||||||
 | 
					        return isinstance(self, Merchant)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def translated_name(self) -> str:
 | 
					    def translated_name(self) -> str:
 | 
				
			||||||
        return _(self.name.replace("_", " "))
 | 
					        return _(self.name.replace("_", " "))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def get_all_entity_classes():
 | 
					    def get_all_entity_classes() -> list:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns all entities subclasses
 | 
					        Returns all entities subclasses
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
 | 
					        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
 | 
				
			||||||
        from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
 | 
					        from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
 | 
				
			||||||
            Rabbit, TeddyBear
 | 
					            Rabbit, TeddyBear
 | 
				
			||||||
        return [BodySnatchPotion, Bomb, Heart, Hedgehog,
 | 
					        from squirrelbattle.entities.friendly import Merchant, Sunflower
 | 
				
			||||||
                Rabbit, TeddyBear, Tiger]
 | 
					        return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,
 | 
				
			||||||
 | 
					                Sunflower, Tiger, Merchant]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def get_all_entity_classes_in_a_dict() -> dict:
 | 
					    def get_all_entity_classes_in_a_dict() -> dict:
 | 
				
			||||||
@@ -482,7 +506,9 @@ class Entity:
 | 
				
			|||||||
        from squirrelbattle.entities.player import Player
 | 
					        from squirrelbattle.entities.player import Player
 | 
				
			||||||
        from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
 | 
					        from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
 | 
				
			||||||
            TeddyBear
 | 
					            TeddyBear
 | 
				
			||||||
        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
 | 
					        from squirrelbattle.entities.friendly import Merchant, Sunflower
 | 
				
			||||||
 | 
					        from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
 | 
				
			||||||
 | 
					            Heart, Sword
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            "Tiger": Tiger,
 | 
					            "Tiger": Tiger,
 | 
				
			||||||
            "Bomb": Bomb,
 | 
					            "Bomb": Bomb,
 | 
				
			||||||
@@ -492,6 +518,9 @@ class Entity:
 | 
				
			|||||||
            "Rabbit": Rabbit,
 | 
					            "Rabbit": Rabbit,
 | 
				
			||||||
            "TeddyBear": TeddyBear,
 | 
					            "TeddyBear": TeddyBear,
 | 
				
			||||||
            "Player": Player,
 | 
					            "Player": Player,
 | 
				
			||||||
 | 
					            "Merchant": Merchant,
 | 
				
			||||||
 | 
					            "Sunflower": Sunflower,
 | 
				
			||||||
 | 
					            "Sword": Sword,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save_state(self) -> dict:
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
@@ -567,7 +596,7 @@ class FightingEntity(Entity):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def keys(self) -> list:
 | 
					    def keys(self) -> list:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns a fighting entities specific attributes
 | 
					        Returns a fighting entity's specific attributes
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return ["name", "maxhealth", "health", "level", "strength",
 | 
					        return ["name", "maxhealth", "health", "level", "strength",
 | 
				
			||||||
                "intelligence", "charisma", "dexterity", "constitution"]
 | 
					                "intelligence", "charisma", "dexterity", "constitution"]
 | 
				
			||||||
@@ -580,3 +609,74 @@ class FightingEntity(Entity):
 | 
				
			|||||||
        for name in self.keys():
 | 
					        for name in self.keys():
 | 
				
			||||||
            d[name] = getattr(self, name)
 | 
					            d[name] = getattr(self, name)
 | 
				
			||||||
        return d
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FriendlyEntity(FightingEntity):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Friendly entities are living entities which do not attack the player
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    dialogue_option: list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def talk_to(self, player: Any) -> str:
 | 
				
			||||||
 | 
					        return _("{entity} said: {message}").format(
 | 
				
			||||||
 | 
					            entity=self.translated_name.capitalize(),
 | 
				
			||||||
 | 
					            message=choice(self.dialogue_option))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def keys(self) -> list:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns a friendly entity's specific attributes
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return ["maxhealth", "health"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InventoryHolder(Entity):
 | 
				
			||||||
 | 
					    hazel: int  # Currency of the game
 | 
				
			||||||
 | 
					    inventory: list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def translate_inventory(self, inventory: list) -> list:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Translate the JSON-state of the inventory into a list of the items in
 | 
				
			||||||
 | 
					        the inventory.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        for i in range(len(inventory)):
 | 
				
			||||||
 | 
					            if isinstance(inventory[i], dict):
 | 
				
			||||||
 | 
					                inventory[i] = self.dict_to_inventory(inventory[i])
 | 
				
			||||||
 | 
					        return inventory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dict_to_inventory(self, item_dict: dict) -> Entity:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Translate a dict object that contains the state of an item
 | 
				
			||||||
 | 
					        into an item object.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        entity_classes = self.get_all_entity_classes_in_a_dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        item_class = entity_classes[item_dict["type"]]
 | 
				
			||||||
 | 
					        return item_class(**item_dict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save_state(self) -> dict:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        We save the inventory of the merchant formatted as JSON
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d = super().save_state()
 | 
				
			||||||
 | 
					        d["hazel"] = self.hazel
 | 
				
			||||||
 | 
					        d["inventory"] = [item.save_state() for item in self.inventory]
 | 
				
			||||||
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_to_inventory(self, obj: Any) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Adds an object to inventory
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.inventory.append(obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_from_inventory(self, obj: Any) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Removes an object from the inventory
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.inventory.remove(obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def change_hazel_balance(self, hz: int) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Change the number of hazel the entity has by hz. hz is negative
 | 
				
			||||||
 | 
					        when the player loses money and positive when he gains money
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.hazel += hz
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
# German translation of Squirrel Battle
 | 
					# SOME DESCRIPTIVE TITLE.
 | 
				
			||||||
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
 | 
					# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse, ifugao
 | 
				
			||||||
# This file is distributed under the same license as the squirrelbattle package.
 | 
					# This file is distributed under the same license as the squirrelbattle package.
 | 
				
			||||||
 | 
					# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					#, fuzzy
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
					"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
				
			||||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
					"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
				
			||||||
"POT-Creation-Date: 2020-12-05 14:46+0100\n"
 | 
					"POT-Creation-Date: 2020-12-12 18:02+0100\n"
 | 
				
			||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
@@ -15,31 +17,52 @@ msgstr ""
 | 
				
			|||||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
"Content-Transfer-Encoding: 8bit\n"
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/menudisplay.py:105
 | 
					#: squirrelbattle/display/menudisplay.py:139
 | 
				
			||||||
msgid "== INVENTORY =="
 | 
					msgid "INVENTORY"
 | 
				
			||||||
msgstr "== BESTAND =="
 | 
					msgstr "BESTAND"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
					#: squirrelbattle/display/menudisplay.py:164
 | 
				
			||||||
 | 
					msgid "STALL"
 | 
				
			||||||
 | 
					msgstr "STAND"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/display/statsdisplay.py:33
 | 
				
			||||||
msgid "Inventory:"
 | 
					msgid "Inventory:"
 | 
				
			||||||
msgstr "Bestand:"
 | 
					msgstr "Bestand:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:50
 | 
					#: squirrelbattle/display/statsdisplay.py:52
 | 
				
			||||||
msgid "YOU ARE DEAD"
 | 
					msgid "YOU ARE DEAD"
 | 
				
			||||||
msgstr "SIE WURDEN GESTORBEN"
 | 
					msgstr "SIE WURDEN GESTORBEN"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#. TODO
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:33
 | 
				
			||||||
 | 
					msgid "I don't sell any squirrel"
 | 
				
			||||||
 | 
					msgstr "Ich verkaufe keinen Eichhörnchen."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "Flower power!!"
 | 
				
			||||||
 | 
					msgstr "Blumenmacht!!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "The sun is warm today"
 | 
				
			||||||
 | 
					msgstr "Die Sonne ist warm heute"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#. The bomb is exploding.
 | 
					#. The bomb is exploding.
 | 
				
			||||||
#. Each entity that is close to the bomb takes damages.
 | 
					#. Each entity that is close to the bomb takes damages.
 | 
				
			||||||
#. The player earn XP if the entity was killed.
 | 
					#. The player earn XP if the entity was killed.
 | 
				
			||||||
#: squirrelbattle/entities/items.py:128
 | 
					#: squirrelbattle/entities/items.py:151
 | 
				
			||||||
msgid "Bomb is exploding."
 | 
					msgid "Bomb is exploding."
 | 
				
			||||||
msgstr "Die Bombe explodiert."
 | 
					msgstr "Die Bombe explodiert."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/entities/items.py:172
 | 
					#: squirrelbattle/entities/items.py:248
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{player} exchanged its body with {entity}."
 | 
					msgid "{player} exchanged its body with {entity}."
 | 
				
			||||||
msgstr "{player} täuscht seinem Körper mit {entity} aus."
 | 
					msgstr "{player} täuscht seinem Körper mit {entity} aus."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:177
 | 
					#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573
 | 
				
			||||||
 | 
					msgid "You do not have enough money"
 | 
				
			||||||
 | 
					msgstr "Sie haben nicht genug Geld"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:249
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"Some keys are missing in your save file.\n"
 | 
					"Some keys are missing in your save file.\n"
 | 
				
			||||||
"Your save seems to be corrupt. It got deleted."
 | 
					"Your save seems to be corrupt. It got deleted."
 | 
				
			||||||
@@ -47,7 +70,7 @@ msgstr ""
 | 
				
			|||||||
"In Ihrer Speicherdatei fehlen einige Schlüssel.\n"
 | 
					"In Ihrer Speicherdatei fehlen einige Schlüssel.\n"
 | 
				
			||||||
"Ihre Speicherung scheint korrupt zu sein. Es wird gelöscht."
 | 
					"Ihre Speicherung scheint korrupt zu sein. Es wird gelöscht."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:185
 | 
					#: squirrelbattle/game.py:257
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"No player was found on this map!\n"
 | 
					"No player was found on this map!\n"
 | 
				
			||||||
"Maybe you died?"
 | 
					"Maybe you died?"
 | 
				
			||||||
@@ -55,7 +78,7 @@ msgstr ""
 | 
				
			|||||||
"Auf dieser Karte wurde kein Spieler gefunden!\n"
 | 
					"Auf dieser Karte wurde kein Spieler gefunden!\n"
 | 
				
			||||||
"Vielleicht sind Sie gestorben?"
 | 
					"Vielleicht sind Sie gestorben?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:205
 | 
					#: squirrelbattle/game.py:277
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"The JSON file is not correct.\n"
 | 
					"The JSON file is not correct.\n"
 | 
				
			||||||
"Your save seems corrupted. It got deleted."
 | 
					"Your save seems corrupted. It got deleted."
 | 
				
			||||||
@@ -63,27 +86,32 @@ msgstr ""
 | 
				
			|||||||
"Die JSON-Datei ist nicht korrekt.\n"
 | 
					"Die JSON-Datei ist nicht korrekt.\n"
 | 
				
			||||||
"Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht."
 | 
					"Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:400
 | 
					#: squirrelbattle/interfaces.py:429
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} hits {opponent}."
 | 
					msgid "{name} hits {opponent}."
 | 
				
			||||||
msgstr "{name} schlägt {opponent}."
 | 
					msgstr "{name} schlägt {opponent}."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:412
 | 
					#: squirrelbattle/interfaces.py:441
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} takes {amount} damage."
 | 
					msgid "{name} takes {amount} damage."
 | 
				
			||||||
msgstr "{name} nimmt {amount} Schadenspunkte."
 | 
					msgstr "{name} nimmt {amount} Schadenspunkte."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:414
 | 
					#: squirrelbattle/interfaces.py:443
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} dies."
 | 
					msgid "{name} dies."
 | 
				
			||||||
msgstr "{name} stirbt."
 | 
					msgstr "{name} stirbt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/menus.py:72
 | 
					#: squirrelbattle/interfaces.py:477
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{entity} said: {message}"
 | 
				
			||||||
 | 
					msgstr "{entity} hat gesagt: {message}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:73
 | 
				
			||||||
msgid "Back"
 | 
					msgid "Back"
 | 
				
			||||||
msgstr "Zurück"
 | 
					msgstr "Zurück"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:300 squirrelbattle/tests/game_test.py:303
 | 
					#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:306
 | 
					#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:16
 | 
					#: squirrelbattle/tests/translations_test.py:16
 | 
				
			||||||
msgid "New game"
 | 
					msgid "New game"
 | 
				
			||||||
msgstr "Neu Spiel"
 | 
					msgstr "Neu Spiel"
 | 
				
			||||||
@@ -161,41 +189,65 @@ msgid "Key used to drop an item in the inventory"
 | 
				
			|||||||
msgstr "Taste um eines Objekts im Bestand zu werfen"
 | 
					msgstr "Taste um eines Objekts im Bestand zu werfen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:53
 | 
					#: squirrelbattle/tests/translations_test.py:53
 | 
				
			||||||
 | 
					msgid "Key used to talk to a friendly entity"
 | 
				
			||||||
 | 
					msgstr "Taste um mit einer friedlicher Entität zu sprechen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:55
 | 
				
			||||||
 | 
					msgid "Key used to wait"
 | 
				
			||||||
 | 
					msgstr "Wartentaste"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:56
 | 
				
			||||||
msgid "Texture pack"
 | 
					msgid "Texture pack"
 | 
				
			||||||
msgstr "Textur-Packung"
 | 
					msgstr "Textur-Packung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:54
 | 
					#: squirrelbattle/tests/translations_test.py:57
 | 
				
			||||||
msgid "Language"
 | 
					msgid "Language"
 | 
				
			||||||
msgstr "Sprache"
 | 
					msgstr "Sprache"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:57
 | 
					#: squirrelbattle/tests/translations_test.py:60
 | 
				
			||||||
msgid "player"
 | 
					msgid "player"
 | 
				
			||||||
msgstr "Spieler"
 | 
					msgstr "Spieler"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:59
 | 
					#: squirrelbattle/tests/translations_test.py:62
 | 
				
			||||||
msgid "tiger"
 | 
					 | 
				
			||||||
msgstr "Tiger"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:60
 | 
					 | 
				
			||||||
msgid "hedgehog"
 | 
					msgid "hedgehog"
 | 
				
			||||||
msgstr "Igel"
 | 
					msgstr "Igel"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:61
 | 
					#: squirrelbattle/tests/translations_test.py:63
 | 
				
			||||||
 | 
					msgid "merchant"
 | 
				
			||||||
 | 
					msgstr "Kaufmann"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:64
 | 
				
			||||||
msgid "rabbit"
 | 
					msgid "rabbit"
 | 
				
			||||||
msgstr "Kanninchen"
 | 
					msgstr "Kanninchen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:62
 | 
					#: squirrelbattle/tests/translations_test.py:65
 | 
				
			||||||
 | 
					msgid "sunflower"
 | 
				
			||||||
 | 
					msgstr "Sonnenblume"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:66
 | 
				
			||||||
msgid "teddy bear"
 | 
					msgid "teddy bear"
 | 
				
			||||||
msgstr "Teddybär"
 | 
					msgstr "Teddybär"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:64
 | 
					#: squirrelbattle/tests/translations_test.py:67
 | 
				
			||||||
 | 
					msgid "tiger"
 | 
				
			||||||
 | 
					msgstr "Tiger"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:69
 | 
				
			||||||
msgid "body snatch potion"
 | 
					msgid "body snatch potion"
 | 
				
			||||||
msgstr "Leichenfleddererzaubertrank"
 | 
					msgstr "Leichenfleddererzaubertrank"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:65
 | 
					#: squirrelbattle/tests/translations_test.py:70
 | 
				
			||||||
msgid "bomb"
 | 
					msgid "bomb"
 | 
				
			||||||
msgstr "Bombe"
 | 
					msgstr "Bombe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:66
 | 
					#: squirrelbattle/tests/translations_test.py:71
 | 
				
			||||||
 | 
					msgid "explosion"
 | 
				
			||||||
 | 
					msgstr "Explosion"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:72
 | 
				
			||||||
msgid "heart"
 | 
					msgid "heart"
 | 
				
			||||||
msgstr "Herz"
 | 
					msgstr "Herz"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:73
 | 
				
			||||||
 | 
					msgid "sword"
 | 
				
			||||||
 | 
					msgstr "schwert"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										207
									
								
								squirrelbattle/locale/en/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								squirrelbattle/locale/en/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
				
			|||||||
 | 
					# SOME DESCRIPTIVE TITLE.
 | 
				
			||||||
 | 
					# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
 | 
				
			||||||
 | 
					# This file is distributed under the same license as the squirrelbattle package.
 | 
				
			||||||
 | 
					# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#, fuzzy
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
				
			||||||
 | 
					"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
				
			||||||
 | 
					"POT-Creation-Date: 2020-12-01 17:10+0100\n"
 | 
				
			||||||
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
 | 
					"Language: \n"
 | 
				
			||||||
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/display/statsdisplay.py:34
 | 
				
			||||||
 | 
					msgid "Inventory:"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/display/statsdisplay.py:39
 | 
				
			||||||
 | 
					msgid "YOU ARE DEAD"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:394 squirrelbattle/interfaces.py:398
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:408
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{name} hits {opponent}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:405 squirrelbattle/interfaces.py:410
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:420
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{name} takes {amount} damage."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:46 squirrelbattle/tests/translations_test.py:15
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:17
 | 
				
			||||||
 | 
					msgid "Resume"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:47 squirrelbattle/tests/translations_test.py:17
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:19
 | 
				
			||||||
 | 
					msgid "Save"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:48 squirrelbattle/tests/translations_test.py:16
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:18
 | 
				
			||||||
 | 
					msgid "Load"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:49 squirrelbattle/tests/translations_test.py:18
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:20
 | 
				
			||||||
 | 
					msgid "Settings"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:50 squirrelbattle/tests/translations_test.py:19
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:21
 | 
				
			||||||
 | 
					msgid "Exit"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:71
 | 
				
			||||||
 | 
					msgid "Back"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:147 squirrelbattle/game.py:148
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Some keys are missing in your save file.\n"
 | 
				
			||||||
 | 
					"Your save seems to be corrupt. It got deleted."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:155 squirrelbattle/game.py:156
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"No player was found on this map!\n"
 | 
				
			||||||
 | 
					"Maybe you died?"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:175 squirrelbattle/game.py:176
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"The JSON file is not correct.\n"
 | 
				
			||||||
 | 
					"Your save seems corrupted. It got deleted."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/settings.py:21 squirrelbattle/tests/translations_test.py:21
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:25
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:27
 | 
				
			||||||
 | 
					msgid "Main key to move up"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: 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 ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/settings.py:31 squirrelbattle/tests/translations_test.py:39
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:43
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:45
 | 
				
			||||||
 | 
					msgid "Texture pack"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/settings.py:32 squirrelbattle/tests/translations_test.py:40
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:44
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:46
 | 
				
			||||||
 | 
					msgid "Language"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:407 squirrelbattle/interfaces.py:412
 | 
				
			||||||
 | 
					#: squirrelbattle/interfaces.py:422
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{name} dies."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:47
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:49
 | 
				
			||||||
 | 
					msgid "player"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:49
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:51
 | 
				
			||||||
 | 
					msgid "tiger"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:50
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:52
 | 
				
			||||||
 | 
					msgid "hedgehog"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:51
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:53
 | 
				
			||||||
 | 
					msgid "rabbit"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:52
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:54
 | 
				
			||||||
 | 
					msgid "teddy bear"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:54
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:56
 | 
				
			||||||
 | 
					msgid "bomb"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:55
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:57
 | 
				
			||||||
 | 
					msgid "heart"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:31
 | 
				
			||||||
 | 
					msgid "Flower power!!"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:31
 | 
				
			||||||
 | 
					msgid "The sun is warm today"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
@@ -1,49 +1,67 @@
 | 
				
			|||||||
# Spanish translation of Squirrel Battle
 | 
					# SOME DESCRIPTIVE TITLE.
 | 
				
			||||||
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
 | 
					# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse, ifugao
 | 
				
			||||||
# This file is distributed under the same license as the squirrelbattle package.
 | 
					# This file is distributed under the same license as the squirrelbattle package.
 | 
				
			||||||
# Translation by ifugaao
 | 
					# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					#, fuzzy
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
					"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
				
			||||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
					"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
				
			||||||
"POT-Creation-Date: 2020-12-05 14:46+0100\n"
 | 
					"POT-Creation-Date: 2020-12-12 18:02+0100\n"
 | 
				
			||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
"Last-Translator: ifugao\n"
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
"Language: \n"
 | 
					"Language: \n"
 | 
				
			||||||
"MIME-Version: 1.0\n"
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
"Content-Transfer-Encoding: 8bit\n"
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Suggested in Weblate: == INVENTORIO ==
 | 
					#: squirrelbattle/display/menudisplay.py:139
 | 
				
			||||||
#: squirrelbattle/display/menudisplay.py:105
 | 
					msgid "INVENTORY"
 | 
				
			||||||
msgid "== INVENTORY =="
 | 
					msgstr "INVENTORIO"
 | 
				
			||||||
msgstr "== INVENTORIO =="
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Suggested in Weblate: Inventorio :
 | 
					#: squirrelbattle/display/menudisplay.py:164
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
					msgid "STALL"
 | 
				
			||||||
 | 
					msgstr "PUESTO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/display/statsdisplay.py:33
 | 
				
			||||||
msgid "Inventory:"
 | 
					msgid "Inventory:"
 | 
				
			||||||
msgstr "Inventorio :"
 | 
					msgstr "Inventorio :"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Suggested in Weblate: ERES MUERTO
 | 
					#: squirrelbattle/display/statsdisplay.py:52
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:50
 | 
					 | 
				
			||||||
msgid "YOU ARE DEAD"
 | 
					msgid "YOU ARE DEAD"
 | 
				
			||||||
msgstr "ERES MUERTO"
 | 
					msgstr "ERES MUERTO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:33
 | 
				
			||||||
 | 
					msgid "I don't sell any squirrel"
 | 
				
			||||||
 | 
					msgstr "No vendo ninguna ardilla"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "Flower power!!"
 | 
				
			||||||
 | 
					msgstr "Poder de las flores!!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "The sun is warm today"
 | 
				
			||||||
 | 
					msgstr "El sol está caliente hoy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#. The bomb is exploding.
 | 
					#. The bomb is exploding.
 | 
				
			||||||
#. Each entity that is close to the bomb takes damages.
 | 
					#. Each entity that is close to the bomb takes damages.
 | 
				
			||||||
#. The player earn XP if the entity was killed.
 | 
					#. The player earn XP if the entity was killed.
 | 
				
			||||||
#: squirrelbattle/entities/items.py:128
 | 
					#: squirrelbattle/entities/items.py:151
 | 
				
			||||||
msgid "Bomb is exploding."
 | 
					msgid "Bomb is exploding."
 | 
				
			||||||
msgstr "La bomba está explotando."
 | 
					msgstr "La bomba está explotando."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/entities/items.py:172
 | 
					#: squirrelbattle/entities/items.py:248
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{player} exchanged its body with {entity}."
 | 
					msgid "{player} exchanged its body with {entity}."
 | 
				
			||||||
msgstr "{player} intercambió su cuerpo con {entity}."
 | 
					msgstr "{player} intercambió su cuerpo con {entity}."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:177
 | 
					#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573
 | 
				
			||||||
 | 
					msgid "You do not have enough money"
 | 
				
			||||||
 | 
					msgstr "No tienes suficiente dinero"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:249
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"Some keys are missing in your save file.\n"
 | 
					"Some keys are missing in your save file.\n"
 | 
				
			||||||
"Your save seems to be corrupt. It got deleted."
 | 
					"Your save seems to be corrupt. It got deleted."
 | 
				
			||||||
@@ -51,7 +69,7 @@ msgstr ""
 | 
				
			|||||||
"Algunas claves faltan en su archivo de guarda.\n"
 | 
					"Algunas claves faltan en su archivo de guarda.\n"
 | 
				
			||||||
"Su guarda parece a ser corruptido. Fue eliminado."
 | 
					"Su guarda parece a ser corruptido. Fue eliminado."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:185
 | 
					#: squirrelbattle/game.py:257
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"No player was found on this map!\n"
 | 
					"No player was found on this map!\n"
 | 
				
			||||||
"Maybe you died?"
 | 
					"Maybe you died?"
 | 
				
			||||||
@@ -59,7 +77,7 @@ msgstr ""
 | 
				
			|||||||
"No jugador encontrado sobre la carta !\n"
 | 
					"No jugador encontrado sobre la carta !\n"
 | 
				
			||||||
"¿ Quizas murió ?"
 | 
					"¿ Quizas murió ?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:205
 | 
					#: squirrelbattle/game.py:277
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"The JSON file is not correct.\n"
 | 
					"The JSON file is not correct.\n"
 | 
				
			||||||
"Your save seems corrupted. It got deleted."
 | 
					"Your save seems corrupted. It got deleted."
 | 
				
			||||||
@@ -67,28 +85,32 @@ msgstr ""
 | 
				
			|||||||
"El JSON archivo no es correcto.\n"
 | 
					"El JSON archivo no es correcto.\n"
 | 
				
			||||||
"Su guarda parece corrupta. Fue eliminada."
 | 
					"Su guarda parece corrupta. Fue eliminada."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:400
 | 
					#: squirrelbattle/interfaces.py:429
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} hits {opponent}."
 | 
					msgid "{name} hits {opponent}."
 | 
				
			||||||
msgstr "{name} golpea a {opponent}."
 | 
					msgstr "{name} golpea a {opponent}."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:412
 | 
					#: squirrelbattle/interfaces.py:441
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} takes {amount} damage."
 | 
					msgid "{name} takes {amount} damage."
 | 
				
			||||||
msgstr "{name} recibe {amount} daño."
 | 
					msgstr "{name} recibe {amount} daño."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:414
 | 
					#: squirrelbattle/interfaces.py:443
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} dies."
 | 
					msgid "{name} dies."
 | 
				
			||||||
msgstr "{name} se muere."
 | 
					msgstr "{name} se muere."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/menus.py:72
 | 
					#: squirrelbattle/interfaces.py:477
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{entity} said: {message}"
 | 
				
			||||||
 | 
					msgstr "{entity} dijo : {message}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:73
 | 
				
			||||||
msgid "Back"
 | 
					msgid "Back"
 | 
				
			||||||
msgstr "Volver"
 | 
					msgstr "Volver"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:300,
 | 
					#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:303,
 | 
					#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:306,
 | 
					 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:16
 | 
					#: squirrelbattle/tests/translations_test.py:16
 | 
				
			||||||
msgid "New game"
 | 
					msgid "New game"
 | 
				
			||||||
msgstr "Nuevo partido"
 | 
					msgstr "Nuevo partido"
 | 
				
			||||||
@@ -166,41 +188,65 @@ msgid "Key used to drop an item in the inventory"
 | 
				
			|||||||
msgstr "Tecla para dejar un objeto del inventorio"
 | 
					msgstr "Tecla para dejar un objeto del inventorio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:53
 | 
					#: squirrelbattle/tests/translations_test.py:53
 | 
				
			||||||
 | 
					msgid "Key used to talk to a friendly entity"
 | 
				
			||||||
 | 
					msgstr "Tecla para hablar con una entidad amiga"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:55
 | 
				
			||||||
 | 
					msgid "Key used to wait"
 | 
				
			||||||
 | 
					msgstr "Tecla para espera"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:56
 | 
				
			||||||
msgid "Texture pack"
 | 
					msgid "Texture pack"
 | 
				
			||||||
msgstr "Paquete de texturas"
 | 
					msgstr "Paquete de texturas"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:54
 | 
					#: squirrelbattle/tests/translations_test.py:57
 | 
				
			||||||
msgid "Language"
 | 
					msgid "Language"
 | 
				
			||||||
msgstr "Languaje"
 | 
					msgstr "Languaje"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:57
 | 
					#: squirrelbattle/tests/translations_test.py:60
 | 
				
			||||||
msgid "player"
 | 
					msgid "player"
 | 
				
			||||||
msgstr "jugador"
 | 
					msgstr "jugador"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:59
 | 
					#: squirrelbattle/tests/translations_test.py:62
 | 
				
			||||||
msgid "tiger"
 | 
					 | 
				
			||||||
msgstr "tigre"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:60
 | 
					 | 
				
			||||||
msgid "hedgehog"
 | 
					msgid "hedgehog"
 | 
				
			||||||
msgstr "erizo"
 | 
					msgstr "erizo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:61
 | 
					#: squirrelbattle/tests/translations_test.py:63
 | 
				
			||||||
 | 
					msgid "merchant"
 | 
				
			||||||
 | 
					msgstr "comerciante"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:64
 | 
				
			||||||
msgid "rabbit"
 | 
					msgid "rabbit"
 | 
				
			||||||
msgstr "conejo"
 | 
					msgstr "conejo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:62
 | 
					#: squirrelbattle/tests/translations_test.py:65
 | 
				
			||||||
 | 
					msgid "sunflower"
 | 
				
			||||||
 | 
					msgstr "girasol"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:66
 | 
				
			||||||
msgid "teddy bear"
 | 
					msgid "teddy bear"
 | 
				
			||||||
msgstr "osito de peluche"
 | 
					msgstr "osito de peluche"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:64
 | 
					#: squirrelbattle/tests/translations_test.py:67
 | 
				
			||||||
 | 
					msgid "tiger"
 | 
				
			||||||
 | 
					msgstr "tigre"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:69
 | 
				
			||||||
msgid "body snatch potion"
 | 
					msgid "body snatch potion"
 | 
				
			||||||
msgstr "poción de intercambio"
 | 
					msgstr "poción de intercambio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:65
 | 
					#: squirrelbattle/tests/translations_test.py:70
 | 
				
			||||||
msgid "bomb"
 | 
					msgid "bomb"
 | 
				
			||||||
msgstr "bomba"
 | 
					msgstr "bomba"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:66
 | 
					#: squirrelbattle/tests/translations_test.py:71
 | 
				
			||||||
 | 
					msgid "explosion"
 | 
				
			||||||
 | 
					msgstr "explosión"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:72
 | 
				
			||||||
msgid "heart"
 | 
					msgid "heart"
 | 
				
			||||||
msgstr "corazón"
 | 
					msgstr "corazón"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:73
 | 
				
			||||||
 | 
					msgid "sword"
 | 
				
			||||||
 | 
					msgstr "espada"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,46 +1,68 @@
 | 
				
			|||||||
# French translation of Squirrel Battle
 | 
					# SOME DESCRIPTIVE TITLE.
 | 
				
			||||||
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
 | 
					# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse, ifugao
 | 
				
			||||||
# This file is distributed under the same license as the squirrelbattle package.
 | 
					# This file is distributed under the same license as the squirrelbattle package.
 | 
				
			||||||
 | 
					# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#, fuzzy
 | 
					#, fuzzy
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
					"Project-Id-Version: squirrelbattle 3.14.1\n"
 | 
				
			||||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
					"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
 | 
				
			||||||
"POT-Creation-Date: 2020-12-05 14:46+0100\n"
 | 
					"POT-Creation-Date: 2020-12-12 18:02+0100\n"
 | 
				
			||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
"Language: fr\n"
 | 
					"Language: \n"
 | 
				
			||||||
"MIME-Version: 1.0\n"
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
"Content-Transfer-Encoding: 8bit\n"
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/menudisplay.py:105
 | 
					#: squirrelbattle/display/menudisplay.py:139
 | 
				
			||||||
msgid "== INVENTORY =="
 | 
					msgid "INVENTORY"
 | 
				
			||||||
msgstr "== INVENTAIRE =="
 | 
					msgstr "INVENTAIRE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:34
 | 
					#: squirrelbattle/display/menudisplay.py:164
 | 
				
			||||||
 | 
					msgid "STALL"
 | 
				
			||||||
 | 
					msgstr "STAND"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/display/statsdisplay.py:33
 | 
				
			||||||
msgid "Inventory:"
 | 
					msgid "Inventory:"
 | 
				
			||||||
msgstr "Inventaire :"
 | 
					msgstr "Inventaire :"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/display/statsdisplay.py:50
 | 
					#: squirrelbattle/display/statsdisplay.py:52
 | 
				
			||||||
msgid "YOU ARE DEAD"
 | 
					msgid "YOU ARE DEAD"
 | 
				
			||||||
msgstr "VOUS ÊTES MORT"
 | 
					msgstr "VOUS ÊTES MORT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#. TODO
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:33
 | 
				
			||||||
 | 
					msgid "I don't sell any squirrel"
 | 
				
			||||||
 | 
					msgstr "Je ne vends pas d'écureuil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "Flower power!!"
 | 
				
			||||||
 | 
					msgstr "Pouvoir des fleurs !!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/entities/friendly.py:52
 | 
				
			||||||
 | 
					msgid "The sun is warm today"
 | 
				
			||||||
 | 
					msgstr "Le soleil est chaud aujourd'hui"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#. The bomb is exploding.
 | 
					#. The bomb is exploding.
 | 
				
			||||||
#. Each entity that is close to the bomb takes damages.
 | 
					#. Each entity that is close to the bomb takes damages.
 | 
				
			||||||
#. The player earn XP if the entity was killed.
 | 
					#. The player earn XP if the entity was killed.
 | 
				
			||||||
#: squirrelbattle/entities/items.py:128
 | 
					#: squirrelbattle/entities/items.py:151
 | 
				
			||||||
msgid "Bomb is exploding."
 | 
					msgid "Bomb is exploding."
 | 
				
			||||||
msgstr "La bombe explose."
 | 
					msgstr "La bombe explose."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/entities/items.py:172
 | 
					#: squirrelbattle/entities/items.py:248
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{player} exchanged its body with {entity}."
 | 
					msgid "{player} exchanged its body with {entity}."
 | 
				
			||||||
msgstr "{player} a échangé son corps avec {entity}."
 | 
					msgstr "{player} a échangé son corps avec {entity}."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:177
 | 
					#: squirrelbattle/game.py:205 squirrelbattle/tests/game_test.py:573
 | 
				
			||||||
 | 
					msgid "You do not have enough money"
 | 
				
			||||||
 | 
					msgstr "Vous n'avez pas assez d'argent"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/game.py:249
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"Some keys are missing in your save file.\n"
 | 
					"Some keys are missing in your save file.\n"
 | 
				
			||||||
"Your save seems to be corrupt. It got deleted."
 | 
					"Your save seems to be corrupt. It got deleted."
 | 
				
			||||||
@@ -48,7 +70,7 @@ msgstr ""
 | 
				
			|||||||
"Certaines clés de votre ficher de sauvegarde sont manquantes.\n"
 | 
					"Certaines clés de votre ficher de sauvegarde sont manquantes.\n"
 | 
				
			||||||
"Votre sauvegarde semble corrompue. Elle a été supprimée."
 | 
					"Votre sauvegarde semble corrompue. Elle a été supprimée."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:185
 | 
					#: squirrelbattle/game.py:257
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"No player was found on this map!\n"
 | 
					"No player was found on this map!\n"
 | 
				
			||||||
"Maybe you died?"
 | 
					"Maybe you died?"
 | 
				
			||||||
@@ -56,7 +78,7 @@ msgstr ""
 | 
				
			|||||||
"Aucun joueur n'a été trouvé sur la carte !\n"
 | 
					"Aucun joueur n'a été trouvé sur la carte !\n"
 | 
				
			||||||
"Peut-être êtes-vous mort ?"
 | 
					"Peut-être êtes-vous mort ?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/game.py:205
 | 
					#: squirrelbattle/game.py:277
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"The JSON file is not correct.\n"
 | 
					"The JSON file is not correct.\n"
 | 
				
			||||||
"Your save seems corrupted. It got deleted."
 | 
					"Your save seems corrupted. It got deleted."
 | 
				
			||||||
@@ -64,27 +86,32 @@ msgstr ""
 | 
				
			|||||||
"Le fichier JSON de sauvegarde est incorrect.\n"
 | 
					"Le fichier JSON de sauvegarde est incorrect.\n"
 | 
				
			||||||
"Votre sauvegarde semble corrompue. Elle a été supprimée."
 | 
					"Votre sauvegarde semble corrompue. Elle a été supprimée."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:400
 | 
					#: squirrelbattle/interfaces.py:429
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} hits {opponent}."
 | 
					msgid "{name} hits {opponent}."
 | 
				
			||||||
msgstr "{name} frappe {opponent}."
 | 
					msgstr "{name} frappe {opponent}."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:412
 | 
					#: squirrelbattle/interfaces.py:441
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} takes {amount} damage."
 | 
					msgid "{name} takes {amount} damage."
 | 
				
			||||||
msgstr "{name} prend {amount} points de dégât."
 | 
					msgstr "{name} prend {amount} points de dégât."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/interfaces.py:414
 | 
					#: squirrelbattle/interfaces.py:443
 | 
				
			||||||
#, python-brace-format
 | 
					#, python-brace-format
 | 
				
			||||||
msgid "{name} dies."
 | 
					msgid "{name} dies."
 | 
				
			||||||
msgstr "{name} meurt."
 | 
					msgstr "{name} meurt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/menus.py:72
 | 
					#: squirrelbattle/interfaces.py:477
 | 
				
			||||||
 | 
					#, python-brace-format
 | 
				
			||||||
 | 
					msgid "{entity} said: {message}"
 | 
				
			||||||
 | 
					msgstr "{entity} a dit : {message}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/menus.py:73
 | 
				
			||||||
msgid "Back"
 | 
					msgid "Back"
 | 
				
			||||||
msgstr "Retour"
 | 
					msgstr "Retour"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:300 squirrelbattle/tests/game_test.py:303
 | 
					#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
 | 
				
			||||||
#: squirrelbattle/tests/game_test.py:306
 | 
					#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:16
 | 
					#: squirrelbattle/tests/translations_test.py:16
 | 
				
			||||||
msgid "New game"
 | 
					msgid "New game"
 | 
				
			||||||
msgstr "Nouvelle partie"
 | 
					msgstr "Nouvelle partie"
 | 
				
			||||||
@@ -162,41 +189,65 @@ msgid "Key used to drop an item in the inventory"
 | 
				
			|||||||
msgstr "Touche pour jeter un objet de l'inventaire"
 | 
					msgstr "Touche pour jeter un objet de l'inventaire"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:53
 | 
					#: squirrelbattle/tests/translations_test.py:53
 | 
				
			||||||
 | 
					msgid "Key used to talk to a friendly entity"
 | 
				
			||||||
 | 
					msgstr "Touche pour parler à une entité pacifique"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:55
 | 
				
			||||||
 | 
					msgid "Key used to wait"
 | 
				
			||||||
 | 
					msgstr "Touche pour attendre"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:56
 | 
				
			||||||
msgid "Texture pack"
 | 
					msgid "Texture pack"
 | 
				
			||||||
msgstr "Pack de textures"
 | 
					msgstr "Pack de textures"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:54
 | 
					#: squirrelbattle/tests/translations_test.py:57
 | 
				
			||||||
msgid "Language"
 | 
					msgid "Language"
 | 
				
			||||||
msgstr "Langue"
 | 
					msgstr "Langue"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:57
 | 
					#: squirrelbattle/tests/translations_test.py:60
 | 
				
			||||||
msgid "player"
 | 
					msgid "player"
 | 
				
			||||||
msgstr "joueur"
 | 
					msgstr "joueur"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:59
 | 
					#: squirrelbattle/tests/translations_test.py:62
 | 
				
			||||||
msgid "tiger"
 | 
					 | 
				
			||||||
msgstr "tigre"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:60
 | 
					 | 
				
			||||||
msgid "hedgehog"
 | 
					msgid "hedgehog"
 | 
				
			||||||
msgstr "hérisson"
 | 
					msgstr "hérisson"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:61
 | 
					#: squirrelbattle/tests/translations_test.py:63
 | 
				
			||||||
 | 
					msgid "merchant"
 | 
				
			||||||
 | 
					msgstr "marchand"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:64
 | 
				
			||||||
msgid "rabbit"
 | 
					msgid "rabbit"
 | 
				
			||||||
msgstr "lapin"
 | 
					msgstr "lapin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:62
 | 
					#: squirrelbattle/tests/translations_test.py:65
 | 
				
			||||||
 | 
					msgid "sunflower"
 | 
				
			||||||
 | 
					msgstr "tournesol"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:66
 | 
				
			||||||
msgid "teddy bear"
 | 
					msgid "teddy bear"
 | 
				
			||||||
msgstr "nounours"
 | 
					msgstr "nounours"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:64
 | 
					#: squirrelbattle/tests/translations_test.py:67
 | 
				
			||||||
 | 
					msgid "tiger"
 | 
				
			||||||
 | 
					msgstr "tigre"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:69
 | 
				
			||||||
msgid "body snatch potion"
 | 
					msgid "body snatch potion"
 | 
				
			||||||
msgstr "potion d'arrachage de corps"
 | 
					msgstr "potion d'arrachage de corps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:65
 | 
					#: squirrelbattle/tests/translations_test.py:70
 | 
				
			||||||
msgid "bomb"
 | 
					msgid "bomb"
 | 
				
			||||||
msgstr "bombe"
 | 
					msgstr "bombe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: squirrelbattle/tests/translations_test.py:66
 | 
					#: squirrelbattle/tests/translations_test.py:71
 | 
				
			||||||
 | 
					msgid "explosion"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:72
 | 
				
			||||||
msgid "heart"
 | 
					msgid "heart"
 | 
				
			||||||
msgstr "cœur"
 | 
					msgstr "cœur"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: squirrelbattle/tests/translations_test.py:73
 | 
				
			||||||
 | 
					msgid "sword"
 | 
				
			||||||
 | 
					msgstr "épée"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ from typing import Any, Optional
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from .display.texturepack import TexturePack
 | 
					from .display.texturepack import TexturePack
 | 
				
			||||||
from .entities.player import Player
 | 
					from .entities.player import Player
 | 
				
			||||||
 | 
					from .entities.friendly import Merchant
 | 
				
			||||||
from .enums import GameMode, KeyValues, DisplayActions
 | 
					from .enums import GameMode, KeyValues, DisplayActions
 | 
				
			||||||
from .settings import Settings
 | 
					from .settings import Settings
 | 
				
			||||||
from .translations import gettext as _, Translator
 | 
					from .translations import gettext as _, Translator
 | 
				
			||||||
@@ -128,3 +129,14 @@ class InventoryMenu(Menu):
 | 
				
			|||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def values(self) -> list:
 | 
					    def values(self) -> list:
 | 
				
			||||||
        return self.player.inventory
 | 
					        return self.player.inventory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StoreMenu(Menu):
 | 
				
			||||||
 | 
					    merchant: Merchant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_merchant(self, merchant: Merchant) -> None:
 | 
				
			||||||
 | 
					        self.merchant = merchant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def values(self) -> list:
 | 
				
			||||||
 | 
					        return self.merchant.inventory
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,8 @@ class Settings:
 | 
				
			|||||||
        self.KEY_USE = ['u', 'Key used to use an item in 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_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.KEY_DROP = ['r', 'Key used to drop an item in the inventory']
 | 
				
			||||||
 | 
					        self.KEY_CHAT = ['t', 'Key used to talk to a friendly entity']
 | 
				
			||||||
 | 
					        self.KEY_WAIT = ['w', 'Key used to wait']
 | 
				
			||||||
        self.TEXTURE_PACK = ['ascii', 'Texture pack']
 | 
					        self.TEXTURE_PACK = ['ascii', 'Texture pack']
 | 
				
			||||||
        self.LOCALE = [locale.getlocale()[0][:2], 'Language']
 | 
					        self.LOCALE = [locale.getlocale()[0][:2], 'Language']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,8 @@ class TermManager:  # pragma: no cover
 | 
				
			|||||||
        curses.cbreak()
 | 
					        curses.cbreak()
 | 
				
			||||||
        # make cursor invisible
 | 
					        # make cursor invisible
 | 
				
			||||||
        curses.curs_set(False)
 | 
					        curses.curs_set(False)
 | 
				
			||||||
 | 
					        # Catch mouse events
 | 
				
			||||||
 | 
					        curses.mousemask(True)
 | 
				
			||||||
        # Enable colors
 | 
					        # Enable colors
 | 
				
			||||||
        curses.start_color()
 | 
					        curses.start_color()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart, Item
 | 
					from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart, Item, \
 | 
				
			||||||
 | 
					    Explosion
 | 
				
			||||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, TeddyBear
 | 
					from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, TeddyBear
 | 
				
			||||||
from squirrelbattle.entities.player import Player
 | 
					from squirrelbattle.entities.player import Player
 | 
				
			||||||
from squirrelbattle.interfaces import Entity, Map
 | 
					from squirrelbattle.interfaces import Entity, Map
 | 
				
			||||||
@@ -138,6 +139,20 @@ class TestEntities(unittest.TestCase):
 | 
				
			|||||||
        self.assertTrue(teddy_bear.dead)
 | 
					        self.assertTrue(teddy_bear.dead)
 | 
				
			||||||
        bomb_state = item.save_state()
 | 
					        bomb_state = item.save_state()
 | 
				
			||||||
        self.assertEqual(bomb_state["damage"], item.damage)
 | 
					        self.assertEqual(bomb_state["damage"], item.damage)
 | 
				
			||||||
 | 
					        explosions = self.map.find_entities(Explosion)
 | 
				
			||||||
 | 
					        self.assertTrue(explosions)
 | 
				
			||||||
 | 
					        explosion = explosions[0]
 | 
				
			||||||
 | 
					        self.assertEqual(explosion.y, item.y)
 | 
				
			||||||
 | 
					        self.assertEqual(explosion.x, item.x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # The player can't hold the explosion
 | 
				
			||||||
 | 
					        explosion.hold(self.player)
 | 
				
			||||||
 | 
					        self.assertNotIn(explosion, self.player.inventory)
 | 
				
			||||||
 | 
					        self.assertFalse(explosion.held)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # The explosion disappears after one tick
 | 
				
			||||||
 | 
					        explosion.act(self.map)
 | 
				
			||||||
 | 
					        self.assertNotIn(explosion, self.map.entities)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_hearts(self) -> None:
 | 
					    def test_hearts(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,8 @@ import unittest
 | 
				
			|||||||
from ..bootstrap import Bootstrap
 | 
					from ..bootstrap import Bootstrap
 | 
				
			||||||
from ..display.display import Display
 | 
					from ..display.display import Display
 | 
				
			||||||
from ..display.display_manager import DisplayManager
 | 
					from ..display.display_manager import DisplayManager
 | 
				
			||||||
from ..entities.items import Bomb
 | 
					from ..entities.friendly import Merchant, Sunflower
 | 
				
			||||||
 | 
					from ..entities.items import Bomb, Heart, Sword, Explosion
 | 
				
			||||||
from ..entities.player import Player
 | 
					from ..entities.player import Player
 | 
				
			||||||
from ..enums import DisplayActions
 | 
					from ..enums import DisplayActions
 | 
				
			||||||
from ..game import Game, KeyValues, GameMode
 | 
					from ..game import Game, KeyValues, GameMode
 | 
				
			||||||
@@ -34,7 +35,17 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        bomb = Bomb()
 | 
					        bomb = Bomb()
 | 
				
			||||||
        self.game.map.add_entity(bomb)
 | 
					        self.game.map.add_entity(bomb)
 | 
				
			||||||
 | 
					        sword = Sword()
 | 
				
			||||||
 | 
					        self.game.map.add_entity(sword)
 | 
				
			||||||
 | 
					        # Add items in the inventory to check that it is well loaded
 | 
				
			||||||
        bomb.hold(self.game.player)
 | 
					        bomb.hold(self.game.player)
 | 
				
			||||||
 | 
					        sword.hold(self.game.player)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Ensure that merchants can be saved
 | 
				
			||||||
 | 
					        merchant = Merchant()
 | 
				
			||||||
 | 
					        merchant.move(3, 6)
 | 
				
			||||||
 | 
					        self.game.map.add_entity(merchant)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        old_state = self.game.save_state()
 | 
					        old_state = self.game.save_state()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
@@ -117,6 +128,9 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.assertEqual(KeyValues.translate_key(
 | 
					        self.assertEqual(KeyValues.translate_key(
 | 
				
			||||||
            self.game.settings.KEY_INVENTORY, self.game.settings),
 | 
					            self.game.settings.KEY_INVENTORY, self.game.settings),
 | 
				
			||||||
            KeyValues.INVENTORY)
 | 
					            KeyValues.INVENTORY)
 | 
				
			||||||
 | 
					        self.assertEqual(KeyValues.translate_key(
 | 
				
			||||||
 | 
					            self.game.settings.KEY_CHAT, self.game.settings),
 | 
				
			||||||
 | 
					            KeyValues.CHAT)
 | 
				
			||||||
        self.assertEqual(KeyValues.translate_key(
 | 
					        self.assertEqual(KeyValues.translate_key(
 | 
				
			||||||
            self.game.settings.KEY_USE, self.game.settings),
 | 
					            self.game.settings.KEY_USE, self.game.settings),
 | 
				
			||||||
            KeyValues.USE)
 | 
					            KeyValues.USE)
 | 
				
			||||||
@@ -126,6 +140,9 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.assertEqual(KeyValues.translate_key(
 | 
					        self.assertEqual(KeyValues.translate_key(
 | 
				
			||||||
            self.game.settings.KEY_DROP, self.game.settings),
 | 
					            self.game.settings.KEY_DROP, self.game.settings),
 | 
				
			||||||
            KeyValues.DROP)
 | 
					            KeyValues.DROP)
 | 
				
			||||||
 | 
					        self.assertEqual(KeyValues.translate_key(
 | 
				
			||||||
 | 
					            self.game.settings.KEY_WAIT, self.game.settings),
 | 
				
			||||||
 | 
					            KeyValues.WAIT)
 | 
				
			||||||
        self.assertEqual(KeyValues.translate_key(' ', self.game.settings),
 | 
					        self.assertEqual(KeyValues.translate_key(' ', self.game.settings),
 | 
				
			||||||
                         KeyValues.SPACE)
 | 
					                         KeyValues.SPACE)
 | 
				
			||||||
        self.assertEqual(KeyValues.translate_key('plop', self.game.settings),
 | 
					        self.assertEqual(KeyValues.translate_key('plop', self.game.settings),
 | 
				
			||||||
@@ -213,9 +230,45 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.assertEqual(new_y, y)
 | 
					        self.assertEqual(new_y, y)
 | 
				
			||||||
        self.assertEqual(new_x, x - 1)
 | 
					        self.assertEqual(new_x, x - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        explosion = Explosion()
 | 
				
			||||||
 | 
					        self.game.map.add_entity(explosion)
 | 
				
			||||||
 | 
					        self.assertIn(explosion, self.game.map.entities)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.WAIT)
 | 
				
			||||||
 | 
					        self.assertNotIn(explosion, self.game.map.entities)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.game.handle_key_pressed(KeyValues.SPACE)
 | 
					        self.game.handle_key_pressed(KeyValues.SPACE)
 | 
				
			||||||
        self.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
					        self.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_mouse_click(self) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Simulate mouse clicks.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.game.state = GameMode.MAINMENU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Change the color of the artwork
 | 
				
			||||||
 | 
					        self.game.display_actions(DisplayActions.MOUSE, 0, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Settings menu
 | 
				
			||||||
 | 
					        self.game.display_actions(DisplayActions.MOUSE, 25, 21)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.main_menu.position, 4)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.SETTINGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bomb = Bomb()
 | 
				
			||||||
 | 
					        bomb.hold(self.game.player)
 | 
				
			||||||
 | 
					        bomb2 = Bomb()
 | 
				
			||||||
 | 
					        bomb2.hold(self.game.player)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.game.state = GameMode.INVENTORY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Click nowhere
 | 
				
			||||||
 | 
					        self.game.display_actions(DisplayActions.MOUSE, 0, 0)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Click on the second item
 | 
				
			||||||
 | 
					        self.game.display_actions(DisplayActions.MOUSE, 8, 25)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.inventory_menu.position, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_new_game(self) -> None:
 | 
					    def test_new_game(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Ensure that the start button starts a new game.
 | 
					        Ensure that the start button starts a new game.
 | 
				
			||||||
@@ -253,13 +306,13 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
        self.assertEqual(self.game.state, GameMode.SETTINGS)
 | 
					        self.assertEqual(self.game.state, GameMode.SETTINGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Define the "move up" key to 'w'
 | 
					        # Define the "move up" key to 'h'
 | 
				
			||||||
        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
					        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
				
			||||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
        self.assertTrue(self.game.settings_menu.waiting_for_key)
 | 
					        self.assertTrue(self.game.settings_menu.waiting_for_key)
 | 
				
			||||||
        self.game.handle_key_pressed(None, 'w')
 | 
					        self.game.handle_key_pressed(None, 'h')
 | 
				
			||||||
        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
					        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
				
			||||||
        self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'w')
 | 
					        self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'h')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Navigate to "move left"
 | 
					        # Navigate to "move left"
 | 
				
			||||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
@@ -280,7 +333,7 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a')
 | 
					        self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Navigate to "texture pack"
 | 
					        # Navigate to "texture pack"
 | 
				
			||||||
        for ignored in range(9):
 | 
					        for ignored in range(11):
 | 
				
			||||||
            self.game.handle_key_pressed(KeyValues.DOWN)
 | 
					            self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Change texture pack
 | 
					        # Change texture pack
 | 
				
			||||||
@@ -417,3 +470,118 @@ class TestGame(unittest.TestCase):
 | 
				
			|||||||
        self.assertTrue(bomb.exploding)
 | 
					        self.assertTrue(bomb.exploding)
 | 
				
			||||||
        self.assertEqual(bomb.y, self.game.player.y)
 | 
					        self.assertEqual(bomb.y, self.game.player.y)
 | 
				
			||||||
        self.assertEqual(bomb.x, self.game.player.x)
 | 
					        self.assertEqual(bomb.x, self.game.player.x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_talk_to_sunflowers(self) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Interact with sunflowers
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.game.state = GameMode.PLAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sunflower = Sunflower()
 | 
				
			||||||
 | 
					        sunflower.move(2, 6)
 | 
				
			||||||
 | 
					        self.game.map.add_entity(sunflower)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Does nothing
 | 
				
			||||||
 | 
					        self.assertIsNone(self.game.handle_friendly_entity_chat(KeyValues.UP))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Talk to sunflower... or not
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        # Wrong key
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.EQUIP)
 | 
				
			||||||
 | 
					        self.assertFalse(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.UP)
 | 
				
			||||||
 | 
					        self.assertFalse(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.PLAY)
 | 
				
			||||||
 | 
					        self.assertFalse(len(self.game.logs.messages) > 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Talk to sunflower
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
 | 
					        self.assertFalse(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.PLAY)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.logs.messages)
 | 
				
			||||||
 | 
					        # Ensure that the message is a good message
 | 
				
			||||||
 | 
					        self.assertTrue(any(self.game.logs.messages[1].endswith(msg)
 | 
				
			||||||
 | 
					                            for msg in Sunflower().dialogue_option))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Test all directions to detect the friendly entity
 | 
				
			||||||
 | 
					        self.game.player.move(3, 6)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.UP)
 | 
				
			||||||
 | 
					        self.assertEqual(len(self.game.logs.messages), 3)
 | 
				
			||||||
 | 
					        self.game.player.move(2, 7)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.LEFT)
 | 
				
			||||||
 | 
					        self.assertEqual(len(self.game.logs.messages), 4)
 | 
				
			||||||
 | 
					        self.game.player.move(2, 5)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.RIGHT)
 | 
				
			||||||
 | 
					        self.assertEqual(len(self.game.logs.messages), 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_talk_to_merchant(self) -> None:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Interact with merchants
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.game.state = GameMode.PLAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        merchant = Merchant()
 | 
				
			||||||
 | 
					        merchant.move(2, 6)
 | 
				
			||||||
 | 
					        self.game.map.add_entity(merchant)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Does nothing
 | 
				
			||||||
 | 
					        self.assertIsNone(self.game.handle_friendly_entity_chat(KeyValues.UP))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Talk to merchant
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.CHAT)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
 | 
					        self.assertFalse(self.game.waiting_for_friendly_key)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.STORE)
 | 
				
			||||||
 | 
					        self.assertTrue(self.game.logs.messages)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Navigate in the menu
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.UP)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.store_menu.position, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.game.player.hazel = 0x7ffff42ff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # The second item is not a heart
 | 
				
			||||||
 | 
					        merchant.inventory[1] = Sword()
 | 
				
			||||||
 | 
					        # Buy the second item by clicking on it
 | 
				
			||||||
 | 
					        item = self.game.store_menu.validate()
 | 
				
			||||||
 | 
					        self.assertIn(item, merchant.inventory)
 | 
				
			||||||
 | 
					        self.game.display_actions(DisplayActions.MOUSE, 7, 25)
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					        self.assertIn(item, self.game.player.inventory)
 | 
				
			||||||
 | 
					        self.assertNotIn(item, merchant.inventory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Buy a heart
 | 
				
			||||||
 | 
					        merchant.inventory[1] = Heart()
 | 
				
			||||||
 | 
					        item = self.game.store_menu.validate()
 | 
				
			||||||
 | 
					        self.assertIn(item, merchant.inventory)
 | 
				
			||||||
 | 
					        self.assertEqual(item, merchant.inventory[1])
 | 
				
			||||||
 | 
					        self.game.player.health = self.game.player.maxhealth - 1 - item.healing
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					        self.assertNotIn(item, self.game.player.inventory)
 | 
				
			||||||
 | 
					        self.assertNotIn(item, merchant.inventory)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.player.health,
 | 
				
			||||||
 | 
					                         self.game.player.maxhealth - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # We don't have enough of money
 | 
				
			||||||
 | 
					        self.game.player.hazel = 0
 | 
				
			||||||
 | 
					        item = self.game.store_menu.validate()
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					        self.assertNotIn(item, self.game.player.inventory)
 | 
				
			||||||
 | 
					        self.assertIn(item, merchant.inventory)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.message, _("You do not have enough money"))
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Exit the menu
 | 
				
			||||||
 | 
					        self.game.handle_key_pressed(KeyValues.SPACE)
 | 
				
			||||||
 | 
					        self.assertEqual(self.game.state, GameMode.PLAY)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,17 +50,24 @@ class TestTranslations(unittest.TestCase):
 | 
				
			|||||||
                         "Touche pour équiper un objet de l'inventaire")
 | 
					                         "Touche pour équiper un objet de l'inventaire")
 | 
				
			||||||
        self.assertEqual(_("Key used to drop an item in the inventory"),
 | 
					        self.assertEqual(_("Key used to drop an item in the inventory"),
 | 
				
			||||||
                         "Touche pour jeter un objet de l'inventaire")
 | 
					                         "Touche pour jeter un objet de l'inventaire")
 | 
				
			||||||
 | 
					        self.assertEqual(_("Key used to talk to a friendly entity"),
 | 
				
			||||||
 | 
					                         "Touche pour parler à une entité pacifique")
 | 
				
			||||||
 | 
					        self.assertEqual(_("Key used to wait"), "Touche pour attendre")
 | 
				
			||||||
        self.assertEqual(_("Texture pack"), "Pack de textures")
 | 
					        self.assertEqual(_("Texture pack"), "Pack de textures")
 | 
				
			||||||
        self.assertEqual(_("Language"), "Langue")
 | 
					        self.assertEqual(_("Language"), "Langue")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_entities_translation(self) -> None:
 | 
					    def test_entities_translation(self) -> None:
 | 
				
			||||||
        self.assertEqual(_("player"), "joueur")
 | 
					        self.assertEqual(_("player"), "joueur")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(_("tiger"), "tigre")
 | 
					 | 
				
			||||||
        self.assertEqual(_("hedgehog"), "hérisson")
 | 
					        self.assertEqual(_("hedgehog"), "hérisson")
 | 
				
			||||||
 | 
					        self.assertEqual(_("merchant"), "marchand")
 | 
				
			||||||
        self.assertEqual(_("rabbit"), "lapin")
 | 
					        self.assertEqual(_("rabbit"), "lapin")
 | 
				
			||||||
 | 
					        self.assertEqual(_("sunflower"), "tournesol")
 | 
				
			||||||
        self.assertEqual(_("teddy bear"), "nounours")
 | 
					        self.assertEqual(_("teddy bear"), "nounours")
 | 
				
			||||||
 | 
					        self.assertEqual(_("tiger"), "tigre")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(_("body snatch potion"), "potion d'arrachage de corps")
 | 
					        self.assertEqual(_("body snatch potion"), "potion d'arrachage de corps")
 | 
				
			||||||
        self.assertEqual(_("bomb"), "bombe")
 | 
					        self.assertEqual(_("bomb"), "bombe")
 | 
				
			||||||
 | 
					        self.assertEqual(_("explosion"), "explosion")
 | 
				
			||||||
        self.assertEqual(_("heart"), "cœur")
 | 
					        self.assertEqual(_("heart"), "cœur")
 | 
				
			||||||
 | 
					        self.assertEqual(_("sword"), "épée")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user