0

Hello I've been learning from the Chris Pine's, learn to program book on ruby and since finishing I have been trying to write a text adventure game, taking some ideas from the bitwise article 'adventures in ruby.'

For combat, I have put in a while statement which breaks when either the player's hit points or the enemy's hit points reach 0. There is a timer which runs the math for damage every 2 seconds. I'd like some way of allowing the player to type in commands during combat in a way that doesn't interrupt the timer, but when asking the code to call a gets.chomp, if the player takes more than 2 seconds, the timer crashes. Heres the code with most of the useless bits taken out:-

while true
    start_time = Time.now
    hp[1] = hp[1] - (enemy.stats[0] - rand(enemy.stats[0]))
    enemy.hp = enemy.hp.to_i - (mystats[0] - rand(mystats[0]))
    if hp[1] <= 0 or enemy.hp <= 0
        break
    end
    puts " "
    puts "(hp: #{hp[1]} mp: #{mp[1]} st: #{st[1]})"
    #enemy conditions go here
    puts "Enemy condition: " + condition
    puts " "
    total_time = Time.now - start_time 
    sleep(2.0 - total_time)
end

The way I can thing it might be done is to have another timer refresh gets.chomp every 2 seconds but I can't think to do that.

Any help would me much appreciated.

Nakilon
  • 34,866
  • 14
  • 107
  • 142
  • 1
    The issues you are running into are because you are trying to do two things at once. If you want a timer to run while allowing the program to block for input, then you'll need to look into using threads, or a concurrency framework like EventMachine. – Jeremy Nov 21 '10 at 14:44
  • Thanks Jeremy, I took a look into threads and I have managed to put in place a basic system whereby combat initiates a new thread which contains the while loop and joins back to the main game loop as soon as either actor dies. Thank you very much :) – Chris B Nov 22 '10 at 10:36

1 Answers1

0

You don't say what version of Ruby you're running. Also, your sample code doesn't demonstrate your use of gets, which is important if you're having a problem with it. Nor does it show any sample of how you're trying to loop in the background as it waits for the user.

Based on your title and the use of Time, this is the minimum code I could think of that would start to test the problem:

time = Time.now
asdf = STDIN.gets
p Time.now - time

In Ruby 1.8.7:

test.rb(main):004:0> greg-mbp-wireless:Desktop greg$ rvm 1.8.7; rvm list

rvm rubies

=> ruby-1.8.7-p302 [ x86_64 ]
   ruby-1.9.2-head [ x86_64 ]
   ruby-1.9.2-p0 [ x86_64 ]

greg-mbp-wireless:Desktop greg$ irb -f test.rb
test.rb(main):001:0> time = Time.now
=> Sun Nov 21 13:24:58 -0700 2010
test.rb(main):002:0> asdf = STDIN.gets

=> "\n"
test.rb(main):003:0> p Time.now - time
3.802123
=> nil

In Ruby 1.9.2:

test.rb(main):004:0> greg-mbp-wireless:Desktop greg$ rvm 1.9.2; rvm list

rvm rubies

   ruby-1.8.7-p302 [ x86_64 ]
   ruby-1.9.2-head [ x86_64 ]
=> ruby-1.9.2-p0 [ x86_64 ]

greg-mbp-wireless:Desktop greg$ irb -f test.rb
test.rb(main):001:0> time = Time.now
=> 2010-11-21 13:25:37 -0700
test.rb(main):002:0> asdf = STDIN.gets

=> "\n"
test.rb(main):003:0> p Time.now - time
3.578869
=> 3.578869

In each test I paused a couple seconds which is reflected in the Time calculations.

Besides p returning a value in 1.9.2 and nil in 1.8.7, I don't see any real difference. Show some sample of how you're looping in the background to do your calculations and I can expand the test code.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • Sorry about the lack of information Greg, next time I'll be sure to be more comprehensive, I managed to solve the problem by using Threads which are a completely new concept to me but a fun one nonetheless! Thank you for your help. – Chris B Nov 22 '10 at 10:38
  • Threads are way cool. I've done some fun things with them, and with spawning multiple child processes. I once had a spider I wrote that used about 15 children. Getting it debugged was a fun exercise. :-) – the Tin Man Nov 22 '10 at 15:45