Skip to content

Instantly share code, notes, and snippets.

@ronsims2
Forked from anonymous/index.html
Created September 22, 2015 12:32
Show Gist options
  • Save ronsims2/6a28d13047239608f2cb to your computer and use it in GitHub Desktop.
Save ronsims2/6a28d13047239608f2cb to your computer and use it in GitHub Desktop.
JS Bin // source https://jsbin.com/sibonu/170
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<script id="jsbin-javascript">
(function(w){
/**
*@todo create api to set things like game name so that direct source code manipulation does have to occur
* use string commands to tell the ge what to do, ie return object with key pair command and param
* add game over and quit screens, build inventory screen logic
*/
var screenTmpl = {
id: 0,
title:"",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
break;
case "B":
break;
case "C":
break;
case "D":
break;
case "E":
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
};
/**
*@todo set gems to zero and potion to false and hearst to 5
*/
var gameData = {
name: "Tank",
hearts: 5,
matches: 5,
lantern: false,// use numeric to count how many times lantern was tried to get
gems: 0,
rescuee: "Helga",
enemies: ["Grublor", "Stolak"],
forestKey: false,
forestBossKey: false,
silverSword: true,
leatherShield: false,
heartPotion: false,
bosses: [{name: "King Malvox", hearts: 7}],
_currentScreen: 0,
_previousScreen: 0,
_currentBoss: "",
_currentShield: 0,
_heartLimit: 5,
_gameOverWin: 43,
_gameOverLose: 42,
_quitScreen: 44,
_inventoryScreen: 40,
_creditsScreen: 41,
inventory: {
sword: {
title: "Sword",
name: "---"
},
shield: {
title: "Shield",
name: "---"
},
light: {
title: "Light",
name: "---"
},
key: {
title: "key",
name: "---"
}
},
screens: [{
id: 1,
title: "The Legend of Helga",
text: "Click OK to begin.",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
action: function(ge, gd, answer){
//initialize inventory here
var matches = "Matches (" + ge.getItem("matches") + ")";
ge.setInventory('light', 'Light', matches);
return {goto: 2};
}
}, {
id: 2,
title:"Before we get started...",
text: "Adventurer, what is your name?",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
if (answer.match(/[A-Za-z0-9]+/)) {
act.goto = 4;
ge.setItem('name', answer);
}
else {
act.goto = 3;
}
return act;
}
}, {
id: 3,
title:"That's not a name!",
text: "It's not that hard, just type your name.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 2};
}
}, {
id: 4,
title:"{{RESCUEE}} has been kidknapped!",
text: "The local village blacksmith said that he saw her taken into the forest by a shadowy figure. " +
"He gave you a Silver Sword to help you in your quest. You'd better hurry into the forest and save her. ",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 5,
title:"{{RESCUEE}} is not going to save herself",
text: "where will you start?",
a: "Venture into the Dark Forest",
b: "Vist the Dark Forest Temple",
c: "QUIT",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
act.goto = 7;
break;
case "B":
act.goto = 6;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 6,
title: "You need a key to get in the Dark Forest Temple.",
text: "Maybe you should look for one in the forest.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 7,
title:"The forest is dark.",
text: "you will need a lantern to find anything, what will you do?",
a: "Look for a lantern",
b: "Look for the temple key",
c: "Go to the Forest Temple",
d: "QUIT",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var roll = ge.rollDice();
var matches = ge.getItem('matches');
var forestKey = ge.getItem('forestKey');
//remove a match if there is no lantern, this must happen before matches value read
if (!lantern) {
//ge.adjustItem('matches', -1);
act.matches = -1;
}
//If there are no matches the game is over
if (!matches && !lantern) {
act.goto = 11;
/**
*@todo replace with real game over screen
*/
return act;
}
switch(answer){
case "A":
if(lantern) {
act.goto = 10;
return act;
}
//Assume no lantern if here
if (roll > 6) {
act.goto = 8;
}
else {
if(matches) {
act.goto = 9;
}
else {
act.goto = 11;
}
}
break;
case "B":
if (forestKey) {
act.goto = 17;
return act;
}
if (roll > 6) {
act.goto = 12;
}
else {
act.goto = 13;//key not found
}
break;
case "C":
if (forestKey) {
//hide key from inventory, it has been used
ge.setInventory("key", "", "---");
act.goto = 18;
}
else {
act.goto = 16;
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 8,
title:"You found a lantern!",
text: "Now you don't have to keep burning your fingers with those pesky matches.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
//change screen sevens message, zero indexed!
ge.setItem('lantern', true);
ge.setInventory("light", "", "Eternal Lantern");
gd.screens[6].title = "Keep your sword ready {{NAME}}.";
gd.screens[6].text = "The light of the lantern has show the true danger ahead. What will you do?";
return {goto: 7};
}
}, {
id: 9,
title:"Drats, you didn't find a lantern yet.",
text: "You'd better hurry you only have {{MATCHES}} matches left!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var matches = ge.getItem('matches');
if (matches) {
act.goto = 7;
}
else {
act.goto = 11;
}
return act;
}
}, {
id: 10,
title:"You can't find something you already have.",
text: "look for the key already!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 11,
title: "As your last match burned to cinder, you saw your hope fade to blackness.",
text: "You are lost forever in darkness. -GAME OVER.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 999};
}
}, {
id: 12,
title: "Hooray!",
text: "You found the Forest Temple key.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestKey', true);
ge.setInventory("key", "", "Forest Temple Key");
return {goto: 7};//forest temple screen
}
}, {
id: 13,//battle screen
title: "An {{ENEMY}} has appear.",
text: "Prepare for battle, I hope your sword is sharp.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 7) {
act.goto = 14;
}
else {
act.goto = 15;
//act.hearts = -1;
}
return act;
}
}, {
id: 14,//battle screen
title: "Victory is Yours {{NAME}}.",
text: "Your fought valiantly and earned 5 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
gems: 5
};
}
}, {
id: 15,
title: "The agnony of defeat!",
text: "Your managed to slay the beast but not before sustaining some damage.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
hearts: -1
};
}
}, {
id: 16,
title: "You need a key to enter the Temple.",
text: "Maybe you should better equip yourself before you head to the temple.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 17,
title: "{{NAME}} you are not going to find another key.",
text: "Is it time to head to the temple?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 18,
title: "Forest Temple Entrance",
text: "Stay alert, this temple is very dangerous, {{NAME}} what will you do?",
a: "Visit the temple shop",
b: "Explore the temple",
c: "Enter Boss Room",
d: "Quit",
e: "",
action: function (ge, gd, answer){
//Set _currentBoss
if (!ge.getItem('_currentBoss')) {
var boss = ge.getBoss(1);
ge.setItem('_currentBoss', boss);
}
//change screen text if boss key found
var bossKey = ge.getItem('forestBossKey');
var lantern = ge.getItem('lantern');
/* This dynamically changed he screen text
if (bossKey) {
var scr = ge.getScreen(gd, 17);
if (scr){
scr.c = "Enter Boss Room";
scr.d = "Quit";
}
}*/
var act = {};
var roll = ge.rollDice();
switch(answer){
case "A":
act.goto = 19;
break;
case "B":
if (!lantern){
act.matches = -1;
}
// find chest
if (roll === 1 || roll === 12) {
act.goto = 26;
}
//find
if (roll === 9 || roll === 10 || roll === 11) {
act.goto = 27;
}
//fight here
if (roll === 2 || roll === 3 || roll === 4 || roll === 5 || roll === 6 || roll === 7 || roll === 8) {
act.goto = 28;
}
break;
case "C":
console.log('boss key ', bossKey);
if (bossKey) {
act.goto = 31;
/**
*@todo send to boss screen
*/
console.log('gotta key');
}
else {
act.goto = 32;
console.log('no key');
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 19,
title: "Hayloo, welcome to my shop.",
text: "I am Dreeko, What would yoooh like to buy?",
a: "A lantern - 20 gems",
b: "5 matches 10 gems",
c: "A leather shield - 25 gems",
d: "A heart potion - 15 gems",
e: "Exit the shop",
action: function (ge, gd, answer){
var lanternPrice = 20;//20
var shieldPrice = 25;//35
var potionPrice = 15;//15
var act = {};
var gems = ge.getItem('gems');
var lantern = ge.getItem('lantern');
var shield = ge.getItem('leatherShield');
var potion = ge.getItem('heartPotion');
switch(answer){
case "A":
if (lantern) {
act.goto = 20;
}
else {
if (ge.sellItem('lantern', lanternPrice)) {
act.goto = 21;
}
else {
act.goto = 22;
}
}
break;
case "B":
act.goto = 23;
break;
case "C":
if (shield) {
act.goto = 20;
}
else {
if (ge.sellItem('leatherShield', shieldPrice)) {
act.goto = 24;
}
else {
act.goto = 22;
}
}
break;
case "D":
if (potion) {
act.goto = 20;
}
else {
if (ge.sellItem('heartPotion', potionPrice)) {
act.goto = 25;
}
else {
act.goto = 22;
}
}
break;
case "E":
act.goto = 18;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 20,
title: "Looks like you already have one of those.",
text: "As much as Dreeko would like to sell you another one, I just can't.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 21,
title: "{{NAME}} you are the owner of a shiny new lantern!",
text: "Dreeko thinks you could have saved money looking for one in the forest though...",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("light", "", "Eternal Lantern");
return {goto: 19};
}
}, {
id: 22,
title: "Dreeko really likes chraity but I have 9 kids to feed.",
text: "Maybe you should check the temple for treasure and come back later?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 23,
title: "I'd really like to sell you something but, in this temple, you really need a lantern.",
text: "Maybe there is somethign else you need?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 24,
title: "Dreeko thinks you are smart.",
text: "The leather shield will cut your damage in half",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentShield', 1);
ge.setInventory("shield", "", "Leather Shield");
return {goto: 19};
}
}, {
id: 25,
title: "This potion is quite special.",
text: "if you fall in battle it will revive you to full health.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("potion", "Heart Potion", "Fairy Syrup");
return {goto: 19};
}
}, {
id: 26,
title: "What luck!",
text: "You found a chest that contains 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.adjustItem('gems', 10);
return {goto: 18};
}
}, {
id: 27,
title: "You found the boss room.",
text: "Are you ready to do battle?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestBossKey', true);
ge.setInventory("key", "", "Forest Boss Key");
return {goto: 18};
}
}, {
id: 28,
title: "An {{ENEMY}} appeared, prepare for battle.",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 8) {
//win
act.goto = 29;
}
else {
act.goto = 30;
}
return act;
}
}, {
id: 29,
title: "BEAST-MODE activated, you slayed the enemy!",
text: "You just earned 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
gems: 10
};
}
}, {
id: 30,
title: "Temple monsters are stonger than those found in the forest.",
text: "You defeated your foe but were injured in the process.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
hearts: -2
};
}
}, {
id: 31,
title: "<<<{{BOSS}}>>> - Forest Temple Boss.",
text: "Strike fast or perish.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 32,
title: "You Cannot enter this Room",
text: "You must explore the temple to find the boss room key to get in.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 18};
}
}, {
id: 33,
title: "{{BOSS}} is charging you.",
text: "What will you do?",
a: "Sword attack",
b: "Try special attack",
c: "Dodge",
d: "Quit",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll1 = ge.rollDice();
var roll2 = ge.rollDice();
switch(answer){
case "A":
if (roll1 > 6) {
act.goto = 34;
}
else {
act.goto = 35;
}
break;
case "B":
if (roll1 === roll2 || (roll1 + roll2 === 14)) {
act.goto = 36;
}
else {
act.goto = 37;
}
break;
case "C":
act.goto = 38;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 34,
title: "Excellent attack {{NAME}}!",
text: "Keep this up and {{BOSS}} will be defeated soon.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -1);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 35,
title: "{{BOSS}} is a skilled figher.",
text: "You have been injured, I'm not sure how much of this you can take.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 36,
title: "<< Five Strike Blazing Slash >> - Special Attack Unleashed!",
text: "You inflicted major damage to {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -3);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 37,
title: "Special attacks are not easy to pull off.",
text: "{{BOSS}} struck before you could power up.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 38,
title: "You can't run forever {{NAME}}.",
text: "The only way to free {{RESCUEE}} is to defeat {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 39,
title: "You defeated {{BOSS}}.",
text: "A hidden stone door crumbles and the {{RESCUEE}} runs out and hugs you. Thank you for saving me {{NAME}} I do not know how to thank you! \n" +
"Congratulations what will you next quest be?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentBoss', null);
ge.adjustItem('_heartLimit', 1);
ge.setItem('hearts', ge.getItem('_heartLimit'));
return {goto: 9999};
}
}, {
id: 40,
title: "Inventory",
text: "{{INVENTORY}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var screenNum = ge.getItem("_previousScreen");
return {goto: screenNum};
}
}, {
id: 41,
title: "Credits",
text: "{{CREDITS}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 42,
title: "Game Over",
text: "What is that sad music playing? Try again?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 43,
title: "Game Over",
text: "Congradulation! You saved Princess {{RESCUEE}}. {{NAME}}, perhaps now you might create your own quest?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 44,
title: "Quitters never prosper.",
text: "What's the matter {{NAME}} couldn't take it?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}]
};
var gameEngine = {
tokens: ["{{NAME}}", "{{TITLE}}", "{{RESCUEE}}", "{{MATCHES}}", "{{HEARTS}}", "{{GEMS}}", "{{ENEMY}}", "{{BOSS}}", "{{INVENTORY}}"],
tokenHandlers: ["name", "title", "rescuee", "matches", "hearts", "gems", "getEnemy", "getCurrentBossName", "formatInventory"],
getScreen: function(gd, num){
var scr = gd.screens[num] || false;
return scr;
},
showScreen: function(gd, screenNum){
var display = this.getScreenText(gd, screenNum);
var answer = "";
if (display.text) {
var opts = display.opts ? '\n' + display.opts + display.bar + '\n' + display.stats : display.bar + '\n' + display.stats;
if (display.stats) {
display.opts += display.bar + '\n' + display.stats;
}
if (display.usePrompt) {
answer = prompt(display.text + opts);
}
else {
alert(display.text);
}
this.process(gd, screenNum, answer);
return true;
}
else {
return false;
}
},
getScreenText: function(gd, screenNum){
var scr = gd.screens[screenNum - 1];
var display = {
text: "",
opts: "",
bar: "****************************************",
usePrompt: false,
stats: this.getStats()
};
if (scr) {
display.text = scr.title + "\n" + display.bar + "\n" + scr.text + "\n";
//opts = scr.a + "\n" + scr.b + "\n" + scr.c + "\n" + scr.d + "\n" + scr.e + "\n";
for (var opt in scr) {
if (opt === "a" || opt === "b" || opt === "c" || opt === "d" || opt === "e") {
if (scr[opt]) {
display.opts += opt.toUpperCase() + ") " + scr[opt] + "\n";
}
}
}
if (display.opts.trim() || scr.usePrompt) {
display.usePrompt = true;
}
if (scr.hideStats) {
display.stats = "";
}
//pre process text
display.text = this.parse(display.text);
display.opts = this.parse(display.opts);
return display;
}
return false;
},
getStats: function(){
var text = "Hearts: {{HEARTS}}\n";
text += "Gems: {{GEMS}}\n";
text = this.parse(text);
return text;
},
formatInventory: function(){
var inv = this.getItem("inventory");
var text = "";
var bar = "====================";
text += bar + "";
for(var item in inv){
var itm = inv[item];
text += "\n" + itm.title + ": " + itm.name + "\n" + bar;
}
return text;
},
setInventory: function(item, title, name) {
var inv = this.getItem("inventory");
var itm = inv[item] || {title: "Unknown", name: ""};
if (title){
itm.title = title;
}
if (name) {
itm.name = name;
}
inv[item] = itm;
},
getData: function(){
return gameData;
},
getTokens: function(){
return this.tokens;
},
addToken: function(tkn, meth){
if (tkn && meth){
this.tokens.push(tkn.toString());
this.tokenHandlers.push(meth);
}
},
parse: function(txt, tokens){//Parse tokens
if (!tokens) {
tokens = this.getTokens();
}
for (var i = 0; i < tokens.length; i++){
var tkn = this.tokens[i];
var item = this.tokenHandlers[i];
var val = this.getItem(item);
var handler = this[item] || false;
if (typeof(handler) === 'function') {
val = handler.apply(this);
}
txt = txt.replace(tkn, val);
}
return txt;
},
//Handle common screen operations
process: function(gd, screenNum, answer){
this.setItem("_previousScreen", this.getItem("_currentScreen"));// Use this if you have menu commands that need to return to the current action screen
this.setItem("_currentScreen", screenNum);
if (answer) {
answer = answer.trim().toUpperCase();
}
var act = gd.screens[screenNum - 1].action(this, gd, answer);// call screen specific logic
if (act) {
var hearts = act.hearts || 0;// heart adjustment
var currentHearts = this.getItem('hearts');
var goto = act.goto || 99999;
var gems = act.gems || 0;
var potion = this.getItem('heartPotion');
var matches = act.matches || 0;
var shield = this.getItem('_currentShield') || 0;
if (matches) {
this.adjustItem('matches', matches);
var matchesText = "Matches (" + this.getItem("matches") + ")";
this.setInventory('light', 'Light', matchesText);
}
/*
remove or add hearts first if hearts === 0 game is over unless hasHeartPotion === true
return false to quit
*/
if (hearts){
if (hearts < 0) {
//use shield
hearts = Math.floor(hearts + shield);
if (!hearts) {
hearts = - 0.5;
}
}
currentHearts = this.adjustItem('hearts', hearts);
}
//Revive player
if (!currentHearts && potion) {
this.adjustItem('hearts', this.getItem('_heartLimit'));
this.setItem('heartPotion', false);
ths.setInventory("potion", "", "---");
currentHearts = this.adjustItem('hearts', hearts);
}
//game over player was killed
if (!currentHearts) {
console.log('Process: game over.');
return false;
}
//handle gems
if (gems) {
this.adjustItem('gems', gems);
}
if (goto) {
this.showScreen(gd, goto);
}
}
else {
this.showScreen(gd, currentScreen);
}
return false;
},
rollDice: function(){
var diceNumber = Math.random() * 12 + 1;
diceNumber = Math.floor(diceNumber);
return diceNumber;
},
getItem: function(name){
if (name) {
var item = gameData[name];
return item;
}
},
setItem: function(name, val){
if (!val) {
val = false; //use false instead of falsey
}
if (name){
gameData[name] = val;
}
},
showScreenTmpl: function(){
console.log('screen template ', screenTmpl);
},
setTitle: function(title){
if (title) {
gameData.screens[0].title = title;
}
var ttl = gameData.screens[0].title;
gameData.title = ttl;
},
getTitle: function(){
return gameData.screens[0].title;
},
adjustItem: function(name, val){
if (name && val) {
var item = this.getItem(name);
item = item + val;
if (item < 0) {
item = 0;
}
gameData[name] = item;
return gameData[name];
}
},
getRandomNum: function(num){
num = num ? num : 1;
return Math.floor(Math.random() * num);
},
getEnemy: function(num){
var nmes = gameData.enemies;
var nme = "";
if (num) {
nme = nmes[num] || "";
}
else {
var rnum = this.getRandomNum(nmes.length);
nme = nmes[rnum];
}
return nme;
},
getBoss: function(num){
var bosses = this.getItem("bosses");
var boss = bosses[num - 1];
return boss;
},
attack: function(target, damage){
var hearts = target.hearts;
hearts = hearts + damage;
if (hearts < 0) {
hearts = 0;
}
target.hearts = hearts;
return hearts;
},
getCurrentBossName: function(){
var boss = this.getItem('_currentBoss') || {};
return boss.name || "";
},
sellItem: function(item, price){
var gems = this.getItem('gems');
if (gems >= price) {
this.adjustItem('gems', (price * -1));
this.setItem(item, true);
return true;
}
return false;
},
start: function(gd){
this.setTitle();
this.showScreen(gd, 1);
}
};
if (w) {
w.ge = gameEngine;
}
return gameEngine;
})(window);
var gd = ge.getData();
ge.start(gd);
</script>
<script id="jsbin-source-javascript" type="text/javascript">(function(w){
/**
*@todo create api to set things like game name so that direct source code manipulation does have to occur
* use string commands to tell the ge what to do, ie return object with key pair command and param
* add game over and quit screens, build inventory screen logic
*/
var screenTmpl = {
id: 0,
title:"",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
break;
case "B":
break;
case "C":
break;
case "D":
break;
case "E":
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
};
/**
*@todo set gems to zero and potion to false and hearst to 5
*/
var gameData = {
name: "Tank",
hearts: 5,
matches: 5,
lantern: false,// use numeric to count how many times lantern was tried to get
gems: 0,
rescuee: "Helga",
enemies: ["Grublor", "Stolak"],
forestKey: false,
forestBossKey: false,
silverSword: true,
leatherShield: false,
heartPotion: false,
bosses: [{name: "King Malvox", hearts: 7}],
_currentScreen: 0,
_previousScreen: 0,
_currentBoss: "",
_currentShield: 0,
_heartLimit: 5,
_gameOverWin: 43,
_gameOverLose: 42,
_quitScreen: 44,
_inventoryScreen: 40,
_creditsScreen: 41,
inventory: {
sword: {
title: "Sword",
name: "---"
},
shield: {
title: "Shield",
name: "---"
},
light: {
title: "Light",
name: "---"
},
key: {
title: "key",
name: "---"
}
},
screens: [{
id: 1,
title: "The Legend of Helga",
text: "Click OK to begin.",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
action: function(ge, gd, answer){
//initialize inventory here
var matches = "Matches (" + ge.getItem("matches") + ")";
ge.setInventory('light', 'Light', matches);
return {goto: 2};
}
}, {
id: 2,
title:"Before we get started...",
text: "Adventurer, what is your name?",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
if (answer.match(/[A-Za-z0-9]+/)) {
act.goto = 4;
ge.setItem('name', answer);
}
else {
act.goto = 3;
}
return act;
}
}, {
id: 3,
title:"That's not a name!",
text: "It's not that hard, just type your name.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 2};
}
}, {
id: 4,
title:"{{RESCUEE}} has been kidknapped!",
text: "The local village blacksmith said that he saw her taken into the forest by a shadowy figure. " +
"He gave you a Silver Sword to help you in your quest. You'd better hurry into the forest and save her. ",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 5,
title:"{{RESCUEE}} is not going to save herself",
text: "where will you start?",
a: "Venture into the Dark Forest",
b: "Vist the Dark Forest Temple",
c: "QUIT",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
act.goto = 7;
break;
case "B":
act.goto = 6;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 6,
title: "You need a key to get in the Dark Forest Temple.",
text: "Maybe you should look for one in the forest.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 7,
title:"The forest is dark.",
text: "you will need a lantern to find anything, what will you do?",
a: "Look for a lantern",
b: "Look for the temple key",
c: "Go to the Forest Temple",
d: "QUIT",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var roll = ge.rollDice();
var matches = ge.getItem('matches');
var forestKey = ge.getItem('forestKey');
//remove a match if there is no lantern, this must happen before matches value read
if (!lantern) {
//ge.adjustItem('matches', -1);
act.matches = -1;
}
//If there are no matches the game is over
if (!matches && !lantern) {
act.goto = 11;
/**
*@todo replace with real game over screen
*/
return act;
}
switch(answer){
case "A":
if(lantern) {
act.goto = 10;
return act;
}
//Assume no lantern if here
if (roll > 6) {
act.goto = 8;
}
else {
if(matches) {
act.goto = 9;
}
else {
act.goto = 11;
}
}
break;
case "B":
if (forestKey) {
act.goto = 17;
return act;
}
if (roll > 6) {
act.goto = 12;
}
else {
act.goto = 13;//key not found
}
break;
case "C":
if (forestKey) {
//hide key from inventory, it has been used
ge.setInventory("key", "", "---");
act.goto = 18;
}
else {
act.goto = 16;
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 8,
title:"You found a lantern!",
text: "Now you don't have to keep burning your fingers with those pesky matches.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
//change screen sevens message, zero indexed!
ge.setItem('lantern', true);
ge.setInventory("light", "", "Eternal Lantern");
gd.screens[6].title = "Keep your sword ready {{NAME}}.";
gd.screens[6].text = "The light of the lantern has show the true danger ahead. What will you do?";
return {goto: 7};
}
}, {
id: 9,
title:"Drats, you didn't find a lantern yet.",
text: "You'd better hurry you only have {{MATCHES}} matches left!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var matches = ge.getItem('matches');
if (matches) {
act.goto = 7;
}
else {
act.goto = 11;
}
return act;
}
}, {
id: 10,
title:"You can't find something you already have.",
text: "look for the key already!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 11,
title: "As your last match burned to cinder, you saw your hope fade to blackness.",
text: "You are lost forever in darkness. -GAME OVER.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 999};
}
}, {
id: 12,
title: "Hooray!",
text: "You found the Forest Temple key.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestKey', true);
ge.setInventory("key", "", "Forest Temple Key");
return {goto: 7};//forest temple screen
}
}, {
id: 13,//battle screen
title: "An {{ENEMY}} has appear.",
text: "Prepare for battle, I hope your sword is sharp.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 7) {
act.goto = 14;
}
else {
act.goto = 15;
//act.hearts = -1;
}
return act;
}
}, {
id: 14,//battle screen
title: "Victory is Yours {{NAME}}.",
text: "Your fought valiantly and earned 5 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
gems: 5
};
}
}, {
id: 15,
title: "The agnony of defeat!",
text: "Your managed to slay the beast but not before sustaining some damage.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
hearts: -1
};
}
}, {
id: 16,
title: "You need a key to enter the Temple.",
text: "Maybe you should better equip yourself before you head to the temple.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 17,
title: "{{NAME}} you are not going to find another key.",
text: "Is it time to head to the temple?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 18,
title: "Forest Temple Entrance",
text: "Stay alert, this temple is very dangerous, {{NAME}} what will you do?",
a: "Visit the temple shop",
b: "Explore the temple",
c: "Enter Boss Room",
d: "Quit",
e: "",
action: function (ge, gd, answer){
//Set _currentBoss
if (!ge.getItem('_currentBoss')) {
var boss = ge.getBoss(1);
ge.setItem('_currentBoss', boss);
}
//change screen text if boss key found
var bossKey = ge.getItem('forestBossKey');
var lantern = ge.getItem('lantern');
/* This dynamically changed he screen text
if (bossKey) {
var scr = ge.getScreen(gd, 17);
if (scr){
scr.c = "Enter Boss Room";
scr.d = "Quit";
}
}*/
var act = {};
var roll = ge.rollDice();
switch(answer){
case "A":
act.goto = 19;
break;
case "B":
if (!lantern){
act.matches = -1;
}
// find chest
if (roll === 1 || roll === 12) {
act.goto = 26;
}
//find
if (roll === 9 || roll === 10 || roll === 11) {
act.goto = 27;
}
//fight here
if (roll === 2 || roll === 3 || roll === 4 || roll === 5 || roll === 6 || roll === 7 || roll === 8) {
act.goto = 28;
}
break;
case "C":
console.log('boss key ', bossKey);
if (bossKey) {
act.goto = 31;
/**
*@todo send to boss screen
*/
console.log('gotta key');
}
else {
act.goto = 32;
console.log('no key');
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 19,
title: "Hayloo, welcome to my shop.",
text: "I am Dreeko, What would yoooh like to buy?",
a: "A lantern - 20 gems",
b: "5 matches 10 gems",
c: "A leather shield - 25 gems",
d: "A heart potion - 15 gems",
e: "Exit the shop",
action: function (ge, gd, answer){
var lanternPrice = 20;//20
var shieldPrice = 25;//35
var potionPrice = 15;//15
var act = {};
var gems = ge.getItem('gems');
var lantern = ge.getItem('lantern');
var shield = ge.getItem('leatherShield');
var potion = ge.getItem('heartPotion');
switch(answer){
case "A":
if (lantern) {
act.goto = 20;
}
else {
if (ge.sellItem('lantern', lanternPrice)) {
act.goto = 21;
}
else {
act.goto = 22;
}
}
break;
case "B":
act.goto = 23;
break;
case "C":
if (shield) {
act.goto = 20;
}
else {
if (ge.sellItem('leatherShield', shieldPrice)) {
act.goto = 24;
}
else {
act.goto = 22;
}
}
break;
case "D":
if (potion) {
act.goto = 20;
}
else {
if (ge.sellItem('heartPotion', potionPrice)) {
act.goto = 25;
}
else {
act.goto = 22;
}
}
break;
case "E":
act.goto = 18;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 20,
title: "Looks like you already have one of those.",
text: "As much as Dreeko would like to sell you another one, I just can't.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 21,
title: "{{NAME}} you are the owner of a shiny new lantern!",
text: "Dreeko thinks you could have saved money looking for one in the forest though...",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("light", "", "Eternal Lantern");
return {goto: 19};
}
}, {
id: 22,
title: "Dreeko really likes chraity but I have 9 kids to feed.",
text: "Maybe you should check the temple for treasure and come back later?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 23,
title: "I'd really like to sell you something but, in this temple, you really need a lantern.",
text: "Maybe there is somethign else you need?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 24,
title: "Dreeko thinks you are smart.",
text: "The leather shield will cut your damage in half",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentShield', 1);
ge.setInventory("shield", "", "Leather Shield");
return {goto: 19};
}
}, {
id: 25,
title: "This potion is quite special.",
text: "if you fall in battle it will revive you to full health.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("potion", "Heart Potion", "Fairy Syrup");
return {goto: 19};
}
}, {
id: 26,
title: "What luck!",
text: "You found a chest that contains 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.adjustItem('gems', 10);
return {goto: 18};
}
}, {
id: 27,
title: "You found the boss room.",
text: "Are you ready to do battle?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestBossKey', true);
ge.setInventory("key", "", "Forest Boss Key");
return {goto: 18};
}
}, {
id: 28,
title: "An {{ENEMY}} appeared, prepare for battle.",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 8) {
//win
act.goto = 29;
}
else {
act.goto = 30;
}
return act;
}
}, {
id: 29,
title: "BEAST-MODE activated, you slayed the enemy!",
text: "You just earned 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
gems: 10
};
}
}, {
id: 30,
title: "Temple monsters are stonger than those found in the forest.",
text: "You defeated your foe but were injured in the process.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
hearts: -2
};
}
}, {
id: 31,
title: "<<<{{BOSS}}>>> - Forest Temple Boss.",
text: "Strike fast or perish.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 32,
title: "You Cannot enter this Room",
text: "You must explore the temple to find the boss room key to get in.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 18};
}
}, {
id: 33,
title: "{{BOSS}} is charging you.",
text: "What will you do?",
a: "Sword attack",
b: "Try special attack",
c: "Dodge",
d: "Quit",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll1 = ge.rollDice();
var roll2 = ge.rollDice();
switch(answer){
case "A":
if (roll1 > 6) {
act.goto = 34;
}
else {
act.goto = 35;
}
break;
case "B":
if (roll1 === roll2 || (roll1 + roll2 === 14)) {
act.goto = 36;
}
else {
act.goto = 37;
}
break;
case "C":
act.goto = 38;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 34,
title: "Excellent attack {{NAME}}!",
text: "Keep this up and {{BOSS}} will be defeated soon.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -1);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 35,
title: "{{BOSS}} is a skilled figher.",
text: "You have been injured, I'm not sure how much of this you can take.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 36,
title: "<< Five Strike Blazing Slash >> - Special Attack Unleashed!",
text: "You inflicted major damage to {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -3);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 37,
title: "Special attacks are not easy to pull off.",
text: "{{BOSS}} struck before you could power up.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 38,
title: "You can't run forever {{NAME}}.",
text: "The only way to free {{RESCUEE}} is to defeat {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 39,
title: "You defeated {{BOSS}}.",
text: "A hidden stone door crumbles and the {{RESCUEE}} runs out and hugs you. Thank you for saving me {{NAME}} I do not know how to thank you! \n" +
"Congratulations what will you next quest be?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentBoss', null);
ge.adjustItem('_heartLimit', 1);
ge.setItem('hearts', ge.getItem('_heartLimit'));
return {goto: 9999};
}
}, {
id: 40,
title: "Inventory",
text: "{{INVENTORY}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var screenNum = ge.getItem("_previousScreen");
return {goto: screenNum};
}
}, {
id: 41,
title: "Credits",
text: "{{CREDITS}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 42,
title: "Game Over",
text: "What is that sad music playing? Try again?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 43,
title: "Game Over",
text: "Congradulation! You saved Princess {{RESCUEE}}. {{NAME}}, perhaps now you might create your own quest?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 44,
title: "Quitters never prosper.",
text: "What's the matter {{NAME}} couldn't take it?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}]
};
var gameEngine = {
tokens: ["{{NAME}}", "{{TITLE}}", "{{RESCUEE}}", "{{MATCHES}}", "{{HEARTS}}", "{{GEMS}}", "{{ENEMY}}", "{{BOSS}}", "{{INVENTORY}}"],
tokenHandlers: ["name", "title", "rescuee", "matches", "hearts", "gems", "getEnemy", "getCurrentBossName", "formatInventory"],
getScreen: function(gd, num){
var scr = gd.screens[num] || false;
return scr;
},
showScreen: function(gd, screenNum){
var display = this.getScreenText(gd, screenNum);
var answer = "";
if (display.text) {
var opts = display.opts ? '\n' + display.opts + display.bar + '\n' + display.stats : display.bar + '\n' + display.stats;
if (display.stats) {
display.opts += display.bar + '\n' + display.stats;
}
if (display.usePrompt) {
answer = prompt(display.text + opts);
}
else {
alert(display.text);
}
this.process(gd, screenNum, answer);
return true;
}
else {
return false;
}
},
getScreenText: function(gd, screenNum){
var scr = gd.screens[screenNum - 1];
var display = {
text: "",
opts: "",
bar: "****************************************",
usePrompt: false,
stats: this.getStats()
};
if (scr) {
display.text = scr.title + "\n" + display.bar + "\n" + scr.text + "\n";
//opts = scr.a + "\n" + scr.b + "\n" + scr.c + "\n" + scr.d + "\n" + scr.e + "\n";
for (var opt in scr) {
if (opt === "a" || opt === "b" || opt === "c" || opt === "d" || opt === "e") {
if (scr[opt]) {
display.opts += opt.toUpperCase() + ") " + scr[opt] + "\n";
}
}
}
if (display.opts.trim() || scr.usePrompt) {
display.usePrompt = true;
}
if (scr.hideStats) {
display.stats = "";
}
//pre process text
display.text = this.parse(display.text);
display.opts = this.parse(display.opts);
return display;
}
return false;
},
getStats: function(){
var text = "Hearts: {{HEARTS}}\n";
text += "Gems: {{GEMS}}\n";
text = this.parse(text);
return text;
},
formatInventory: function(){
var inv = this.getItem("inventory");
var text = "";
var bar = "====================";
text += bar + "";
for(var item in inv){
var itm = inv[item];
text += "\n" + itm.title + ": " + itm.name + "\n" + bar;
}
return text;
},
setInventory: function(item, title, name) {
var inv = this.getItem("inventory");
var itm = inv[item] || {title: "Unknown", name: ""};
if (title){
itm.title = title;
}
if (name) {
itm.name = name;
}
inv[item] = itm;
},
getData: function(){
return gameData;
},
getTokens: function(){
return this.tokens;
},
addToken: function(tkn, meth){
if (tkn && meth){
this.tokens.push(tkn.toString());
this.tokenHandlers.push(meth);
}
},
parse: function(txt, tokens){//Parse tokens
if (!tokens) {
tokens = this.getTokens();
}
for (var i = 0; i < tokens.length; i++){
var tkn = this.tokens[i];
var item = this.tokenHandlers[i];
var val = this.getItem(item);
var handler = this[item] || false;
if (typeof(handler) === 'function') {
val = handler.apply(this);
}
txt = txt.replace(tkn, val);
}
return txt;
},
//Handle common screen operations
process: function(gd, screenNum, answer){
this.setItem("_previousScreen", this.getItem("_currentScreen"));// Use this if you have menu commands that need to return to the current action screen
this.setItem("_currentScreen", screenNum);
if (answer) {
answer = answer.trim().toUpperCase();
}
var act = gd.screens[screenNum - 1].action(this, gd, answer);// call screen specific logic
if (act) {
var hearts = act.hearts || 0;// heart adjustment
var currentHearts = this.getItem('hearts');
var goto = act.goto || 99999;
var gems = act.gems || 0;
var potion = this.getItem('heartPotion');
var matches = act.matches || 0;
var shield = this.getItem('_currentShield') || 0;
if (matches) {
this.adjustItem('matches', matches);
var matchesText = "Matches (" + this.getItem("matches") + ")";
this.setInventory('light', 'Light', matchesText);
}
/*
remove or add hearts first if hearts === 0 game is over unless hasHeartPotion === true
return false to quit
*/
if (hearts){
if (hearts < 0) {
//use shield
hearts = Math.floor(hearts + shield);
if (!hearts) {
hearts = - 0.5;
}
}
currentHearts = this.adjustItem('hearts', hearts);
}
//Revive player
if (!currentHearts && potion) {
this.adjustItem('hearts', this.getItem('_heartLimit'));
this.setItem('heartPotion', false);
ths.setInventory("potion", "", "---");
currentHearts = this.adjustItem('hearts', hearts);
}
//game over player was killed
if (!currentHearts) {
console.log('Process: game over.');
return false;
}
//handle gems
if (gems) {
this.adjustItem('gems', gems);
}
if (goto) {
this.showScreen(gd, goto);
}
}
else {
this.showScreen(gd, currentScreen);
}
return false;
},
rollDice: function(){
var diceNumber = Math.random() * 12 + 1;
diceNumber = Math.floor(diceNumber);
return diceNumber;
},
getItem: function(name){
if (name) {
var item = gameData[name];
return item;
}
},
setItem: function(name, val){
if (!val) {
val = false; //use false instead of falsey
}
if (name){
gameData[name] = val;
}
},
showScreenTmpl: function(){
console.log('screen template ', screenTmpl);
},
setTitle: function(title){
if (title) {
gameData.screens[0].title = title;
}
var ttl = gameData.screens[0].title;
gameData.title = ttl;
},
getTitle: function(){
return gameData.screens[0].title;
},
adjustItem: function(name, val){
if (name && val) {
var item = this.getItem(name);
item = item + val;
if (item < 0) {
item = 0;
}
gameData[name] = item;
return gameData[name];
}
},
getRandomNum: function(num){
num = num ? num : 1;
return Math.floor(Math.random() * num);
},
getEnemy: function(num){
var nmes = gameData.enemies;
var nme = "";
if (num) {
nme = nmes[num] || "";
}
else {
var rnum = this.getRandomNum(nmes.length);
nme = nmes[rnum];
}
return nme;
},
getBoss: function(num){
var bosses = this.getItem("bosses");
var boss = bosses[num - 1];
return boss;
},
attack: function(target, damage){
var hearts = target.hearts;
hearts = hearts + damage;
if (hearts < 0) {
hearts = 0;
}
target.hearts = hearts;
return hearts;
},
getCurrentBossName: function(){
var boss = this.getItem('_currentBoss') || {};
return boss.name || "";
},
sellItem: function(item, price){
var gems = this.getItem('gems');
if (gems >= price) {
this.adjustItem('gems', (price * -1));
this.setItem(item, true);
return true;
}
return false;
},
start: function(gd){
this.setTitle();
this.showScreen(gd, 1);
}
};
if (w) {
w.ge = gameEngine;
}
return gameEngine;
})(window);
var gd = ge.getData();
ge.start(gd);</script></body>
</html>
(function(w){
/**
*@todo create api to set things like game name so that direct source code manipulation does have to occur
* use string commands to tell the ge what to do, ie return object with key pair command and param
* add game over and quit screens, build inventory screen logic
*/
var screenTmpl = {
id: 0,
title:"",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
break;
case "B":
break;
case "C":
break;
case "D":
break;
case "E":
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
};
/**
*@todo set gems to zero and potion to false and hearst to 5
*/
var gameData = {
name: "Tank",
hearts: 5,
matches: 5,
lantern: false,// use numeric to count how many times lantern was tried to get
gems: 0,
rescuee: "Helga",
enemies: ["Grublor", "Stolak"],
forestKey: false,
forestBossKey: false,
silverSword: true,
leatherShield: false,
heartPotion: false,
bosses: [{name: "King Malvox", hearts: 7}],
_currentScreen: 0,
_previousScreen: 0,
_currentBoss: "",
_currentShield: 0,
_heartLimit: 5,
_gameOverWin: 43,
_gameOverLose: 42,
_quitScreen: 44,
_inventoryScreen: 40,
_creditsScreen: 41,
inventory: {
sword: {
title: "Sword",
name: "---"
},
shield: {
title: "Shield",
name: "---"
},
light: {
title: "Light",
name: "---"
},
key: {
title: "key",
name: "---"
}
},
screens: [{
id: 1,
title: "The Legend of Helga",
text: "Click OK to begin.",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
action: function(ge, gd, answer){
//initialize inventory here
var matches = "Matches (" + ge.getItem("matches") + ")";
ge.setInventory('light', 'Light', matches);
return {goto: 2};
}
}, {
id: 2,
title:"Before we get started...",
text: "Adventurer, what is your name?",
a: "",
b: "",
c: "",
d: "",
e: "",
hideStats: true,
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
if (answer.match(/[A-Za-z0-9]+/)) {
act.goto = 4;
ge.setItem('name', answer);
}
else {
act.goto = 3;
}
return act;
}
}, {
id: 3,
title:"That's not a name!",
text: "It's not that hard, just type your name.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 2};
}
}, {
id: 4,
title:"{{RESCUEE}} has been kidknapped!",
text: "The local village blacksmith said that he saw her taken into the forest by a shadowy figure. " +
"He gave you a Silver Sword to help you in your quest. You'd better hurry into the forest and save her. ",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 5,
title:"{{RESCUEE}} is not going to save herself",
text: "where will you start?",
a: "Venture into the Dark Forest",
b: "Vist the Dark Forest Temple",
c: "QUIT",
d: "",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
switch(answer){
case "A":
act.goto = 7;
break;
case "B":
act.goto = 6;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 6,
title: "You need a key to get in the Dark Forest Temple.",
text: "Maybe you should look for one in the forest.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 5};
}
}, {
id: 7,
title:"The forest is dark.",
text: "you will need a lantern to find anything, what will you do?",
a: "Look for a lantern",
b: "Look for the temple key",
c: "Go to the Forest Temple",
d: "QUIT",
e: "",
usePrompt: true,
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var roll = ge.rollDice();
var matches = ge.getItem('matches');
var forestKey = ge.getItem('forestKey');
//remove a match if there is no lantern, this must happen before matches value read
if (!lantern) {
//ge.adjustItem('matches', -1);
act.matches = -1;
}
//If there are no matches the game is over
if (!matches && !lantern) {
act.goto = 11;
/**
*@todo replace with real game over screen
*/
return act;
}
switch(answer){
case "A":
if(lantern) {
act.goto = 10;
return act;
}
//Assume no lantern if here
if (roll > 6) {
act.goto = 8;
}
else {
if(matches) {
act.goto = 9;
}
else {
act.goto = 11;
}
}
break;
case "B":
if (forestKey) {
act.goto = 17;
return act;
}
if (roll > 6) {
act.goto = 12;
}
else {
act.goto = 13;//key not found
}
break;
case "C":
if (forestKey) {
//hide key from inventory, it has been used
ge.setInventory("key", "", "---");
act.goto = 18;
}
else {
act.goto = 16;
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 8,
title:"You found a lantern!",
text: "Now you don't have to keep burning your fingers with those pesky matches.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
//change screen sevens message, zero indexed!
ge.setItem('lantern', true);
ge.setInventory("light", "", "Eternal Lantern");
gd.screens[6].title = "Keep your sword ready {{NAME}}.";
gd.screens[6].text = "The light of the lantern has show the true danger ahead. What will you do?";
return {goto: 7};
}
}, {
id: 9,
title:"Drats, you didn't find a lantern yet.",
text: "You'd better hurry you only have {{MATCHES}} matches left!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var lantern = ge.getItem('lantern');
var matches = ge.getItem('matches');
if (matches) {
act.goto = 7;
}
else {
act.goto = 11;
}
return act;
}
}, {
id: 10,
title:"You can't find something you already have.",
text: "look for the key already!",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 11,
title: "As your last match burned to cinder, you saw your hope fade to blackness.",
text: "You are lost forever in darkness. -GAME OVER.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 999};
}
}, {
id: 12,
title: "Hooray!",
text: "You found the Forest Temple key.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestKey', true);
ge.setInventory("key", "", "Forest Temple Key");
return {goto: 7};//forest temple screen
}
}, {
id: 13,//battle screen
title: "An {{ENEMY}} has appear.",
text: "Prepare for battle, I hope your sword is sharp.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 7) {
act.goto = 14;
}
else {
act.goto = 15;
//act.hearts = -1;
}
return act;
}
}, {
id: 14,//battle screen
title: "Victory is Yours {{NAME}}.",
text: "Your fought valiantly and earned 5 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
gems: 5
};
}
}, {
id: 15,
title: "The agnony of defeat!",
text: "Your managed to slay the beast but not before sustaining some damage.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 7,
hearts: -1
};
}
}, {
id: 16,
title: "You need a key to enter the Temple.",
text: "Maybe you should better equip yourself before you head to the temple.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 17,
title: "{{NAME}} you are not going to find another key.",
text: "Is it time to head to the temple?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 7};
}
}, {
id: 18,
title: "Forest Temple Entrance",
text: "Stay alert, this temple is very dangerous, {{NAME}} what will you do?",
a: "Visit the temple shop",
b: "Explore the temple",
c: "Enter Boss Room",
d: "Quit",
e: "",
action: function (ge, gd, answer){
//Set _currentBoss
if (!ge.getItem('_currentBoss')) {
var boss = ge.getBoss(1);
ge.setItem('_currentBoss', boss);
}
//change screen text if boss key found
var bossKey = ge.getItem('forestBossKey');
var lantern = ge.getItem('lantern');
/* This dynamically changed he screen text
if (bossKey) {
var scr = ge.getScreen(gd, 17);
if (scr){
scr.c = "Enter Boss Room";
scr.d = "Quit";
}
}*/
var act = {};
var roll = ge.rollDice();
switch(answer){
case "A":
act.goto = 19;
break;
case "B":
if (!lantern){
act.matches = -1;
}
// find chest
if (roll === 1 || roll === 12) {
act.goto = 26;
}
//find
if (roll === 9 || roll === 10 || roll === 11) {
act.goto = 27;
}
//fight here
if (roll === 2 || roll === 3 || roll === 4 || roll === 5 || roll === 6 || roll === 7 || roll === 8) {
act.goto = 28;
}
break;
case "C":
console.log('boss key ', bossKey);
if (bossKey) {
act.goto = 31;
/**
*@todo send to boss screen
*/
console.log('gotta key');
}
else {
act.goto = 32;
console.log('no key');
}
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 19,
title: "Hayloo, welcome to my shop.",
text: "I am Dreeko, What would yoooh like to buy?",
a: "A lantern - 20 gems",
b: "5 matches 10 gems",
c: "A leather shield - 25 gems",
d: "A heart potion - 15 gems",
e: "Exit the shop",
action: function (ge, gd, answer){
var lanternPrice = 20;//20
var shieldPrice = 25;//35
var potionPrice = 15;//15
var act = {};
var gems = ge.getItem('gems');
var lantern = ge.getItem('lantern');
var shield = ge.getItem('leatherShield');
var potion = ge.getItem('heartPotion');
switch(answer){
case "A":
if (lantern) {
act.goto = 20;
}
else {
if (ge.sellItem('lantern', lanternPrice)) {
act.goto = 21;
}
else {
act.goto = 22;
}
}
break;
case "B":
act.goto = 23;
break;
case "C":
if (shield) {
act.goto = 20;
}
else {
if (ge.sellItem('leatherShield', shieldPrice)) {
act.goto = 24;
}
else {
act.goto = 22;
}
}
break;
case "D":
if (potion) {
act.goto = 20;
}
else {
if (ge.sellItem('heartPotion', potionPrice)) {
act.goto = 25;
}
else {
act.goto = 22;
}
}
break;
case "E":
act.goto = 18;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 20,
title: "Looks like you already have one of those.",
text: "As much as Dreeko would like to sell you another one, I just can't.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 21,
title: "{{NAME}} you are the owner of a shiny new lantern!",
text: "Dreeko thinks you could have saved money looking for one in the forest though...",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("light", "", "Eternal Lantern");
return {goto: 19};
}
}, {
id: 22,
title: "Dreeko really likes chraity but I have 9 kids to feed.",
text: "Maybe you should check the temple for treasure and come back later?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 23,
title: "I'd really like to sell you something but, in this temple, you really need a lantern.",
text: "Maybe there is somethign else you need?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 19};
}
}, {
id: 24,
title: "Dreeko thinks you are smart.",
text: "The leather shield will cut your damage in half",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentShield', 1);
ge.setInventory("shield", "", "Leather Shield");
return {goto: 19};
}
}, {
id: 25,
title: "This potion is quite special.",
text: "if you fall in battle it will revive you to full health.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setInventory("potion", "Heart Potion", "Fairy Syrup");
return {goto: 19};
}
}, {
id: 26,
title: "What luck!",
text: "You found a chest that contains 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.adjustItem('gems', 10);
return {goto: 18};
}
}, {
id: 27,
title: "You found the boss room.",
text: "Are you ready to do battle?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('forestBossKey', true);
ge.setInventory("key", "", "Forest Boss Key");
return {goto: 18};
}
}, {
id: 28,
title: "An {{ENEMY}} appeared, prepare for battle.",
text: "",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll = ge.rollDice();
if (roll > 8) {
//win
act.goto = 29;
}
else {
act.goto = 30;
}
return act;
}
}, {
id: 29,
title: "BEAST-MODE activated, you slayed the enemy!",
text: "You just earned 10 gems.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
gems: 10
};
}
}, {
id: 30,
title: "Temple monsters are stonger than those found in the forest.",
text: "You defeated your foe but were injured in the process.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 18,
hearts: -2
};
}
}, {
id: 31,
title: "<<<{{BOSS}}>>> - Forest Temple Boss.",
text: "Strike fast or perish.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 32,
title: "You Cannot enter this Room",
text: "You must explore the temple to find the boss room key to get in.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 18};
}
}, {
id: 33,
title: "{{BOSS}} is charging you.",
text: "What will you do?",
a: "Sword attack",
b: "Try special attack",
c: "Dodge",
d: "Quit",
e: "",
action: function (ge, gd, answer){
var act = {};
var roll1 = ge.rollDice();
var roll2 = ge.rollDice();
switch(answer){
case "A":
if (roll1 > 6) {
act.goto = 34;
}
else {
act.goto = 35;
}
break;
case "B":
if (roll1 === roll2 || (roll1 + roll2 === 14)) {
act.goto = 36;
}
else {
act.goto = 37;
}
break;
case "C":
act.goto = 38;
break;
case "STUFF":
case "INVENTORY":
act.goto = ge.getItem("_inventoryScreen");
break;
default:
act.goto = ge.getItem("_quitScreen");
}
return act;
}
}, {
id: 34,
title: "Excellent attack {{NAME}}!",
text: "Keep this up and {{BOSS}} will be defeated soon.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -1);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 35,
title: "{{BOSS}} is a skilled figher.",
text: "You have been injured, I'm not sure how much of this you can take.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 36,
title: "<< Five Strike Blazing Slash >> - Special Attack Unleashed!",
text: "You inflicted major damage to {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var act = {goto: 33};
var boss = gd._currentBoss;
var bossHearts = ge.attack(boss, -3);
if (!bossHearts) {
act.goto = 39;
}
return act;
}
}, {
id: 37,
title: "Special attacks are not easy to pull off.",
text: "{{BOSS}} struck before you could power up.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {
goto: 33,
hearts: -2
};
}
}, {
id: 38,
title: "You can't run forever {{NAME}}.",
text: "The only way to free {{RESCUEE}} is to defeat {{BOSS}}.",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 33};
}
}, {
id: 39,
title: "You defeated {{BOSS}}.",
text: "A hidden stone door crumbles and the {{RESCUEE}} runs out and hugs you. Thank you for saving me {{NAME}} I do not know how to thank you! \n" +
"Congratulations what will you next quest be?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
ge.setItem('_currentBoss', null);
ge.adjustItem('_heartLimit', 1);
ge.setItem('hearts', ge.getItem('_heartLimit'));
return {goto: 9999};
}
}, {
id: 40,
title: "Inventory",
text: "{{INVENTORY}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
var screenNum = ge.getItem("_previousScreen");
return {goto: screenNum};
}
}, {
id: 41,
title: "Credits",
text: "{{CREDITS}}",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 42,
title: "Game Over",
text: "What is that sad music playing? Try again?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 43,
title: "Game Over",
text: "Congradulation! You saved Princess {{RESCUEE}}. {{NAME}}, perhaps now you might create your own quest?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}, {
id: 44,
title: "Quitters never prosper.",
text: "What's the matter {{NAME}} couldn't take it?",
a: "",
b: "",
c: "",
d: "",
e: "",
action: function (ge, gd, answer){
return {goto: 9999};
}
}]
};
var gameEngine = {
tokens: ["{{NAME}}", "{{TITLE}}", "{{RESCUEE}}", "{{MATCHES}}", "{{HEARTS}}", "{{GEMS}}", "{{ENEMY}}", "{{BOSS}}", "{{INVENTORY}}"],
tokenHandlers: ["name", "title", "rescuee", "matches", "hearts", "gems", "getEnemy", "getCurrentBossName", "formatInventory"],
getScreen: function(gd, num){
var scr = gd.screens[num] || false;
return scr;
},
showScreen: function(gd, screenNum){
var display = this.getScreenText(gd, screenNum);
var answer = "";
if (display.text) {
var opts = display.opts ? '\n' + display.opts + display.bar + '\n' + display.stats : display.bar + '\n' + display.stats;
if (display.stats) {
display.opts += display.bar + '\n' + display.stats;
}
if (display.usePrompt) {
answer = prompt(display.text + opts);
}
else {
alert(display.text);
}
this.process(gd, screenNum, answer);
return true;
}
else {
return false;
}
},
getScreenText: function(gd, screenNum){
var scr = gd.screens[screenNum - 1];
var display = {
text: "",
opts: "",
bar: "****************************************",
usePrompt: false,
stats: this.getStats()
};
if (scr) {
display.text = scr.title + "\n" + display.bar + "\n" + scr.text + "\n";
//opts = scr.a + "\n" + scr.b + "\n" + scr.c + "\n" + scr.d + "\n" + scr.e + "\n";
for (var opt in scr) {
if (opt === "a" || opt === "b" || opt === "c" || opt === "d" || opt === "e") {
if (scr[opt]) {
display.opts += opt.toUpperCase() + ") " + scr[opt] + "\n";
}
}
}
if (display.opts.trim() || scr.usePrompt) {
display.usePrompt = true;
}
if (scr.hideStats) {
display.stats = "";
}
//pre process text
display.text = this.parse(display.text);
display.opts = this.parse(display.opts);
return display;
}
return false;
},
getStats: function(){
var text = "Hearts: {{HEARTS}}\n";
text += "Gems: {{GEMS}}\n";
text = this.parse(text);
return text;
},
formatInventory: function(){
var inv = this.getItem("inventory");
var text = "";
var bar = "====================";
text += bar + "";
for(var item in inv){
var itm = inv[item];
text += "\n" + itm.title + ": " + itm.name + "\n" + bar;
}
return text;
},
setInventory: function(item, title, name) {
var inv = this.getItem("inventory");
var itm = inv[item] || {title: "Unknown", name: ""};
if (title){
itm.title = title;
}
if (name) {
itm.name = name;
}
inv[item] = itm;
},
getData: function(){
return gameData;
},
getTokens: function(){
return this.tokens;
},
addToken: function(tkn, meth){
if (tkn && meth){
this.tokens.push(tkn.toString());
this.tokenHandlers.push(meth);
}
},
parse: function(txt, tokens){//Parse tokens
if (!tokens) {
tokens = this.getTokens();
}
for (var i = 0; i < tokens.length; i++){
var tkn = this.tokens[i];
var item = this.tokenHandlers[i];
var val = this.getItem(item);
var handler = this[item] || false;
if (typeof(handler) === 'function') {
val = handler.apply(this);
}
txt = txt.replace(tkn, val);
}
return txt;
},
//Handle common screen operations
process: function(gd, screenNum, answer){
this.setItem("_previousScreen", this.getItem("_currentScreen"));// Use this if you have menu commands that need to return to the current action screen
this.setItem("_currentScreen", screenNum);
if (answer) {
answer = answer.trim().toUpperCase();
}
var act = gd.screens[screenNum - 1].action(this, gd, answer);// call screen specific logic
if (act) {
var hearts = act.hearts || 0;// heart adjustment
var currentHearts = this.getItem('hearts');
var goto = act.goto || 99999;
var gems = act.gems || 0;
var potion = this.getItem('heartPotion');
var matches = act.matches || 0;
var shield = this.getItem('_currentShield') || 0;
if (matches) {
this.adjustItem('matches', matches);
var matchesText = "Matches (" + this.getItem("matches") + ")";
this.setInventory('light', 'Light', matchesText);
}
/*
remove or add hearts first if hearts === 0 game is over unless hasHeartPotion === true
return false to quit
*/
if (hearts){
if (hearts < 0) {
//use shield
hearts = Math.floor(hearts + shield);
if (!hearts) {
hearts = - 0.5;
}
}
currentHearts = this.adjustItem('hearts', hearts);
}
//Revive player
if (!currentHearts && potion) {
this.adjustItem('hearts', this.getItem('_heartLimit'));
this.setItem('heartPotion', false);
ths.setInventory("potion", "", "---");
currentHearts = this.adjustItem('hearts', hearts);
}
//game over player was killed
if (!currentHearts) {
console.log('Process: game over.');
return false;
}
//handle gems
if (gems) {
this.adjustItem('gems', gems);
}
if (goto) {
this.showScreen(gd, goto);
}
}
else {
this.showScreen(gd, currentScreen);
}
return false;
},
rollDice: function(){
var diceNumber = Math.random() * 12 + 1;
diceNumber = Math.floor(diceNumber);
return diceNumber;
},
getItem: function(name){
if (name) {
var item = gameData[name];
return item;
}
},
setItem: function(name, val){
if (!val) {
val = false; //use false instead of falsey
}
if (name){
gameData[name] = val;
}
},
showScreenTmpl: function(){
console.log('screen template ', screenTmpl);
},
setTitle: function(title){
if (title) {
gameData.screens[0].title = title;
}
var ttl = gameData.screens[0].title;
gameData.title = ttl;
},
getTitle: function(){
return gameData.screens[0].title;
},
adjustItem: function(name, val){
if (name && val) {
var item = this.getItem(name);
item = item + val;
if (item < 0) {
item = 0;
}
gameData[name] = item;
return gameData[name];
}
},
getRandomNum: function(num){
num = num ? num : 1;
return Math.floor(Math.random() * num);
},
getEnemy: function(num){
var nmes = gameData.enemies;
var nme = "";
if (num) {
nme = nmes[num] || "";
}
else {
var rnum = this.getRandomNum(nmes.length);
nme = nmes[rnum];
}
return nme;
},
getBoss: function(num){
var bosses = this.getItem("bosses");
var boss = bosses[num - 1];
return boss;
},
attack: function(target, damage){
var hearts = target.hearts;
hearts = hearts + damage;
if (hearts < 0) {
hearts = 0;
}
target.hearts = hearts;
return hearts;
},
getCurrentBossName: function(){
var boss = this.getItem('_currentBoss') || {};
return boss.name || "";
},
sellItem: function(item, price){
var gems = this.getItem('gems');
if (gems >= price) {
this.adjustItem('gems', (price * -1));
this.setItem(item, true);
return true;
}
return false;
},
start: function(gd){
this.setTitle();
this.showScreen(gd, 1);
}
};
if (w) {
w.ge = gameEngine;
}
return gameEngine;
})(window);
var gd = ge.getData();
ge.start(gd);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment