minesweeprb 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16bc74524f23df3a1ab558f120560e152b2a1c7551379a6237eefac7cf48962b
4
- data.tar.gz: f879f2d59af8c486aa34114fcc77995a7a1951edeac59026d9c54ecbdeda09af
3
+ metadata.gz: d8570b88e453c2b2831d7b4d155ece9b35191aa989b38c3df409cde3258af522
4
+ data.tar.gz: b4d5c63637d268285cc2a0a08d9b3011b9ceed0aaeabfb36fb63004b90938f82
5
5
  SHA512:
6
- metadata.gz: 73cfcc1a3d6e6099f122eb340b567d7517d1853b7654d93ef00df9da1c08ba5ace35a36dbf54d8ec49651c9e5a97f3d09d7cec0255d9f910892aad26589400ec
7
- data.tar.gz: aae8f678ed0182f6d76cee2df5491c007a57b91ba1f45625e593a5ffc02d2b1e0d4eb96ea859f5d2b1107d78c1bbbbfe6f2cd4afffecd87a7f8e30cf539fb2ec
6
+ metadata.gz: 0250dbc2b118b525aad974cf1ab17001cff0484abdf4b2c49961d02e7f040a5f9dfdcb687473e3514f030899369ef650d61011cd68b9bf17c0ca0c36afa9ef7b
7
+ data.tar.gz: ecdb3eacfb7288c3f8383ac6936d782947c7c1fb06fcc57c80dba1e9b404508ff51526bebec7a793beee00e6d2e55e469354d3cae95cfebf5afce23c7727f990
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 2020-02-08 0.3.0
2
+
3
+ * Add mouse support
4
+
1
5
  ### 2020-02-08 0.2.0
2
6
 
3
7
  * Use curses for gameboard to reduce flickering
@@ -50,8 +50,8 @@ module Minesweeprb
50
50
  },
51
51
  ].freeze
52
52
 
53
- attr_reader :active_square,
54
- :flagged_squares,
53
+ attr_accessor :active_square
54
+ attr_reader :flagged_squares,
55
55
  :marked_squares,
56
56
  :mined_squares,
57
57
  :revealed_squares,
@@ -165,10 +165,10 @@ module Minesweeprb
165
165
  SPRITES[:mine]
166
166
  elsif flagged_squares.include?(pos)
167
167
  SPRITES[:flag]
168
- elsif marked_squares.include?(pos)
169
- SPRITES[:mark]
170
168
  elsif revealed_squares[pos]
171
169
  SPRITES[:clues][revealed_squares[pos]]
170
+ elsif marked_squares.include?(pos)
171
+ SPRITES[:mark]
172
172
  else
173
173
  SPRITES[:square]
174
174
  end
@@ -222,6 +222,7 @@ module Minesweeprb
222
222
  end
223
223
 
224
224
  def reveal_square(square)
225
+ return if over? || flagged_squares.include?(active_square)
225
226
  start_game if revealed_squares.empty?
226
227
  return if revealed_squares.keys.include?(square)
227
228
  return lose! if mined_squares.include?(square)
@@ -6,16 +6,18 @@ require_relative './game'
6
6
 
7
7
  module Minesweeprb
8
8
  class Gameboard
9
+ include Curses
10
+
9
11
  RESTART = ['r'].freeze
10
- REVEAL = [10, Curses::KEY_ENTER].freeze
12
+ REVEAL = [10, KEY_ENTER].freeze
11
13
  FLAG = ['f', ' '].freeze
12
14
  QUIT = ['q', 27].freeze
13
15
 
14
16
  MOVE = {
15
- Curses::KEY_UP => :up,
16
- Curses::KEY_DOWN => :down,
17
- Curses::KEY_LEFT => :left,
18
- Curses::KEY_RIGHT => :right,
17
+ KEY_UP => :up,
18
+ KEY_DOWN => :down,
19
+ KEY_LEFT => :left,
20
+ KEY_RIGHT => :right,
19
21
  'k' => :up,
20
22
  'j' => :down,
21
23
  'h' => :left,
@@ -23,38 +25,38 @@ module Minesweeprb
23
25
  }.freeze
24
26
 
