Algorithms
Overview
Here are described the algorithms of enemy action execution process and simple action execution process.
The General Algo
Actingthat use this algo are assumed to also be decorated with theSequentialdecorator
Overview:
The assumption is made that before this next step the
entity.nextActionfield has been set. This generally happens right beforeexecuteAction(), in the functioncalculateAction(), called by theWorldon theEntity.The
Worldloops through all non-player reals and calls theirexecuteAction().Each real generates a list of possible
movs, which are just directions they would like to do stuff into. The function that does this is set individually for every step sequence but themovsthemselves are acquired by callingentity.sequence:getMovs().An
actionwith that mov'sdirectionset on it, walks this action'schain, which has the corresponding handlers. For example, with anAttackMoveActionas the action, the entity is going to try attacking and then, if it fails, moving.This is the most important difference between this algorithm and the player algorithm: if another real is blocking their way of e.g. moving / attacking, they will pass them the turn. They will call
executeAction()on that real. If it has already executed their action, though, the currentmovwill fail.If all the
movshave failed, thefailActionchain is traversed on the actor entity.
The Simple Algo
There is an assumption about the action that this algorithm makes. It's that the
directionfield (if needed) is already set on the action beforeexecuteAction()is called. This is in contrast with theGeneralAlgo, where the direction for the action is chosen insideexecuteAction(). In case of player, the next action and the direction are set before the new iteration of the game loop, since the players don't have theircomputeAction()being called.The
WorldcallsexecuteActionon player, causing it to loop through the chain of thenextAction, trying the action components one after the other.If the action fails, the
failActionchain is traversed.
Is the Simple Algo just for the player?
Note that the Simple Algo is useful not just for the player, but can be used for other things too. In fact, the general algo applies pretty much to just enemies, while the player algo is used for traps, special tiles, etc. This is because their actions are pretty homogenous, that is, they do the same thing every beat. For example, bounce traps test if there is something on top of them to do the action of bouncing on that something in the direction that trey're looking; the special tiles see if there is something on top of them and do e.g. submerging on that something. This lets us return the action (+, optionally, direction) directly in the overriden calculateAction method, which also simplifies the algorithm quite a bit.
Here's an excerpt from the code for traps as an example usage of the player algo not for the player. Note that the code for the decorator has not been included.
-- ...
-- Class definition
local Trap = class('Trap', Entity)
Trap.layer = Layers.trap
Trap.state = State.UNPRESSED
Decorators.Start(Trap)
decorate(Trap, Decorators.WithHP)
decorate(Trap, Decorators.Ticking)
decorate(Trap, Decorators.Attackable)
decorate(Trap, Decorators.Acting)
decorate(Trap, Decorators.DynamicStats)
-- use the player algo
Retouchers.Algos.simple(Trap)
Retouchers.Attackableness.no(Trap)
-- ...
decorate(BounceTrap, Bouncing)
TrapRetouchers.bePushedOnBounce(BounceTrap)
TrapRetouchers.tickUnpress(BounceTrap)
utils.redirectActionToDecorator(BounceTrap, 'Bouncing')
-- ...