Merge branch 'master' into map_generation
# Conflicts: # squirrelbattle/game.py # squirrelbattle/interfaces.py # squirrelbattle/tests/game_test.py
This commit is contained in:
		@@ -1,10 +1,13 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import random
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart, Item
 | 
			
		||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, TeddyBear
 | 
			
		||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart, Item, \
 | 
			
		||||
    Explosion
 | 
			
		||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit,\
 | 
			
		||||
    TeddyBear, GiantSeaEagle
 | 
			
		||||
from squirrelbattle.entities.friendly import Trumpet
 | 
			
		||||
from squirrelbattle.entities.player import Player
 | 
			
		||||
from squirrelbattle.interfaces import Entity, Map
 | 
			
		||||
from squirrelbattle.resources import ResourceManager
 | 
			
		||||
@@ -13,16 +16,17 @@ from squirrelbattle.resources import ResourceManager
 | 
			
		||||
class TestEntities(unittest.TestCase):
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Load example map that can be used in tests.
 | 
			
		||||
        Loads example map that can be used in tests.
 | 
			
		||||
        """
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
    def test_basic_entities(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with basic entities.
 | 
			
		||||
        Tests some random stuff with basic entities.
 | 
			
		||||
        """
 | 
			
		||||
        entity = Entity()
 | 
			
		||||
        entity.move(42, 64)
 | 
			
		||||
