A year of gamedev experiments.

Day 87 - Beholder on Your Phone Pt5

Yesterday’s post was way too long; sorry about that. I’m not sure if today’s will be shorter.

Dude Refactor

Ran into a few bumps with duplicate Dude names in the tests, and didn’t want to have to manually
keep them unique, so wrote a quick before hook to make sure I have two (likely) unique Dude names
available to the test case.

Misc Process

Another refactor was the move the SetKey cheat into a method called process_misc so we can call
it for both new players (for whom we don’t process input yet) and existing players (for whom we
will process input).

it'shows ifConditionFalse story without condition'doget'/',From:@dude,SkipToState:'S09'expect(last_response.body).toinclude("But it's a really cool car!")expect(last_response.body).not_toinclude("I'm always nervous when we hang out.")endit'shows ifConditionFalse story with false condition'doget'/',From:@dude,SkipToState:'S09',SetKey:'siri-smoked',SetKeyValue:'false'expect(last_response.body).toinclude("But it's a really cool car!")expect(last_response.body).not_toinclude("I'm always nervous when we hang out.")endit'shows ifConditionTrue story with true condition'doget'/',From:@dude,SkipToState:'S09',SetKey:'siri-smoked',SetKeyValue:'true'expect(last_response.body).toinclude("I'm always nervous when we hang out.")expect(last_response.body).not_toinclude("But it's a really cool car!")endit'proceeds to ifConditionFalse state without condition'doget'/',From:@dude,SkipToState:'S09'get'/',From:@dudeexpect(last_response.body).toinclude("Can you like, buzz off?")endit'proceeds to ifConditionFalse state with false condition'doget'/',From:@dude,SkipToState:'S09',SetKey:'siri-smoked',SetKeyValue:'false'get'/',From:@dudeexpect(last_response.body).toinclude("Can you like, buzz off?")endit'proceeds to ifConditionTrue state with true condition'doget'/',From:@dude,SkipToState:'S09',SetKey:'siri-smoked',SetKeyValue:'true'get'/',From:@dudeexpect(last_response.body).toinclude("Hehe. You're such a nerd")end

Looks pretty repetitive, and we may DRY it up sooner than
later. But it does work.

Storyless States

In order to get the “can be played all the way through” test case to
work, we had to allow for states that don’t actually have a story key. The fix was trivial, but
the important part is that we added a test for it:

"S03":{"beholder":"siri","beholderPos":"center","beholderExp":"shy","beholderAnimation":"fadeIn","bg":"Lunchroom","buttonText":"Success","namePlate":"Siriak the Rapid","story":"Yeah, well... I was planning on hanging out around this lame dance. There's nothing else to do tonight. You want to come?","next":"SIRIWIN"},

"S02":{"beholder":"siri","beholderPos":"left","beholderExp":"neutral","beholderAnimation":"fadeIn","bg":"Lunchroom","namePlate":":name:","conditionalStory":{"condition":{"siri-smoked":"true"},"ifConditionTrue":{"story":"Yeah. Or we could just hang out by the dumpster. Maybe just you and me this time?","next":"S03","buttonText":"Next"},"ifConditionFalse":{"story":"Sweet! I love beer!","next":"S04","buttonText":"Next"}}},

"D1S307":{"bg":"Dumpster","story":"Someone offers you the cigarette, and you can feel Siriak's gaze drawn down upon you. You draw, hold it, and exhale, all without erupting into a fit of coughing. They think you're cool. Siriak thinks you're cool. And you've made a fool of the surgeon general.","next":"DAY2","buttonText":"Next","beholder":"siri","beholderPos":"center","beholderExp":"neutral","beholderAnimation":"fadeIn","plotPoint":{"siri-smoked":"true"}},

defprocess_output(player)state=player['state']response=GameStates.story(state,player)GameStates.selections(state,player).each_with_indexdo|selection,index|response+="\n#{index+1}) #{selection.first}"endGameStates.plot_points(state).each_pairdo|key,value|player[key]=valueputs"Plot point set player key #{key} to #{value}, and now player is #{player}"end

and there we have it. It may seem weird to have put the plot points in process_output, but they
are an output of the state (just not one that is directly exposed to the player).

Good Endings

Rather than just rerunning the tests a bunch of times, let’s actually seek out a good ending:

it'can be played to a good ending'doget'/',From:@dudeTimeout::timeout(10)dountillast_response.body.include?('Royalty does not concern itself with common dances.')||last_response.body.include?('True power is slow dancing with someone who could beat you senseless.')||last_response.body.include?('Thirst for knowledge. Hunger for power. No feast is fine enough.')do@dude+='0'iflast_response.body.include?('And you won\'t be alone...')get'/',From:@dude,Body:['1','2','3'].sampleputslast_response.bodyendendend

When we hit a bad ending, we just add a zero to the end of the player ID and we get restarted. We
also test the bad ending the same way.