25
27
  COLORS = {
26
- win: [Curses::A_BOLD | Curses::COLOR_GREEN],
27
- lose: [Curses::A_BOLD | Curses::COLOR_MAGENTA],
28
- Game::SPRITES[:clock] => [Curses::A_BOLD | Curses::COLOR_CYAN],
29
- Game::SPRITES[:win_face] => [Curses::A_BOLD | Curses::COLOR_YELLOW],
30
- Game::SPRITES[:lose_face] => [Curses::A_BOLD | Curses::COLOR_RED],
31
- Game::SPRITES[:play_face] => [Curses::A_BOLD | Curses::COLOR_CYAN],
32
-
33
- Game::SPRITES[:mine] => [Curses::A_BOLD | Curses::COLOR_RED],
34
- Game::SPRITES[:flag] => [Curses::A_BOLD | Curses::COLOR_RED],
35
- Game::SPRITES[:mark] => [Curses::A_BOLD | Curses::COLOR_MAGENTA],
36
- Game::SPRITES[:clues][0] => [Curses::COLOR_BLACK],
37
- Game::SPRITES[:clues][1] => [Curses::COLOR_BLUE],
38
- Game::SPRITES[:clues][2] => [Curses::COLOR_GREEN],
39
- Game::SPRITES[:clues][3] => [Curses::COLOR_MAGENTA],
40
- Game::SPRITES[:clues][4] => [Curses::COLOR_CYAN],
41
- Game::SPRITES[:clues][5] => [Curses::COLOR_RED],
42
- Game::SPRITES[:clues][6] => [Curses::COLOR_YELLOW],
43
- Game::SPRITES[:clues][7] => [Curses::A_BOLD | Curses::COLOR_MAGENTA],
44
- Game::SPRITES[:clues][8] => [Curses::A_BOLD | Curses::COLOR_RED],
28
+ win: [A_BOLD | COLOR_GREEN],
29
+ lose: [A_BOLD | COLOR_MAGENTA],
30
+ Game::SPRITES[:clock] => [A_BOLD | COLOR_CYAN],
31
+ Game::SPRITES[:win_face] => [A_BOLD | COLOR_YELLOW],
32
+ Game::SPRITES[:lose_face] => [A_BOLD | COLOR_RED],
33
+ Game::SPRITES[:play_face] => [A_BOLD | COLOR_CYAN],
34
+
35
+ Game::SPRITES[:mine] => [A_BOLD | COLOR_RED],
36
+ Game::SPRITES[:flag] => [A_BOLD | COLOR_RED],
37
+ Game::SPRITES[:mark] => [A_BOLD | COLOR_MAGENTA],
38
+ Game::SPRITES[:clues][0] => [COLOR_BLACK],
39
+ Game::SPRITES[:clues][1] => [COLOR_BLUE],
40
+ Game::SPRITES[:clues][2] => [COLOR_GREEN],
41
+ Game::SPRITES[:clues][3] => [COLOR_MAGENTA],
42
+ Game::SPRITES[:clues][4] => [COLOR_CYAN],
43
+ Game::SPRITES[:clues][5] => [COLOR_RED],
44
+ Game::SPRITES[:clues][6] => [COLOR_YELLOW],
45
+ Game::SPRITES[:clues][7] => [A_BOLD | COLOR_MAGENTA],
46
+ Game::SPRITES[:clues][8] => [A_BOLD | COLOR_RED],
45
47
  }.freeze
46
48
 
47
49
  COLOR_PAIRS = COLORS.keys.freeze
48
50
 
49
- attr_reader :game, :pastel, :window
51
+ attr_reader :game, :pastel, :window, :game_x, :game_y
50
52
 
51
53
  def initialize(size)
52
54
  @pastel = Pastel.new
53
55
  @game = Game.new(size)
54
56
  @timers = Timers::Group.new
55
57
  @game_timer = @timers.every(0.5) { paint }
56
- Thread.new { loop { @timers.wait } }
57
58
  setup_curses
59
+ Thread.new { loop { @timers.wait } }
58
60
  end
59
61
 
60
62
  def draw
@@ -63,28 +65,30 @@ module Minesweeprb
63
65
  end
64
66
 
65
67
  def clear
66
- Curses.close_screen
68
+ close_screen
67
69
  end
68
70
 
69
71
  private
70
72
 
71
73
  def setup_curses
