minesweeprb 0.4.2 → 0.5.0.rc5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7b2455f9494e12c5bf2bddea4488d916173e411fc790bbc0b5efa468f896adb
4
- data.tar.gz: 89b78d2f8a6280c28823c62d9c1348c3fcb8e2c2e15f4d5323457e388f811e08
3
+ metadata.gz: c997529a9b88173318f8789784b99ac9c68440322dee81f00b3a8460e04d3fba
4
+ data.tar.gz: 7ad2f3640a581fc567dcc97a0e047f2daa6377bb1365001a4ff12f90c6b971fa
5
5
  SHA512:
6
- metadata.gz: 854a839d903dc70508fafd42e4ab173abd7c1b4cad9919489a856c793ab58ff5d09920cb8b87c359f28b7326f91d3ecefca21c32f1492a360d29c4a394d2d5fb
7
- data.tar.gz: 282f1b1ce362b13e2f8693f8add2c50fab969d08cf4f414111de4275acddc4e8c3d22cd60348327c2d9e04d5b85ee997d03e0cea7134971b8ec9da85f1dbb459
6
+ metadata.gz: fffeab53498e2992856ab00f96b91dc9e1d92821e8cfd7f6db763427e8d7767e282f1a9db7d0f9ffe86b87dab096282c21d4d1c758c47b60074c98787371fbf2
7
+ data.tar.gz: '08e7d4939717bbe1b904c59c7aa0f273b612506e6b0200372ef5aea3aa4fc76f6ce6fe9b0f705b345cbc74df76716fddf50fe30b7dbb5d7b8cee5e42b4430289'
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v5
15
+
16
+ - uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: "4.0"
19
+ bundler-cache: true
20
+
21
+ - name: Run tests
22
+ run: bundle exec rspec
23
+
24
+ lint:
25
+ runs-on: ubuntu-latest
26
+
27
+ steps:
28
+ - uses: actions/checkout@v5
29
+
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: "4.0"
33
+ bundler-cache: true
34
+
35
+ - name: Run rubocop
36
+ run: bundle exec rubocop
@@ -0,0 +1,47 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ release:
9
+ runs-on: ubuntu-latest
10
+
11
+ permissions:
12
+ contents: write
13
+ id-token: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v5
17
+
18
+ - uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: "4.0"
21
+ bundler-cache: true
22
+
23
+ - name: Verify version matches tag
24
+ run: |
25
+ tag="${GITHUB_REF#refs/tags/v}"
26
+ gem_version=$(ruby -r ./lib/minesweeprb/version -e "puts Minesweeprb::VERSION")
27
+ if [ "$tag" != "$gem_version" ]; then
28
+ echo "Tag v$tag does not match Minesweeprb::VERSION ($gem_version)"
29
+ exit 1
30
+ fi
31
+
32
+ - name: Run tests
33
+ run: bundle exec rake ci
34
+
35
+ - name: Build gem
36
+ run: gem build minesweeprb.gemspec
37
+
38
+ - name: Configure RubyGems trusted publisher
39
+ uses: rubygems/configure-rubygems-credentials@v1.0.0
40
+
41
+ - name: Push to RubyGems
42
+ run: gem push minesweeprb-*.gem
43
+
44
+ - name: Upload gem to GitHub release
45
+ run: gh release upload "${{ github.event.release.tag_name }}" minesweeprb-*.gem
46
+ env:
47
+ GH_TOKEN: ${{ github.token }}
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  .rspec_status
12
12
 
13
13
  *.gem
14
+ .claude/
data/.rubocop.yml CHANGED
@@ -1,13 +1,68 @@
1
- require: rubocop-rspec
1
+ plugins:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+ TargetRubyVersion: 4.0
2
8
 
3
9
  Style/Documentation:
4
10
  Enabled: false
5
11
 
6
- Metrics/BlockLength:
7
- ExcludedMethods: ['describe']
8
-
9
12
  Style/TrailingCommaInArrayLiteral:
10
13
  EnforcedStyleForMultiline: comma
11
14
 
