diff options
-rw-r--r-- | bloodfields.stage | 152 | ||||
-rw-r--r-- | src/functionfloat.cpp | 17 | ||||
-rw-r--r-- | src/functionfloat.h | 16 | ||||
-rw-r--r-- | src/functioninteger.cpp | 17 | ||||
-rw-r--r-- | src/functioninteger.h | 16 | ||||
-rw-r--r-- | src/functionrandom.cpp | 9 | ||||
-rw-r--r-- | src/game.cpp | 4 | ||||
-rw-r--r-- | src/gamebuilder.cpp | 2 | ||||
-rw-r--r-- | src/parser.l | 8 | ||||
-rw-r--r-- | src/parser.y | 6 | ||||
-rw-r--r-- | src/variable.cpp | 34 | ||||
-rw-r--r-- | support/vim/syntax/stage.vim | 2 | ||||
-rw-r--r-- | test.stage | 12 |
13 files changed, 256 insertions, 39 deletions
diff --git a/bloodfields.stage b/bloodfields.stage index 7b61dd4..91bee08 100644 --- a/bloodfields.stage +++ b/bloodfields.stage | |||
@@ -6,6 +6,11 @@ global | |||
6 | { | 6 | { |
7 | exit(); | 7 | exit(); |
8 | } | 8 | } |
9 | |||
10 | command: "exit" | ||
11 | { | ||
12 | exit(); | ||
13 | } | ||
9 | } | 14 | } |
10 | 15 | ||
11 | situation <<start>> | 16 | situation <<start>> |
@@ -14,19 +19,19 @@ situation <<start>> | |||
14 | { | 19 | { |
15 | global.enemyTypes = { | 20 | global.enemyTypes = { |
16 | 1: { | 21 | 1: { |
17 | 'name': 'Snail', | 22 | 'name': 'snail', |
18 | 'action': 'bites', | 23 | 'action': 'oozes on', |
19 | 'hp': 3, | 24 | 'hp': 3, |
20 | 'attack': 2 | 25 | 'attack': 2 |
21 | }, | 26 | }, |
22 | 2: { | 27 | 2: { |
23 | 'name': 'Wolf', | 28 | 'name': 'wolf', |
24 | 'action': 'bites', | 29 | 'action': 'bites', |
25 | 'hp': 7, | 30 | 'hp': 7, |
26 | 'attack': 3 | 31 | 'attack': 3 |
27 | }, | 32 | }, |
28 | 3: { | 33 | 3: { |
29 | 'name': 'Snake', | 34 | 'name': 'snake', |
30 | 'action': 'strikes at', | 35 | 'action': 'strikes at', |
31 | 'hp': 3, | 36 | 'hp': 3, |
32 | 'attack': 3 | 37 | 'attack': 3 |
@@ -35,17 +40,17 @@ situation <<start>> | |||
35 | 40 | ||
36 | global.enemyMods = { | 41 | global.enemyMods = { |
37 | 1: { | 42 | 1: { |
38 | 'name': 'Pathetic', | 43 | 'name': 'pathetic', |
39 | 'hp': 0, | 44 | 'hp': 0, |
40 | 'attack': 0 | 45 | 'attack': 0 |
41 | }, | 46 | }, |
42 | 2: { | 47 | 2: { |
43 | 'name': 'Sickly', | 48 | 'name': 'sickly', |
44 | 'hp': 3, | 49 | 'hp': 3, |
45 | 'attack': 1 | 50 | 'attack': 1 |
46 | }, | 51 | }, |
47 | 3: { | 52 | 3: { |
48 | 'name': 'Wimpy', | 53 | 'name': 'wimpy', |
49 | 'hp': 5, | 54 | 'hp': 5, |
50 | 'attack': 2 | 55 | 'attack': 2 |
51 | } | 56 | } |
@@ -54,7 +59,9 @@ situation <<start>> | |||
54 | player.hpMax = 10; | 59 | player.hpMax = 10; |
55 | player.hpCur = player.hpMax; | 60 | player.hpCur = player.hpMax; |
56 | player.xp = 0; | 61 | player.xp = 0; |
62 | player.level = 1; | ||
57 | player.attack = 3; | 63 | player.attack = 3; |
64 | player.potions = 1; | ||
58 | 65 | ||
59 | global.bJustTravelled = false; | 66 | global.bJustTravelled = false; |
60 | 67 | ||
@@ -64,16 +71,23 @@ situation <<start>> | |||
64 | 71 | ||
65 | function status() | 72 | function status() |
66 | { | 73 | { |
74 | display('You have ' + (100-player.xp) + ' xp until your next level.'); | ||
67 | display('You have ' + player.hpCur + ' of ' + player.hpMax + ' hp.'); | 75 | display('You have ' + player.hpCur + ' of ' + player.hpMax + ' hp.'); |
76 | display('You are carrying ' + player.potions + ' potions.'); | ||
68 | } | 77 | } |
69 | 78 | ||
70 | function look() | 79 | function look() |
71 | { | 80 | { |
72 | if( exists(global.enemy) )then | 81 | if exists(global.enemy) then |
73 | { | 82 | { |
74 | display('''You are standing in a field of wheat. You see a ''' + | 83 | display('''You are standing in a field of wheat. You see a ''' + |
75 | global.enemy['name'] + ''' in front of you.'''); | 84 | global.enemy['name'] + ''' in front of you.'''); |
76 | } | 85 | } |
86 | else if exists( global.treasure ) then | ||
87 | { | ||
88 | display('''You are standing in a field of wheat. You find a ''' + | ||
89 | global.treasure['name'] + ''' lying here!'''); | ||
90 | } | ||
77 | else | 91 | else |
78 | { | 92 | { |
79 | display('''You are standing in a field of wheat.'''); | 93 | display('''You are standing in a field of wheat.'''); |
@@ -86,12 +100,24 @@ function mkEnemy() | |||
86 | eid = random( 1, 3 ); | 100 | eid = random( 1, 3 ); |
87 | global.enemy = global.enemyTypes[eid]; | 101 | global.enemy = global.enemyTypes[eid]; |
88 | 102 | ||
89 | mod = 1; | 103 | mod = player.level; |
104 | if mod > 3 then | ||
105 | { | ||
106 | mod = 3; | ||
107 | } | ||
90 | global.enemy['name'] = global.enemyMods[mod]['name'] + ' ' + | 108 | global.enemy['name'] = global.enemyMods[mod]['name'] + ' ' + |
91 | global.enemy['name']; | 109 | global.enemy['name']; |
92 | global.enemy['attack'] = global.enemy['attack'] + | 110 | global.enemy['attack'] = global.enemy['attack'] + |
93 | global.enemyMods[mod]['attack']; | 111 | global.enemyMods[mod]['attack']; |
94 | global.enemy['hp'] = global.enemy['hp'] + global.enemyMods[mod]['hp']; | 112 | global.enemy['hp'] = global.enemy['hp'] + global.enemyMods[mod]['hp']; |
113 | global.enemy['level'] = mod; | ||
114 | } | ||
115 | |||
116 | function mkTreasure() | ||
117 | { | ||
118 | global.treasure = { | ||
119 | 'name': 'potion' | ||
120 | }; | ||
95 | } | 121 | } |
96 | 122 | ||
97 | function rollAttack( attack ) | 123 | function rollAttack( attack ) |
@@ -107,7 +133,26 @@ function playerAttack() | |||
107 | ' damage.'); | 133 | ' damage.'); |
108 | if global.enemy['hp'] <= 0 then | 134 | if global.enemy['hp'] <= 0 then |
109 | { | 135 | { |
110 | display('You killed the ' + global.enemy['name'] + '!'); | 136 | xp = 10; |
137 | display('You killed the ' + global.enemy['name'] + '! You gained ' + | ||
138 | xp + ' experience points.'); | ||
139 | player.xp += xp; | ||
140 | if player.xp >= 100 then | ||
141 | { | ||
142 | player.xp -= 100; | ||
143 | player.level += 1; | ||
144 | player.hpMax += integer(random(0.25,0.75)*player.hpMax); | ||
145 | player.hpCur = player.hpMax; | ||
146 | display("You have leveled! Welcome to level " + player.level ); | ||
147 | } | ||
148 | |||
149 | select = random(1, 3); | ||
150 | if select == 1 then | ||
151 | { | ||
152 | display('It looks like the ' + global.enemy['name'] + | ||
153 | ' dropped something...'); | ||
154 | mkTreasure(); | ||
155 | } | ||
111 | delete( global.enemy ); | 156 | delete( global.enemy ); |
112 | } | 157 | } |
113 | } | 158 | } |
@@ -123,22 +168,37 @@ function enemyAttack() | |||
123 | display('The ' + global.enemy['name'] + ' killed you!'); | 168 | display('The ' + global.enemy['name'] + ' killed you!'); |
124 | exit(); | 169 | exit(); |
125 | } | 170 | } |
171 | else | ||
172 | { | ||
173 | display('''You have ''' + player.hpCur + ''' hp left.'''); | ||
174 | } | ||
126 | } | 175 | } |
127 | 176 | ||
128 | situation <<travel>> | 177 | situation <<travel>> |
129 | { | 178 | { |
179 | command: "hi" | ||
180 | { | ||
181 | display("Yup, you're in travel."); | ||
182 | } | ||
183 | |||
130 | enter | 184 | enter |
131 | { | 185 | { |
132 | delete( global.enemy ); | 186 | delete( global.enemy ); |
133 | 187 | ||
134 | display('You wander aimlessly through the seemingly endless field of wheat.'); | 188 | display('You wander aimlessly through the seemingly endless field of wheat.'); |
135 | 189 | ||
136 | select = random(1,3); | 190 | select = random(1,6); |
137 | if select == 1 then | 191 | if select <= 4 then // 66% of the time, enemy! |
138 | { | 192 | { |
139 | mkEnemy(); | 193 | mkEnemy(); |
140 | display('''There's a ''' + global.enemy['name'] + ''' here!'''); | 194 | display('''There's a ''' + global.enemy['name'] + ''' here!'''); |
141 | } | 195 | } |
196 | else if select == 6 then // 16% of the time, treasure! | ||
197 | { | ||
198 | mkTreasure(); | ||
199 | display('''You find a ''' + global.treasure['name'] + | ||
200 | ''' lying here!'''); | ||
201 | } | ||
142 | 202 | ||
143 | global.bJustTravelled = true; | 203 | global.bJustTravelled = true; |
144 | 204 | ||
@@ -161,11 +221,64 @@ situation <<field>> | |||
161 | } | 221 | } |
162 | } | 222 | } |
163 | 223 | ||
224 | command: "take" | ||
225 | { | ||
226 | if exists(global.treasure) then | ||
227 | { | ||
228 | if global.treasure['name'] == 'potion' then | ||
229 | { | ||
230 | display('''You pickup the ''' + global.treasure['name'] + | ||
231 | ''' and put it in your pocket.'''); | ||
232 | player.potions += 1; | ||
233 | delete( global.treasure ); | ||
234 | } | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | display('''There's nothing here to take...'''); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | command: 'drink' | ||
243 | { | ||
244 | if player.potions == 0 then | ||
245 | { | ||
246 | display('''You don't have anything to drink!'''); | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | if player.hpCur == player.hpMax then | ||
251 | { | ||
252 | display('''You're already as healthy as can be! | ||
253 | Save the potions for when you're more injured.'''); | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | player.potions -= 1; | ||
258 | gain = integer( random( 0.25, 0.5 ) * player.hpMax ); | ||
259 | player.hpCur += gain; | ||
260 | if player.hpCur > player.hpMax then | ||
261 | { | ||
262 | gain -= player.hpCur - player.hpMax; | ||
263 | player.hpCur = player.hpMax; | ||
264 | } | ||
265 | display('''That really hit the spot! The potion restored ''' + | ||
266 | gain + ''' hp!'''); | ||
267 | goto( <<field>> ); | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
164 | command: "look" | 272 | command: "look" |
165 | { | 273 | { |
166 | look(); | 274 | look(); |
167 | } | 275 | } |
168 | 276 | ||
277 | command: "status" | ||
278 | { | ||
279 | status(); | ||
280 | } | ||
281 | |||
169 | command: "walk" | 282 | command: "walk" |
170 | { | 283 | { |
171 | if not exists(global.enemy) then | 284 | if not exists(global.enemy) then |
@@ -174,11 +287,17 @@ situation <<field>> | |||
174 | } | 287 | } |
175 | else | 288 | else |
176 | { | 289 | { |
177 | display("You can't walk around with an enemy in front of you! | 290 | display("You can't leave, the " + global.enemy['name'] + |
178 | You can try to flee if you'd like..."); | 291 | ' is blocking your path.'); |
179 | } | 292 | } |
180 | } | 293 | } |
181 | 294 | ||
295 | command: "help" | ||
296 | { | ||
297 | display("Available commands are: walk, status, look, attack, take, | ||
298 | drink"); | ||
299 | } | ||
300 | |||
182 | setup | 301 | setup |
183 | { | 302 | { |
184 | look(); | 303 | look(); |
@@ -192,11 +311,6 @@ situation <<field>> | |||
192 | { | 311 | { |
193 | enemyAttack(); | 312 | enemyAttack(); |
194 | } | 313 | } |
195 | status(); | ||
196 | // look(); | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | } | 314 | } |
201 | global.bJustTravelled = false; | 315 | global.bJustTravelled = false; |
202 | } | 316 | } |
diff --git a/src/functionfloat.cpp b/src/functionfloat.cpp new file mode 100644 index 0000000..7d6a0a5 --- /dev/null +++ b/src/functionfloat.cpp | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "functionfloat.h" | ||
2 | |||
3 | #include "gamestate.h" | ||
4 | |||
5 | FunctionFloat::FunctionFloat() | ||
6 | { | ||
7 | } | ||
8 | |||
9 | FunctionFloat::~FunctionFloat() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | void FunctionFloat::call( class GameState &gState ) | ||
14 | { | ||
15 | gState.push( gState.popDeref().to( Variable::tFloat ) ); | ||
16 | } | ||
17 | |||
diff --git a/src/functionfloat.h b/src/functionfloat.h new file mode 100644 index 0000000..ca72151 --- /dev/null +++ b/src/functionfloat.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef FUNCTION_FLOAT_H | ||
2 | #define FUNCTION_FLOAT_H | ||
3 | |||
4 | #include "function.h" | ||
5 | |||
6 | class FunctionFloat : public Function | ||
7 | { | ||
8 | public: | ||
9 | FunctionFloat(); | ||
10 | virtual ~FunctionFloat(); | ||
11 | |||
12 | virtual Bu::String getName() const { return "float"; } | ||
13 | virtual void call( class GameState &gState ); | ||
14 | }; | ||
15 | |||
16 | #endif | ||
diff --git a/src/functioninteger.cpp b/src/functioninteger.cpp new file mode 100644 index 0000000..049f9ca --- /dev/null +++ b/src/functioninteger.cpp | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "functioninteger.h" | ||
2 | |||
3 | #include "gamestate.h" | ||
4 | |||
5 | FunctionInteger::FunctionInteger() | ||
6 | { | ||
7 | } | ||
8 | |||
9 | FunctionInteger::~FunctionInteger() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | void FunctionInteger::call( class GameState &gState ) | ||
14 | { | ||
15 | gState.push( gState.popDeref().to( Variable::tInt ) ); | ||
16 | } | ||
17 | |||
diff --git a/src/functioninteger.h b/src/functioninteger.h new file mode 100644 index 0000000..2832c20 --- /dev/null +++ b/src/functioninteger.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef FUNCTION_INTEGER_H | ||
2 | #define FUNCTION_INTEGER_H | ||
3 | |||
4 | #include "function.h" | ||
5 | |||
6 | class FunctionInteger : public Function | ||
7 | { | ||
8 | public: | ||
9 | FunctionInteger(); | ||
10 | virtual ~FunctionInteger(); | ||
11 | |||
12 | virtual Bu::String getName() const { return "integer"; } | ||
13 | virtual void call( class GameState &gState ); | ||
14 | }; | ||
15 | |||
16 | #endif | ||
diff --git a/src/functionrandom.cpp b/src/functionrandom.cpp index 2665a14..ec302b3 100644 --- a/src/functionrandom.cpp +++ b/src/functionrandom.cpp | |||
@@ -20,10 +20,17 @@ void FunctionRandom::call( class GameState &gState ) | |||
20 | if( vHigh.getType() != vLow.getType() ) | 20 | if( vHigh.getType() != vLow.getType() ) |
21 | throw Bu::ExceptionBase("Different types in random!"); | 21 | throw Bu::ExceptionBase("Different types in random!"); |
22 | 22 | ||
23 | double dRand = random()/(double)(RAND_MAX-1); | ||
23 | if( vLow.getType() == Variable::tInt ) | 24 | if( vLow.getType() == Variable::tInt ) |
24 | { | 25 | { |
25 | gState.push( Variable( (int64_t)( | 26 | gState.push( Variable( (int64_t)( |
26 | (random()%(vHigh.getInt()-vLow.getInt()+1ll))+vLow.getInt() | 27 | (dRand*(vHigh.getInt()-vLow.getInt()+1ll))+vLow.getInt() |
28 | ) ) ); | ||
29 | } | ||
30 | else if( vLow.getType() == Variable::tFloat ) | ||
31 | { | ||
32 | gState.push( Variable( (double)( | ||
33 | (dRand*(vHigh.getFloat()-vLow.getFloat()))+vLow.getFloat() | ||
27 | ) ) ); | 34 | ) ) ); |
28 | } | 35 | } |
29 | } | 36 | } |
diff --git a/src/game.cpp b/src/game.cpp index c19b039..3a432d9 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
@@ -5,6 +5,8 @@ | |||
5 | #include "functiondelete.h" | 5 | #include "functiondelete.h" |
6 | #include "functionexit.h" | 6 | #include "functionexit.h" |
7 | #include "functionrandom.h" | 7 | #include "functionrandom.h" |
8 | #include "functioninteger.h" | ||
9 | #include "functionfloat.h" | ||
8 | 10 | ||
9 | Game::Game() | 11 | Game::Game() |
10 | { | 12 | { |
@@ -14,6 +16,8 @@ Game::Game() | |||
14 | addFunction( new FunctionDelete() ); | 16 | addFunction( new FunctionDelete() ); |
15 | addFunction( new FunctionExit() ); | 17 | addFunction( new FunctionExit() ); |
16 | addFunction( new FunctionRandom() ); | 18 | addFunction( new FunctionRandom() ); |
19 | addFunction( new FunctionInteger() ); | ||
20 | addFunction( new FunctionFloat() ); | ||
17 | } | 21 | } |
18 | 22 | ||
19 | Game::~Game() | 23 | Game::~Game() |
diff --git a/src/gamebuilder.cpp b/src/gamebuilder.cpp index d04a642..3cf2e1f 100644 --- a/src/gamebuilder.cpp +++ b/src/gamebuilder.cpp | |||
@@ -88,7 +88,7 @@ void GameBuilder::beginSituationMode( Situation::Mode m ) | |||
88 | 88 | ||
89 | void GameBuilder::closeSituationMode() | 89 | void GameBuilder::closeSituationMode() |
90 | { | 90 | { |
91 | //sio << "Set situation mode " << eCurSitMode << " to " << *pCurRoot << sio.nl; | 91 | // sio << "Set situation <<" << pCurSit->getName() << ">> mode " << eCurSitMode << " to " << *pCurRoot << sio.nl; |
92 | pCurSit->setAst( pCurRoot, eCurSitMode ); | 92 | pCurSit->setAst( pCurRoot, eCurSitMode ); |
93 | pCurRoot = pCurNode = NULL; | 93 | pCurRoot = pCurNode = NULL; |
94 | } | 94 | } |
diff --git a/src/parser.l b/src/parser.l index 7b11765..e0bc340 100644 --- a/src/parser.l +++ b/src/parser.l | |||
@@ -67,7 +67,7 @@ null { return tokNull; } | |||
67 | 67 | ||
68 | [a-zA-Z_][a-zA-Z0-9_]* { yylval->sValue = new Bu::String( yytext ); return tokIdent; } | 68 | [a-zA-Z_][a-zA-Z0-9_]* { yylval->sValue = new Bu::String( yytext ); return tokIdent; } |
69 | 69 | ||
70 | [1-9][0-9]* { | 70 | -?[1-9][0-9]* { |
71 | yylval->iValue = strtoll( yytext, NULL, 10 ); | 71 | yylval->iValue = strtoll( yytext, NULL, 10 ); |
72 | return tokInt; | 72 | return tokInt; |
73 | } | 73 | } |
@@ -76,10 +76,10 @@ null { return tokNull; } | |||
76 | return tokInt; | 76 | return tokInt; |
77 | } | 77 | } |
78 | 78 | ||
79 | ([1-9][0-9]*)?\.[0-9]* { | 79 | -?([1-9][0-9]*|0)?\.[0-9]* { |
80 | printf("Parsing float: %s\n", yytext ); | 80 | // printf("Parsing float: %s\n", yytext ); |
81 | yylval->dValue = strtod( yytext, NULL ); | 81 | yylval->dValue = strtod( yytext, NULL ); |
82 | printf("Final float: %f\n", yylval->dValue ); | 82 | // printf("Final float: %f\n", yylval->dValue ); |
83 | return tokFloat; | 83 | return tokFloat; |
84 | } | 84 | } |
85 | 85 | ||
diff --git a/src/parser.y b/src/parser.y index 3dfd737..2e9eead 100644 --- a/src/parser.y +++ b/src/parser.y | |||
@@ -54,7 +54,7 @@ void yyerror( YYLTYPE *llocp, yyscan_t yyscanner, GameBuilder &, const char *err | |||
54 | %token tokDo | 54 | %token tokDo |
55 | %token tokIn | 55 | %token tokIn |
56 | %token tokIf | 56 | %token tokIf |
57 | %token tokThen | 57 | %token tokThen "then" |
58 | %token tokElse | 58 | %token tokElse |
59 | %token tokNot | 59 | %token tokNot |
60 | %token tokCommand | 60 | %token tokCommand |
@@ -204,7 +204,9 @@ ifnext: | |||
204 | | tokElse { bld.addNode( AstNode::tScope ); } '{' cmpltExprList '}' { | 204 | | tokElse { bld.addNode( AstNode::tScope ); } '{' cmpltExprList '}' { |
205 | bld.closeNode(); | 205 | bld.closeNode(); |
206 | } | 206 | } |
207 | | tokElse { bld.addNode( AstNode::tScope ); } ifbase | 207 | | tokElse { bld.addNode( AstNode::tScope ); } ifbase { |
208 | bld.closeNode(); | ||
209 | } | ||
208 | ; | 210 | ; |
209 | 211 | ||
210 | varRef: tokIdent { bld.addVarRef( *($1), sidLocal ); } | 212 | varRef: tokIdent { bld.addVarRef( *($1), sidLocal ); } |
diff --git a/src/variable.cpp b/src/variable.cpp index 965e1af..2ea8334 100644 --- a/src/variable.cpp +++ b/src/variable.cpp | |||
@@ -463,7 +463,6 @@ Variable Variable::operator+( const Variable &rhs ) const | |||
463 | { | 463 | { |
464 | return *this + rhs.to( eNew ); | 464 | return *this + rhs.to( eNew ); |
465 | } | 465 | } |
466 | throw VariableException("Adding between dissimilar types is not yet supported."); | ||
467 | } | 466 | } |
468 | else | 467 | else |
469 | { | 468 | { |
@@ -509,7 +508,16 @@ Variable Variable::operator-( const Variable &rhs ) const | |||
509 | { | 508 | { |
510 | if( eType != rhs.eType ) | 509 | if( eType != rhs.eType ) |
511 | { | 510 | { |
512 | throw VariableException("Subtracting between dissimilar types is not yet supported."); | 511 | Type eNew = bestType( eType, rhs.eType ); |
512 | |||
513 | if( eType != eNew ) | ||
514 | { | ||
515 | return to( eNew ) - rhs; | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | return *this - rhs.to( eNew ); | ||
520 | } | ||
513 | } | 521 | } |
514 | else | 522 | else |
515 | { | 523 | { |
@@ -551,7 +559,16 @@ Variable Variable::operator*( const Variable &rhs ) const | |||
551 | { | 559 | { |
552 | if( eType != rhs.eType ) | 560 | if( eType != rhs.eType ) |
553 | { | 561 | { |
554 | throw VariableException("Subtracting between dissimilar types is not yet supported."); | 562 | Type eNew = bestType( eType, rhs.eType ); |
563 | |||
564 | if( eType != eNew ) | ||
565 | { | ||
566 | return to( eNew ) * rhs; | ||
567 | } | ||
568 | else | ||
569 | { | ||
570 | return *this * rhs.to( eNew ); | ||
571 | } | ||
555 | } | 572 | } |
556 | else | 573 | else |
557 | { | 574 | { |
@@ -592,7 +609,16 @@ Variable Variable::operator/( const Variable &rhs ) const | |||
592 | { | 609 | { |
593 | if( eType != rhs.eType ) | 610 | if( eType != rhs.eType ) |
594 | { | 611 | { |
595 | throw VariableException("Subtracting between dissimilar types is not yet supported."); | 612 | Type eNew = bestType( eType, rhs.eType ); |
613 | |||
614 | if( eType != eNew ) | ||
615 | { | ||
616 | return to( eNew ) / rhs; | ||
617 | } | ||
618 | else | ||
619 | { | ||
620 | return *this / rhs.to( eNew ); | ||
621 | } | ||
596 | } | 622 | } |
597 | else | 623 | else |
598 | { | 624 | { |
diff --git a/support/vim/syntax/stage.vim b/support/vim/syntax/stage.vim index 34da126..45e1346 100644 --- a/support/vim/syntax/stage.vim +++ b/support/vim/syntax/stage.vim | |||
@@ -19,7 +19,7 @@ syn keyword Statement setup enter | |||
19 | syn keyword Todo TODO FIXME XXX | 19 | syn keyword Todo TODO FIXME XXX |
20 | syn keyword Type function command situation game global player | 20 | syn keyword Type function command situation game global player |
21 | syn keyword Constant null true false | 21 | syn keyword Constant null true false |
22 | syn keyword Builtins display goto exists delete exit return | 22 | syn keyword Builtins display goto exists delete exit return random integer float |
23 | 23 | ||
24 | syn cluster CommentGroup contains=Todo | 24 | syn cluster CommentGroup contains=Todo |
25 | 25 | ||
@@ -17,13 +17,11 @@ situation <<start>> | |||
17 | { | 17 | { |
18 | setup | 18 | setup |
19 | { | 19 | { |
20 | stuff = {}; | 20 | for each i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] do |
21 | stuff['bob'] = {'joe': 'hi', 'sub': {1: 5, 2: 8} }; | 21 | { |
22 | stuff['bob']['sub'][55] = "aoeu"; | 22 | display( random(0.25, 0.5)*10 ); |
23 | stuff['bob'] = 'hia'; | 23 | } |
24 | stuff['joe'] = stuff['bob']; | 24 | display( 0.25 * 10.0 ); |
25 | stuff['joe'] += 'aoeu'; | ||
26 | display( stuff['bob']['sub'][55] ); | ||
27 | exit(); | 25 | exit(); |
28 | } | 26 | } |
29 | 27 | ||