'change' command explained


#1

Continuing the discussion from:

[change is is a obscure command that may not need to be used in most code. It was updated on GitHub and Perforce source from version 3.0.4304 and up. Revised by @Noolarch 2017-03-11]

When a coroutine or method is called on a mind (an object that is of the Mind class) it is updated and tracked by that mind. Easy enough.

When a coroutine is called on an object other than a mind such as an Actor, Integer or BadGuy, by default it inherits the same mind object that tracks and updates the calling scope. So if there was a MyMission mind object that called _do_stuff the invoked object that stores info about running _do_stuff would be tracked and stored in the MyMission instance. And if _do_stuff calls bad_guy._do_bad_stuff it will inherit the same MyMission mind for its updating. This helps group all the ongoing concurrent commands that originated from MyMission. If the MyMission object is destructed/completes then all the coroutines that it was updating will be stopped and cleaned up with it.

// in MyMind._do_stuff() coroutine
// The following coroutine is updated by the MyMind object until complete
bad_guy._do_bad_stuff
// If the MyMind object is destructed then _do_stuff is aborted if it isn't yet complete

Changing your mind

Most of the time you just call your routines and they pick an appropriate updater mind and you never need to worry about it. It just works.

As in life though, sometimes you want to change your mind.

The change command allows you to specify the mind to be used as an updater for an expression.

See the change syntax here.

// in MyMind._do_stuff() coroutine
// The following coroutine is updated by the OtherMind object until complete
change OtherMind.instance bad_guy._do_bad_stuff
// If the OtherMind object is destructed then _do_stuff continues unaffected until it completes

There is always a global/default mind derived from the Master class that is called the master mind and it is always easily accessible via Master.instance. You can use it in a change command too.

// in MyMind._do_stuff() coroutine
// The following coroutine is updated by the master mind until complete
change Master.instance bad_guy._do_bad_stuff

Other notes and tips

  • You can call any expression with a change command including a code block.
  • The rule that calls on a mind object are updated on that mind holds true even if it is nested in a change command.
  • You can use this_mind to return the mind being used by the current routine.
// in MyMind._do_stuff() coroutine
// The following coroutine inherits the MyMind object as updater
bad_guy._do_bad_stuff
// The following coroutine inherits the MyMind object as updater
@test?._wait_false
// Prints out "Current mind: MyMind"
println("Current mind: " this_mind)

change ThatMind.instance
  [
  // Prints out "Current mind: ThatMind"
  println("Current mind: " this_mind)
  // The following coroutine is updated by the ThatMind object
  bad_guy._do_bad_stuff
  // The following coroutine is updated by the ThatMind object
  @success?._wait_true
  // The following coroutine is updated by mission_mind
  mission_mind._do_mission_stuff
  // Inferred this is MyMind so the following coroutine is updated by the MyMind object
  _do_stuff2
  ]

// The following coroutine inherits the MyMind object as updater
@test2?._wait_true
// Prints out "Current mind: MyMind"
println("Current mind: " this_mind)

Please see this post for more info on minds:


What is branch and change and what's the difference between these two?
Concurrency in SK | Single Threaded
Assigning a coroutine to a Mind
Great curated posts to learn about SkookumScript
#2

So change means divert/change to some mind, that make sense. Thanks!

One more question, in

// in MyMind coroutine
change other_mind obj._do_stuff // Gets updates in other_mind until complete

Can a coroutine access the mind it currently running on? e.g. can _do_stuff reference other_mind in it’s method body?


#5

Yes.

You just use this_mind.

It is similar to this, this_class and this_code.

If you have an InvokedBase object such as an InvokedCoroutine returned from a branch or this_code you can also call .mind() on it. For example, this_code.mind or coro_behavior.mind. Though using this should be rare.