12
15
  Style/TrailingCommaInHashLiteral:
13
16
  EnforcedStyleForMultiline: comma
17
+
18
+ # Game logic has inherently long methods
19
+ Metrics/MethodLength:
20
+ CountAsOne: ['array', 'hash']
21
+ Max: 25
22
+
23
+ Metrics/AbcSize:
24
+ Max: 55
25
+
26
+ Metrics/ClassLength:
27
+ Max: 250
28
+
29
+ Metrics/CyclomaticComplexity:
30
+ Max: 10
31
+
32
+ Metrics/PerceivedComplexity:
33
+ Max: 12
34
+
35
+ Layout/LineLength:
36
+ Max: 150
37
+
38
+ # clue_0..clue_8 naming is intentional
39
+ Naming/VariableNumber:
40
+ Enabled: false
41
+
42
+ # Short param names like x, y are idiomatic for grid code
43
+ Naming/MethodParameterName:
44
+ AllowedNames: ['x', 'y', 'w', 'h']
45
+
46
+ Naming/PredicateMethod:
47
+ Enabled: false
48
+
49
+ RSpec/MultipleExpectations:
50
+ Max: 5
51
+
52
+ RSpec/ExampleLength:
53
+ Max: 20
54
+
55
+ RSpec/AnyInstance:
56
+ Enabled: false
57
+
58
+ RSpec/VerifiedDoubles:
59
+ Enabled: false
60
+
61
+ RSpec/SpecFilePathFormat:
62
+ Enabled: false
63
+
64
+ RSpec/SubjectStub:
65
+ Enabled: false
66
+
67
+ RSpec/DescribeClass:
68
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 2026-03-09 0.5.0
2
+
3
+ * Get working on ruby 4
4
+
1
5
  ### 2020-02-11 0.4.2
2
6
 
3
7
  * Fix timer loop and make it actually sleep
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @scudco
data/Gemfile CHANGED
@@ -5,5 +5,9 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in minesweeprb.gemspec
6
6
  gemspec
7
7
 
8
- gem 'rake', '~> 12.0'
9
- gem 'rspec', '~> 3.0'
8
+ gem 'irb'
9
+ gem 'rake'
10
+ gem 'rspec'
11
+ gem 'rubocop', require: false
12
+ gem 'rubocop-rake', require: false
13
+ gem 'rubocop-rspec', require: false
data/Gemfile.lock CHANGED
@@ -1,136 +1,108 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- minesweeprb (0.4.0)
5
- curses (~> 1.3)
6
- tty (~> 0.10)
4
+ minesweeprb (0.5.0.rc5)
5
+ curses
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
10
9
  specs:
11
- curses (1.3.2)
12
- diff-lcs (1.3)
13
- equatable (0.6.1)
14
- kramdown (1.16.2)
15
- necromancer (0.5.1)
16
- pastel (0.7.3)
17
- equatable (~> 0.6)
18
- tty-color (~> 0.5)
19
- rake (12.3.3)
20
- rouge (3.15.0)
21
- rspec (3.9.0)
22
- rspec-core (~> 3.9.0)
23
- rspec-expectations (~> 3.9.0)
24
- rspec-mocks (~> 3.9.0)
25
- rspec-core (3.9.1)
26
- rspec-support (~> 3.9.1)
27
- rspec-expectations (3.9.0)
10
+ addressable (2.8.9)
11
+ public_suffix (>= 2.0.2, < 8.0)
12
+ ast (2.4.3)
13
+ bigdecimal (4.0.1)
14
+ curses (1.6.0)
15
+ date (3.5.1)
16
+ diff-lcs (1.6.2)
17
+ erb (6.0.2)
18
+ io-console (0.8.2)
19
+ irb (1.17.0)
20
+ pp (>= 0.6.0)
21
+ prism (>= 1.3.0)
22
+ rdoc (>= 4.0.0)
23
+ reline (>= 0.4.2)
24
+ json (2.19.1)
25
+ json-schema (6.2.0)
26
+ addressable (~> 2.8)
27
+ bigdecimal (>= 3.1, < 5)
28
+ language_server-protocol (3.17.0.5)
29
+ lint_roller (1.1.0)
30
+ mcp (0.8.0)
31
+ json-schema (>= 4.1)
32
+ parallel (1.27.0)
33
+ parser (3.3.10.2)
34
+ ast (~> 2.4.1)
35
+ racc
36
+ pp (0.6.3)
37
+ prettyprint
38
+ prettyprint (0.2.0)
39
+ prism (1.9.0)
40
+ psych (5.3.1)
41
+ date
42
+ stringio
43
+ public_suffix (7.0.5)
44
+ racc (1.8.1)
45
+ rainbow (3.1.1)
46
+ rake (13.3.1)
47
+ rdoc (7.2.0)
48
+ erb
49
+ psych (>= 4.0.0)
50
+ tsort
51
+ regexp_parser (2.11.3)
52
+ reline (0.6.3)
53
+ io-console (~> 0.5)
54
+ rspec (3.13.2)
55
+ rspec-core (~> 3.13.0)
56
+ rspec-expectations (~> 3.13.0)
57
+ rspec-mocks (~> 3.13.0)
58
+ rspec-core (3.13.6)
59
+ rspec-support (~> 3.13.0)
60
+ rspec-expectations (3.13.5)
28
61
  diff-lcs (>= 1.2.0, < 2.0)
