Class: TextPlayer::Dfrotz

Inherits:
Object
  • Object
show all
Defined in:
lib/text_player/dfrotz.rb

Overview

Dfrotz - Direct interface to dfrotz interpreter

Constant Summary collapse

TIMEOUT =
1
IO_SELECT_TIMEOUT =
0.1
CHUNK_SIZE =
1024
COMMAND_DELAY =
0.1
SYSTEM_PATH =
"dfrotz"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(game_path, dfrotz: nil, timeout: TIMEOUT, command_delay: COMMAND_DELAY) ⇒ Dfrotz

Returns a new instance of Dfrotz.



24
25
26
27
28
29
30
31
32
33
# File 'lib/text_player/dfrotz.rb', line 24

def initialize(game_path, dfrotz: nil, timeout: TIMEOUT, command_delay: COMMAND_DELAY)
  Signal.trap("PIPE", "DEFAULT")
  @game_path = game_path
  @dfrotz = dfrotz || self.class.path
  raise "dfrotz not found: #{@dfrotz.inspect}" unless self.class.executable?(@dfrotz)

  @timeout = timeout
  @command_delay = command_delay
  @stdin = @stdout = @wait_thr = nil
end

Class Method Details

.executable?(path = self.path) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/text_player/dfrotz.rb', line 20

def self.executable?(path = self.path)
  File.executable?(path) || system("which #{path} > /dev/null 2>&1")
end

.pathObject



16
17
18
# File 'lib/text_player/dfrotz.rb', line 16

def self.path
  ENV.fetch("DFROTZ_PATH", SYSTEM_PATH)
end

Instance Method Details

#read_allObject



60
61
62
# File 'lib/text_player/dfrotz.rb', line 60

def read_all
  read_until(nil)
end

#read_until(pattern) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/text_player/dfrotz.rb', line 64

def read_until(pattern)
  return "" unless running?

  output = +""
  begin
    Timeout.timeout(@timeout) do
      loop do
        break unless read_chunk_into(output)
        break if pattern && output =~ pattern
      end
    end
  rescue Timeout::Error
    # Return whatever we got
  end
  output
end

#running?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/text_player/dfrotz.rb', line 81

def running?
  @stdin && !@stdin.closed? && @wait_thr&.alive?
end

#startObject



35
36
37
38
39
40
# File 'lib/text_player/dfrotz.rb', line 35

def start
  return true if running?

  @stdin, @stdout, @wait_thr = Open3.popen2(@dfrotz, @game_path)
  true
end

#terminateObject



85
86
87
88
89
90
91
92
# File 'lib/text_player/dfrotz.rb', line 85

def terminate
  return true unless running?

  close
  @wait_thr.kill
rescue
  true
end

#write(cmd) ⇒ Object

Send a command to the game.

Automatically sleeps for COMMAND_DELAY seconds, keeping callers simple. It takes time for every command to return output. If you don’t wait, you’ll get nothing in response, and then follow up commands will return the last command’s output instead of the current command’s.



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/text_player/dfrotz.rb', line 48

def write(cmd)
  return false unless running?

  @stdin.puts(cmd)
  @stdin.flush
  sleep(@command_delay)
  true
rescue Errno::EPIPE
  # Process has exited - this is expected during quit
  false
end