@@ -37,7 +41,7 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_fighting_entities(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with fighting entities.
 | 
			
		||||
        Tests some random stuff with fighting entities.
 | 
			
		||||
        """
 | 
			
		||||
        entity = Tiger()
 | 
			
		||||
        self.map.add_entity(entity)
 | 
			
		||||
@@ -53,20 +57,21 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertTrue(entity.dead)
 | 
			
		||||
 | 
			
		||||
        entity = Rabbit()
 | 
			
		||||
        entity.critical = 0
 | 
			
		||||
        self.map.add_entity(entity)
 | 
			
		||||
        entity.move(15, 44)
 | 
			
		||||
        # Move randomly
 | 
			
		||||
        self.map.tick()
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertFalse(entity.y == 15 and entity.x == 44)
 | 
			
		||||
 | 
			
		||||
        # Move to the player
 | 
			
		||||
        entity.move(3, 6)
 | 
			
		||||
        self.map.tick()
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(entity.y == 2 and entity.x == 6)
 | 
			
		||||
 | 
			
		||||
        # Rabbit should fight
 | 
			
		||||
        old_health = self.player.health
 | 
			
		||||
        self.map.tick()
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(entity.y == 2 and entity.x == 6)
 | 
			
		||||
        self.assertEqual(old_health - entity.strength, self.player.health)
 | 
			
		||||
        self.assertEqual(self.map.logs.messages[-1],
 | 
			
		||||
@@ -74,6 +79,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)
 | 
			
		||||
@@ -88,9 +94,50 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertTrue(entity.dead)
 | 
			
		||||
        self.assertGreaterEqual(self.player.current_xp, 3)
 | 
			
		||||
 | 
			
		||||
        # Test the familiars
 | 
			
		||||
        fam = Trumpet()
 | 
			
		||||
        entity = Rabbit()
 | 
			
		||||
        self.map.add_entity(entity)
 | 
			
		||||
        self.map.add_entity(fam)
 | 
			
		||||
        self.player.move(1, 6)
 | 
			
		||||
        entity.move(2, 6)
 | 
			
		||||
        fam.move(2, 7)
 | 
			
		||||
 | 
			
		||||
        # Test fighting
 | 
			
		||||
        entity.health = 2
 | 
			
		||||
        entity.paths = []
 | 
			
		||||
        entity.recalculate_paths()
 | 
			
		||||
        fam.target = entity
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(entity.dead)
 | 
			
		||||
 | 
			
		||||
        # Test finding a new target
 | 
			
		||||
        entity2 = Rabbit()
 | 
			
		||||
        self.map.add_entity(entity2)
 | 
			
		||||
        entity2.move(2, 6)
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(fam.target == entity2)
 | 
			
		||||
        self.map.remove_entity(entity2)
 | 
			
		||||
 | 
			
		||||
        # Test following the player and finding the player as target
 | 
			
		||||
        self.player.move(5, 5)
 | 
			
		||||
        fam.move(4, 5)
 | 
			
		||||
        fam.target = None
 | 
			
		||||
        self.player.move_down()
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(fam.target == self.player)
 | 
			
		||||
        self.assertEqual(fam.y, 5)
 | 
			
		||||
        self.assertEqual(fam.x, 5)
 | 
			
		||||
 | 
			
		||||
        # Test random move
 | 
			
		||||
        fam.move(13, 20)
 | 
			
		||||
        fam.target = self.player
 | 
			
		||||
        self.map.tick(self.player)
 | 
			
		||||
        self.assertTrue(fam.x != 20 or fam.y != 13)
 | 
			
		||||
 | 
			
		||||
    def test_items(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with items.
 | 
			
		||||
        Tests some random stuff with items.
 | 
			
		||||
        """
 | 
			
		||||
        item = Item()
 | 
			
		||||
        self.map.add_entity(item)
 | 
			
		||||
@@ -111,7 +158,7 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_bombs(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with bombs.
 | 
			
		||||
        Tests some random stuff with bombs.
 | 
			
		||||
        """
 | 
			
		||||
        item = Bomb()
 | 
			
		||||
        hedgehog = Hedgehog()
 | 
			
		||||
@@ -132,16 +179,30 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(item.y, 42)
 | 
			
		||||
        self.assertEqual(item.x, 42)
 | 
			
		||||
        # Wait for the explosion
 | 
			
		||||
        for ignored in range(5):
 | 
			
		||||
        for _ignored in range(5):
 | 
			
		||||
            item.act(self.map)
 | 
			
		||||
        self.assertTrue(hedgehog.dead)
 | 
			
		||||
        self.assertTrue(teddy_bear.dead)
 | 
			
		||||
        bomb_state = item.save_state()
 | 
			
		||||
        self.assertEqual(bomb_state["damage"], item.damage)
 | 
			
		||||
        explosions = self.map.find_entities(Explosion)
 | 
			
		||||
        self.assertTrue(explosions)
 | 
			
		||||
        explosion = explosions[0]
 | 
			
		||||
        self.assertEqual(explosion.y, item.y)
 | 
			
		||||
        self.assertEqual(explosion.x, item.x)
 | 
			
		||||
 | 
			
		||||
        # The player can't hold the explosion
 | 
			
		||||
        explosion.hold(self.player)
 | 
			
		||||
        self.assertNotIn(explosion, self.player.inventory)
 | 
			
		||||
        self.assertFalse(explosion.held)
 | 
			
		||||
 | 
			
		||||
        # The explosion disappears after one tick
 | 
			
		||||
        explosion.act(self.map)
 | 
			
		||||
        self.assertNotIn(explosion, self.map.entities)
 | 
			
		||||
 | 
			
		||||
    def test_hearts(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with hearts.
 | 
			
		||||
        Tests some random stuff with hearts.
 | 
			
		||||
        """
 | 
			
		||||
        item = Heart()
 | 
			
		||||
        self.map.add_entity(item)
 | 
			
		||||
@@ -156,7 +217,7 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_body_snatch_potion(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with body snatch potions.
 | 
			
		||||
        Tests some random stuff with body snatch potions.
 | 
			
		||||
        """
 | 
			
		||||
        item = BodySnatchPotion()
 | 
			
		||||
        self.map.add_entity(item)
 | 
			
		||||
@@ -174,7 +235,7 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_players(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some random stuff with players.
 | 
			
		||||
        Tests some random stuff with players.
 | 
			
		||||
        """
 | 
			
		||||
        player = Player()
 | 
			
		||||
        self.map.add_entity(player)
 | 
			
		||||
@@ -204,3 +265,17 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
        player_state = player.save_state()
 | 
			
		||||
        self.assertEqual(player_state["current_xp"], 10)
 | 
			
		||||
 | 
			
		||||
    def test_critical_hit(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that critical hits are working.
 | 
			
		||||
        """
 | 
			
		||||
        random.seed(2)  # Next random.randint(1, 100) will output 8
 | 
			
		||||
        self.player.critical = 10
 | 
			
		||||
        sea_eagle = GiantSeaEagle()
 | 
			
		||||
        self.map.add_entity(sea_eagle)
 | 
			
		||||
        sea_eagle.move(2, 6)
 | 
			
		||||
        old_health = sea_eagle.health
 | 
			
		||||
        self.player.hit(sea_eagle)
 | 
			
		||||
        self.assertEqual(sea_eagle.health,
 | 
			
		||||
                         old_health - self.player.strength * 4)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import curses
 | 
			
		||||
import os
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
@@ -8,11 +9,13 @@ 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
 | 
			
		||||
from ..entities.items import Bomb, Heart, Sword, Explosion, Shield, Helmet, \
 | 
			
		||||
    Chestplate, RingCritical, Monocle
 | 
			
		||||
from ..entities.monsters import GiantSeaEagle
 | 
			
		||||
from ..entities.player import Player
 | 
			
		||||
from ..enums import DisplayActions
 | 
			
		||||
from ..game import Game, KeyValues, GameMode
 | 
			
		||||
from ..interfaces import Tile, Map
 | 
			
		||||
from ..interfaces import Map, Tile
 | 
			
		||||
from ..menus import MainMenuValues
 | 
			
		||||
from ..resources import ResourceManager
 | 
			
		||||
from ..settings import Settings
 | 
			
		||||
@@ -22,21 +25,21 @@ from ..translations import gettext as _, Translator
 | 
			
		||||
class TestGame(unittest.TestCase):
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Setup game.
 | 
			
		||||
        Sets the game up.
 | 
			
		||||
        """
 | 
			
		||||
        self.game = Game()
 | 
			
		||||
        self.game.new_game()
 | 
			
		||||
        self.game.map = Map.load(ResourceManager.get_asset_path(
 | 
			
		||||
            "example_map.txt"))
 | 
			
		||||
        self.game.player.move(self.game.map.start_y, self.game.map.start_x)
 | 
			
		||||
        self.game.map = Map.load(
 | 
			
		||||
            ResourceManager.get_asset_path("example_map.txt"))
 | 
			
		||||
        self.game.map.add_entity(self.game.player)
 | 
			
		||||
        self.game.player.move(self.game.map.start_y, self.game.map.start_x)
 | 
			
		||||
        self.game.logs.add_message("Hello World !")
 | 
			
		||||
        display = DisplayManager(None, self.game)
 | 
			
		||||
        self.game.display_actions = display.handle_display_action
 | 
			
		||||
 | 
			
		||||
    def test_load_game(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Save a game and reload it.
 | 
			
		||||
        Saves a game and reloads it.
 | 
			
		||||
        """
 | 
			
		||||
        bomb = Bomb()
 | 
			
		||||
        self.game.map.add_entity(bomb)
 | 
			
		||||
@@ -63,6 +66,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
        new_state = self.game.save_state()
 | 
			
		||||
        self.assertEqual(old_state, new_state)
 | 
			
		||||
        self.assertIsNone(self.game.message)
 | 
			
		||||
 | 
			
		||||
        # Ensure that the bomb is loaded
 | 
			
		||||
        self.assertTrue(self.game.player.inventory)
 | 
			
		||||
@@ -90,7 +94,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_bootstrap_fail(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the test can't play the game,
 | 
			
		||||
        Ensures that the test can't play the game,
 | 
			
		||||
        because there is no associated shell.
 | 
			
		||||
        Yeah, that's only for coverage.
 | 
			
		||||
        """
 | 
			
		||||
@@ -99,7 +103,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_key_translation(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test key bindings.
 | 
			
		||||
        Tests key bindings.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.settings = Settings()
 | 
			
		||||
 | 
			
		||||
@@ -145,6 +149,12 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_DROP, self.game.settings),
 | 
			
		||||
            KeyValues.DROP)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_WAIT, self.game.settings),
 | 
			
		||||
            KeyValues.WAIT)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(
 | 
			
		||||
            self.game.settings.KEY_LADDER, self.game.settings),
 | 
			
		||||
            KeyValues.LADDER)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key(' ', self.game.settings),
 | 
			
		||||
                         KeyValues.SPACE)
 | 
			
		||||
        self.assertEqual(KeyValues.translate_key('plop', self.game.settings),
 | 
			
		||||
@@ -152,7 +162,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_key_press(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Press a key and see what is done.
 | 
			
		||||
        Presses a key and asserts what is done is correct.
 | 
			
		||||
        """
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
			
		||||
        self.assertEqual(self.game.main_menu.validate(),
 | 
			
		||||
@@ -238,17 +248,28 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(new_y, y)
 | 
			
		||||
        self.assertEqual(new_x, x - 1)
 | 
			
		||||
 | 
			
		||||
        explosion = Explosion()
 | 
			
		||||
        self.game.map.add_entity(explosion)
 | 
			
		||||
        self.assertIn(explosion, self.game.map.entities)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.WAIT)
 | 
			
		||||
        self.assertNotIn(explosion, self.game.map.entities)
 | 
			
		||||
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.SPACE)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
			
		||||
 | 
			
		||||
    def test_mouse_click(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Simulate mouse clicks.
 | 
			
		||||
        Simulates mouse clicks.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.MAINMENU
 | 
			
		||||
 | 
			
		||||
        # Change the color of the artwork
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 0, 10,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
 | 
			
		||||
        # Settings menu
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 25, 21)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 25, 21,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.assertEqual(self.game.main_menu.position, 4)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.SETTINGS)
 | 
			
		||||
 | 
			
		||||
@@ -260,17 +281,19 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.game.state = GameMode.INVENTORY
 | 
			
		||||
 | 
			
		||||
        # Click nowhere
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 0, 0)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 0, 0,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
			
		||||
 | 
			
		||||
        # Click on the second item
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 8, 25)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 8, 25,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.INVENTORY)
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.position, 1)
 | 
			
		||||
 | 
			
		||||
    def test_new_game(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the start button starts a new game.
 | 
			
		||||
        Ensures that the start button starts a new game.
 | 
			
		||||
        """
 | 
			
		||||
        old_map = self.game.map
 | 
			
		||||
        old_player = self.game.player
 | 
			
		||||
@@ -293,7 +316,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_settings_menu(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the settings menu is working properly.
 | 
			
		||||
        Ensures that the settings menu is working properly.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.settings = Settings()
 | 
			
		||||
 | 
			
		||||
@@ -305,13 +328,13 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.SETTINGS)
 | 
			
		||||
 | 
			
		||||
        # Define the "move up" key to 'w'
 | 
			
		||||
        # Define the "move up" key to 'h'
 | 
			
		||||
        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        self.assertTrue(self.game.settings_menu.waiting_for_key)
 | 
			
		||||
        self.game.handle_key_pressed(None, 'w')
 | 
			
		||||
        self.game.handle_key_pressed(None, 'h')
 | 
			
		||||
        self.assertFalse(self.game.settings_menu.waiting_for_key)
 | 
			
		||||
        self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'w')
 | 
			
		||||
        self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'h')
 | 
			
		||||
 | 
			
		||||
        # Navigate to "move left"
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
@@ -332,7 +355,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a')
 | 
			
		||||
 | 
			
		||||
        # Navigate to "texture pack"
 | 
			
		||||
        for ignored in range(10):
 | 
			
		||||
        for ignored in range(12):
 | 
			
		||||
            self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
 | 
			
		||||
        # Change texture pack
 | 
			
		||||
