Principles of Kodu Computation

David S. Touretzky, Carnegie Mellon University


  1. Predicates bind to the closest matching object.

    "WHEN see apple DO boom it" will first blow up the apple closest to the character and then work its way outward. (Unlike "eat" or "launch", the "boom" action has an unlimited range.)

  2. Filters applied to a predicate are intersected to restrict the match.

    • "WHEN see" matches any object except the character itself.
    • "WHEN see apple" matches the nearest apple.
    • "WHEN see red" matches the nearest red thing.
    • "WHEN see red apple" matches the nearest red apple.
    • "WHEN see red apple LOS" matches the nearest red apple in the character's line of sight.

  3. Characters don't see themselves.

    Characters won't pick themselves as a match for a predicate unless a "me" modifier is used. In that case they can only match themselves. Examples:

    • "WHEN see red DO color it blue" will sequentially match all the red things (except perhaps for the character itself) and turn them blue.

    • "WHEN see me red DO color it blue" will turn the character itself blue if it is presently red.

  4. "Not" applies to the predicate, not the filters..

    The conditions "WHEN see not red" and "WHEN see red not" have the same meaning. They both mean "see nothing that is red". They do not mean "see something that is not red". At present there is no way to express the latter in Kodu.

  5. Objects have either one or two colors.

    Body color and glow color are independent, and either will satisfy a color filter. "WHEN see red DO move toward" will move toward the closest object that either has a red body or is glowing red. There is no way to distinguish between these two conditions.

    The "glow" action with no color argument uses the object's current body color to set the glow color.

  6. Bump is transitory.

    When a pursuing object bumps its target they will bounce off each other in a manner determined by their mass and relative speed. This can terminate the bump relation after as little as one rule cycle; the duration of contact is indeterminate. A lost contact might be re-established, either deliberately through continued pursuit or accidentally via rebounding off other objects. Inertia and the elasticity of collisions mean the persistence of a bump is not guaranteed even if the pursuer halts its motion the instant the bump occurs. Due to the transitory nature of "bump", rules employing this predicate do not offer the "once" modifier.

    Rule Evaluation

  7. Indented rules are only considered when their parent's condition is true.

    Since the parent is only considered if its own parent's condition is true, an indented rule depends on all its ancestors' conditions being simultaneously true.

  8. Kodu first evaluates all the WHENs, and then performs the selected DOs.

    On each rule cycle, all the predicates on the current page are evaluated before any actions are run. This matters when a rule's action changes some state that a later rule's condition refers to. Even if the later rule's condition will be made false by the earlier rule's action, the later rule will still run because its condition was true when all the conditions were being evaluated.

    This convention is sometimes useful and other times a source of obscure bugs. An example of the latter is:

    [1] WHEN DO set score 5 points once
    [2] WHEN timer 1 second DO subtract 1 point
    [3] WHEN scored 0 points DO win
    This code never subtracts anything from the score. It wins immediately, because all scores start out at 0. So on the first rule cycle the conditions of rules 1 and 3 both evaluate to true. Then rule 1's action initializes the red score to 5, rule 2 starts its timer, and rule 3's action immediately ends the program. This is obviously not what the programmer intended.

    One solution is to initialize the score on page 1 but put the loop on page 2 so that the exit test cannot run until after the score has been properly initialized. Another solution is to use a short time delay to prevent the exit test from running on the very first rule cycle:

    [1] WHEN DO set score 5 points once
    [2] WHEN timer 1 second DO subtract 1 point
    [3] WHEN timer .25 seconds DO
           ↳ [4] WHEN scored 0 points DO win
    A third solution is to set a flag to indicate that initialization has happened, and include that flag in the termination test, which again prevents the test from running on the very first rule cycle:
    [1] WHEN DO set score red 5 points once
    [2] WHEN DO set score "F" 1 point once
    [3] WHEN timer 1 second DO subtract red 1 point
    [4] WHEN scored "F" 1 point DO
           ↳ [5] WHEN scored red 0 points DO win

  9. Actions are performed sequentially.

    Actions can build on the effects of earlier actions. This matters mainly for score operations, where the actions "set score 5" and "score 1 point" will leave the score at 6 points when the rules are ordered as stated. If the order is reversed, the score will first be incremented and then that value will be discarded as the score is set to 5.

  10. When actions conflict, the earlier rule prevails.

    This rule arbitration mechanism is the heart of the Default Value idiom. In order for two actions to conflict, the verb must be the same, and the parameter values must be incompatible. For example, "color me red" and "color me blue" conflict, so the earlier action will prevail. Similarly, "open me" and "close me" conflict, as do "move toward" and "move wander".

    There are a few cases where actions combine rather than conflict. For example, "move avoid" can merge with other move actions such as "move toward". Also, if a "WHEN gamepad L-stick DO move" rule is ordered after a "move toward" action, the two motions will combine. But if the gamepad rule appears before the "move toward" action it will override it.

  11. Page switch short-circuits action execution.

    When a "switch to page" action is executed, the actions of any remaining (i.e., higher numbered) rules are skipped. The following actions can therefore act as the "else" part of a conditional.

    The "win" and "end" primitives also prevent any following actions from executing, because they immediately end the game.

  12. The "once" modifier is not satisfied until the action executes successfully; it then remains satisfied until the rule's predicate becomes false.

    For example: in a world with multiple apples, "WHEN see apple DO eat it once" will run until the first apple is successfully eaten. It will not run again until no apples are visible for at least one rule cycle, or the page is re-entered via a "switch to page" action.

  13. "Once" flags are cleared on page entry.

    Upon switching into a page, all rules have their "once" flag cleared, making them eligible to run. This is true even when the page being entered is the one that was just left.

  14. Conflicting goals call for separate pages.

    If a program's goals can't be approached simultaneously, such as traveling to different locations or performing actions on different objects, the most straightforward solution is to assign each goal to a separate page. For example, to fetch an apple from a tree that launches an apple when bumped, and to give that apple to an octopus, we must pursue multiple objects. Pursuing the apple takes priority over pursuing the tree, but both can go on the same page because the apple doesn't become visible until the tree has been bumped. Pursuing the octopus should go on a separate page because the octopus is visible all the time; it will either override or be overridden by pursuit of the tree, neither of which is desirable.

    PAGE 1:
    [1] WHEN see apple DO move toward
    [2] WHEN bump apple DO grab it
           ↳ [3] WHEN DO switch to page 2
    [4] WHEN see tree DO move toward

    PAGE 2:
    [1] WHEN see octopus DO move toward
    [2] WHEN bump octopus DO give
    It is often possible to avoid page switches by using some other type of state to control which goal is being pursued, but at a cost of increased rule complexity, which results from adding dependency relationships. The example above could be coded as a single page by using the character's holding state to control which rules are active:
    [1] WHEN got apple DO
           ↳ [2] WHEN see octopus DO move toward
           ↳ [3] WHEN bump octopus DO give
    [4] WHEN see apple DO move toward
    [5] WHEN bump apple DO grab it
    [6] WHEN see tree DO move toward

    The earlier two-page solution uses a single indented rule with an empty WHEN part: an instance of the Do Two Things idiom. The one-page solution uses two indented rules with non-empty WHEN parts, so these rules implement more complex conjunctive conditions: the If This And Also That idiom.

    Even more complex state machines can be implemented on a single page by using scores, but the result is more baroque and less transparent than using separate pages.

  15. Timer predicates are only true for an instant.

    A rule such as "WHEN timer 1 second DO ..." will run for one just rule cycle every time the timer expires. Thus, their actions should be of the type that take effect instantaneously, such as updating a score, creating or destroying an object, playing a sound, or switching pages. Move actions would be ineffective in this context because they require multiple rule cycles for the character to accelerate.

    To use a timer to trigger an extended duration action, the timer must either set a flag or cause a page switch.

  16. Timers don't nest.

    Because timer predicates are only true for an instant, any dependent (indented) rule can only run for an instant. Thus, if the indented rule contains its own timer, the nested timer will start but will be cancelled on the very next rule cycle when the parent rule is no longer active. Thus, nested timers conditions can never be satisfied.


  17. Tiles in score expressions, whether point tiles or score references, combine additively.

    Score expressions can occur in "WHEN scored score-color" conditions or in "DO score score-color", "DO set score score-color", or "DO subtract score-color" actions. A score expression consists of one or more tiles, in any order, that are either point tiles or score color tiles. The values of all the tiles that make up a score expression are added together.

    A "WHEN scored score-color" condition or a "DO score score-color", "DO set score score-color", or "DO subtract score-color" action can also take a random expression as an argument. This consists of a "random" tile optionally preceded and/or followed by a score expression.

  18. A "WHEN scored score-color" condition with no score expression responds to any change in the score.

    The condition will be true if the score changed during the preceding rule cycle.


  19. Any object can grab or give.

    Even inanimate objects like trees and rocks can grab, give, or receive objects. For clarity in the points that follow, we will use the term "character" for the holder and "object" for the thing being held, but any object can play either role.

  20. A character can only hold one thing at a time.

    If a character is holding an object when it grabs another object, the first object is dropped. Similarly, if a character is holding an object when another character gives it something, the first object is dropped.

  21. Held characters can't hold or grab anything.

    If a character is grabbed while holding an object, the held object is dropped. If a held character attempts to grab an object, it fails: the action has no effect.

  22. Held objects are visible to other characters, but not the holder.

    The holder can detect the held object with "got", but not with "see".

  23. Held objects can't be grabbed by another character.

    A character can see and bump a held object, but cannot steal it from the holder. However, the holder can use "give" to transfer the object.

  24. Held objects can't move, but otherwise behave normally.

    For example: held objects can perceive the world, speak, create or launch other objects, and even boom the object holding them. But they cannot move or, as mentioned above, grab anything.


  25. Speech actions are sequential and last between 1.25 and 1.5 seconds.

    A character can only say one thing at a time. (But characters can play multiple sounds at once.) The minimum duration for a speech action is somewhere between 1.25 and 1.5 seconds.

  26. Speech actions don't queue.

    If a character is already saying something when a new speech action is attempted, the new speech is discarded.

  27. Speech can he heard either at onset or offset (the default).

    When a spoken text is heard is controlled by an option of the "said" tile in "WHEN hear said". By default, a character will not "hear" (hence, react to) an utterance until the speaker has finished. This allows for natural pacing of a conversation between characters. However, if a character should react immediately to an utterance, the setting can be changed to respond to the onset rather than the offset of speech.

  28. Continuously repeated speech has no offset, and the speech bubble never goes away.

    With the default setting of "WHEN hear said", a character will never hear an utterance that is being repeated continuously because there is no speech offset event. The "once" modifier or some transient WHEN condition can be used to ensure that speech is uttered only once.


    (Coming soon.) Paths are not objects and cannot be seen, bumped, or programmed. "end of path" is like "see" in that a character does not sense itself unless a "me" tile is used.


  29. Between dying and nonexistence there is exactly one rule cycle.

    Dying, which can result from being eaten or shot, is detected by "WHEN health 0 points". The condition is true for exactly one rule cycle, so actions that require more time (such as motion) will not execute successfully. Switching to a new page can be used for short-circuit effect, but any rules on the new page will never run because this is the character's last rule cycle. However, many other actions can be performed in the dying state, such as manipulating scores, creating objects, even launching a missile.

  30. A dying character cannot see itself.

    A dying character that wishes to check its body color or glow color cannot do so, because it is no longer perceptible in the world.

  31. Dying characters can't hold anything.

    During its last rule cycle, a dying character has already dropped whatever it was holding.


    (Coming soon.)

    Camera Control

    (Coming soon.)

Dave Touretzky
Last modified: Sat Aug 22 23:22:26 EDT 2015