Context: I'm making a little "program your robot army" sort of game in Java in which the player writes Lua scripts (which are then run by LuaJ) to program their robots to do stuff. So far there are two objectives:
- Keep It Simple, Stupid, and
- React to the environment.
To take a simple example of what I currently have, the player should be able to tell their robot to go to a particular location with something like
robot:goTo(5, 8)
Like Colobot, the scripting engine effectively halts (blocks) at that instruction until the robot has reached its destination.
I like this -- it's meets the first requirement nicely, in that you can't do anything until goTo
decides to return. It's also simple on the Java side -- I can basically do while (/* condition */) yield()
and just resume the coroutine every tick (then maintaining state in local variables is trivial). But: what if that resource at (5,8) disappears, or an enemy comes near, or energy runs low? There's no opportunity to bail -- the robot has to reach (5,8) before it can do anything else.
The main other idea I can think of is to produce some sort of loop:
while not robot:near(5,8) do
if robot:enemyNearby() then
break -- and do some other stuff, presumably
else
robot:moveTo(5,8)
end
end
where moveTo
this time sets the velocity/acceleration and then immediately returns, without blocking until arrival.
I could have robot:goTo
return the actual coroutine (either wrapped, so you just call it, or directly, which requires calling coroutine.resume
and passing the coroutine), which might look something like this:
moveTask = robot:moveTo(5,8)
while not robot:near(5,8) do
if robot:enemyNearby() then
break
else
moveTask()
-- or perhaps coroutine.resume(moveTask)
-- or some other syntactic sugar
end
end
These last two approaches look pretty similar, but reusing a coroutine as in the second example makes managing state (e.g. a path) trivial, at the cost of exposing coroutines to the player.
To reiterate, the goal is to allow for writing simple scripts, in which a set of actions are executed in series (sorta like queued actions in The Sims), while simultaneously allowing more complex scripts with actions that may be interrupted by arbitrary events (nearby enemy, target moved, stats dropping).
Any tips or ideas would be much appreciated!