Merge branch 'master' into 'doc'
# Conflicts: # squirrelbattle/entities/items.py # squirrelbattle/interfaces.py
This commit is contained in:
commit
196e3708d2
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
|
local/
|
||||||
|
|
||||||
.coverage
|
.coverage
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
1 6
|
1 6
|
||||||
####### #############
|
####### #############
|
||||||
#.....# #...........#
|
#.H...# #...........#
|
||||||
#.....# #####...........#
|
#.....# #####...........#
|
||||||
#.....# #...............#
|
#.....# #............H..#
|
||||||
#.##### #.###...........#
|
#.##### #.###...........#
|
||||||
#.# #.# #...........#
|
#.# #.# #...........#
|
||||||
#.# #.# #############
|
#.# #.# #############
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
1 17
|
1 17
|
||||||
########### #########
|
########### #########
|
||||||
#.........# #.......#
|
#....H....# #.......#
|
||||||
#.........# ############.......#
|
#.........# ############.......#
|
||||||
#.........###############..........#.......##############
|
#.........###############..........#.......##############
|
||||||
#.........#........................#....................#
|
#.........#........................#....................#
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
########.##########......# #.........# #.........#
|
########.##########......# #.........# #.........#
|
||||||
#...........##......# #.........# #.........#
|
#...........##......# #.........# #.........#
|
||||||
#...........##......# #.........# #.........#
|
#...........##......# #.........# #.........#
|
||||||
#...........##......# #.........# ################.######
|
#...........##..H...# #.........# ################.######
|
||||||
#...........##......# #.........# #.................############
|
#...........##......# #.........# #.................############
|
||||||
#...........##......# ########.########.......#.........#..........#
|
#...........##......# ########.########.......#.........#..........#
|
||||||
#...........##......# #...............#.......#.........#..........#
|
#...........##......# #...............#.......#.........#..........#
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
1 6
|
||||||
|
################################################################################
|
||||||
|
#..............................................................................#
|
||||||
|
#..#...........................................................................#
|
||||||
|
#...........#..................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
#..............................................................................#
|
||||||
|
################################################################################
|
|
@ -22,13 +22,21 @@ class MapDisplay(Display):
|
||||||
self.pack.tile_width * self.map.width + 1)
|
self.pack.tile_width * self.map.width + 1)
|
||||||
|
|
||||||
def update_pad(self) -> None:
|
def update_pad(self) -> None:
|
||||||
self.pad.resize(500, 500)
|
for j in range(len(self.map.tiles)):
|
||||||
self.addstr(self.pad, 0, 0, self.map.draw_string(self.pack),
|
for i in range(len(self.map.tiles[j])):
|
||||||
self.pack.tile_fg_color, self.pack.tile_bg_color)
|
if not self.map.seen_tiles[j][i]:
|
||||||
|
continue
|
||||||
|
fg, bg = self.map.tiles[j][i].visible_color(self.pack) if \
|
||||||
|
self.map.visibility[j][i] else \
|
||||||
|
self.map.tiles[j][i].hidden_color(self.pack)
|
||||||
|
self.addstr(self.pad, j, self.pack.tile_width * i,
|
||||||
|
self.map.tiles[j][i].char(self.pack), fg, bg)
|
||||||
for e in self.map.entities:
|
for e in self.map.entities:
|
||||||
|
if self.map.visibility[e.y][e.x]:
|
||||||
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.pack[e.name.upper()],
|
||||||
self.pack.entity_fg_color, self.pack.entity_bg_color)
|
self.pack.entity_fg_color,
|
||||||
|
self.pack.entity_bg_color)
|
||||||
|
|
||||||
# Display Path map for debug purposes
|
# Display Path map for debug purposes
|
||||||
# from squirrelbattle.entities.player import Player
|
# from squirrelbattle.entities.player import Player
|
||||||
|
|
|
@ -23,16 +23,18 @@ class StatsDisplay(Display):
|
||||||
self.player = game.player
|
self.player = game.player
|
||||||
|
|
||||||
def update_pad(self) -> None:
|
def update_pad(self) -> None:
|
||||||
string2 = _("player").capitalize() + " -- LVL {}\nEXP {}/{}\nHP {}/{}"\
|
string2 = f"{_(self.player.name).capitalize()} " \
|
||||||
.format(self.player.level, self.player.current_xp,
|
f"-- LVL {self.player.level} -- " \
|
||||||
self.player.max_xp, self.player.health,
|
f"FLOOR {-self.player.map.floor}\n" \
|
||||||
self.player.maxhealth)
|
f"EXP {self.player.current_xp}/{self.player.max_xp}\n" \
|
||||||
|
f"HP {self.player.health}/{self.player.maxhealth}"
|
||||||
self.addstr(self.pad, 0, 0, string2)
|
self.addstr(self.pad, 0, 0, string2)
|
||||||
string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}\nCRI {}%"\
|
string3 = f"STR {self.player.strength}\n" \
|
||||||
.format(self.player.strength,
|
f"INT {self.player.intelligence}\n" \
|
||||||
self.player.intelligence, self.player.charisma,
|
f"CHR {self.player.charisma}\n" \
|
||||||
self.player.dexterity, self.player.constitution,\
|
f"DEX {self.player.dexterity}\n" \
|
||||||
self.player.critical)
|
f"CON {self.player.constitution}\n" \
|
||||||
|
f"CRI {self.player.critical}%"
|
||||||
self.addstr(self.pad, 3, 0, string3)
|
self.addstr(self.pad, 3, 0, string3)
|
||||||
|
|
||||||
inventory_str = _("Inventory:") + " "
|
inventory_str = _("Inventory:") + " "
|
||||||
|
@ -57,15 +59,16 @@ class StatsDisplay(Display):
|
||||||
if self.player.equipped_secondary:
|
if self.player.equipped_secondary:
|
||||||
self.addstr(self.pad, 11, 0,
|
self.addstr(self.pad, 11, 0,
|
||||||
_("Equipped secondary:") + " "
|
_("Equipped secondary:") + " "
|
||||||
f"{self.pack[self.player.equipped_secondary.name.upper()]}")
|
+ self.pack[self.player.equipped_secondary
|
||||||
|
.name.upper()])
|
||||||
if self.player.equipped_armor:
|
if self.player.equipped_armor:
|
||||||
self.addstr(self.pad, 12, 0,
|
self.addstr(self.pad, 12, 0,
|
||||||
_("Equipped chestplate:") + " "
|
_("Equipped chestplate:") + " "
|
||||||
f"{self.pack[self.player.equipped_armor.name.upper()]}")
|
+ self.pack[self.player.equipped_armor.name.upper()])
|
||||||
if self.player.equipped_helmet:
|
if self.player.equipped_helmet:
|
||||||
self.addstr(self.pad, 13, 0,
|
self.addstr(self.pad, 13, 0,
|
||||||
_("Equipped helmet:") + " "
|
_("Equipped helmet:") + " "
|
||||||
f"{self.pack[self.player.equipped_helmet.name.upper()]}")
|
+ self.pack[self.player.equipped_helmet.name.upper()])
|
||||||
|
|
||||||
self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} "
|
self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} "
|
||||||
f"x{self.player.hazel}")
|
f"x{self.player.hazel}")
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import curses
|
import curses
|
||||||
from typing import Any
|
from typing import Any, Union, Tuple
|
||||||
|
|
||||||
|
|
||||||
class TexturePack:
|
class TexturePack:
|
||||||
|
@ -13,10 +13,11 @@ class TexturePack:
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
tile_width: int
|
tile_width: int
|
||||||
tile_fg_color: int
|
tile_fg_color: Union[int, Tuple[int, int, int]]
|
||||||
tile_bg_color: int
|
tile_fg_visible_color: Union[int, Tuple[int, int, int]]
|
||||||
entity_fg_color: int
|
tile_bg_color: Union[int, Tuple[int, int, int]]
|
||||||
entity_bg_color: int
|
entity_fg_color: Union[int, Tuple[int, int, int]]
|
||||||
|
entity_bg_color: Union[int, Tuple[int, int, int]]
|
||||||
|
|
||||||
BODY_SNATCH_POTION: str
|
BODY_SNATCH_POTION: str
|
||||||
BOMB: str
|
BOMB: str
|
||||||
|
@ -64,9 +65,10 @@ class TexturePack:
|
||||||
TexturePack.ASCII_PACK = TexturePack(
|
TexturePack.ASCII_PACK = TexturePack(
|
||||||
name="ascii",
|
name="ascii",
|
||||||
tile_width=1,
|
tile_width=1,
|
||||||
|
tile_fg_visible_color=(1000, 1000, 1000),
|
||||||
tile_fg_color=curses.COLOR_WHITE,
|
tile_fg_color=curses.COLOR_WHITE,
|
||||||
tile_bg_color=curses.COLOR_BLACK,
|
tile_bg_color=curses.COLOR_BLACK,
|
||||||
entity_fg_color=curses.COLOR_WHITE,
|
entity_fg_color=(1000, 1000, 1000),
|
||||||
entity_bg_color=curses.COLOR_BLACK,
|
entity_bg_color=curses.COLOR_BLACK,
|
||||||
|
|
||||||
BODY_SNATCH_POTION='S',
|
BODY_SNATCH_POTION='S',
|
||||||
|
@ -76,6 +78,7 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||||
EMPTY=' ',
|
EMPTY=' ',
|
||||||
EXPLOSION='%',
|
EXPLOSION='%',
|
||||||
FLOOR='.',
|
FLOOR='.',
|
||||||
|
LADDER='H',
|
||||||
HAZELNUT='¤',
|
HAZELNUT='¤',
|
||||||
HEART='❤',
|
HEART='❤',
|
||||||
HEDGEHOG='*',
|
HEDGEHOG='*',
|
||||||
|
@ -97,10 +100,11 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||||
TexturePack.SQUIRREL_PACK = TexturePack(
|
TexturePack.SQUIRREL_PACK = TexturePack(
|
||||||
name="squirrel",
|
name="squirrel",
|
||||||
tile_width=2,
|
tile_width=2,
|
||||||
|
tile_fg_visible_color=(1000, 1000, 1000),
|
||||||
tile_fg_color=curses.COLOR_WHITE,
|
tile_fg_color=curses.COLOR_WHITE,
|
||||||
tile_bg_color=curses.COLOR_BLACK,
|
tile_bg_color=curses.COLOR_BLACK,
|
||||||
entity_fg_color=curses.COLOR_WHITE,
|
entity_fg_color=(1000, 1000, 1000),
|
||||||
entity_bg_color=curses.COLOR_WHITE,
|
entity_bg_color=(1000, 1000, 1000),
|
||||||
|
|
||||||
BODY_SNATCH_POTION='🔀',
|
BODY_SNATCH_POTION='🔀',
|
||||||
BOMB='💣',
|
BOMB='💣',
|
||||||
|
@ -109,6 +113,8 @@ TexturePack.SQUIRREL_PACK = TexturePack(
|
||||||
EMPTY=' ',
|
EMPTY=' ',
|
||||||
EXPLOSION='💥',
|
EXPLOSION='💥',
|
||||||
FLOOR='██',
|
FLOOR='██',
|
||||||
|
LADDER=('🪜', curses.COLOR_WHITE, (1000, 1000, 1000),
|
||||||
|
curses.COLOR_WHITE, (1000, 1000, 1000)),
|
||||||
HAZELNUT='🌰',
|
HAZELNUT='🌰',
|
||||||
HEART='💜',
|
HEART='💜',
|
||||||
HEDGEHOG='🦔',
|
HEDGEHOG='🦔',
|
||||||
|
|
|
@ -44,27 +44,6 @@ class Item(Entity):
|
||||||
"""
|
"""
|
||||||
Indicates what should be done when the item is equipped.
|
Indicates what should be done when the item is equipped.
|
||||||
"""
|
"""
|
||||||
if isinstance(self, Chestplate):
|
|
||||||
if self.held_by.equipped_armor:
|
|
||||||
self.held_by.equipped_armor.unequip()
|
|
||||||
self.held_by.remove_from_inventory(self)
|
|
||||||
self.held_by.equipped_armor = self
|
|
||||||
elif isinstance(self, Helmet):
|
|
||||||
if self.held_by.equipped_helmet:
|
|
||||||
self.held_by.equipped_helmet.unequip()
|
|
||||||
self.held_by.remove_from_inventory(self)
|
|
||||||
self.held_by.equipped_helmet = self
|
|
||||||
elif isinstance(self, Weapon):
|
|
||||||
if self.held_by.equipped_main:
|
|
||||||
if self.held_by.equipped_secondary:
|
|
||||||
self.held_by.equipped_secondary.unequip()
|
|
||||||
self.held_by.remove_from_inventory(self)
|
|
||||||
self.held_by.equipped_secondary = self
|
|
||||||
# For weapons, they are equipped as main only if main is empty.
|
|
||||||
else:
|
|
||||||
self.held_by.remove_from_inventory(self)
|
|
||||||
self.held_by.equipped_main = self
|
|
||||||
else:
|
|
||||||
# Other objects are only equipped as secondary.
|
# Other objects are only equipped as secondary.
|
||||||
if self.held_by.equipped_secondary:
|
if self.held_by.equipped_secondary:
|
||||||
self.held_by.equipped_secondary.unequip()
|
self.held_by.equipped_secondary.unequip()
|
||||||
|
@ -75,17 +54,7 @@ class Item(Entity):
|
||||||
"""
|
"""
|
||||||
Indicates what should be done when the item is unequipped.
|
Indicates what should be done when the item is unequipped.
|
||||||
"""
|
"""
|
||||||
if isinstance(self, Chestplate):
|
self.held_by.remove_from_inventory(self)
|
||||||
self.held_by.equipped_armor = None
|
|
||||||
elif isinstance(self, Helmet):
|
|
||||||
self.held_by.equipped_helmet = None
|
|
||||||
elif isinstance(self, Weapon):
|
|
||||||
if self.held_by.equipped_main == self:
|
|
||||||
self.held_by.equipped_main = None
|
|
||||||
else:
|
|
||||||
self.held_by.equipped_secondary = None
|
|
||||||
else:
|
|
||||||
self.held_by.equipped_secondary = None
|
|
||||||
self.held_by.add_to_inventory(self)
|
self.held_by.add_to_inventory(self)
|
||||||
|
|
||||||
def hold(self, holder: InventoryHolder) -> None:
|
def hold(self, holder: InventoryHolder) -> None:
|
||||||
|
@ -236,7 +205,6 @@ class Explosion(Item):
|
||||||
"""
|
"""
|
||||||
The player can't hold an explosion.
|
The player can't hold an explosion.
|
||||||
"""
|
"""
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Weapon(Item):
|
class Weapon(Item):
|
||||||
|
@ -261,7 +229,8 @@ class Weapon(Item):
|
||||||
"""
|
"""
|
||||||
When a weapon is equipped, the player gains strength.
|
When a weapon is equipped, the player gains strength.
|
||||||
"""
|
"""
|
||||||
super().equip()
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_main = self
|
||||||
self.held_by.strength += self.damage
|
self.held_by.strength += self.damage
|
||||||
|
|
||||||
def unequip(self) -> None:
|
def unequip(self) -> None:
|
||||||
|
@ -305,33 +274,45 @@ class Armor(Item):
|
||||||
d["constitution"] = self.constitution
|
d["constitution"] = self.constitution
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class Shield(Armor):
|
class Shield(Armor):
|
||||||
"""
|
"""
|
||||||
Class of shield items, they can be equipped in the other hand.
|
Class of shield items, they can be equipped in the other hand.
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, name: str = "shield", constitution: int = 2,
|
||||||
def __init__(self, name: str = "shield", constitution: int = 2,\
|
|
||||||
price: int = 16, *args, **kwargs):
|
price: int = 16, *args, **kwargs):
|
||||||
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
super().__init__(name=name, constitution=constitution, price=price,
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
class Helmet(Armor):
|
class Helmet(Armor):
|
||||||
"""
|
"""
|
||||||
Class of helmet items, they can be equipped on the head.
|
Class of helmet items, they can be equipped on the head.
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, name: str = "helmet", constitution: int = 2,
|
||||||
def __init__(self, name: str = "helmet", constitution: int = 2, \
|
|
||||||
price: int = 18, *args, **kwargs):
|
price: int = 18, *args, **kwargs):
|
||||||
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
super().__init__(name=name, constitution=constitution, price=price,
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
def equip(self) -> None:
|
||||||
|
if self.held_by.equipped_helmet:
|
||||||
|
self.held_by.equipped_helmet.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_helmet = self
|
||||||
|
|
||||||
class Chestplate(Armor):
|
class Chestplate(Armor):
|
||||||
"""
|
"""
|
||||||
Class of chestplate items, they can be equipped on the body.
|
Class of chestplate items, they can be equipped on the body.
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, name: str = "chestplate", constitution: int = 4,
|
||||||
def __init__(self, name: str = "chestplate", constitution: int = 4,\
|
|
||||||
price: int = 30, *args, **kwargs):
|
price: int = 30, *args, **kwargs):
|
||||||
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
super().__init__(name=name, constitution=constitution, price=price,
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
def equip(self) -> None:
|
||||||
|
if self.held_by.equipped_armor:
|
||||||
|
self.held_by.equipped_armor.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_armor = self
|
||||||
|
|
||||||
class BodySnatchPotion(Item):
|
class BodySnatchPotion(Item):
|
||||||
"""
|
"""
|
||||||
|
@ -366,6 +347,7 @@ class BodySnatchPotion(Item):
|
||||||
|
|
||||||
self.held_by.inventory.remove(self)
|
self.held_by.inventory.remove(self)
|
||||||
|
|
||||||
|
|
||||||
class Ring(Item):
|
class Ring(Item):
|
||||||
"""
|
"""
|
||||||
A class of rings that boost the player's statistics.
|
A class of rings that boost the player's statistics.
|
||||||
|
@ -379,9 +361,9 @@ class Ring(Item):
|
||||||
critical: int
|
critical: int
|
||||||
experience: float
|
experience: float
|
||||||
|
|
||||||
def __init__(self, maxhealth: int = 0, strength: int = 0,\
|
def __init__(self, maxhealth: int = 0, strength: int = 0,
|
||||||
intelligence: int = 0, charisma: int = 0,\
|
intelligence: int = 0, charisma: int = 0,
|
||||||
dexterity: int = 0, constitution: int = 0,\
|
dexterity: int = 0, constitution: int = 0,
|
||||||
critical: int = 0, experience: float = 0, *args, **kwargs):
|
critical: int = 0, experience: float = 0, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.maxhealth = maxhealth
|
self.maxhealth = maxhealth
|
||||||
|
@ -417,17 +399,26 @@ class Ring(Item):
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
d = super().save_state()
|
d = super().save_state()
|
||||||
|
d["maxhealth"] = self.maxhealth
|
||||||
|
d["strength"] = self.strength
|
||||||
|
d["intelligence"] = self.intelligence
|
||||||
|
d["charisma"] = self.charisma
|
||||||
|
d["dexterity"] = self.dexterity
|
||||||
d["constitution"] = self.constitution
|
d["constitution"] = self.constitution
|
||||||
|
d["critical"] = self.critical
|
||||||
|
d["experience"] = self.experience
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class RingCritical(Ring):
|
class RingCritical(Ring):
|
||||||
def __init__(self, name: str = "ring_of_critical_damage", price: int = 15,
|
def __init__(self, name: str = "ring_of_critical_damage", price: int = 15,
|
||||||
critical: int = 20, *args, **kwargs):
|
critical: int = 20, *args, **kwargs):
|
||||||
super().__init__(name=name, price=price, critical=critical, \
|
super().__init__(name=name, price=price, critical=critical,
|
||||||
*args, **kwargs)
|
*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RingXP(Ring):
|
class RingXP(Ring):
|
||||||
def __init__(self, name: str = "ring_of_more_experience", price: int = 25,
|
def __init__(self, name: str = "ring_of_more_experience", price: int = 25,
|
||||||
experience: float = 2, *args, **kwargs):
|
experience: float = 2, *args, **kwargs):
|
||||||
super().__init__(name=name, price=price, experience=experience, \
|
super().__init__(name=name, price=price, experience=experience,
|
||||||
*args, **kwargs)
|
*args, **kwargs)
|
||||||
|
|
|
@ -94,9 +94,11 @@ class Rabbit(Monster):
|
||||||
A rabbit monster.
|
A rabbit monster.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name: str = "rabbit", strength: int = 1,
|
def __init__(self, name: str = "rabbit", strength: int = 1,
|
||||||
maxhealth: int = 15, critical: int = 30, *args, **kwargs) -> None:
|
maxhealth: int = 15, critical: int = 30,
|
||||||
|
*args, **kwargs) -> None:
|
||||||
super().__init__(name=name, strength=strength,
|
super().__init__(name=name, strength=strength,
|
||||||
maxhealth=maxhealth, critical=critical, *args, **kwargs)
|
maxhealth=maxhealth, critical=critical,
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TeddyBear(Monster):
|
class TeddyBear(Monster):
|
||||||
|
@ -108,6 +110,7 @@ class TeddyBear(Monster):
|
||||||
super().__init__(name=name, strength=strength,
|
super().__init__(name=name, strength=strength,
|
||||||
maxhealth=maxhealth, *args, **kwargs)
|
maxhealth=maxhealth, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class GiantSeaEagle(Monster):
|
class GiantSeaEagle(Monster):
|
||||||
"""
|
"""
|
||||||
An eagle boss
|
An eagle boss
|
||||||
|
|
|
@ -26,10 +26,10 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
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,
|
||||||
hazel: int = 42, equipped_main: Optional[Item] = None,
|
hazel: int = 42, equipped_main: Optional[Item] = None,
|
||||||
equipped_armor: Optional[Item] = None, critical: int = 5,\
|
equipped_armor: Optional[Item] = None, critical: int = 5,
|
||||||
equipped_secondary: Optional[Item] = None, \
|
equipped_secondary: Optional[Item] = None,
|
||||||
equipped_helmet: Optional[Item] = None, xp_buff: float = 1,\
|
equipped_helmet: Optional[Item] = None, xp_buff: float = 1,
|
||||||
*args, **kwargs) -> None:
|
vision: int = 5, *args, **kwargs) -> 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,
|
||||||
dexterity=dexterity, constitution=constitution,
|
dexterity=dexterity, constitution=constitution,
|
||||||
|
@ -40,18 +40,15 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
self.inventory = self.translate_inventory(inventory or [])
|
self.inventory = self.translate_inventory(inventory or [])
|
||||||
self.paths = dict()
|
self.paths = dict()
|
||||||
self.hazel = hazel
|
self.hazel = hazel
|
||||||
if isinstance(equipped_main, dict):
|
self.equipped_main = self.dict_to_item(equipped_main) \
|
||||||
equipped_main = self.dict_to_item(equipped_main)
|
if isinstance(equipped_main, dict) else equipped_main
|
||||||
if isinstance(equipped_armor, dict):
|
self.equipped_armor = self.dict_to_item(equipped_armor) \
|
||||||
equipped_armor = self.dict_to_item(equipped_armor)
|
if isinstance(equipped_armor, dict) else equipped_armor
|
||||||
if isinstance(equipped_secondary, dict):
|
self.equipped_secondary = self.dict_to_item(equipped_secondary) \
|
||||||
equipped_secondary = self.dict_to_item(equipped_secondary)
|
if isinstance(equipped_secondary, dict) else equipped_secondary
|
||||||
if isinstance(equipped_helmet, dict):
|
self.equipped_helmet = self.dict_to_item(equipped_helmet) \
|
||||||
equipped_helmet = self.dict_to_item(equipped_helmet)
|
if isinstance(equipped_helmet, dict) else equipped_helmet
|
||||||
self.equipped_main = equipped_main
|
self.vision = vision
|
||||||
self.equipped_armor = equipped_armor
|
|
||||||
self.equipped_secondary = equipped_secondary
|
|
||||||
self.equipped_helmet = equipped_helmet
|
|
||||||
|
|
||||||
def move(self, y: int, x: int) -> None:
|
def move(self, y: int, x: int) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -62,6 +59,7 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
self.map.currenty = y
|
self.map.currenty = y
|
||||||
self.map.currentx = x
|
self.map.currentx = x
|
||||||
self.recalculate_paths()
|
self.recalculate_paths()
|
||||||
|
self.map.compute_visibility(self.y, self.x, self.vision)
|
||||||
|
|
||||||
def level_up(self) -> None:
|
def level_up(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -82,7 +80,7 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
Adds some experience to the player.
|
Adds some experience to the player.
|
||||||
If the required amount is reached, the player levels up.
|
If the required amount is reached, the player levels up.
|
||||||
"""
|
"""
|
||||||
self.current_xp += int(xp*self.xp_buff)
|
self.current_xp += int(xp * self.xp_buff)
|
||||||
self.level_up()
|
self.level_up()
|
||||||
|
|
||||||
def remove_from_inventory(self, obj: Item) -> None:
|
def remove_from_inventory(self, obj: Item) -> None:
|
||||||
|
|
|
@ -47,6 +47,7 @@ class KeyValues(Enum):
|
||||||
SPACE = auto()
|
SPACE = auto()
|
||||||
CHAT = auto()
|
CHAT = auto()
|
||||||
WAIT = auto()
|
WAIT = auto()
|
||||||
|
LADDER = auto()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]:
|
def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]:
|
||||||
|
@ -81,4 +82,6 @@ class KeyValues(Enum):
|
||||||
return KeyValues.CHAT
|
return KeyValues.CHAT
|
||||||
elif key == settings.KEY_WAIT:
|
elif key == settings.KEY_WAIT:
|
||||||
return KeyValues.WAIT
|
return KeyValues.WAIT
|
||||||
|
elif key == settings.KEY_LADDER:
|
||||||
|
return KeyValues.LADDER
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -3,7 +3,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, List
|
||||||
import curses
|
import curses
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
@ -22,7 +22,8 @@ class Game:
|
||||||
"""
|
"""
|
||||||
The game object controls all actions in the game.
|
The game object controls all actions in the game.
|
||||||
"""
|
"""
|
||||||
map: Map
|
maps: List[Map]
|
||||||
|
map_index: int
|
||||||
player: Player
|
player: Player
|
||||||
screen: Any
|
screen: Any
|
||||||
# display_actions is a display interface set by the bootstrapper
|
# display_actions is a display interface set by the bootstrapper
|
||||||
|
@ -52,7 +53,9 @@ class Game:
|
||||||
Creates a new game on the screen.
|
Creates a new game on the screen.
|
||||||
"""
|
"""
|
||||||
# TODO generate a new map procedurally
|
# TODO generate a new map procedurally
|
||||||
self.map = Map.load(ResourceManager.get_asset_path("example_map_2.txt"))
|
self.maps = []
|
||||||
|
self.map_index = 0
|
||||||
|
self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
|
||||||
self.map.logs = self.logs
|
self.map.logs = self.logs
|
||||||
self.logs.clear()
|
self.logs.clear()
|
||||||
self.player = Player()
|
self.player = Player()
|
||||||
|
@ -61,6 +64,24 @@ class Game:
|
||||||
self.map.spawn_random_entities(randint(3, 10))
|
self.map.spawn_random_entities(randint(3, 10))
|
||||||
self.inventory_menu.update_player(self.player)
|
self.inventory_menu.update_player(self.player)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def map(self) -> Map:
|
||||||
|
"""
|
||||||
|
Return the current map where the user is.
|
||||||
|
"""
|
||||||
|
return self.maps[self.map_index]
|
||||||
|
|
||||||
|
@map.setter
|
||||||
|
def map(self, m: Map) -> None:
|
||||||
|
"""
|
||||||
|
Redefine the current map.
|
||||||
|
"""
|
||||||
|
if len(self.maps) == self.map_index:
|
||||||
|
# Insert new map
|
||||||
|
self.maps.append(m)
|
||||||
|
# Redefine the current map
|
||||||
|
self.maps[self.map_index] = m
|
||||||
|
|
||||||
def run(self, screen: Any) -> None: # pragma no cover
|
def run(self, screen: Any) -> None: # pragma no cover
|
||||||
"""
|
"""
|
||||||
Main infinite loop.
|
Main infinite loop.
|
||||||
|
@ -110,7 +131,7 @@ class Game:
|
||||||
self.state = GameMode.MAINMENU
|
self.state = GameMode.MAINMENU
|
||||||
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: # noqa: C901
|
||||||
"""
|
"""
|
||||||
In play mode, arrows or zqsd move the main character.
|
In play mode, arrows or zqsd move the main character.
|
||||||
"""
|
"""
|
||||||
|
@ -130,7 +151,10 @@ class Game:
|
||||||
self.state = GameMode.INVENTORY
|
self.state = GameMode.INVENTORY
|
||||||
self.display_actions(DisplayActions.UPDATE)
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
elif key == KeyValues.USE and self.player.equipped_main:
|
elif key == KeyValues.USE and self.player.equipped_main:
|
||||||
|
if self.player.equipped_main:
|
||||||
self.player.equipped_main.use()
|
self.player.equipped_main.use()
|
||||||
|
if self.player.equipped_secondary:
|
||||||
|
self.player.equipped_secondary.use()
|
||||||
elif key == KeyValues.SPACE:
|
elif key == KeyValues.SPACE:
|
||||||
self.state = GameMode.MAINMENU
|
self.state = GameMode.MAINMENU
|
||||||
elif key == KeyValues.CHAT:
|
elif key == KeyValues.CHAT:
|
||||||
|
@ -138,6 +162,54 @@ class Game:
|
||||||
self.waiting_for_friendly_key = True
|
self.waiting_for_friendly_key = True
|
||||||
elif key == KeyValues.WAIT:
|
elif key == KeyValues.WAIT:
|
||||||
self.map.tick(self.player)
|
self.map.tick(self.player)
|
||||||
|
elif key == KeyValues.LADDER:
|
||||||
|
self.handle_ladder()
|
||||||
|
|
||||||
|
def handle_ladder(self) -> None:
|
||||||
|
"""
|
||||||
|
The player pressed the ladder key to switch map
|
||||||
|
"""
|
||||||
|
# On a ladder, we switch level
|
||||||
|
y, x = self.player.y, self.player.x
|
||||||
|
if not self.map.tiles[y][x].is_ladder():
|
||||||
|
return
|
||||||
|
|
||||||
|
# We move up on the ladder of the beginning,
|
||||||
|
# down at the end of the stage
|
||||||
|
move_down = y != self.map.start_y and x != self.map.start_x
|
||||||
|
old_map = self.map
|
||||||
|
self.map_index += 1 if move_down else -1
|
||||||
|
if self.map_index == -1:
|
||||||
|
self.map_index = 0
|
||||||
|
return
|
||||||
|
while self.map_index >= len(self.maps):
|
||||||
|
# TODO: generate a new map
|
||||||
|
self.maps.append(Map.load(ResourceManager.get_asset_path(
|
||||||
|
"example_map_2.txt")))
|
||||||
|
new_map = self.map
|
||||||
|
new_map.floor = self.map_index
|
||||||
|
old_map.remove_entity(self.player)
|
||||||
|
new_map.add_entity(self.player)
|
||||||
|
if move_down:
|
||||||
|
self.player.move(self.map.start_y, self.map.start_x)
|
||||||
|
self.logs.add_message(
|
||||||
|
_("The player climbs down to the floor {floor}.")
|
||||||
|
.format(floor=-self.map_index))
|
||||||
|
else:
|
||||||
|
# Find the ladder of the end of the game
|
||||||
|
ladder_y, ladder_x = -1, -1
|
||||||
|
for y in range(self.map.height):
|
||||||
|
for x in range(self.map.width):
|
||||||
|
if (y, x) != (self.map.start_y, self.map.start_x) \
|
||||||
|
and self.map.tiles[y][x].is_ladder():
|
||||||
|
ladder_y, ladder_x = y, x
|
||||||
|
break
|
||||||
|
self.player.move(ladder_y, ladder_x)
|
||||||
|
self.logs.add_message(
|
||||||
|
_("The player climbs up the floor {floor}.")
|
||||||
|
.format(floor=-self.map_index))
|
||||||
|
|
||||||
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
|
|
||||||
def handle_friendly_entity_chat(self, key: KeyValues) -> None:
|
def handle_friendly_entity_chat(self, key: KeyValues) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from math import sqrt
|
from math import ceil, sqrt
|
||||||
from random import choice, randint
|
from random import choice, choices, randint
|
||||||
from typing import List, Optional, Any, Dict, Tuple
|
from typing import List, Optional, Any, Dict, Tuple
|
||||||
from queue import PriorityQueue
|
from queue import PriorityQueue
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from random import choice, randint, choices
|
|
||||||
from typing import List, Optional, Any
|
|
||||||
|
|
||||||
from .display.texturepack import TexturePack
|
from .display.texturepack import TexturePack
|
||||||
from .translations import gettext as _
|
from .translations import gettext as _
|
||||||
|
@ -34,16 +32,47 @@ class Logs:
|
||||||
self.messages = []
|
self.messages = []
|
||||||
|
|
||||||
|
|
||||||
|
class Slope():
|
||||||
|
X: int
|
||||||
|
Y: int
|
||||||
|
|
||||||
|
def __init__(self, y: int, x: int) -> None:
|
||||||
|
self.Y = y
|
||||||
|
self.X = x
|
||||||
|
|
||||||
|
def compare(self, other: "Slope") -> int:
|
||||||
|
y, x = other.Y, other.X
|
||||||
|
return self.Y * x - self.X * y
|
||||||
|
|
||||||
|
def __lt__(self, other: "Slope") -> bool:
|
||||||
|
return self.compare(other) < 0
|
||||||
|
|
||||||
|
def __eq__(self, other: "Slope") -> bool:
|
||||||
|
return self.compare(other) == 0
|
||||||
|
|
||||||
|
def __gt__(self, other: "Slope") -> bool:
|
||||||
|
return self.compare(other) > 0
|
||||||
|
|
||||||
|
def __le__(self, other: "Slope") -> bool:
|
||||||
|
return self.compare(other) <= 0
|
||||||
|
|
||||||
|
def __ge__(self, other: "Slope") -> bool:
|
||||||
|
return self.compare(other) >= 0
|
||||||
|
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
"""
|
"""
|
||||||
The Map object represents a with its width, height
|
The Map object represents a with its width, height
|
||||||
and tiles, that have their custom properties.
|
and tiles, that have their custom properties.
|
||||||
"""
|
"""
|
||||||
|
floor: int
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
start_y: int
|
start_y: int
|
||||||
start_x: int
|
start_x: int
|
||||||
tiles: List[List["Tile"]]
|
tiles: List[List["Tile"]]
|
||||||
|
visibility: List[List[bool]]
|
||||||
|
seen_tiles: List[List[bool]]
|
||||||
entities: List["Entity"]
|
entities: List["Entity"]
|
||||||
logs: Logs
|
logs: Logs
|
||||||
# coordinates of the point that should be
|
# coordinates of the point that should be
|
||||||
|
@ -53,11 +82,16 @@ class Map:
|
||||||
|
|
||||||
def __init__(self, width: int, height: int, tiles: list,
|
def __init__(self, width: int, height: int, tiles: list,
|
||||||
start_y: int, start_x: int):
|
start_y: int, start_x: int):
|
||||||
|
self.floor = 0
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.start_y = start_y
|
self.start_y = start_y
|
||||||
self.start_x = start_x
|
self.start_x = start_x
|
||||||
self.tiles = tiles
|
self.tiles = tiles
|
||||||
|
self.visibility = [[False for _ in range(len(tiles[0]))]
|
||||||
|
for _ in range(len(tiles))]
|
||||||
|
self.seen_tiles = [[False for _ in range(len(tiles[0]))]
|
||||||
|
for _ in range(len(tiles))]
|
||||||
self.entities = []
|
self.entities = []
|
||||||
self.logs = Logs()
|
self.logs = Logs()
|
||||||
|
|
||||||
|
@ -147,18 +181,138 @@ class Map:
|
||||||
"""
|
"""
|
||||||
Puts randomly {count} entities on the map, only on empty ground tiles.
|
Puts randomly {count} entities on the map, only on empty ground tiles.
|
||||||
"""
|
"""
|
||||||
for ignored in range(count):
|
for _ignored in range(count):
|
||||||
y, x = 0, 0
|
y, x = 0, 0
|
||||||
while True:
|
while True:
|
||||||
y, x = randint(0, self.height - 1), randint(0, self.width - 1)
|
y, x = randint(0, self.height - 1), randint(0, self.width - 1)
|
||||||
tile = self.tiles[y][x]
|
tile = self.tiles[y][x]
|
||||||
if tile.can_walk():
|
if tile.can_walk():
|
||||||
break
|
break
|
||||||
entity = choices(Entity.get_all_entity_classes(),\
|
entity = choices(Entity.get_all_entity_classes(),
|
||||||
weights = Entity.get_weights(), k=1)[0]()
|
weights=Entity.get_weights(), k=1)[0]()
|
||||||
entity.move(y, x)
|
entity.move(y, x)
|
||||||
self.add_entity(entity)
|
self.add_entity(entity)
|
||||||
|
|
||||||
|
def compute_visibility(self, y: int, x: int, max_range: int) -> None:
|
||||||
|
"""
|
||||||
|
Sets the visible tiles to be the ones visible by an entity at point
|
||||||
|
(y, x), using a twaked shadow casting algorithm
|
||||||
|
"""
|
||||||
|
|
||||||
|
for line in self.visibility:
|
||||||
|
for i in range(len(line)):
|
||||||
|
line[i] = False
|
||||||
|
self.set_visible(0, 0, 0, (y, x))
|
||||||
|
for octant in range(8):
|
||||||
|
self.compute_visibility_octant(octant, (y, x), max_range, 1,
|
||||||
|
Slope(1, 1), Slope(0, 1))
|
||||||
|
|
||||||
|
def crop_top_visibility(self, octant: int, origin: Tuple[int, int],
|
||||||
|
x: int, top: Slope) -> int:
|
||||||
|
if top.X == 1:
|
||||||
|
top_y = x
|
||||||
|
else:
|
||||||
|
top_y = ceil(((x * 2 - 1) * top.Y + top.X) / (top.X * 2))
|
||||||
|
if self.is_wall(top_y, x, octant, origin):
|
||||||
|
top_y += top >= Slope(top_y * 2 + 1, x * 2) and not \
|
||||||
|
self.is_wall(top_y + 1, x, octant, origin)
|
||||||
|
else:
|
||||||
|
ax = x * 2
|
||||||
|
ax += self.is_wall(top_y + 1, x + 1, octant, origin)
|
||||||
|
top_y += top > Slope(top_y * 2 + 1, ax)
|
||||||
|
return top_y
|
||||||
|
|
||||||
|
def crop_bottom_visibility(self, octant: int, origin: Tuple[int, int],
|
||||||
|
x: int, bottom: Slope) -> int:
|
||||||
|
if bottom.Y == 0:
|
||||||
|
bottom_y = 0
|
||||||
|
else:
|
||||||
|
bottom_y = ceil(((x * 2 - 1) * bottom.Y + bottom.X)
|
||||||
|
/ (bottom.X * 2))
|
||||||
|
bottom_y += bottom >= Slope(bottom_y * 2 + 1, x * 2) and \
|
||||||
|
self.is_wall(bottom_y, x, octant, origin) and \
|
||||||
|
not self.is_wall(bottom_y + 1, x, octant, origin)
|
||||||
|
return bottom_y
|
||||||
|
|
||||||
|
def compute_visibility_octant(self, octant: int, origin: Tuple[int, int],
|
||||||
|
max_range: int, distance: int, top: Slope,
|
||||||
|
bottom: Slope) -> None:
|
||||||
|
for x in range(distance, max_range + 1):
|
||||||
|
top_y = self.crop_top_visibility(octant, origin, x, top)
|
||||||
|
bottom_y = self.crop_bottom_visibility(octant, origin, x, bottom)
|
||||||
|
was_opaque = -1
|
||||||
|
for y in range(top_y, bottom_y - 1, -1):
|
||||||
|
if x + y > max_range:
|
||||||
|
continue
|
||||||
|
is_opaque = self.is_wall(y, x, octant, origin)
|
||||||
|
is_visible = is_opaque\
|
||||||
|
or ((y != top_y or top > Slope(y * 4 - 1, x * 4 + 1))
|
||||||
|
and (y != bottom_y
|
||||||
|
or bottom < Slope(y * 4 + 1, x * 4 - 1)))
|
||||||
|
# is_visible = is_opaque\
|
||||||
|
# or ((y != top_y or top >= Slope(y, x))
|
||||||
|
# and (y != bottom_y or bottom <= Slope(y, x)))
|
||||||
|
if is_visible:
|
||||||
|
self.set_visible(y, x, octant, origin)
|
||||||
|
if x == max_range:
|
||||||
|
continue
|
||||||
|
if is_opaque and was_opaque == 0:
|
||||||
|
nx, ny = x * 2, y * 2 + 1
|
||||||
|
nx -= self.is_wall(y + 1, x, octant, origin)
|
||||||
|
if top > Slope(ny, nx):
|
||||||
|
if y == bottom_y:
|
||||||
|
bottom = Slope(ny, nx)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.compute_visibility_octant(
|
||||||
|
octant, origin, max_range, x + 1, top,
|
||||||
|
Slope(ny, nx))
|
||||||
|
elif y == bottom_y: # pragma: no cover
|
||||||
|
return
|
||||||
|
elif not is_opaque and was_opaque == 1:
|
||||||
|
nx, ny = x * 2, y * 2 + 1
|
||||||
|
nx += self.is_wall(y + 1, x + 1, octant, origin)
|
||||||
|
if bottom >= Slope(ny, nx): # pragma: no cover
|
||||||
|
return
|
||||||
|
top = Slope(ny, nx)
|
||||||
|
was_opaque = is_opaque
|
||||||
|
if was_opaque != 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def translate_coord(y: int, x: int, octant: int,
|
||||||
|
origin: Tuple[int, int]) -> Tuple[int, int]:
|
||||||
|
ny, nx = origin
|
||||||
|
if octant == 0:
|
||||||
|
return ny - y, nx + x
|
||||||
|
elif octant == 1:
|
||||||
|
return ny - x, nx + y
|
||||||
|
elif octant == 2:
|
||||||
|
return ny - x, nx - y
|
||||||
|
elif octant == 3:
|
||||||
|
return ny - y, nx - x
|
||||||
|
elif octant == 4:
|
||||||
|
return ny + y, nx - x
|
||||||
|
elif octant == 5:
|
||||||
|
return ny + x, nx - y
|
||||||
|
elif octant == 6:
|
||||||
|
return ny + x, nx + y
|
||||||
|
elif octant == 7:
|
||||||
|
return ny + y, nx + x
|
||||||
|
|
||||||
|
def is_wall(self, y: int, x: int, octant: int,
|
||||||
|
origin: Tuple[int, int]) -> bool:
|
||||||
|
y, x = self.translate_coord(y, x, octant, origin)
|
||||||
|
return 0 <= y < len(self.tiles) and 0 <= x < len(self.tiles[0]) and \
|
||||||
|
self.tiles[y][x].is_wall()
|
||||||
|
|
||||||
|
def set_visible(self, y: int, x: int, octant: int,
|
||||||
|
origin: Tuple[int, int]) -> None:
|
||||||
|
y, x = self.translate_coord(y, x, octant, origin)
|
||||||
|
if 0 <= y < len(self.tiles) and 0 <= x < len(self.tiles[0]):
|
||||||
|
self.visibility[y][x] = True
|
||||||
|
self.seen_tiles[y][x] = True
|
||||||
|
|
||||||
def tick(self, p: Any) -> None:
|
def tick(self, p: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Triggers all entity events.
|
Triggers all entity events.
|
||||||
|
@ -210,6 +364,7 @@ class Tile(Enum):
|
||||||
EMPTY = auto()
|
EMPTY = auto()
|
||||||
WALL = auto()
|
WALL = auto()
|
||||||
FLOOR = auto()
|
FLOOR = auto()
|
||||||
|
LADDER = auto()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_ascii_char(ch: str) -> "Tile":
|
def from_ascii_char(ch: str) -> "Tile":
|
||||||
|
@ -226,7 +381,25 @@ class Tile(Enum):
|
||||||
Translates a Tile to the corresponding character according
|
Translates a Tile to the corresponding character according
|
||||||
to the texture pack.
|
to the texture pack.
|
||||||
"""
|
"""
|
||||||
return getattr(pack, self.name)
|
val = getattr(pack, self.name)
|
||||||
|
return val[0] if isinstance(val, tuple) else val
|
||||||
|
|
||||||
|
def visible_color(self, pack: TexturePack) -> Tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Retrieve the tuple (fg_color, bg_color) of the current Tile
|
||||||
|
if it is visible.
|
||||||
|
"""
|
||||||
|
val = getattr(pack, self.name)
|
||||||
|
return (val[2], val[4]) if isinstance(val, tuple) else \
|
||||||
|
(pack.tile_fg_visible_color, pack.tile_bg_color)
|
||||||
|
|
||||||
|
def hidden_color(self, pack: TexturePack) -> Tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Retrieve the tuple (fg_color, bg_color) of the current Tile.
|
||||||
|
"""
|
||||||
|
val = getattr(pack, self.name)
|
||||||
|
return (val[1], val[3]) if isinstance(val, tuple) else \
|
||||||
|
(pack.tile_fg_color, pack.tile_bg_color)
|
||||||
|
|
||||||
def is_wall(self) -> bool:
|
def is_wall(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -234,6 +407,12 @@ class Tile(Enum):
|
||||||
"""
|
"""
|
||||||
return self == Tile.WALL
|
return self == Tile.WALL
|
||||||
|
|
||||||
|
def is_ladder(self) -> bool:
|
||||||
|
"""
|
||||||
|
Is this Tile a ladder?
|
||||||
|
"""
|
||||||
|
return self == Tile.LADDER
|
||||||
|
|
||||||
def can_walk(self) -> bool:
|
def can_walk(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if an entity (player or not) can move in this tile.
|
Checks if an entity (player or not) can move in this tile.
|
||||||
|
@ -525,12 +704,12 @@ class FightingEntity(Entity):
|
||||||
The entity deals damage to the opponent
|
The entity deals damage to the opponent
|
||||||
based on their respective stats.
|
based on their respective stats.
|
||||||
"""
|
"""
|
||||||
diceroll = randint(0, 100)
|
diceroll = randint(1, 100)
|
||||||
damage = self.strength
|
damage = self.strength
|
||||||
string = " "
|
string = " "
|
||||||
if diceroll <= self.critical: # It is a critical hit
|
if diceroll <= self.critical: # It is a critical hit
|
||||||
damage *= 4
|
damage *= 4
|
||||||
string = _(" It's a critical hit! ")
|
string = " " + _("It's a critical hit!") + " "
|
||||||
return _("{name} hits {opponent}.")\
|
return _("{name} hits {opponent}.")\
|
||||||
.format(name=_(self.translated_name.capitalize()),
|
.format(name=_(self.translated_name.capitalize()),
|
||||||
opponent=_(opponent.translated_name)) + string + \
|
opponent=_(opponent.translated_name)) + string + \
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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-12 18:02+0100\n"
|
"POT-Creation-Date: 2021-01-08 01:57+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"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"
|
||||||
|
@ -17,19 +17,44 @@ 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:139
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr "{name} nimmt {amount} Schadenspunkte."
|
||||||
|
|
||||||
|
#: squirrelbattle/display/menudisplay.py:160
|
||||||
msgid "INVENTORY"
|
msgid "INVENTORY"
|
||||||
msgstr "BESTAND"
|
msgstr "BESTAND"
|
||||||
|
|
||||||
#: squirrelbattle/display/menudisplay.py:164
|
#: squirrelbattle/display/menudisplay.py:202
|
||||||
msgid "STALL"
|
msgid "STALL"
|
||||||
msgstr "STAND"
|
msgstr "STAND"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:33
|
#: squirrelbattle/display/statsdisplay.py:23
|
||||||
|
#: squirrelbattle/tests/translations_test.py:60
|
||||||
|
msgid "player"
|
||||||
|
msgstr "Spieler"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:35
|
||||||
msgid "Inventory:"
|
msgid "Inventory:"
|
||||||
msgstr "Bestand:"
|
msgstr "Bestand:"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:52
|
#: squirrelbattle/display/statsdisplay.py:52
|
||||||
|
msgid "Equipped main:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:56
|
||||||
|
msgid "Equipped secondary:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:61
|
||||||
|
msgid "Equipped chestplate:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:65
|
||||||
|
msgid "Equipped helmet:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:72
|
||||||
msgid "YOU ARE DEAD"
|
msgid "YOU ARE DEAD"
|
||||||
msgstr "SIE WURDEN GESTORBEN"
|
msgstr "SIE WURDEN GESTORBEN"
|
||||||
|
|
||||||
|
@ -49,20 +74,30 @@ 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:151
|
#: squirrelbattle/entities/items.py:163
|
||||||
msgid "Bomb is exploding."
|
msgid "Bomb is exploding."
|
||||||
msgstr "Die Bombe explodiert."
|
msgstr "Die Bombe explodiert."
|
||||||
|
|
||||||
#: squirrelbattle/entities/items.py:248
|
#: squirrelbattle/entities/items.py:344
|
||||||
#, 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:205 squirrelbattle/tests/game_test.py:573
|
#: squirrelbattle/game.py:182
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs down to the floor {floor}."
|
||||||
|
msgstr "Der Spieler klettert auf dem Stock {floor} hinunter."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:195
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs up the floor {floor}."
|
||||||
|
msgstr "Der Spieler klettert auf dem Stock {floor} hinoben."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:285 squirrelbattle/tests/game_test.py:592
|
||||||
msgid "The buyer does not have enough money"
|
msgid "The buyer does not have enough money"
|
||||||
msgstr "Der Kaufer hat nicht genug Geld"
|
msgstr "Der Kaufer hat nicht genug Geld"
|
||||||
|
|
||||||
#: squirrelbattle/game.py:249
|
#: squirrelbattle/game.py:328
|
||||||
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."
|
||||||
|
@ -70,7 +105,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:257
|
#: squirrelbattle/game.py:336
|
||||||
msgid ""
|
msgid ""
|
||||||
"No player was found on this map!\n"
|
"No player was found on this map!\n"
|
||||||
"Maybe you died?"
|
"Maybe you died?"
|
||||||
|
@ -78,7 +113,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:277
|
#: squirrelbattle/game.py:356
|
||||||
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."
|
||||||
|
@ -86,22 +121,26 @@ 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:429
|
#: squirrelbattle/interfaces.py:452
|
||||||
|
msgid "It's a critical hit!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:453
|
||||||
#, 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:441
|
#: squirrelbattle/interfaces.py:465
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} takes {amount} damage."
|
msgid "{name} takes {damage} damage."
|
||||||
msgstr "{name} nimmt {amount} Schadenspunkte."
|
msgstr ""
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:443
|
#: squirrelbattle/interfaces.py:467
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} dies."
|
msgid "{name} dies."
|
||||||
msgstr "{name} stirbt."
|
msgstr "{name} stirbt."
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:477
|
#: squirrelbattle/interfaces.py:501
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{entity} said: {message}"
|
msgid "{entity} said: {message}"
|
||||||
msgstr "{entity} hat gesagt: {message}"
|
msgstr "{entity} hat gesagt: {message}"
|
||||||
|
@ -110,8 +149,8 @@ msgstr "{entity} hat gesagt: {message}"
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Zurück"
|
msgstr "Zurück"
|
||||||
|
|
||||||
#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
|
#: squirrelbattle/tests/game_test.py:358 squirrelbattle/tests/game_test.py:361
|
||||||
#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
|
#: squirrelbattle/tests/game_test.py:364 squirrelbattle/tests/game_test.py:367
|
||||||
#: squirrelbattle/tests/translations_test.py:16
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
msgid "New game"
|
msgid "New game"
|
||||||
msgstr "Neu Spiel"
|
msgstr "Neu Spiel"
|
||||||
|
@ -197,57 +236,57 @@ msgid "Key used to wait"
|
||||||
msgstr "Wartentaste"
|
msgstr "Wartentaste"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:56
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "Key used to use ladders"
|
||||||
|
msgstr "Leitertaste"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:58
|
||||||
msgid "Texture pack"
|
msgid "Texture pack"
|
||||||
msgstr "Textur-Packung"
|
msgstr "Textur-Packung"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:57
|
#: squirrelbattle/tests/translations_test.py:59
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Sprache"
|
msgstr "Sprache"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:60
|
#: squirrelbattle/tests/translations_test.py:64
|
||||||
msgid "player"
|
|
||||||
msgstr "Spieler"
|
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:62
|
|
||||||
msgid "hedgehog"
|
msgid "hedgehog"
|
||||||
msgstr "Igel"
|
msgstr "Igel"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:63
|
#: squirrelbattle/tests/translations_test.py:65
|
||||||
msgid "merchant"
|
msgid "merchant"
|
||||||
msgstr "Kaufmann"
|
msgstr "Kaufmann"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:64
|
#: squirrelbattle/tests/translations_test.py:66
|
||||||
msgid "rabbit"
|
msgid "rabbit"
|
||||||
msgstr "Kanninchen"
|
msgstr "Kanninchen"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:65
|
#: squirrelbattle/tests/translations_test.py:67
|
||||||
msgid "sunflower"
|
msgid "sunflower"
|
||||||
msgstr "Sonnenblume"
|
msgstr "Sonnenblume"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:66
|
#: squirrelbattle/tests/translations_test.py:68
|
||||||
msgid "teddy bear"
|
msgid "teddy bear"
|
||||||
msgstr "Teddybär"
|
msgstr "Teddybär"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:67
|
#: squirrelbattle/tests/translations_test.py:69
|
||||||
msgid "tiger"
|
msgid "tiger"
|
||||||
msgstr "Tiger"
|
msgstr "Tiger"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:69
|
#: squirrelbattle/tests/translations_test.py:71
|
||||||
msgid "body snatch potion"
|
msgid "body snatch potion"
|
||||||
msgstr "Leichenfleddererzaubertrank"
|
msgstr "Leichenfleddererzaubertrank"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:70
|
#: squirrelbattle/tests/translations_test.py:72
|
||||||
msgid "bomb"
|
msgid "bomb"
|
||||||
msgstr "Bombe"
|
msgstr "Bombe"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:71
|
#: squirrelbattle/tests/translations_test.py:73
|
||||||
msgid "explosion"
|
msgid "explosion"
|
||||||
msgstr "Explosion"
|
msgstr "Explosion"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:72
|
#: squirrelbattle/tests/translations_test.py:74
|
||||||
msgid "heart"
|
msgid "heart"
|
||||||
msgstr "Herz"
|
msgstr "Herz"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:73
|
#: squirrelbattle/tests/translations_test.py:75
|
||||||
msgid "sword"
|
msgid "sword"
|
||||||
msgstr "schwert"
|
msgstr "schwert"
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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-12 18:02+0100\n"
|
"POT-Creation-Date: 2021-01-06 15:19+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"
|
||||||
|
@ -17,19 +17,44 @@ 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:139
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr "{name} recibe {amount} daño."
|
||||||
|
|
||||||
|
#: squirrelbattle/display/menudisplay.py:160
|
||||||
msgid "INVENTORY"
|
msgid "INVENTORY"
|
||||||
msgstr "INVENTORIO"
|
msgstr "INVENTORIO"
|
||||||
|
|
||||||
#: squirrelbattle/display/menudisplay.py:164
|
#: squirrelbattle/display/menudisplay.py:202
|
||||||
msgid "STALL"
|
msgid "STALL"
|
||||||
msgstr "PUESTO"
|
msgstr "PUESTO"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:33
|
#: squirrelbattle/display/statsdisplay.py:23
|
||||||
|
#: squirrelbattle/tests/translations_test.py:60
|
||||||
|
msgid "player"
|
||||||
|
msgstr "jugador"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:35
|
||||||
msgid "Inventory:"
|
msgid "Inventory:"
|
||||||
msgstr "Inventorio :"
|
msgstr "Inventorio :"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:52
|
#: squirrelbattle/display/statsdisplay.py:52
|
||||||
|
msgid "Equipped main:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:56
|
||||||
|
msgid "Equipped secondary:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:61
|
||||||
|
msgid "Equipped chestplate:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:65
|
||||||
|
msgid "Equipped helmet:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:72
|
||||||
msgid "YOU ARE DEAD"
|
msgid "YOU ARE DEAD"
|
||||||
msgstr "ERES MUERTO"
|
msgstr "ERES MUERTO"
|
||||||
|
|
||||||
|
@ -48,20 +73,30 @@ 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:151
|
#: squirrelbattle/entities/items.py:163
|
||||||
msgid "Bomb is exploding."
|
msgid "Bomb is exploding."
|
||||||
msgstr "La bomba está explotando."
|
msgstr "La bomba está explotando."
|
||||||
|
|
||||||
#: squirrelbattle/entities/items.py:248
|
#: squirrelbattle/entities/items.py:344
|
||||||
#, 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:205 squirrelbattle/tests/game_test.py:573
|
#: squirrelbattle/game.py:182
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs down to the floor {floor}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:195
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs up the floor {floor}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:285 squirrelbattle/tests/game_test.py:592
|
||||||
msgid "The buyer does not have enough money"
|
msgid "The buyer does not have enough money"
|
||||||
msgstr "El comprador no tiene suficiente dinero"
|
msgstr "El comprador no tiene suficiente dinero"
|
||||||
|
|
||||||
#: squirrelbattle/game.py:249
|
#: squirrelbattle/game.py:328
|
||||||
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."
|
||||||
|
@ -69,7 +104,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:257
|
#: squirrelbattle/game.py:336
|
||||||
msgid ""
|
msgid ""
|
||||||
"No player was found on this map!\n"
|
"No player was found on this map!\n"
|
||||||
"Maybe you died?"
|
"Maybe you died?"
|
||||||
|
@ -77,7 +112,7 @@ msgstr ""
|
||||||
"No jugador encontrado sobre la carta !\n"
|
"No jugador encontrado sobre la carta !\n"
|
||||||
"¿ Quizas murió ?"
|
"¿ Quizas murió ?"
|
||||||
|
|
||||||
#: squirrelbattle/game.py:277
|
#: squirrelbattle/game.py:356
|
||||||
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."
|
||||||
|
@ -85,22 +120,26 @@ 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:429
|
#: squirrelbattle/interfaces.py:452
|
||||||
|
msgid "It's a critical hit!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:453
|
||||||
#, 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:441
|
#: squirrelbattle/interfaces.py:465
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} takes {amount} damage."
|
msgid "{name} takes {damage} damage."
|
||||||
msgstr "{name} recibe {amount} daño."
|
msgstr ""
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:443
|
#: squirrelbattle/interfaces.py:467
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} dies."
|
msgid "{name} dies."
|
||||||
msgstr "{name} se muere."
|
msgstr "{name} se muere."
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:477
|
#: squirrelbattle/interfaces.py:501
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{entity} said: {message}"
|
msgid "{entity} said: {message}"
|
||||||
msgstr "{entity} dijo : {message}"
|
msgstr "{entity} dijo : {message}"
|
||||||
|
@ -109,8 +148,8 @@ msgstr "{entity} dijo : {message}"
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Volver"
|
msgstr "Volver"
|
||||||
|
|
||||||
#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
|
#: squirrelbattle/tests/game_test.py:358 squirrelbattle/tests/game_test.py:361
|
||||||
#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
|
#: squirrelbattle/tests/game_test.py:364 squirrelbattle/tests/game_test.py:367
|
||||||
#: squirrelbattle/tests/translations_test.py:16
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
msgid "New game"
|
msgid "New game"
|
||||||
msgstr "Nuevo partido"
|
msgstr "Nuevo partido"
|
||||||
|
@ -196,57 +235,57 @@ msgid "Key used to wait"
|
||||||
msgstr "Tecla para espera"
|
msgstr "Tecla para espera"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:56
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "Key used to use ladders"
|
||||||
|
msgstr "Tecla para el uso de las escaleras"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:58
|
||||||
msgid "Texture pack"
|
msgid "Texture pack"
|
||||||
msgstr "Paquete de texturas"
|
msgstr "Paquete de texturas"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:57
|
#: squirrelbattle/tests/translations_test.py:59
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Languaje"
|
msgstr "Languaje"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:60
|
#: squirrelbattle/tests/translations_test.py:64
|
||||||
msgid "player"
|
|
||||||
msgstr "jugador"
|
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:62
|
|
||||||
msgid "hedgehog"
|
msgid "hedgehog"
|
||||||
msgstr "erizo"
|
msgstr "erizo"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:63
|
#: squirrelbattle/tests/translations_test.py:65
|
||||||
msgid "merchant"
|
msgid "merchant"
|
||||||
msgstr "comerciante"
|
msgstr "comerciante"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:64
|
#: squirrelbattle/tests/translations_test.py:66
|
||||||
msgid "rabbit"
|
msgid "rabbit"
|
||||||
msgstr "conejo"
|
msgstr "conejo"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:65
|
#: squirrelbattle/tests/translations_test.py:67
|
||||||
msgid "sunflower"
|
msgid "sunflower"
|
||||||
msgstr "girasol"
|
msgstr "girasol"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:66
|
#: squirrelbattle/tests/translations_test.py:68
|
||||||
msgid "teddy bear"
|
msgid "teddy bear"
|
||||||
msgstr "osito de peluche"
|
msgstr "osito de peluche"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:67
|
#: squirrelbattle/tests/translations_test.py:69
|
||||||
msgid "tiger"
|
msgid "tiger"
|
||||||
msgstr "tigre"
|
msgstr "tigre"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:69
|
#: squirrelbattle/tests/translations_test.py:71
|
||||||
msgid "body snatch potion"
|
msgid "body snatch potion"
|
||||||
msgstr "poción de intercambio"
|
msgstr "poción de intercambio"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:70
|
#: squirrelbattle/tests/translations_test.py:72
|
||||||
msgid "bomb"
|
msgid "bomb"
|
||||||
msgstr "bomba"
|
msgstr "bomba"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:71
|
#: squirrelbattle/tests/translations_test.py:73
|
||||||
msgid "explosion"
|
msgid "explosion"
|
||||||
msgstr "explosión"
|
msgstr "explosión"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:72
|
#: squirrelbattle/tests/translations_test.py:74
|
||||||
msgid "heart"
|
msgid "heart"
|
||||||
msgstr "corazón"
|
msgstr "corazón"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:73
|
#: squirrelbattle/tests/translations_test.py:75
|
||||||
msgid "sword"
|
msgid "sword"
|
||||||
msgstr "espada"
|
msgstr "espada"
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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-12 18:02+0100\n"
|
"POT-Creation-Date: 2021-01-06 15:19+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"
|
||||||
|
@ -17,19 +17,44 @@ 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:139
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr "{name} prend {amount} points de dégât."
|
||||||
|
|
||||||
|
#: squirrelbattle/display/menudisplay.py:160
|
||||||
msgid "INVENTORY"
|
msgid "INVENTORY"
|
||||||
msgstr "INVENTAIRE"
|
msgstr "INVENTAIRE"
|
||||||
|
|
||||||
#: squirrelbattle/display/menudisplay.py:164
|
#: squirrelbattle/display/menudisplay.py:202
|
||||||
msgid "STALL"
|
msgid "STALL"
|
||||||
msgstr "STAND"
|
msgstr "STAND"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:33
|
#: squirrelbattle/display/statsdisplay.py:23
|
||||||
|
#: squirrelbattle/tests/translations_test.py:60
|
||||||
|
msgid "player"
|
||||||
|
msgstr "joueur"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:35
|
||||||
msgid "Inventory:"
|
msgid "Inventory:"
|
||||||
msgstr "Inventaire :"
|
msgstr "Inventaire :"
|
||||||
|
|
||||||
#: squirrelbattle/display/statsdisplay.py:52
|
#: squirrelbattle/display/statsdisplay.py:52
|
||||||
|
msgid "Equipped main:"
|
||||||
|
msgstr "Équipement principal :"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:56
|
||||||
|
msgid "Equipped secondary:"
|
||||||
|
msgstr "Équipement secondaire :"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:61
|
||||||
|
msgid "Equipped chestplate:"
|
||||||
|
msgstr "Plastron équipé :"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:65
|
||||||
|
msgid "Equipped helmet:"
|
||||||
|
msgstr "Casque équipé :"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:72
|
||||||
msgid "YOU ARE DEAD"
|
msgid "YOU ARE DEAD"
|
||||||
msgstr "VOUS ÊTES MORT"
|
msgstr "VOUS ÊTES MORT"
|
||||||
|
|
||||||
|
@ -49,20 +74,30 @@ 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:151
|
#: squirrelbattle/entities/items.py:163
|
||||||
msgid "Bomb is exploding."
|
msgid "Bomb is exploding."
|
||||||
msgstr "La bombe explose."
|
msgstr "La bombe explose."
|
||||||
|
|
||||||
#: squirrelbattle/entities/items.py:248
|
#: squirrelbattle/entities/items.py:344
|
||||||
#, 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:205 squirrelbattle/tests/game_test.py:573
|
#: squirrelbattle/game.py:182
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs down to the floor {floor}."
|
||||||
|
msgstr "Le joueur descend à l'étage {floor}."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:195
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The player climbs up the floor {floor}."
|
||||||
|
msgstr "Le joueur monte à l'étage {floor}."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:285 squirrelbattle/tests/game_test.py:592
|
||||||
msgid "The buyer does not have enough money"
|
msgid "The buyer does not have enough money"
|
||||||
msgstr "L'acheteur n'a pas assez d'argent"
|
msgstr "L'acheteur n'a pas assez d'argent"
|
||||||
|
|
||||||
#: squirrelbattle/game.py:249
|
#: squirrelbattle/game.py:328
|
||||||
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."
|
||||||
|
@ -70,7 +105,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:257
|
#: squirrelbattle/game.py:336
|
||||||
msgid ""
|
msgid ""
|
||||||
"No player was found on this map!\n"
|
"No player was found on this map!\n"
|
||||||
"Maybe you died?"
|
"Maybe you died?"
|
||||||
|
@ -78,7 +113,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:277
|
#: squirrelbattle/game.py:356
|
||||||
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."
|
||||||
|
@ -86,22 +121,26 @@ 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:429
|
#: squirrelbattle/interfaces.py:452
|
||||||
|
msgid "It's a critical hit!"
|
||||||
|
msgstr "C'est un coup critique !"
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:453
|
||||||
#, 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:441
|
#: squirrelbattle/interfaces.py:465
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} takes {amount} damage."
|
msgid "{name} takes {damage} damage."
|
||||||
msgstr "{name} prend {amount} points de dégât."
|
msgstr "{name} prend {damage} dégâts."
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:443
|
#: squirrelbattle/interfaces.py:467
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} dies."
|
msgid "{name} dies."
|
||||||
msgstr "{name} meurt."
|
msgstr "{name} meurt."
|
||||||
|
|
||||||
#: squirrelbattle/interfaces.py:477
|
#: squirrelbattle/interfaces.py:501
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{entity} said: {message}"
|
msgid "{entity} said: {message}"
|
||||||
msgstr "{entity} a dit : {message}"
|
msgstr "{entity} a dit : {message}"
|
||||||
|
@ -110,8 +149,8 @@ msgstr "{entity} a dit : {message}"
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Retour"
|
msgstr "Retour"
|
||||||
|
|
||||||
#: squirrelbattle/tests/game_test.py:344 squirrelbattle/tests/game_test.py:347
|
#: squirrelbattle/tests/game_test.py:358 squirrelbattle/tests/game_test.py:361
|
||||||
#: squirrelbattle/tests/game_test.py:350 squirrelbattle/tests/game_test.py:353
|
#: squirrelbattle/tests/game_test.py:364 squirrelbattle/tests/game_test.py:367
|
||||||
#: squirrelbattle/tests/translations_test.py:16
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
msgid "New game"
|
msgid "New game"
|
||||||
msgstr "Nouvelle partie"
|
msgstr "Nouvelle partie"
|
||||||
|
@ -197,57 +236,57 @@ msgid "Key used to wait"
|
||||||
msgstr "Touche pour attendre"
|
msgstr "Touche pour attendre"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:56
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "Key used to use ladders"
|
||||||
|
msgstr "Touche pour utiliser les échelles"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:58
|
||||||
msgid "Texture pack"
|
msgid "Texture pack"
|
||||||
msgstr "Pack de textures"
|
msgstr "Pack de textures"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:57
|
#: squirrelbattle/tests/translations_test.py:59
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Langue"
|
msgstr "Langue"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:60
|
#: squirrelbattle/tests/translations_test.py:64
|
||||||
msgid "player"
|
|
||||||
msgstr "joueur"
|
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:62
|
|
||||||
msgid "hedgehog"
|
msgid "hedgehog"
|
||||||
msgstr "hérisson"
|
msgstr "hérisson"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:63
|
#: squirrelbattle/tests/translations_test.py:65
|
||||||
msgid "merchant"
|
msgid "merchant"
|
||||||
msgstr "marchand"
|
msgstr "marchand"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:64
|
#: squirrelbattle/tests/translations_test.py:66
|
||||||
msgid "rabbit"
|
msgid "rabbit"
|
||||||
msgstr "lapin"
|
msgstr "lapin"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:65
|
#: squirrelbattle/tests/translations_test.py:67
|
||||||
msgid "sunflower"
|
msgid "sunflower"
|
||||||
msgstr "tournesol"
|
msgstr "tournesol"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:66
|
#: squirrelbattle/tests/translations_test.py:68
|
||||||
msgid "teddy bear"
|
msgid "teddy bear"
|
||||||
msgstr "nounours"
|
msgstr "nounours"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:67
|
#: squirrelbattle/tests/translations_test.py:69
|
||||||
msgid "tiger"
|
msgid "tiger"
|
||||||
msgstr "tigre"
|
msgstr "tigre"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:69
|
#: squirrelbattle/tests/translations_test.py:71
|
||||||
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:70
|
#: squirrelbattle/tests/translations_test.py:72
|
||||||
msgid "bomb"
|
msgid "bomb"
|
||||||
msgstr "bombe"
|
msgstr "bombe"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:71
|
#: squirrelbattle/tests/translations_test.py:73
|
||||||
msgid "explosion"
|
msgid "explosion"
|
||||||
msgstr ""
|
msgstr "explosion"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:72
|
#: squirrelbattle/tests/translations_test.py:74
|
||||||
msgid "heart"
|
msgid "heart"
|
||||||
msgstr "cœur"
|
msgstr "cœur"
|
||||||
|
|
||||||
#: squirrelbattle/tests/translations_test.py:73
|
#: squirrelbattle/tests/translations_test.py:75
|
||||||
msgid "sword"
|
msgid "sword"
|
||||||
msgstr "épée"
|
msgstr "épée"
|
||||||
|
|
|
@ -34,6 +34,7 @@ class Settings:
|
||||||
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_CHAT = ['t', 'Key used to talk to a friendly entity']
|
||||||
self.KEY_WAIT = ['w', 'Key used to wait']
|
self.KEY_WAIT = ['w', 'Key used to wait']
|
||||||
|
self.KEY_LADDER = ['<', 'Key used to use ladders']
|
||||||
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']
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ class TestEntities(unittest.TestCase):
|
||||||
{self.player.name.capitalize()} takes {entity.strength} damage.")
|
{self.player.name.capitalize()} takes {entity.strength} damage.")
|
||||||
|
|
||||||
# Fight the rabbit
|
# Fight the rabbit
|
||||||
|
self.player.critical = 0
|
||||||
old_health = entity.health
|
old_health = entity.health
|
||||||
self.player.move_down()
|
self.player.move_down()
|
||||||
self.assertEqual(entity.health, old_health - self.player.strength)
|
self.assertEqual(entity.health, old_health - self.player.strength)
|
||||||
|
@ -177,7 +178,7 @@ class TestEntities(unittest.TestCase):
|
||||||
self.assertEqual(item.y, 42)
|
self.assertEqual(item.y, 42)
|
||||||
self.assertEqual(item.x, 42)
|
self.assertEqual(item.x, 42)
|
||||||
# Wait for the explosion
|
# Wait for the explosion
|
||||||
for ignored in range(5):
|
for _ignored in range(5):
|
||||||
item.act(self.map)
|
item.act(self.map)
|
||||||
self.assertTrue(hedgehog.dead)
|
self.assertTrue(hedgehog.dead)
|
||||||
self.assertTrue(teddy_bear.dead)
|
self.assertTrue(teddy_bear.dead)
|
||||||
|
|
|
@ -2,13 +2,16 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import random
|
||||||
import unittest
|
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.friendly import Merchant, Sunflower
|
from ..entities.friendly import Merchant, Sunflower
|
||||||
from ..entities.items import Bomb, Heart, Sword, Explosion
|
from ..entities.items import Bomb, Heart, Sword, Explosion, Shield, Helmet, \
|
||||||
|
Chestplate, RingCritical
|
||||||
|
from ..entities.monsters import GiantSeaEagle
|
||||||
from ..entities.player import Player
|
from ..entities.player import Player
|
||||||
from ..enums import DisplayActions
|
from ..enums import DisplayActions
|
||||||
from ..game import Game, KeyValues, GameMode
|
from ..game import Game, KeyValues, GameMode
|
||||||
|
@ -46,11 +49,6 @@ class TestGame(unittest.TestCase):
|
||||||
bomb.hold(self.game.player)
|
bomb.hold(self.game.player)
|
||||||
sword.hold(self.game.player)
|
sword.hold(self.game.player)
|
||||||
|
|
||||||
for entity in self.game.map.entities:
|
|
||||||
# trumpets change order when they are loaded, this breaks the test.
|
|
||||||
if entity.name == 'trumpet':
|
|
||||||
self.game.map.remove_entity(entity)
|
|
||||||
|
|
||||||
# Ensure that merchants can be saved
|
# Ensure that merchants can be saved
|
||||||
merchant = Merchant()
|
merchant = Merchant()
|
||||||
merchant.move(3, 6)
|
merchant.move(3, 6)
|
||||||
|
@ -153,6 +151,9 @@ class TestGame(unittest.TestCase):
|
||||||
self.assertEqual(KeyValues.translate_key(
|
self.assertEqual(KeyValues.translate_key(
|
||||||
self.game.settings.KEY_WAIT, self.game.settings),
|
self.game.settings.KEY_WAIT, self.game.settings),
|
||||||
KeyValues.WAIT)
|
KeyValues.WAIT)
|
||||||
|
self.assertEqual(KeyValues.translate_key(
|
||||||
|
self.game.settings.KEY_LADDER, self.game.settings),
|
||||||
|
KeyValues.LADDER)
|
||||||
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),
|
||||||
|
@ -343,7 +344,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(11):
|
for ignored in range(12):
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
|
||||||
# Change texture pack
|
# Change texture pack
|
||||||
|
@ -615,6 +616,131 @@ class TestGame(unittest.TestCase):
|
||||||
self.game.handle_key_pressed(KeyValues.SPACE)
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
||||||
self.assertEqual(self.game.state, GameMode.PLAY)
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
||||||
|
|
||||||
|
def test_equipment(self) -> None:
|
||||||
|
"""
|
||||||
|
Ensure that equipment is working.
|
||||||
|
"""
|
||||||
|
self.game.state = GameMode.INVENTORY
|
||||||
|
|
||||||
|
# sword goes into the main equipment slot
|
||||||
|
sword = Sword()
|
||||||
|
sword.hold(self.game.player)
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_main, sword)
|
||||||
|
self.assertFalse(self.game.player.inventory)
|
||||||
|
|
||||||
|
# shield goes into the secondary equipment slot
|
||||||
|
shield = Shield()
|
||||||
|
shield.hold(self.game.player)
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_secondary, shield)
|
||||||
|
self.assertFalse(self.game.player.inventory)
|
||||||
|
|
||||||
|
# helmet goes into the helmet slot
|
||||||
|
helmet = Helmet()
|
||||||
|
helmet.hold(self.game.player)
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_helmet, helmet)
|
||||||
|
self.assertFalse(self.game.player.inventory)
|
||||||
|
|
||||||
|
# helmet goes into the armor slot
|
||||||
|
chestplate = Chestplate()
|
||||||
|
chestplate.hold(self.game.player)
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_armor, chestplate)
|
||||||
|
self.assertFalse(self.game.player.inventory)
|
||||||
|
|
||||||
|
# Use bomb
|
||||||
|
bomb = Bomb()
|
||||||
|
bomb.hold(self.game.player)
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_secondary, bomb)
|
||||||
|
self.assertIn(shield, self.game.player.inventory)
|
||||||
|
self.game.state = GameMode.PLAY
|
||||||
|
self.game.handle_key_pressed(KeyValues.USE)
|
||||||
|
self.assertIsNone(self.game.player.equipped_secondary)
|
||||||
|
self.game.state = GameMode.INVENTORY
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.equipped_secondary, shield)
|
||||||
|
self.assertFalse(self.game.player.inventory)
|
||||||
|
|
||||||
|
# Reequip, which is useless but covers code
|
||||||
|
sword.equip()
|
||||||
|
shield.equip()
|
||||||
|
helmet.equip()
|
||||||
|
chestplate.equip()
|
||||||
|
self.game.save_state()
|
||||||
|
|
||||||
|
# Unequip all
|
||||||
|
sword.unequip()
|
||||||
|
shield.unequip()
|
||||||
|
helmet.unequip()
|
||||||
|
chestplate.unequip()
|
||||||
|
self.assertIsNone(self.game.player.equipped_main)
|
||||||
|
self.assertIsNone(self.game.player.equipped_secondary)
|
||||||
|
self.assertIsNone(self.game.player.equipped_helmet)
|
||||||
|
self.assertIsNone(self.game.player.equipped_armor)
|
||||||
|
self.assertIn(sword, self.game.player.inventory)
|
||||||
|
self.assertIn(shield, self.game.player.inventory)
|
||||||
|
self.assertIn(helmet, self.game.player.inventory)
|
||||||
|
self.assertIn(chestplate, self.game.player.inventory)
|
||||||
|
|
||||||
|
# Test rings
|
||||||
|
self.game.player.inventory.clear()
|
||||||
|
ring = RingCritical()
|
||||||
|
ring.hold(self.game.player)
|
||||||
|
old_critical = self.game.player.critical
|
||||||
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
|
self.assertEqual(self.game.player.critical,
|
||||||
|
old_critical + ring.critical)
|
||||||
|
self.game.save_state()
|
||||||
|
ring.unequip()
|
||||||
|
|
||||||
|
def test_critical_hit(self) -> None:
|
||||||
|
"""
|
||||||
|
Ensure that critical hits are working.
|
||||||
|
"""
|
||||||
|
random.seed(2) # Next random.randint(1, 100) will output 8
|
||||||
|
self.game.player.critical = 10
|
||||||
|
sea_eagle = GiantSeaEagle()
|
||||||
|
self.game.map.add_entity(sea_eagle)
|
||||||
|
sea_eagle.move(2, 6)
|
||||||
|
old_health = sea_eagle.health
|
||||||
|
self.game.player.hit(sea_eagle)
|
||||||
|
self.assertEqual(sea_eagle.health,
|
||||||
|
old_health - self.game.player.strength * 4)
|
||||||
|
|
||||||
|
def test_ladders(self) -> None:
|
||||||
|
"""
|
||||||
|
Ensure that the player can climb on ladders.
|
||||||
|
"""
|
||||||
|
self.game.state = GameMode.PLAY
|
||||||
|
|
||||||
|
self.assertEqual(self.game.player.map.floor, 0)
|
||||||
|
self.game.handle_key_pressed(KeyValues.LADDER)
|
||||||
|
self.assertEqual(self.game.player.map.floor, 0)
|
||||||
|
|
||||||
|
# Move nowhere
|
||||||
|
self.game.player.move(10, 10)
|
||||||
|
self.game.handle_key_pressed(KeyValues.LADDER)
|
||||||
|
self.assertEqual(self.game.player.map.floor, 0)
|
||||||
|
|
||||||
|
# Move down
|
||||||
|
self.game.player.move(3, 40) # Move on a ladder
|
||||||
|
self.game.handle_key_pressed(KeyValues.LADDER)
|
||||||
|
self.assertEqual(self.game.map_index, 1)
|
||||||
|
self.assertEqual(self.game.player.map.floor, 1)
|
||||||
|
self.assertEqual(self.game.player.y, 1)
|
||||||
|
self.assertEqual(self.game.player.x, 17)
|
||||||
|
self.game.display_actions(DisplayActions.UPDATE)
|
||||||
|
|
||||||
|
# Move up
|
||||||
|
self.game.handle_key_pressed(KeyValues.LADDER)
|
||||||
|
self.assertEqual(self.game.player.map.floor, 0)
|
||||||
|
self.assertEqual(self.game.player.y, 3)
|
||||||
|
self.assertEqual(self.game.player.x, 40)
|
||||||
|
self.game.display_actions(DisplayActions.UPDATE)
|
||||||
|
|
||||||
def test_credits(self) -> None:
|
def test_credits(self) -> None:
|
||||||
"""
|
"""
|
||||||
Load credits menu.
|
Load credits menu.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from squirrelbattle.display.texturepack import TexturePack
|
from squirrelbattle.display.texturepack import TexturePack
|
||||||
from squirrelbattle.interfaces import Map, Tile
|
from squirrelbattle.interfaces import Map, Tile, Slope
|
||||||
from squirrelbattle.resources import ResourceManager
|
from squirrelbattle.resources import ResourceManager
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,3 +37,21 @@ class TestInterfaces(unittest.TestCase):
|
||||||
self.assertFalse(Tile.WALL.can_walk())
|
self.assertFalse(Tile.WALL.can_walk())
|
||||||
self.assertFalse(Tile.EMPTY.can_walk())
|
self.assertFalse(Tile.EMPTY.can_walk())
|
||||||
self.assertRaises(ValueError, Tile.from_ascii_char, 'unknown')
|
self.assertRaises(ValueError, Tile.from_ascii_char, 'unknown')
|
||||||
|
|
||||||
|
def test_slope(self) -> None:
|
||||||
|
"""
|
||||||
|
Test good behaviour of slopes (basically vectors, compared according to
|
||||||
|
the determinant)
|
||||||
|
"""
|
||||||
|
a = Slope(1, 1)
|
||||||
|
b = Slope(0, 1)
|
||||||
|
self.assertTrue(b < a)
|
||||||
|
self.assertTrue(b <= a)
|
||||||
|
self.assertTrue(a <= a)
|
||||||
|
self.assertTrue(a == a)
|
||||||
|
self.assertTrue(a > b)
|
||||||
|
self.assertTrue(a >= b)
|
||||||
|
|
||||||
|
# def test_visibility(self) -> None:
|
||||||
|
# m = Map.load(ResourceManager.get_asset_path("example_map_3.txt"))
|
||||||
|
# m.compute_visibility(1, 1, 50)
|
||||||
|
|
|
@ -53,6 +53,8 @@ class TestTranslations(unittest.TestCase):
|
||||||
self.assertEqual(_("Key used to talk to a friendly entity"),
|
self.assertEqual(_("Key used to talk to a friendly entity"),
|
||||||
"Touche pour parler à une entité pacifique")
|
"Touche pour parler à une entité pacifique")
|
||||||
self.assertEqual(_("Key used to wait"), "Touche pour attendre")
|
self.assertEqual(_("Key used to wait"), "Touche pour attendre")
|
||||||
|
self.assertEqual(_("Key used to use ladders"),
|
||||||
|
"Touche pour utiliser les échelles")
|
||||||
self.assertEqual(_("Texture pack"), "Pack de textures")
|
self.assertEqual(_("Texture pack"), "Pack de textures")
|
||||||
self.assertEqual(_("Language"), "Langue")
|
self.assertEqual(_("Language"), "Langue")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue