# Copyright (C) 2020-2021 by ÿnérant, eichhornchen, nicomarg, charlse # SPDX-License-Identifier: GPL-3.0-or-later import curses import unittest from ..bootstrap import Bootstrap from ..display.display import Display from ..display.display_manager import DisplayManager from ..entities.friendly import Chest, Merchant, Sunflower from ..entities.items import Bomb, Bow, Chestplate, Explosion, FireBallStaff, \ Heart, Helmet, Monocle, RingCritical, ScrollofDamage, ScrollofWeakening, \ Shield, Sword from ..entities.monsters import GiantSeaEagle, Rabbit from ..entities.player import Player from ..enums import DisplayActions, GameMode, KeyValues from ..game import Game from ..interfaces import Map, Tile from ..menus import MainMenuValues from ..resources import ResourceManager from ..settings import Settings from ..translations import gettext as _, Translator class TestGame(unittest.TestCase): def setUp(self) -> None: """ 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.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: """ Saves a game and reloads it. """ bomb = Bomb() self.game.map.add_entity(bomb) sword = Sword() self.game.map.add_entity(sword) # Add items in the inventory to check that it is well loaded bomb.hold(self.game.player) sword.hold(self.game.player) sword.equip() # Ensure that merchants can be saved merchant = Merchant() merchant.move(3, 6) self.game.map.add_entity(merchant) old_state = self.game.save_state() self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SAVE) self.game.handle_key_pressed(KeyValues.ENTER) # Save game self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.LOAD) self.game.handle_key_pressed(KeyValues.ENTER) # Load game 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) # Error on loading save with open(ResourceManager.get_config_path("save.json"), "w") as f: f.write("I am not a JSON file") self.assertIsNone(self.game.message) self.game.load_game() self.assertIsNotNone(self.game.message) self.game.message = None with open(ResourceManager.get_config_path("save.json"), "w") as f: f.write("{}") self.assertIsNone(self.game.message) self.game.load_game() self.assertIsNotNone(self.game.message) self.game.message = None # Load game with a dead player self.game.map.remove_entity(self.game.player) self.game.save_game() self.game.load_game() self.assertIsNotNone(self.game.message) def test_bootstrap_fail(self) -> None: """ Ensures that the test can't play the game, because there is no associated shell. Yeah, that's only for coverage. """ self.assertRaises(Exception, Bootstrap.run_game) def test_key_translation(self) -> None: """ Tests key bindings. """ self.game.settings = Settings() self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_UP_PRIMARY, self.game.settings), KeyValues.UP) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_UP_SECONDARY, self.game.settings), KeyValues.UP) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_DOWN_PRIMARY, self.game.settings), KeyValues.DOWN) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_DOWN_SECONDARY, self.game.settings), KeyValues.DOWN) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_LEFT_PRIMARY, self.game.settings), KeyValues.LEFT) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_LEFT_SECONDARY, self.game.settings), KeyValues.LEFT) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_RIGHT_PRIMARY, self.game.settings), KeyValues.RIGHT) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_RIGHT_SECONDARY, self.game.settings), KeyValues.RIGHT) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_ENTER, self.game.settings), KeyValues.ENTER) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_INVENTORY, self.game.settings), KeyValues.INVENTORY) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_CHAT, self.game.settings), KeyValues.CHAT) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_USE, self.game.settings), KeyValues.USE) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_EQUIP, self.game.settings), KeyValues.EQUIP) 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), None) self.assertEqual(KeyValues.translate_key( self.game.settings.KEY_DANCE, self.game.settings), KeyValues.DANCE) def test_key_press(self) -> None: """ Presses a key and asserts what is done is correct. """ self.assertEqual(self.game.state, GameMode.MAINMENU) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.START) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.START) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.RESUME) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SAVE) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.LOAD) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SETTINGS) self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.state, GameMode.SETTINGS) self.game.handle_key_pressed(KeyValues.SPACE) self.assertEqual(self.game.state, GameMode.MAINMENU) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.EXIT) self.assertRaises(SystemExit, self.game.handle_key_pressed, KeyValues.ENTER) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SETTINGS) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.LOAD) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SAVE) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.RESUME) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.main_menu.validate(), MainMenuValues.START) self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.state, GameMode.PLAY) # Kill entities for entity in self.game.map.entities.copy(): if not isinstance(entity, Player): self.game.map.remove_entity(entity) y, x = self.game.player.y, self.game.player.x # Ensure that the neighborhood is walkable for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: self.game.map.tiles[y + dy][x + dx] = Tile.FLOOR self.game.handle_key_pressed(KeyValues.DOWN) new_y, new_x = self.game.player.y, self.game.player.x self.assertEqual(new_y, y + 1) self.assertEqual(new_x, x) y, x = new_y, new_x self.game.handle_key_pressed(KeyValues.RIGHT) new_y, new_x = self.game.player.y, self.game.player.x self.assertEqual(new_y, y) self.assertEqual(new_x, x + 1) y, x = self.game.player.y, self.game.player.x self.game.handle_key_pressed(KeyValues.UP) new_y, new_x = self.game.player.y, self.game.player.x self.assertEqual(new_y, y - 1) self.assertEqual(new_x, x) y, x = self.game.player.y, self.game.player.x self.game.handle_key_pressed(KeyValues.LEFT) new_y, new_x = self.game.player.y, self.game.player.x 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.game.handle_key_pressed(KeyValues.WAIT) self.assertNotIn(explosion, self.game.map.entities) rabbit = Rabbit() self.game.map.add_entity(rabbit) self.game.player.move(1, 6) rabbit.move(3, 6) self.game.player.charisma = 11 self.game.handle_key_pressed(KeyValues.DANCE) self.assertEqual(rabbit.confused, 1) string = rabbit.hit(self.game.player) self.assertEqual( string, _("{name} is confused, it can not hit {opponent}.") .format(name=rabbit.translated_name.capitalize(), opponent=self.game.player.translated_name)) rabbit.confused = 0 self.game.player.charisma = 0 self.game.handle_key_pressed(KeyValues.DANCE) self.assertEqual(rabbit.confused, 0) rabbit.die() self.game.player.charisma = 11 self.game.handle_key_pressed(KeyValues.DANCE) self.game.player.charisma = 1 self.game.handle_key_pressed(KeyValues.SPACE) self.assertEqual(self.game.state, GameMode.MAINMENU) def test_mouse_click(self) -> None: """ 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, curses.BUTTON1_CLICKED) self.assertEqual(self.game.main_menu.position, 4) self.assertEqual(self.game.state, GameMode.SETTINGS) bomb = Bomb() bomb.hold(self.game.player) bomb2 = Bomb() bomb2.hold(self.game.player) self.game.state = GameMode.INVENTORY # Click nowhere 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, curses.BUTTON1_CLICKED) self.assertEqual(self.game.state, GameMode.INVENTORY) self.assertEqual(self.game.inventory_menu.position, 1) def test_new_game(self) -> None: """ Ensures that the start button starts a new game. """ old_map = self.game.map old_player = self.game.player self.game.handle_key_pressed(KeyValues.ENTER) # Start new game new_map = self.game.map new_player = self.game.player # Ensure that self.assertNotEqual(old_map, new_map) self.assertNotEqual(old_player, new_player) self.game.handle_key_pressed(KeyValues.SPACE) old_map = new_map old_player = new_player self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.ENTER) # Resume game new_map = self.game.map new_player = self.game.player self.assertEqual(old_map, new_map) self.assertEqual(old_player, new_player) def test_settings_menu(self) -> None: """ Ensures that the settings menu is working properly. """ self.game.settings = Settings() # Open settings menu self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.state, GameMode.SETTINGS) # 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, 'h') self.assertFalse(self.game.settings_menu.waiting_for_key) self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'h') # Navigate to "move left" self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.UP) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) # Define the "move up" key to 'a' self.game.handle_key_pressed(KeyValues.ENTER) self.assertTrue(self.game.settings_menu.waiting_for_key) # Can't used a mapped key self.game.handle_key_pressed(None, 's') self.assertTrue(self.game.settings_menu.waiting_for_key) self.game.handle_key_pressed(None, 'a') self.assertFalse(self.game.settings_menu.waiting_for_key) self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a') # Navigate to "texture pack" for ignored in range(14): self.game.handle_key_pressed(KeyValues.DOWN) # Change texture pack self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii") self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.TEXTURE_PACK, "squirrel") self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii") # Change language Translator.compilemessages() Translator.refresh_translations() self.game.settings.LOCALE = "en" self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.LOCALE, "fr") self.assertEqual(_("New game"), "Nouvelle partie") self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.LOCALE, "de") self.assertEqual(_("New game"), "Neu Spiel") self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.LOCALE, "es") self.assertEqual(_("New game"), "Nuevo partido") self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.settings.LOCALE, "en") self.assertEqual(_("New game"), "New game") # Navigate to "back" button self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.ENTER) self.assertEqual(self.game.state, GameMode.MAINMENU) def test_logs(self) -> None: """ Tests the use of logs """ self.assertEqual(self.game.logs.messages, ["Hello World !"]) self.game.logs.add_messages(["Hello", "World"]) self.assertEqual(self.game.logs.messages, ["Hello World !", "Hello", "World"]) self.game.logs.clear() self.assertEqual(self.game.logs.messages, []) def test_dead_screen(self) -> None: """ Kills the player and renders the dead message on the fake screen. """ self.game.state = GameMode.PLAY # Kill player self.game.player.take_damage(self.game.player, self.game.player.health + 2) y, x = self.game.player.y, self.game.player.x for key in [KeyValues.UP, KeyValues.DOWN, KeyValues.LEFT, KeyValues.RIGHT]: self.game.handle_key_pressed(key) new_y, new_x = self.game.player.y, self.game.player.x self.assertEqual(new_y, y) self.assertEqual(new_x, x) def test_not_implemented(self) -> None: """ 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: """ Displays error messages. """ self.game.message = "I am an error" self.game.display_actions(DisplayActions.UPDATE) self.game.display_actions(DisplayActions.REFRESH) self.game.handle_key_pressed(None, "random key") self.assertIsNone(self.game.message) def test_inventory_menu(self) -> None: """ Opens the inventory menu and interacts with items. """ self.game.state = GameMode.PLAY # Open and close the inventory self.game.handle_key_pressed(KeyValues.INVENTORY) self.assertEqual(self.game.state, GameMode.INVENTORY) self.game.handle_key_pressed(KeyValues.SPACE) self.assertEqual(self.game.state, GameMode.PLAY) # Add five bombs in the inventory for ignored in range(5): bomb = Bomb() bomb.map = self.game.map bomb.map.add_entity(bomb) bomb.hold(self.game.player) self.game.handle_key_pressed(KeyValues.INVENTORY) self.assertEqual(self.game.state, GameMode.INVENTORY) # Navigate in the menu self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.inventory_menu.position, 3) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.DOWN) self.game.handle_key_pressed(KeyValues.UP) self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.inventory_menu.position, 4) # Equip key does nothing self.game.handle_key_pressed(KeyValues.EQUIP) # Drop an item bomb = self.game.player.inventory[-1] self.assertEqual(self.game.inventory_menu.validate(), bomb) self.assertEqual(bomb.held_by, self.game.player) self.game.handle_key_pressed(KeyValues.DROP) self.assertIsNone(bomb.held_by) self.assertIsNone(bomb.owner) self.assertFalse(bomb.exploding) self.assertEqual(bomb.y, self.game.player.y) self.assertEqual(bomb.x, self.game.player.x) # Use the bomb bomb = self.game.player.inventory[-1] self.assertEqual(self.game.inventory_menu.validate(), bomb) self.assertEqual(bomb.held_by, self.game.player) self.game.handle_key_pressed(KeyValues.USE) self.assertIsNone(bomb.held_by) self.assertEqual(bomb.owner, self.game.player) self.assertTrue(bomb.exploding) self.assertEqual(bomb.y, self.game.player.y) self.assertEqual(bomb.x, self.game.player.x) def test_talk_to_sunflowers(self) -> None: """ Interacts with sunflowers. """ self.game.state = GameMode.PLAY sunflower = Sunflower() sunflower.move(self.game.player.y + 1, self.game.player.x) self.game.map.add_entity(sunflower) # Does nothing self.assertIsNone(self.game.handle_friendly_entity_chat(KeyValues.UP)) # Talk to sunflower... or not self.game.handle_key_pressed(KeyValues.CHAT) self.assertTrue(self.game.waiting_for_friendly_key) # Wrong key self.game.handle_key_pressed(KeyValues.EQUIP) self.assertFalse(self.game.waiting_for_friendly_key) self.game.handle_key_pressed(KeyValues.CHAT) self.assertTrue(self.game.waiting_for_friendly_key) self.game.handle_key_pressed(KeyValues.UP) self.assertFalse(self.game.waiting_for_friendly_key) self.assertEqual(self.game.state, GameMode.PLAY) self.assertFalse(len(self.game.logs.messages) > 1) # Talk to sunflower self.game.handle_key_pressed(KeyValues.CHAT) self.assertTrue(self.game.waiting_for_friendly_key) self.game.handle_key_pressed(KeyValues.DOWN) self.assertFalse(self.game.waiting_for_friendly_key) self.assertEqual(self.game.state, GameMode.PLAY) self.assertTrue(self.game.logs.messages) # Ensure that the message is a good message 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) self.game.handle_key_pressed(KeyValues.CHAT) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(len(self.game.logs.messages), 3) self.game.player.move(sunflower.y, sunflower.x + 1) self.game.handle_key_pressed(KeyValues.CHAT) self.game.handle_key_pressed(KeyValues.LEFT) self.assertEqual(len(self.game.logs.messages), 4) self.game.player.move(sunflower.y, sunflower.x - 1) self.game.handle_key_pressed(KeyValues.CHAT) self.game.handle_key_pressed(KeyValues.RIGHT) self.assertEqual(len(self.game.logs.messages), 5) def test_talk_to_merchant(self) -> None: """ Interacts with merchants. """ self.game.state = GameMode.PLAY merchant = Merchant() merchant.move(self.game.player.y + 1, self.game.player.x) self.game.map.add_entity(merchant) # Does nothing self.assertIsNone(self.game.handle_friendly_entity_chat(KeyValues.UP)) # Talk to merchant self.game.handle_key_pressed(KeyValues.CHAT) self.assertTrue(self.game.waiting_for_friendly_key) self.game.handle_key_pressed(KeyValues.DOWN) self.assertFalse(self.game.waiting_for_friendly_key) self.assertEqual(self.game.state, GameMode.STORE) self.assertTrue(self.game.logs.messages) # 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 = 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, 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]) self.game.player.health = self.game.player.maxhealth - 1 - item.healing self.game.handle_key_pressed(KeyValues.ENTER) self.assertNotIn(item, self.game.player.inventory) self.assertNotIn(item, merchant.inventory) self.assertEqual(self.game.player.health, self.game.player.maxhealth - 1) # We don't have enough of money self.game.player.hazel = 0 item = self.game.store_menu.validate() self.game.handle_key_pressed(KeyValues.ENTER) self.assertNotIn(item, self.game.player.inventory) self.assertIn(item, merchant.inventory) 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) # shield goes into the secondary equipment slot shield = Shield() shield.hold(self.game.player) shield.equip() self.assertEqual(self.game.player.equipped_secondary, shield) # helmet goes into the helmet slot helmet = Helmet() helmet.hold(self.game.player) helmet.equip() self.assertEqual(self.game.player.equipped_helmet, helmet) # helmet goes into the armor slot chestplate = Chestplate() chestplate.hold(self.game.player) chestplate.equip() self.assertEqual(self.game.player.equipped_armor, chestplate) # Use bomb bomb = Bomb() bomb.hold(self.game.player) bomb.equip() self.assertEqual(self.game.player.equipped_secondary, bomb) self.assertFalse(shield.equipped) self.game.state = GameMode.PLAY self.game.handle_key_pressed(KeyValues.USE) self.assertIsNone(self.game.player.equipped_secondary) self.game.state = GameMode.INVENTORY shield.equip() self.assertEqual(self.game.player.equipped_secondary, shield) # 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) self.game.display_actions(DisplayActions.REFRESH) # Test rings self.game.player.inventory.clear() ring = RingCritical() ring.hold(self.game.player) self.game.display_actions(DisplayActions.REFRESH) 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.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) 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, []) def test_chests(self) -> None: """ Interacts with chests. """ self.game.state = GameMode.PLAY chest = Chest() chest.move(2, 6) self.game.map.add_entity(chest) chest.inventory.append(FireBallStaff()) # Talk to merchant self.game.handle_key_pressed(KeyValues.CHAT) self.assertTrue(self.game.waiting_for_friendly_key) self.game.handle_key_pressed(KeyValues.DOWN) self.assertFalse(self.game.waiting_for_friendly_key) self.assertEqual(self.game.state, GameMode.CHEST) self.assertTrue(self.game.logs.messages) # 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_chest_menu) self.game.handle_key_pressed(KeyValues.RIGHT) self.assertTrue(self.game.is_in_chest_menu) self.game.handle_key_pressed(KeyValues.UP) self.assertEqual(self.game.chest_menu.position, 1) # The second item is not a heart chest.inventory[1] = sword = Sword() # Take the second item item = self.game.chest_menu.validate() self.assertIn(item, chest.inventory) self.game.display_actions(DisplayActions.MOUSE, 7, 25, curses.BUTTON1_CLICKED) self.assertIn(item, self.game.player.inventory) self.assertNotIn(item, chest.inventory) # Give an item back self.game.inventory_menu.position = len(self.game.player.inventory) - 1 self.game.handle_key_pressed(KeyValues.LEFT) self.assertFalse(self.game.is_in_chest_menu) self.assertIn(sword, self.game.player.inventory) self.assertEqual(self.game.inventory_menu.validate(), sword) self.game.handle_key_pressed(KeyValues.ENTER) self.assertNotIn(sword, self.game.player.inventory) self.assertIn(sword, chest.inventory) # Test immortality self.game.player.hit(chest) self.assertTrue(not chest.dead) # Exit the menu self.game.handle_key_pressed(KeyValues.SPACE) self.assertEqual(self.game.state, GameMode.PLAY) def test_doors(self) -> None: """ Check that the user can open doors. """ self.game.state = GameMode.PLAY self.game.player.move(9, 8) self.assertEqual(self.game.map.tiles[10][8], Tile.DOOR) # Open door self.game.handle_key_pressed(KeyValues.DOWN) self.assertEqual(self.game.map.tiles[10][8], Tile.FLOOR) self.assertEqual(self.game.player.y, 10) self.assertEqual(self.game.player.x, 8) self.game.display_actions(DisplayActions.REFRESH)