LambdaHack- A game engine library for tactical squad ASCII roguelike dungeon crawlers

Safe HaskellNone



Breadth first search and related algorithms using the client monad.



getCacheBfsAndPath :: forall m. MonadClient m => ActorId -> Point -> m (Array BfsDistance, Maybe AndPath) Source #

Get cached BFS array and path or, if not stored, generate and store first.

getCacheBfs :: MonadClient m => ActorId -> m (Array BfsDistance) Source #

Get cached BFS array or, if not stored, generate and store first.

getCachePath :: MonadClient m => ActorId -> Point -> m (Maybe AndPath) Source #

Get cached BFS path or, if not stored, generate and store first.

furthestKnown :: MonadClient m => ActorId -> m Point Source #

Furthest (wrt paths) known position.

closestUnknown :: MonadClient m => ActorId -> m (Maybe Point) Source #

Closest reachable unknown tile position, if any.

Note: some of these tiles are behind suspect tiles and they are chosen in preference to more distant directly accessible unknown tiles. This is in principle OK, but in dungeons with few hidden doors AI is at a disadvantage (and with many hidden doors, it fares as well as a human that deduced the dungeon properties). Changing Bfs to accomodate all dungeon styles would be complex and would slow down the engine.

If the level has inaccessible open areas (at least from the stairs AI used) the level will be nevertheless here finally marked explored, to enable transition to other levels. We should generally avoid such levels, because digging and/or trying to find other stairs leading to disconnected areas is not KISS so we don't do this in AI, so AI is at a disadvantage.

If the closest unknown is more than 126 tiles away from the targetting actor, the level will marked as explored. We could complicate the code and not mark if the unknown is too far as opposed to inaccessible, but then if it is both too distant and inaccessible, AI would be permanently stuck on such levels. To cope with this, escapes need to be placed on open or small levels, or in dispersed enough that they don't appear in such potentially unexplored potions of caves. Other than that, this is rather harmless and hard to exploit, so let it be. The principled way to fix this would be to extend BFS to Word16, but then it takes too long to compute on maze levels, so we'd need to optimize hard for JS.

closestSmell :: MonadClient m => ActorId -> m [(Int, (Point, Time))] Source #

Finds smells closest to the actor, except under the actor, because actors consume smell only moving over them, not standing. Of the closest, prefers the newest smell.

closestTriggers :: MonadClient m => FleeViaStairsOrEscape -> ActorId -> m [(Int, (Point, (Point, ItemBag)))] Source #

Closest (wrt paths) AI-triggerable tiles with embedded items. In AI, the level the actor is on is either explored or the actor already has a weapon equipped, so no need to explore further, he tries to find enemies on other levels, but before that, he triggers other tiles in hope of some loot or beneficial effect to enter next level with.

condEnoughGearM :: MonadClientRead m => ActorId -> m Bool Source #

Check whether the actor has enough gear to go look for enemies. We assume weapons in equipment are better than any among organs or at least provide some essential diversity. Disabled if, due to tactic, actors follow leader and so would repeatedly move towards and away form stairs at leader change, depending on current leader's gear. Number of items of a single kind is ignored, because variety is needed.

closestItems :: MonadClient m => ActorId -> m [(Int, (Point, ItemBag))] Source #

Closest (wrt paths) items.

closestFoes :: MonadClient m => [(ActorId, Actor)] -> ActorId -> m [(Int, (ActorId, Actor))] Source #

Closest (wrt paths) enemy actors.