minehunt 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|