Class: GamesAndRpgParadise::Minesweeper::Terminal::Game

Inherits:
Object
  • Object
show all
Defined in:
lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb

Overview

GamesAndRpgParadise::Minesweeper::Terminal::Game

Constant Summary collapse

EXIT_KEYS =
#

EXIT_KEYS

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: GamesAndRpgParadise::Minesweeper::Terminal::DEFAULT_DECORATOR, randomiser: GamesAndRpgParadise::Minesweeper::Terminal::DEFAULT_RANDOMISER) ⇒ Game

#

Create a Game instance

#

Parameters:

  • input (IO) (defaults to: $stdin)

    the input stream, defaults to stdin

  • output (IO) (defaults to: $stdout)

    the output stream, defaults to stdout

  • env (Hash) (defaults to: {})

    the environment variables

  • width (Integer) (defaults to: nil)

    the number of columns

  • height (Integer) (defaults to: nil)

    the number of rows

  • mines_limit (Integer) (defaults to: nil)

    the total number of mines

  • screen_width (Integer) (defaults to: nil)

    the terminal screen width

  • screen_height (Integer) (defaults to: nil)

    the terminal screen height

  • decorator (Pastel) (defaults to: GamesAndRpgParadise::Minesweeper::Terminal::DEFAULT_DECORATOR)

    the decorator for styling

  • randomiser (Proc) (defaults to: GamesAndRpgParadise::Minesweeper::Terminal::DEFAULT_RANDOMISER)

    the random number generator



63
64
65
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
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 63

def initialize(input:         $stdin,
               output:        $stdout,
               env:           {},
               width:         nil,
               height:        nil,
               mines_limit:   nil,
               screen_width:  nil,
               screen_height: nil,
               decorator:     GamesAndRpgParadise::Minesweeper::Terminal::DEFAULT_DECORATOR,
               randomiser:    GamesAndRpgParadise::Minesweeper::Terminal::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
  @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.

#


37
38
39
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 37

def cursor
  @cursor
end

Instance Method Details

#finished?Boolean

#

finished?

Check whether or not the game is finished

#

Returns:

  • (Boolean)


114
115
116
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 114

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

#flagObject

#

flag

Place a flag.

#


246
247
248
249
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 246

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.

#

keyctrl_x

Quit game

#


258
259
260
261
262
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 258

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.

#

keydown

Move cursor down

#


300
301
302
303
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 300

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.

#

keyleft

Move cursor left

#


312
313
314
315
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 312

def keyleft(*)
  return if finished?
  @curr_x = @grid.move_left(@curr_x)
end

#keypress(event) ⇒ Object

#

keypress

Control game movement and actions

#

Parameters:

  • event (TTY::Reader::KeyEvent)

    the keypress event



229
230
231
232
233
234
235
236
237
238
239
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 229

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.

#

keyright

Move cursor right

#


324
325
326
327
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 324

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.

#

keyspace

Uncover a field.

#


271
272
273
274
275
276
277
278
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 271

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.

#

keyup

Move cursor up

#


288
289
290
291
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 288

def keyup(*)
  return if finished?
 @curr_y = @grid.move_up(@curr_y)
end

#render_gridObject

#

render_grid

Render grid with current position marker

#


217
218
219
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 217

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

#render_grid_boxString

#

render_grid_box

Render box with grid

#

Returns:



180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 180

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

#

render_intro_box

Render box with intro.

#

Returns:



144
145
146
147
148
149
150
151
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 144

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

#render_status_boxString

#

render_status_box

Render box with status message.

#

Returns:



160
161
162
163
164
165
166
167
168
169
170
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 160

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

Reset game

#


97
98
99
100
101
102
103
104
105
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 97

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

#runObject

#

run

Start the game.

#


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 123

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

Status message

#

Returns:



202
203
204
205
206
207
208
209
210
# File 'lib/games_and_rpg_paradise/games/minesweeper/terminal/game.rb', line 202

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