lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


no.. not pre-emptive.  I've simply hidden the "yield" commands in those wait
and play functions in my example.  The script writer is controlling the time
flow of the program.  In my implementation the yield commands simply return
job control information to my job-despatcher. (information like set this
coroutine to sleep until Signal X occurs etc)

The problem with your functional implementation is that its a right pain in
the bum to *see* what the buggery its up to, never mind *edit the time flow
of the script*.  This is my problem with purely functional languages that
are trying to be script languages, they tend to forget that they are
*script* languages. :-)

I need to change states and conditions and the *flow* of my alien monster's
program on a whim, by just shuffling some code about here and there.  I
can't (read: don't have the time to) sit down and re-work out the functional
implementation when the game designer/planner comes to me and says he wants
the alien to pick its nose before attacking (if its itchy), oh and then once
in 5 times make him trip over first.

All that said, I can put up with the syntax if it works but I'm not sure if
your example will work - jump_to_state changes "state" and then when the
resume function is called isn't the PC for the coroutine in the function
that state was originally referring to?   If not is there some kind of
implicit reset of the program counter to zero?


----- Original Message ----- 
From: "Nick Trout" <nick@rockstarvancouver.com>
Newsgroups: gmane.comp.lang.lua.general
Sent: Tuesday, June 24, 2003 12:15 PM
Subject: RE: Re[2]: why no "continue" statement for loops?


>
> Also, on a completely different note; whilst I would *never ever* use
> gotos
> in C++ or even C for that matter, there is an argument for having them
in
> a
> *multi-threaded* scripting language. (note the emphasis on
multi-threaded)

Shouldn't the emphasis be on "pre-emptive multi-threaded" scripting
language? Lua is cooperative hence you have to think about control flow
and suspend/yield points. You don't have to think about this in
pre-emptive environments. Gotos are nice where you are constantly
changing state and would otherwise meet a stack overflow by calling
functions - the lazy mans function call ;-)


> With multi-threaded scripting languages, especially those for games,
it is
> necessary to implement state machines, or more simply put, areas of
code
> you
> can *jump* to, to get a character to go into a particular state.
>
> I understand why lua doesn't have this right now, the "co-routines"
are a
> far call from multi-threading and require the user to write a whole
> multi-threading kernel in order to use them.  However, once this is
> written
> you begin wanting to write code like this:  (believe me, you really
*do*)
> (pseudo code)
>
> Thread AlienMonster
> init:
>     initialise_state()        // initialise function for this monster
>
> check:
>     nearest_player = check_for_nearest_player();
>     if ( nearest_player )
>     {
>         jump_to_state( attack );
>     }
>
> idle:
>     play( "scratch_arse" );        // animation (takes time to
complete)
>     wait( 5 )
>     play( "look_around_aimlessly" );
>     jump_to_state( check );
>
> attack:
>     play( "monster_roar" );
>     while ( nearest_player == check_for_nearest_player() )
>     {
>         if ( turn_to_player() )        // facing player?
>         {
>             play( "chase_1_step" );        // step towards the player
> (takes
> time for animation to complete)
>         }
>         wait( 1 )     // wait 1 frame (or nth of a second)
>     }
>     jump_to_state( check );
> EndThread


You could possibly do this in Lua with the following completely seat of
the pants untested code:


-- Thread AlienMonster

function init()
    initialise_state()        // initialise function for this monster
    jump_to_state(check)
end

function check()
    nearest_player = check_for_nearest_player()
    if nearest_player then
        jump_to_state( attack )
    else
        jump_to_state(idle)
    end
end

function idle()
     play( "scratch_arse" );        // animation (takes time to
complete)
     wait( 5 )
     play( "look_around_aimlessly" );
     jump_to_state( check );
end

function attack()
     play( "monster_roar" );
     while ( nearest_player == check_for_nearest_player() )
     {
         if ( turn_to_player() )        // facing player?
         {
             play( "chase_1_step" );        // step towards the player
 (takes
 time for animation to complete)
         }
         wait( 1 )     // wait 1 frame (or nth of a second)
     }
     jump_to_state( check );
end

-- EndThread

state = init

function wait(t)
    while timer < t do
        coroutine.yield()
    end
end

function jump_to_state(newtstate)
    state = newstate
    coroutine.yield()
end

co = coroutine.create(function() state() end)
while couroutine.resume(co) do
end



> Of course I can make "attack", "idle" and "check" functions and then
have
> some kind of table which is run through in order, but then there are
no
> *conditions*, and quite frankly, setting up the table is just as much
a
> pain
> in the arse as writing the above using while/dos and lots of local
"state"
> variables, which is definitely *not* the way to write that kind of
code.
> Importantly, the above is *simple to understand*.

You can do some nice things with first class objects in Lua.



Nick