Internally, there is reference to the top-level action list, "main" or "advanced" or w/e, that is used to find which action list should be executed when an input is requested.
swap_action_list,name=xyz aborts the existing action list execution, changes the reference of the top-level action list to "xyz", and then restarts the action list execution. Transitioning between action lists can be used to encode stateful information.
run_action_list,name=xyz is roughly equivalent to copying the actions from list "xyz" and injecting them at this location (it works just like a subroutine.) Note: any conditionals on this action will propagate to all of these referenced actions.
Code: Select all
main+=/action1,if=abc main+=/run_action_list,name=test,if=abc
main+=/action2,if=abc == test+=/action1
test+=/action2
So yes, run_action_list always returns to the calling list unless an action was taken or the top-level action list was changed.
Code: Select all
// list of action lists
lists = {
"main" = {action1, action2, run_action_list("foo"), action3, swap_action_list("foo")}
"foo" = {action4, action5}
}
current = "main" // reference to current action list
// basic combat loop
while (...) {
...
// try to find an action to execute
run_current_action_list_once();
...
}
Action List Functions:
Code: Select all
// execute the action list referenced by "current"
// (exceptions are used as multi-level goto)
// if a Restart exception is thrown, try the action list again
// if a Clicked exception is thrown, an action was taken, return true
// if run_action_list() completes normally, there is nothing to do, return false
boolean run_current_action_list_once() {
while (true) {
try {
run_action_list(current);
return false; // no actions taken
} catch (Clicked ex) {
return true; // action was clicked
} catch (Restart ex) {
// retry the action list
}
}
}
// execute the action list referenced by name
void run_action_list(name) {
for (lists[name] as action) {
action();
}
}
// change the current action list and restart
void swap_action_list(name) {
current = name;
throw new Restart();
}
// generic implementation for action1
void action1() {
if (energy > 50 and ...) {
MANGLE.click(); // throws Clicked() exception on success
}
}
Example:
Code: Select all
current = "main"
run_current_action_list_once()
run_action_list("main") => {action1, action2, run_action_list("foo"), action3, swap_action_list("foo")}
action1()
action2()
run_action_list("foo") => {action4, action5}
action4()
action5()
// end of "foo" action list
action3()
swap_action_list("bar")
current = "bar"
throw to Restart
// according to run_current_action_list_once(), Restart => we try again
// however the current action list has changed
run_action_list("bar")
action4()
action5()
// end
HotW casting in Catus is implemented using a lot of action list runs and swaps:
https://dl.dropboxusercontent.com/u/298 ... Cleave.txt