> On Thu, Jun 10, 2010 at 7:50 AM, James Paige <[email protected]> wrote:
>> I have noticed that sometimes new users misunderstand how the "if"
>> command works. I see someone write code like:
>>
>>  if(condition) then(action)
>>
>> but this code only runs once in their "new game" script, and they wonder
>> why "action" fails to happen each and every time that "condition" comes
>> true
>>
>> This wouldn't work until script multitasking was supported, but what if
>> there was a flow control command like:
>>
>>  script, my script, begin
>>    whenever(condition) do(action)
>>  end
>>
>> This would be shorthand for writing:
>>
>>  script, my script, begin
>>    whenever loop
>>  end
>>
>>  script, whenever loop, begin
>>    while(true) do(
>>      if(condition) then(action)
>>      wait(1)
>>    )
>>  end

I assume that you meant (using the currently proposed script
multitasking constructs):

script, my script, begin
  new script (whenever loop)
end

(I think that "fork script" might be better than "new script")

>> Does that seem like a thing that would be worth having? It seems pretty
>> cool to me... but I can't think of any other language* with a similar
>> flow control structure, which makes me wonder if it has already been
>> tried and declared harmful by older wiser minds.

I don't think it's crazy. But what concerns me is forking a script
that runs forever - this can explode very easily. I also think it
would lower the usefulness of whenever, because I think most such
conditions will have exceptions. How about tying whenever to its
parent script chain in some way? One possibility would be that if the
script from which it was called exits, and whatever called that exits,
etc, all the way back to the original plotscript/fork, then the
whenever stops. For example, if you write a script
MyAwesomeBattleSystem which runs a script SetupEffects which contains
a bunch of whenevers which do various things, you'd probably want all
those whenevers to stop functioning when the battle ends. However,
MyAwesomeBattleSystem isn't necessarily a plotscript, it might be
called from some main loop. Hmm. Maybe we could add a "stop all child
whenevers" command. Or kill whenevers whenever their parent script
exits. Or maybe this is getting too complicated.

Food for thought:

In a large script which does something in the background like walk
NPCs about a map you want to exit the script as soon as the map is
left. Unfortunately doing this rigorously requires checking whether
the map has changed after every wait statement*.  Otherwise the script
will either throw an error or start moving NPCs on the new map (a
common bug in Powerstick Man XE). My solution is (I'm planning on
adding this script to plotscr.hsd):

script, exit script on map change, begin
  new script, begin
    variable (this map)
    this map := current map
    while (this map == current map) do (
      wait
      if (parent script == 0) then (exit script)  # stop if the parent exits
    )
    kill script (parent script)
  end
end

plotscript, rascal chasing a duck, begin
  exit script on map change
  # chase a duck ...
end

(Here parentscript is NOT the function described on the wiki, and
means "parent script", not "parent script thread")

Adding whenever might make it simple to express such exit conditions:

plotscript, rascal chasing a duck, begin
  variable (this map)
  this map := current map
  whenever (this map <> current map) do (kill script (this script))
  ...
end

(Not sure about how killscript and whenever would interact)

>> (* actually, I can think of one language that has something like this.
>> The machine language for the ancient Daytronics System-10 mainframe has
>> the EXU command which executes code any time a logic bit changes state.
>> This is also the one and ONLY flow control of any kind that the language
>> supports. All other flow control patterns have to be painstakingly
>> cobbled together with a series of EXU commands and bit flips)

Now there's a crazy idea!

>> ---
>> James

* Actually, now that I think about it, waitfornpc probably breaks when
the leave the map! But wait. The obvious solution is the have any
waits immediately broken when the map changes, but what if script
multitasking is implemented, and the map is set to save NPC state? If
an NPC is in the middle of a scripted movement when you leave the map,
maybe you DO want the script to pause and wait for the map to be
reentered? Maybe it would be reasonable to make this behaviour the
default if script multitasking and NPC state saving are both enabled.
Thoughts?


Eeek! Top-posting!

On 10 June 2010 16:48, Seth Hetu <[email protected]> wrote:
> Lua scripters always tell me that this is easy as pie in Lua, though I
> don't know first-hand.
>
> They also tell me that this leads to a problematic chain of functionality:
>
> //Trigger whenever a player's HP is below 10
> when (player.hp < 10)
>   (flash screen)
> end
>
> Which leads to:
>
> //Simplified form of "get a user who's nearby"
> when (user1.x-user2.x < 5)
>    (do something)
> end
>
> By itself, this is no problem. But then consider the user wants to
> trigger "whenever two users are nearby". They could put the previous
> fragment inside two loops:
>
> //Check if ANY users are nearby
> for user1 in all_users:
>  for user2 in all_users:
>      when (user1.x-user2.x < 5  and user1!=user2)
>        (do something)
>      end
>  end
> end
>
> This will create a LOT of whenever loops to keep track of.
> Alternatively, you could support some kind of "pick any user" flag
> inside whenever loops. This would also consume resources (though it
> might be manageable.)

Such a flag would be totally impractical to implement.

To me, the interesting assumption you've made in your example is that
user1 and user2 have been copied, rather than referring to the user1
and user2 variables in the parent function. I am planning on exposing
the original variables in embedded scripts. But maybe this is a case
for not doing that? And I don't like the idea of treating variables in
whenever and in newscript differently. Also at issue is making local
and global variables behave differently.


The best way to write that using the proposed multitasking constructs
looks like it'll be:

script, foo, begin
  ...
  new script, begin
    for each (user1, all_users) do, begin
      for each (user2, all_users) do, begin
        if (user1.x-user2.x < 5  and user1!=user2) then (new script
(do something))
      end
    end
  end
  ...
end

Also, hopefully script thread switching will be implemented really
efficiently, so having hundreds of whenever's running won't be too
worrisome.

> I'm not saying this is a bad idea; I can see its appeal. Just giving
> some thoughts on what users will expect once they understand
> "whenever" triggers.
>
> -->Seth
_______________________________________________
Ohrrpgce mailing list
[email protected]
http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org

Reply via email to