peoro / ngu.js

1 stars 2 forks source link

Redesign the interface for complex, high-level tasks #3

Open peoro opened 4 years ago

peoro commented 4 years ago

High-level tasks are tasks that NGU.js should automatize by taking complete control of the game for an extended period of time. The user must be able to interrupt the long running task at any point.

In order to express non-trivial behaviors, it would be really useful to combine simpler tasks together.

The LoopRunner structure we're currently using is way too limited. It can only run one task (loop) at a time and uses exceptions to control the flow.
Running a sub-task within a loop is a dirty hack, tough to write and to understand.

Let's try to find out and implement a nicer design.

peoro commented 4 years ago

Something I was thinking about using is Behavior Trees.

I wasn't quite convinced by any BT module I saw on NPM though.

peoro commented 4 years ago

Using a Behavior Tree, the behavior discussed in #6 could be modeled with something like:

IdleITOPOD = Sequence([
    SwitchLoadout( 2 ),
    SetDiggers( [engu, mngu, ebeard, mbeard, ...] ),
    GoToAdv( ITOPOD ),
    For( Infinity, Sequence([
        For( 50, KillEnemy() ),
        FixInventory()
    ]) )
])

KillTitan = Sequence([
    SwitchLoadout( 1 ),
    SetDiggers( [gold, adv, ...] ),
    While( TitanDead(), WaitFrame() ),
    While( Not( TitanDead() ), WaitFrame() )
])

Idle = Priority([
    {when: And( EMCapped(), EMUnused() ), do: AssignEM() },
    IdleITOPOD()
])

MainLoop = Priority([
    { when:TitanAlmostAlive(), do:KillTitan() },
    Idle()
])

Priority nodes would keep checking for their conditions to become true.

Without OCR we can't implement EMCapped, EMUnused, TitanAlmostAlive, TitanDead correctly yet, but we can achieve that behavior using timers or other tricks.