diff --git a/dungeonbattle/entities/monsters.py b/dungeonbattle/entities/monsters.py index f7dd413..67063da 100644 --- a/dungeonbattle/entities/monsters.py +++ b/dungeonbattle/entities/monsters.py @@ -1,5 +1,6 @@ from random import choice +from .player import Player from ..interfaces import FightingEntity, Map @@ -9,12 +10,32 @@ class Monster(FightingEntity): By default, a monster will move randomly where it is possible And if a player is close to the monster, the monster run on the player. """ - # TODO If a player is close, move to the player - for _ in range(100): - if choice([self.move_up, self.move_down, - self.move_left, self.move_right])(): + target = None + for entity in m.entities: + if self.distance_squared(entity) <= 25 and \ + isinstance(entity, Player): + target = entity break + if target: + # Move to target player + y, x = self.vector(target) + if abs(y) > abs(x): # Move vertically + if y > 0: + self.move_down() + else: + self.move_up() + else: # Move horizontally + if x > 0: + self.move_right() + else: + self.move_left() + else: + for _ in range(100): + if choice([self.move_up, self.move_down, + self.move_left, self.move_right])(): + break + class Hedgehog(Monster): name = "hedgehog" diff --git a/dungeonbattle/interfaces.py b/dungeonbattle/interfaces.py index 04ed8d1..5611795 100644 --- a/dungeonbattle/interfaces.py +++ b/dungeonbattle/interfaces.py @@ -1,7 +1,8 @@ #!/usr/bin/env python from enum import Enum, auto +from math import sqrt from random import randint -from typing import List +from typing import List, Tuple from dungeonbattle.display.texturepack import TexturePack @@ -172,6 +173,22 @@ class Entity: """ pass + def distance_squared(self, other: "Entity") -> int: + """ + Get the square of the distance to another entity. + Useful to check distances since square root takes time. + """ + return (self.y - other.y) ** 2 + (self.x - other.x) ** 2 + + def distance(self, other: "Entity") -> float: + """ + Get the cartesian distance to another entity. + """ + return sqrt(self.distance_squared(other)) + + def vector(self, other: "Entity") -> Tuple[int, int]: + return other.y - self.y, other.x - self.x + class FightingEntity(Entity): maxhealth: int diff --git a/dungeonbattle/tests/entities_test.py b/dungeonbattle/tests/entities_test.py index adca2ec..3d61812 100644 --- a/dungeonbattle/tests/entities_test.py +++ b/dungeonbattle/tests/entities_test.py @@ -23,6 +23,11 @@ class TestEntities(unittest.TestCase): self.assertEqual(entity.x, 64) self.assertIsNone(entity.act(self.map)) + other_entity = Entity() + other_entity.move(45, 68) + self.assertEqual(entity.distance_squared(other_entity), 25) + self.assertEqual(entity.distance(other_entity), 5) + def test_fighting_entities(self) -> None: """ Test some random stuff with fighting entities.