minehunt 1.0.0

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -0
  3. data/bin/minehunt +114 -0
  4. data/lib/minehunt.rb +121 -0
  5. metadata +61 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 322e0063d5bfff9584242e7394d523f296b09fb63f8ad60eb4171bf7c140276d
4
+ data.tar.gz: 8474fcafea89310fe07dc776dc71243d68e16b805249a9f9111c988caba821d3
5
+ SHA512:
6
+ metadata.gz: 7c93386b2e102cd6df6f3330172e6a408141daeb885d77152ff3afe7581d5090a22d2c0d69c88c42c33d903c217658d98bee488f5954cd4b35579ddd87c2730f
7
+ data.tar.gz: 4fda1ac747d01670cc76f5aef87c64e88c2b8940d19d15b6002cb263a54ee83622ba30555def267ff42258fe97f355bbbf2f1064ce3251c03d533ffb7e9f2029
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Implementing HP {48,49,50} minehunt game
data/bin/minehunt ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'curses'
5
+
6
+ require 'minehunt'
7
+
8
+ def display_curses( field,
9
+ state = { dead: false, victory: false },
10
+ theme = { explorer: '()',
11
+ dead_explorer: '☠ ',
12
+ door: '=>',
13
+ mine: '<>',
14
+ cell: '██',
15
+ visited_cell: ' ' } )
16
+ Curses.setpos 0, 0
17
+
18
+ if state[:dead]
19
+ Curses.addstr "You died! :(, score #{field.score} "
20
+ elsif state[:victory]
21
+ Curses.addstr "You won!! :), score #{field.score} "
22
+ else
23
+ Curses.addstr "#{field.number_of_mines} mines, #{field.count_nearby_mines} nearby, score #{field.score}"
24
+ end
25
+
26
+ field.height.times do |y|
27
+ Curses.setpos y + 2, 0
28
+ field.width.times do |x|
29
+ if [field.explorer_x, field.explorer_y] == [x, y]
30
+ Curses.addstr state[:dead] ? theme[:dead_explorer] : theme[:explorer]
31
+ elsif [field.width, field.height] == [x + 1, y + 1]
32
+ Curses.addstr theme[:door]
33
+ elsif field.field[[x, y]].open
34
+ Curses.addstr theme[:visited_cell]
35
+ elsif field.field[[x, y]].mine && ( state[:dead] || state[:victory] )
36
+ Curses.addstr theme[:mine]
37
+ else
38
+ Curses.addstr theme[:cell]
39
+ end
40
+ end
41
+ end
42
+
43
+ Curses.refresh
44
+ end
45
+
46
+ def ncurses_main( number_of_mines )
47
+ field = MineHunt::Board.new( number_of_mines )
48
+ finished = false
49
+
50
+ Curses.init_screen
51
+ Curses.cbreak
52
+ Curses.noecho
53
+ Curses.stdscr.keypad = true
54
+
55
+ at_exit do
56
+ Curses.close_screen
57
+ end
58
+
59
+ display_curses( field )
60
+
61
+ loop do
62
+ direction = ''
63
+ ch = Curses.getch
64
+ if finished
65
+ begin
66
+ case ch
67
+ when 'r'
68
+ field = MineHunt::Board.new( number_of_mines )
69
+ finished = false
70
+ else
71
+ break
72
+ end
73
+ rescue Curses::RequestDeniedError
74
+ 'prout'
75
+ end
76
+ else
77
+ begin
78
+ case ch
79
+ when '1'
80
+ direction = 'down-left'
81
+ when '2', Curses::KEY_DOWN
82
+ direction = 'down'
83
+ when '3'
84
+ direction = 'down-right'
85
+ when '4', Curses::KEY_LEFT
86
+ direction = 'left'
87
+ when '6', Curses::KEY_RIGHT
88
+ direction = 'right'
89
+ when '7'
90
+ direction = 'up-left'
91
+ when '8', Curses::KEY_UP
92
+ direction = 'up'
93
+ when '9'
94
+ direction = 'up-right'
95
+ when 'q'
96
+ break
97
+ end
98
+ rescue Curses::RequestDeniedError
99
+ 'prout'
100
+ end
101
+ end
102
+
103
+ state = field.move( direction )
104
+ finished = state[:dead] || state[:victory]
105
+ display_curses( field, state )
106
+ end
107
+
108
+ exit!
109
+ end
110
+
111
+ number_of_mines = 20
112
+ number_of_mines = ARGV.first.to_i if ARGV.length == 1
113
+
114
+ ncurses_main( number_of_mines )
data/lib/minehunt.rb ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ module MineHunt
5
+ VERSION = '1.0.0'
6
+
7
+ class Cell
8
+ attr_accessor :mine,
9
+ :open
10
+
11
+ def initialize( mine: false, open: false )
12
+ @mine = mine
13
+ @open = open
14
+ end
15
+
16
+ def explore
17
+ @open = true
18
+
19
+ @mine
20
+ end
21
+ end
22
+
23
+ class Board
24
+ attr_reader :width,
25
+ :height,
26
+ :field,
27
+ :number_of_mines,
28
+ :explorer_x,
29
+ :explorer_y,
30
+ :score
31
+
32
+ def initialize( number_of_mines = 20, height = 8, width = 16 )
33
+ @height = height
34
+ @width = width
35
+ @explorer_x = 0
36
+ @explorer_y = 0
37
+ @score = 1
38
+ @field = {}
39
+ @number_of_mines = if number_of_mines.negative? && number_of_mines > ((@height * @width) - 2)
40
+ 20
41
+ else
42
+ number_of_mines
43
+ end
44
+
45
+ @width.times do |x|
46
+ @height.times do |y|
47
+ @field[[x, y]] = Cell.new( open: x.zero? && y.zero? )
48
+ end
49
+ end
50
+
51
+ placed_mines = 0
52
+ while placed_mines < @number_of_mines
53
+ coordinates = [rand( @width ), rand( @height )]
54
+ next if coordinates == [0, 0]
55
+ next if @field[ coordinates ].mine
56
+
57
+ @field[ coordinates ].mine = true
58
+ placed_mines += 1
59
+ end
60
+ end
61
+
62
+ def update_explorer_location( direction )
63
+ case direction
64
+ when 'up'
65
+ @explorer_y -= 1 if @explorer_y.positive?
66
+ when 'right'
67
+ @explorer_x += 1 if @explorer_x < (@width - 1)
68
+ when 'down'
69
+ @explorer_y += 1 if @explorer_y < (@height - 1)
70
+ when 'left'
71
+ @explorer_x -= 1 if @explorer_x.positive?
72
+ when 'up-right'
73
+ if @explorer_x < (@width - 1) && @explorer_y.positive?
74
+ @explorer_x += 1
75
+ @explorer_y -= 1
76
+ end
77
+ when 'down-right'
78
+ if @explorer_x < (@width - 1) && @explorer_y < (@height - 1)
79
+ @explorer_x += 1
80
+ @explorer_y += 1
81
+ end
82
+ when 'down-left'
83
+ if @explorer_x.positive? && @explorer_y < (@height - 1)
84
+ @explorer_x -= 1
85
+ @explorer_y += 1
86
+ end
87
+ when 'up-left'
88
+ if @explorer_x.positive? && @explorer_y.positive?
89
+ @explorer_x -= 1
90
+ @explorer_y -= 1
91
+ end
92
+ end
93
+ end
94
+
95
+ def move( direction )
96
+ update_explorer_location( direction )
97
+ @score += 1 unless @field[[@explorer_x, @explorer_y]].open
98
+
99
+ { dead: @field[[@explorer_x, @explorer_y]].explore,
100
+ victory: @explorer_x == (@width - 1) && @explorer_y == (@height - 1) }
101
+ end
102
+
103
+ def count_nearby_mines
104
+ counter = 0
105
+
106
+ [@explorer_x - 1, @explorer_x, @explorer_x + 1].each do |x|
107
+ [@explorer_y - 1, @explorer_y, @explorer_y + 1].each do |y|
108
+ next if x.negative?
109
+ next if y.negative?
110
+ next if x == @width
111
+ next if y == @height
112
+ next if x == @explorer_x && y == @explorer_y
113
+
114
+ counter += 1 if @field[[x, y]].mine
115
+ end
116
+ end
117
+
118
+ counter
119
+ end
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minehunt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Gwenhael Le Moine
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: curses
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.4
27
+ description: Mine hunting game inspired by the HP 48
28
+ email: gwenhael@le-moine.org
29
+ executables:
30
+ - minehunt
31
+ extensions: []
32
+ extra_rdoc_files:
33
+ - README.md
34
+ files:
35
+ - README.md
36
+ - bin/minehunt
37
+ - lib/minehunt.rb
38
+ homepage: https://src.le-moine.org/gwh/myhunt/src/branch/main/ruby
39
+ licenses:
40
+ - GPL-3.0
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">"
49
+ - !ruby/object:Gem::Version
50
+ version: '3'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.3.7
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Mine hunting game
61
+ test_files: []