72
- Curses.init_screen
73
- Curses.use_default_colors
74
- Curses.start_color
75
- Curses.curs_set(0)
76
- Curses.noecho
77
- Curses.ESCDELAY = 1;
78
- @window = Curses::Window.new(0, 0, 0, 0)
74
+ init_screen
75
+ use_default_colors
76
+ start_color
77
+ curs_set(0)
78
+ noecho
79
+ self.ESCDELAY = 1;
80
+ mousemask(BUTTON1_CLICKED|BUTTON2_CLICKED|BUTTON3_CLICKED|BUTTON4_CLICKED)
81
+ @window = Window.new(0, 0, 0, 0)
79
82
  @window.keypad(true)
80
83
  COLOR_PAIRS.each.with_index do |char, index|
81
84
  fg, bg = COLORS[char]
82
- Curses.init_pair(index + 1, fg, bg || -1)
85
+ init_pair(index + 1, fg, bg || -1)
83
86
  end
84
87
  end
85
88
 
86
89
  def process_input(key)
87
90
  case key
91
+ when KEY_MOUSE then process_mouse(getmouse)
88
92
  when *MOVE.keys then game.move(MOVE[key])
89
93
  when *REVEAL then game.reveal_active_square
90
94
  when *FLAG then game.cycle_flag
@@ -95,6 +99,25 @@ module Minesweeprb
95
99
  true
96
100
  end
97
101
 
102
+ def process_mouse(m)
103
+ top = game_y
104
+ left = game_x
105
+ bottom = game_y + game.height
106
+ right = game_x + game.width * 2 - 1
107
+ on_board = (top..bottom).include?(m.y) &&
108
+ (left..right).include?(m.x) &&
109
+ (m.x - game_x).even?
110
+
111
+ return if !on_board && !game.over?
112
+
113
+ game.active_square = [(m.x - game_x) / 2, m.y - game_y]
114
+
115
+ case m.bstate
116
+ when BUTTON1_CLICKED then game.reveal_active_square
117
+ when BUTTON2_CLICKED, (BUTTON_CTRL | BUTTON1_CLICKED) then game.cycle_flag
118
+ end
119
+ end
120
+
98
121
  def how_to_play
99
122
  instructions = []
100
123
  instructions << '(←↓↑→ or hjkl)Move' unless game.over?
@@ -111,27 +134,28 @@ module Minesweeprb
111
134
  game.header.center(window.maxx - 1).chars.each do |char|
112
135
  window.attron(color_for(char)) { window << char }
113
136
  end
114
- Curses.clrtoeol
137
+ clrtoeol
115
138
  window << "\n"
116
139
 
117
140
  # COLOR_PAIRS.each do |char|
118
141
  # window.attron(color_for(char)) { window << char }
119
142
  # end
120
- # Curses.clrtoeol
143
+ # clrtoeol
121
144
  # window << "\n"
122
145
 
123
146
  padding = (window.maxx - game.width * 2) / 2
124
147
  game.squares.each.with_index do |line, row|
125
148
  window << ' ' * padding
149
+ @game_x, @game_y = window.curx, window.cury if row.zero?
126
150
  line.each.with_index do |char, col|
127
151
  if game.active_square == [col, row]
128
- window.attron(color_for(char) | Curses::A_REVERSE) { window << char }
152
+ window.attron(color_for(char) | A_REVERSE) { window << char }
129
153
  else
130
154
  window.attron(color_for(char)) { window << char }
131
155
  end
132
156
  window << ' ' if col < line.length
133
157
  end
134
- Curses.clrtoeol
158
+ clrtoeol
135
159
  window << "\n"
136
160
  end
137
161
 
@@ -148,13 +172,13 @@ module Minesweeprb
148
172
  window.attron(char_color) { window << char }
149
173
  end
150
174
  end
151
- Curses.clrtoeol
175
+ clrtoeol
152
176
  window << "\n"
153
177
  end
154
178
 
155
179
  window << "\n"
156
180
  window << how_to_play.center(window.maxx - 1)
157
- Curses.clrtoeol
181
+ clrtoeol
158
182
  window << "\n"
159
183
 
160
184
  window.refresh
@@ -164,7 +188,7 @@ module Minesweeprb
164
188
  pair = COLOR_PAIRS.index(char)
165
189
 
166
190
  if pair
167
- Curses.color_pair(pair + 1)
191
+ color_pair(pair + 1)
168
192
  else
169
193
  0
170
194
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Minesweeprb
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minesweeprb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - scudco
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-08 00:00:00.000000000 Z
11
+ date: 2020-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: timers