29
- rspec-support (~> 3.9.0)
30
- rspec-mocks (3.9.1)
62
+ rspec-support (~> 3.13.0)
63
+ rspec-mocks (3.13.8)
31
64
  diff-lcs (>= 1.2.0, < 2.0)
32
- rspec-support (~> 3.9.0)
33
- rspec-support (3.9.2)
34
- strings (0.1.8)
35
- strings-ansi (~> 0.1)
36
- unicode-display_width (~> 1.5)
37
- unicode_utils (~> 1.4)
38
- strings-ansi (0.1.0)
39
- thor (0.20.3)
40
- tty (0.10.0)
41
- bundler (~> 1.16, < 2.0)
42
- equatable (~> 0.5)
43
- pastel (~> 0.7.2)
44
- thor (~> 0.20.0)
45
- tty-box (~> 0.4.1)
46
- tty-color (~> 0.5)
47
- tty-command (~> 0.9.0)
48
- tty-config (~> 0.3.2)
49
- tty-cursor (~> 0.7)
50
- tty-editor (~> 0.5)
51
- tty-file (~> 0.8.0)
52
- tty-font (~> 0.4.0)
53
- tty-logger (~> 0.2.0)
54
- tty-markdown (~> 0.6.0)
55
- tty-pager (~> 0.12)
56
- tty-pie (~> 0.3.0)
57
- tty-platform (~> 0.2)
58
- tty-progressbar (~> 0.17)
59
- tty-prompt (~> 0.19)
60
- tty-screen (~> 0.7)
61
- tty-spinner (~> 0.9)
62
- tty-table (~> 0.11.0)
63
- tty-tree (~> 0.3)
64
- tty-which (~> 0.4)
65
- tty-box (0.4.1)
66
- pastel (~> 0.7.2)
67
- strings (~> 0.1.6)
68
- tty-cursor (~> 0.7)
69
- tty-color (0.5.1)
70
- tty-command (0.9.0)
71
- pastel (~> 0.7.0)
72
- tty-config (0.3.2)
73
- tty-cursor (0.7.1)
74
- tty-editor (0.5.1)
75
- tty-prompt (~> 0.19)
76
- tty-which (~> 0.4)
77
- tty-file (0.8.0)
78
- diff-lcs (~> 1.3)
79
- pastel (~> 0.7.2)
80
- tty-prompt (~> 0.18)
81
- tty-font (0.4.0)
82
- tty-logger (0.2.0)
83
- pastel (~> 0.7.0)
84
- tty-markdown (0.6.0)
85
- kramdown (~> 1.16.2)
86
- pastel (~> 0.7.2)
87
- rouge (~> 3.3)
88
- strings (~> 0.1.4)
89
- tty-color (~> 0.4)
90
- tty-screen (~> 0.6)
91
- tty-pager (0.12.1)
92
- strings (~> 0.1.4)
93
- tty-screen (~> 0.6)
94
- tty-which (~> 0.4)
95
- tty-pie (0.3.0)
96
- pastel (~> 0.7.3)
97
- tty-cursor (~> 0.7)
98
- tty-platform (0.3.0)
99
- tty-progressbar (0.17.0)
100
- strings-ansi (~> 0.1.0)
101
- tty-cursor (~> 0.7)
102
- tty-screen (~> 0.7)
103
- unicode-display_width (~> 1.6)
104
- tty-prompt (0.20.0)
105
- necromancer (~> 0.5.0)
106
- pastel (~> 0.7.0)
107
- tty-reader (~> 0.7.0)
108
- tty-reader (0.7.0)
109
- tty-cursor (~> 0.7)
110
- tty-screen (~> 0.7)
111
- wisper (~> 2.0.0)
112
- tty-screen (0.7.1)
113
- tty-spinner (0.9.3)
114
- tty-cursor (~> 0.7)
115
- tty-table (0.11.0)
116
- equatable (~> 0.6)
117
- necromancer (~> 0.5)
118
- pastel (~> 0.7.2)
119
- strings (~> 0.1.5)
120
- tty-screen (~> 0.7)
121
- tty-tree (0.4.0)
122
- tty-which (0.4.2)
123
- unicode-display_width (1.6.1)
124
- unicode_utils (1.4.0)
125
- wisper (2.0.1)
65
+ rspec-support (~> 3.13.0)
66
+ rspec-support (3.13.7)
67
+ rubocop (1.85.1)
68
+ json (~> 2.3)
69
+ language_server-protocol (~> 3.17.0.2)
70
+ lint_roller (~> 1.1.0)
71
+ mcp (~> 0.6)
72
+ parallel (~> 1.10)
73
+ parser (>= 3.3.0.2)
74
+ rainbow (>= 2.2.2, < 4.0)
75
+ regexp_parser (>= 2.9.3, < 3.0)
76
+ rubocop-ast (>= 1.49.0, < 2.0)
77
+ ruby-progressbar (~> 1.7)
78
+ unicode-display_width (>= 2.4.0, < 4.0)
79
+ rubocop-ast (1.49.1)
80
+ parser (>= 3.3.7.2)
81
+ prism (~> 1.7)
82
+ rubocop-rake (0.7.1)
83
+ lint_roller (~> 1.1)
84
+ rubocop (>= 1.72.1)
85
+ rubocop-rspec (3.9.0)
86
+ lint_roller (~> 1.1)
87
+ rubocop (~> 1.81)
88
+ ruby-progressbar (1.13.0)
89
+ stringio (3.2.0)
90
+ tsort (0.2.0)
91
+ unicode-display_width (3.2.0)
92
+ unicode-emoji (~> 4.1)
93
+ unicode-emoji (4.2.0)
126
94
 
