From 8b9a15a755ebc6681ff6be808615e375cb567080 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 3 Jan 2012 00:08:48 -0700 Subject: New functions, fixes, and a working bloodfields. --- bloodfields.stage | 152 +++++++++++++++++++++++++++++++++++++------ src/functionfloat.cpp | 17 +++++ src/functionfloat.h | 16 +++++ src/functioninteger.cpp | 17 +++++ src/functioninteger.h | 16 +++++ src/functionrandom.cpp | 9 ++- src/game.cpp | 4 ++ src/gamebuilder.cpp | 2 +- src/parser.l | 8 +-- src/parser.y | 6 +- src/variable.cpp | 34 ++++++++-- support/vim/syntax/stage.vim | 2 +- test.stage | 12 ++-- 13 files changed, 256 insertions(+), 39 deletions(-) create mode 100644 src/functionfloat.cpp create mode 100644 src/functionfloat.h create mode 100644 src/functioninteger.cpp create mode 100644 src/functioninteger.h diff --git a/bloodfields.stage b/bloodfields.stage index 7b61dd4..91bee08 100644 --- a/bloodfields.stage +++ b/bloodfields.stage @@ -6,6 +6,11 @@ global { exit(); } + + command: "exit" + { + exit(); + } } situation <> @@ -14,19 +19,19 @@ situation <> { global.enemyTypes = { 1: { - 'name': 'Snail', - 'action': 'bites', + 'name': 'snail', + 'action': 'oozes on', 'hp': 3, 'attack': 2 }, 2: { - 'name': 'Wolf', + 'name': 'wolf', 'action': 'bites', 'hp': 7, 'attack': 3 }, 3: { - 'name': 'Snake', + 'name': 'snake', 'action': 'strikes at', 'hp': 3, 'attack': 3 @@ -35,17 +40,17 @@ situation <> global.enemyMods = { 1: { - 'name': 'Pathetic', + 'name': 'pathetic', 'hp': 0, 'attack': 0 }, 2: { - 'name': 'Sickly', + 'name': 'sickly', 'hp': 3, 'attack': 1 }, 3: { - 'name': 'Wimpy', + 'name': 'wimpy', 'hp': 5, 'attack': 2 } @@ -54,7 +59,9 @@ situation <> player.hpMax = 10; player.hpCur = player.hpMax; player.xp = 0; + player.level = 1; player.attack = 3; + player.potions = 1; global.bJustTravelled = false; @@ -64,16 +71,23 @@ situation <> function status() { + display('You have ' + (100-player.xp) + ' xp until your next level.'); display('You have ' + player.hpCur + ' of ' + player.hpMax + ' hp.'); + display('You are carrying ' + player.potions + ' potions.'); } function look() { - if( exists(global.enemy) )then + if exists(global.enemy) then { display('''You are standing in a field of wheat. You see a ''' + global.enemy['name'] + ''' in front of you.'''); } + else if exists( global.treasure ) then + { + display('''You are standing in a field of wheat. You find a ''' + + global.treasure['name'] + ''' lying here!'''); + } else { display('''You are standing in a field of wheat.'''); @@ -86,12 +100,24 @@ function mkEnemy() eid = random( 1, 3 ); global.enemy = global.enemyTypes[eid]; - mod = 1; + mod = player.level; + if mod > 3 then + { + mod = 3; + } global.enemy['name'] = global.enemyMods[mod]['name'] + ' ' + global.enemy['name']; global.enemy['attack'] = global.enemy['attack'] + global.enemyMods[mod]['attack']; global.enemy['hp'] = global.enemy['hp'] + global.enemyMods[mod]['hp']; + global.enemy['level'] = mod; +} + +function mkTreasure() +{ + global.treasure = { + 'name': 'potion' + }; } function rollAttack( attack ) @@ -107,7 +133,26 @@ function playerAttack() ' damage.'); if global.enemy['hp'] <= 0 then { - display('You killed the ' + global.enemy['name'] + '!'); + xp = 10; + display('You killed the ' + global.enemy['name'] + '! You gained ' + + xp + ' experience points.'); + player.xp += xp; + if player.xp >= 100 then + { + player.xp -= 100; + player.level += 1; + player.hpMax += integer(random(0.25,0.75)*player.hpMax); + player.hpCur = player.hpMax; + display("You have leveled! Welcome to level " + player.level ); + } + + select = random(1, 3); + if select == 1 then + { + display('It looks like the ' + global.enemy['name'] + + ' dropped something...'); + mkTreasure(); + } delete( global.enemy ); } } @@ -123,22 +168,37 @@ function enemyAttack() display('The ' + global.enemy['name'] + ' killed you!'); exit(); } + else + { + display('''You have ''' + player.hpCur + ''' hp left.'''); + } } situation <> { + command: "hi" + { + display("Yup, you're in travel."); + } + enter { delete( global.enemy ); display('You wander aimlessly through the seemingly endless field of wheat.'); - select = random(1,3); - if select == 1 then + select = random(1,6); + if select <= 4 then // 66% of the time, enemy! { mkEnemy(); display('''There's a ''' + global.enemy['name'] + ''' here!'''); } + else if select == 6 then // 16% of the time, treasure! + { + mkTreasure(); + display('''You find a ''' + global.treasure['name'] + + ''' lying here!'''); + } global.bJustTravelled = true; @@ -161,11 +221,64 @@ situation <> } } + command: "take" + { + if exists(global.treasure) then + { + if global.treasure['name'] == 'potion' then + { + display('''You pickup the ''' + global.treasure['name'] + + ''' and put it in your pocket.'''); + player.potions += 1; + delete( global.treasure ); + } + } + else + { + display('''There's nothing here to take...'''); + } + } + + command: 'drink' + { + if player.potions == 0 then + { + display('''You don't have anything to drink!'''); + } + else + { + if player.hpCur == player.hpMax then + { + display('''You're already as healthy as can be! + Save the potions for when you're more injured.'''); + } + else + { + player.potions -= 1; + gain = integer( random( 0.25, 0.5 ) * player.hpMax ); + player.hpCur += gain; + if player.hpCur > player.hpMax then + { + gain -= player.hpCur - player.hpMax; + player.hpCur = player.hpMax; + } + display('''That really hit the spot! The potion restored ''' + + gain + ''' hp!'''); + goto( <> ); + } + } + } + command: "look" { look(); } + command: "status" + { + status(); + } + command: "walk" { if not exists(global.enemy) then @@ -174,11 +287,17 @@ situation <> } else { - display("You can't walk around with an enemy in front of you! - You can try to flee if you'd like..."); + display("You can't leave, the " + global.enemy['name'] + + ' is blocking your path.'); } } + command: "help" + { + display("Available commands are: walk, status, look, attack, take, + drink"); + } + setup { look(); @@ -192,11 +311,6 @@ situation <> { enemyAttack(); } - status(); -// look(); - } - else - { } global.bJustTravelled = false; } 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 @@ +#include "functionfloat.h" + +#include "gamestate.h" + +FunctionFloat::FunctionFloat() +{ +} + +FunctionFloat::~FunctionFloat() +{ +} + +void FunctionFloat::call( class GameState &gState ) +{ + gState.push( gState.popDeref().to( Variable::tFloat ) ); +} + 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 @@ +#ifndef FUNCTION_FLOAT_H +#define FUNCTION_FLOAT_H + +#include "function.h" + +class FunctionFloat : public Function +{ +public: + FunctionFloat(); + virtual ~FunctionFloat(); + + virtual Bu::String getName() const { return "float"; } + virtual void call( class GameState &gState ); +}; + +#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 @@ +#include "functioninteger.h" + +#include "gamestate.h" + +FunctionInteger::FunctionInteger() +{ +} + +FunctionInteger::~FunctionInteger() +{ +} + +void FunctionInteger::call( class GameState &gState ) +{ + gState.push( gState.popDeref().to( Variable::tInt ) ); +} + 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 @@ +#ifndef FUNCTION_INTEGER_H +#define FUNCTION_INTEGER_H + +#include "function.h" + +class FunctionInteger : public Function +{ +public: + FunctionInteger(); + virtual ~FunctionInteger(); + + virtual Bu::String getName() const { return "integer"; } + virtual void call( class GameState &gState ); +}; + +#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 ) if( vHigh.getType() != vLow.getType() ) throw Bu::ExceptionBase("Different types in random!"); + double dRand = random()/(double)(RAND_MAX-1); if( vLow.getType() == Variable::tInt ) { gState.push( Variable( (int64_t)( - (random()%(vHigh.getInt()-vLow.getInt()+1ll))+vLow.getInt() + (dRand*(vHigh.getInt()-vLow.getInt()+1ll))+vLow.getInt() + ) ) ); + } + else if( vLow.getType() == Variable::tFloat ) + { + gState.push( Variable( (double)( + (dRand*(vHigh.getFloat()-vLow.getFloat()))+vLow.getFloat() ) ) ); } } 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 @@ #include "functiondelete.h" #include "functionexit.h" #include "functionrandom.h" +#include "functioninteger.h" +#include "functionfloat.h" Game::Game() { @@ -14,6 +16,8 @@ Game::Game() addFunction( new FunctionDelete() ); addFunction( new FunctionExit() ); addFunction( new FunctionRandom() ); + addFunction( new FunctionInteger() ); + addFunction( new FunctionFloat() ); } 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 ) void GameBuilder::closeSituationMode() { - //sio << "Set situation mode " << eCurSitMode << " to " << *pCurRoot << sio.nl; +// sio << "Set situation <<" << pCurSit->getName() << ">> mode " << eCurSitMode << " to " << *pCurRoot << sio.nl; pCurSit->setAst( pCurRoot, eCurSitMode ); pCurRoot = pCurNode = NULL; } 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; } [a-zA-Z_][a-zA-Z0-9_]* { yylval->sValue = new Bu::String( yytext ); return tokIdent; } -[1-9][0-9]* { +-?[1-9][0-9]* { yylval->iValue = strtoll( yytext, NULL, 10 ); return tokInt; } @@ -76,10 +76,10 @@ null { return tokNull; } return tokInt; } -([1-9][0-9]*)?\.[0-9]* { - printf("Parsing float: %s\n", yytext ); +-?([1-9][0-9]*|0)?\.[0-9]* { +// printf("Parsing float: %s\n", yytext ); yylval->dValue = strtod( yytext, NULL ); - printf("Final float: %f\n", yylval->dValue ); +// printf("Final float: %f\n", yylval->dValue ); return tokFloat; } 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 %token tokDo %token tokIn %token tokIf -%token tokThen +%token tokThen "then" %token tokElse %token tokNot %token tokCommand @@ -204,7 +204,9 @@ ifnext: | tokElse { bld.addNode( AstNode::tScope ); } '{' cmpltExprList '}' { bld.closeNode(); } - | tokElse { bld.addNode( AstNode::tScope ); } ifbase + | tokElse { bld.addNode( AstNode::tScope ); } ifbase { + bld.closeNode(); + } ; 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 { return *this + rhs.to( eNew ); } - throw VariableException("Adding between dissimilar types is not yet supported."); } else { @@ -509,7 +508,16 @@ Variable Variable::operator-( const Variable &rhs ) const { if( eType != rhs.eType ) { - throw VariableException("Subtracting between dissimilar types is not yet supported."); + Type eNew = bestType( eType, rhs.eType ); + + if( eType != eNew ) + { + return to( eNew ) - rhs; + } + else + { + return *this - rhs.to( eNew ); + } } else { @@ -551,7 +559,16 @@ Variable Variable::operator*( const Variable &rhs ) const { if( eType != rhs.eType ) { - throw VariableException("Subtracting between dissimilar types is not yet supported."); + Type eNew = bestType( eType, rhs.eType ); + + if( eType != eNew ) + { + return to( eNew ) * rhs; + } + else + { + return *this * rhs.to( eNew ); + } } else { @@ -592,7 +609,16 @@ Variable Variable::operator/( const Variable &rhs ) const { if( eType != rhs.eType ) { - throw VariableException("Subtracting between dissimilar types is not yet supported."); + Type eNew = bestType( eType, rhs.eType ); + + if( eType != eNew ) + { + return to( eNew ) / rhs; + } + else + { + return *this / rhs.to( eNew ); + } } else { 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 syn keyword Todo TODO FIXME XXX syn keyword Type function command situation game global player syn keyword Constant null true false -syn keyword Builtins display goto exists delete exit return +syn keyword Builtins display goto exists delete exit return random integer float syn cluster CommentGroup contains=Todo diff --git a/test.stage b/test.stage index 66a9b70..4ffec79 100644 --- a/test.stage +++ b/test.stage @@ -17,13 +17,11 @@ situation <> { setup { - stuff = {}; - stuff['bob'] = {'joe': 'hi', 'sub': {1: 5, 2: 8} }; - stuff['bob']['sub'][55] = "aoeu"; - stuff['bob'] = 'hia'; - stuff['joe'] = stuff['bob']; - stuff['joe'] += 'aoeu'; - display( stuff['bob']['sub'][55] ); + for each i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] do + { + display( random(0.25, 0.5)*10 ); + } + display( 0.25 * 10.0 ); exit(); } -- cgit v1.2.3