├── .gitignore
├── Gruntfile.js
├── LICENSE.md
├── README.md
├── build-authoring-tool.js
├── build-library.js
├── docs
└── toolscreenshot.png
├── ensemble
├── ActionLibrary.js
├── RuleLibrary.js
├── Validate.js
├── Volition.js
├── ensemble.js
├── jslib
│ ├── underscore-min.js
│ ├── underscore-min.map
│ ├── underscore.js
│ └── util.js
└── socialRecord.js
├── ensembletool
├── README.md
├── csslib
│ ├── images
│ │ ├── animated-overlay.gif
│ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png
│ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png
│ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ ├── ui-bg_flat_10_000000_40x100.png
│ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ ├── ui-bg_glass_100_f6f6f6_1x400.png
│ │ ├── ui-bg_glass_100_fdf5ce_1x400.png
│ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png
│ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png
│ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_228ef1_256x240.png
│ │ ├── ui-icons_2e83ff_256x240.png
│ │ ├── ui-icons_454545_256x240.png
│ │ ├── ui-icons_888888_256x240.png
│ │ ├── ui-icons_cd0a0a_256x240.png
│ │ ├── ui-icons_ef8c08_256x240.png
│ │ ├── ui-icons_ffd27a_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── jquery-ui.structure.min.css
│ └── jquery-ui.theme.min.css
├── defaultdata
│ ├── actions.json
│ ├── cast.json
│ ├── history.json
│ ├── schema.json
│ ├── triggerRules.json
│ └── volitionRules.json
├── ensembleconsole.css
├── index.html
├── js
│ ├── actionEditor.js
│ ├── consoleViewer.js
│ ├── ensembleconsole.js
│ ├── fileio.js
│ ├── historyViewer.js
│ ├── messages.js
│ ├── ruleTester.js
│ ├── rulesEditor.js
│ ├── rulesViewer.js
│ └── schemaviewer.js
├── jslib
│ ├── ensemble.js
│ ├── jquery-2.1.0.js
│ ├── jquery-ui.min.js
│ ├── underscore-min.js
│ ├── underscore-min.map
│ ├── underscore.js
│ └── util.js
├── main.js
└── package.json
├── examples
└── loversAndRivals
│ ├── data
│ ├── actions.json
│ ├── cast.json
│ ├── history.json
│ ├── schema.json
│ ├── triggerRules.json
│ └── volitionRules.json
│ ├── ensemble.js
│ ├── index.html
│ ├── loversAndRivals.js
│ └── styles.css
├── index.html
├── jsdoc-conf.json
├── jsdoc-default.css
├── package-lock.json
├── package.json
└── tests
├── data
├── rpgActions.json
├── rpgSchema.json
├── samsVolition.json
├── testActions.json
├── testActionsGrammar.json
├── testActionsGrammar10.json
├── testActionsGrammar11.json
├── testActionsGrammar12.json
├── testActionsGrammar13.json
├── testActionsGrammar14.json
├── testActionsGrammar15.json
├── testActionsGrammar16.json
├── testActionsGrammar17.json
├── testActionsGrammar2.json
├── testActionsGrammar3.json
├── testActionsGrammar4.json
├── testActionsGrammar5.json
├── testActionsGrammar6.json
├── testActionsGrammar7.json
├── testActionsGrammar8.json
├── testActionsGrammar9.json
├── testHistory.json
├── testSocial.json
├── testState.json
├── testTriggerRules.json
└── testVolitionRules.json
├── externalApplicationFiles
├── actions.json
├── cast.json
├── dataLoversAndRivals
│ ├── actions.json
│ ├── cast.json
│ ├── history.json
│ ├── schema.json
│ ├── triggerRules.json
│ └── volitionRules.json
├── samsVolition.json
├── schema.json
└── testTrigger.json
├── index.html
├── js
├── ActionLibraryUnitTests.js
├── ExternalApplicationTest.js
├── RuleLibraryUnitTests.js
├── SocialRecordUnitTests.js
├── Tests.js
├── ValidateUnitTests.js
├── VolitionUnitTests.js
└── ensembleUnitTests.js
├── jslib
├── jquery-2.1.0.js
├── underscore-min.js
├── underscore-min.map
└── underscore.js
├── test-styles.css
└── tests-main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # generic
2 | .DS_Store
3 |
4 | # used in build process
5 | build
6 | doc
7 | node_modules
8 | release
9 |
10 | # backups of domain JSON files, generated by the authoring tool
11 | examples/loversAndRivals/data/_bak_*
12 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | // Project configuration.
4 | const config = {
5 | pkg: grunt.file.readJSON("package.json"),
6 | shell: {
7 | options: {stderr: false},
8 | buildLibrary: {command: "node build-library.js <%=pkg.version%>"},
9 | buildAuthoringTool: {command: "node build-authoring-tool.js <%=pkg.version%>"}
10 | },
11 | jsdoc: {
12 | dist: {
13 | src: "ensemble/*.js",
14 | options: {
15 | destination: "doc",
16 | configure: "jsdoc-conf.json",
17 | private: false
18 | }
19 | }
20 | },
21 | copy: {
22 | buildLibrary: {
23 | files: [
24 | {src: "build/ensemble.js", dest: "ensembletool/jslib/ensemble.js"},
25 | {src: "build/ensemble.js", dest: "examples/loversAndRivals/ensemble.js"}
26 | ]
27 | },
28 | release: {
29 | files: [
30 | {src: "build/ensemble.js", dest: "release/ensemble.js"}
31 | ]
32 | }
33 | }
34 | };
35 |
36 | // Set up a compress:PLATFORM subtask for each authoring tool target platform
37 | const authoringToolTargetPlatforms = [
38 | {releaseName: "linux32", internalName: "linux-ia32"},
39 | {releaseName: "linux64", internalName: "linux-x64"},
40 | {releaseName: "macOS", internalName: "darwin-x64"},
41 | {releaseName: "win32", internalName: "win32-ia32"},
42 | {releaseName: "win64", internalName: "win32-x64"}
43 | ];
44 | config.compress = {};
45 | for (let platform of authoringToolTargetPlatforms) {
46 | config.compress[platform.releaseName] = {
47 | options: {archive: `release/EnsembleTool-v<%=pkg.version%>-${platform.releaseName}.zip`, mode: "zip"},
48 | files: [{expand: true, cwd: `build/Ensemble Tool-${platform.internalName}`, src: "**", dest: "."}]
49 | };
50 | }
51 |
52 | // Load config
53 | grunt.initConfig(config);
54 |
55 | // Load plugins
56 | grunt.loadNpmTasks("grunt-contrib-compress");
57 | grunt.loadNpmTasks("grunt-contrib-copy");
58 | grunt.loadNpmTasks("grunt-jsdoc");
59 | grunt.loadNpmTasks("grunt-shell");
60 | //grunt.loadNpmTasks("grunt-contrib-uglify");
61 |
62 | // Default task: just build the library
63 | grunt.registerTask("default", ["deploy"]);
64 |
65 | // Build ensemble.js and copy newly built file into place for consumers
66 | grunt.registerTask("deploy", ["shell:buildLibrary", "copy:buildLibrary"]);
67 |
68 | // Generate library documentation
69 | grunt.registerTask("document", ["jsdoc"]);
70 |
71 | // Rebuild the library, then build the authoring tool for all target platforms
72 | grunt.registerTask("build", ["deploy", "shell:buildAuthoringTool"]);
73 |
74 | // Rebuild the library and authoring tool, then zip the authoring tool builds
75 | // and copy all release-ready files to the release directory
76 | grunt.registerTask("release", ["build", "compress", "copy:release"]);
77 | };
78 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | BSD-4-Clause (University of California-Specific)
2 |
3 | Copyright (c) 2019, The Regents of the University of California. All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 | 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Santa Cruz and its contributors.
10 | 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ensemble
2 |
3 | A framework for creating socially aware characters. An evolution of the Comme il Faut AI system, which powered the game Prom Week.
4 |
5 | ## ensemble.js
6 |
7 | `ensemble.js`, available as part of the [latest release](https://github.com/ensemble-engine/ensemble/releases/latest), is a standalone JavaScript library that you can include in a web project with an HTML script tag:
8 |
9 | ``
10 |
11 | Then, in your JavaScript code, you can use the `ensemble` singleton object to call [Ensemble methods](https://github.com/ensemble-engine/ensemble/wiki/Ensemble-API).
12 |
13 | See the [wiki homepage](https://github.com/ensemble-engine/ensemble/wiki/) for tutorial links and other resources for getting started.
14 |
15 | ## Ensemble Authoring Tool
16 |
17 | It can be difficult and tedious to author Ensemble domains (schema, trigger rules, volition rules, characters, history, and actions) in pure JSON without helper functions. The Ensemble Authoring Tool is a standalone desktop app designed to help authors develop and test their domains.
18 |
19 | 
20 |
21 | The latest builds can be found on the [releases](https://github.com/ensemble-engine/ensemble/releases/latest) page.
22 |
23 | ## Contribute
24 |
25 | See the [Contributing](https://github.com/ensemble-engine/ensemble/wiki/Contributing) wiki page for information about how to contribute to the project, [how to build the library from source](https://github.com/ensemble-engine/ensemble/wiki/Developing-Ensemble-Core), [how to build the tool from source](https://github.com/ensemble-engine/ensemble/wiki/Developing-the-Authoring-Tool), etc.
26 |
27 | ## Get Help
28 | If you are having issues, please let us know by opening an [issue](https://github.com/ensemble-engine/ensemble/issues) (maybe using the “question” tag)! We'd seriously love to hear from you!
29 |
30 | ## License
31 | The project is licensed under the BSD-4-clause license.
32 |
--------------------------------------------------------------------------------
/build-authoring-tool.js:
--------------------------------------------------------------------------------
1 | // replace version string in ensembletool/package.json with updated version string
2 | // (passed as first CLI argument)
3 | if (process.argv[2]) {
4 | const version = process.argv[2];
5 | const packageFilePath = "ensembletool/package.json";
6 | const fs = require("fs");
7 | const oldContents = fs.readFileSync(packageFilePath, "utf8");
8 | const newContents = oldContents.replace(/"version": "[^"]+"/, `"version": "${version}"`);
9 | fs.writeFileSync(packageFilePath, newContents);
10 | }
11 |
12 | const packager = require("electron-packager");
13 |
14 | async function bundleElectronApp(options) {
15 | const appPaths = await packager(options);
16 | console.log(`Electron app bundles created:\n${appPaths.join("\n")}`);
17 | };
18 |
19 | bundleElectronApp({
20 | // options as specified in https://github.com/electron/electron-packager/blob/master/docs/api.md
21 | arch: "ia32,x64",
22 | dir: "ensembletool",
23 | platform: "darwin,win32,linux",
24 | out: "build",
25 | overwrite: true
26 | });
27 |
--------------------------------------------------------------------------------
/build-library.js:
--------------------------------------------------------------------------------
1 | // This script builds the build/ensemble.js standalone Ensemble library file.
2 |
3 | const fs = require("fs");
4 |
5 | const buildDir = "build";
6 | const mainBuildPath = buildDir + "/ensemble.js";
7 | const testBuildPath = buildDir + "/ensemble-test.js";
8 | const version = process.argv[2];
9 |
10 | const modules = [
11 | {name: "underscore", path: "ensemble/jslib/underscore-min.js", wrapper: "none"},
12 | {name: "util", path: "ensemble/jslib/util.js"},
13 | {name: "socialRecord", path: "ensemble/socialRecord.js"},
14 | {name: "ruleLibrary", path: "ensemble/RuleLibrary.js"},
15 | {name: "actionLibrary", path: "ensemble/ActionLibrary.js"},
16 | {name: "volition", path: "ensemble/Volition.js"},
17 | {name: "validate", path: "ensemble/Validate.js"},
18 | {name: "ensemble", path: "ensemble/ensemble.js"}
19 | ];
20 |
21 | if (!fs.existsSync(buildDir)) {
22 | console.log(`Creating directory ${buildDir}/`);
23 | fs.mkdirSync(buildDir);
24 | }
25 |
26 | for (let buildPath of [mainBuildPath, testBuildPath]) {
27 | console.log(`Building ${buildPath}...`);
28 | fs.writeFileSync(buildPath, `// *** Ensemble v${version} ***\nensemble = (function(){\n`);
29 | for (let mod of modules) {
30 | console.log(" *", mod.name, mod.path);
31 | fs.appendFile(buildPath, `// MODULE ${mod.name}\n`, () => {});
32 | const moduleContents = fs.readFileSync(mod.path).toString();
33 | let moduleOutput = "";
34 | if (mod.wrapper === "none") {
35 | moduleOutput = moduleContents;
36 | }
37 | else if (mod.wrapper === "IIFE" || mod.wrapper === undefined) {
38 | // keep internal modules private unless building for tests
39 | if (buildPath !== testBuildPath) moduleOutput = "const ";
40 | moduleOutput += `${mod.name} = (function(){\n${moduleContents}\n})();`;
41 | }
42 | else {
43 | console.error(`No such wrapper type: ${mod.wrapper} for module: ${mod.name}`);
44 | moduleOutput = `// OMITTED MODULE ${mod.name} DUE TO ERROR`;
45 | }
46 | fs.appendFile(buildPath, moduleOutput + "\n", () => {});
47 | }
48 | fs.appendFile(buildPath, "return ensemble;\n})();", () => {});
49 | }
50 |
--------------------------------------------------------------------------------
/docs/toolscreenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/docs/toolscreenshot.png
--------------------------------------------------------------------------------
/ensemble/Volition.js:
--------------------------------------------------------------------------------
1 | /*global console, define */
2 | /*jshint sub:true*/
3 | /*
4 | * This is the class Volition, for caching and accessing calculated volitions for characters in ensemble, using an Iterator pattern.
5 | *
6 | * Basic usage of this module: store a calculated volition using the saveVolitions function
7 | *
8 | * The internal format for a volitions objects should be structured like this:
9 | * {
10 | "Simon": {
11 | "Monica": [
12 | { "category": "network", "type": "buddy", "intentType": true, "weight": 20 },
13 | { "category": "relationship", "type": "involved with", "intentType": true, "weight": 19 }
14 | ]
15 | },
16 | "Monica": {
17 | "Simon": [
18 | { "category": "network", "type": "romance", "intentType": false, "weight": 12 }
19 | ]
20 | }
21 | }
22 | *
23 | * Public methods are:
24 | *
25 | * calculateVolition
26 | * runTriggerRules
27 | *
28 | * @class volition
29 | * @private
30 | */
31 | var volitionCache = {};
32 | var cachePositions = {};
33 |
34 | /**
35 | * Get the highest-weighted volition in a given set, for a particular pair of characters, or return undefined if no such volition can be found.
36 | *
37 | * @param {String} key The identifier for a volition set.
38 | * @param {String} from Identifier for the "from" character.
39 | * @param {String} to Identifier for the "to" character.
40 | *
41 | * @return {Object} A volition predicate, with keys "category", "network", "type", "intentType", and "weight". (Or undefined if there are no volotions for this pair of characters.)
42 | */
43 | var getFirstVolition = function(key, from, to) {
44 |
45 | // Check that we have volitions to return.
46 | var vSet = volitionCache[key];
47 | if (vSet === undefined) {
48 | console.log("No matching volition set found with key '" + key + "'.");
49 | return undefined;
50 | }
51 | if (vSet[from] === undefined || vSet[from][to] === undefined) {
52 | console.log("No matching volitions found in set '" + key + "' from '" + from + "' to '" + to + "'.");
53 | return undefined;
54 | }
55 |
56 | // Set the cache position for this pair of characters to 0.
57 | var cachePositionsKey = key + from + to;
58 | cachePositions[cachePositionsKey] = 0;
59 |
60 | // Return the volition at the first position (highest weighted).
61 | return vSet[from][to][0];
62 |
63 | };
64 |
65 | /**
66 | * Get the next-highest-weighted volition in a given set, for a particular pair of characters, or return undefined if no such volition can be found. If this function on a set for the first time, it acts the same as getFirstVolition. Note that iteration is by a particular pair of characters; calling the function for a different pair of characters will start at getFirst for that pair.
67 | *
68 | * @param {String} key The identifier for a volition set.
69 | * @param {String} from Identifier for the "from" character.
70 | * @param {String} to Identifier for the "to" character.
71 | *
72 | * TODO: It would be nice to have functionality to get a specified intent (e.g. 'what is the volition for Simon to startDating Monica?')
73 | *
74 | * @return {Object} A volition predicate, with keys "category", "network", "type", "intentType", and "weight". (Or undefined if there are no more volitions for this pair of characters.)
75 | */
76 | var getNextVolition = function(key, from, to) {
77 |
78 | var cachePositionsKey = key + from + to;
79 | var vSet = volitionCache[key];
80 | var pos = cachePositions[cachePositionsKey];
81 |
82 | // If we have no cached position, act like getFirstVolition.
83 | if (pos === undefined) {
84 | return getFirstVolition(key, from, to);
85 | }
86 |
87 | // If we are out of volitions, return undefined
88 | if (vSet[from][to][pos+1] === undefined) {
89 | return undefined;
90 | }
91 |
92 | // Advance the cache position and return the next volition.
93 | cachePositions[cachePositionsKey] += 1;
94 | pos = cachePositions[cachePositionsKey];
95 | return vSet[from][to][pos];
96 |
97 | };
98 |
99 | /** Given a set of pre-computed volitions, returns an object with a boolean and an array of reasons why (i.e. b/c their weight is >= 0).
100 | *
101 | * @method isAccepted
102 | * @memberof Volition
103 | * @param {String} key The string that serves as an index to look up volitions in the volitionCache
104 | * @param {String} initiator The first person in the predicate attempted the intent predicate
105 | * @param {String} responder The second person in the predicate
106 | * @param {Object} predicate Predicate intent object to try to match from the predicate intents in the volitionCache
107 | * @return {Object} returnObject an object with the keys:
108 | * {Boolean} accepted - whether the intent is accepted
109 | * {Array} reasonsWhy - the array of volition predicates that are the reason(s) something was accepted
110 | */
111 | var isAccepted = function(key, initiator, responder, predicate) {
112 | var acceptIfNoMatch = true; // If no matching rules affect the decision, should the character accept or reject the game?
113 | var minimumWeightForAccept = 0;
114 |
115 | var returnObject = {};
116 | returnObject.accepted = acceptIfNoMatch;
117 | returnObject.reasonsWhy = [];
118 |
119 | var thisV = getFirstVolition(key, responder, initiator);
120 | while (thisV !== undefined) {
121 | if (thisV["category"] === predicate["category"] &&
122 | thisV["type"] === predicate["type"] &&
123 | thisV["intentType"] === predicate["intentType"]) {
124 | returnObject.weight = thisV.weight;
125 | if (thisV.weight < minimumWeightForAccept) {
126 | returnObject.reasonsWhy.push(thisV);
127 | returnObject.accepted = false;
128 | return returnObject;
129 | }
130 | else {
131 | returnObject.reasonsWhy.push(thisV);
132 | returnObject.accepted = true;
133 | return returnObject;
134 | }
135 | }
136 | thisV = getNextVolition(key, responder, initiator);
137 | }
138 |
139 | return returnObject;
140 | };
141 |
142 | /**
143 | * Take a set of calculated volitions, sort it, and store it in the internal cache. Return an interface that allows for iterating through its results.
144 | *
145 | * @param {String} key An identifier for this volition set.
146 | * @param {Object} volitions [description]
147 | *
148 | * @return {Object} An interface with functions "getFirst" and "getNext" to iterate through the volitions for particular pair of characters.
149 | */
150 | var register = function(key, volitions) {
151 |
152 | // Sort the passed-in volitions.
153 | //
154 | // Very simple function used by _.sortBy below to know how to order
155 | // the volition objects for a character set.
156 | var vSort = function(obj) {
157 | return -1 * obj.weight; // -1* since sort works in asending
158 | };
159 |
160 | // Each character pair in calculatedVolitions now needs to be sorted
161 | // in weight order. Use underscore sortBy on the weight key.
162 | var cast = _.keys(volitions);
163 | var castLength = cast.length;
164 | for (var first = 0; first < castLength; first++) {
165 | for (var second = 0; second < castLength; second++) {
166 | if (second === first) {
167 | //For 'undirected' volitions, we want people to be able to direct volitions towards themselves.
168 | //continue;
169 | }
170 |
171 | volitions[cast[first]][cast[second]] = _.sortBy(volitions[cast[first]][cast[second]], vSort);
172 | }
173 | }
174 |
175 | // Store the sorted volition object in our internal cache.
176 | volitionCache[key] = volitions;
177 |
178 | // Return an interface using currying to pre-fill the value
179 | // of key to the volition set in question.
180 | return {
181 | getFirst: function(first, second) {
182 | return getFirstVolition(key, first, second);
183 | },
184 | getNext: function(first, second) {
185 | return getNextVolition(key, first, second);
186 | },
187 | getWeight: function(first, second, predicate) {
188 | var tempPredicates = volitionCache[key][first][second];
189 | var checkNextPredicate = false;
190 | for (var i = 0 ; i < tempPredicates.length ; i += 1) {
191 | for (var key in predicate) {
192 | if (predicate[key] !== tempPredicates[key]) {
193 | checkNextPredicate = true;
194 | break;
195 | }
196 | }
197 | if(checkNextPredicate !== true) {
198 | return tempPredicates[i].weight;
199 | }
200 | }
201 | return 0; // our default value
202 | },
203 | dump: function() { // for testing
204 | return volitionCache[key];
205 | },
206 | isAccepted: function(initiator, responder, predicate) {
207 | return isAccepted(key, initiator, responder, predicate);
208 | }
209 | };
210 | };
211 |
212 | /**
213 | * Return a volitions object prepared to have a blank array for every obj[first][second] pair of cast members.
214 | *
215 | * @param {Array of Strings} cast Cast members to prepare the object with.
216 | *
217 | * @return {Object} Prepared volitions object.
218 | */
219 | var newSet = function(cast) {
220 | var volitionShell = {};
221 | if (cast === undefined) return volitionShell;
222 | for (var i = 0; i < cast.length; i++) {
223 | volitionShell[cast[i]] = {};
224 | for (var j = 0; j < cast.length; j++) {
225 | if (i === j) {
226 | //We want the i === j case to be represented, as a means of characters having undirected volitions (e.g., a character wants to boost their own intelligence).
227 | //continue;
228 | }
229 | volitionShell[cast[i]][cast[j]] = [];
230 | }
231 | }
232 | return volitionShell;
233 | };
234 |
235 | /**
236 | * @function getVolitionCacheByKey
237 | * @memberof Volition
238 | * @description Given a key, return the contents of the voitionCache at that point
239 | * @private
240 | * @param {[string]} key [The identifier of a volition set.]
241 | * @return {[type]} [The volitions of the specified key.]
242 | */
243 | var getVolitionCacheByKey = function(key){
244 | return volitionCache[key];
245 | };
246 |
247 | /**
248 | * @functiongetAllVolitionsByKeyFromTo
249 | * @private
250 | * @memberof Volition
251 | * @param {[string]} key [The idenfifier of a volition set]
252 | * @param {[string]} from [The 'initiator' that these volitions pertain to]
253 | * @param {[string]} to [The 'responder' that these volitions pertain to]
254 | * @return {[type]} [The volitions from the volition set specified by key that describe what the 'from' character wants to do with the 'to' character]
255 | */
256 | var getAllVolitionsByKeyFromTo = function(key, from, to){
257 | return volitionCache[key][from][to];
258 | };
259 |
260 | var volitionInterface = {
261 | newSet: newSet,
262 | register: register,
263 | };
264 |
265 | /* test-code */
266 | volitionInterface.getVolitionCacheByKey = getVolitionCacheByKey;
267 | volitionInterface.getAllVolitionsByKeyFromTo = getAllVolitionsByKeyFromTo;
268 | volitionInterface.isAccepted = isAccepted;
269 | /* end-test-code */
270 |
271 | return volitionInterface;
272 |
--------------------------------------------------------------------------------
/ensembletool/README.md:
--------------------------------------------------------------------------------
1 | # Ensemble Authoring Tool
2 |
3 | The Ensemble Authoring Tool can be built as a standalone app for Mac/Windows/Linux (via Node) with:
4 |
5 | grunt build
6 |
7 | It can also be run in a web browser for testing, but to do this you'll need a web server running on your computer for file i/o. On Mac OS, if you navigate to the main ensemble folder (one folder above "ensembletool", you can type this at a command prompt to start a server based in that directory:
8 |
9 | python -m SimpleHTTPServer
10 |
11 | You then need to open a web browser pointing at the right spot:
12 |
13 | http://localhost:8000/ensembletool/
14 |
--------------------------------------------------------------------------------
/ensembletool/csslib/images/animated-overlay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/animated-overlay.gif
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_diagonals-thick_18_b81900_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_diagonals-thick_18_b81900_40x40.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_diagonals-thick_20_666666_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_diagonals-thick_20_666666_40x40.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_flat_10_000000_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_flat_10_000000_40x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_100_f6f6f6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_100_f6f6f6_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_100_fdf5ce_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_100_fdf5ce_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_gloss-wave_35_f6a828_500x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_gloss-wave_35_f6a828_500x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_highlight-soft_100_eeeeee_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-bg_highlight-soft_75_ffe45c_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_228ef1_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_228ef1_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_ef8c08_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_ef8c08_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_ffd27a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_ffd27a_256x240.png
--------------------------------------------------------------------------------
/ensembletool/csslib/images/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ensemble-engine/ensemble/8b74bdec4ba2ef4e14795b7591df3b5d73f283e3/ensembletool/csslib/images/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/ensembletool/defaultdata/actions.json:
--------------------------------------------------------------------------------
1 | {
2 | "fileName" : "consoleDefaultActions.json",
3 | "actions" : [
4 | {
5 | "name" : "STARTDATING",
6 | "intent" : {
7 | "category" : "relationship",
8 | "type" : "involved with",
9 | "intentType" : true,
10 | "first" : "initiator",
11 | "second" : "responder"
12 | },
13 | "conditions" : [],
14 | "influenceRules" : [],
15 | "leadsTo" : ["ASKOUT", "PICKUPLINE"]
16 | },
17 | {
18 | "name" : "ASKOUT",
19 | "conditions" : [],
20 | "influenceRules" : [],
21 | "leadsTo" : ["askoutTerminal", "askoutTerminalReject"]
22 | },
23 | {
24 | "name" : "PICKUPLINE",
25 | "conditions" : [],
26 | "influenceRules" : [
27 | {
28 | "name": "Happy people are more inclined to do pickuplines.",
29 | "conditions": [
30 | {
31 | "category" : "status",
32 | "type" : "happy",
33 | "first" : "initiator",
34 | "value" : true
35 | }
36 | ],
37 | "weight" : 542
38 | }
39 | ],
40 | "leadsTo" : ["pickupLineTerminal"]
41 | },
42 | {
43 | "name" : "askoutTerminal",
44 | "conditions" : [],
45 | "influenceRules" : [],
46 | "effects" : [{
47 | "category" : "relationship",
48 | "type" : "involved with",
49 | "first" : "initiator",
50 | "second" : "responder",
51 | "value" : true
52 | }],
53 | "isAccept" : true
54 | },
55 | {
56 | "name" : "askoutTerminalReject",
57 | "conditions" : [],
58 | "influenceRules" : [],
59 | "effects" : [{
60 | "category" : "relationship",
61 | "type" : "involved with",
62 | "first" : "initiator",
63 | "second" : "responder",
64 | "value" : false
65 | }],
66 | "isAccept" : false
67 | },
68 | {
69 | "name" : "pickupLineTerminal",
70 | "conditions" : [],
71 | "influenceRules" : [],
72 | "effects" : [{
73 | "category" : "relationship",
74 | "type" : "involved with",
75 | "first" : "initiator",
76 | "second" : "responder",
77 | "value" : true
78 | }],
79 | "isAccept" : true
80 | },
81 | {
82 | "name" : "STARTFRIENDS",
83 | "conditions" : [],
84 | "influenceRules" : [],
85 | "intent" : {
86 | "category" : "relationship",
87 | "type" : "friends",
88 | "intentType" : true,
89 | "first" : "initiator",
90 | "second" : "responder"
91 | },
92 | "leadsTo" : ["BOND", "LAUGH"]
93 | },
94 | {
95 | "name" : "BOND",
96 | "conditions" : [],
97 | "influenceRules" : [],
98 | "leadsTo" : ["bondTerminal"]
99 | },
100 | {
101 | "name" : "LAUGH",
102 | "conditions" : [],
103 | "influenceRules" : [],
104 | "leadsTo" : ["laughTerminal1", "laughTerminal2"]
105 | },
106 | {
107 | "name" : "bondTerminal",
108 | "conditions" : [],
109 | "influenceRules" : [],
110 | "effects" : [{
111 | "category" : "relationship",
112 | "type" : "friends",
113 | "first" : "initiator",
114 | "second" : "responder",
115 | "value" : true
116 | }],
117 | "isAccept" : true
118 | },
119 | {
120 | "name" : "laughTerminal1",
121 | "conditions" : [],
122 | "influenceRules" : [],
123 | "effects" : [{
124 | "category" : "relationship",
125 | "type" : "friends",
126 | "first" : "initiator",
127 | "second" : "responder",
128 | "value" : true
129 | }],
130 | "isAccept" : true
131 | },
132 | {
133 | "name" : "laughTerminal2",
134 | "conditions" : [],
135 | "influenceRules" : [
136 | {
137 | "name": "lucky people are a little less inclined to do a laughTerminal2.",
138 | "conditions": [
139 | {
140 | "category" : "trait",
141 | "type" : "lucky",
142 | "first" : "initiator",
143 | "value" : true
144 | }
145 | ],
146 | "weight" : 2
147 | }
148 |
149 | ],
150 | "effects" : [{
151 | "category" : "relationship",
152 | "type" : "friends",
153 | "first" : "initiator",
154 | "second" : "responder",
155 | "value" : true
156 | }],
157 | "isAccept" : true
158 | }
159 | ]
160 | }
161 |
--------------------------------------------------------------------------------
/ensembletool/defaultdata/cast.json:
--------------------------------------------------------------------------------
1 | {
2 | "cast": {
3 | "al": {
4 | "name": "Al"
5 | },
6 | "bob": {
7 | "name": "Bob"
8 | },
9 | "carla": {
10 | "name": "Carla"
11 | },
12 | "diane": {
13 | "name": "Diane"
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ensembletool/defaultdata/history.json:
--------------------------------------------------------------------------------
1 | {
2 | "history": [{
3 | "pos": 0,
4 | "data": [
5 | {
6 | "category": "relationship",
7 | "type": "involved with",
8 | "first": "al",
9 | "second": "bob",
10 | "value": true
11 | },{
12 | "category": "network",
13 | "type": "affinity",
14 | "first": "al",
15 | "second": "bob",
16 | "value": 75
17 | },{
18 | "category": "network",
19 | "type": "affinity",
20 | "first": "bob",
21 | "second": "al",
22 | "value": 90
23 | },{
24 | "category": "status",
25 | "type": "happy",
26 | "first": "bob",
27 | "value": true
28 | },{
29 | "category": "status",
30 | "type": "injured",
31 | "first": "diane",
32 | "value": true
33 | },{
34 | "category": "directedStatus",
35 | "type": "attracted to",
36 | "first": "al",
37 | "second": "diane",
38 | "value": true
39 | }
40 | ]}, {
41 | "pos": 1,
42 | "data": [
43 | {
44 | "category": "relationship",
45 | "type": "involved with",
46 | "first": "bob",
47 | "second": "al",
48 | "value": false
49 | },{
50 | "category": "status",
51 | "type": "happy",
52 | "first": "bob",
53 | "value": false
54 | },{
55 | "category": "directedStatus",
56 | "type": "upset with",
57 | "first": "bob",
58 | "second": "al",
59 | "value": true
60 | }
61 | ]}, {
62 | "pos": 2,
63 | "data": [
64 | {
65 | "category": "status",
66 | "type": "lonely",
67 | "first": "al",
68 | "value": true
69 | },{
70 | "category": "relationship",
71 | "type": "friends",
72 | "first": "bob",
73 | "second": "al",
74 | "value": true
75 | },{
76 | "category": "relationship",
77 | "type": "friends",
78 | "first": "diane",
79 | "second": "al",
80 | "value": true
81 | },{
82 | "category": "network",
83 | "type": "affinity",
84 | "first": "diane",
85 | "second": "bob",
86 | "value": 50
87 | },{
88 | "category": "network",
89 | "type": "affinity",
90 | "first": "bob",
91 | "second": "diane",
92 | "value": 80
93 | },{
94 | "category": "directedStatus",
95 | "type": "upset with",
96 | "first": "bob",
97 | "second": "al",
98 | "value": false
99 | }
100 | ]}
101 | ]
102 | }
103 |
--------------------------------------------------------------------------------
/ensembletool/defaultdata/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": [
3 | {
4 | "category": "status",
5 | "isBoolean": true,
6 | "directionType": "undirected",
7 | "types": ["grieving", "happy", "lonely", "sad", "injured", "injured", "fatigued", "dead", "exhausted", "recovering", "resting", "expelled"],
8 | "duration": 6,
9 | "defaultValue": false,
10 | "actionable": false
11 | },
12 | {
13 | "category": "network",
14 | "isBoolean": false,
15 | "directionType": "directed",
16 | "types": ["affinity", "trust"],
17 | "defaultValue": 50,
18 | "minValue": 0,
19 | "maxValue": 100,
20 | "actionable": true
21 | },
22 | {
23 | "category": "relationship",
24 | "isBoolean": true,
25 | "directionType": "reciprocal",
26 | "types": ["friends", "involved with", "comrades"],
27 | "defaultValue": false,
28 | "actionable": true
29 | },
30 | {
31 | "category": "directedStatus",
32 | "isBoolean": true,
33 | "directionType": "directed",
34 | "types": ["attracted to", "worried about", "upset with", "hates"],
35 | "duration": 20,
36 | "defaultValue": false,
37 | "actionable": false
38 | },
39 | {
40 | "category": "trait",
41 | "isBoolean": true,
42 | "directionType": "undirected",
43 | "types": ["liked movies", "liked sports", "liked music", "has a great smile", "jealous", "trusting", "has a kind face"],
44 | "defaultValue": false,
45 | "actionable": false
46 | },
47 | {
48 | "category": "socialRecordLabel",
49 | "types": ["romanticfailure", "romantic advance", "embarrassing", "newlabel"],
50 | "isBoolean": true,
51 | "directionType": "directed",
52 | "defaultValue": false,
53 | "actionable": false,
54 | "duration": 0
55 | }
56 | ]
57 | }
58 |
--------------------------------------------------------------------------------
/ensembletool/defaultdata/triggerRules.json:
--------------------------------------------------------------------------------
1 | {
2 | "fileName" : "testTriggerRules",
3 | "type": "trigger",
4 | "rules": [
5 | {
6 | "name": "If I'm jealous and someone hits on my sweetie, I hate them A LOT.",
7 | "conditions": [
8 | {
9 | "category": "relationship",
10 | "type": "involved with",
11 | "first": "x",
12 | "second": "y"
13 | },{
14 | "category": "trait",
15 | "type": "jealous",
16 | "first": "x"
17 | },{
18 | "category": "socialRecordLabel",
19 | "type": "romantic advance",
20 | "first": "z",
21 | "second": "y"
22 | }
23 | ],
24 | "effects": [
25 | {
26 | "category": "directedStatus",
27 | "type": "hates",
28 | "first": "x",
29 | "second": "z",
30 | "value": true
31 | }
32 | ]
33 | },
34 | {
35 | "name": "If your sweetie is injured, you worry about them.",
36 | "conditions": [
37 | {
38 | "category": "status",
39 | "type": "injured",
40 | "first": "y"
41 | },{
42 | "category": "relationship",
43 | "type": "involved with",
44 | "first": "x",
45 | "second": "y"
46 | }
47 | ],
48 | "effects": [
49 | {
50 | "category": "directedStatus",
51 | "type": "worried about",
52 | "first": "x",
53 | "second": "y",
54 | "value": true
55 | }
56 | ]
57 | },
58 | {
59 | "name": "Someone with two friends is no longer lonely.",
60 | "conditions": [
61 | {
62 | "category": "status",
63 | "type": "lonely",
64 | "first": "x"
65 | },{
66 | "category": "relationship",
67 | "type": "friends",
68 | "first": "x",
69 | "second": "y"
70 | },{
71 | "category": "relationship",
72 | "type": "friends",
73 | "first": "x",
74 | "second": "z"
75 | }
76 | ],
77 | "effects": [
78 | {
79 | "category": "status",
80 | "type": "lonely",
81 | "first": "x",
82 | "value": false
83 | }
84 | ]
85 | },
86 | {
87 | "name": "If worried and no longer dating, remove status.",
88 | "conditions": [
89 | {
90 | "category": "relationship",
91 | "type": "involved with",
92 | "first": "x",
93 | "second": "y",
94 | "value": true,
95 | "order": 0,
96 | "turnsAgoBetween": ["NOW", 3]
97 | },
98 | {
99 | "category": "relationship",
100 | "type": "involved with",
101 | "first": "x",
102 | "second": "y",
103 | "value": false,
104 | "order": 1,
105 | "turnsAgoBetween": ["NOW", 3]
106 |
107 | },
108 | {
109 | "category": "directedStatus",
110 | "type": "worried about",
111 | "first": "x",
112 | "second": "y",
113 | "value": true
114 | }
115 | ],
116 | "effects": [
117 | {
118 | "category": "directedStatus",
119 | "type": "worried about",
120 | "first": "x",
121 | "second": "y",
122 | "value": false
123 | }
124 | ]
125 | }
126 | ],
127 | "inactiveRules": [
128 | {
129 | "name": "If someone starts dating my ex, I stop being friends with them.",
130 | "conditions": [
131 | {
132 | "category": "relationship",
133 | "type": "involved with",
134 | "first": "x",
135 | "second": "y",
136 | "turnsAgoBetween": [1, 100]
137 | },
138 | {
139 | "category": "relationship",
140 | "type": "involved with",
141 | "first": "x",
142 | "second": "y",
143 | "value": false
144 | },
145 | {
146 | "category": "relationship",
147 | "type": "involved with",
148 | "first": "y",
149 | "second": "z",
150 | "value": true
151 | },
152 | {
153 | "category": "relationship",
154 | "type": "friends",
155 | "first": "x",
156 | "second": "z"
157 | }
158 | ],
159 | "effects": [
160 | {
161 | "category": "relationship",
162 | "type": "friends",
163 | "first": "x",
164 | "second": "z",
165 | "value": false
166 | }
167 | ]
168 | }
169 | ]
170 |
171 | }
--------------------------------------------------------------------------------
/ensembletool/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Ensemble Tool
6 |
7 |
8 |
9 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 | Ensemble Tool
43 |
44 |
45 |
52 |
53 |
54 |
Commands: set •
55 | unset •
56 | volitions •
57 | next •
58 | show •
59 | actions •
60 | doAction
61 |
62 |
63 |
64 |
65 |
66 |
67 | Command:
68 |
69 |
70 |
71 |
72 |
Social Record History
73 |
74 |
Timestep
75 |
76 |
77 |
78 |
Green indicates new value this timestep.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | Filter Rules:
88 |
Showing only rules that match ""
89 |
90 |
94 |
95 |
Trigger Rules
96 |
97 |
98 |
99 |
Volition Rules
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
No Rule Loaded.
109 |
110 |
111 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
Active Schema
157 |
158 |
159 |
160 |
161 |
162 |
163 |
Actions
164 |
165 |
166 |
167 |
168 |
Characters
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
--------------------------------------------------------------------------------
/ensembletool/js/actionEditor.js:
--------------------------------------------------------------------------------
1 | /*
2 | Handles the ability to edit actions. Presents each "actionable" intent twice for each type (for "start dating" / "stop dating")
3 | And for each of those, offers a starter "isAccept" and "isReject" answer.
4 | */
5 |
6 | actionEditor = (function(){
7 |
8 |
9 | var intentDisplay = $("#typesTabs");
10 | var authoringArea = $("#authoringArea");
11 | var listOfActionsArea = $("#listOfActionsDiv");
12 | var actionEditorArea = $("#tabsActionEditor");
13 |
14 | var init = function() {
15 | // Setup interface buttons.
16 | var socialStructure = ensemble.getSocialStructure();
17 | console.log("Here is the social structure FROM INIT: " , socialStructure);
18 |
19 | //NOTE: WE PROBABLY WANT TO MOVE THE CONTENTS OF REFRESH INTO INIT;
20 | //REFRESH IS AN ARTIFACT OF AN INITIAL ATTEMPT THAT USED TO CALL
21 | //actionEditor.init() IN THE WRONG PLACE.
22 | refresh();
23 | intentDisplay.tabs(
24 | {activate: function( event, ui ) {
25 | console.log("hi you clicked me!")
26 | }}).addClass( "ui-tabs-vertical ui-helper-clearfix" );
27 |
28 |
29 | $("button#intentAreaButton").click(intentAreaButtonClick);
30 | $("button#authoringAreaButton").click(authoringareaButtonClick);
31 |
32 |
33 |
34 |
35 | //intentTypeList.append("Start Dating");
36 | //intentTypeList.append("Stop Dating")
37 | /*
38 | intentDisplay.append("");
42 | */
43 |
44 | }
45 |
46 | var intentAreaButtonClick = function() {
47 | console.log("INTENT AREA CLICK!")
48 | var socialStructure = ensemble.getSocialStructure();
49 | console.log("Umm.. maybe this has made the socialStructure better? " , socialStructure);
50 | console.log("Um, I think this is what was clicked?" , event.target.parentElement.id);
51 | console.log("Uh, what about event? " , event);
52 | /*
53 | if (interfaceTimestep >= socialRecord.getCurrentTimeStep()) {
54 | return;
55 | }
56 | interfaceTimestep += 1;
57 | refresh();
58 | */
59 | };
60 |
61 | var authoringareaButtonClick = function() {
62 | console.log("AUTHORING AREA CLICK!")
63 | var socialStructure = ensemble.getSocialStructure();
64 | console.log("Umm.. maybe this has made the socialStructure better? " , socialStructure);
65 | /*
66 | if (interfaceTimestep <= 0) {
67 | return;
68 | }
69 | interfaceTimestep -= 1;
70 | refresh();
71 | */
72 | };
73 |
74 |
75 | var refresh = function() {
76 |
77 | console.log("hello! You just clicked the action editor tab! ")
78 | var socialStructure = ensemble.getSocialStructure();
79 | console.log("Umm.. maybe this has made the socialStructure better? " , socialStructure);
80 |
81 | for(var categoryKey in socialStructure){
82 | var category = socialStructure[categoryKey];
83 | console.log("A CATEGORY: " , categoryKey)
84 | console.log("Here's a category " , category)
85 | for (var typeKey in category){
86 | console.log("A TYPE: " , typeKey)
87 | var type = category[typeKey]
88 | console.log("Here's a type" , type)
89 | var noWhiteSpaceTypeKey = typeKey.replace(/\s/g,'')
90 | var buttonID = "actionEditorButton-"+noWhiteSpaceTypeKey;
91 | console.log("Here is a button id? " + buttonID)
92 | listOfActionsArea.append("");
93 | //listOfActionsArea.append("