Merge branch 'equipment' into 'master'
Equipment Closes #19, #30, #48, #51 et #52 See merge request ynerant/squirrel-battle!54
This commit is contained in:
commit
fb47c15d6b
|
@ -33,7 +33,8 @@ class StatsDisplay(Display):
|
|||
f"INT {self.player.intelligence}\n" \
|
||||
f"CHR {self.player.charisma}\n" \
|
||||
f"DEX {self.player.dexterity}\n" \
|
||||
f"CON {self.player.constitution}"
|
||||
f"CON {self.player.constitution}\n" \
|
||||
f"CRI {self.player.critical}%"
|
||||
self.addstr(self.pad, 3, 0, string3)
|
||||
|
||||
inventory_str = _("Inventory:") + " "
|
||||
|
@ -49,13 +50,31 @@ class StatsDisplay(Display):
|
|||
if count > 1:
|
||||
inventory_str += f"x{count} "
|
||||
printed_items.append(item)
|
||||
self.addstr(self.pad, 8, 0, inventory_str)
|
||||
self.addstr(self.pad, 9, 0, inventory_str)
|
||||
|
||||
self.addstr(self.pad, 9, 0, f"{self.pack.HAZELNUT} "
|
||||
if self.player.equipped_main:
|
||||
self.addstr(self.pad, 10, 0,
|
||||
_("Equipped main:") + " "
|
||||
f"{self.pack[self.player.equipped_main.name.upper()]}")
|
||||
if self.player.equipped_secondary:
|
||||
self.addstr(self.pad, 11, 0,
|
||||
_("Equipped secondary:") + " "
|
||||
+ self.pack[self.player.equipped_secondary
|
||||
.name.upper()])
|
||||
if self.player.equipped_armor:
|
||||
self.addstr(self.pad, 12, 0,
|
||||
_("Equipped chestplate:") + " "
|
||||
+ self.pack[self.player.equipped_armor.name.upper()])
|
||||
if self.player.equipped_helmet:
|
||||
self.addstr(self.pad, 13, 0,
|
||||
_("Equipped helmet:") + " "
|
||||
+ self.pack[self.player.equipped_helmet.name.upper()])
|
||||
|
||||
self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} "
|
||||
f"x{self.player.hazel}")
|
||||
|
||||
if self.player.dead:
|
||||
self.addstr(self.pad, 11, 0, _("YOU ARE DEAD"), curses.COLOR_RED,
|
||||
self.addstr(self.pad, 15, 0, _("YOU ARE DEAD"), curses.COLOR_RED,
|
||||
bold=True, blink=True, standout=True)
|
||||
|
||||
def display(self) -> None:
|
||||
|
|
|
@ -35,6 +35,12 @@ class TexturePack:
|
|||
TIGER: str
|
||||
TRUMPET: str
|
||||
WALL: str
|
||||
EAGLE: str
|
||||
SHIELD: str
|
||||
CHESTPLATE: str
|
||||
HELMET: str
|
||||
RING_OF_MORE_EXPERIENCE: str
|
||||
RING_OF_CRITICAL_DAMAGE: str
|
||||
|
||||
ASCII_PACK: "TexturePack"
|
||||
SQUIRREL_PACK: "TexturePack"
|
||||
|
@ -66,7 +72,7 @@ TexturePack.ASCII_PACK = TexturePack(
|
|||
entity_bg_color=curses.COLOR_BLACK,
|
||||
|
||||
BODY_SNATCH_POTION='S',
|
||||
BOMB='o',
|
||||
BOMB='ç',
|
||||
EMPTY=' ',
|
||||
EXPLOSION='%',
|
||||
FLOOR='.',
|
||||
|
@ -77,12 +83,18 @@ TexturePack.ASCII_PACK = TexturePack(
|
|||
MERCHANT='M',
|
||||
PLAYER='@',
|
||||
RABBIT='Y',
|
||||
SHIELD='D',
|
||||
SUNFLOWER='I',
|
||||
SWORD='\u2020',
|
||||
TEDDY_BEAR='8',
|
||||
TIGER='n',
|
||||
TRUMPET='/',
|
||||
WALL='#',
|
||||
EAGLE='µ',
|
||||
CHESTPLATE='(',
|
||||
HELMET='0',
|
||||
RING_OF_MORE_EXPERIENCE='o',
|
||||
RING_OF_CRITICAL_DAMAGE='o',
|
||||
)
|
||||
|
||||
TexturePack.SQUIRREL_PACK = TexturePack(
|
||||
|
@ -107,10 +119,16 @@ TexturePack.SQUIRREL_PACK = TexturePack(
|
|||
PLAYER='🐿️ ️',
|
||||
MERCHANT='🦜',
|
||||
RABBIT='🐇',
|
||||
SHIELD='🛡️ ',
|
||||
SUNFLOWER='🌻',
|
||||
SWORD='🗡️ ',
|
||||
TEDDY_BEAR='🧸',
|
||||
TIGER='🐅',
|
||||
TRUMPET='🎺',
|
||||
WALL='🧱',
|
||||
EAGLE='🦅',
|
||||
CHESTPLATE='🦺',
|
||||
HELMET='⛑️',
|
||||
RING_OF_MORE_EXPERIENCE='💍',
|
||||
RING_OF_CRITICAL_DAMAGE='💍',
|
||||
)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
from random import choice, randint
|
||||
from typing import Optional
|
||||
|
||||
from .player import Player
|
||||
from ..interfaces import Entity, FightingEntity, Map, InventoryHolder
|
||||
from ..translations import gettext as _
|
||||
|
||||
|
@ -30,7 +29,7 @@ class Item(Entity):
|
|||
The item is dropped from the inventory onto the floor.
|
||||
"""
|
||||
if self.held:
|
||||
self.held_by.inventory.remove(self)
|
||||
self.held_by.remove_from_inventory(self)
|
||||
self.held_by.map.add_entity(self)
|
||||
self.move(self.held_by.y, self.held_by.x)
|
||||
self.held = False
|
||||
|
@ -45,15 +44,27 @@ class Item(Entity):
|
|||
"""
|
||||
Indicates what should be done when the item is equipped.
|
||||
"""
|
||||
# Other objects are only equipped as secondary.
|
||||
if self.held_by.equipped_secondary:
|
||||
self.held_by.equipped_secondary.unequip()
|
||||
self.held_by.remove_from_inventory(self)
|
||||
self.held_by.equipped_secondary = self
|
||||
|
||||
def hold(self, player: InventoryHolder) -> None:
|
||||
def unequip(self) -> None:
|
||||
"""
|
||||
Indicates what should be done when the item is unequipped.
|
||||
"""
|
||||
self.held_by.remove_from_inventory(self)
|
||||
self.held_by.add_to_inventory(self)
|
||||
|
||||
def hold(self, holder: InventoryHolder) -> None:
|
||||
"""
|
||||
The item is taken from the floor and put into the inventory.
|
||||
"""
|
||||
self.held = True
|
||||
self.held_by = player
|
||||
self.held_by = holder
|
||||
self.held_by.map.remove_entity(self)
|
||||
player.add_to_inventory(self)
|
||||
holder.add_to_inventory(self)
|
||||
|
||||
def save_state(self) -> dict:
|
||||
"""
|
||||
|
@ -68,7 +79,8 @@ class Item(Entity):
|
|||
"""
|
||||
Returns the list of all item classes.
|
||||
"""
|
||||
return [BodySnatchPotion, Bomb, Heart, Sword]
|
||||
return [BodySnatchPotion, Bomb, Heart, Shield, Sword,
|
||||
Chestplate, Helmet, RingCritical, RingXP]
|
||||
|
||||
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
|
||||
"""
|
||||
|
@ -120,7 +132,7 @@ class Bomb(Item):
|
|||
"""
|
||||
damage: int = 5
|
||||
exploding: bool
|
||||
owner: Optional["Player"]
|
||||
owner: Optional["InventoryHolder"]
|
||||
tick: int
|
||||
|
||||
def __init__(self, name: str = "bomb", damage: int = 5,
|
||||
|
@ -193,7 +205,6 @@ class Explosion(Item):
|
|||
"""
|
||||
The player can't hold an explosion.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Weapon(Item):
|
||||
|
@ -214,14 +225,99 @@ class Weapon(Item):
|
|||
d["damage"] = self.damage
|
||||
return d
|
||||
|
||||
def equip(self) -> None:
|
||||
"""
|
||||
When a weapon is equipped, the player gains strength.
|
||||
"""
|
||||
self.held_by.remove_from_inventory(self)
|
||||
self.held_by.equipped_main = self
|
||||
self.held_by.strength += self.damage
|
||||
|
||||
def unequip(self) -> None:
|
||||
"""
|
||||
Remove the strength earned by the weapon.
|
||||
:return:
|
||||
"""
|
||||
super().unequip()
|
||||
self.held_by.strength -= self.damage
|
||||
|
||||
|
||||
class Sword(Weapon):
|
||||
"""
|
||||
A basic weapon
|
||||
"""
|
||||
def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs):
|
||||
def __init__(self, name: str = "sword", price: int = 20,
|
||||
*args, **kwargs):
|
||||
super().__init__(name=name, price=price, *args, **kwargs)
|
||||
self.name = name
|
||||
|
||||
|
||||
class Armor(Item):
|
||||
"""
|
||||
Class of items that increase the player's constitution.
|
||||
"""
|
||||
constitution: int
|
||||
|
||||
def __init__(self, constitution: int, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.constitution = constitution
|
||||
|
||||
def equip(self) -> None:
|
||||
super().equip()
|
||||
self.held_by.constitution += self.constitution
|
||||
|
||||
def unequip(self) -> None:
|
||||
super().unequip()
|
||||
self.held_by.constitution -= self.constitution
|
||||
|
||||
def save_state(self) -> dict:
|
||||
d = super().save_state()
|
||||
d["constitution"] = self.constitution
|
||||
return d
|
||||
|
||||
|
||||
class Shield(Armor):
|
||||
"""
|
||||
Class of shield items, they can be equipped in the other hand.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str = "shield", constitution: int = 2,
|
||||
price: int = 6, *args, **kwargs):
|
||||
super().__init__(name=name, constitution=constitution, price=price,
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Helmet(Armor):
|
||||
"""
|
||||
Class of helmet items, they can be equipped on the head.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str = "helmet", constitution: int = 2,
|
||||
price: int = 8, *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 of chestplate items, they can be equipped on the body.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str = "chestplate", constitution: int = 4,
|
||||
price: int = 15, *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):
|
||||
|
@ -256,3 +352,79 @@ class BodySnatchPotion(Item):
|
|||
self.held_by.recalculate_paths()
|
||||
|
||||
self.held_by.inventory.remove(self)
|
||||
|
||||
|
||||
class Ring(Item):
|
||||
"""
|
||||
A class of rings that boost the player's statistics.
|
||||
"""
|
||||
maxhealth: int
|
||||
strength: int
|
||||
intelligence: int
|
||||
charisma: int
|
||||
dexterity: int
|
||||
constitution: int
|
||||
critical: int
|
||||
experience: float
|
||||
|
||||
def __init__(self, maxhealth: int = 0, strength: int = 0,
|
||||
intelligence: int = 0, charisma: int = 0,
|
||||
dexterity: int = 0, constitution: int = 0,
|
||||
critical: int = 0, experience: float = 0, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.maxhealth = maxhealth
|
||||
self.strength = strength
|
||||
self.intelligence = intelligence
|
||||
self.charisma = charisma
|
||||
self.dexterity = dexterity
|
||||
self.constitution = constitution
|
||||
self.critical = critical
|
||||
self.experience = experience
|
||||
|
||||
def equip(self) -> None:
|
||||
super().equip()
|
||||
self.held_by.maxhealth += self.maxhealth
|
||||
self.held_by.strength += self.strength
|
||||
self.held_by.intelligence += self.intelligence
|
||||
self.held_by.charisma += self.charisma
|
||||
self.held_by.dexterity += self.dexterity
|
||||
self.held_by.constitution += self.constitution
|
||||
self.held_by.critical += self.critical
|
||||
self.held_by.xp_buff += self.experience
|
||||
|
||||
def unequip(self) -> None:
|
||||
super().unequip()
|
||||
self.held_by.maxhealth -= self.maxhealth
|
||||
self.held_by.strength -= self.strength
|
||||
self.held_by.intelligence -= self.intelligence
|
||||
self.held_by.charisma -= self.charisma
|
||||
self.held_by.dexterity -= self.dexterity
|
||||
self.held_by.constitution -= self.constitution
|
||||
self.held_by.critical -= self.critical
|
||||
self.held_by.xp_buff -= self.experience
|
||||
|
||||
def save_state(self) -> dict:
|
||||
d = super().save_state()
|
||||
d["maxhealth"] = self.maxhealth
|
||||
d["strength"] = self.strength
|
||||
d["intelligence"] = self.intelligence
|
||||
d["charisma"] = self.charisma
|
||||
d["dexterity"] = self.dexterity
|
||||
d["constitution"] = self.constitution
|
||||
d["critical"] = self.critical
|
||||
d["experience"] = self.experience
|
||||
return d
|
||||
|
||||
|
||||
class RingCritical(Ring):
|
||||
def __init__(self, name: str = "ring_of_critical_damage", price: int = 15,
|
||||
critical: int = 20, *args, **kwargs):
|
||||
super().__init__(name=name, price=price, critical=critical,
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class RingXP(Ring):
|
||||
def __init__(self, name: str = "ring_of_more_experience", price: int = 25,
|
||||
experience: float = 2, *args, **kwargs):
|
||||
super().__init__(name=name, price=price, experience=experience,
|
||||
*args, **kwargs)
|
||||
|
|
|
@ -94,9 +94,11 @@ class Rabbit(Monster):
|
|||
A rabbit monster.
|
||||
"""
|
||||
def __init__(self, name: str = "rabbit", strength: int = 1,
|
||||
maxhealth: int = 15, *args, **kwargs) -> None:
|
||||
maxhealth: int = 15, critical: int = 30,
|
||||
*args, **kwargs) -> None:
|
||||
super().__init__(name=name, strength=strength,
|
||||
maxhealth=maxhealth, *args, **kwargs)
|
||||
maxhealth=maxhealth, critical=critical,
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class TeddyBear(Monster):
|
||||
|
@ -107,3 +109,13 @@ class TeddyBear(Monster):
|
|||
maxhealth: int = 50, *args, **kwargs) -> None:
|
||||
super().__init__(name=name, strength=strength,
|
||||
maxhealth=maxhealth, *args, **kwargs)
|
||||
|
||||
|
||||
class GiantSeaEagle(Monster):
|
||||
"""
|
||||
An eagle boss
|
||||
"""
|
||||
def __init__(self, name: str = "eagle", strength: int = 1000,
|
||||
maxhealth: int = 5000, *args, **kwargs) -> None:
|
||||
super().__init__(name=name, strength=strength,
|
||||
maxhealth=maxhealth, *args, **kwargs)
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from random import randint
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from .items import Item
|
||||
from ..interfaces import FightingEntity, InventoryHolder
|
||||
|
||||
|
||||
|
@ -12,22 +14,40 @@ class Player(InventoryHolder, FightingEntity):
|
|||
"""
|
||||
current_xp: int = 0
|
||||
max_xp: int = 10
|
||||
xp_buff: float = 1
|
||||
paths: Dict[Tuple[int, int], Tuple[int, int]]
|
||||
equipped_main: Optional[Item]
|
||||
equipped_secondary: Optional[Item]
|
||||
equipped_helmet: Optional[Item]
|
||||
equipped_armor: Optional[Item]
|
||||
|
||||
def __init__(self, name: str = "player", maxhealth: int = 20,
|
||||
strength: int = 5, intelligence: int = 1, charisma: int = 1,
|
||||
dexterity: int = 1, constitution: int = 1, level: int = 1,
|
||||
current_xp: int = 0, max_xp: int = 10, inventory: list = None,
|
||||
hazel: int = 42, vision: int = 5, *args, **kwargs) \
|
||||
-> None:
|
||||
hazel: int = 42, equipped_main: Optional[Item] = None,
|
||||
equipped_armor: Optional[Item] = None, critical: int = 5,
|
||||
equipped_secondary: Optional[Item] = None,
|
||||
equipped_helmet: Optional[Item] = None, xp_buff: float = 1,
|
||||
vision: int = 5, *args, **kwargs) -> None:
|
||||
super().__init__(name=name, maxhealth=maxhealth, strength=strength,
|
||||
intelligence=intelligence, charisma=charisma,
|
||||
dexterity=dexterity, constitution=constitution,
|
||||
level=level, *args, **kwargs)
|
||||
level=level, critical=critical, *args, **kwargs)
|
||||
self.current_xp = current_xp
|
||||
self.max_xp = max_xp
|
||||
self.xp_buff = xp_buff
|
||||
self.inventory = self.translate_inventory(inventory or [])
|
||||
self.paths = dict()
|
||||
self.hazel = hazel
|
||||
self.equipped_main = self.dict_to_item(equipped_main) \
|
||||
if isinstance(equipped_main, dict) else equipped_main
|
||||
self.equipped_armor = self.dict_to_item(equipped_armor) \
|
||||
if isinstance(equipped_armor, dict) else equipped_armor
|
||||
self.equipped_secondary = self.dict_to_item(equipped_secondary) \
|
||||
if isinstance(equipped_secondary, dict) else equipped_secondary
|
||||
self.equipped_helmet = self.dict_to_item(equipped_helmet) \
|
||||
if isinstance(equipped_helmet, dict) else equipped_helmet
|
||||
self.vision = vision
|
||||
|
||||
def move(self, y: int, x: int) -> None:
|
||||
|
@ -60,9 +80,24 @@ class Player(InventoryHolder, FightingEntity):
|
|||
Adds some experience to the player.
|
||||
If the required amount is reached, the player levels up.
|
||||
"""
|
||||
self.current_xp += xp
|
||||
self.current_xp += int(xp * self.xp_buff)
|
||||
self.level_up()
|
||||
|
||||
def remove_from_inventory(self, obj: Item) -> None:
|
||||
"""
|
||||
Remove the given item from the inventory, even if the item is equipped.
|
||||
"""
|
||||
if obj == self.equipped_main:
|
||||
self.equipped_main = None
|
||||
elif obj == self.equipped_armor:
|
||||
self.equipped_armor = None
|
||||
elif obj == self.equipped_secondary:
|
||||
self.equipped_secondary = None
|
||||
elif obj == self.equipped_helmet:
|
||||
self.equipped_helmet = None
|
||||
else:
|
||||
return super().remove_from_inventory(obj)
|
||||
|
||||
# noinspection PyTypeChecker,PyUnresolvedReferences
|
||||
def check_move(self, y: int, x: int, move_if_possible: bool = False) \
|
||||
-> bool:
|
||||
|
@ -92,4 +127,12 @@ class Player(InventoryHolder, FightingEntity):
|
|||
d = super().save_state()
|
||||
d["current_xp"] = self.current_xp
|
||||
d["max_xp"] = self.max_xp
|
||||
d["equipped_main"] = self.equipped_main.save_state()\
|
||||
if self.equipped_main else None
|
||||
d["equipped_armor"] = self.equipped_armor.save_state()\
|
||||
if self.equipped_armor else None
|
||||
d["equipped_secondary"] = self.equipped_secondary.save_state()\
|
||||
if self.equipped_secondary else None
|
||||
d["equipped_helmet"] = self.equipped_helmet.save_state()\
|
||||
if self.equipped_helmet else None
|
||||
return d
|
||||
|
|
|
@ -131,7 +131,7 @@ class Game:
|
|||
self.state = GameMode.MAINMENU
|
||||
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.
|
||||
"""
|
||||
|
@ -149,6 +149,12 @@ class Game:
|
|||
self.map.tick(self.player)
|
||||
elif key == KeyValues.INVENTORY:
|
||||
self.state = GameMode.INVENTORY
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
elif key == KeyValues.USE and self.player.equipped_main:
|
||||
if self.player.equipped_main:
|
||||
self.player.equipped_main.use()
|
||||
if self.player.equipped_secondary:
|
||||
self.player.equipped_secondary.use()
|
||||
elif key == KeyValues.SPACE:
|
||||
self.state = GameMode.MAINMENU
|
||||
elif key == KeyValues.CHAT:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from enum import Enum, auto
|
||||
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 queue import PriorityQueue
|
||||
from functools import reduce
|
||||
|
@ -188,7 +188,8 @@ class Map:
|
|||
tile = self.tiles[y][x]
|
||||
if tile.can_walk():
|
||||
break
|
||||
entity = choice(Entity.get_all_entity_classes())()
|
||||
entity = choices(Entity.get_all_entity_classes(),
|
||||
weights=Entity.get_weights(), k=1)[0]()
|
||||
entity.move(y, x)
|
||||
self.add_entity(entity)
|
||||
|
||||
|
@ -602,11 +603,19 @@ class Entity:
|
|||
"""
|
||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
|
||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
|
||||
Rabbit, TeddyBear
|
||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||
Trumpet
|
||||
Rabbit, TeddyBear, GiantSeaEagle
|
||||
from squirrelbattle.entities.friendly import Merchant, Sunflower
|
||||
return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,
|
||||
Sunflower, Tiger, Merchant, Trumpet]
|
||||
Sunflower, Tiger, Merchant, GiantSeaEagle]
|
||||
|
||||
@staticmethod
|
||||
def get_weights() -> list:
|
||||
"""
|
||||
Returns a weigth list associated to the above function, to
|
||||
be used to spawn random entities with a certain probability.
|
||||
"""
|
||||
return [3, 5, 6, 5, 5, 5,
|
||||
5, 4, 4, 1]
|
||||
|
||||
@staticmethod
|
||||
def get_all_entity_classes_in_a_dict() -> dict:
|
||||
|
@ -615,11 +624,11 @@ class Entity:
|
|||
"""
|
||||
from squirrelbattle.entities.player import Player
|
||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
|
||||
TeddyBear
|
||||
TeddyBear, GiantSeaEagle
|
||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||
Trumpet
|
||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
|
||||
Heart, Sword
|
||||
Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP
|
||||
return {
|
||||
"Tiger": Tiger,
|
||||
"Bomb": Bomb,
|
||||
|
@ -633,6 +642,12 @@ class Entity:
|
|||
"Sunflower": Sunflower,
|
||||
"Sword": Sword,
|
||||
"Trumpet": Trumpet,
|
||||
"Eagle": GiantSeaEagle,
|
||||
"Shield": Shield,
|
||||
"Chestplate": Chestplate,
|
||||
"Helmet": Helmet,
|
||||
"RingCritical": RingCritical,
|
||||
"RingXP": RingXP,
|
||||
}
|
||||
|
||||
def save_state(self) -> dict:
|
||||
|
@ -659,11 +674,12 @@ class FightingEntity(Entity):
|
|||
dexterity: int
|
||||
constitution: int
|
||||
level: int
|
||||
critical: int
|
||||
|
||||
def __init__(self, maxhealth: int = 0, health: Optional[int] = None,
|
||||
strength: int = 0, intelligence: int = 0, charisma: int = 0,
|
||||
dexterity: int = 0, constitution: int = 0, level: int = 0,
|
||||
*args, **kwargs) -> None:
|
||||
critical: int = 0, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.maxhealth = maxhealth
|
||||
self.health = maxhealth if health is None else health
|
||||
|
@ -673,6 +689,7 @@ class FightingEntity(Entity):
|
|||
self.dexterity = dexterity
|
||||
self.constitution = constitution
|
||||
self.level = level
|
||||
self.critical = critical
|
||||
|
||||
@property
|
||||
def dead(self) -> bool:
|
||||
|
@ -686,21 +703,28 @@ class FightingEntity(Entity):
|
|||
The entity deals damage to the opponent
|
||||
based on their respective stats.
|
||||
"""
|
||||
diceroll = randint(1, 100)
|
||||
damage = self.strength
|
||||
string = " "
|
||||
if diceroll <= self.critical: # It is a critical hit
|
||||
damage *= 4
|
||||
string = " " + _("It's a critical hit!") + " "
|
||||
return _("{name} hits {opponent}.")\
|
||||
.format(name=_(self.translated_name.capitalize()),
|
||||
opponent=_(opponent.translated_name)) + " " + \
|
||||
opponent.take_damage(self, self.strength)
|
||||
opponent=_(opponent.translated_name)) + string + \
|
||||
opponent.take_damage(self, damage)
|
||||
|
||||
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
||||
"""
|
||||
The entity takes damage from the attacker
|
||||
based on their respective stats.
|
||||
"""
|
||||
self.health -= amount
|
||||
damage = max(0, amount - self.constitution)
|
||||
self.health -= damage
|
||||
if self.health <= 0:
|
||||
self.die()
|
||||
return _("{name} takes {amount} damage.")\
|
||||
.format(name=self.translated_name.capitalize(), amount=str(amount))\
|
||||
return _("{name} takes {damage} damage.")\
|
||||
.format(name=self.translated_name.capitalize(), damage=str(damage))\
|
||||
+ (" " + _("{name} dies.")
|
||||
.format(name=self.translated_name.capitalize())
|
||||
if self.health <= 0 else "")
|
||||
|
@ -757,10 +781,10 @@ class InventoryHolder(Entity):
|
|||
"""
|
||||
for i in range(len(inventory)):
|
||||
if isinstance(inventory[i], dict):
|
||||
inventory[i] = self.dict_to_inventory(inventory[i])
|
||||
inventory[i] = self.dict_to_item(inventory[i])
|
||||
return inventory
|
||||
|
||||
def dict_to_inventory(self, item_dict: dict) -> Entity:
|
||||
def dict_to_item(self, item_dict: dict) -> Entity:
|
||||
"""
|
||||
Translates a dictionnary that contains the state of an item
|
||||
into an item object.
|
||||
|
@ -783,12 +807,14 @@ class InventoryHolder(Entity):
|
|||
"""
|
||||
Adds an object to the inventory.
|
||||
"""
|
||||
if obj not in self.inventory:
|
||||
self.inventory.append(obj)
|
||||
|
||||
def remove_from_inventory(self, obj: Any) -> None:
|
||||
"""
|
||||
Removes an object from the inventory.
|
||||
"""
|
||||
if obj in self.inventory:
|
||||
self.inventory.remove(obj)
|
||||
|
||||
def change_hazel_balance(self, hz: int) -> None:
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: squirrelbattle 3.14.1\n"
|
||||
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
|
||||
"POT-Creation-Date: 2021-01-06 15:19+0100\n"
|
||||
"POT-Creation-Date: 2021-01-08 01:57+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,6 +17,10 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} nimmt {amount} Schadenspunkte."
|
||||
|
||||
#: squirrelbattle/display/menudisplay.py:160
|
||||
msgid "INVENTORY"
|
||||
msgstr "BESTAND"
|
||||
|
@ -25,11 +29,32 @@ msgstr "BESTAND"
|
|||
msgid "STALL"
|
||||
msgstr "STAND"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:36
|
||||
#: squirrelbattle/display/statsdisplay.py:23
|
||||
#: squirrelbattle/tests/translations_test.py:60
|
||||
msgid "player"
|
||||
msgstr "Spieler"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:35
|
||||
msgid "Inventory:"
|
||||
msgstr "Bestand:"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:55
|
||||
#: squirrelbattle/display/statsdisplay.py:52
|
||||
msgid "Equipped main:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:56
|
||||
msgid "Equipped secondary:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:61
|
||||
msgid "Equipped chestplate:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:65
|
||||
msgid "Equipped helmet:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:72
|
||||
msgid "YOU ARE DEAD"
|
||||
msgstr "SIE WURDEN GESTORBEN"
|
||||
|
||||
|
@ -49,11 +74,11 @@ msgstr "Die Sonne ist warm heute"
|
|||
#. The bomb is exploding.
|
||||
#. Each entity that is close to the bomb takes damages.
|
||||
#. The player earn XP if the entity was killed.
|
||||
#: squirrelbattle/entities/items.py:151
|
||||
#: squirrelbattle/entities/items.py:163
|
||||
msgid "Bomb is exploding."
|
||||
msgstr "Die Bombe explodiert."
|
||||
|
||||
#: squirrelbattle/entities/items.py:248
|
||||
#: squirrelbattle/entities/items.py:344
|
||||
#, python-brace-format
|
||||
msgid "{player} exchanged its body with {entity}."
|
||||
msgstr "{player} täuscht seinem Körper mit {entity} aus."
|
||||
|
@ -96,6 +121,10 @@ msgstr ""
|
|||
"Die JSON-Datei ist nicht korrekt.\n"
|
||||
"Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht."
|
||||
|
||||
#: squirrelbattle/interfaces.py:452
|
||||
msgid "It's a critical hit!"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/interfaces.py:453
|
||||
#, python-brace-format
|
||||
msgid "{name} hits {opponent}."
|
||||
|
@ -103,8 +132,8 @@ msgstr "{name} schlägt {opponent}."
|
|||
|
||||
#: squirrelbattle/interfaces.py:465
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} nimmt {amount} Schadenspunkte."
|
||||
msgid "{name} takes {damage} damage."
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/interfaces.py:467
|
||||
#, python-brace-format
|
||||
|
@ -218,10 +247,6 @@ msgstr "Textur-Packung"
|
|||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:62
|
||||
msgid "player"
|
||||
msgstr "Spieler"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:64
|
||||
msgid "hedgehog"
|
||||
msgstr "Igel"
|
||||
|
|
|
@ -17,6 +17,10 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} recibe {amount} daño."
|
||||
|
||||
#: squirrelbattle/display/menudisplay.py:160
|
||||
msgid "INVENTORY"
|
||||
msgstr "INVENTORIO"
|
||||
|
@ -25,11 +29,32 @@ msgstr "INVENTORIO"
|
|||
msgid "STALL"
|
||||
msgstr "PUESTO"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:36
|
||||
#: squirrelbattle/display/statsdisplay.py:23
|
||||
#: squirrelbattle/tests/translations_test.py:60
|
||||
msgid "player"
|
||||
msgstr "jugador"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:35
|
||||
msgid "Inventory:"
|
||||
msgstr "Inventorio :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:55
|
||||
#: squirrelbattle/display/statsdisplay.py:52
|
||||
msgid "Equipped main:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:56
|
||||
msgid "Equipped secondary:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:61
|
||||
msgid "Equipped chestplate:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:65
|
||||
msgid "Equipped helmet:"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:72
|
||||
msgid "YOU ARE DEAD"
|
||||
msgstr "ERES MUERTO"
|
||||
|
||||
|
@ -48,11 +73,11 @@ msgstr "El sol está caliente hoy"
|
|||
#. The bomb is exploding.
|
||||
#. Each entity that is close to the bomb takes damages.
|
||||
#. The player earn XP if the entity was killed.
|
||||
#: squirrelbattle/entities/items.py:151
|
||||
#: squirrelbattle/entities/items.py:163
|
||||
msgid "Bomb is exploding."
|
||||
msgstr "La bomba está explotando."
|
||||
|
||||
#: squirrelbattle/entities/items.py:248
|
||||
#: squirrelbattle/entities/items.py:344
|
||||
#, python-brace-format
|
||||
msgid "{player} exchanged its body with {entity}."
|
||||
msgstr "{player} intercambió su cuerpo con {entity}."
|
||||
|
@ -95,6 +120,10 @@ msgstr ""
|
|||
"El JSON archivo no es correcto.\n"
|
||||
"Su guarda parece corrupta. Fue eliminada."
|
||||
|
||||
#: squirrelbattle/interfaces.py:452
|
||||
msgid "It's a critical hit!"
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/interfaces.py:453
|
||||
#, python-brace-format
|
||||
msgid "{name} hits {opponent}."
|
||||
|
@ -102,8 +131,8 @@ msgstr "{name} golpea a {opponent}."
|
|||
|
||||
#: squirrelbattle/interfaces.py:465
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} recibe {amount} daño."
|
||||
msgid "{name} takes {damage} damage."
|
||||
msgstr ""
|
||||
|
||||
#: squirrelbattle/interfaces.py:467
|
||||
#, python-brace-format
|
||||
|
@ -217,10 +246,6 @@ msgstr "Paquete de texturas"
|
|||
msgid "Language"
|
||||
msgstr "Languaje"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:62
|
||||
msgid "player"
|
||||
msgstr "jugador"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:64
|
||||
msgid "hedgehog"
|
||||
msgstr "erizo"
|
||||
|
|
|
@ -17,6 +17,10 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} prend {amount} points de dégât."
|
||||
|
||||
#: squirrelbattle/display/menudisplay.py:160
|
||||
msgid "INVENTORY"
|
||||
msgstr "INVENTAIRE"
|
||||
|
@ -25,11 +29,32 @@ msgstr "INVENTAIRE"
|
|||
msgid "STALL"
|
||||
msgstr "STAND"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:36
|
||||
#: squirrelbattle/display/statsdisplay.py:23
|
||||
#: squirrelbattle/tests/translations_test.py:60
|
||||
msgid "player"
|
||||
msgstr "joueur"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:35
|
||||
msgid "Inventory:"
|
||||
msgstr "Inventaire :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:55
|
||||
#: squirrelbattle/display/statsdisplay.py:52
|
||||
msgid "Equipped main:"
|
||||
msgstr "Équipement principal :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:56
|
||||
msgid "Equipped secondary:"
|
||||
msgstr "Équipement secondaire :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:61
|
||||
msgid "Equipped chestplate:"
|
||||
msgstr "Plastron équipé :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:65
|
||||
msgid "Equipped helmet:"
|
||||
msgstr "Casque équipé :"
|
||||
|
||||
#: squirrelbattle/display/statsdisplay.py:72
|
||||
msgid "YOU ARE DEAD"
|
||||
msgstr "VOUS ÊTES MORT"
|
||||
|
||||
|
@ -49,11 +74,11 @@ msgstr "Le soleil est chaud aujourd'hui"
|
|||
#. The bomb is exploding.
|
||||
#. Each entity that is close to the bomb takes damages.
|
||||
#. The player earn XP if the entity was killed.
|
||||
#: squirrelbattle/entities/items.py:151
|
||||
#: squirrelbattle/entities/items.py:163
|
||||
msgid "Bomb is exploding."
|
||||
msgstr "La bombe explose."
|
||||
|
||||
#: squirrelbattle/entities/items.py:248
|
||||
#: squirrelbattle/entities/items.py:344
|
||||
#, python-brace-format
|
||||
msgid "{player} exchanged its body with {entity}."
|
||||
msgstr "{player} a échangé son corps avec {entity}."
|
||||
|
@ -96,6 +121,10 @@ msgstr ""
|
|||
"Le fichier JSON de sauvegarde est incorrect.\n"
|
||||
"Votre sauvegarde semble corrompue. Elle a été supprimée."
|
||||
|
||||
#: squirrelbattle/interfaces.py:452
|
||||
msgid "It's a critical hit!"
|
||||
msgstr "C'est un coup critique !"
|
||||
|
||||
#: squirrelbattle/interfaces.py:453
|
||||
#, python-brace-format
|
||||
msgid "{name} hits {opponent}."
|
||||
|
@ -103,8 +132,8 @@ msgstr "{name} frappe {opponent}."
|
|||
|
||||
#: squirrelbattle/interfaces.py:465
|
||||
#, python-brace-format
|
||||
msgid "{name} takes {amount} damage."
|
||||
msgstr "{name} prend {amount} points de dégât."
|
||||
msgid "{name} takes {damage} damage."
|
||||
msgstr "{name} prend {damage} dégâts."
|
||||
|
||||
#: squirrelbattle/interfaces.py:467
|
||||
#, python-brace-format
|
||||
|
@ -218,10 +247,6 @@ msgstr "Pack de textures"
|
|||
msgid "Language"
|
||||
msgstr "Langue"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:62
|
||||
msgid "player"
|
||||
msgstr "joueur"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:64
|
||||
msgid "hedgehog"
|
||||
msgstr "hérisson"
|
||||
|
@ -256,7 +281,7 @@ msgstr "bombe"
|
|||
|
||||
#: squirrelbattle/tests/translations_test.py:73
|
||||
msgid "explosion"
|
||||
msgstr ""
|
||||
msgstr "explosion"
|
||||
|
||||
#: squirrelbattle/tests/translations_test.py:74
|
||||
msgid "heart"
|
||||
|
|
|
@ -19,6 +19,7 @@ class TestEntities(unittest.TestCase):
|
|||
"""
|
||||
self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
|
||||
self.player = Player()
|
||||
self.player.constitution = 0
|
||||
self.map.add_entity(self.player)
|
||||
self.player.move(self.map.start_y, self.map.start_x)
|
||||
|
||||
|
@ -55,6 +56,7 @@ class TestEntities(unittest.TestCase):
|
|||
self.assertTrue(entity.dead)
|
||||
|
||||
entity = Rabbit()
|
||||
entity.critical = 0
|
||||
self.map.add_entity(entity)
|
||||
entity.move(15, 44)
|
||||
# Move randomly
|
||||
|
@ -76,6 +78,7 @@ class TestEntities(unittest.TestCase):
|
|||
{self.player.name.capitalize()} takes {entity.strength} damage.")
|
||||
|
||||
# Fight the rabbit
|
||||
self.player.critical = 0
|
||||
old_health = entity.health
|
||||
self.player.move_down()
|
||||
self.assertEqual(entity.health, old_health - self.player.strength)
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
import random
|
||||
import unittest
|
||||
|
||||
from ..bootstrap import Bootstrap
|
||||
from ..display.display import Display
|
||||
from ..display.display_manager import DisplayManager
|
||||
from ..entities.friendly import Merchant, Sunflower
|
||||
from ..entities.items import Bomb, Heart, Sword, Explosion
|
||||
from ..entities.items import Bomb, Heart, Sword, Explosion, Shield, Helmet, \
|
||||
Chestplate, RingCritical
|
||||
from ..entities.monsters import GiantSeaEagle
|
||||
from ..entities.player import Player
|
||||
from ..enums import DisplayActions
|
||||
from ..game import Game, KeyValues, GameMode
|
||||
|
@ -613,6 +616,100 @@ class TestGame(unittest.TestCase):
|
|||
self.game.handle_key_pressed(KeyValues.SPACE)
|
||||
self.assertEqual(self.game.state, GameMode.PLAY)
|
||||
|
||||
def test_equipment(self) -> None:
|
||||
"""
|
||||
Ensure that equipment is working.
|
||||
"""
|
||||
self.game.state = GameMode.INVENTORY
|
||||
|
||||
# sword goes into the main equipment slot
|
||||
sword = Sword()
|
||||
sword.hold(self.game.player)
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_main, sword)
|
||||
self.assertFalse(self.game.player.inventory)
|
||||
|
||||
# shield goes into the secondary equipment slot
|
||||
shield = Shield()
|
||||
shield.hold(self.game.player)
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_secondary, shield)
|
||||
self.assertFalse(self.game.player.inventory)
|
||||
|
||||
# helmet goes into the helmet slot
|
||||
helmet = Helmet()
|
||||
helmet.hold(self.game.player)
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_helmet, helmet)
|
||||
self.assertFalse(self.game.player.inventory)
|
||||
|
||||
# helmet goes into the armor slot
|
||||
chestplate = Chestplate()
|
||||
chestplate.hold(self.game.player)
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_armor, chestplate)
|
||||
self.assertFalse(self.game.player.inventory)
|
||||
|
||||
# Use bomb
|
||||
bomb = Bomb()
|
||||
bomb.hold(self.game.player)
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_secondary, bomb)
|
||||
self.assertIn(shield, self.game.player.inventory)
|
||||
self.game.state = GameMode.PLAY
|
||||
self.game.handle_key_pressed(KeyValues.USE)
|
||||
self.assertIsNone(self.game.player.equipped_secondary)
|
||||
self.game.state = GameMode.INVENTORY
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.equipped_secondary, shield)
|
||||
self.assertFalse(self.game.player.inventory)
|
||||
|
||||
# Reequip, which is useless but covers code
|
||||
sword.equip()
|
||||
shield.equip()
|
||||
helmet.equip()
|
||||
chestplate.equip()
|
||||
self.game.save_state()
|
||||
|
||||
# Unequip all
|
||||
sword.unequip()
|
||||
shield.unequip()
|
||||
helmet.unequip()
|
||||
chestplate.unequip()
|
||||
self.assertIsNone(self.game.player.equipped_main)
|
||||
self.assertIsNone(self.game.player.equipped_secondary)
|
||||
self.assertIsNone(self.game.player.equipped_helmet)
|
||||
self.assertIsNone(self.game.player.equipped_armor)
|
||||
self.assertIn(sword, self.game.player.inventory)
|
||||
self.assertIn(shield, self.game.player.inventory)
|
||||
self.assertIn(helmet, self.game.player.inventory)
|
||||
self.assertIn(chestplate, self.game.player.inventory)
|
||||
|
||||
# Test rings
|
||||
self.game.player.inventory.clear()
|
||||
ring = RingCritical()
|
||||
ring.hold(self.game.player)
|
||||
old_critical = self.game.player.critical
|
||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||
self.assertEqual(self.game.player.critical,
|
||||
old_critical + ring.critical)
|
||||
self.game.save_state()
|
||||
ring.unequip()
|
||||
|
||||
def test_critical_hit(self) -> None:
|
||||
"""
|
||||
Ensure that critical hits are working.
|
||||
"""
|
||||
random.seed(2) # Next random.randint(1, 100) will output 8
|
||||
self.game.player.critical = 10
|
||||
sea_eagle = GiantSeaEagle()
|
||||
self.game.map.add_entity(sea_eagle)
|
||||
sea_eagle.move(2, 6)
|
||||
old_health = sea_eagle.health
|
||||
self.game.player.hit(sea_eagle)
|
||||
self.assertEqual(sea_eagle.health,
|
||||
old_health - self.game.player.strength * 4)
|
||||
|
||||
def test_ladders(self) -> None:
|
||||
"""
|
||||
Ensure that the player can climb on ladders.
|
||||
|
|
Loading…
Reference in New Issue