diff --git a/squirrelbattle/entities/items.py b/squirrelbattle/entities/items.py index 51a7145..04db192 100644 --- a/squirrelbattle/entities/items.py +++ b/squirrelbattle/entities/items.py @@ -84,8 +84,8 @@ class Item(Entity): """ Returns the list of all item classes. """ - return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\ - Chestplate, Helmet, RingCritical, RingXP, \ + return [BodySnatchPotion, Bomb, Heart, Shield, Sword, + Chestplate, Helmet, RingCritical, RingXP, ScrollofDamage, ScrollofWeakening, Ruler, Bow, FireBallStaff] def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: @@ -256,13 +256,15 @@ class Sword(Weapon): *args, **kwargs): super().__init__(name=name, price=price, *args, **kwargs) + class Ruler(Weapon): """ A basic weapon """ def __init__(self, name: str = "ruler", price: int = 2, damage: int = 1, *args, **kwargs): - super().__init__(name=name, price=price, damage=damage, *args, **kwargs) + super().__init__(name=name, price=price, damage=damage, *args, **kwargs) + class Armor(Item): """ @@ -297,6 +299,7 @@ class Shield(Armor): super().__init__(name=name, constitution=constitution, price=price, *args, **kwargs) + class Helmet(Armor): """ Class of helmet items, they can be equipped on the head. @@ -312,6 +315,7 @@ class Helmet(Armor): 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. @@ -327,6 +331,7 @@ class Chestplate(Armor): self.held_by.remove_from_inventory(self) self.held_by.equipped_armor = self + class BodySnatchPotion(Item): """ The body-snatch potion allows to exchange all characteristics with a random @@ -436,6 +441,7 @@ class RingXP(Ring): super().__init__(name=name, price=price, experience=experience, *args, **kwargs) + class ScrollofDamage(Item): """ A scroll that, when used, deals damage to all entities in a certain radius. @@ -451,11 +457,12 @@ class ScrollofDamage(Item): """ for entity in self.held_by.map.entities: if entity.is_fighting_entity() and not entity == self.held_by: - if entity.distance(self.held_by)<=5: - self.held_by.map.logs.add_message(entity.take_damage(\ + if entity.distance(self.held_by) <= 5: + self.held_by.map.logs.add_message(entity.take_damage( self.held_by, self.held_by.intelligence)) self.held_by.inventory.remove(self) + class ScrollofWeakening(Item): """ A scroll that, when used, reduces the damage of the ennemies for 3 turn. @@ -470,13 +477,17 @@ class ScrollofWeakening(Item): """ for entity in self.held_by.map.entities: if entity.is_fighting_entity() and not entity == self.held_by: - entity.strength = entity.strength - max(1, self.held_by.intelligence//2) - entity.effects.append(["strength", \ - -max(1, self.held_by.intelligence//2), 3]) - self.held_by.map.logs.add_message(\ - _(f"The ennemies have -{max(1, self.held_by.intelligence//2)} strength for 3 turns")) + entity.strength = entity.strength - \ + max(1, self.held_by.intelligence // 2) + entity.effects.append(["strength", + -max(1, self.held_by.intelligence // 2), + 3]) + self.held_by.map.logs.add_message( + _(f"The ennemies have -{max(1, self.held_by.intelligence // 2)}" + + "strength for 3 turns")) self.held_by.inventory.remove(self) + class LongRangeWeapon(Item): def __init__(self, damage: int = 4, rang: int = 3, *args, **kwargs): @@ -489,26 +500,28 @@ class LongRangeWeapon(Item): for entity in self.held_by.map.entities: if entity.is_fighting_entity(): if direction == 0 and self.held_by.x == entity.x \ - and self.held_by.y-entity.y>0 and \ - self.held_by.y-entity.y<=self.range: + and self.held_by.y - entity.y > 0 and \ + self.held_by.y - entity.y <= self.range: to_kill = entity elif direction == 2 and self.held_by.x == entity.x \ - and entity.y-self.held_by.y>0 and \ - entity.y-self.held_by.y<=self.range: + and entity.y - self.held_by.y > 0 and \ + entity.y - self.held_by.y <= self.range: to_kill = entity elif direction == 1 and self.held_by.y == entity.y \ - and entity.x-self.held_by.x>0 and \ - entity.x-self.held_by.x<=self.range: + and entity.x - self.held_by.x > 0 and \ + entity.x - self.held_by.x <= self.range: to_kill = entity elif direction == 3 and self.held_by.y == entity.y \ - and self.held_by.x-entity.x>0 and \ - self.held_by.x-entity.x<=self.range: + and self.held_by.x - entity.x > 0 and \ + self.held_by.x - entity.x <= self.range: to_kill = entity if to_kill: - self.held_by.map.logs.add_message(_("{name}")\ - .format(name=to_kill.translated_name.capitalize())+ self.string + " " \ - + to_kill.take_damage(self.held_by, self.damage + \ - getattr(self.held_by, self.stat))) + line = _("{name}").format(name=to_kill.translated_name.capitalize() + ) + self.string + " "\ + + to_kill.take_damage( + self.held_by, self.damage + + getattr(self.held_by, self.stat)) + self.held_by.map.logs.add_message(line) return (to_kill.x, to_kill.y) if to_kill else None def equip(self) -> None: @@ -531,13 +544,15 @@ class LongRangeWeapon(Item): The string that is printed when we hit an ennemy. """ + class Bow(LongRangeWeapon): """ - A type of long range weapon that deals damage based on the player's dexterity + A type of long range weapon that deals damage + based on the player's dexterity """ def __init__(self, name: str = "bow", price: int = 22, damage: int = 4, rang: int = 3, *args, **kwargs): - super().__init__(name=name, price=price, damage=damage, \ + super().__init__(name=name, price=price, damage=damage, rang=rang, *args, **kwargs) @property @@ -551,13 +566,15 @@ class Bow(LongRangeWeapon): def string(self) -> str: return " is shot by an arrow." + class FireBallStaff(LongRangeWeapon): """ - A type of long range weapon that deals damage based on the player's dexterity + A type of powerful long range weapon that deals damage + based on the player's intelligence """ - def __init__(self, name: str = "fire_ball_staff", price: int = 36,\ + def __init__(self, name: str = "fire_ball_staff", price: int = 36, damage: int = 6, rang: int = 4, *args, **kwargs): - super().__init__(name=name, price=price, damage=damage, \ + super().__init__(name=name, price=price, damage=damage, rang=rang, *args, **kwargs) @property @@ -575,10 +592,10 @@ class FireBallStaff(LongRangeWeapon): """ Adds an explosion animation when killing something. """ - A = super().throw(direction) - if A: - x=A[0] - y=A[1] + coord = super().throw(direction) + if coord: + x = coord[0] + y = coord[1] explosion = Explosion(y=y, x=x) self.held_by.map.add_entity(explosion) diff --git a/squirrelbattle/game.py b/squirrelbattle/game.py index f30183e..dc866f2 100644 --- a/squirrelbattle/game.py +++ b/squirrelbattle/game.py @@ -277,7 +277,6 @@ class Game: if self.player.equipped_main: self.player.equipped_main.throw(direction) - def handle_key_pressed_inventory(self, key: KeyValues) -> None: """ diff --git a/squirrelbattle/interfaces.py b/squirrelbattle/interfaces.py index dc4bdda..34a4c90 100644 --- a/squirrelbattle/interfaces.py +++ b/squirrelbattle/interfaces.py @@ -605,7 +605,7 @@ class Entity: from squirrelbattle.entities.monsters import Tiger, Hedgehog, \ Rabbit, TeddyBear, GiantSeaEagle from squirrelbattle.entities.friendly import Merchant, Sunflower, \ - Trumpet + Trumpet return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear, Sunflower, Tiger, Merchant, GiantSeaEagle, Trumpet] @@ -697,7 +697,7 @@ class FightingEntity(Entity): self.constitution = constitution self.level = level self.critical = critical - self.effects = [] #effects are temporary buff or weakening of the stats. + self.effects = [] # effects = temporary buff or weakening of the stats. @property def dead(self) -> bool: @@ -713,12 +713,13 @@ class FightingEntity(Entity): for i in range(len(self.effects)): self.effects[i][2] -= 1 - l = self.effects[:] - for i in range(len(l)): - if l[i][2] <= 0: - setattr(self, l[i][0], getattr(self, l[i][0])-l[i][1]) - self.effects.remove(l[i]) - + copy = self.effects[:] + for i in range(len(copy)): + if copy[i][2] <= 0: + setattr(self, copy[i][0], + getattr(self, copy[i][0]) - copy[i][1]) + self.effects.remove(copy[i]) + def hit(self, opponent: "FightingEntity") -> str: """ The entity deals damage to the opponent diff --git a/squirrelbattle/tests/game_test.py b/squirrelbattle/tests/game_test.py index 0843ae8..6fe4203 100644 --- a/squirrelbattle/tests/game_test.py +++ b/squirrelbattle/tests/game_test.py @@ -10,11 +10,12 @@ 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, Shield, Helmet, \ - Chestplate, RingCritical -from ..entities.monsters import GiantSeaEagle + Chestplate, RingCritical, Bow, FireBallStaff, ScrollofDamage,\ + ScrollofWeakening +from ..entities.monsters import Rabbit, GiantSeaEagle from ..entities.player import Player -from ..enums import DisplayActions -from ..game import Game, KeyValues, GameMode +from ..enums import DisplayActions, KeyValues, GameMode +from ..game import Game from ..interfaces import Map from ..menus import MainMenuValues from ..resources import ResourceManager @@ -344,7 +345,7 @@ class TestGame(unittest.TestCase): self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a') # Navigate to "texture pack" - for ignored in range(12): + for ignored in range(13): self.game.handle_key_pressed(KeyValues.DOWN) # Change texture pack @@ -756,3 +757,100 @@ class TestGame(unittest.TestCase): self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.state, GameMode.MAINMENU) + + def test_launch(self) -> None: + """ + Use the long range weapons to kill some entities. + """ + self.game.state = GameMode.PLAY + self.game.player.move(2, 6) + + b = Bow() + b.held_by = self.game.player + self.game.player.equipped_main = b + self.assertTrue(self.game.player.equipped_main) + + entity = Rabbit() + entity.health = 1 + self.game.map.add_entity(entity) + entity.move(3, 6) + + self.game.handle_launch(KeyValues.UP) + + self.game.waiting_for_launch_key = True + self.game.handle_key_pressed(KeyValues.CHAT) + + entity = Rabbit() + entity.health = 1 + self.game.map.add_entity(entity) + entity.move(2, 8) + self.game.waiting_for_launch_key = True + self.game.handle_key_pressed(KeyValues.RIGHT) + + entity = Rabbit() + entity.health = 1 + self.game.map.add_entity(entity) + entity.move(2, 5) + self.game.waiting_for_launch_key = True + self.game.handle_key_pressed(KeyValues.LEFT) + + key = "l" + KeyValues.translate_key(key, self.game.settings) + + self.game.handle_key_pressed(KeyValues.LAUNCH) + self.assertTrue(self.game.waiting_for_launch_key) + self.game.handle_key_pressed(KeyValues.DOWN) + + self.assertTrue(entity.dead) + + entity2 = Rabbit() + entity2.health = 1 + self.game.map.add_entity(entity2) + entity2.move(1, 6) + + b = FireBallStaff() + self.game.player.inventory.append(b) + b.held_by = self.game.player + b.equip() + + self.game.handle_key_pressed(KeyValues.LAUNCH) + self.assertTrue(self.game.waiting_for_launch_key) + self.game.handle_key_pressed(KeyValues.UP) + + self.assertTrue(entity2.dead) + + def test_scrolls(self) -> None: + """ + Use the scrolls. + """ + self.game.state = GameMode.PLAY + self.game.player.move(2, 6) + + entity = Rabbit() + self.game.map.add_entity(entity) + entity.move(3, 6) + + entity2 = GiantSeaEagle() + self.game.map.add_entity(entity2) + entity2.move(3, 8) + + scroll1 = ScrollofDamage() + scroll2 = ScrollofWeakening() + self.game.player.inventory.append(scroll1) + self.game.player.inventory.append(scroll2) + scroll1.held_by = self.game.player + scroll2.held_by = self.game.player + + scroll1.use() + self.assertTrue(entity.health != entity.maxhealth) + self.assertTrue(entity2.health != entity2.maxhealth) + + scroll2.use() + self.assertEqual(entity.strength, 0) + self.assertEqual(entity2.strength, 999) + + self.game.map.tick(self.game.player) + self.game.map.tick(self.game.player) + self.game.map.tick(self.game.player) + + self.assertEqual(entity2.effects, [])