@@ -112,4 +112,83 @@ def perform(self) -> None:
112112
113113 # The actor will either try to move or attack in the chosen random direction.
114114 # Its possible the actor will just bump into the wall, wasting a turn.
115- return BumpAction (self .entity , direction_x , direction_y ,).perform ()
115+ return BumpAction (self .entity , direction_x , direction_y ,).perform ()
116+
117+
118+ class SpawnerEnemy (BaseAI ):
119+ """
120+ A spawner enemy will spawn a new enemy (of the selected type) in a random location around it self. while trying to get distanced from the player.
121+ """
122+
123+ def __init__ (
124+ self , entity : Actor
125+ ):
126+ super ().__init__ (entity )
127+
128+ self .is_setup = False
129+
130+ def setup (self ,spawned_entity : Actor , spawn_rate : int ):
131+ self .spawned_entity = spawned_entity
132+ self .spawn_rate = spawn_rate
133+ self .spawn_timer = 0
134+ self .is_setup = True
135+
136+ def perform (self ) -> None :
137+ # Do not perform if this AI is not setup or the spawner is not visible.
138+ if not self .is_setup or not self .engine .game_map .visible [self .entity .x , self .entity .y ]:
139+ return WaitAction (self .entity ).perform ()
140+
141+
142+
143+ # If the spawn timer is greater than the spawn rate, spawn a new enemy.
144+ if self .spawn_timer >= self .spawn_rate :
145+ # Reset the spawn timer.
146+ self .spawn_timer = 0
147+
148+ # Get a random location near the spawner.
149+ x = self .entity .x + random .randint (- 3 , 3 )
150+ y = self .entity .y + random .randint (- 3 , 3 )
151+
152+ tries = 0
153+ while not self .engine .game_map .in_bounds (x , y ) or not self .engine .game_map .get_blocking_entity_at_location (x , y ):
154+ x = self .entity .x + random .randint (- 3 , 3 )
155+ y = self .entity .y + random .randint (- 3 , 3 )
156+ tries += 1
157+ if tries > 10 :
158+ return WaitAction (self .entity ).perform () # If the spawner is not able to find a valid location, it will wait.
159+
160+ # Spawn the new enemy.
161+ self .spawned_entity .spawn (self .engine .game_map , x , y )
162+ # Add a message to the message log.
163+ self .engine .message_log .add_message (
164+ f"The { self .entity .name } spawned a new { self .spawned_entity .name } !"
165+ )
166+
167+ # Get the distance between the player and the spawner.
168+ distance = self .entity .distance (self .engine .player .x , self .engine .player .y )
169+
170+ # If the distance is less than 5, move away from the player.
171+ if distance < 5 :
172+ # Get the direction to the player.
173+ direction_x = self .engine .player .x - self .entity .x
174+ direction_y = self .engine .player .y - self .entity .y
175+
176+ # Normalize the direction.
177+ direction_x = max (min (direction_x , 1 ), - 1 )
178+ direction_y = max (min (direction_y , 1 ), - 1 )
179+
180+ # Round the direction.
181+ direction_x = - round (direction_x )
182+ direction_y = - round (direction_y )
183+
184+ # Move the spawner in the direction of the player.
185+ return MovementAction (
186+ self .entity , direction_x , direction_y ,
187+ ).perform ()
188+
189+
190+ # Add 1 to the spawn timer.
191+ self .spawn_timer += 1
192+
193+ # Return a wait action.
194+ return WaitAction (self .entity ).perform ()
0 commit comments