initial commit
This commit is contained in:
commit
bbfa2addc9
30
causality.txt
Normal file
30
causality.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
TIME TRAVEL:
|
||||||
|
actions -- things that the player has explicitly done. They generate nevs, but are not necessarily the only source of them.
|
||||||
|
nev -- narrative event -- a moment in time. nevs contain some text to display to the user to communicate what is happening, some handles with which she may generate actions, and some consequences to the state of the world.
|
||||||
|
|
||||||
|
CHANGING THE PAST:
|
||||||
|
in my game, a nev can be inserted in the past as a result of a later action, in direct violation of causality. I do this because it is interesting.
|
||||||
|
ways we could deal with this:
|
||||||
|
- try to calculate a stable loop to determine whether or not the action is legal
|
||||||
|
- cons: hard for the author to reason about (?), hard to write code to deal with, high time complexity
|
||||||
|
- split the timeline
|
||||||
|
- cons: the player may be able to perform an action which has consequences in the past which will prevent him from performing the action. The player will then see the consequence but not the action.
|
||||||
|
- model this problem as inserting an action at the earlier point to begin with
|
||||||
|
- pros: the system should probably be able to model things this way anyway
|
||||||
|
causality is not violated
|
||||||
|
- cons: maybe somewhat fragile from the author's POV
|
||||||
|
how to specify where the nev goes?
|
||||||
|
UI for undoing should be on the nev following the player's actual action, not the modelled one
|
||||||
|
same problems as timeline splitting, actually -- just giving the author the tool rather than baking it into the engine
|
||||||
|
these are important questions regardless of whether we implement things this way or not though
|
||||||
|
|
||||||
|
OK
|
||||||
|
ACTIONS:
|
||||||
|
- happen in response to nevs!
|
||||||
|
- nevs have [generated?] stable IDs, and appear at most once in the text. (nevs can also be parameterized?)
|
||||||
|
|
||||||
|
MULTIPLE ACTORS:
|
||||||
|
- soooo it makes sense to have multiple actors generating actions! the player-character is merely one such actor, with a simple "AI".
|
||||||
|
- other actors can generate nevs according to other criteria.
|
||||||
|
- so we could model a TimeLord actor which generates a nev in response to the player's future action? No, because the only way to tell if future actions are valid is to simulate the world!
|
||||||
|
- could provide a world-simulating primitive that action validity calls could run
|
144
iffy.js
Normal file
144
iffy.js
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
(function() {
|
||||||
|
var ActorPlayer, Gst, Nev, Story, Wst;
|
||||||
|
/*
|
||||||
|
Iffy - parserless interactive fiction for the web
|
||||||
|
(c)2010 Jeremy Penner
|
||||||
|
*/
|
||||||
|
Wst = function(obj, _arg) {
|
||||||
|
this.gst = _arg;
|
||||||
|
this.prototype = obj;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Wst.prototype.WstNext = function(nev) {
|
||||||
|
var wstNext;
|
||||||
|
wstNext = new Object();
|
||||||
|
wstNext.prototype = this;
|
||||||
|
wstNext.nev = nev;
|
||||||
|
return wstNext;
|
||||||
|
};
|
||||||
|
Wst.prototype.WstPrev = function() {
|
||||||
|
var _ref;
|
||||||
|
return (typeof (_ref = this.prototype.nev) !== "undefined" && _ref !== null) ? this.prototype : null;
|
||||||
|
};
|
||||||
|
Gst = function(_arg, _arg2) {
|
||||||
|
this.jDiv = _arg2;
|
||||||
|
this.story = _arg;
|
||||||
|
this.wstInit = this.story.WstInit(this);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Gst.prototype.Display = function() {
|
||||||
|
var _i, _len, _ref, _result, nev;
|
||||||
|
this.jDiv.append("<div class='title'>\
|
||||||
|
<h1>" + (this.story.jStory.attr('title')) + "</h1>\
|
||||||
|
<h2>" + (this.story.jStory.attr('author')) + "</h2>\
|
||||||
|
</div>");
|
||||||
|
_result = []; _ref = this.RgnevRun();
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
nev = _ref[_i];
|
||||||
|
_result.push((function() {
|
||||||
|
this.jDiv.append($("<div class='nev'/>").append(nev.StHtmlDisplay(this)));
|
||||||
|
return this.jDiv.append($("<div class='nev'/>").append(nev.StHtmlDisplay(this)));
|
||||||
|
}).call(this));
|
||||||
|
}
|
||||||
|
return _result;
|
||||||
|
};
|
||||||
|
Gst.prototype.RgnevRun = function() {
|
||||||
|
var _i, _len, _ref, inev, nevResponse, rgnev, wst;
|
||||||
|
rgnev = [this.story.NevByName("start")];
|
||||||
|
wst = this.wstInit;
|
||||||
|
inev = 0;
|
||||||
|
while (inev < rgnev.length) {
|
||||||
|
_ref = this.story.RgnevResponse(rgnev[inev], wst);
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
nevResponse = _ref[_i];
|
||||||
|
if (nev.FCanRun(this, wst)) {
|
||||||
|
wst = wst.WstNext(nevResponse);
|
||||||
|
nevReponse.RunAction(gst, wst);
|
||||||
|
rgnev.push(nevResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inev++;
|
||||||
|
}
|
||||||
|
return rgnev;
|
||||||
|
};
|
||||||
|
Gst.prototype.FilterStHtml = function(stHtml) {
|
||||||
|
var _i, _len, _ref, _result, actor;
|
||||||
|
_result = []; _ref = this.story.rgactor;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
actor = _ref[_i];
|
||||||
|
_result.push(stHtml = actor.FilterStHtml(stHtml));
|
||||||
|
}
|
||||||
|
return _result;
|
||||||
|
};
|
||||||
|
Nev = function(_arg) {
|
||||||
|
this.jnev = _arg;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Nev.prototype.ID = function() {
|
||||||
|
return this.jnev;
|
||||||
|
};
|
||||||
|
Nev.prototype.FCanRun = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
Nev.prototype.RunAction = function(gst, wst) {};
|
||||||
|
Nev.prototype.StHtmlDisplay = function(gst) {
|
||||||
|
var _i, _len, _ref, dHTML, jdivTmp, stHtml;
|
||||||
|
jdivTmp = $("<div/>");
|
||||||
|
_ref = $(this.jnev).children();
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
dHTML = _ref[_i];
|
||||||
|
jdivTmp.append(document.importNode(dHTML, true));
|
||||||
|
}
|
||||||
|
stHtml = jdivTmp[0].innerHTML;
|
||||||
|
gst.FilterStHtml(stHtml);
|
||||||
|
return stHtml;
|
||||||
|
};
|
||||||
|
ActorPlayer = function(_arg) {
|
||||||
|
this.story = _arg;
|
||||||
|
this.mpnevID_rgaction = {};
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
ActorPlayer.prototype.RgnevResponse = function(nev, wst) {
|
||||||
|
var rgaction;
|
||||||
|
rgaction = this.mpnevID_rgaction[nev.ID()];
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
ActorPlayer.prototype.FilterStHtml = function(stHtml) {
|
||||||
|
return stHtml;
|
||||||
|
};
|
||||||
|
Story = function(_arg) {
|
||||||
|
this.jStory = _arg;
|
||||||
|
this.rgactor = [new ActorPlayer(this)];
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Story.prototype.NevByName = function(stName) {
|
||||||
|
var jNev;
|
||||||
|
jNev = this.jStory.find("[name=" + (stName) + "]");
|
||||||
|
return jNev.length > 0 ? new Nev(jNev[0]) : null;
|
||||||
|
};
|
||||||
|
Story.prototype.RgnevResponse = function(nev, wst) {
|
||||||
|
var _i, _j, _len, _len2, _ref, _ref2, actor, rgnev;
|
||||||
|
rgnev = [];
|
||||||
|
_ref = this.rgactor;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
actor = _ref[_i];
|
||||||
|
_ref2 = actor.RgnevResponse(nev, wst);
|
||||||
|
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
||||||
|
nev = _ref2[_j];
|
||||||
|
rgnev.push(nev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rgnev;
|
||||||
|
};
|
||||||
|
Story.prototype.WstInit = function(gst) {
|
||||||
|
return new Wst({}, gst);
|
||||||
|
};
|
||||||
|
window.PlayStory = function(url, jDiv) {
|
||||||
|
return $.get(url, function(domXml) {
|
||||||
|
var gst, story;
|
||||||
|
story = new Story($("story", domXml));
|
||||||
|
gst = new Gst(story, jDiv);
|
||||||
|
return gst.Display();
|
||||||
|
}, "xml");
|
||||||
|
};
|
||||||
|
}).call(this);
|
15
test.html
Normal file
15
test.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript" src="jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="iffy.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function () {
|
||||||
|
PlayStory("timemachine.xml", $("#story"));
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="story" />
|
||||||
|
</body>
|
||||||
|
</html>
|
47
timemachine.xml
Normal file
47
timemachine.xml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<story title="Richard and Larry Build A Time Machine" author="Jeremy Penner">
|
||||||
|
<nev name="start">
|
||||||
|
<p>"I still can't believe you actually used a [DeLorean]," says Larry.</p>
|
||||||
|
<p>"Hey, if you're going to do a thing, you ought to do it right," says [Richard].</p>
|
||||||
|
</nev>
|
||||||
|
<word name="DeLorean">
|
||||||
|
<description>
|
||||||
|
Larry looks at the DeLorean with astonishment. Richard has done it up to look <i>exactly</i> like the car from
|
||||||
|
<i>Back to the Future</i>.
|
||||||
|
</description>
|
||||||
|
<verb name="Drive">
|
||||||
|
<p>Larry eyes the car. "Give me the keys," he says. "I want to take this baby to 88."</p>
|
||||||
|
<p>"Oh, it doesn't drive anymore," says Richard. "I had to use the engine to power the time machine."</p>
|
||||||
|
</verb>
|
||||||
|
</word>
|
||||||
|
<word name="Richard">
|
||||||
|
<verb name="how" display="What have you done?">
|
||||||
|
<p>"So, run it by me again," says Larry.</p>
|
||||||
|
<p>"I modified this [DeLorean] to send information backwards through time," says [Richard].</p>
|
||||||
|
<p>"Just information. Not matter."</p>
|
||||||
|
<p>"Right."</p>
|
||||||
|
<p>Larry ponders this for a moment. "How... how does that even work?"</p>
|
||||||
|
<p>[Richard] waves his hands around. "Spooky action at a distance," he says.</p>
|
||||||
|
<p>"No, I mean, augh. I mean, what can you practically change about the past with this machine?" says Larry.</p>
|
||||||
|
<p>
|
||||||
|
"Well, so far I've gotten my computer to crash five minutes before I push this [button]," says [Richard], gesturing at one of the
|
||||||
|
controls inside the [DeLorean].
|
||||||
|
</p>
|
||||||
|
</verb>
|
||||||
|
</word>
|
||||||
|
<word name="button">
|
||||||
|
<verb name="Push">
|
||||||
|
<shownev id="button.Push" main="true" /> <!-- after defaults to nevCurrent -->
|
||||||
|
<shownev id="crash" after="start" />
|
||||||
|
<p>Larry reaches for the button and gives it a push.</p>
|
||||||
|
<p>"Nothing happened", says Larry, looking at the [computer].</p>
|
||||||
|
<p>"I <i>told</i> you you were going to push it," says [Richard].</p>
|
||||||
|
<p>Larry opens his mouth to say something, then seems to think better of it.</p>
|
||||||
|
</verb>
|
||||||
|
</word>
|
||||||
|
<nev name="crash">
|
||||||
|
<p>There is a beep as [Richard Richard's] [computer] spontaneously and inexplicably reboots.</p>
|
||||||
|
<p>"Aw, geez, you're going to push the button, aren't you?", whines [Richard].</p>
|
||||||
|
<p>"What? What button?" asks Larry, puzzled.</p>
|
||||||
|
<p>"Never mind," says [Richard].</p>
|
||||||
|
</nev>
|
||||||
|
</story>
|
Loading…
Reference in a new issue