Class: Textbringer::Gamegrid

Inherits:
Object
  • Object
show all
Defined in:
lib/textbringer/gamegrid.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height, margin_left: 0) ⇒ Gamegrid

Returns a new instance of Gamegrid.



9
10
11
12
13
14
15
16
17
18
# File 'lib/textbringer/gamegrid.rb', line 9

def initialize(width, height, margin_left: 0)
  @width = width
  @height = height
  @margin_left = margin_left
  @grid = Array.new(height) { Array.new(width, 0) }
  @faces = Array.new(height) { Array.new(width, nil) }
  @display_options = {}
  @score = 0
  @timer_thread = nil
end

Instance Attribute Details

#heightObject (readonly)

Returns the value of attribute height.



6
7
8
# File 'lib/textbringer/gamegrid.rb', line 6

def height
  @height
end

#scoreObject

Returns the value of attribute score.



7
8
9
# File 'lib/textbringer/gamegrid.rb', line 7

def score
  @score
end

#widthObject (readonly)

Returns the value of attribute width.



6
7
8
# File 'lib/textbringer/gamegrid.rb', line 6

def width
  @width
end

Class Method Details

.add_score(game_name, score, player_name: "anonymous") ⇒ Object



127
128
129
130
131
132
133
# File 'lib/textbringer/gamegrid.rb', line 127

def self.add_score(game_name, score, player_name: "anonymous")
  path = score_file_path(game_name)
  FileUtils.mkdir_p(File.dirname(path))
  File.open(path, "a") do |f|
    f.puts("#{score}\t#{player_name}\t#{Time.now.iso8601}")
  end
end

.load_scores(game_name, limit: 10) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/textbringer/gamegrid.rb', line 135

def self.load_scores(game_name, limit: 10)
  path = score_file_path(game_name)
  return [] unless File.exist?(path)
  lines = File.readlines(path, chomp: true)
  lines.map { |line|
    parts = line.split("\t")
    { score: parts[0].to_i, player: parts[1], time: parts[2] }
  }.sort_by { |h| -h[:score] }.first(limit)
end

.score_file_path(game_name) ⇒ Object

Score persistence



122
123
124
125
# File 'lib/textbringer/gamegrid.rb', line 122

def self.score_file_path(game_name)
  safe_name = File.basename(game_name).gsub(/[^A-Za-z0-9_\-]/, "_")
  File.expand_path("~/.textbringer/scores/#{safe_name}.scores")
end

Instance Method Details

#face_mapObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/textbringer/gamegrid.rb', line 66

def face_map
  highlight_on = {}
  highlight_off = {}
  offset = 0
  @height.times do |y|
    offset += @margin_left
    @width.times do |x|
      value = @grid[y][x]
      # Priority: explicit set_face > display_option face > nil
      face_name = @faces[y][x]
      if face_name.nil?
        opt = @display_options[value]
        face_name = opt[:face] if opt
      end
      if face_name
        face = Face[face_name]
        if face
          highlight_on[offset] = face
          char_len = cell_char(value).bytesize
          highlight_off[offset + char_len] = true
        end
      end
      offset += cell_char(value).bytesize
    end
    offset += 1  # newline
  end
  [highlight_on, highlight_off]
end

#fill(value) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/textbringer/gamegrid.rb', line 46

def fill(value)
  @height.times do |y|
    @width.times do |x|
      @grid[y][x] = value
      @faces[y][x] = nil
    end
  end
end

#get_cell(x, y) ⇒ Object



27
28
29
30
# File 'lib/textbringer/gamegrid.rb', line 27

def get_cell(x, y)
  check_bounds(x, y)
  @grid[y][x]
end

#get_face(x, y) ⇒ Object



37
38
39
40
# File 'lib/textbringer/gamegrid.rb', line 37

def get_face(x, y)
  check_bounds(x, y)
  @faces[y][x]
end

#renderObject

Rendering



57
58
59
60
61
62
63
64
# File 'lib/textbringer/gamegrid.rb', line 57

def render
  margin = " " * @margin_left
  @height.times.map { |y|
    margin + @width.times.map { |x|
      cell_char(@grid[y][x])
    }.join
  }.join("\n")
end

#set_cell(x, y, value) ⇒ Object

Cell API



22
23
24
25
# File 'lib/textbringer/gamegrid.rb', line 22

def set_cell(x, y, value)
  check_bounds(x, y)
  @grid[y][x] = value
end

#set_display_option(value, char:, face: nil) ⇒ Object



42
43
44
# File 'lib/textbringer/gamegrid.rb', line 42

def set_display_option(value, char:, face: nil)
  @display_options[value] = { char: char, face: face }
end

#set_face(x, y, face_name) ⇒ Object



32
33
34
35
# File 'lib/textbringer/gamegrid.rb', line 32

def set_face(x, y, face_name)
  check_bounds(x, y)
  @faces[y][x] = face_name
end

#start_timer(interval, &callback) ⇒ Object

Timer



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/textbringer/gamegrid.rb', line 97

def start_timer(interval, &callback)
  stop_timer
  @timer_thread = Thread.new do
    loop do
      sleep(interval)
      Controller.current.next_tick(&callback)
    rescue ThreadError
      break
    end
  end
end

#stop_timerObject



109
110
111
112
113
114
# File 'lib/textbringer/gamegrid.rb', line 109

def stop_timer
  if @timer_thread
    @timer_thread.kill
    @timer_thread = nil
  end
end

#timer_active?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/textbringer/gamegrid.rb', line 116

def timer_active?
  !@timer_thread.nil? && @timer_thread.alive?
end