Monster Behaviors
v3 Tutorials
Goal
There is going to be a lot of code in this tutorial. We have to start using the scheduling system we built last time. We’ll also be laying the foundation for creating monster behaviors. Our first behavior will be a simple move and attack, but we can expand on this in the future to create lots of interesting monsters.
Defining a Behavior Interface
First we need to define the interface that all of our future Behaviors will use. Create a new file named IBehavior.cs in the Interfaces folder. Add the following code:
We’re going to keep it simple and just have a simple Act(…) method that will take the Monster performing the action and the CommandSystem as parameters.
Creating a Move and Attack Behavior
Our first concrete behavior that will implement our IBehavior interface will be StandardMoveAndAttack.
Briefly lets go over what the StandardMoveAndAttack behavior will do.
- A monster should perform a standard melee attack on the player if the player is adjacent to the monster.
- If the player is not within attack range, the monster should move closer to the player via the shortest available path.
- Only monsters that are aware of the player should chase him.
- Once the monster is alerted and begins the chase, if the player evades him and remains out of visual range for a period of time the monster should stop pursuit.
- If the monster can see the player but does not have a valid path (possibly because of being blocked by other monsters) it should wait a turn.
Because we want to have many additional behaviors in the future we should make a new folder named Behaviors and then create the file StandardMoveAndAttack.cs in that folder. Add the following code:
Be aware that if you try to Build right now there will be errors. We never added the TurnsAlerted property to our Monster class. Additionally we are missing the MoveMonster method on our CommandSystem.
Note: You may also notice the TODO comment. I discovered a bug in V3 RogueSharp and have a fix for it but for now this is a workaround.
Monster Class Updates
We should make sure we get back to a state where the project will build as quickly as possible. With that in mind open Monster.cs and add a new TurnsAlerted property as well as a PerformAction method that we’ll use later.
Did you notice the question mark on the int? property? That’s shorthand for a Nullable<int> type. Since integers are value types they cannot normally be null, however we want a null integer to represent that the monster has not been alerted.
Notice that the PerformAction method is virtual also. Since this is on our Monster base class, we’ll give any monster the StandardMoveAndAttack behavior by default. We can override this in any of our Monster sub-classes to get more interesting behaviors.
Actor Class Updates
At this point we’re still not building, but we are getting closer. Open Actor.cs and make sure that the Actor class implements IScheduleable so that we can add them to our scheduling system.
CommandSystem Class Updates
We should get our CommandSystem updated now so we can finally build again. Open CommandSystem.cs and add the IsPlayerTurn property as well as the ActivateMonsters() and MoveMonster(…) methods.
Update 1/31/2017 – Added the EndPlayerTurn() method which was accidentally omitted from the code below. Thank you to Zacharry Field for bringing this to my attention.
The ActivateMonsters() method is intended to be called after the Player takes a turn. This will proceed to get the next scheduled Actor from the SchedulingSystem. If this happens to be the Player again, we’ll wait for the Player to make a move. Otherwise we’ll have the Monster perform an action and then call ActivateMonsters() again recursively. This will keep having Monsters perform their actions until it is once again the Player’s turn.
Add Player and Monsters to Scheduling System
Open DungeonMap.cs and update the AddPlayer(…), AddMonster(…), and RemoveMonster(…) methods to use the SchedulingSystem. Just add the calls at the end of each method.
Updating the Game Class
We’re almost done. The rest of the updates will be in Game.cs so open up the file and add a new public property.
Make sure to instantiate a new SchedulingSystem in the Main() method.
The last set of updates will be made in the OnRootConsoleUpdate(…) method. We need to ensure that it is the player’s turn before handling key presses. We also need to activate monsters after the player has taken their turn.
Everything should build now and if you run the game you’ll see that monsters will now chase the player around and attack. The scheduling system that we implemented last time is all hooked up now too.
Final Thoughts
This was a long post with a lot of code but it should pave the way for adding more monsters and more interesting behaviors in the future.
As always the code for the tutorial series so far can be found on Bitbucket:
https://bitbucket.org/FaronBracy/roguesharpv3tutorial/commits/tag/14MonsterBehaviors
Bored waiting for the next tutorial post? The completed project is already available on Bitbucket.