Merging master into village, conflicts were solved
This commit is contained in:
		@@ -1,10 +1,12 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from random import choice, randint
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
from .player import Player
 | 
			
		||||
from ..interfaces import Entity, FightingEntity, Map
 | 
			
		||||
from ..translations import gettext as _
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Item(Entity):
 | 
			
		||||
@@ -20,16 +22,26 @@ class Item(Entity):
 | 
			
		||||
        self.held = held
 | 
			
		||||
        self.held_by = held_by
 | 
			
		||||
 | 
			
		||||
    def drop(self, y: int, x: int) -> None:
 | 
			
		||||
    def drop(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        The item is dropped from the inventory onto the floor
 | 
			
		||||
        """
 | 
			
		||||
        if self.held:
 | 
			
		||||
            self.held_by.inventory.remove(self)
 | 
			
		||||
            self.map.add_entity(self)
 | 
			
		||||
            self.move(self.held_by.y, self.held_by.x)
 | 
			
		||||
            self.held = False
 | 
			
		||||
            self.held_by = None
 | 
			
		||||
        self.map.add_entity(self)
 | 
			
		||||
        self.move(y, x)
 | 
			
		||||
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Indicates what should be done when the item is used.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
    def equip(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Indicates what should be done when the item is equipped.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
    def hold(self, player: "Player") -> None:
 | 
			
		||||
        """
 | 
			
		||||
@@ -55,8 +67,8 @@ class Heart(Item):
 | 
			
		||||
    """
 | 
			
		||||
    healing: int
 | 
			
		||||
 | 
			
		||||
    def __init__(self, healing: int = 5, *args, **kwargs):
 | 
			
		||||
        super().__init__(name="heart", *args, **kwargs)
 | 
			
		||||
    def __init__(self, name: str = "heart", healing: int = 5, *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
        self.healing = healing
 | 
			
		||||
 | 
			
		||||
    def hold(self, player: "Player") -> None:
 | 
			
		||||
@@ -81,26 +93,47 @@ class Bomb(Item):
 | 
			
		||||
    """
 | 
			
		||||
    damage: int = 5
 | 
			
		||||
    exploding: bool
 | 
			
		||||
    owner: Optional["Player"]
 | 
			
		||||
    tick: int
 | 
			
		||||
 | 
			
		||||
    def __init__(self, damage: int = 5, exploding: bool = False,
 | 
			
		||||
                 *args, **kwargs):
 | 
			
		||||
        super().__init__(name="bomb", *args, **kwargs)
 | 
			
		||||
    def __init__(self, name: str = "bomb", damage: int = 5,
 | 
			
		||||
                 exploding: bool = False, *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
        self.damage = damage
 | 
			
		||||
        self.exploding = exploding
 | 
			
		||||
        self.tick = 4
 | 
			
		||||
        self.owner = None
 | 
			
		||||
 | 
			
		||||
    def drop(self, x: int, y: int) -> None:
 | 
			
		||||
        super().drop(x, y)
 | 
			
		||||
        self.exploding = True
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        When the bomb is used, throw it and explodes it.
 | 
			
		||||
        """
 | 
			
		||||
        if self.held:
 | 
			
		||||
            self.owner = self.held_by
 | 
			
		||||
            super().drop()
 | 
			
		||||
            self.exploding = True
 | 
			
		||||
 | 
			
		||||
    def act(self, m: Map) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Special exploding action of the bomb
 | 
			
		||||
        """
 | 
			
		||||
        if self.exploding:
 | 
			
		||||
            for e in m.entities.copy():
 | 
			
		||||
                if abs(e.x - self.x) + abs(e.y - self.y) <= 1 and \
 | 
			
		||||
                        isinstance(e, FightingEntity):
 | 
			
		||||
                    e.take_damage(self, self.damage)
 | 
			
		||||
            if self.tick > 0:
 | 
			
		||||
                # The bomb will explode in <tick> moves
 | 
			
		||||
                self.tick -= 1
 | 
			
		||||
            else:
 | 
			
		||||
                # The bomb is exploding.
 | 
			
		||||
                # Each entity that is close to the bomb takes damages.
 | 
			
		||||
                # The player earn XP if the entity was killed.
 | 
			
		||||
                log_message = _("Bomb is exploding.")
 | 
			
		||||
                for e in m.entities.copy():
 | 
			
		||||
                    if abs(e.x - self.x) + abs(e.y - self.y) <= 3 and \
 | 
			
		||||
                            isinstance(e, FightingEntity):
 | 
			
		||||
                        log_message += " " + e.take_damage(self, self.damage)
 | 
			
		||||
                        if e.dead:
 | 
			
		||||
                            self.owner.add_xp(randint(3, 7))
 | 
			
		||||
                m.logs.add_message(log_message)
 | 
			
		||||
                m.entities.remove(self)
 | 
			
		||||
 | 
			
		||||
    def save_state(self) -> dict:
 | 
			
		||||
        """
 | 
			
		||||
@@ -110,7 +143,7 @@ class Bomb(Item):
 | 
			
		||||
        d["exploding"] = self.exploding
 | 
			
		||||
        d["damage"] = self.damage
 | 
			
		||||
        return d
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
class Weapon(Item):
 | 
			
		||||
    """
 | 
			
		||||
    Non-throwable items that improve player damage
 | 
			
		||||
@@ -136,4 +169,35 @@ class Sword(Weapon) :
 | 
			
		||||
    def __init__(self, name: int, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.name = "sword"
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
class BodySnatchPotion(Item):
 | 
			
		||||
    """
 | 
			
		||||
    The body-snatch potion allows to exchange all characteristics with a random
 | 
			
		||||
    other entity.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name: str = "body_snatch_potion", *args, **kwargs):
 | 
			
		||||
        super().__init__(name=name, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def use(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Find a valid random entity, then exchange characteristics.
 | 
			
		||||
        """
 | 
			
		||||
        valid_entities = self.held_by.map.find_entities(FightingEntity)
 | 
			
		||||
        valid_entities.remove(self.held_by)
 | 
			
		||||
        entity = choice(valid_entities)
 | 
			
		||||
        entity_state = entity.save_state()
 | 
			
		||||
        player_state = self.held_by.save_state()
 | 
			
		||||
        self.held_by.__dict__.update(entity_state)
 | 
			
		||||
        entity.__dict__.update(player_state)
 | 
			
		||||
        self.held_by.map.currenty, self.held_by.map.currentx = self.held_by.y,\
 | 
			
		||||
            self.held_by.x
 | 
			
		||||
 | 
			
		||||
        self.held_by.map.logs.add_message(
 | 
			
		||||
            _("{player} exchanged its body with {entity}.").format(
 | 
			
		||||
                player=self.held_by.translated_name.capitalize(),
 | 
			
		||||
                entity=entity.translated_name))
 | 
			
		||||
 | 
			
		||||
        self.held_by.recalculate_paths()
 | 
			
		||||
 | 
			
		||||
        self.held_by.inventory.remove(self)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from random import choice
 | 
			
		||||
from random import shuffle
 | 
			
		||||
 | 
			
		||||
from .player import Player
 | 
			
		||||
from ..interfaces import FightingEntity, Map
 | 
			
		||||
@@ -49,9 +49,13 @@ class Monster(FightingEntity):
 | 
			
		||||
            if not moved and self.distance_squared(target) <= 1:
 | 
			
		||||
                self.map.logs.add_message(self.hit(target))
 | 
			
		||||
        else:
 | 
			
		||||
            for _ in range(100):
 | 
			
		||||
                if choice([self.move_up, self.move_down,
 | 
			
		||||
                          self.move_left, self.move_right])():
 | 
			
		||||
            # Move in a random direction
 | 
			
		||||
            # If the direction is not available, try another one
 | 
			
		||||
            moves = [self.move_up, self.move_down,
 | 
			
		||||
                     self.move_left, self.move_right]
 | 
			
		||||
            shuffle(moves)
 | 
			
		||||
            for move in moves:
 | 
			
		||||
                if move():
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -59,9 +63,9 @@ class Tiger(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A tiger monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 2, maxhealth: int = 20,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="tiger", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "tiger", strength: int = 2,
 | 
			
		||||
                 maxhealth: int = 20, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -69,9 +73,9 @@ class Hedgehog(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A really mean hedgehog monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 3, maxhealth: int = 10,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="hedgehog", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "hedgehog", strength: int = 3,
 | 
			
		||||
                 maxhealth: int = 10, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -79,9 +83,9 @@ class Rabbit(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A rabbit monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 1, maxhealth: int = 15,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="rabbit", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "rabbit", strength: int = 1,
 | 
			
		||||
                 maxhealth: int = 15, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -89,7 +93,7 @@ class TeddyBear(Monster):
 | 
			
		||||
    """
 | 
			
		||||
    A cute teddybear monster
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, strength: int = 0, maxhealth: int = 50,
 | 
			
		||||
                 *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="teddy_bear", strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "teddy_bear", strength: int = 0,
 | 
			
		||||
                 maxhealth: int = 50, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name=name, strength=strength,
 | 
			
		||||
                         maxhealth=maxhealth, *args, **kwargs)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,17 +17,24 @@ class Player(FightingEntity):
 | 
			
		||||
    paths: Dict[Tuple[int, int], Tuple[int, int]]
 | 
			
		||||
    hazel: int #It is the currency of this game
 | 
			
		||||
 | 
			
		||||
    def __init__(self, maxhealth: int = 20, strength: int = 5,
 | 
			
		||||
                 intelligence: int = 1, charisma: int = 1, dexterity: int = 1,
 | 
			
		||||
                 constitution: int = 1, level: int = 1, current_xp: int = 0,
 | 
			
		||||
                 max_xp: int = 10, hazel: int = 42, *args, **kwargs) -> None:
 | 
			
		||||
        super().__init__(name="player", maxhealth=maxhealth, strength=strength,
 | 
			
		||||
    def __init__(self, name: str = "player", maxhealth: int = 20,
 | 
			
		||||
                 strength: int = 5, intelligence: int = 1, charisma: int = 1,
 | 
			
		||||
                 dexterity: int = 1, constitution: int = 1, level: int = 1,
 | 
			
		||||
                 current_xp: int = 0, max_xp: int = 10, inventory: list = None,
 | 
			
		||||
                 hazel: int = 42, *args, **kwargs) \
 | 
			
		||||
            -> None:
 | 
			
		||||
        super().__init__(name=name, maxhealth=maxhealth, strength=strength,
 | 
			
		||||
                         intelligence=intelligence, charisma=charisma,
 | 
			
		||||
                         dexterity=dexterity, constitution=constitution,
 | 
			
		||||
                         level=level, *args, **kwargs)
 | 
			
		||||
        self.current_xp = current_xp
 | 
			
		||||
        self.max_xp = max_xp
 | 
			
		||||
        self.inventory = list()
 | 
			
		||||
        self.inventory = inventory if inventory else list()
 | 
			
		||||
        for i in range(len(self.inventory)):
 | 
			
		||||
            if isinstance(self.inventory[i], dict):
 | 
			
		||||
                entity_classes = self.get_all_entity_classes_in_a_dict()
 | 
			
		||||
                item_class = entity_classes[self.inventory[i]["type"]]
 | 
			
		||||
                self.inventory[i] = item_class(**self.inventory[i])
 | 
			
		||||
        self.paths = dict()
 | 
			
		||||
        self.hazel = hazel
 | 
			
		||||
 | 
			
		||||
@@ -130,4 +137,5 @@ class Player(FightingEntity):
 | 
			
		||||
        d = super().save_state()
 | 
			
		||||
        d["current_xp"] = self.current_xp
 | 
			
		||||
        d["max_xp"] = self.max_xp
 | 
			
		||||
        d["inventory"] = [item.save_state() for item in self.inventory]
 | 
			
		||||
        return d
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user