mirror of
https://github.com/Oreolek/gamebookformat.git
synced 2024-06-26 03:41:04 +03:00
Checking generated examples against saved expected outputs.
This commit is contained in:
parent
d99ca50fa2
commit
ca4b8389a8
8
Makefile
8
Makefile
|
@ -35,6 +35,14 @@ uploadto=$(shell cat .uploadto)
|
|||
%.png: %.dot
|
||||
dot -Tpng $< > $@
|
||||
|
||||
expected: all
|
||||
$(RM) expected/* && cp examples/*.{rtf,tex,html,debug,txt,dot,map} \
|
||||
expected
|
||||
|
||||
checkexpected: all
|
||||
diff -r -x "*.aux" -x "*.gamebook" -x "*.log" -x "*.out" -x "*.png" \
|
||||
-x "*.pdf" -x .gitignore -q examples expected
|
||||
|
||||
upload: html png pdf rtf
|
||||
if [ -n "$(uploadto)" ]; then \
|
||||
scp examples/*.html examples/*.png examples/*.pdf examples/*.rtf $(uploadto);\
|
||||
|
|
0
expected/.gitignore
vendored
Normal file
0
expected/.gitignore
vendored
Normal file
17
expected/codewords.debug
Normal file
17
expected/codewords.debug
Normal file
|
@ -0,0 +1,17 @@
|
|||
BEGIN DEBUG OUTPUT
|
||||
Book title: Gamebook
|
||||
Number of sections: 9
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1 (start) - Demonstrating how [COLLECT code]Codewords[/COLLECT] (AKA sightings) can be used. Go to 2.
|
||||
2 (second) - Got codeword [ADD code]warrior[/ADD]. Simple enough to set a codeword. Turn to 5.
|
||||
3 (xortest) - OK, if you have the codeword [HAS code]warrior[/HAS], you may turn to 4 otherwise you may go back to 2. Although we both know you have that codeword. If you have the codeword [HAS code]fun[/HAS] you may turn to 6, without it you can go to 8.
|
||||
4 (the_end) - That was easy.
|
||||
5 (choice) - If you have the codeword [HAS code]warrior[/HAS] you may turn to 4. If you do not have the codeword [HAS NOT code]fun[/HAS NOT], you may turn to 8. If you have the codeword [HAS code]fun[/HAS], you may instead turn to 6. Otherwise see 3.
|
||||
6 (cheater) - Cheater! There is no way you can have codeword fun.
|
||||
7 (noautotest) - If you have the codeword [HAS code]fun[/HAS] turn to ((automatic))6. Otherwise you can go to the end at 4 or to the xortest at 3.
|
||||
8 (notsofun) - This is just to demonstrate choices allowed when not having a codeword. Now go on to 9 (autotest) or 3 (xor test).
|
||||
9 (autotest) - If you have codeword [HAS code]warrior[/HAS] turn to ((automatic))7. Otherwise you can go to the end at 4 or back to 1.
|
||||
END DEBUG OUTPUT
|
33
expected/codewords.dot
Normal file
33
expected/codewords.dot
Normal file
|
@ -0,0 +1,33 @@
|
|||
digraph gamebook {
|
||||
|
||||
|
||||
1->2
|
||||
2->5
|
||||
3->4
|
||||
|
||||
3->2
|
||||
|
||||
3->8
|
||||
|
||||
3->6
|
||||
5->4
|
||||
|
||||
5->6
|
||||
|
||||
5->3
|
||||
|
||||
5->8
|
||||
7->6
|
||||
|
||||
7->3
|
||||
|
||||
7->4
|
||||
8->9
|
||||
|
||||
8->3
|
||||
9->1
|
||||
|
||||
9->7
|
||||
|
||||
9->4
|
||||
}
|
411
expected/codewords.html
Normal file
411
expected/codewords.html
Normal file
|
@ -0,0 +1,411 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Gamebook</title>
|
||||
<script>
|
||||
var gamebook = {
|
||||
'player' : {
|
||||
'started' : false,
|
||||
'currentSection' : null,
|
||||
'collections' : {},
|
||||
|
||||
'collect' : function(type, name) {
|
||||
this.collections[type] = {
|
||||
'name' : name,
|
||||
'contents' : [],
|
||||
'add' : function(what) {
|
||||
if (this.contents.indexOf(what) === -1
|
||||
&& !(what in gamebook.dropped[type])) {
|
||||
this.contents.push(what);
|
||||
this.contents.sort();
|
||||
}
|
||||
},
|
||||
'drop' : function(what) {
|
||||
var i = this.contents.indexOf(what);
|
||||
if (i >= 0) {
|
||||
this.contents.splice(i, 1);
|
||||
gamebook.dropped[type][what] = true;
|
||||
}
|
||||
},
|
||||
'has' : function(what) {
|
||||
return this.contents.indexOf(what) >= 0;
|
||||
}
|
||||
};
|
||||
gamebook.dropped[type] = {};
|
||||
gamebook.addCollectionView(type, name);
|
||||
},
|
||||
|
||||
'add' : function(type, what) {
|
||||
this.collections[type].add(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'drop' : function(type, what) {
|
||||
this.collections[type].drop(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'has' : function(type, what) {
|
||||
return this.collections[type].has(what);
|
||||
}
|
||||
},
|
||||
|
||||
'sections' : {},
|
||||
|
||||
'turnToFunctions' : {},
|
||||
|
||||
'dropped' : {},
|
||||
|
||||
'addSection' : function(nr, element) {
|
||||
var section = {'element' : element, 'nr' : nr};
|
||||
this.sections[nr] = section;
|
||||
},
|
||||
|
||||
'turnTo' : function(nr) {
|
||||
if (!gamebook.player.started) {
|
||||
gamebook.start();
|
||||
}
|
||||
if (!nr in this.sections) {
|
||||
throw new Exception("Can not turn to non-existing section "
|
||||
+ nr + ".");
|
||||
}
|
||||
this.displaySection(nr);
|
||||
},
|
||||
|
||||
'start' : function() {
|
||||
this.hideIntroSections();
|
||||
this.addClassToClass('startlink', 'nodisplay');
|
||||
gamebook.player.started = true;
|
||||
},
|
||||
|
||||
'displaySection' : function(nr) {
|
||||
if (this.player.currentSection) {
|
||||
this.player.currentSection.element.style.display = 'none';
|
||||
}
|
||||
var e = this.sections[nr].element;
|
||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||
e.style.display = 'block';
|
||||
this.player.currentSection = gamebook.sections[nr];
|
||||
},
|
||||
|
||||
'hideIntroSections' : function() {
|
||||
this.addClassToClass('introsection', 'nodisplay');
|
||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||
},
|
||||
|
||||
'showIntroSections' : function() {
|
||||
this.runActionsInIntroSections();
|
||||
this.removeClassFromClass('introsection', 'nodisplay');
|
||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||
document.body.scrollIntoView();
|
||||
},
|
||||
|
||||
'runActionsInIntroSections' : function() {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName('introsectionbody'),
|
||||
gamebook.runActions);
|
||||
},
|
||||
|
||||
'addClassToClass' : function(className, addClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.add(addClass);
|
||||
});
|
||||
},
|
||||
|
||||
'removeClassFromClass' : function(className, removeClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.remove(removeClass);
|
||||
});
|
||||
},
|
||||
|
||||
'runActions' : function(e) {
|
||||
var enableNextLink = true;
|
||||
var hasXorScope = false;
|
||||
var hasAutoScope = false;
|
||||
var xorEnableNext = false;
|
||||
var autoDisableAllRemainingLinks = (
|
||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||
if (!c.classList) {
|
||||
return;
|
||||
}
|
||||
if (c.classList.contains('sectionref')) {
|
||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||
gamebook.enableLink(c);
|
||||
if (hasAutoScope) {
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
} else {
|
||||
gamebook.disableLink(c);
|
||||
}
|
||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||
hasAutoScope = false;
|
||||
hasXorScope = false;
|
||||
} else if (c.classList.contains('collect')) {
|
||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||
} else if (c.classList.contains('add')) {
|
||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('drop')) {
|
||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('has')) {
|
||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('hasnot')) {
|
||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('xor')) {
|
||||
hasXorScope = true;
|
||||
xorEnableNext = !enableNextLink;
|
||||
} else if (c.classList.contains('auto')) {
|
||||
hasAutoScope = true;
|
||||
} else if (c.classList.contains('random')) {
|
||||
c.addEventListener('click',
|
||||
gamebook.enableRandomLinkAfter);
|
||||
c.classList.add("enabledlink");
|
||||
c.classList.remove("disabledlink");
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'enableLink' : function(e) {
|
||||
e.addEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.add("enabledlink");
|
||||
e.classList.remove("disabledlink");
|
||||
},
|
||||
|
||||
'disableLink' : function(e) {
|
||||
e.removeEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.remove("enabledlink");
|
||||
e.classList.add("disabledlink");
|
||||
},
|
||||
|
||||
'enableRandomLinkAfter' : function(event) {
|
||||
this.classList.remove("enabledlink");
|
||||
this.classList.add("disabledlink");
|
||||
var links = [];
|
||||
var e = this.nextSibling;
|
||||
while (e) {
|
||||
if (e.classList && e.classList.contains('sectionref')) {
|
||||
links.push(e);
|
||||
}
|
||||
e = e.nextSibling;
|
||||
}
|
||||
if (links.length > 0) {
|
||||
var selected = links[Math.floor(Math.random()*links.length)]
|
||||
gamebook.enableLink(selected);
|
||||
} else {
|
||||
console.log("Random with nothing to select?");
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'addCollectionView' : function(type, name) {
|
||||
var ce = document.getElementById('collections');
|
||||
var template = document.getElementById('collectionTemplate');
|
||||
var e = template.cloneNode(true);
|
||||
e.className = "collection";
|
||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||
e.dataset.type = type;
|
||||
ce.appendChild(e);
|
||||
},
|
||||
|
||||
'updateCollectionsView' : function() {
|
||||
var ce = document.getElementById('collections');
|
||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||
if (c.className === 'collection') {
|
||||
var type = c.dataset.type;
|
||||
var collection = gamebook.player.collections[type];
|
||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||
cc.innerHTML = collection.contents.join(', ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getTurnToFunction' : function(nr) {
|
||||
if (nr in this.turnToFunctions) {
|
||||
return this.turnToFunctions[nr];
|
||||
} else {
|
||||
var f = function () {
|
||||
gamebook.turnTo(nr);
|
||||
};
|
||||
this.turnToFunctions[nr] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random {
|
||||
font-weight: bold;
|
||||
margin: 0.2em;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionref.enabledlink {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random {
|
||||
cursor: pointer;}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||
.random {background: #eef;
|
||||
}
|
||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||
.hideintrolink:hover {background: #a9f;}
|
||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||
.disabledlink:hover {background: inherit;}
|
||||
.sectionnumber {font-weight: bolder;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;}
|
||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||
.sectiontext {margin-top: 0.5em;}
|
||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||
.collections {margin-top: 4em;}
|
||||
.collection {background: #ddd; margin-top: 1em;}
|
||||
.collectionheading {}
|
||||
.collectionheading::after {content: ": ";}
|
||||
.collectioncontents {}
|
||||
.collect {}
|
||||
.add {font-weight: bold;}
|
||||
.drop {font-style: italic;}
|
||||
.has {font-style: italic;}
|
||||
.hasnot {font-style: italic;}
|
||||
.collectionTemplate {display: none;}
|
||||
.sectionimage {width: 100%; padding: 1em;}
|
||||
.nodisplay {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hideintrolink nodisplay"
|
||||
onclick="gamebook.hideIntroSections()">(hide instructions)</div>
|
||||
<div class="gamebook">
|
||||
|
||||
<div class="startlink"
|
||||
onclick="gamebook.turnTo(1)">Turn to 1 to begin.</div>
|
||||
|
||||
<div class="section" id="section1">
|
||||
<span class="sectionnumber" id="para1">1</span>
|
||||
<div class="sectiontext">
|
||||
Demonstrating how <span class="collect" data-type="code"
|
||||
data-name="Codewords">Codewords</span> (AKA sightings) can be used. Go to <a class="sectionref enabledlink" data-ref="2">2</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(1, document.getElementById('section1'));
|
||||
}
|
||||
</script> <div class="section" id="section2">
|
||||
<span class="sectionnumber" id="para2">2</span>
|
||||
<div class="sectiontext">
|
||||
Got codeword <span class="add" data-type="code"
|
||||
data-what="warrior">warrior</span>. Simple enough to set a codeword. Turn to <a class="sectionref enabledlink" data-ref="5">5</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(2, document.getElementById('section2'));
|
||||
}
|
||||
</script> <div class="section" id="section3">
|
||||
<span class="sectionnumber" id="para3">3</span>
|
||||
<div class="sectiontext">
|
||||
OK, if you have the codeword <span class="has" data-type="code" data-what="warrior">warrior</span>, you may turn to <span class="xor"></span><a class="sectionref enabledlink" data-ref="4">4</a> otherwise you may go back to <a class="sectionref enabledlink" data-ref="2">2</a>. Although we both know you have that codeword. If you have the codeword <span class="has" data-type="code" data-what="fun">fun</span> you may turn to <span class="xor"></span><a class="sectionref enabledlink" data-ref="6">6</a>, without it you can go to <a class="sectionref enabledlink" data-ref="8">8</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(3, document.getElementById('section3'));
|
||||
}
|
||||
</script> <div class="section" id="section4">
|
||||
<span class="sectionnumber" id="para4">4</span>
|
||||
<div class="sectiontext">
|
||||
That was easy.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(4, document.getElementById('section4'));
|
||||
}
|
||||
</script> <div class="section" id="section5">
|
||||
<span class="sectionnumber" id="para5">5</span>
|
||||
<div class="sectiontext">
|
||||
If you have the codeword <span class="has" data-type="code" data-what="warrior">warrior</span> you may turn to <a class="sectionref enabledlink" data-ref="4">4</a>. If you do not have the codeword <span class="hasnot" data-type="code"
|
||||
data-what="fun">fun</span>, you may turn to <a class="sectionref enabledlink" data-ref="8">8</a>. If you have the codeword <span class="has" data-type="code" data-what="fun">fun</span>, you may instead turn to <a class="sectionref enabledlink" data-ref="6">6</a>. Otherwise see <a class="sectionref enabledlink" data-ref="3">3</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(5, document.getElementById('section5'));
|
||||
}
|
||||
</script> <div class="section" id="section6">
|
||||
<span class="sectionnumber" id="para6">6</span>
|
||||
<div class="sectiontext">
|
||||
Cheater! There is no way you can have codeword fun.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(6, document.getElementById('section6'));
|
||||
}
|
||||
</script> <div class="section" id="section7">
|
||||
<span class="sectionnumber" id="para7">7</span>
|
||||
<div class="sectiontext">
|
||||
If you have the codeword <span class="has" data-type="code" data-what="fun">fun</span> turn to <span class="auto"></span><a class="sectionref enabledlink" data-ref="6">6</a>. Otherwise you can go to the end at <a class="sectionref enabledlink" data-ref="4">4</a> or to the xortest at <a class="sectionref enabledlink" data-ref="3">3</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(7, document.getElementById('section7'));
|
||||
}
|
||||
</script> <div class="section" id="section8">
|
||||
<span class="sectionnumber" id="para8">8</span>
|
||||
<div class="sectiontext">
|
||||
This is just to demonstrate choices allowed when not having a codeword. Now go on to <a class="sectionref enabledlink" data-ref="9">9</a> (autotest) or <a class="sectionref enabledlink" data-ref="3">3</a> (xor test).
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(8, document.getElementById('section8'));
|
||||
}
|
||||
</script> <div class="section" id="section9">
|
||||
<span class="sectionnumber" id="para9">9</span>
|
||||
<div class="sectiontext">
|
||||
If you have codeword <span class="has" data-type="code" data-what="warrior">warrior</span> turn to <span class="auto"></span><a class="sectionref enabledlink" data-ref="7">7</a>. Otherwise you can go to the end at <a class="sectionref enabledlink" data-ref="4">4</a> or back to <a class="sectionref enabledlink" data-ref="1">1</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(9, document.getElementById('section9'));
|
||||
}
|
||||
</script> <div id="collections" class="collections">
|
||||
</div>
|
||||
<div id="collectionTemplate" class="collectionTemplate">
|
||||
<span class="collectionheading"></span>
|
||||
<span class="collectioncontents"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.runActionsInIntroSections();
|
||||
}
|
||||
</script>
|
||||
<div class="displayintrolink nodisplay"
|
||||
onclick="gamebook.showIntroSections()">(show instructions)</div>
|
||||
</body>
|
||||
</html>
|
97
expected/codewords.rtf
Normal file
97
expected/codewords.rtf
Normal file
|
@ -0,0 +1,97 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww14140\viewh14860\viewkind0
|
||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\b\fs24 \cf0
|
||||
|
||||
\b \qc Gamebook
|
||||
\b0\
|
||||
|
||||
\b Turn to 1 to begin.
|
||||
\b0\
|
||||
\
|
||||
|
||||
\b \qc 1
|
||||
\b0\
|
||||
\ql Demonstrating how Codewords (AKA sightings) can be used. Go to \b 2
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 2
|
||||
\b0\
|
||||
\ql Got codeword warrior. Simple enough to set a codeword. Turn to \b 5
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 3
|
||||
\b0\
|
||||
\ql OK, if you have the codeword warrior, you may turn to \b 4
|
||||
\b0
|
||||
otherwise you may go back to \b 2
|
||||
\b0
|
||||
. Although we both know you have that codeword. If you have the codeword fun you may turn to \b 6
|
||||
\b0
|
||||
, without it you can go to \b 8
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 4
|
||||
\b0\
|
||||
\ql That was easy. \
|
||||
\
|
||||
|
||||
\b \qc 5
|
||||
\b0\
|
||||
\ql If you have the codeword warrior you may turn to \b 4
|
||||
\b0
|
||||
. If you do not have the codeword fun, you may turn to \b 8
|
||||
\b0
|
||||
. If you have the codeword fun, you may instead turn to \b 6
|
||||
\b0
|
||||
. Otherwise see \b 3
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 6
|
||||
\b0\
|
||||
\ql Cheater! There is no way you can have codeword fun. \
|
||||
\
|
||||
|
||||
\b \qc 7
|
||||
\b0\
|
||||
\ql If you have the codeword fun turn to \b 6
|
||||
\b0
|
||||
. Otherwise you can go to the end at \b 4
|
||||
\b0
|
||||
or to the xortest at \b 3
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 8
|
||||
\b0\
|
||||
\ql This is just to demonstrate choices allowed when not having a codeword. Now go on to \b 9
|
||||
\b0
|
||||
(autotest) or \b 3
|
||||
\b0
|
||||
(xor test). \
|
||||
\
|
||||
|
||||
\b \qc 9
|
||||
\b0\
|
||||
\ql If you have codeword warrior turn to \b 7
|
||||
\b0
|
||||
. Otherwise you can go to the end at \b 4
|
||||
\b0
|
||||
or back to \b 1
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
}
|
112
expected/codewords.tex
Normal file
112
expected/codewords.tex
Normal file
|
@ -0,0 +1,112 @@
|
|||
\documentclass[a5,onecolumn]{book}
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\usepackage[top=3.3cm, bottom=3.3cm, left=2cm, right=2cm]{geometry}
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\ifnum\pdfoutput=1
|
||||
\pdftrue
|
||||
\else
|
||||
\pdffalse
|
||||
\fi
|
||||
\fi
|
||||
|
||||
\title{Gamebook}
|
||||
\author{}
|
||||
\date{}
|
||||
|
||||
\newcounter{sectionnr}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\clearpage
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section1}
|
||||
\subsection*{\begin{center} \textbf{1} \end{center}}
|
||||
|
||||
\noindent
|
||||
Demonstrating how Codewords (AKA sightings) can be used. Go to \textbf{\autoref{section2}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section2}
|
||||
\subsection*{\begin{center} \textbf{2} \end{center}}
|
||||
|
||||
\noindent
|
||||
Got codeword \textbf{warrior}. Simple enough to set a codeword. Turn to \textbf{\autoref{section5}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section3}
|
||||
\subsection*{\begin{center} \textbf{3} \end{center}}
|
||||
|
||||
\noindent
|
||||
OK, if you have the codeword \textit{warrior}, you may turn to \textbf{\autoref{section4}} otherwise you may go back to \textbf{\autoref{section2}}. Although we both know you have that codeword. If you have the codeword \textit{fun} you may turn to \textbf{\autoref{section6}}, without it you can go to \textbf{\autoref{section8}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section4}
|
||||
\subsection*{\begin{center} \textbf{4} \end{center}}
|
||||
|
||||
\noindent
|
||||
That was easy.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section5}
|
||||
\subsection*{\begin{center} \textbf{5} \end{center}}
|
||||
|
||||
\noindent
|
||||
If you have the codeword \textit{warrior} you may turn to \textbf{\autoref{section4}}. If you do not have the codeword \textit{fun}, you may turn to \textbf{\autoref{section8}}. If you have the codeword \textit{fun}, you may instead turn to \textbf{\autoref{section6}}. Otherwise see \textbf{\autoref{section3}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section6}
|
||||
\subsection*{\begin{center} \textbf{6} \end{center}}
|
||||
|
||||
\noindent
|
||||
Cheater! There is no way you can have codeword fun.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section7}
|
||||
\subsection*{\begin{center} \textbf{7} \end{center}}
|
||||
|
||||
\noindent
|
||||
If you have the codeword \textit{fun} turn to \textbf{\autoref{section6}}. Otherwise you can go to the end at \textbf{\autoref{section4}} or to the xortest at \textbf{\autoref{section3}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section8}
|
||||
\subsection*{\begin{center} \textbf{8} \end{center}}
|
||||
|
||||
\noindent
|
||||
This is just to demonstrate choices allowed when not having a codeword. Now go on to \textbf{\autoref{section9}} (autotest) or \textbf{\autoref{section3}} (xor test).
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section9}
|
||||
\subsection*{\begin{center} \textbf{9} \end{center}}
|
||||
|
||||
\noindent
|
||||
If you have codeword \textit{warrior} turn to \textbf{\autoref{section7}}. Otherwise you can go to the end at \textbf{\autoref{section4}} or back to \textbf{\autoref{section1}}.
|
||||
\vspace{1em}
|
||||
\end{document}
|
33
expected/codewords.txt
Normal file
33
expected/codewords.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
Gamebook
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1
|
||||
Demonstrating how Codewords (AKA sightings) can be used. Go to 2.
|
||||
|
||||
2
|
||||
Got codeword warrior. Simple enough to set a codeword. Turn to 5.
|
||||
|
||||
3
|
||||
OK, if you have the codeword warrior, you may turn to 4 otherwise you may go back to 2. Although we both know you have that codeword. If you have the codeword fun you may turn to 6, without it you can go to 8.
|
||||
|
||||
4
|
||||
That was easy.
|
||||
|
||||
5
|
||||
If you have the codeword warrior you may turn to 4. If you do not have the codeword fun, you may turn to 8. If you have the codeword fun, you may instead turn to 6. Otherwise see 3.
|
||||
|
||||
6
|
||||
Cheater! There is no way you can have codeword fun.
|
||||
|
||||
7
|
||||
If you have the codeword fun turn to 6. Otherwise you can go to the end at 4 or to the xortest at 3.
|
||||
|
||||
8
|
||||
This is just to demonstrate choices allowed when not having a codeword. Now go on to 9 (autotest) or 3 (xor test).
|
||||
|
||||
9
|
||||
If you have codeword warrior turn to 7. Otherwise you can go to the end at 4 or back to 1.
|
||||
|
16
expected/format.debug
Normal file
16
expected/format.debug
Normal file
|
@ -0,0 +1,16 @@
|
|||
BEGIN DEBUG OUTPUT
|
||||
Book title: Format
|
||||
Number of sections: 4
|
||||
|
||||
Introduction
|
||||
Adding an introduction to the gamebook here. This will create a section, but it will not be shuffled nor numbered with the gamebook sections below.
|
||||
Another Heading
|
||||
This starts another non-shuffled section.
|
||||
|
||||
Adventure begins in section 1.
|
||||
|
||||
1 (start) - This examples tests gamebook formatting, not so much game mechanics or references. Currently there is nothing here really. This section contains some tricky characters to quote, like } and { and " and ' and \. HTML will probably not like <div> or &boom;. There should be an image below as well. If something broke, turn to 2, otherwise turn to 4. [IMG]testimage.png[/IMG]
|
||||
2 (bad) - Bad.
|
||||
3 (dum) - Sections tagged as dummy will not be visible in output at all.
|
||||
4 (good) - Good!
|
||||
END DEBUG OUTPUT
|
7
expected/format.dot
Normal file
7
expected/format.dot
Normal file
|
@ -0,0 +1,7 @@
|
|||
digraph gamebook {
|
||||
|
||||
|
||||
1->2
|
||||
|
||||
1->4
|
||||
}
|
370
expected/format.html
Normal file
370
expected/format.html
Normal file
|
@ -0,0 +1,370 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Format</title>
|
||||
<script>
|
||||
var gamebook = {
|
||||
'player' : {
|
||||
'started' : false,
|
||||
'currentSection' : null,
|
||||
'collections' : {},
|
||||
|
||||
'collect' : function(type, name) {
|
||||
this.collections[type] = {
|
||||
'name' : name,
|
||||
'contents' : [],
|
||||
'add' : function(what) {
|
||||
if (this.contents.indexOf(what) === -1
|
||||
&& !(what in gamebook.dropped[type])) {
|
||||
this.contents.push(what);
|
||||
this.contents.sort();
|
||||
}
|
||||
},
|
||||
'drop' : function(what) {
|
||||
var i = this.contents.indexOf(what);
|
||||
if (i >= 0) {
|
||||
this.contents.splice(i, 1);
|
||||
gamebook.dropped[type][what] = true;
|
||||
}
|
||||
},
|
||||
'has' : function(what) {
|
||||
return this.contents.indexOf(what) >= 0;
|
||||
}
|
||||
};
|
||||
gamebook.dropped[type] = {};
|
||||
gamebook.addCollectionView(type, name);
|
||||
},
|
||||
|
||||
'add' : function(type, what) {
|
||||
this.collections[type].add(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'drop' : function(type, what) {
|
||||
this.collections[type].drop(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'has' : function(type, what) {
|
||||
return this.collections[type].has(what);
|
||||
}
|
||||
},
|
||||
|
||||
'sections' : {},
|
||||
|
||||
'turnToFunctions' : {},
|
||||
|
||||
'dropped' : {},
|
||||
|
||||
'addSection' : function(nr, element) {
|
||||
var section = {'element' : element, 'nr' : nr};
|
||||
this.sections[nr] = section;
|
||||
},
|
||||
|
||||
'turnTo' : function(nr) {
|
||||
if (!gamebook.player.started) {
|
||||
gamebook.start();
|
||||
}
|
||||
if (!nr in this.sections) {
|
||||
throw new Exception("Can not turn to non-existing section "
|
||||
+ nr + ".");
|
||||
}
|
||||
this.displaySection(nr);
|
||||
},
|
||||
|
||||
'start' : function() {
|
||||
this.hideIntroSections();
|
||||
this.addClassToClass('startlink', 'nodisplay');
|
||||
gamebook.player.started = true;
|
||||
},
|
||||
|
||||
'displaySection' : function(nr) {
|
||||
if (this.player.currentSection) {
|
||||
this.player.currentSection.element.style.display = 'none';
|
||||
}
|
||||
var e = this.sections[nr].element;
|
||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||
e.style.display = 'block';
|
||||
this.player.currentSection = gamebook.sections[nr];
|
||||
},
|
||||
|
||||
'hideIntroSections' : function() {
|
||||
this.addClassToClass('introsection', 'nodisplay');
|
||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||
},
|
||||
|
||||
'showIntroSections' : function() {
|
||||
this.runActionsInIntroSections();
|
||||
this.removeClassFromClass('introsection', 'nodisplay');
|
||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||
document.body.scrollIntoView();
|
||||
},
|
||||
|
||||
'runActionsInIntroSections' : function() {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName('introsectionbody'),
|
||||
gamebook.runActions);
|
||||
},
|
||||
|
||||
'addClassToClass' : function(className, addClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.add(addClass);
|
||||
});
|
||||
},
|
||||
|
||||
'removeClassFromClass' : function(className, removeClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.remove(removeClass);
|
||||
});
|
||||
},
|
||||
|
||||
'runActions' : function(e) {
|
||||
var enableNextLink = true;
|
||||
var hasXorScope = false;
|
||||
var hasAutoScope = false;
|
||||
var xorEnableNext = false;
|
||||
var autoDisableAllRemainingLinks = (
|
||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||
if (!c.classList) {
|
||||
return;
|
||||
}
|
||||
if (c.classList.contains('sectionref')) {
|
||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||
gamebook.enableLink(c);
|
||||
if (hasAutoScope) {
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
} else {
|
||||
gamebook.disableLink(c);
|
||||
}
|
||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||
hasAutoScope = false;
|
||||
hasXorScope = false;
|
||||
} else if (c.classList.contains('collect')) {
|
||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||
} else if (c.classList.contains('add')) {
|
||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('drop')) {
|
||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('has')) {
|
||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('hasnot')) {
|
||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('xor')) {
|
||||
hasXorScope = true;
|
||||
xorEnableNext = !enableNextLink;
|
||||
} else if (c.classList.contains('auto')) {
|
||||
hasAutoScope = true;
|
||||
} else if (c.classList.contains('random')) {
|
||||
c.addEventListener('click',
|
||||
gamebook.enableRandomLinkAfter);
|
||||
c.classList.add("enabledlink");
|
||||
c.classList.remove("disabledlink");
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'enableLink' : function(e) {
|
||||
e.addEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.add("enabledlink");
|
||||
e.classList.remove("disabledlink");
|
||||
},
|
||||
|
||||
'disableLink' : function(e) {
|
||||
e.removeEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.remove("enabledlink");
|
||||
e.classList.add("disabledlink");
|
||||
},
|
||||
|
||||
'enableRandomLinkAfter' : function(event) {
|
||||
this.classList.remove("enabledlink");
|
||||
this.classList.add("disabledlink");
|
||||
var links = [];
|
||||
var e = this.nextSibling;
|
||||
while (e) {
|
||||
if (e.classList && e.classList.contains('sectionref')) {
|
||||
links.push(e);
|
||||
}
|
||||
e = e.nextSibling;
|
||||
}
|
||||
if (links.length > 0) {
|
||||
var selected = links[Math.floor(Math.random()*links.length)]
|
||||
gamebook.enableLink(selected);
|
||||
} else {
|
||||
console.log("Random with nothing to select?");
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'addCollectionView' : function(type, name) {
|
||||
var ce = document.getElementById('collections');
|
||||
var template = document.getElementById('collectionTemplate');
|
||||
var e = template.cloneNode(true);
|
||||
e.className = "collection";
|
||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||
e.dataset.type = type;
|
||||
ce.appendChild(e);
|
||||
},
|
||||
|
||||
'updateCollectionsView' : function() {
|
||||
var ce = document.getElementById('collections');
|
||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||
if (c.className === 'collection') {
|
||||
var type = c.dataset.type;
|
||||
var collection = gamebook.player.collections[type];
|
||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||
cc.innerHTML = collection.contents.join(', ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getTurnToFunction' : function(nr) {
|
||||
if (nr in this.turnToFunctions) {
|
||||
return this.turnToFunctions[nr];
|
||||
} else {
|
||||
var f = function () {
|
||||
gamebook.turnTo(nr);
|
||||
};
|
||||
this.turnToFunctions[nr] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random {
|
||||
font-weight: bold;
|
||||
margin: 0.2em;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionref.enabledlink {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random {
|
||||
cursor: pointer;}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||
.random {background: #eef;
|
||||
}
|
||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||
.hideintrolink:hover {background: #a9f;}
|
||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||
.disabledlink:hover {background: inherit;}
|
||||
.sectionnumber {font-weight: bolder;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;}
|
||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||
.sectiontext {margin-top: 0.5em;}
|
||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||
.collections {margin-top: 4em;}
|
||||
.collection {background: #ddd; margin-top: 1em;}
|
||||
.collectionheading {}
|
||||
.collectionheading::after {content: ": ";}
|
||||
.collectioncontents {}
|
||||
.collect {}
|
||||
.add {font-weight: bold;}
|
||||
.drop {font-style: italic;}
|
||||
.has {font-style: italic;}
|
||||
.hasnot {font-style: italic;}
|
||||
.collectionTemplate {display: none;}
|
||||
.sectionimage {width: 100%; padding: 1em;}
|
||||
.nodisplay {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hideintrolink nodisplay"
|
||||
onclick="gamebook.hideIntroSections()">HIDE THE INTRO</div>
|
||||
<div class="gamebook">
|
||||
|
||||
<div class="introsection">
|
||||
<span class="introsectionheading">Introduction</span>
|
||||
<div class="introsectionbody">
|
||||
Adding an introduction to the gamebook here. This will create a section, but it will not be shuffled nor numbered with the gamebook sections below.
|
||||
</div>
|
||||
</div>
|
||||
<div class="introsection">
|
||||
<span class="introsectionheading">Another Heading</span>
|
||||
<div class="introsectionbody">
|
||||
This starts another non-shuffled section.
|
||||
</div>
|
||||
</div>
|
||||
<div class="startlink"
|
||||
onclick="gamebook.turnTo(1)">Adventure begins in section 1.</div>
|
||||
|
||||
<div class="section" id="section1">
|
||||
<span class="sectionnumber" id="para1">1</span>
|
||||
<div class="sectiontext">
|
||||
This examples tests gamebook formatting, not so much game mechanics or references. Currently there is nothing here really. This section contains some tricky characters to quote, like } and { and " and ' and \. HTML will probably not like <div> or &boom;. There should be an image below as well. If something broke, turn to <a class="sectionref enabledlink" data-ref="2">2</a>, otherwise turn to <a class="sectionref enabledlink" data-ref="4">4</a>. <img src="testimage.png" class="sectionimage"></img>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(1, document.getElementById('section1'));
|
||||
}
|
||||
</script> <div class="section" id="section2">
|
||||
<span class="sectionnumber" id="para2">2</span>
|
||||
<div class="sectiontext">
|
||||
Bad.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(2, document.getElementById('section2'));
|
||||
}
|
||||
</script> <div class="section" id="section3">
|
||||
<span class="sectionnumber" id="para3">3</span>
|
||||
<div class="sectiontext">
|
||||
Sections tagged as dummy will not be visible in output at all.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(3, document.getElementById('section3'));
|
||||
}
|
||||
</script> <div class="section" id="section4">
|
||||
<span class="sectionnumber" id="para4">4</span>
|
||||
<div class="sectiontext">
|
||||
Good!
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(4, document.getElementById('section4'));
|
||||
}
|
||||
</script> <div id="collections" class="collections">
|
||||
</div>
|
||||
<div id="collectionTemplate" class="collectionTemplate">
|
||||
<span class="collectionheading"></span>
|
||||
<span class="collectioncontents"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.runActionsInIntroSections();
|
||||
}
|
||||
</script>
|
||||
<div class="displayintrolink nodisplay"
|
||||
onclick="gamebook.showIntroSections()">SHOW THE INTRO</div>
|
||||
</body>
|
||||
</html>
|
54
expected/format.rtf
Normal file
54
expected/format.rtf
Normal file
|
@ -0,0 +1,54 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww14140\viewh14860\viewkind0
|
||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\b\fs24 \cf0
|
||||
|
||||
\b \qc Format
|
||||
\b0\
|
||||
|
||||
\b \qc Introduction
|
||||
\b0\
|
||||
|
||||
|
||||
|
||||
\ql Adding an introduction to the gamebook here. This will create a section, but it will not be shuffled nor numbered with the gamebook sections below. \
|
||||
\
|
||||
\b \qc Another Heading
|
||||
\b0\
|
||||
|
||||
|
||||
|
||||
\ql This starts another non-shuffled section. \
|
||||
\
|
||||
\b Adventure begins in section 1.
|
||||
\b0\
|
||||
\
|
||||
|
||||
\b \qc 1
|
||||
\b0\
|
||||
\ql This examples tests gamebook formatting, not so much game mechanics or references. Currently there is nothing here really. This section contains some tricky characters to quote, like \} and \{ and " and ' and \\. HTML will probably not like <div> or &boom;. There should be an image below as well. If something broke, turn to \b 2
|
||||
\b0
|
||||
, otherwise turn to \b 4
|
||||
\b0
|
||||
. testimage.png \
|
||||
\
|
||||
|
||||
\b \qc 2
|
||||
\b0\
|
||||
\ql Bad. \
|
||||
\
|
||||
|
||||
\b \qc 3
|
||||
\b0\
|
||||
\ql Sections tagged as dummy will not be visible in output at all. \
|
||||
\
|
||||
|
||||
\b \qc 4
|
||||
\b0\
|
||||
\ql Good! \
|
||||
\
|
||||
|
||||
}
|
88
expected/format.tex
Normal file
88
expected/format.tex
Normal file
|
@ -0,0 +1,88 @@
|
|||
\documentclass[a5,onecolumn]{book}
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\usepackage[top=3.3cm, bottom=3.3cm, left=2cm, right=2cm]{geometry}
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\ifnum\pdfoutput=1
|
||||
\pdftrue
|
||||
\else
|
||||
\pdffalse
|
||||
\fi
|
||||
\fi
|
||||
|
||||
\title{Format}
|
||||
\author{}
|
||||
\date{}
|
||||
|
||||
\newcounter{sectionnr}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\clearpage
|
||||
|
||||
|
||||
\subsection*{\begin{center} \textbf{Introduction} \end{center}}
|
||||
|
||||
|
||||
\noindent
|
||||
Adding an introduction to the gamebook here. This will create a section, but it will not be shuffled nor numbered with the gamebook sections below.
|
||||
\vspace{1em}
|
||||
\subsection*{\begin{center} \textbf{Another Heading} \end{center}}
|
||||
|
||||
|
||||
\noindent
|
||||
This starts another non-shuffled section.
|
||||
\vspace{1em}
|
||||
|
||||
Adventure begins in section 1.
|
||||
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section1}
|
||||
\subsection*{\begin{center} \textbf{1} \end{center}}
|
||||
|
||||
\noindent
|
||||
This examples tests gamebook formatting, not so much game mechanics or references. Currently there is nothing here really. This section contains some tricky characters to quote, like \} and \{ and " and ' and \textbackslash. HTML will probably not like <div> or \&boom;. There should be an image below as well. If something broke, turn to \textbf{\autoref{section2}}, otherwise turn to \textbf{\autoref{section4}}. \begin{center}
|
||||
\includegraphics[width=.9\textwidth]{testimage.png}
|
||||
\end{center}
|
||||
|
||||
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section2}
|
||||
\subsection*{\begin{center} \textbf{2} \end{center}}
|
||||
|
||||
\noindent
|
||||
Bad.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section3}
|
||||
\subsection*{\begin{center} \textbf{3} \end{center}}
|
||||
|
||||
\noindent
|
||||
Sections tagged as dummy will not be visible in output at all.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section4}
|
||||
\subsection*{\begin{center} \textbf{4} \end{center}}
|
||||
|
||||
\noindent
|
||||
Good!
|
||||
\vspace{1em}
|
||||
\end{document}
|
24
expected/format.txt
Normal file
24
expected/format.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
Format
|
||||
|
||||
|
||||
Introduction
|
||||
Adding an introduction to the gamebook here. This will create a section, but it will not be shuffled nor numbered with the gamebook sections below.
|
||||
|
||||
Another Heading
|
||||
This starts another non-shuffled section.
|
||||
|
||||
|
||||
Adventure begins in section 1.
|
||||
|
||||
1
|
||||
This examples tests gamebook formatting, not so much game mechanics or references. Currently there is nothing here really. This section contains some tricky characters to quote, like } and { and " and ' and \. HTML will probably not like <div> or &boom;. There should be an image below as well. If something broke, turn to 2, otherwise turn to 4. testimage.png
|
||||
|
||||
2
|
||||
Bad.
|
||||
|
||||
3
|
||||
Sections tagged as dummy will not be visible in output at all.
|
||||
|
||||
4
|
||||
Good!
|
||||
|
19
expected/items.debug
Normal file
19
expected/items.debug
Normal file
|
@ -0,0 +1,19 @@
|
|||
BEGIN DEBUG OUTPUT
|
||||
Book title: Items
|
||||
Number of sections: 11
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1 (start) - Demonstrating how to manage player [COLLECT item]Inventory[/COLLECT]. You start the book carrying a [ADD item]sword[/ADD] and a [ADD item]shield[/ADD]. Turn to 2.
|
||||
2 (tjunction) - You have reached a t-junction. Here you find a [FOUND item]key[/FOUND] and a [FOUND item]stick[/FOUND]. You can go west to 7, or east to 4.
|
||||
3 (cut_rope) - OK. That was fun. Turn to 10.
|
||||
4 (curse) - There is a [FOUND item]cursed bracelet[/FOUND] here. You can go on to 6 or go back to 2. You can also drop the [HAS item]stick[/HAS] for no particular reason if you have it, see 11.
|
||||
5 (treasure) - You found [FOUND item]something valuable[/FOUND], but there is no way forward, so you head back to 2.
|
||||
6 (portal) - A magic portal ahead will only allow you to pass if you did not pick up the [HAS NOT item]cursed bracelet[/HAS NOT], leading you to 5. If you have the [HAS item]cursed bracelet[/HAS] you have to go back to 2 instead. Actually feel free to head back to 2 either way.
|
||||
7 (door) - There is a locked door here.eh If you have a [HAS item]key[/HAS] you can use that to open the door, see 8. Being right before the link should be enough for the formatter to figure out that the key is required to be allowed to follow the link. Else you can try to open with the [HAS item]sword[/HAS], if you have it, see 9. Hopefully the magic is good enough to pair pre-conditions to links, or more markup must be added later. You could also try to go back to pick up the key, see 2.
|
||||
8 (inside) - There is a rope here that can be cut using a [HAS item]sword[/HAS]. If you have one and want to do that, see 3. Otherwise turn to 10.
|
||||
9 (attempt_break_door_with_sword) - OK. The door is broken, but so is the [DROP item]sword[/DROP]. Turn to 8.
|
||||
10 (won) - Congratulations, you won.
|
||||
11 (drop_stick) - OK [DROP item]stick[/DROP] dropped. Turn back to 2 to confirm stick can not be picked up again even if the text says it is there (books work that way, although ideally this dynamic version should provide some hints that it is no longer there).
|
||||
END DEBUG OUTPUT
|
28
expected/items.dot
Normal file
28
expected/items.dot
Normal file
|
@ -0,0 +1,28 @@
|
|||
digraph gamebook {
|
||||
|
||||
|
||||
1->2
|
||||
2->7
|
||||
|
||||
2->4
|
||||
3->10
|
||||
4->2
|
||||
|
||||
4->6
|
||||
|
||||
4->11
|
||||
5->2
|
||||
6->5
|
||||
|
||||
6->2
|
||||
7->8
|
||||
|
||||
7->9
|
||||
|
||||
7->2
|
||||
8->10
|
||||
|
||||
8->3
|
||||
9->8
|
||||
11->2
|
||||
}
|
446
expected/items.html
Normal file
446
expected/items.html
Normal file
|
@ -0,0 +1,446 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Items</title>
|
||||
<script>
|
||||
var gamebook = {
|
||||
'player' : {
|
||||
'started' : false,
|
||||
'currentSection' : null,
|
||||
'collections' : {},
|
||||
|
||||
'collect' : function(type, name) {
|
||||
this.collections[type] = {
|
||||
'name' : name,
|
||||
'contents' : [],
|
||||
'add' : function(what) {
|
||||
if (this.contents.indexOf(what) === -1
|
||||
&& !(what in gamebook.dropped[type])) {
|
||||
this.contents.push(what);
|
||||
this.contents.sort();
|
||||
}
|
||||
},
|
||||
'drop' : function(what) {
|
||||
var i = this.contents.indexOf(what);
|
||||
if (i >= 0) {
|
||||
this.contents.splice(i, 1);
|
||||
gamebook.dropped[type][what] = true;
|
||||
}
|
||||
},
|
||||
'has' : function(what) {
|
||||
return this.contents.indexOf(what) >= 0;
|
||||
}
|
||||
};
|
||||
gamebook.dropped[type] = {};
|
||||
gamebook.addCollectionView(type, name);
|
||||
},
|
||||
|
||||
'add' : function(type, what) {
|
||||
this.collections[type].add(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'drop' : function(type, what) {
|
||||
this.collections[type].drop(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'has' : function(type, what) {
|
||||
return this.collections[type].has(what);
|
||||
}
|
||||
},
|
||||
|
||||
'sections' : {},
|
||||
|
||||
'turnToFunctions' : {},
|
||||
|
||||
'dropped' : {},
|
||||
|
||||
'addSection' : function(nr, element) {
|
||||
var section = {'element' : element, 'nr' : nr};
|
||||
this.sections[nr] = section;
|
||||
},
|
||||
|
||||
'turnTo' : function(nr) {
|
||||
if (!gamebook.player.started) {
|
||||
gamebook.start();
|
||||
}
|
||||
if (!nr in this.sections) {
|
||||
throw new Exception("Can not turn to non-existing section "
|
||||
+ nr + ".");
|
||||
}
|
||||
this.displaySection(nr);
|
||||
},
|
||||
|
||||
'start' : function() {
|
||||
this.hideIntroSections();
|
||||
this.addClassToClass('startlink', 'nodisplay');
|
||||
gamebook.player.started = true;
|
||||
},
|
||||
|
||||
'displaySection' : function(nr) {
|
||||
if (this.player.currentSection) {
|
||||
this.player.currentSection.element.style.display = 'none';
|
||||
}
|
||||
var e = this.sections[nr].element;
|
||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||
e.style.display = 'block';
|
||||
this.player.currentSection = gamebook.sections[nr];
|
||||
},
|
||||
|
||||
'hideIntroSections' : function() {
|
||||
this.addClassToClass('introsection', 'nodisplay');
|
||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||
},
|
||||
|
||||
'showIntroSections' : function() {
|
||||
this.runActionsInIntroSections();
|
||||
this.removeClassFromClass('introsection', 'nodisplay');
|
||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||
document.body.scrollIntoView();
|
||||
},
|
||||
|
||||
'runActionsInIntroSections' : function() {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName('introsectionbody'),
|
||||
gamebook.runActions);
|
||||
},
|
||||
|
||||
'addClassToClass' : function(className, addClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.add(addClass);
|
||||
});
|
||||
},
|
||||
|
||||
'removeClassFromClass' : function(className, removeClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.remove(removeClass);
|
||||
});
|
||||
},
|
||||
|
||||
'runActions' : function(e) {
|
||||
var enableNextLink = true;
|
||||
var hasXorScope = false;
|
||||
var hasAutoScope = false;
|
||||
var xorEnableNext = false;
|
||||
var autoDisableAllRemainingLinks = (
|
||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||
if (!c.classList) {
|
||||
return;
|
||||
}
|
||||
if (c.classList.contains('sectionref')) {
|
||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||
gamebook.enableLink(c);
|
||||
if (hasAutoScope) {
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
} else {
|
||||
gamebook.disableLink(c);
|
||||
}
|
||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||
hasAutoScope = false;
|
||||
hasXorScope = false;
|
||||
} else if (c.classList.contains('collect')) {
|
||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||
} else if (c.classList.contains('add')) {
|
||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('drop')) {
|
||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('has')) {
|
||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('hasnot')) {
|
||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('xor')) {
|
||||
hasXorScope = true;
|
||||
xorEnableNext = !enableNextLink;
|
||||
} else if (c.classList.contains('auto')) {
|
||||
hasAutoScope = true;
|
||||
} else if (c.classList.contains('random')) {
|
||||
c.addEventListener('click',
|
||||
gamebook.enableRandomLinkAfter);
|
||||
c.classList.add("enabledlink");
|
||||
c.classList.remove("disabledlink");
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'enableLink' : function(e) {
|
||||
e.addEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.add("enabledlink");
|
||||
e.classList.remove("disabledlink");
|
||||
},
|
||||
|
||||
'disableLink' : function(e) {
|
||||
e.removeEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.remove("enabledlink");
|
||||
e.classList.add("disabledlink");
|
||||
},
|
||||
|
||||
'enableRandomLinkAfter' : function(event) {
|
||||
this.classList.remove("enabledlink");
|
||||
this.classList.add("disabledlink");
|
||||
var links = [];
|
||||
var e = this.nextSibling;
|
||||
while (e) {
|
||||
if (e.classList && e.classList.contains('sectionref')) {
|
||||
links.push(e);
|
||||
}
|
||||
e = e.nextSibling;
|
||||
}
|
||||
if (links.length > 0) {
|
||||
var selected = links[Math.floor(Math.random()*links.length)]
|
||||
gamebook.enableLink(selected);
|
||||
} else {
|
||||
console.log("Random with nothing to select?");
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'addCollectionView' : function(type, name) {
|
||||
var ce = document.getElementById('collections');
|
||||
var template = document.getElementById('collectionTemplate');
|
||||
var e = template.cloneNode(true);
|
||||
e.className = "collection";
|
||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||
e.dataset.type = type;
|
||||
ce.appendChild(e);
|
||||
},
|
||||
|
||||
'updateCollectionsView' : function() {
|
||||
var ce = document.getElementById('collections');
|
||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||
if (c.className === 'collection') {
|
||||
var type = c.dataset.type;
|
||||
var collection = gamebook.player.collections[type];
|
||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||
cc.innerHTML = collection.contents.join(', ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getTurnToFunction' : function(nr) {
|
||||
if (nr in this.turnToFunctions) {
|
||||
return this.turnToFunctions[nr];
|
||||
} else {
|
||||
var f = function () {
|
||||
gamebook.turnTo(nr);
|
||||
};
|
||||
this.turnToFunctions[nr] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random {
|
||||
font-weight: bold;
|
||||
margin: 0.2em;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionref.enabledlink {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random {
|
||||
cursor: pointer;}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||
.random {background: #eef;
|
||||
}
|
||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||
.hideintrolink:hover {background: #a9f;}
|
||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||
.disabledlink:hover {background: inherit;}
|
||||
.sectionnumber {font-weight: bolder;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;}
|
||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||
.sectiontext {margin-top: 0.5em;}
|
||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||
.collections {margin-top: 4em;}
|
||||
.collection {background: #ddd; margin-top: 1em;}
|
||||
.collectionheading {}
|
||||
.collectionheading::after {content: ": ";}
|
||||
.collectioncontents {}
|
||||
.collect {}
|
||||
.add {font-weight: bold;}
|
||||
.drop {font-style: italic;}
|
||||
.has {font-style: italic;}
|
||||
.hasnot {font-style: italic;}
|
||||
.collectionTemplate {display: none;}
|
||||
.sectionimage {width: 100%; padding: 1em;}
|
||||
.nodisplay {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hideintrolink nodisplay"
|
||||
onclick="gamebook.hideIntroSections()">(hide instructions)</div>
|
||||
<div class="gamebook">
|
||||
|
||||
<div class="startlink"
|
||||
onclick="gamebook.turnTo(1)">Turn to 1 to begin.</div>
|
||||
|
||||
<div class="section" id="section1">
|
||||
<span class="sectionnumber" id="para1">1</span>
|
||||
<div class="sectiontext">
|
||||
Demonstrating how to manage player <span class="collect" data-type="item"
|
||||
data-name="Inventory">Inventory</span>. You start the book carrying a <span class="add" data-type="item"
|
||||
data-what="sword">sword</span> and a <span class="add" data-type="item"
|
||||
data-what="shield">shield</span>. Turn to <a class="sectionref enabledlink" data-ref="2">2</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(1, document.getElementById('section1'));
|
||||
}
|
||||
</script> <div class="section" id="section2">
|
||||
<span class="sectionnumber" id="para2">2</span>
|
||||
<div class="sectiontext">
|
||||
You have reached a t-junction. Here you find a <span class="found enabledlink"
|
||||
onclick="gamebook.player.add('item', 'key')"
|
||||
>key</span>
|
||||
and a <span class="found enabledlink"
|
||||
onclick="gamebook.player.add('item', 'stick')"
|
||||
>stick</span>
|
||||
. You can go west to <a class="sectionref enabledlink" data-ref="7">7</a>, or east to <a class="sectionref enabledlink" data-ref="4">4</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(2, document.getElementById('section2'));
|
||||
}
|
||||
</script> <div class="section" id="section3">
|
||||
<span class="sectionnumber" id="para3">3</span>
|
||||
<div class="sectiontext">
|
||||
OK. That was fun. Turn to <a class="sectionref enabledlink" data-ref="10">10</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(3, document.getElementById('section3'));
|
||||
}
|
||||
</script> <div class="section" id="section4">
|
||||
<span class="sectionnumber" id="para4">4</span>
|
||||
<div class="sectiontext">
|
||||
There is a <span class="found enabledlink"
|
||||
onclick="gamebook.player.add('item', 'cursed bracelet')"
|
||||
>cursed bracelet</span>
|
||||
here. You can go on to <a class="sectionref enabledlink" data-ref="6">6</a> or go back to <a class="sectionref enabledlink" data-ref="2">2</a>. You can also drop the <span class="has" data-type="item" data-what="stick">stick</span> for no particular reason if you have it, see <a class="sectionref enabledlink" data-ref="11">11</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(4, document.getElementById('section4'));
|
||||
}
|
||||
</script> <div class="section" id="section5">
|
||||
<span class="sectionnumber" id="para5">5</span>
|
||||
<div class="sectiontext">
|
||||
You found <span class="found enabledlink"
|
||||
onclick="gamebook.player.add('item', 'something valuable')"
|
||||
>something valuable</span>
|
||||
, but there is no way forward, so you head back to <a class="sectionref enabledlink" data-ref="2">2</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(5, document.getElementById('section5'));
|
||||
}
|
||||
</script> <div class="section" id="section6">
|
||||
<span class="sectionnumber" id="para6">6</span>
|
||||
<div class="sectiontext">
|
||||
A magic portal ahead will only allow you to pass if you did not pick up the <span class="hasnot" data-type="item"
|
||||
data-what="cursed bracelet">cursed bracelet</span>, leading you to <a class="sectionref enabledlink" data-ref="5">5</a>. If you have the <span class="has" data-type="item" data-what="cursed bracelet">cursed bracelet</span> you have to go back to <a class="sectionref enabledlink" data-ref="2">2</a> instead. Actually feel free to head back to <a class="sectionref enabledlink" data-ref="2">2</a> either way.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(6, document.getElementById('section6'));
|
||||
}
|
||||
</script> <div class="section" id="section7">
|
||||
<span class="sectionnumber" id="para7">7</span>
|
||||
<div class="sectiontext">
|
||||
There is a locked door here.eh If you have a <span class="has" data-type="item" data-what="key">key</span> you can use that to open the door, see <a class="sectionref enabledlink" data-ref="8">8</a>. Being right before the link should be enough for the formatter to figure out that the key is required to be allowed to follow the link. Else you can try to open with the <span class="has" data-type="item" data-what="sword">sword</span>, if you have it, see <a class="sectionref enabledlink" data-ref="9">9</a>. Hopefully the magic is good enough to pair pre-conditions to links, or more markup must be added later. You could also try to go back to pick up the key, see <a class="sectionref enabledlink" data-ref="2">2</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(7, document.getElementById('section7'));
|
||||
}
|
||||
</script> <div class="section" id="section8">
|
||||
<span class="sectionnumber" id="para8">8</span>
|
||||
<div class="sectiontext">
|
||||
There is a rope here that can be cut using a <span class="has" data-type="item" data-what="sword">sword</span>. If you have one and want to do that, see <a class="sectionref enabledlink" data-ref="3">3</a>. Otherwise turn to <a class="sectionref enabledlink" data-ref="10">10</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(8, document.getElementById('section8'));
|
||||
}
|
||||
</script> <div class="section" id="section9">
|
||||
<span class="sectionnumber" id="para9">9</span>
|
||||
<div class="sectiontext">
|
||||
OK. The door is broken, but so is the <span class="drop" data-type="item"
|
||||
data-what="sword">sword</span>. Turn to <a class="sectionref enabledlink" data-ref="8">8</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(9, document.getElementById('section9'));
|
||||
}
|
||||
</script> <div class="section" id="section10">
|
||||
<span class="sectionnumber" id="para10">10</span>
|
||||
<div class="sectiontext">
|
||||
Congratulations, you won.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(10, document.getElementById('section10'));
|
||||
}
|
||||
</script> <div class="section" id="section11">
|
||||
<span class="sectionnumber" id="para11">11</span>
|
||||
<div class="sectiontext">
|
||||
OK <span class="drop" data-type="item"
|
||||
data-what="stick">stick</span> dropped. Turn back to <a class="sectionref enabledlink" data-ref="2">2</a> to confirm stick can not be picked up again even if the text says it is there (books work that way, although ideally this dynamic version should provide some hints that it is no longer there).
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(11, document.getElementById('section11'));
|
||||
}
|
||||
</script> <div id="collections" class="collections">
|
||||
</div>
|
||||
<div id="collectionTemplate" class="collectionTemplate">
|
||||
<span class="collectionheading"></span>
|
||||
<span class="collectioncontents"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.runActionsInIntroSections();
|
||||
}
|
||||
</script>
|
||||
<div class="displayintrolink nodisplay"
|
||||
onclick="gamebook.showIntroSections()">(show instructions)</div>
|
||||
</body>
|
||||
</html>
|
107
expected/items.rtf
Normal file
107
expected/items.rtf
Normal file
|
@ -0,0 +1,107 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww14140\viewh14860\viewkind0
|
||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\b\fs24 \cf0
|
||||
|
||||
\b \qc Items
|
||||
\b0\
|
||||
|
||||
\b Turn to 1 to begin.
|
||||
\b0\
|
||||
\
|
||||
|
||||
\b \qc 1
|
||||
\b0\
|
||||
\ql Demonstrating how to manage player Inventory. You start the book carrying a sword and a shield. Turn to \b 2
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 2
|
||||
\b0\
|
||||
\ql You have reached a t-junction. Here you find a key and a stick. You can go west to \b 7
|
||||
\b0
|
||||
, or east to \b 4
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 3
|
||||
\b0\
|
||||
\ql OK. That was fun. Turn to \b 10
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 4
|
||||
\b0\
|
||||
\ql There is a cursed bracelet here. You can go on to \b 6
|
||||
\b0
|
||||
or go back to \b 2
|
||||
\b0
|
||||
. You can also drop the stick for no particular reason if you have it, see \b 11
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 5
|
||||
\b0\
|
||||
\ql You found something valuable, but there is no way forward, so you head back to \b 2
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 6
|
||||
\b0\
|
||||
\ql A magic portal ahead will only allow you to pass if you did not pick up the cursed bracelet, leading you to \b 5
|
||||
\b0
|
||||
. If you have the cursed bracelet you have to go back to \b 2
|
||||
\b0
|
||||
instead. Actually feel free to head back to \b 2
|
||||
\b0
|
||||
either way. \
|
||||
\
|
||||
|
||||
\b \qc 7
|
||||
\b0\
|
||||
\ql There is a locked door here.eh If you have a key you can use that to open the door, see \b 8
|
||||
\b0
|
||||
. Being right before the link should be enough for the formatter to figure out that the key is required to be allowed to follow the link. Else you can try to open with the sword, if you have it, see \b 9
|
||||
\b0
|
||||
. Hopefully the magic is good enough to pair pre-conditions to links, or more markup must be added later. You could also try to go back to pick up the key, see \b 2
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 8
|
||||
\b0\
|
||||
\ql There is a rope here that can be cut using a sword. If you have one and want to do that, see \b 3
|
||||
\b0
|
||||
. Otherwise turn to \b 10
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 9
|
||||
\b0\
|
||||
\ql OK. The door is broken, but so is the sword. Turn to \b 8
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 10
|
||||
\b0\
|
||||
\ql Congratulations, you won. \
|
||||
\
|
||||
|
||||
\b \qc 11
|
||||
\b0\
|
||||
\ql OK stick dropped. Turn back to \b 2
|
||||
\b0
|
||||
to confirm stick can not be picked up again even if the text says it is there (books work that way, although ideally this dynamic version should provide some hints that it is no longer there). \
|
||||
\
|
||||
|
||||
}
|
130
expected/items.tex
Normal file
130
expected/items.tex
Normal file
|
@ -0,0 +1,130 @@
|
|||
\documentclass[a5,onecolumn]{book}
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\usepackage[top=3.3cm, bottom=3.3cm, left=2cm, right=2cm]{geometry}
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\ifnum\pdfoutput=1
|
||||
\pdftrue
|
||||
\else
|
||||
\pdffalse
|
||||
\fi
|
||||
\fi
|
||||
|
||||
\title{Items}
|
||||
\author{Pelle Nilsson}
|
||||
\date{}
|
||||
|
||||
\newcounter{sectionnr}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\clearpage
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section1}
|
||||
\subsection*{\begin{center} \textbf{1} \end{center}}
|
||||
|
||||
\noindent
|
||||
Demonstrating how to manage player Inventory. You start the book carrying a \textbf{sword} and a \textbf{shield}. Turn to \textbf{\autoref{section2}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section2}
|
||||
\subsection*{\begin{center} \textbf{2} \end{center}}
|
||||
|
||||
\noindent
|
||||
You have reached a t-junction. Here you find a \textbf{key} and a \textbf{stick}. You can go west to \textbf{\autoref{section7}}, or east to \textbf{\autoref{section4}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section3}
|
||||
\subsection*{\begin{center} \textbf{3} \end{center}}
|
||||
|
||||
\noindent
|
||||
OK. That was fun. Turn to \textbf{\autoref{section10}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section4}
|
||||
\subsection*{\begin{center} \textbf{4} \end{center}}
|
||||
|
||||
\noindent
|
||||
There is a \textbf{cursed bracelet} here. You can go on to \textbf{\autoref{section6}} or go back to \textbf{\autoref{section2}}. You can also drop the \textit{stick} for no particular reason if you have it, see \textbf{\autoref{section11}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section5}
|
||||
\subsection*{\begin{center} \textbf{5} \end{center}}
|
||||
|
||||
\noindent
|
||||
You found \textbf{something valuable}, but there is no way forward, so you head back to \textbf{\autoref{section2}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section6}
|
||||
\subsection*{\begin{center} \textbf{6} \end{center}}
|
||||
|
||||
\noindent
|
||||
A magic portal ahead will only allow you to pass if you did not pick up the \textit{cursed bracelet}, leading you to \textbf{\autoref{section5}}. If you have the \textit{cursed bracelet} you have to go back to \textbf{\autoref{section2}} instead. Actually feel free to head back to \textbf{\autoref{section2}} either way.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section7}
|
||||
\subsection*{\begin{center} \textbf{7} \end{center}}
|
||||
|
||||
\noindent
|
||||
There is a locked door here.eh If you have a \textit{key} you can use that to open the door, see \textbf{\autoref{section8}}. Being right before the link should be enough for the formatter to figure out that the key is required to be allowed to follow the link. Else you can try to open with the \textit{sword}, if you have it, see \textbf{\autoref{section9}}. Hopefully the magic is good enough to pair pre-conditions to links, or more markup must be added later. You could also try to go back to pick up the key, see \textbf{\autoref{section2}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section8}
|
||||
\subsection*{\begin{center} \textbf{8} \end{center}}
|
||||
|
||||
\noindent
|
||||
There is a rope here that can be cut using a \textit{sword}. If you have one and want to do that, see \textbf{\autoref{section3}}. Otherwise turn to \textbf{\autoref{section10}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section9}
|
||||
\subsection*{\begin{center} \textbf{9} \end{center}}
|
||||
|
||||
\noindent
|
||||
OK. The door is broken, but so is the \textit{sword}
|
||||
. Turn to \textbf{\autoref{section8}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section10}
|
||||
\subsection*{\begin{center} \textbf{10} \end{center}}
|
||||
|
||||
\noindent
|
||||
Congratulations, you won.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section11}
|
||||
\subsection*{\begin{center} \textbf{11} \end{center}}
|
||||
|
||||
\noindent
|
||||
OK \textit{stick}
|
||||
dropped. Turn back to \textbf{\autoref{section2}} to confirm stick can not be picked up again even if the text says it is there (books work that way, although ideally this dynamic version should provide some hints that it is no longer there).
|
||||
\vspace{1em}
|
||||
\end{document}
|
39
expected/items.txt
Normal file
39
expected/items.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
Items
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1
|
||||
Demonstrating how to manage player Inventory. You start the book carrying a sword and a shield. Turn to 2.
|
||||
|
||||
2
|
||||
You have reached a t-junction. Here you find a key and a stick. You can go west to 7, or east to 4.
|
||||
|
||||
3
|
||||
OK. That was fun. Turn to 10.
|
||||
|
||||
4
|
||||
There is a cursed bracelet here. You can go on to 6 or go back to 2. You can also drop the stick for no particular reason if you have it, see 11.
|
||||
|
||||
5
|
||||
You found something valuable, but there is no way forward, so you head back to 2.
|
||||
|
||||
6
|
||||
A magic portal ahead will only allow you to pass if you did not pick up the cursed bracelet, leading you to 5. If you have the cursed bracelet you have to go back to 2 instead. Actually feel free to head back to 2 either way.
|
||||
|
||||
7
|
||||
There is a locked door here.eh If you have a key you can use that to open the door, see 8. Being right before the link should be enough for the formatter to figure out that the key is required to be allowed to follow the link. Else you can try to open with the sword, if you have it, see 9. Hopefully the magic is good enough to pair pre-conditions to links, or more markup must be added later. You could also try to go back to pick up the key, see 2.
|
||||
|
||||
8
|
||||
There is a rope here that can be cut using a sword. If you have one and want to do that, see 3. Otherwise turn to 10.
|
||||
|
||||
9
|
||||
OK. The door is broken, but so is the sword. Turn to 8.
|
||||
|
||||
10
|
||||
Congratulations, you won.
|
||||
|
||||
11
|
||||
OK stick dropped. Turn back to 2 to confirm stick can not be picked up again even if the text says it is there (books work that way, although ideally this dynamic version should provide some hints that it is no longer there).
|
||||
|
410
expected/references.debug
Normal file
410
expected/references.debug
Normal file
|
@ -0,0 +1,410 @@
|
|||
BEGIN DEBUG OUTPUT
|
||||
Book title: Gamebook
|
||||
Number of sections: 400
|
||||
|
||||
Introduction
|
||||
This gamebook demonstrates simple references between sections. Also notice that an intro section like this one can reference sections, like the start at 1 or the next section at 202.
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1 (start) - This is where the adventure begins. You can go on to the next section, see 202 or try the random selection feature at 76.
|
||||
2 () - (EMPTY)
|
||||
3 () - (EMPTY)
|
||||
4 () - (EMPTY)
|
||||
5 () - (EMPTY)
|
||||
6 () - (EMPTY)
|
||||
7 () - (EMPTY)
|
||||
8 () - (EMPTY)
|
||||
9 () - (EMPTY)
|
||||
10 () - (EMPTY)
|
||||
11 () - (EMPTY)
|
||||
12 () - (EMPTY)
|
||||
13 () - (EMPTY)
|
||||
14 () - (EMPTY)
|
||||
15 () - (EMPTY)
|
||||
16 () - (EMPTY)
|
||||
17 () - (EMPTY)
|
||||
18 () - (EMPTY)
|
||||
19 () - (EMPTY)
|
||||
20 () - (EMPTY)
|
||||
21 () - (EMPTY)
|
||||
22 () - (EMPTY)
|
||||
23 () - (EMPTY)
|
||||
24 () - (EMPTY)
|
||||
25 () - (EMPTY)
|
||||
26 () - (EMPTY)
|
||||
27 () - (EMPTY)
|
||||
28 () - (EMPTY)
|
||||
29 () - (EMPTY)
|
||||
30 () - (EMPTY)
|
||||
31 () - (EMPTY)
|
||||
32 () - (EMPTY)
|
||||
33 () - (EMPTY)
|
||||
34 () - (EMPTY)
|
||||
35 () - (EMPTY)
|
||||
36 () - (EMPTY)
|
||||
37 () - (EMPTY)
|
||||
38 () - (EMPTY)
|
||||
39 () - (EMPTY)
|
||||
40 () - (EMPTY)
|
||||
41 () - (EMPTY)
|
||||
42 () - (EMPTY)
|
||||
43 () - (EMPTY)
|
||||
44 () - (EMPTY)
|
||||
45 () - (EMPTY)
|
||||
46 () - (EMPTY)
|
||||
47 () - (EMPTY)
|
||||
48 () - (EMPTY)
|
||||
49 () - (EMPTY)
|
||||
50 () - (EMPTY)
|
||||
51 () - (EMPTY)
|
||||
52 () - (EMPTY)
|
||||
53 () - (EMPTY)
|
||||
54 () - (EMPTY)
|
||||
55 () - (EMPTY)
|
||||
56 () - (EMPTY)
|
||||
57 () - (EMPTY)
|
||||
58 () - (EMPTY)
|
||||
59 () - (EMPTY)
|
||||
60 () - (EMPTY)
|
||||
61 () - (EMPTY)
|
||||
62 () - (EMPTY)
|
||||
63 () - (EMPTY)
|
||||
64 () - (EMPTY)
|
||||
65 () - (EMPTY)
|
||||
66 () - (EMPTY)
|
||||
67 (altend) - Alternative ending.
|
||||
68 () - (EMPTY)
|
||||
69 () - (EMPTY)
|
||||
70 () - (EMPTY)
|
||||
71 () - (EMPTY)
|
||||
72 () - (EMPTY)
|
||||
73 () - (EMPTY)
|
||||
74 () - (EMPTY)
|
||||
75 () - (EMPTY)
|
||||
76 (random) - [RANDOM]Pick a destination at random[/RANDOM] from 202 or 345 or 67.
|
||||
77 () - (EMPTY)
|
||||
78 () - (EMPTY)
|
||||
79 () - (EMPTY)
|
||||
80 () - (EMPTY)
|
||||
81 () - (EMPTY)
|
||||
82 () - (EMPTY)
|
||||
83 () - (EMPTY)
|
||||
84 () - (EMPTY)
|
||||
85 () - (EMPTY)
|
||||
86 () - (EMPTY)
|
||||
87 () - (EMPTY)
|
||||
88 () - (EMPTY)
|
||||
89 () - (EMPTY)
|
||||
90 () - (EMPTY)
|
||||
91 () - (EMPTY)
|
||||
92 () - (EMPTY)
|
||||
93 () - (EMPTY)
|
||||
94 () - (EMPTY)
|
||||
95 () - (EMPTY)
|
||||
96 () - (EMPTY)
|
||||
97 () - (EMPTY)
|
||||
98 () - (EMPTY)
|
||||
99 () - (EMPTY)
|
||||
100 () - (EMPTY)
|
||||
101 () - (EMPTY)
|
||||
102 () - (EMPTY)
|
||||
103 () - (EMPTY)
|
||||
104 () - (EMPTY)
|
||||
105 () - (EMPTY)
|
||||
106 () - (EMPTY)
|
||||
107 () - (EMPTY)
|
||||
108 () - (EMPTY)
|
||||
109 () - (EMPTY)
|
||||
110 () - (EMPTY)
|
||||
111 () - (EMPTY)
|
||||
112 () - (EMPTY)
|
||||
113 () - (EMPTY)
|
||||
114 () - (EMPTY)
|
||||
115 () - (EMPTY)
|
||||
116 () - (EMPTY)
|
||||
117 () - (EMPTY)
|
||||
118 () - (EMPTY)
|
||||
119 () - (EMPTY)
|
||||
120 () - (EMPTY)
|
||||
121 () - (EMPTY)
|
||||
122 () - (EMPTY)
|
||||
123 () - (EMPTY)
|
||||
124 () - (EMPTY)
|
||||
125 () - (EMPTY)
|
||||
126 () - (EMPTY)
|
||||
127 () - (EMPTY)
|
||||
128 () - (EMPTY)
|
||||
129 () - (EMPTY)
|
||||
130 () - (EMPTY)
|
||||
131 () - (EMPTY)
|
||||
132 () - (EMPTY)
|
||||
133 () - (EMPTY)
|
||||
134 () - (EMPTY)
|
||||
135 () - (EMPTY)
|
||||
136 () - (EMPTY)
|
||||
137 () - (EMPTY)
|
||||
138 () - (EMPTY)
|
||||
139 () - (EMPTY)
|
||||
140 () - (EMPTY)
|
||||
141 () - (EMPTY)
|
||||
142 () - (EMPTY)
|
||||
143 () - (EMPTY)
|
||||
144 () - (EMPTY)
|
||||
145 () - (EMPTY)
|
||||
146 () - (EMPTY)
|
||||
147 () - (EMPTY)
|
||||
148 () - (EMPTY)
|
||||
149 () - (EMPTY)
|
||||
150 () - (EMPTY)
|
||||
151 () - (EMPTY)
|
||||
152 () - (EMPTY)
|
||||
153 () - (EMPTY)
|
||||
154 () - (EMPTY)
|
||||
155 () - (EMPTY)
|
||||
156 () - (EMPTY)
|
||||
157 () - (EMPTY)
|
||||
158 () - (EMPTY)
|
||||
159 () - (EMPTY)
|
||||
160 () - (EMPTY)
|
||||
161 () - (EMPTY)
|
||||
162 () - (EMPTY)
|
||||
163 () - (EMPTY)
|
||||
164 () - (EMPTY)
|
||||
165 () - (EMPTY)
|
||||
166 () - (EMPTY)
|
||||
167 () - (EMPTY)
|
||||
168 () - (EMPTY)
|
||||
169 () - (EMPTY)
|
||||
170 () - (EMPTY)
|
||||
171 () - (EMPTY)
|
||||
172 () - (EMPTY)
|
||||
173 () - (EMPTY)
|
||||
174 () - (EMPTY)
|
||||
175 () - (EMPTY)
|
||||
176 () - (EMPTY)
|
||||
177 () - (EMPTY)
|
||||
178 () - (EMPTY)
|
||||
179 () - (EMPTY)
|
||||
180 () - (EMPTY)
|
||||
181 () - (EMPTY)
|
||||
182 () - (EMPTY)
|
||||
183 () - (EMPTY)
|
||||
184 () - (EMPTY)
|
||||
185 () - (EMPTY)
|
||||
186 () - (EMPTY)
|
||||
187 () - (EMPTY)
|
||||
188 () - (EMPTY)
|
||||
189 () - (EMPTY)
|
||||
190 () - (EMPTY)
|
||||
191 () - (EMPTY)
|
||||
192 () - (EMPTY)
|
||||
193 () - (EMPTY)
|
||||
194 () - (EMPTY)
|
||||
195 () - (EMPTY)
|
||||
196 () - (EMPTY)
|
||||
197 () - (EMPTY)
|
||||
198 () - (EMPTY)
|
||||
199 () - (EMPTY)
|
||||
200 () - (EMPTY)
|
||||
201 () - (EMPTY)
|
||||
202 (next) - This is the next section. Go on to the end at 345.
|
||||
203 () - (EMPTY)
|
||||
204 () - (EMPTY)
|
||||
205 () - (EMPTY)
|
||||
206 () - (EMPTY)
|
||||
207 () - (EMPTY)
|
||||
208 () - (EMPTY)
|
||||
209 () - (EMPTY)
|
||||
210 () - (EMPTY)
|
||||
211 () - (EMPTY)
|
||||
212 () - (EMPTY)
|
||||
213 () - (EMPTY)
|
||||
214 () - (EMPTY)
|
||||
215 () - (EMPTY)
|
||||
216 () - (EMPTY)
|
||||
217 () - (EMPTY)
|
||||
218 () - (EMPTY)
|
||||
219 () - (EMPTY)
|
||||
220 () - (EMPTY)
|
||||
221 () - (EMPTY)
|
||||
222 () - (EMPTY)
|
||||
223 () - (EMPTY)
|
||||
224 () - (EMPTY)
|
||||
225 () - (EMPTY)
|
||||
226 () - (EMPTY)
|
||||
227 () - (EMPTY)
|
||||
228 () - (EMPTY)
|
||||
229 () - (EMPTY)
|
||||
230 () - (EMPTY)
|
||||
231 () - (EMPTY)
|
||||
232 () - (EMPTY)
|
||||
233 () - (EMPTY)
|
||||
234 () - (EMPTY)
|
||||
235 () - (EMPTY)
|
||||
236 () - (EMPTY)
|
||||
237 () - (EMPTY)
|
||||
238 () - (EMPTY)
|
||||
239 () - (EMPTY)
|
||||
240 () - (EMPTY)
|
||||
241 () - (EMPTY)
|
||||
242 () - (EMPTY)
|
||||
243 () - (EMPTY)
|
||||
244 () - (EMPTY)
|
||||
245 () - (EMPTY)
|
||||
246 () - (EMPTY)
|
||||
247 () - (EMPTY)
|
||||
248 () - (EMPTY)
|
||||
249 () - (EMPTY)
|
||||
250 () - (EMPTY)
|
||||
251 () - (EMPTY)
|
||||
252 () - (EMPTY)
|
||||
253 () - (EMPTY)
|
||||
254 () - (EMPTY)
|
||||
255 () - (EMPTY)
|
||||
256 () - (EMPTY)
|
||||
257 () - (EMPTY)
|
||||
258 () - (EMPTY)
|
||||
259 () - (EMPTY)
|
||||
260 () - (EMPTY)
|
||||
261 () - (EMPTY)
|
||||
262 () - (EMPTY)
|
||||
263 () - (EMPTY)
|
||||
264 () - (EMPTY)
|
||||
265 () - (EMPTY)
|
||||
266 () - (EMPTY)
|
||||
267 () - (EMPTY)
|
||||
268 () - (EMPTY)
|
||||
269 () - (EMPTY)
|
||||
270 () - (EMPTY)
|
||||
271 () - (EMPTY)
|
||||
272 () - (EMPTY)
|
||||
273 () - (EMPTY)
|
||||
274 () - (EMPTY)
|
||||
275 () - (EMPTY)
|
||||
276 () - (EMPTY)
|
||||
277 () - (EMPTY)
|
||||
278 () - (EMPTY)
|
||||
279 () - (EMPTY)
|
||||
280 () - (EMPTY)
|
||||
281 () - (EMPTY)
|
||||
282 () - (EMPTY)
|
||||
283 () - (EMPTY)
|
||||
284 () - (EMPTY)
|
||||
285 () - (EMPTY)
|
||||
286 () - (EMPTY)
|
||||
287 () - (EMPTY)
|
||||
288 () - (EMPTY)
|
||||
289 () - (EMPTY)
|
||||
290 () - (EMPTY)
|
||||
291 () - (EMPTY)
|
||||
292 () - (EMPTY)
|
||||
293 () - (EMPTY)
|
||||
294 () - (EMPTY)
|
||||
295 () - (EMPTY)
|
||||
296 () - (EMPTY)
|
||||
297 () - (EMPTY)
|
||||
298 () - (EMPTY)
|
||||
299 () - (EMPTY)
|
||||
300 () - (EMPTY)
|
||||
301 () - (EMPTY)
|
||||
302 () - (EMPTY)
|
||||
303 () - (EMPTY)
|
||||
304 () - (EMPTY)
|
||||
305 () - (EMPTY)
|
||||
306 () - (EMPTY)
|
||||
307 () - (EMPTY)
|
||||
308 () - (EMPTY)
|
||||
309 () - (EMPTY)
|
||||
310 () - (EMPTY)
|
||||
311 () - (EMPTY)
|
||||
312 () - (EMPTY)
|
||||
313 () - (EMPTY)
|
||||
314 () - (EMPTY)
|
||||
315 () - (EMPTY)
|
||||
316 () - (EMPTY)
|
||||
317 () - (EMPTY)
|
||||
318 () - (EMPTY)
|
||||
319 () - (EMPTY)
|
||||
320 () - (EMPTY)
|
||||
321 () - (EMPTY)
|
||||
322 () - (EMPTY)
|
||||
323 () - (EMPTY)
|
||||
324 () - (EMPTY)
|
||||
325 () - (EMPTY)
|
||||
326 () - (EMPTY)
|
||||
327 () - (EMPTY)
|
||||
328 () - (EMPTY)
|
||||
329 () - (EMPTY)
|
||||
330 () - (EMPTY)
|
||||
331 () - (EMPTY)
|
||||
332 () - (EMPTY)
|
||||
333 () - (EMPTY)
|
||||
334 () - (EMPTY)
|
||||
335 () - (EMPTY)
|
||||
336 () - (EMPTY)
|
||||
337 () - (EMPTY)
|
||||
338 () - (EMPTY)
|
||||
339 () - (EMPTY)
|
||||
340 () - (EMPTY)
|
||||
341 () - (EMPTY)
|
||||
342 () - (EMPTY)
|
||||
343 () - (EMPTY)
|
||||
344 () - (EMPTY)
|
||||
345 (end) - The end.
|
||||
346 () - (EMPTY)
|
||||
347 () - (EMPTY)
|
||||
348 () - (EMPTY)
|
||||
349 () - (EMPTY)
|
||||
350 () - (EMPTY)
|
||||
351 () - (EMPTY)
|
||||
352 () - (EMPTY)
|
||||
353 () - (EMPTY)
|
||||
354 () - (EMPTY)
|
||||
355 () - (EMPTY)
|
||||
356 () - (EMPTY)
|
||||
357 () - (EMPTY)
|
||||
358 () - (EMPTY)
|
||||
359 () - (EMPTY)
|
||||
360 () - (EMPTY)
|
||||
361 () - (EMPTY)
|
||||
362 () - (EMPTY)
|
||||
363 () - (EMPTY)
|
||||
364 () - (EMPTY)
|
||||
365 () - (EMPTY)
|
||||
366 () - (EMPTY)
|
||||
367 () - (EMPTY)
|
||||
368 () - (EMPTY)
|
||||
369 () - (EMPTY)
|
||||
370 () - (EMPTY)
|
||||
371 () - (EMPTY)
|
||||
372 () - (EMPTY)
|
||||
373 () - (EMPTY)
|
||||
374 () - (EMPTY)
|
||||
375 () - (EMPTY)
|
||||
376 () - (EMPTY)
|
||||
377 () - (EMPTY)
|
||||
378 () - (EMPTY)
|
||||
379 () - (EMPTY)
|
||||
380 () - (EMPTY)
|
||||
381 () - (EMPTY)
|
||||
382 () - (EMPTY)
|
||||
383 () - (EMPTY)
|
||||
384 () - (EMPTY)
|
||||
385 () - (EMPTY)
|
||||
386 () - (EMPTY)
|
||||
387 () - (EMPTY)
|
||||
388 () - (EMPTY)
|
||||
389 () - (EMPTY)
|
||||
390 () - (EMPTY)
|
||||
391 () - (EMPTY)
|
||||
392 () - (EMPTY)
|
||||
393 () - (EMPTY)
|
||||
394 () - (EMPTY)
|
||||
395 () - (EMPTY)
|
||||
396 () - (EMPTY)
|
||||
397 () - (EMPTY)
|
||||
398 () - (EMPTY)
|
||||
399 () - (EMPTY)
|
||||
400 () - (EMPTY)
|
||||
END DEBUG OUTPUT
|
13
expected/references.dot
Normal file
13
expected/references.dot
Normal file
|
@ -0,0 +1,13 @@
|
|||
digraph gamebook {
|
||||
|
||||
|
||||
1->202
|
||||
|
||||
1->76
|
||||
76->202
|
||||
|
||||
76->67
|
||||
|
||||
76->345
|
||||
202->345
|
||||
}
|
374
expected/references.html
Normal file
374
expected/references.html
Normal file
|
@ -0,0 +1,374 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Gamebook</title>
|
||||
<script>
|
||||
var gamebook = {
|
||||
'player' : {
|
||||
'started' : false,
|
||||
'currentSection' : null,
|
||||
'collections' : {},
|
||||
|
||||
'collect' : function(type, name) {
|
||||
this.collections[type] = {
|
||||
'name' : name,
|
||||
'contents' : [],
|
||||
'add' : function(what) {
|
||||
if (this.contents.indexOf(what) === -1
|
||||
&& !(what in gamebook.dropped[type])) {
|
||||
this.contents.push(what);
|
||||
this.contents.sort();
|
||||
}
|
||||
},
|
||||
'drop' : function(what) {
|
||||
var i = this.contents.indexOf(what);
|
||||
if (i >= 0) {
|
||||
this.contents.splice(i, 1);
|
||||
gamebook.dropped[type][what] = true;
|
||||
}
|
||||
},
|
||||
'has' : function(what) {
|
||||
return this.contents.indexOf(what) >= 0;
|
||||
}
|
||||
};
|
||||
gamebook.dropped[type] = {};
|
||||
gamebook.addCollectionView(type, name);
|
||||
},
|
||||
|
||||
'add' : function(type, what) {
|
||||
this.collections[type].add(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'drop' : function(type, what) {
|
||||
this.collections[type].drop(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'has' : function(type, what) {
|
||||
return this.collections[type].has(what);
|
||||
}
|
||||
},
|
||||
|
||||
'sections' : {},
|
||||
|
||||
'turnToFunctions' : {},
|
||||
|
||||
'dropped' : {},
|
||||
|
||||
'addSection' : function(nr, element) {
|
||||
var section = {'element' : element, 'nr' : nr};
|
||||
this.sections[nr] = section;
|
||||
},
|
||||
|
||||
'turnTo' : function(nr) {
|
||||
if (!gamebook.player.started) {
|
||||
gamebook.start();
|
||||
}
|
||||
if (!nr in this.sections) {
|
||||
throw new Exception("Can not turn to non-existing section "
|
||||
+ nr + ".");
|
||||
}
|
||||
this.displaySection(nr);
|
||||
},
|
||||
|
||||
'start' : function() {
|
||||
this.hideIntroSections();
|
||||
this.addClassToClass('startlink', 'nodisplay');
|
||||
gamebook.player.started = true;
|
||||
},
|
||||
|
||||
'displaySection' : function(nr) {
|
||||
if (this.player.currentSection) {
|
||||
this.player.currentSection.element.style.display = 'none';
|
||||
}
|
||||
var e = this.sections[nr].element;
|
||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||
e.style.display = 'block';
|
||||
this.player.currentSection = gamebook.sections[nr];
|
||||
},
|
||||
|
||||
'hideIntroSections' : function() {
|
||||
this.addClassToClass('introsection', 'nodisplay');
|
||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||
},
|
||||
|
||||
'showIntroSections' : function() {
|
||||
this.runActionsInIntroSections();
|
||||
this.removeClassFromClass('introsection', 'nodisplay');
|
||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||
document.body.scrollIntoView();
|
||||
},
|
||||
|
||||
'runActionsInIntroSections' : function() {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName('introsectionbody'),
|
||||
gamebook.runActions);
|
||||
},
|
||||
|
||||
'addClassToClass' : function(className, addClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.add(addClass);
|
||||
});
|
||||
},
|
||||
|
||||
'removeClassFromClass' : function(className, removeClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.remove(removeClass);
|
||||
});
|
||||
},
|
||||
|
||||
'runActions' : function(e) {
|
||||
var enableNextLink = true;
|
||||
var hasXorScope = false;
|
||||
var hasAutoScope = false;
|
||||
var xorEnableNext = false;
|
||||
var autoDisableAllRemainingLinks = (
|
||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||
if (!c.classList) {
|
||||
return;
|
||||
}
|
||||
if (c.classList.contains('sectionref')) {
|
||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||
gamebook.enableLink(c);
|
||||
if (hasAutoScope) {
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
} else {
|
||||
gamebook.disableLink(c);
|
||||
}
|
||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||
hasAutoScope = false;
|
||||
hasXorScope = false;
|
||||
} else if (c.classList.contains('collect')) {
|
||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||
} else if (c.classList.contains('add')) {
|
||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('drop')) {
|
||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('has')) {
|
||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('hasnot')) {
|
||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('xor')) {
|
||||
hasXorScope = true;
|
||||
xorEnableNext = !enableNextLink;
|
||||
} else if (c.classList.contains('auto')) {
|
||||
hasAutoScope = true;
|
||||
} else if (c.classList.contains('random')) {
|
||||
c.addEventListener('click',
|
||||
gamebook.enableRandomLinkAfter);
|
||||
c.classList.add("enabledlink");
|
||||
c.classList.remove("disabledlink");
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'enableLink' : function(e) {
|
||||
e.addEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.add("enabledlink");
|
||||
e.classList.remove("disabledlink");
|
||||
},
|
||||
|
||||
'disableLink' : function(e) {
|
||||
e.removeEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.remove("enabledlink");
|
||||
e.classList.add("disabledlink");
|
||||
},
|
||||
|
||||
'enableRandomLinkAfter' : function(event) {
|
||||
this.classList.remove("enabledlink");
|
||||
this.classList.add("disabledlink");
|
||||
var links = [];
|
||||
var e = this.nextSibling;
|
||||
while (e) {
|
||||
if (e.classList && e.classList.contains('sectionref')) {
|
||||
links.push(e);
|
||||
}
|
||||
e = e.nextSibling;
|
||||
}
|
||||
if (links.length > 0) {
|
||||
var selected = links[Math.floor(Math.random()*links.length)]
|
||||
gamebook.enableLink(selected);
|
||||
} else {
|
||||
console.log("Random with nothing to select?");
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'addCollectionView' : function(type, name) {
|
||||
var ce = document.getElementById('collections');
|
||||
var template = document.getElementById('collectionTemplate');
|
||||
var e = template.cloneNode(true);
|
||||
e.className = "collection";
|
||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||
e.dataset.type = type;
|
||||
ce.appendChild(e);
|
||||
},
|
||||
|
||||
'updateCollectionsView' : function() {
|
||||
var ce = document.getElementById('collections');
|
||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||
if (c.className === 'collection') {
|
||||
var type = c.dataset.type;
|
||||
var collection = gamebook.player.collections[type];
|
||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||
cc.innerHTML = collection.contents.join(', ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getTurnToFunction' : function(nr) {
|
||||
if (nr in this.turnToFunctions) {
|
||||
return this.turnToFunctions[nr];
|
||||
} else {
|
||||
var f = function () {
|
||||
gamebook.turnTo(nr);
|
||||
};
|
||||
this.turnToFunctions[nr] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random {
|
||||
font-weight: bold;
|
||||
margin: 0.2em;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionref.enabledlink {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random {
|
||||
cursor: pointer;}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||
.random {background: #eef;
|
||||
}
|
||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||
.hideintrolink:hover {background: #a9f;}
|
||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||
.disabledlink:hover {background: inherit;}
|
||||
.sectionnumber {font-weight: bolder;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;}
|
||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||
.sectiontext {margin-top: 0.5em;}
|
||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||
.collections {margin-top: 4em;}
|
||||
.collection {background: #ddd; margin-top: 1em;}
|
||||
.collectionheading {}
|
||||
.collectionheading::after {content: ": ";}
|
||||
.collectioncontents {}
|
||||
.collect {}
|
||||
.add {font-weight: bold;}
|
||||
.drop {font-style: italic;}
|
||||
.has {font-style: italic;}
|
||||
.hasnot {font-style: italic;}
|
||||
.collectionTemplate {display: none;}
|
||||
.sectionimage {width: 100%; padding: 1em;}
|
||||
.nodisplay {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hideintrolink nodisplay"
|
||||
onclick="gamebook.hideIntroSections()">(hide instructions)</div>
|
||||
<div class="gamebook">
|
||||
|
||||
<div class="introsection">
|
||||
<span class="introsectionheading">Introduction</span>
|
||||
<div class="introsectionbody">
|
||||
This gamebook demonstrates simple references between sections. Also notice that an intro section like this one can reference sections, like the start at <a class="sectionref enabledlink" data-ref="1">1</a> or the next section at <a class="sectionref enabledlink" data-ref="202">202</a>.
|
||||
</div>
|
||||
</div>
|
||||
<div class="startlink"
|
||||
onclick="gamebook.turnTo(1)">Turn to 1 to begin.</div>
|
||||
|
||||
<div class="section" id="section1">
|
||||
<span class="sectionnumber" id="para1">1</span>
|
||||
<div class="sectiontext">
|
||||
This is where the adventure begins. You can go on to the next section, see <a class="sectionref enabledlink" data-ref="202">202</a> or try the random selection feature at <a class="sectionref enabledlink" data-ref="76">76</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(1, document.getElementById('section1'));
|
||||
}
|
||||
</script> <div class="section" id="section67">
|
||||
<span class="sectionnumber" id="para67">67</span>
|
||||
<div class="sectiontext">
|
||||
Alternative ending.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(67, document.getElementById('section67'));
|
||||
}
|
||||
</script> <div class="section" id="section76">
|
||||
<span class="sectionnumber" id="para76">76</span>
|
||||
<div class="sectiontext">
|
||||
<span class="random enabledlink">Pick a destination at random</span> from <a class="sectionref enabledlink" data-ref="202">202</a> or <a class="sectionref enabledlink" data-ref="345">345</a> or <a class="sectionref enabledlink" data-ref="67">67</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(76, document.getElementById('section76'));
|
||||
}
|
||||
</script> <div class="section" id="section202">
|
||||
<span class="sectionnumber" id="para202">202</span>
|
||||
<div class="sectiontext">
|
||||
This is the next section. Go on to the end at <a class="sectionref enabledlink" data-ref="345">345</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(202, document.getElementById('section202'));
|
||||
}
|
||||
</script> <div class="section" id="section345">
|
||||
<span class="sectionnumber" id="para345">345</span>
|
||||
<div class="sectiontext">
|
||||
The end.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(345, document.getElementById('section345'));
|
||||
}
|
||||
</script> <div id="collections" class="collections">
|
||||
</div>
|
||||
<div id="collectionTemplate" class="collectionTemplate">
|
||||
<span class="collectionheading"></span>
|
||||
<span class="collectioncontents"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.runActionsInIntroSections();
|
||||
}
|
||||
</script>
|
||||
<div class="displayintrolink nodisplay"
|
||||
onclick="gamebook.showIntroSections()">(show instructions)</div>
|
||||
</body>
|
||||
</html>
|
64
expected/references.rtf
Normal file
64
expected/references.rtf
Normal file
|
@ -0,0 +1,64 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww14140\viewh14860\viewkind0
|
||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\b\fs24 \cf0
|
||||
|
||||
\b \qc Gamebook
|
||||
\b0\
|
||||
|
||||
\b \qc Introduction
|
||||
\b0\
|
||||
|
||||
|
||||
|
||||
\ql This gamebook demonstrates simple references between sections. Also notice that an intro section like this one can reference sections, like the start at \b 1
|
||||
\b0
|
||||
or the next section at \b 202
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
\b Turn to 1 to begin.
|
||||
\b0\
|
||||
\
|
||||
|
||||
\b \qc 1
|
||||
\b0\
|
||||
\ql This is where the adventure begins. You can go on to the next section, see \b 202
|
||||
\b0
|
||||
or try the random selection feature at \b 76
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 67
|
||||
\b0\
|
||||
\ql Alternative ending. \
|
||||
\
|
||||
|
||||
\b \qc 76
|
||||
\b0\
|
||||
\ql Pick a destination at random from \b 202
|
||||
\b0
|
||||
or \b 345
|
||||
\b0
|
||||
or \b 67
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 202
|
||||
\b0\
|
||||
\ql This is the next section. Go on to the end at \b 345
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 345
|
||||
\b0\
|
||||
\ql The end. \
|
||||
\
|
||||
|
||||
}
|
481
expected/references.tex
Normal file
481
expected/references.tex
Normal file
|
@ -0,0 +1,481 @@
|
|||
\documentclass[a5,onecolumn]{book}
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\usepackage[top=3.3cm, bottom=3.3cm, left=2cm, right=2cm]{geometry}
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\ifnum\pdfoutput=1
|
||||
\pdftrue
|
||||
\else
|
||||
\pdffalse
|
||||
\fi
|
||||
\fi
|
||||
|
||||
\title{Gamebook}
|
||||
\author{}
|
||||
\date{}
|
||||
|
||||
\newcounter{sectionnr}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\clearpage
|
||||
|
||||
|
||||
\subsection*{\begin{center} \textbf{Introduction} \end{center}}
|
||||
|
||||
|
||||
\noindent
|
||||
This gamebook demonstrates simple references between sections. Also notice that an intro section like this one can reference sections, like the start at \textbf{\autoref{section1}} or the next section at \textbf{\autoref{section202}}.
|
||||
\vspace{1em}
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section1}
|
||||
\subsection*{\begin{center} \textbf{1} \end{center}}
|
||||
|
||||
\noindent
|
||||
This is where the adventure begins. You can go on to the next section, see \textbf{\autoref{section202}} or try the random selection feature at \textbf{\autoref{section76}}.
|
||||
\vspace{1em}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section67}
|
||||
\subsection*{\begin{center} \textbf{67} \end{center}}
|
||||
|
||||
\noindent
|
||||
Alternative ending.
|
||||
\vspace{1em}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section76}
|
||||
\subsection*{\begin{center} \textbf{76} \end{center}}
|
||||
|
||||
\noindent
|
||||
Pick a destination at random from \textbf{\autoref{section202}} or \textbf{\autoref{section345}} or \textbf{\autoref{section67}}.
|
||||
\vspace{1em}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section202}
|
||||
\subsection*{\begin{center} \textbf{202} \end{center}}
|
||||
|
||||
\noindent
|
||||
This is the next section. Go on to the end at \textbf{\autoref{section345}}.
|
||||
\vspace{1em}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section345}
|
||||
\subsection*{\begin{center} \textbf{345} \end{center}}
|
||||
|
||||
\noindent
|
||||
The end.
|
||||
\vspace{1em}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\refstepcounter{sectionnr}
|
||||
\end{document}
|
25
expected/references.txt
Normal file
25
expected/references.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
Gamebook
|
||||
|
||||
|
||||
Introduction
|
||||
This gamebook demonstrates simple references between sections. Also notice that an intro section like this one can reference sections, like the start at 1 or the next section at 202.
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1
|
||||
This is where the adventure begins. You can go on to the next section, see 202 or try the random selection feature at 76.
|
||||
|
||||
67
|
||||
Alternative ending.
|
||||
|
||||
76
|
||||
Pick a destination at random from 202 or 345 or 67.
|
||||
|
||||
202
|
||||
This is the next section. Go on to the end at 345.
|
||||
|
||||
345
|
||||
The end.
|
||||
|
||||
|
13
expected/unreachable.debug
Normal file
13
expected/unreachable.debug
Normal file
|
@ -0,0 +1,13 @@
|
|||
BEGIN DEBUG OUTPUT
|
||||
Book title: Gamebook
|
||||
Number of sections: 5
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1 (start) - It starts here. You can get to 4.
|
||||
2 (seconddummy) - Another fake section that is also ignored.
|
||||
3 (nothereeither) - You can not get here either, but because it is tagged as fake there will be no warning generated.
|
||||
4 (here) - You can get here. Congratulations!
|
||||
5 (nothere) - You can not get here. Verification should warn you about that, if enabled (with the --verify option).
|
||||
END DEBUG OUTPUT
|
5
expected/unreachable.dot
Normal file
5
expected/unreachable.dot
Normal file
|
@ -0,0 +1,5 @@
|
|||
digraph gamebook {
|
||||
|
||||
|
||||
1->4
|
||||
}
|
368
expected/unreachable.html
Normal file
368
expected/unreachable.html
Normal file
|
@ -0,0 +1,368 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Gamebook</title>
|
||||
<script>
|
||||
var gamebook = {
|
||||
'player' : {
|
||||
'started' : false,
|
||||
'currentSection' : null,
|
||||
'collections' : {},
|
||||
|
||||
'collect' : function(type, name) {
|
||||
this.collections[type] = {
|
||||
'name' : name,
|
||||
'contents' : [],
|
||||
'add' : function(what) {
|
||||
if (this.contents.indexOf(what) === -1
|
||||
&& !(what in gamebook.dropped[type])) {
|
||||
this.contents.push(what);
|
||||
this.contents.sort();
|
||||
}
|
||||
},
|
||||
'drop' : function(what) {
|
||||
var i = this.contents.indexOf(what);
|
||||
if (i >= 0) {
|
||||
this.contents.splice(i, 1);
|
||||
gamebook.dropped[type][what] = true;
|
||||
}
|
||||
},
|
||||
'has' : function(what) {
|
||||
return this.contents.indexOf(what) >= 0;
|
||||
}
|
||||
};
|
||||
gamebook.dropped[type] = {};
|
||||
gamebook.addCollectionView(type, name);
|
||||
},
|
||||
|
||||
'add' : function(type, what) {
|
||||
this.collections[type].add(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'drop' : function(type, what) {
|
||||
this.collections[type].drop(what);
|
||||
gamebook.updateCollectionsView();
|
||||
},
|
||||
|
||||
'has' : function(type, what) {
|
||||
return this.collections[type].has(what);
|
||||
}
|
||||
},
|
||||
|
||||
'sections' : {},
|
||||
|
||||
'turnToFunctions' : {},
|
||||
|
||||
'dropped' : {},
|
||||
|
||||
'addSection' : function(nr, element) {
|
||||
var section = {'element' : element, 'nr' : nr};
|
||||
this.sections[nr] = section;
|
||||
},
|
||||
|
||||
'turnTo' : function(nr) {
|
||||
if (!gamebook.player.started) {
|
||||
gamebook.start();
|
||||
}
|
||||
if (!nr in this.sections) {
|
||||
throw new Exception("Can not turn to non-existing section "
|
||||
+ nr + ".");
|
||||
}
|
||||
this.displaySection(nr);
|
||||
},
|
||||
|
||||
'start' : function() {
|
||||
this.hideIntroSections();
|
||||
this.addClassToClass('startlink', 'nodisplay');
|
||||
gamebook.player.started = true;
|
||||
},
|
||||
|
||||
'displaySection' : function(nr) {
|
||||
if (this.player.currentSection) {
|
||||
this.player.currentSection.element.style.display = 'none';
|
||||
}
|
||||
var e = this.sections[nr].element;
|
||||
this.runActions(e.getElementsByClassName('sectiontext')[0]);
|
||||
e.style.display = 'block';
|
||||
this.player.currentSection = gamebook.sections[nr];
|
||||
},
|
||||
|
||||
'hideIntroSections' : function() {
|
||||
this.addClassToClass('introsection', 'nodisplay');
|
||||
this.removeClassFromClass('displayintrolink', 'nodisplay');
|
||||
this.addClassToClass('hideintrolink', 'nodisplay');
|
||||
},
|
||||
|
||||
'showIntroSections' : function() {
|
||||
this.runActionsInIntroSections();
|
||||
this.removeClassFromClass('introsection', 'nodisplay');
|
||||
this.addClassToClass('displayintrolink', 'nodisplay');
|
||||
this.removeClassFromClass('hideintrolink', 'nodisplay');
|
||||
document.body.scrollIntoView();
|
||||
},
|
||||
|
||||
'runActionsInIntroSections' : function() {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName('introsectionbody'),
|
||||
gamebook.runActions);
|
||||
},
|
||||
|
||||
'addClassToClass' : function(className, addClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.add(addClass);
|
||||
});
|
||||
},
|
||||
|
||||
'removeClassFromClass' : function(className, removeClass) {
|
||||
Array.prototype.forEach.call(
|
||||
document.getElementsByClassName(className),
|
||||
function(e) {
|
||||
e.classList.remove(removeClass);
|
||||
});
|
||||
},
|
||||
|
||||
'runActions' : function(e) {
|
||||
var enableNextLink = true;
|
||||
var hasXorScope = false;
|
||||
var hasAutoScope = false;
|
||||
var xorEnableNext = false;
|
||||
var autoDisableAllRemainingLinks = (
|
||||
gamebook.player.started && e.classList.contains('introsectionbody'));
|
||||
Array.prototype.forEach.call(e.childNodes, function(c) {
|
||||
if (!c.classList) {
|
||||
return;
|
||||
}
|
||||
if (c.classList.contains('sectionref')) {
|
||||
if (enableNextLink && !autoDisableAllRemainingLinks) {
|
||||
gamebook.enableLink(c);
|
||||
if (hasAutoScope) {
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
} else {
|
||||
gamebook.disableLink(c);
|
||||
}
|
||||
enableNextLink = !(hasXorScope && !xorEnableNext);
|
||||
hasAutoScope = false;
|
||||
hasXorScope = false;
|
||||
} else if (c.classList.contains('collect')) {
|
||||
gamebook.player.collect(c.dataset.type, c.dataset.name);
|
||||
} else if (c.classList.contains('add')) {
|
||||
gamebook.player.add(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('drop')) {
|
||||
gamebook.player.drop(c.dataset.type, c.dataset.what);
|
||||
} else if (c.classList.contains('has')) {
|
||||
enableNextLink = gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('hasnot')) {
|
||||
enableNextLink = !gamebook.player.has(c.dataset.type,
|
||||
c.dataset.what);
|
||||
} else if (c.classList.contains('xor')) {
|
||||
hasXorScope = true;
|
||||
xorEnableNext = !enableNextLink;
|
||||
} else if (c.classList.contains('auto')) {
|
||||
hasAutoScope = true;
|
||||
} else if (c.classList.contains('random')) {
|
||||
c.addEventListener('click',
|
||||
gamebook.enableRandomLinkAfter);
|
||||
c.classList.add("enabledlink");
|
||||
c.classList.remove("disabledlink");
|
||||
autoDisableAllRemainingLinks = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'enableLink' : function(e) {
|
||||
e.addEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.add("enabledlink");
|
||||
e.classList.remove("disabledlink");
|
||||
},
|
||||
|
||||
'disableLink' : function(e) {
|
||||
e.removeEventListener('click',
|
||||
gamebook.getTurnToFunction(e.dataset.ref));
|
||||
e.classList.remove("enabledlink");
|
||||
e.classList.add("disabledlink");
|
||||
},
|
||||
|
||||
'enableRandomLinkAfter' : function(event) {
|
||||
this.classList.remove("enabledlink");
|
||||
this.classList.add("disabledlink");
|
||||
var links = [];
|
||||
var e = this.nextSibling;
|
||||
while (e) {
|
||||
if (e.classList && e.classList.contains('sectionref')) {
|
||||
links.push(e);
|
||||
}
|
||||
e = e.nextSibling;
|
||||
}
|
||||
if (links.length > 0) {
|
||||
var selected = links[Math.floor(Math.random()*links.length)]
|
||||
gamebook.enableLink(selected);
|
||||
} else {
|
||||
console.log("Random with nothing to select?");
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'addCollectionView' : function(type, name) {
|
||||
var ce = document.getElementById('collections');
|
||||
var template = document.getElementById('collectionTemplate');
|
||||
var e = template.cloneNode(true);
|
||||
e.className = "collection";
|
||||
e.getElementsByClassName('collectionheading')[0].innerHTML = name;
|
||||
e.dataset.type = type;
|
||||
ce.appendChild(e);
|
||||
},
|
||||
|
||||
'updateCollectionsView' : function() {
|
||||
var ce = document.getElementById('collections');
|
||||
Array.prototype.forEach.call(ce.childNodes, function(c) {
|
||||
if (c.className === 'collection') {
|
||||
var type = c.dataset.type;
|
||||
var collection = gamebook.player.collections[type];
|
||||
var cc = c.getElementsByClassName('collectioncontents')[0];
|
||||
cc.innerHTML = collection.contents.join(', ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getTurnToFunction' : function(nr) {
|
||||
if (nr in this.turnToFunctions) {
|
||||
return this.turnToFunctions[nr];
|
||||
} else {
|
||||
var f = function () {
|
||||
gamebook.turnTo(nr);
|
||||
};
|
||||
this.turnToFunctions[nr] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.startlink,.sectionref,.displayintrolink,.hideintrolink,.found,.add,.random {
|
||||
font-weight: bold;
|
||||
margin: 0.2em;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionref.enabledlink {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,.random {
|
||||
cursor: pointer;}
|
||||
|
||||
.startlink,.enabledlink,.displayintrolink,.hideintrolink,.found,
|
||||
.random {background: #eef;
|
||||
}
|
||||
.startlink:hover,.enabledlink:hover,.displayintrolink:hover,
|
||||
.hideintrolink:hover {background: #a9f;}
|
||||
.disabledlink {color: #bbb; cursor: not-allowed; background: inherit;}
|
||||
.disabledlink:hover {background: inherit;}
|
||||
.sectionnumber {font-weight: bolder;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;}
|
||||
.section {display: none; width: 90%; margin-left: 5%; margin-right: 5%;}
|
||||
.sectiontext {margin-top: 0.5em;}
|
||||
.gamebook {max-width: 30em; padding: 1em; width: 100%; font-size: 133%;}
|
||||
.collections {margin-top: 4em;}
|
||||
.collection {background: #ddd; margin-top: 1em;}
|
||||
.collectionheading {}
|
||||
.collectionheading::after {content: ": ";}
|
||||
.collectioncontents {}
|
||||
.collect {}
|
||||
.add {font-weight: bold;}
|
||||
.drop {font-style: italic;}
|
||||
.has {font-style: italic;}
|
||||
.hasnot {font-style: italic;}
|
||||
.collectionTemplate {display: none;}
|
||||
.sectionimage {width: 100%; padding: 1em;}
|
||||
.nodisplay {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hideintrolink nodisplay"
|
||||
onclick="gamebook.hideIntroSections()">(hide instructions)</div>
|
||||
<div class="gamebook">
|
||||
|
||||
<div class="startlink"
|
||||
onclick="gamebook.turnTo(1)">Turn to 1 to begin.</div>
|
||||
|
||||
<div class="section" id="section1">
|
||||
<span class="sectionnumber" id="para1">1</span>
|
||||
<div class="sectiontext">
|
||||
It starts here. You can get to <a class="sectionref enabledlink" data-ref="4">4</a>.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(1, document.getElementById('section1'));
|
||||
}
|
||||
</script> <div class="section" id="section2">
|
||||
<span class="sectionnumber" id="para2">2</span>
|
||||
<div class="sectiontext">
|
||||
Another fake section that is also ignored.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(2, document.getElementById('section2'));
|
||||
}
|
||||
</script> <div class="section" id="section3">
|
||||
<span class="sectionnumber" id="para3">3</span>
|
||||
<div class="sectiontext">
|
||||
You can not get here either, but because it is tagged as fake there will be no warning generated.
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(3, document.getElementById('section3'));
|
||||
}
|
||||
</script> <div class="section" id="section4">
|
||||
<span class="sectionnumber" id="para4">4</span>
|
||||
<div class="sectiontext">
|
||||
You can get here. Congratulations!
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(4, document.getElementById('section4'));
|
||||
}
|
||||
</script> <div class="section" id="section5">
|
||||
<span class="sectionnumber" id="para5">5</span>
|
||||
<div class="sectiontext">
|
||||
You can not get here. Verification should warn you about that, if enabled (with the --verify option).
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.addSection(5, document.getElementById('section5'));
|
||||
}
|
||||
</script> <div id="collections" class="collections">
|
||||
</div>
|
||||
<div id="collectionTemplate" class="collectionTemplate">
|
||||
<span class="collectionheading"></span>
|
||||
<span class="collectioncontents"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
if (this.gamebook) {
|
||||
gamebook.runActionsInIntroSections();
|
||||
}
|
||||
</script>
|
||||
<div class="displayintrolink nodisplay"
|
||||
onclick="gamebook.showIntroSections()">(show instructions)</div>
|
||||
</body>
|
||||
</html>
|
43
expected/unreachable.rtf
Normal file
43
expected/unreachable.rtf
Normal file
|
@ -0,0 +1,43 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww14140\viewh14860\viewkind0
|
||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\b\fs24 \cf0
|
||||
|
||||
\b \qc Gamebook
|
||||
\b0\
|
||||
|
||||
\b Turn to 1 to begin.
|
||||
\b0\
|
||||
\
|
||||
|
||||
\b \qc 1
|
||||
\b0\
|
||||
\ql It starts here. You can get to \b 4
|
||||
\b0
|
||||
. \
|
||||
\
|
||||
|
||||
\b \qc 2
|
||||
\b0\
|
||||
\ql Another fake section that is also ignored. \
|
||||
\
|
||||
|
||||
\b \qc 3
|
||||
\b0\
|
||||
\ql You can not get here either, but because it is tagged as fake there will be no warning generated. \
|
||||
\
|
||||
|
||||
\b \qc 4
|
||||
\b0\
|
||||
\ql You can get here. Congratulations! \
|
||||
\
|
||||
|
||||
\b \qc 5
|
||||
\b0\
|
||||
\ql You can not get here. Verification should warn you about that, if enabled (with the --verify option). \
|
||||
\
|
||||
|
||||
}
|
80
expected/unreachable.tex
Normal file
80
expected/unreachable.tex
Normal file
|
@ -0,0 +1,80 @@
|
|||
\documentclass[a5,onecolumn]{book}
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\usepackage[top=3.3cm, bottom=3.3cm, left=2cm, right=2cm]{geometry}
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\ifnum\pdfoutput=1
|
||||
\pdftrue
|
||||
\else
|
||||
\pdffalse
|
||||
\fi
|
||||
\fi
|
||||
|
||||
\title{Gamebook}
|
||||
\author{}
|
||||
\date{}
|
||||
|
||||
\newcounter{sectionnr}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\clearpage
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section1}
|
||||
\subsection*{\begin{center} \textbf{1} \end{center}}
|
||||
|
||||
\noindent
|
||||
It starts here. You can get to \textbf{\autoref{section4}}.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section2}
|
||||
\subsection*{\begin{center} \textbf{2} \end{center}}
|
||||
|
||||
\noindent
|
||||
Another fake section that is also ignored.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section3}
|
||||
\subsection*{\begin{center} \textbf{3} \end{center}}
|
||||
|
||||
\noindent
|
||||
You can not get here either, but because it is tagged as fake there will be no warning generated.
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section4}
|
||||
\subsection*{\begin{center} \textbf{4} \end{center}}
|
||||
|
||||
\noindent
|
||||
You can get here. Congratulations!
|
||||
\vspace{1em}
|
||||
\phantomsection
|
||||
\refstepcounter{sectionnr}
|
||||
\label{section5}
|
||||
\subsection*{\begin{center} \textbf{5} \end{center}}
|
||||
|
||||
\noindent
|
||||
You can not get here. Verification should warn you about that, if enabled (with the --verify option).
|
||||
\vspace{1em}
|
||||
\end{document}
|
21
expected/unreachable.txt
Normal file
21
expected/unreachable.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
Gamebook
|
||||
|
||||
|
||||
|
||||
Turn to 1 to begin.
|
||||
|
||||
1
|
||||
It starts here. You can get to 4.
|
||||
|
||||
2
|
||||
Another fake section that is also ignored.
|
||||
|
||||
3
|
||||
You can not get here either, but because it is tagged as fake there will be no warning generated.
|
||||
|
||||
4
|
||||
You can get here. Congratulations!
|
||||
|
||||
5
|
||||
You can not get here. Verification should warn you about that, if enabled (with the --verify option).
|
||||
|
4
todo.org
4
todo.org
|
@ -1,4 +1,4 @@
|
|||
* TODO [39/67] [58%]
|
||||
* TODO [40/67] [59%]
|
||||
- [X] Debug output
|
||||
- [X] DOT output
|
||||
- [X] LaTeX output
|
||||
|
@ -45,7 +45,7 @@
|
|||
eg [a-z][a-z_0-9]+
|
||||
- [X] Random pick of link to follow from a section.
|
||||
- [X] Possibility to make predictable random numbers and shuffling for testing
|
||||
- [ ] Test generate examples and compare to expected output in all formats
|
||||
- [X] Test generate examples and compare to expected output in all formats
|
||||
- [ ] Unit tests (finally...)
|
||||
- [ ] Verify gamebook (always; drop the --verify option)
|
||||
- [ ] Dummy and fake sections (handle properly when verifying)
|
||||
|
|
Loading…
Reference in a new issue