-
Notifications
You must be signed in to change notification settings - Fork 10
Ensemble API
A reference list of all public functions available from the ensemble.js library
This page is under construction. Stay tuned for full, up-to-date function definitions! In the meantime refer to the comments above function definitions in the standalone ensemble.js. They may be slightly out of date, incomplete, or incorrect, but better than nothing! Also take a gander at the Lovers and Rivals example game for example function calls.
Functions are listed roughly in the order you would usually call them in an interactive media project. The functions listed under the Running category are typically called repeatedly in a core interaction or game loop.
This class is the top level interface into ensemble. Include the ensemble.js library file in your project to gain access to the global ensemble singleton object, which is used to call all Ensemble methods.
<script src="ensemble.js"></script>After you load ensemble, you should call ensemble.loadFile(), and the appropriate other load functions for your schema, trigger rules, volition rules, characters, history, and actions, before calling any other ensemble functions that depend on them.
Loads a JSON file using an XMLHttpRequest, parses the JSON string into a JavaScript object, and returns that object. Does not do anything particularly Ensemble-specific.
If you're defining your social domain in separate files (schema.json, actions.json, etc), call loadFile() for each file. A full domain requires schema, actions, characters, history, volition rules, and trigger rules. You can name the files whatever you want as long as you keep track of the parsed output of loadFile() for each of those definitions, in order to pass them to the correct loading function (loadSocialStructure(parsedSchemaJSON), addActions(parsedActionsJSON), etc).
Alternatively, you could store your definitions as JSON objects directly in your JavaScript, in which case you wouldn't need to call loadFile(). This may be preferable for deploying a game or other project that uses Ensemble, so you aren't making unnecessary HttpRequests. The authoring tool will not accept this as input however; it expects domain definition objects to exist in their own JSON files.
Parameters: filename - a string of the relative path to the data file
Returns: A JSON object containing the parsed contents of the given file
Example:
var rawSchema = ensemble.loadFile("data/schema.json")Assuming that, relative to the file this function is being called from, there is a data directory with the file schema.json, the schema will be loaded into Ensemble, and rawSchema will have the contents of the JSON file.
[TODO: For each of the below loading functions, add a link to the appropriate JSON definition documentation]
Validates a given JSON string or object schema definition and restructures it slightly for internal ensemble.js use. This should be called before loading in any other aspects of Ensemble (history, rules, actions, etc), since their loading functions reference the internal data model created by loadSocialStructure(). Not cumulative.
Parameters: data - a schema definition JSON object to load. Typically the result of a call to loadFile().
Returns: A slightly restructured (and more redundant) schema definition object for faster internal ensemble.js lookup. Authors generally don't need to use this return value. Use getSocialStructure() instead.
Example:
var rawSchema = ensemble.loadFile("data/schema.json");
ensemble.loadSocialStructure(rawSchema);Takes a JSON string or object definition of characters and stores it for internal Ensemble use. Not cumulative. Doesn't do any validation (yet).
Parameters: data - a cast definition JSON object to load. Typically the result of a call to loadFile(). It should contain a top-level key, cast, whose value is a dictionary whose keys are character identifiers and whose values are objects with character metadata (such as the key, name).
Returns: An array of character ID strings. Can store this or use getCharacters().
Example:
var rawCast = ensemble.loadFile("data/cast.json");
ensemble.addCharacters(rawCast);Takes a JSON string or object definition of either volition rules or trigger rules, validates it, and stores it for internal Ensemble use. You should expect to call this function at least twice: for volition rules and for trigger rules. This function is cumulative; calling it on multiple objects of the same type will lead to the rules from both objects being stored in the appropriate rules library.
Parameters: data - a volition rules or trigger rules definition JSON object to load. Typically the result of a call to loadFile(). It should define top level keys fileName, type, and rules, where type is either "volition" or "trigger".
Returns: An array of unique ID strings for each rule added, in the form type_num (i.e. ["triggerRules_1", ..]) Authors generally don't need to use this return value. Use getRules(type) instead.
Example:
var rawTriggerRules = ensemble.loadFile("data/triggerRules.json");
ensemble.addRules(rawTriggerRules);
var rawVolitionRules = ensemble.loadFile("data/volitionRules.json");
ensemble.addRules(rawVolitionRules);Takes a JSON string or object definition of one or more valid actions and stores it in the currently active action library. This effect is cumulative; calling this function on multiple objects will lead to the actions from both objects being stored in the action library. There is currently no real validation of the actions at this step, though there should be (see issue #79).
Parameters: data - an actions definition JSON object to load. Typically the result of a call to loadFile().
Returns: An array of every action currently stored in the action library. Authors generally don't need to use this return value. Use getAllActions() instead.
Example:
var rawActions = ensemble.loadFile("data/actions.json");
ensemble.addActions(rawActions);Takes a JSON string or object definition of history data, validates it, and uses it to initialize the social record. This function is cumulative; calling it on multiple history objects will lead to the predicates from both objects getting stored to the social record. If there are duplicate statements (the same schema type, for the same character(s), for the same timestep, but different values), the second history object will overwrite the value given by the first.
Parameters: data - a history definition JSON object to load. Typically the result of a call to loadFile(). It should contain a top-level key, history, whose value is an array of timestep objects.
Returns: A JSON object of the history that was just loaded in. Authors generally don't need to use this return value. Use dumpSocialRecord(), getSocialRecordCopyAtTimestep(timestep), or getSocialRecordCopy() instead.
Example:
var rawHistory = ensemble.loadFile("data/history.json");
ensemble.addHistory(rawHistory);Calculates the volition weights (or scores) for each character in the given cast at the current timestep. Each character in the cast will form volitions for every character, including themselves, for each intent. Weights are assigned to each of these volitions by running all active volition rules. If a rule's conditions are met for a particular binding of characters to roles in the rule, the numerical weight(s) defined in the rule's effect will be summed with all other contributing rule weights to produce a final score for all character pairs and all intents.
Note: In the future, might be renamed to calculateVolitions(), plural, since it calculates all the volitions. See issue #83.
Parameters: cast - an array of character ID strings, the cast of characters to calculate volition for and between
Returns: A calculated volition custom iterator object with functions getFirst(), getNext(), getWeight(), dump(), and isAccepted(). This object is passed to getActions() to calculate the actions characters want to perform given their volition scores. Call the dump() function of the returned calculated volition object for a dictionary containing the cast and their volitions in the form:
{
"Simon": {
"Monica": [
{ "category": "network", "type": "buddy", "intentType": true, "weight": 20 },
{ "category": "relationship", "type": "involved with", "intentType": true, "weight": 19 }
]
},
"Monica": {
"Simon": [
{ "category": "network", "type": "romance", "intentType": false, "weight": 12 }
]
}
}Meaning Simon has 20 volition to increase their buddy-ness with Monica, and 19 volition to set their involved with relationship type to true, while Monica has 12 volition to decrease their romance network with Simon. This is assuming the schema category network is scalar and relationship is boolean.
Example:
var cast = ensemble.getCharacters();
var calculatedVolitions = ensemble.calculateVolition(cast);
console.log("Calculated volitions:", calculatedVolitions.dump());Given a calculated volition object, returns the single 'best' (highest-weighted) action among all volitions from initiator to responder. Actions are scored by traversing the action graph starting at the root level nodes for each intent (beginning with the initial volition score for this intent, given by calculateVolition()), and stepping through child nodes, adding any weight assigned by action influence rules whose conditions are met as you go, for the final score assigned to the terminal nodes. If you haven't defined influence rules on actions, action scores will be equal to the original volition scores of the terminal action's ancestor intent-level nodes.
Parameters:
-
initiator- the string ID of the character initiating the action -
responder- the string ID of the recipient of the action (can be the same as theinitiatorto retrieve self-directed actions, or actions that pertain to changing undirected schema types) -
calculatedVolitions- a calculated volition object, as returned bycalculateVolition() -
cast- an array of character ID strings, to be used for consideration in binding roles defined by the actions
Returns: A bound action object of the highest-scoring action for this particular initiator, responder, and cast. Or undefined if the initiator has no volitions or actions with a weight greater than or equal to 0 toward the responder. If there is one, the returned bound action object will take the form:
{
name: "pushup",
displayName: "Do Pushups",
conditions: [],
influenceRules: [],
fileName: "actions.json",
id: 11,
origin: undefined,
weight: 10,
effects: [
{ category: "attribute", type: "strength", first: "rival", operator: "+", value: 10, second: undefined },
{ category: "socialRecordLabelUndirected", type: "self-involved", first: "rival", value: true, second: undefined }
],
salience: 10,
lineage: "RAISESTRENGTH-WORKOUT",
goodBindings: [{
initiator: "hero",
responder: "hero",
weight$$: 10
}]
}name, displayName, conditions, influenceRules, and are taken from the original JSON action definition. fileName, id, and origin are properties added by ensemble.addActions(). The last five properties listed above, weight, effects, salience, lineage, and goodBindings are added during action calculation:
-
weight- the score calculated for this action from the given initiator to responder at the current timestep. (See explanation of this scoring above.) -
effects- an array of bound effects statements. Nearly identical to the author-defined effects statements for this action definition (from the author-givenactions.json), but instead of abstract roles in thefirstandsecondproperties (e.g.,"initiator"and"responder"), the roles have assigned character IDs. Alternate bindings may be found ingoodBindings. -
salience- the sum of the weight and author-specified salience for this action. (This may eventually be calculated automatically based on the action's number of conditions. See issue #92.) Salience is only relevant for domains with enough actions defined that many are possible for a given situation and you need a better way to choose among them than randomly. Most authors can safely ignore this. -
lineage- a string listing the names of ancestor action nodes of this terminal action node in the action graph in order from parent to child, etc, and separated by dashes. In this example, the top-level intent action node was "RAISESTRENGTH", which contained "WORKOUT" in itsleadsToarray, which in turn contained "pushup" in itsleadsToarray. This was the path taken by the action scoring which resulted in this terminal action getting the weight it did. -
goodBindings- an array of character binding objects. Each one maps characters fromcastto roles defined in the action. Often, this won't be useful because it'll be a single binding object with "initiator" and "responder" character bindings, which you already know because you passed those as parameters. But if this is an action with roles besides "initiator" and "responder", this will be useful. For example, you could have defined an "onlooker" role by setting it to thefirstorsecondproperty of a condition, influence rule, or effect predicate of an action.
Example:
var cast = ensemble.getCharacters();
var calculatedVolitions = ensemble.calculateVolition(cast);
var bestActionFromBobToJane = ensemble.getAction("bob", "jane", calculatedVolitions, cast);
if (bestActionFromBobToJane)
console.log("Action Bob most wants to do to/with Jane:", bestActionFromBobToJane);
else
console.log("Bob doesn't want to do anything with Jane");ensemble.getActions(initiator, responder, calculatedVolitions, cast, numIntents, numActionsPerIntent, numActionsPerGroup)
Given a bound action object, like those returned by ensemble.getAction(), performs the action by executing all of its effects.
Apply rules that conditionally change social state
Set a particular social fact in the social record
Get a particular social state value
Progress timestep
Print all history to the console
[Under construction]