127
95
  PLATFORMS
128
96
  ruby
129
97
 
130
98
  DEPENDENCIES
99
+ irb
131
100
  minesweeprb!
132
- rake (~> 12.0)
133
- rspec (~> 3.0)
101
+ rake
102
+ rspec
103
+ rubocop
104
+ rubocop-rake
105
+ rubocop-rspec
134
106
 
135
107
  BUNDLED WITH
136
- 1.17.3
108
+ 4.0.7
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  Use clues on the gameboard to deduce locations of mines. Correctly reveal all non-mine squares to win.
4
4
 
5
- ## Demo
6
5
  <p align="center">
7
6
  <a href="https://i.imgur.com/9VpbRzV.mp4"><img src="https://i.imgur.com/9VpbRzV.jpg?fbplay" width="390"/></a>
8
7
  </p>
data/Rakefile CHANGED
@@ -5,4 +5,31 @@ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ require 'rubocop/rake_task'
9
+ RuboCop::RakeTask.new
10
+
8
11
  task default: :spec
12
+ task ci: %w[spec rubocop]
13
+
14
+ desc 'Release a new version (e.g., rake release_gem[0.5.0])'
15
+ task :release_gem, [:version] do |_t, args|
16
+ version = args[:version]
17
+ abort 'Usage: rake release_gem[VERSION]' unless version
18
+
19
+ version_file = 'lib/minesweeprb/version.rb'
20
+ content = File.read(version_file)
21
+ new_content = content.sub(/VERSION = '.*'/, "VERSION = '#{version}'")
22
+ abort 'VERSION not found in version.rb' if content == new_content
23
+
24
+ File.write(version_file, new_content)
25
+ sh 'bundle install'
26
+ sh "git add #{version_file} Gemfile.lock"
27
+ sh "git commit -m 'Bump version to #{version}'"
28
+ sh "git tag v#{version}"
29
+ sh 'git push --tags'
30
+ sh 'git push'
31
+
32
+ prerelease = version.match?(/[a-zA-Z]/)
33
+ flags = prerelease ? '--prerelease' : ''
34
+ sh "gh release create v#{version} --title 'v#{version}' --generate-notes #{flags}"
35
+ end
@@ -1,35 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'thor'
3
+ require 'optparse'
4
4
 