@@ -379,7 +402,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_dead_screen(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Kill player and render dead screen.
 | 
			
		||||
        Kills the player and renders the dead message on the fake screen.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
        # Kill player
 | 
			
		||||
@@ -395,13 +418,14 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_not_implemented(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Check that some functions are not implemented, only for coverage.
 | 
			
		||||
        Checks that some functions are not implemented, only for coverage.
 | 
			
		||||
        """
 | 
			
		||||
        self.assertRaises(NotImplementedError, Display.display, None)
 | 
			
		||||
        self.assertRaises(NotImplementedError, Display.update, None, self.game)
 | 
			
		||||
 | 
			
		||||
    def test_messages(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Display error messages.
 | 
			
		||||
        Displays error messages.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.message = "I am an error"
 | 
			
		||||
        self.game.display_actions(DisplayActions.UPDATE)
 | 
			
		||||
@@ -411,7 +435,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_inventory_menu(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Open the inventory menu and interact with items.
 | 
			
		||||
        Opens the inventory menu and interacts with items.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
        # Open and close the inventory
 | 
			
		||||
@@ -472,7 +496,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_talk_to_sunflowers(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Interact with sunflowers
 | 
			
		||||
        Interacts with sunflowers.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
 | 
			
		||||
@@ -504,8 +528,8 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.PLAY)
 | 
			
		||||
        self.assertTrue(self.game.logs.messages)
 | 
			
		||||
        # Ensure that the message is a good message
 | 
			
		||||
        self.assertIn(self.game.logs.messages[1][21:],
 | 
			
		||||
                      Sunflower.dialogue_option)
 | 
			
		||||
        self.assertTrue(any(self.game.logs.messages[1].endswith(msg)
 | 
			
		||||
                            for msg in Sunflower().dialogue_option))
 | 
			
		||||
 | 
			
		||||
        # Test all directions to detect the friendly entity
 | 
			
		||||
        self.game.player.move(sunflower.y + 1, sunflower.x)
 | 
			
		||||
@@ -523,7 +547,7 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_talk_to_merchant(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Interact with merchants
 | 
			
		||||
        Interacts with merchants.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
 | 
			
		||||
@@ -545,21 +569,28 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        # Navigate in the menu
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.DOWN)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.LEFT)
 | 
			
		||||
        self.assertFalse(self.game.is_in_store_menu)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.RIGHT)
 | 
			
		||||
        self.assertTrue(self.game.is_in_store_menu)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.UP)
 | 
			
		||||
        self.assertEqual(self.game.store_menu.position, 1)
 | 
			
		||||
 | 
			
		||||
        self.game.player.hazel = 0x7ffff42ff
 | 
			
		||||
 | 
			
		||||
        # The second item is not a heart
 | 
			
		||||
        merchant.inventory[1] = Sword()
 | 
			
		||||
        merchant.inventory[1] = sword = Sword()
 | 
			
		||||
        # Buy the second item by clicking on it
 | 
			
		||||
        item = self.game.store_menu.validate()
 | 
			
		||||
        self.assertIn(item, merchant.inventory)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 8, 25)
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 7, 25,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.assertIn(item, self.game.player.inventory)
 | 
			
		||||
        self.assertNotIn(item, merchant.inventory)
 | 
			
		||||
 | 
			
		||||
        # Buy a heart
 | 
			
		||||
        merchant.inventory[1] = Heart()
 | 
			
		||||
        self.game.display_actions(DisplayActions.REFRESH)
 | 
			
		||||
        item = self.game.store_menu.validate()
 | 
			
		||||
        self.assertIn(item, merchant.inventory)
 | 
			
		||||
        self.assertEqual(item, merchant.inventory[1])
 | 
			
		||||
@@ -576,9 +607,169 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        self.assertNotIn(item, self.game.player.inventory)
 | 
			
		||||
        self.assertIn(item, merchant.inventory)
 | 
			
		||||
        self.assertEqual(self.game.message, _("You do not have enough money"))
 | 
			
		||||
        self.assertEqual(self.game.message,
 | 
			
		||||
                         _("The buyer does not have enough money"))
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
 | 
			
		||||
        # Sell an item
 | 
			
		||||
        self.game.inventory_menu.position = len(self.game.player.inventory) - 1
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.LEFT)
 | 
			
		||||
        self.assertFalse(self.game.is_in_store_menu)
 | 
			
		||||
        self.assertIn(sword, self.game.player.inventory)
 | 
			
		||||
        self.assertEqual(self.game.inventory_menu.validate(), sword)
 | 
			
		||||
        old_player_money, old_merchant_money = self.game.player.hazel,\
 | 
			
		||||
            merchant.hazel
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        self.assertNotIn(sword, self.game.player.inventory)
 | 
			
		||||
        self.assertIn(sword, merchant.inventory)
 | 
			
		||||
        self.assertEqual(self.game.player.hazel, old_player_money + sword.price)
 | 
			
		||||
        self.assertEqual(merchant.hazel, old_merchant_money - sword.price)
 | 
			
		||||
 | 
			
		||||
        # Exit the menu
 | 
			
		||||
        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_monocle(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        The player is wearing a monocle, then the stats are displayed.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.PLAY
 | 
			
		||||
 | 
			
		||||
        monocle = Monocle()
 | 
			
		||||
        monocle.hold(self.game.player)
 | 
			
		||||
        monocle.equip()
 | 
			
		||||
 | 
			
		||||
        sea_eagle = GiantSeaEagle()
 | 
			
		||||
        self.game.map.add_entity(sea_eagle)
 | 
			
		||||
        sea_eagle.move(2, 6)
 | 
			
		||||
 | 
			
		||||
        self.game.display_actions(DisplayActions.REFRESH)
 | 
			
		||||
 | 
			
		||||
    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:
 | 
			
		||||
        """
 | 
			
		||||
        Load credits menu.
 | 
			
		||||
        """
 | 
			
		||||
        self.game.state = GameMode.MAINMENU
 | 
			
		||||
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 41, 41,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.CREDITS)
 | 
			
		||||
        self.game.display_actions(DisplayActions.MOUSE, 21, 21,
 | 
			
		||||
                                  curses.BUTTON1_CLICKED)
 | 
			
		||||
        self.game.display_actions(DisplayActions.REFRESH)
 | 
			
		||||
 | 
			
		||||
        self.game.state = GameMode.CREDITS
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,14 @@
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.display.texturepack import TexturePack
 | 
			
		||||
from squirrelbattle.interfaces import Map, Tile
 | 
			
		||||
from squirrelbattle.interfaces import Map, Tile, Slope
 | 
			
		||||
from squirrelbattle.resources import ResourceManager
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestInterfaces(unittest.TestCase):
 | 
			
		||||
    def test_map(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Create a map and check that it is well parsed.
 | 
			
		||||
        Creates a map and checks that it is well parsed.
 | 
			
		||||
        """
 | 
			
		||||
        m = Map.load_from_string("0 0\n.#\n#.\n")
 | 
			
		||||
        self.assertEqual(m.width, 2)
 | 
			
		||||
@@ -20,7 +20,7 @@ class TestInterfaces(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_load_map(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Try to load a map from a file.
 | 
			
		||||
        Tries to load a map from a file.
 | 
			
		||||
        """
 | 
			
		||||
        m = Map.load(ResourceManager.get_asset_path("example_map.txt"))
 | 
			
		||||
        self.assertEqual(m.width, 52)
 | 
			
		||||
@@ -28,7 +28,7 @@ class TestInterfaces(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_tiles(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Test some things about tiles.
 | 
			
		||||
        Tests some things about tiles.
 | 
			
		||||
        """
 | 
			
		||||
        self.assertFalse(Tile.FLOOR.is_wall())
 | 
			
		||||
        self.assertTrue(Tile.WALL.is_wall())
 | 
			
		||||
@@ -37,3 +37,21 @@ class TestInterfaces(unittest.TestCase):
 | 
			
		||||
        self.assertFalse(Tile.WALL.can_walk())
 | 
			
		||||
        self.assertFalse(Tile.EMPTY.can_walk())
 | 
			
		||||
        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)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,8 @@ class FakePad:
 | 
			
		||||
    def addstr(self, y: int, x: int, message: str, color: int = 0) -> None:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def refresh(self, pminrow: int, pmincol: int, sminrow: int,
 | 
			
		||||
                smincol: int, smaxrow: int, smaxcol: int) -> None:
 | 
			
		||||
    def noutrefresh(self, pminrow: int, pmincol: int, sminrow: int,
 | 
			
		||||
                    smincol: int, smaxrow: int, smaxcol: int) -> None:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def erase(self) -> None:
 | 
			
		||||
@@ -24,3 +24,6 @@ class FakePad:
 | 
			
		||||
 | 
			
		||||
    def getmaxyx(self) -> Tuple[int, int]:
 | 
			
		||||
        return 42, 42
 | 
			
		||||
 | 
			
		||||
    def inch(self, y: int, x: int) -> str:
 | 
			
		||||
        return "i"
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ class TestSettings(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_settings(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that settings are well loaded.
 | 
			
		||||
        Ensures that settings are well loaded.
 | 
			
		||||
        """
 | 
			
		||||
        settings = Settings()
 | 
			
		||||
        self.assertEqual(settings.KEY_UP_PRIMARY, 'z')
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ class TestTranslations(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_main_menu_translation(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the main menu is translated.
 | 
			
		||||
        Ensures that the main menu is translated.
 | 
			
		||||
        """
 | 
			
		||||
        self.assertEqual(_("New game"), "Nouvelle partie")
 | 
			
		||||
        self.assertEqual(_("Resume"), "Continuer")
 | 
			
		||||
@@ -22,7 +22,7 @@ class TestTranslations(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_settings_menu_translation(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Ensure that the settings menu is translated.
 | 
			
		||||
        Ensures that the settings menu is translated.
 | 
			
		||||
        """
 | 
			
		||||
        self.assertEqual(_("Main key to move up"),
 | 
			
		||||
                         "Touche principale pour aller vers le haut")
 | 
			
		||||
@@ -52,18 +52,33 @@ class TestTranslations(unittest.TestCase):
 | 
			
		||||
                         "Touche pour jeter un objet de l'inventaire")
 | 
			
		||||
        self.assertEqual(_("Key used to talk to a friendly entity"),
 | 
			
		||||
                         "Touche pour parler à une entité pacifique")
 | 
			
		||||
        self.assertEqual(_("Key used to wait"), "Touche pour attendre")
 | 
			
		||||
        self.assertEqual(_("Key used to use ladders"),
 | 
			
		||||
                         "Touche pour utiliser les échelles")
 | 
			
		||||
        self.assertEqual(_("Texture pack"), "Pack de textures")
 | 
			
		||||
        self.assertEqual(_("Language"), "Langue")
 | 
			
		||||
 | 
			
		||||
    def test_entities_translation(self) -> None:
 | 
			
		||||
        self.assertEqual(_("player"), "joueur")
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(_("tiger"), "tigre")
 | 
			
		||||
        self.assertEqual(_("hedgehog"), "hérisson")
 | 
			
		||||
        self.assertEqual(_("merchant"), "marchand")
 | 
			
		||||
        self.assertEqual(_("rabbit"), "lapin")
 | 
			
		||||
        self.assertEqual(_("sunflower"), "tournesol")
 | 
			
		||||
        self.assertEqual(_("teddy bear"), "nounours")
 | 
			
		||||
        self.assertEqual(_("tiger"), "tigre")
 | 
			
		||||
        self.assertEqual(_("eagle"), "pygargue")
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(_("body snatch potion"), "potion d'arrachage de corps")
 | 
			
		||||
        self.assertEqual(_("bomb"), "bombe")
 | 
			
		||||
        self.assertEqual(_("explosion"), "explosion")
 | 
			
		||||
        self.assertEqual(_("heart"), "cœur")
 | 
			
		||||
        self.assertEqual(_("sword"), "épée")
 | 
			
		||||
        self.assertEqual(_("helmet"), "casque")
 | 
			
		||||
        self.assertEqual(_("chestplate"), "plastron")
 | 
			
		||||
        self.assertEqual(_("shield"), "bouclier")
 | 
			
		||||
        self.assertEqual(_("ring of critical damage"),
 | 
			
		||||
                         "anneau de coup critique")
 | 
			
		||||
        self.assertEqual(_("ring of more experience"),
 | 
			
		||||
                         "anneau de plus d'expérience")
 | 
			
		||||
        self.assertEqual(_("monocle"), "monocle")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user