squirrel-battle/squirrelbattle/tests/entities_test.py

305 lines
10 KiB
Python
Raw Permalink Normal View History

2021-01-10 09:46:17 +00:00
# Copyright (C) 2020-2021 by ÿnérant, eichhornchen, nicomarg, charlse
2020-11-27 15:33:17 +00:00
# SPDX-License-Identifier: GPL-3.0-or-later
2021-01-10 10:25:53 +00:00
2021-01-08 14:58:54 +00:00
import random
2020-11-06 15:13:28 +00:00
import unittest
from ..entities.friendly import Chest, Trumpet
2021-01-10 10:25:53 +00:00
from ..entities.items import BodySnatchPotion, Bomb, Explosion, Heart, Item
from ..entities.monsters import GiantSeaEagle, Hedgehog, Rabbit, \
TeddyBear, Tiger
from ..entities.player import Player
from ..interfaces import Entity, Map
from ..resources import ResourceManager
2020-11-06 15:13:28 +00:00
class TestEntities(unittest.TestCase):
def setUp(self) -> None:
"""
Loads example map that can be used in tests.
2020-11-06 15:13:28 +00:00
"""
2020-11-19 01:49:59 +00:00
self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
2020-11-11 15:58:20 +00:00
self.player = Player()
2021-01-05 18:50:25 +00:00
self.player.constitution = 0
2020-11-11 15:58:20 +00:00
self.map.add_entity(self.player)
self.player.move(self.map.start_y, self.map.start_x)
2020-11-06 15:13:28 +00:00
def test_basic_entities(self) -> None:
"""
Tests some random stuff with basic entities.
2020-11-06 15:13:28 +00:00
"""
entity = Entity()
entity.move(42, 64)
self.assertEqual(entity.y, 42)
self.assertEqual(entity.x, 64)
self.assertIsNone(entity.act(self.map))
2020-11-10 21:59:02 +00:00
other_entity = Entity()
other_entity.move(45, 68)
self.assertEqual(entity.distance_squared(other_entity), 25)
self.assertEqual(entity.distance(other_entity), 5)
2020-11-06 15:13:28 +00:00
def test_fighting_entities(self) -> None:
"""
Tests some random stuff with fighting entities.
2020-11-06 15:13:28 +00:00
"""
2020-11-20 17:02:08 +00:00
entity = Tiger()
2020-11-10 21:44:53 +00:00
self.map.add_entity(entity)
self.assertEqual(entity.maxhealth, 30)
2020-11-06 15:13:28 +00:00
self.assertEqual(entity.maxhealth, entity.health)
self.assertEqual(entity.strength, 5)
for _ in range(5):
2020-11-19 19:02:44 +00:00
self.assertEqual(entity.hit(entity),
"Tiger hits tiger. Tiger takes 5 damage.")
2020-11-19 00:11:11 +00:00
self.assertFalse(entity.dead)
2020-11-28 00:25:35 +00:00
self.assertEqual(entity.hit(entity), "Tiger hits tiger. "
+ "Tiger takes 5 damage. Tiger dies.")
2020-11-06 15:13:28 +00:00
self.assertTrue(entity.dead)
2020-11-19 00:11:11 +00:00
entity = Rabbit()
entity.health = 15
2021-01-05 18:50:25 +00:00
entity.critical = 0
2020-11-10 21:44:53 +00:00
self.map.add_entity(entity)
entity.move(15, 44)
# Move randomly
self.map.tick(self.player)
self.assertFalse(entity.y == 15 and entity.x == 44)
# Move to the player
2020-11-11 15:58:20 +00:00
entity.move(3, 6)
self.map.tick(self.player)
2020-11-11 15:58:20 +00:00
self.assertTrue(entity.y == 2 and entity.x == 6)
2020-11-10 21:44:53 +00:00
2020-11-19 00:11:11 +00:00
# Rabbit should fight
old_health = self.player.health
self.map.tick(self.player)
self.assertTrue(entity.y == 2 and entity.x == 6)
self.assertEqual(old_health - entity.strength, self.player.health)
2020-11-19 19:02:44 +00:00
self.assertEqual(self.map.logs.messages[-1],
2020-11-28 00:25:35 +00:00
f"{entity.name.capitalize()} hits {self.player.name}. \
{self.player.name.capitalize()} takes {entity.strength} damage.")
2020-11-19 00:11:11 +00:00
# Fight the rabbit
2021-01-06 16:39:13 +00:00
self.player.critical = 0
2020-11-19 00:11:11 +00:00
old_health = entity.health
self.player.move_down()
self.assertEqual(entity.health, old_health - self.player.strength)
self.assertFalse(entity.dead)
old_health = entity.health
self.player.move_down()
self.assertEqual(entity.health, old_health - self.player.strength)
self.assertFalse(entity.dead)
old_health = entity.health
self.player.move_down()
self.assertEqual(entity.health, old_health - self.player.strength)
self.assertTrue(entity.dead)
self.assertGreaterEqual(self.player.current_xp, 3)
# Test that a chest is destroyed by a bomb
bomb = Bomb()
bomb.owner = self.player
bomb.move(3, 6)
self.map.add_entity(bomb)
chest = Chest()
chest.move(4, 6)
self.map.add_entity(chest)
bomb.exploding = True
for _ in range(5):
self.map.tick(self.player)
self.assertTrue(chest.annihilated)
def test_familiar(self) -> None:
2020-12-31 14:43:38 +00:00
fam = Trumpet()
entity = Rabbit()
self.map.add_entity(entity)
self.map.add_entity(fam)
2020-12-31 16:15:24 +00:00
self.player.move(1, 6)
entity.move(2, 6)
fam.move(2, 7)
2021-01-05 09:20:55 +00:00
# Test fighting
2020-12-31 14:43:38 +00:00
entity.health = 2
entity.paths = []
entity.recalculate_paths()
fam.target = entity
self.map.tick(self.player)
self.assertTrue(entity.dead)
2021-01-05 09:20:55 +00:00
# Test finding a new target
2021-01-05 08:38:49 +00:00
entity2 = Rabbit()
self.map.add_entity(entity2)
entity2.move(2, 6)
self.map.tick(self.player)
2021-01-05 09:20:55 +00:00
self.assertTrue(fam.target == entity2)
2021-01-05 08:38:49 +00:00
self.map.remove_entity(entity2)
2021-01-05 09:20:55 +00:00
# Test following the player and finding the player as target
2020-12-31 16:15:24 +00:00
self.player.move(5, 5)
fam.move(4, 5)
2021-01-05 08:38:49 +00:00
fam.target = None
2020-12-31 14:43:38 +00:00
self.player.move_down()
self.map.tick(self.player)
2021-01-05 09:20:55 +00:00
self.assertTrue(fam.target == self.player)
2020-12-31 14:43:38 +00:00
self.assertEqual(fam.y, 5)
self.assertEqual(fam.x, 5)
2021-01-05 09:20:55 +00:00
# Test random move
2021-01-05 08:38:49 +00:00
fam.move(13, 20)
2021-01-05 09:20:55 +00:00
fam.target = self.player
2021-01-05 08:38:49 +00:00
self.map.tick(self.player)
2021-01-05 09:20:55 +00:00
self.assertTrue(fam.x != 20 or fam.y != 13)
2021-01-05 08:38:49 +00:00
2020-11-06 15:13:28 +00:00
def test_items(self) -> None:
"""
Tests some random stuff with items.
2020-11-06 15:13:28 +00:00
"""
item = Item()
2020-11-11 15:58:20 +00:00
self.map.add_entity(item)
2020-11-06 15:13:28 +00:00
self.assertFalse(item.held)
2020-11-11 15:58:20 +00:00
item.hold(self.player)
2020-11-06 15:13:28 +00:00
self.assertTrue(item.held)
2020-12-04 16:15:41 +00:00
item.drop()
self.assertEqual(item.y, 1)
2020-11-11 15:58:20 +00:00
self.assertEqual(item.x, 6)
# Pick up item
2020-12-04 16:15:41 +00:00
self.player.move_left()
self.player.move_right()
2020-11-11 15:58:20 +00:00
self.assertTrue(item.held)
self.assertEqual(item.held_by, self.player)
self.assertIn(item, self.player.inventory)
self.assertNotIn(item, self.map.entities)
2020-11-06 15:13:28 +00:00
def test_bombs(self) -> None:
"""
Tests some random stuff with bombs.
2020-11-06 15:13:28 +00:00
"""
item = Bomb()
2020-11-10 20:47:36 +00:00
hedgehog = Hedgehog()
2020-11-19 00:11:11 +00:00
teddy_bear = TeddyBear()
2020-11-06 16:59:19 +00:00
self.map.add_entity(item)
2020-11-10 20:47:36 +00:00
self.map.add_entity(hedgehog)
2020-11-19 00:11:11 +00:00
self.map.add_entity(teddy_bear)
2020-11-10 20:47:36 +00:00
hedgehog.health = 2
2020-11-19 00:11:11 +00:00
teddy_bear.health = 2
2020-11-10 20:47:36 +00:00
hedgehog.move(41, 42)
2020-11-19 00:11:11 +00:00
teddy_bear.move(42, 41)
2020-11-06 15:13:28 +00:00
item.act(self.map)
2020-11-10 20:47:36 +00:00
self.assertFalse(hedgehog.dead)
2020-11-19 00:11:11 +00:00
self.assertFalse(teddy_bear.dead)
2020-12-04 16:15:41 +00:00
self.player.move(42, 42)
item.hold(self.player)
item.use()
2020-11-06 15:13:28 +00:00
self.assertEqual(item.y, 42)
self.assertEqual(item.x, 42)
2020-12-04 16:15:41 +00:00
# Wait for the explosion
for _ignored in range(5):
2020-12-04 16:15:41 +00:00
item.act(self.map)
2020-11-10 20:47:36 +00:00
self.assertTrue(hedgehog.dead)
2020-11-19 00:11:11 +00:00
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)
2020-11-06 15:13:28 +00:00
2020-11-11 16:15:28 +00:00
def test_hearts(self) -> None:
"""
Tests some random stuff with hearts.
2020-11-11 16:15:28 +00:00
"""
item = Heart()
self.map.add_entity(item)
item.move(2, 6)
self.player.health -= 2 * item.healing
self.player.move_down()
self.assertNotIn(item, self.map.entities)
self.assertEqual(self.player.health,
self.player.maxhealth - item.healing)
2020-11-19 00:11:11 +00:00
heart_state = item.save_state()
self.assertEqual(heart_state["healing"], item.healing)
2020-11-11 16:15:28 +00:00
2020-12-05 13:39:33 +00:00
def test_body_snatch_potion(self) -> None:
"""
Tests some random stuff with body snatch potions.
2020-12-05 13:39:33 +00:00
"""
item = BodySnatchPotion()
self.map.add_entity(item)
item.hold(self.player)
tiger = Tiger(y=42, x=42)
self.map.add_entity(tiger)
# The player becomes a tiger, and the tiger becomes a squirrel
item.use()
self.assertEqual(self.player.name, "tiger")
self.assertEqual(tiger.name, "player")
self.assertEqual(self.player.y, 42)
self.assertEqual(self.player.x, 42)
2020-11-06 15:13:28 +00:00
def test_players(self) -> None:
"""
Tests some random stuff with players.
2020-11-06 15:13:28 +00:00
"""
player = Player()
2020-11-06 17:03:30 +00:00
self.map.add_entity(player)
player.move(1, 6)
2020-11-06 15:13:28 +00:00
self.assertEqual(player.strength, 5)
self.assertEqual(player.health, player.maxhealth)
self.assertEqual(player.maxhealth, 20)
2020-11-06 17:03:30 +00:00
# Test movements and ensure that collisions are working
self.assertFalse(player.move_up())
self.assertTrue(player.move_left())
self.assertFalse(player.move_left())
for _ in range(8):
2020-11-06 17:03:30 +00:00
self.assertTrue(player.move_down())
self.assertFalse(player.move_down())
self.assertTrue(player.move_right())
self.assertTrue(player.move_right())
self.assertTrue(player.move_right())
self.assertFalse(player.move_right())
self.assertTrue(player.move_down())
self.assertTrue(player.move_down())
2020-11-06 20:23:17 +00:00
player.add_xp(70)
self.assertEqual(player.current_xp, 10)
self.assertEqual(player.max_xp, 40)
self.assertEqual(player.level, 4)
2020-11-19 00:11:11 +00:00
player_state = player.save_state()
self.assertEqual(player_state["current_xp"], 10)
2021-01-08 14:58:54 +00:00
player = Player()
player.map = self.map
player.add_xp(700)
for _ in range(13):
player.level_up()
self.assertEqual(player.level, 12)
self.assertEqual(player.critical, 5 + 95 // 30)
self.assertEqual(player.charisma, 3)
2021-01-08 14:58:54 +00:00
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)