Skip to content

Commit

Permalink
Added: $select_r variant of the $select behaviour
Browse files Browse the repository at this point in the history
Added: more checking of behaviour return values
Fixes: $invert behaviour was broken
Fixes: bug when assigning a null to a synthetic id based attribute
Fixes: was not parsing use of behaviour templates properly
Fixes: bug in custom event handling
  • Loading branch information
mmower committed May 20, 2024
1 parent 1b41367 commit 266cbb6
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 13 deletions.
3 changes: 3 additions & 0 deletions assets/templates/runtime/rez_0prototype.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ const basic_object = {
return $(ref_id);
},
set: function (ref) {
if(ref === null) {
throw "Cannot assign an empty ID ref";
}
this.setAttribute(attr_name, ref.id);
},
});
Expand Down
11 changes: 10 additions & 1 deletion assets/templates/runtime/rez_behaviour.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,16 @@ RezBehaviour.prototype = {
}
}

return execute(this.owner, this, wmem);
const result = execute(this.owner, this, wmem);
if(typeof(result) !== "object") {
throw "Behaviour execute returned non-object";
} else if(!result.hasOwnProperty("success")) {
throw "Behaviour execute return object without success";
} else if(typeof(result.success) == "undefined") {
throw "Behaviour execute returned success undefined";
}

return result;
},

instantiate(owner, options, children = []) {
Expand Down
2 changes: 1 addition & 1 deletion assets/templates/runtime/rez_event.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ RezEventProcessor.prototype = {
handleCustomEvent(event_name, params) {
const [receiver, handler] = this.getEventHandler(event_name);
if(!handler) {
return {error: `Unable to find an event handler for |${event_name}|`};
return RezEvent.error(`Unable to find an event handler for |${event_name}|`);
} else {
console.log(`Routing event |${event_name}| to |${receiver.id}|`);
return handler(receiver, params);
Expand Down
2 changes: 1 addition & 1 deletion assets/templates/runtime/rez_game.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ RezGame.prototype = {
getGameObject(id, should_throw = true) {
if (!this.game_objects.has(id)) {
if (should_throw) {
throw "No such ID |" + id + "| found!";
throw `No such ID |${id}| found!`;
} else {
return null;
}
Expand Down
43 changes: 34 additions & 9 deletions assets/templates/stdlib.rez.eex
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
throw `Cannot take ${n} items from an array containing ${this.length} items!`;
}

return Number.range(1, n).map((_) => {return this.shift()});
return Math.range(1, n).map((_) => {return this.shift()});
}
}

Expand Down Expand Up @@ -360,6 +360,14 @@
}
}

@patch PATCH_STRING_INDEFINITE_ARTICLE {
patch: "String"
method: "indefiniteArticle"
impl: function() {
return this.beginsWithConsonant() ? "a" : "an";
}
}

%% Some helpful set functions from:
%% https://medium.com/@alvaro.saburido/set-theory-for-arrays-in-es6-eb2f20a61848
%% https://stackoverflow.com/a/31129384/7518
Expand Down Expand Up @@ -845,7 +853,7 @@

name: "i_article"
impl: (s) => {
const article = s.beginsWithConsonant() ? "a" : "an";
const article = s.indefiniteArticle();
return `${article} ${s}`;
}
}
Expand Down Expand Up @@ -1081,6 +1089,28 @@
}
}

@behaviour $select_r {
%% The $select_r behaviour is similar to $select except that each time it
%% executes, it executes its children in random order.

$template: true
options: []
min_children: 2

execute: (owner, behaviour, wmem) => {
let result = {success: true, wmem: wmem};
const indices = Math.range(0, behaviour.childCount-1).fy_shuffle();
for(const i of indices) {
const child = behaviour.getChildAt(i);
result = child.executeBehaviour(result.wmem);
if(result.success) {
break;
}
}
return result;
}
}

@behaviour $select_p {
%% The $select_p behaviour is similar to SELECT except that before ticking any
%% child it does a probability check using the "p" option. If the check passes
Expand Down Expand Up @@ -1317,13 +1347,8 @@

execute: (owner, behaviour, wmem) => {
const result = behaviour.firstChild.executeBehaviour(wmem);
if(result.success) {
result.success = false;
result.error = "Inversion";
result.id = behaviour.id;
} else {
result.success = true;
}
result.success = !result.success;
return result;
}
}

Expand Down
8 changes: 8 additions & 0 deletions docs/behaviour_catalog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ The `$sequence` behaviour takes two or more children and, when executed, it exec

The effect is like a boolean `and` expression. Sequences are often a set of conditions followed by a set of actions.

Metaphorically a `$sequence` is like a recipe, a set of steps that should be following from start to finish. If you get half way through a recipe and are missing a key ingredient, the recipe cannot be finished.

== $select

The `$select` behaviour takes two or more children and, when executed, it executes each of its children in turn. If any child succeeds then `$select` will immediately succeed without executing any further children. If all the children fail then `$select` will fail.

The effect is like a boolean `or` expression. Selects often express a range of alternative behaviours where we want only the first to succeed.

Metaphorically a `$select` is like the mains section of a menu, you pick an choose among the options available but don't (at least the author tries not to) order two mains.

== $select_p

The `$select_p` behaviour is a variant on `$select`. It takes a probability option `p` and before executing any child will test `p`. If the test succeeds it will execute that child and behaviour similar to `$select`. If no children get executed or all the children fail then `$select_p` will fail.
Expand All @@ -35,6 +39,10 @@ The `$select_p` behaviour is a variant on `$select`. It takes a probability opti
|probability of any given child getting executed
|===

== $select_r

The `$select_r` behaviour is a variant on `$select`. When a `$select_r` is executed it executes its children in a random order.

== $loop

The `$loop` behaviour takes one child and executes it a number of times specified by the option `count`. If the child should fail then `$loop` fails. If the child succeeds each time then `$loop` succeeds.
Expand Down
6 changes: 5 additions & 1 deletion lib/parser/btree_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ defmodule Rez.Parser.BTreeParser do
def bt_template_ref() do
sequence(
[
ignore(open_bracket()),
iows(),
ignore(amp()),
iows(),
js_identifier()
js_identifier(),
iows(),
ignore(close_bracket())
],
ast: fn [template_id] ->
{:template, template_id}
Expand Down

0 comments on commit 266cbb6

Please sign in to comment.