AI routines for enemies in Herculeum are nothing fancy, mostly just random movement until the player happens to wander too close. The plan is to have each monster to behave in a semi-predictable, distinct way (think monster in Super Mario Bros.). First guinea pig for AI experimentation will be rat. The plan is to make them search for closest wall and then walk alongside the wall, randomly turning back when they arrive a corner. If player happens to come too close, the rat will attack. I have not yet decided how will they react on ranged attacks, but probably they are going to flee.
To make things more interesting, I’m going to write AI routines using Hy.
As always, I started with little bit doodling and then writing couple of tests:
(import [pyherc.test.builders [LevelBuilder CharacterBuilder]] [pyherc.ai.rat [next-to-wall?]] [hamcrest [assert-that is- is-not :as is-not- none has-items]]) (defn test-empty-space-is-detected [] "test that an empty space is not reported as wall" (let [[character (-> (CharacterBuilder) (.build))] [level (-> (LevelBuilder) (.with-floor-tile :floor) (.with-wall-tile :empty-wall) (.with-empty-wall-tile :empty-wall) (.with-solid-wall-tile :solid-wall) (.with-character character (, 5 9)) (.build))] [wall-info (next-to-wall? character)]] (assert-that wall-info (is- (none))))) (defn test-wall-is-detected [] "test that a wall can be detected next to a given point" (let [[character (-> (CharacterBuilder) (.build))] [level (-> (LevelBuilder) (.with-floor-tile :floor) (.with-wall-tile :empty-wall) (.with-empty-wall-tile :empty-wall) (.with-solid-wall-tile :solid-wall) (.with-wall-at (, 4 10)) (.with-wall-at (, 5 10)) (.with-wall-at (, 6 10)) (.with-character character (, 5 9)) (.build))] [wall-info (next-to-wall? character)]] (assert-that wall-info (is-not- (none))) (let [[wall-direction (get wall-info :wall-direction)]] (assert-that wall-direction has-items [:east :west]))))
The threading macro (->) makes it breeze to use all those builders that I have coded in Python. Without it I would have to write very deeply nested function calls. I’m also very happy about how clean and readable Hamcrest verifications are. It’s really hard to get closer to natural language in a standard programming language.