5
5
  module Minesweeprb
6
- # Handle the application command line parsing
7
- # and the dispatch to various command objects
8
- #
9
- # @api public
10
- class CLI < Thor
11
- # Error raised by this runner
12
- Error = Class.new(StandardError)
13
-
14
- default_command 'play'
15
-
16
- desc 'version', 'minesweeprb version'
17
- def version
18
- require_relative 'version'
19
- puts "v#{Minesweeprb::VERSION}"
6
+ class CLI
7
+ class Error < StandardError
20
8
  end
21
- map %w[--version -v] => :version
22
-
23
- desc 'play', 'Play Minesweeper'
24
- method_option :help, aliases: '-h', type: :boolean,
25
- desc: 'Display usage information'
26
- def play(*)
27
- if options[:help]
28
- invoke :help, ['play']
29
- else
30
- require_relative 'commands/play'
31
- Minesweeprb::Commands::Play.new(options).execute
9
+
10
+ def self.start(argv = ARGV)
11
+ options = {}
12
+
13
+ parser = OptionParser.new do |opts|
14
+ opts.banner = 'Usage: minesweeprb [options]'
15
+
16
+ opts.on('-v', '--version', 'Print version') do
17
+ require_relative 'version'
18
+ puts "v#{Minesweeprb::VERSION}"
19
+ exit
20
+ end
21
+
22
+ opts.on('-t', '--theme NAME', 'Theme (classic, modern)') do |name|
23
+ options[:theme] = name
24
+ end
25
+
26
+ opts.on('-h', '--help', 'Show this help') do
27
+ puts opts
28
+ exit
29
+ end
32
30
  end
31
+
32
+ parser.parse!(argv)
33
+
34
+ require_relative 'commands/play'
35
+ Commands::Play.new(options).execute
33
36
  end
34
37
  end
35
38
  end
@@ -1,99 +1,72 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'tty-screen'
4
-
5
- require_relative '../command'
3
+ require 'io/console'
4
+ require 'curses'
6
5
  require_relative '../../minesweeprb'
6
+ require_relative '../menu'
7
+ require_relative '../theme'
7
8
 
8
9
  module Minesweeprb
9
10
  module Commands
10
- class Play < Minesweeprb::Command
11
+ class Play
12
+ include Curses
13
+
11
14
  SIZES = [
12
15
  # [ label, width, height, # of mines ]
13
- ['Tiny', 5, 5, 3],
16
+ ['Tiny', 5, 5, 3],
14
17
  ['Small', 9, 9, 10],
15
18
  ['Medium', 13, 13, 15],
16
19
  ['Large', 17, 17, 20],
17
20
  ['Huge', 21, 21, 25],
18
- ].map { |options| GameTemplate.new(*options) }.freeze
21
+ ].map { |label, width, height, mines| GameTemplate.new(label:, width:, height:, mines:) }.freeze
19
22
 
