1 /*
     
2 
     3 This is the 'runtime' for Hoot.  It's the code that makes a Hoot game playable.
     
4 A minified copy of this entire script is in examplegame.html to make it run.
     
5 
     6 NOTE: examplegame.html copy minified with UglifyJS (at jscompress.com)
     
7 
     8 
     9 
    10 TODO: runtime needs for the "location" var to mean the current location
    
11 so that the engine can always display a clickable with the location name
    
12 as a clickable title in the game display
    
13 
    14 ALSO: allow location to be set to something invalid (like NOWHERE) which
    
15 will not display the location at all
    
16 
    17 ALSO: might want to do something similar for an inventory (game author
    
18 would be responsible for creating inventory interface)
    
19 
    20 */
    
21 
    22 
    23 
    24 function rungame(tree, outputarea){
    
25 	var gamevars = [];
    
26 	var upper = false;
    
27 
    28 	// the first element in the tree will be array of the rest of the tree
    
29 	tree = tree[0];
    
30 
    31 	outputarea.empty();
    
32 	runfunc('start');
    
33 
    34 	function runfunc(funcname){
    
35 		thefunc = findfunc(funcname);
    
36 		if(!thefunc){ alert("Sorry, can't continue because I couldn't find a thing named \""+funcname+"\"."); return; }
    
37 		// console.log("running function "+thefunc[1][1]);
    
38 		expressions(thefunc, 2);
    
39 	}
    
40 
    41 	function findfunc(funcname){
    
42 		for(s in tree){
    
43 			if(tree[s][1] && tree[s][1][1] && tree[s][1][1].toLowerCase() == funcname.toLowerCase()){ 
    
44 				return tree[s];
    
45 			}
    
46 		}
    
47 		return null;
    
48 	}
    
49 
    50 	function expression(expr){
    
51 		switch(expr[0]){
    
52 			case 'assign':
    
53 				// console.log("assigning "+expr[1][1]+" to "+expr[2][1]);
    
54 			 gamevars[expr[1][1].toLowerCase()] = expr[2][1]; 
    
55 
    56 			 break;
    
57 			case 'print':  print(expr); break;
    
58 			case 'ifseq':  ifsequence(expr); break;
    
59 			case 'runme':  runfunc(expr[1][1]); break;
    
60 			case 'decr':   gamevars[expr[1][1].toLowerCase()]--; break;
    
61 			case 'incr':   gamevars[expr[1][1].toLowerCase()]++; break;
    
62 			case 'elseseq': break; // do nothing, this will run if needed
    
63 			default: alert("Sorry, I wasn't expecting a '"+expr[0]+"' in the script. :-(");
    
64 		}
    
65 	}
    
66 
    67 	function expressions(list, startpos){
    
68 		// run multiple expressions from a list, starting from startpos
    
69 		for(var e=startpos; e<list.length; e++){
    
70 			expression(list[e]);
    
71 		}
    
72 	}
    
73 
    74 	function ifsequence(tree){
    
75 		var val1 = tree[1][1];
    
76 		var test_opr = tree[2][1];
    
77 		var val2 = tree[3][1];
    
78 
    79 		// console.log("Test: "+val1+" "+test_opr+" "+val2);
    
80 
    81 		if(tree[1][0] == "name"){ val1=gamevars[val1.toLowerCase()]; }
    
82 		if(tree[3][0] == "name"){ val2=gamevars[val2.toLowerCase()]; }
    
83 
    84 		// console.log("translates to: "+val1+" "+test_opr+" "+val2);
    
85 
    86 
    87 		if( (test_opr == "equals"           && val1 == val2) ||
    
88 			(test_opr == "less than"         && val1 <  val2) ||
    
89 			(test_opr == "greater than"      && val1 >  val2) ||
    
90 			(test_opr == "doesn't equal"        && val1 != val2) ){
    
91 			// console.log("true");
    
92 			expressions(tree,4);
    
93 		}
    
94 		else{
    
95 			// console.log("false");
    
96 			// see if there's an else to run
    
97 			for(e in tree){
    
98 				if(tree[e][0] == "elseseq"){
    
99 					expressions(tree[e],1);
   
100 				}
   
101 			}
   
102 		}
   
103 	}
   
104 
   105 	function print(printables){
   
106 		for(var p = 1; p<printables.length; p++){
   
107 			type = printables[p][0]; // the type of printable item
   
108 			body = printables[p][1]; // the body of the printable
   
109 			// console.log("printing "+type+": "+body);
   
110 			switch(type){
   
111 				case 'string' : printstr(body); break;
   
112 				case 'strname'   : printname(body); break;
   
113 				case 'upname' : upper = true; printname(body); break;
   
114 				case 'link'   : printlink(body); break;
   
115 				case 'break'  : printbreak(); break;
   
116 				default: alert("Sorry, I don't know how to display a '"+type+"'. :-(");
   
117 			}
   
118 		}
   
119 	}
   
120 
   121 	function printname(name){
   
122 		name = name.toLowerCase();
   
123 		if(name in gamevars){
   
124 			printstr(gamevars[name]);
   
125 			return;
   
126 		}
   
127 		if(findfunc(name)){
   
128 			runfunc(name);
   
129 			return;
   
130 		}
   
131 		alert("Sorry, couldn't find anything called '"+name+"' to display.");
   
132 	}
   
133 
   134 	function printstr(str){
   
135 		str = String(str);
   
136 		str = str.replace(/\\\//g,'/');
   
137 		if(upper){
   
138 			upper = false; // we've done it, don't do it again until requested
   
139 			printstr(str.charAt(0).toUpperCase()+str.slice(1));
   
140 			return;
   
141 		}
   
142 		outputarea.append("<span>"+str+"</span>");
   
143 	}
   
144 
   145 	function printlink(funcname){
   
146 		outputarea.append($("<a href=\"#\">"+body+"</a>").click(function(){
   
147 			outputarea.empty();
   
148 			runfunc(funcname);
   
149 			return false;
   
150 		}));
   
151 	}
   
152 
   153 	function printbreak(){
   
154 		outputarea.append("<hr>");
   
155 	}
   
156 }