1
0
Fork 0
mirror of https://github.com/Oreolek/raconteur.git synced 2024-05-17 00:08:16 +03:00

Add tools.js

This commit is contained in:
Bruno Dias 2015-04-10 00:48:40 -03:00
parent 24bbe13945
commit d6c0f50cab
4 changed files with 229 additions and 29 deletions

View file

@ -18,7 +18,7 @@ gulp.task('lib', function () {
});
gulp.task('undularity', function () {
return gulp.src('../undularity/undularity.js')
return gulp.src('../undularity/*.js')
.pipe(gulp.dest('./build/lib/'));
});
@ -68,7 +68,7 @@ gulp.task('serve', ['default'], function () {
gulp.watch('../template/less/*.less', ['less']);
gulp.watch('../template/html/*.html', ['html']);
gulp.watch('../undum/lib/*.js', ['browserify']);
gulp.watch('../undularity/undularity.js', ['browserify']);
gulp.watch('../undularity/*.js', ['browserify']);
gulp.watch('../template/js/*.js', ['browserify']);
});

View file

@ -1,6 +1,7 @@
var situation = require('../lib/undularity.js'),
$ = require('jquery'),
undum = require('../lib/undum.js');
undum = require('../lib/undum.js'),
tools = require('../lib/tools.js');
var a = situation.a,
span = situation.span,
@ -42,9 +43,9 @@ situation('markdown-features', {
headers (as above), [external links](http://github.com), and even
preformatted blocks of text:
situation('start', {
content: "This is an example."
});
situation('start', {
content: "This is an example."
});
Additionally, we also support "smart quotes" and -- dashes.`,
tags: ['testing-option'],
@ -56,21 +57,21 @@ situation('special-links', {
# Special Links
Undularity supports various special types of links, starting with
${a.content('writer').class('once').writer('writerlink').tag()} links.
${a('writer').class('once').writer('writerlink')} links.
Also notable are ${a.id('replacer-link').content('replacer').replacer('replacer-link').tag()}
Also notable are ${a('replacer').id('replacer-link').replacer('replacer-link')}
links, which replace the content of a given id.
And finally, we have ${
a.class("once").content('inserter').inserter('inserter-link').tag()
} links, which insert something into a specified element${span.id('inserter-link').tag()}.
And finally, we have ${a('inserter').class("once").inserter('inserter-link')}
links, which insert something into a specified element${span().id('inserter-link')}.
`,
writers: {
writerlink: "Writer links can only be clicked once.",
'replacer-link': "switching",
'inserter-link': "-- like this"
},
tags: ['testing-option']
tags: ['testing-option'],
optionText: 'Special Links'
});
situation('custom-actions', {
@ -79,7 +80,7 @@ situation('custom-actions', {
You can define actions with custom effects that access the underlying
Undum API. Try clicking
${a.content('this link').action('specialaction').tag()} for example.
${a('this link').action('specialaction')} for example.
`,
actions: {
specialaction: function (character, system, from) {
@ -94,6 +95,52 @@ situation('custom-actions', {
optionText: 'Special Actions'
});
situation('randomness', {
content: (character, system, from) =>
`
# Randomness
Randomness in Undum is best if you use Undum's own random number
generator, which ensures consistency across save games. For example,
try saving and reloading to verify that this list of animals remains
in the same order:
${["dog", "cat", "alpaca", "crow"].shuffle(system).join(', ')}.
`,
tags: ['testing-option'],
optionText: 'Randomness'
});
var myIterators = {};
situation('iterators', {
content: (character, system, from) =>
`
# Iterators
Iterators are an useful feature for generating adaptive text. For example,
clicking ${a('this link').writer('iterator')} will output a
new paragraph with a random animal.
Initialising iterators during your init function will make them even more
useful, since it lets you pass the system object on to them to ensure
consistency between saves. For example, ${a('this link')
.writer('consistent')} will produce the same output every
time.
Other iterators allow you to ${a('cycle').writer('cycler')} through
different content in ${a('various ways').writer('stopper')}.
`,
writers: {
iterator: tools.oneOf(['Cat', 'Dog', 'Crow', 'Alpaca']).randomly(),
consistent: () => myIterators.consistentIterator(),
cycler: tools.oneOf(['Spring', 'Summer', 'Fall', 'Winter']).cycling(),
stopper: tools.oneOf(['First click', 'Second click', 'Another click']).stopping()
},
tags: ['testing-option'],
optionText: 'Iterators'
});
qualities({
stats: {
name: 'Statistics',
@ -107,6 +154,9 @@ undum.game.init = function (character, system) {
character.qualities.intelligence = 10;
character.qualities.perception = 10;
character.qualities.size = 1;
myIterators.consistentIterator =
tools.oneOf(['Blue', 'Black', 'Green', 'Red', 'White'])
.inRandomOrder(system);
};
$(function(){undum.begin()});

130
undularity/tools.js Normal file
View file

@ -0,0 +1,130 @@
/*
Undularity Tools
Those functions are not a core part of Undularity, but provide some
general functionality that relates to adaptive text generation.
This is provided partly as a helper to less technical users, and as
a convenience for authors.
*/
/* Monkey patching */
/* Array.prototype.shuffle() */
/*
Shuffles an array. It can use Undum's random number generator implementation,
so it expects a System.rnd object to be passed into it. If one isn't
supplied, it will use Math.Random instead.
This is an implementation of the Fischer-Yates (Knuth) shuffle.
Returns the shuffled array.
*/
Array.prototype.shuffle = function (system) {
var rng = (system) ? system.rnd.random : Math.random;
// slice() clones the array. Object members are copied by reference,
// beware.
var newArr = this.slice();
var m = newArr.length;
while (m) {
let i = Math.floor(rng() * m --);
let t = newArr[m];
newArr[m] = newArr[i];
newArr[i] = t;
}
return newArr;
};
/*
oneOf()
Takes an array and returns an object with several methods. Each method
returns an iterator which iterates over the array in a specific way:
inOrder()
Returns the array items in order.
cycling()
Returns the array items in order, cycling back to the first item when
it runs out.
stopping()
Returns the array items in order, then repeats the last item when it
runs out.
randomly()
Returns the array items at random. Takes a system object, for consistent
randomness. Will never return the same item twice in a row.
trulyAtRandom()
Returns the array items purely at random. Takes a system object, for
consistent randomness.
inRandomOrder()
Returns the array items in a random order. Takes a system object, for
consistent randomness.
*/
var oneOf = function (ary) {
return {
inOrder () {
var i = 0;
return function () {
return ary[i++];
};
},
cycling () {
var i = 0;
return function () {
if (i >= ary.length) i = 0;
return ary[i++];
};
},
stopping () {
var i = 0;
return function () {
if (i >= ary.length) i = ary.length - 1;
return ary[i++];
}
},
randomly (system) {
var rng = (system) ? system.random : Math.random,
last;
return function () {
var i;
do {
i = Math.floor(rng() * ary.length);
} while (i === last);
last = i;
return ary[i];
};
},
trulyAtRandom (system) {
var rng = (system) ? system.random : Math.random;
return function () {
return ary[Math.floor(rng() * ary.length)];
};
},
inRandomOrder (system) {
var shuffled = ary.shuffle(system),
i = 0;
return function () {
return shuffled[i++];
};
}
};
};
exports.oneOf = oneOf;

View file

@ -179,18 +179,28 @@ UndularitySituation.prototype.act = function (character, system, action) {
var responses = {
writer: function (ref) {
if (self.writers[ref] === undefined) {
console.log(self);
throw new Error("Tried to call undefined writer:" + ref);
}
system.write(
markdown.render(
self.writers[ref].fcall(self, character, system, action)
).fade());
},
replacer: function (ref) {
if (self.writers[ref] === undefined) {
throw new Error("Tried to call undefined replacer:" + ref);
}
system.replaceWith(
markdown.renderInline(
self.writers[ref].fcall(self, character, system, action)
).spanWrap().fade(), `#${ref}`);
},
inserter: function (ref) {
if (self.writers[ref] === undefined) {
throw new Error("Tried to call undefined inserter:" + ref);
}
system.writeInto(
markdown.renderInline(
self.writers[ref].fcall(self, character, system, action)
@ -229,11 +239,11 @@ UndularitySituation.prototype.act = function (character, system, action) {
once: The 'once' special link class. A getter.
*/
var elementMonad = function (element) {
var elementHelper = function (element) {
this.element = element;
};
var monadSetterGen = function (prop) {
var elementSetterGen = function (prop) {
return function (value) {
var newMonad = Object.create(this);
newMonad['_' + prop] = value;
@ -241,13 +251,13 @@ var monadSetterGen = function (prop) {
}
}
elementMonad.prototype.class = monadSetterGen("class");
elementMonad.prototype.id = monadSetterGen("id");
elementMonad.prototype.type = monadSetterGen("linkType");
elementMonad.prototype.content = monadSetterGen("content");
elementMonad.prototype.ref = monadSetterGen("ref");
elementMonad.prototype.url = elementMonad.prototype.ref;
elementMonad.prototype.situation = elementMonad.prototype.ref;
elementHelper.prototype.class = elementSetterGen("class");
elementHelper.prototype.id = elementSetterGen("id");
elementHelper.prototype.type = elementSetterGen("linkType");
elementHelper.prototype.content = elementSetterGen("content");
elementHelper.prototype.ref = elementSetterGen("ref");
elementHelper.prototype.url = elementHelper.prototype.ref;
elementHelper.prototype.situation = elementHelper.prototype.ref;
var linkTypeGen = function (type) {
return function (ref) {
@ -255,12 +265,12 @@ var linkTypeGen = function (type) {
}
}
elementMonad.prototype.writer = linkTypeGen("writer");
elementMonad.prototype.replacer = linkTypeGen("replacer");
elementMonad.prototype.inserter = linkTypeGen("inserter");
elementMonad.prototype.action = linkTypeGen("action");
elementHelper.prototype.writer = linkTypeGen("writer");
elementHelper.prototype.replacer = linkTypeGen("replacer");
elementHelper.prototype.inserter = linkTypeGen("inserter");
elementHelper.prototype.action = linkTypeGen("action");
elementMonad.prototype.tag = function () {
elementHelper.prototype.toString = function () {
var classes = "",
classString = "",
idString = "",
@ -300,8 +310,18 @@ elementMonad.prototype.tag = function () {
return `<${this.element}${classString}${idString}${hrefString}>${contentString}</${this.element}>`;
};
var a = Object.freeze(new elementMonad("a"));
var span = Object.freeze(new elementMonad("span"));
var a_proto = Object.freeze(new elementHelper("a"));
var span_proto = Object.freeze(new elementHelper("span"));
var a = function (content) {
if (content) return a_proto.content(content);
return a_proto;
};
var span = function (content) {
if (content) return span_proto.content(content);
return span_proto;
};
/*
Quality definition function