Algorithms
Overview
Here are described the algorithms of enemy action execution process and simple action execution process.
The General Algo
Acting
that use this algo are assumed to also be decorated with theSequential
decorator
Overview:
The assumption is made that before this next step the
entity.nextAction
field has been set. This generally happens right beforeexecuteAction()
, in the functioncalculateAction()
, called by theWorld
on theEntity
.The
World
loops 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 themovs
themselves are acquired by callingentity.sequence:getMovs()
.An
action
with that mov'sdirection
set on it, walks this action'schain
, which has the corresponding handlers. For example, with anAttackMoveAction
as 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 currentmov
will fail.If all the
movs
have failed, thefailAction
chain is traversed on the actor entity.
The Simple Algo
There is an assumption about the action that this algorithm makes. It's that the
direction
field (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
World
callsexecuteAction
on player, causing it to loop through the chain of thenextAction
, trying the action components one after the other.If the action fails, the
failAction
chain 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')
-- ...