Class: Minehunter::Game

Inherits:
Object
  • Object
show all
Defined in:
lib/minehunter/game.rb

Overview

Responsible for playing mine hunting game

Constant Summary collapse

EXIT_KEYS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The keys to exit game

[?\C-x, "q", "\e"].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input: $stdin, output: $stdout, env: {}, width: nil, height: nil, mines_limit: nil, screen_width: nil, screen_height: nil, decorator: DEFAULT_DECORATOR, randomiser: DEFAULT_RANDOMISER) ⇒ Game

Create a Game instance



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/minehunter/game.rb', line 49

def initialize(input: $stdin, output: $stdout, env: {},
               width: nil, height: nil, mines_limit: nil,
               screen_width: nil, screen_height: nil,
               decorator: DEFAULT_DECORATOR, randomiser: DEFAULT_RANDOMISER)
  @output = output
  @width = width
  @top = (screen_height - height - 4) / 2
  @left = (screen_width - width - 4) / 2
  @pos_x = (width - 1) / 2
  @pos_y = (height - 1) / 2
  @decorator = decorator
  @randomiser = randomiser
  @box = TTY::Box
  @cursor = TTY::Cursor
  @reader = TTY::Reader.new(input: input, output: output, env: env,
                            interrupt: :exit)
  @grid = Grid.new(width: width, height: height, mines_limit: mines_limit)
  @intro = Intro
  @intro_top = (screen_height - @intro.height - 2) / 2
  @intro_left = (screen_width - @intro.width - 4) / 2

  reset
end

Instance Attribute Details

#cursorObject (readonly)

The terminal cursor clearing and positioning



23
24
25
# File 'lib/minehunter/game.rb', line 23

def cursor
  @cursor
end

Instance Method Details

#finished?Boolean

Check whether or not the game is finished



90
91
92
# File 'lib/minehunter/game.rb', line 90

def finished?
  @lost || @grid.cleared?
end

#flagObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Place a flag



205
206
207
208
209
# File 'lib/minehunter/game.rb', line 205

def flag
  return if finished?

  @grid.flag(@curr_x, @curr_y) unless finished?
end

#keyctrl_xObject Also known as: keyescape

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Quit game



214
215
216
217
218
# File 'lib/minehunter/game.rb', line 214

def keyctrl_x(*)
  @output.print cursor.clear_screen
  @output.print cursor.move_to(0, 0)
  @stop = true
end

#keydownObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Move cursor down



248
249
250
251
252
# File 'lib/minehunter/game.rb', line 248

def keydown(*)
  return if finished?

  @curr_y = @grid.move_down(@curr_y)
end

#keyleftObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Move cursor left



257
258
259
260
261
# File 'lib/minehunter/game.rb', line 257

def keyleft(*)
  return if finished?

  @curr_x = @grid.move_left(@curr_x)
end

#keypress(event) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Control game movement and actions



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/minehunter/game.rb', line 190

def keypress(event)
  case event.value.to_sym
  when :h, :a then keyleft
  when :l, :d then keyright
  when :j, :s then keydown
  when :k, :w then keyup
  when :f, :g then flag
  when :r then reset
  when :q then keyctrl_x
  end
end

#keyrightObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Move cursor right



266
267
268
269
270
# File 'lib/minehunter/game.rb', line 266

def keyright(*)
  return if finished?

  @curr_x = @grid.move_right(@curr_x)
end

#keyspaceObject Also known as: keyenter, keyreturn

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Uncover a field



224
225
226
227
228
229
230
231
232
# File 'lib/minehunter/game.rb', line 224

def keyspace(*)
  return if @grid.flag?(@curr_x, @curr_y)

  if @first_uncover
    @grid.fill_with_mines(@curr_x, @curr_y, randomiser: @randomiser)
    @first_uncover = false
  end
  @lost = @grid.uncover(@curr_x, @curr_y)
end

#keyupObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Move cursor up



239
240
241
242
243
# File 'lib/minehunter/game.rb', line 239

def keyup(*)
  return if finished?

  @curr_y = @grid.move_up(@curr_y)
end

#render_gridObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Render grid with current position marker



180
181
182
# File 'lib/minehunter/game.rb', line 180

def render_grid
  @grid.render(@curr_x, @curr_y, decorator: @decorator)
end

#render_grid_boxString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Render box with grid



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/minehunter/game.rb', line 149

def render_grid_box
  @box.frame(
    render_grid,
    top: @top + 2,
    left: @left,
    padding: [0, 1],
    border: {
      top_left: :divider_right,
      top_right: :divider_left
    }
  )
end

#render_intro_boxString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Render box with intro



118
119
120
121
122
123
124
125
# File 'lib/minehunter/game.rb', line 118

def render_intro_box
  @box.frame(
    @intro.render,
    top: @intro_top,
    left: @intro_left,
    padding: [0, 1]
  )
end

#render_status_boxString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Render box with status message



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/minehunter/game.rb', line 132

def render_status_box
  @box.frame(
    status,
    top: @top,
    left: @left,
    width: @width + 4,
    padding: [0, 1],
    border: {bottom: false},
    align: :center
  )
end

#resetObject

Reset game



76
77
78
79
80
81
82
83
# File 'lib/minehunter/game.rb', line 76

def reset
  @curr_x = @pos_x
  @curr_y = @pos_y
  @first_uncover = true
  @lost = false
  @stop = false
  @grid.reset
end

#runObject

Start the game



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/minehunter/game.rb', line 97

def run
  @output.print cursor.hide + cursor.clear_screen + render_intro_box
  pressed_key = @reader.read_keypress
  keyctrl_x if EXIT_KEYS.include?(pressed_key)

  @output.print cursor.clear_screen
  @reader.subscribe(self)

  until @stop
    @output.print render_status_box + render_grid_box
    @reader.read_keypress
  end
ensure
  @output.print cursor.show
end

#statusString

Status message



167
168
169
170
171
172
173
174
175
# File 'lib/minehunter/game.rb', line 167

def status
  if @lost
    "GAME OVER"
  elsif @grid.cleared?
    "YOU WIN"
  else
    "Flags #{@grid.flags_remaining}"
  end
end