20
23
  def initialize(options)
21
24
  @options = options
25
+ @theme = @options[:theme] ? Theme[@options[:theme]] : Theme.default
22
26
  end
23
27
 
24
- def execute(input: $stdin, output: $stdout)
25
- template = prompt_size(output)
26
- template = prompt_custom(output) if template == :custom
28
+ def execute
29
+ init_screen
30
+ use_default_colors
31
+ start_color
32
+ curs_set(0)
33
+ noecho
34
+ self.ESCDELAY = 1
35
+ mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED | BUTTON4_CLICKED)
27
36
 
28
- game = Game.new(**template.to_h)
29
- gameboard = Gameboard.new(game)
30
- begin
31
- gameboard.draw
32
- ensure
33
- gameboard.clear
37
+ loop do
38
+ template = prompt_size
39
+ break if template.nil?
40
+
41
+ game = Game.new(**template.to_h, sprites: @theme.sprites)
42
+ Gameboard.new(game, theme: @theme).draw
34
43
  end
44
+ ensure
45
+ close_screen
35
46
  end
36
47
 
48
+ # Gameboard chrome: 1 top margin + 1 header + 1 gap + grid + 1 gap + 1 status + 1 gap + 1 instructions
49
+ BOARD_CHROME_ROWS = 7
50
+
37
51
  private
38
52
 
39
- def prompt_size(output)
40
- options = SIZES.map do |option|
41
- too_big = option.height > TTY::Screen.height || option.width * 2 - 1 > TTY::Screen.width
42
- disabled = '(screen too small)' if too_big
53
+ def prompt_size
54
+ screen_rows, screen_cols = IO.console.winsize
55
+
56
+ options = SIZES.map do |tmpl|
57
+ too_tall = tmpl.height + BOARD_CHROME_ROWS > screen_rows
58
+ too_wide = (tmpl.width * 2) - 1 > screen_cols
59
+ disabled = '(screen too small)' if too_tall || too_wide
43
60
  {
44
61
  disabled: disabled,
45
- name: option.label,
46
- value: option,
62
+ name: tmpl.label,
63
+ value: tmpl,
47
64
  }
48
65
  end
49
66
 
50
- options << {
51
- name: 'Custom',
52
- value: :custom
53
- }
54
-
55
- prompt(interrupt: -> { exit 1 }).select('Size:', options, cycle: true)
56
- end
57
-
58
- def prompt_custom(output)
59
- min_width = 1
60
- max_width = TTY::Screen.width / 2 - 1
61
- width = prompt.ask("Width (#{min_width}-#{max_width})") do |q|
62
- q.required true
63
- q.convert :int
64
- q.validate do |val|
65
- val =~ /\d+/ && (min_width..max_width).include?(val.to_i)
66
- end
67
- end
68
-
69
- min_height = width == 1 ? 2 : 1
70
- max_height = TTY::Screen.height - 10 # leave room for interface
71
- height = prompt.ask("Height (#{min_height}-#{max_height})") do |q|
72
- q.required true
73
- q.convert :int
74
- q.validate do |val|
75
- val =~ /\d+/ && (min_height..max_height).include?(val.to_i)
76
- end
77
- end
78
-
79
- min_mines = 1
80
- max_mines = width * height - 1
81
- mines = prompt.ask("Mines (#{min_mines}-#{max_mines})") do |q|
82
- q.required true
83
- q.convert :int
84
- q.validate do |val|
85
- val =~ /\d+/ && (min_mines..max_mines).include?(val.to_i)
86
- end
87
- end
88
-
89
- GameTemplate.new('Custom', width, height, mines)
90
- end
67
+ options << { name: 'Quit', value: nil }
91
68
 
92
- def clear_output(output)
93
- output.print cursor.hide
94
- output.print cursor.up(1)
95
- output.print cursor.clear_screen_down
96
- output.puts
69
+ Menu.select('Choose a size:', options)
97
70
  end
98
71
  end
99
72
  end