301 Days

A year of gamedev experiments.

Day 84 - Beholder on Your Phone Pt2

| Comments

In which we continue to port a very reasonable game to an unreasonable platform.

Test, Code, Repeat

Still working on the port of Beholder High, still concentrating on just the text for now. First more tests, to make sure we can take the player name:

spec/sms_beholder_spec.rblink
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  it 'accepts a player name' do
    get '/', From: 'Dude4'
    get '/', From: 'Dude4', Body: 'NameOfDude4'
    get '/', From: 'Dude4'
    get '/', From: 'Dude4'

    expect(last_response.body).to include("You're NameOfDude4, a student at Beholder High.")
  end

  it 'uses the right player name' do
    get '/', From: 'Dude5'
    get '/', From: 'Dude5', Body: 'NumberFive'
    get '/', From: 'Dude6'
    get '/', From: 'Dude6'
    get '/', From: 'Dude5'
    get '/', From: 'Dude5'

    expect(last_response.body).to include("You're NumberFive, a student at Beholder High.")
  end

and we flesh out the code to pass them:

sms_beholder.rblink
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class SMSBeholder < Sinatra::Base
  player_data = {}
  game_states = JSON.parse(File.open('script.json', 'r').read)

  get '/' do
    source = params['From']
    body   = params['Body']

    player_data[source] ||= {}
    player_data[source]['state'] ||= 'SPLASH'

    state = player_data[source]['state']
    puts state

    # Handle input
    if player_data[source].key?('last_state')
      last_state = player_data[source]['last_state']
      if game_states[last_state].key?('textEntry')
        text_entry_key = game_states[last_state]['textEntry']['key']
        player_data[source][text_entry_key] = body
      end
    end

    next_state = game_states[state]['next']
    response = game_states[state]['story']
    player_data[source]['last_state'] = state
    player_data[source]['state'] = next_state
    puts player_data

    # Fill in values in response
    for key in player_data[source].keys
      response.sub!(":#{key}:", player_data[source][key])
    end
    response
  end

So now we have a player_data hash, keyed by message source, to keep player data. We keep the state there, defaulted to SPLASH.

Also, if the last state had a textEntry key, we set that key on the player to the test they entered.

Finally, when sending the text to the player, we can subsitute anything if the form of :some_key: with the value of that key in the player data.

With the end result that we can now pass those tests. Yay!

Cheat Code

This is really awkward:

spec/sms_beholder_spec.rblink
32
33
34
35
36
  it 'accepts a player name' do
    get '/', From: 'Dude4'
    get '/', From: 'Dude4', Body: 'NameOfDude4'
    get '/', From: 'Dude4'
    get '/', From: 'Dude4'

and will only get worse as we progress. A purist would dictate that this should be addressed in the test code (and I probably will at some point), but let’s use this opportunity to implement a cheat code in the game itself (to be used purely for testing, of course).

We’ll test-drive this as well:

spec/sms_beholder_spec.rblink
52
53
54
55
56
  it 'lets you skip to a different state for testing' do
    get '/', From: 'Dude7', SkipToState: 'D1S107'

    expect(last_response.body).to include("Your brooding has distracted you")
  end

and the implementation is simple:

sms_beholder.rblink
16
17
    state = player_data[source]['state']
    state = params['SkipToState'] if params.key?('SkipToState')

Rubocop has some complaints, and we may want to tackle those. Tomorrow.


Useful Stuff


Day 84 code

Comments