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.
- checksums.yaml +7 -0
- data/README.md +1 -0
- data/bin/minehunt +114 -0
- data/lib/minehunt.rb +121 -0
- 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: []
|