good_luck_wizard 0.0.3 → 0.0.4
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 +4 -4
- data/Gemfile +2 -0
- data/README.md +13 -19
- data/Rakefile +1 -1
- data/bin/release +65 -0
- data/exe/glw +8 -1
- data/good_luck_wizard.gemspec +2 -1
- data/lib/glw/buffer_state.rb +15 -0
- data/lib/glw/input.rb +96 -0
- data/lib/glw/screen.rb +103 -0
- data/lib/glw/screen_cell.rb +7 -0
- data/lib/glw/terminal.rb +31 -0
- data/lib/glw/version.rb +1 -1
- data/lib/glw.rb +18 -20
- data/test_input.rb +21 -0
- metadata +30 -13
- data/lib/glw/game.rb +0 -31
- data/lib/glw/map.rb +0 -71
- data/lib/glw/term.rb +0 -72
- data/lib/glw/term_colors.rb +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4542c554b53395dec06ab3026510aa4ad8b24511077f0820e607daa8a48eeb57
|
|
4
|
+
data.tar.gz: 6991409bd222f25a008b86716cda64f1cb06928637882ade5676e5114a126c5c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: acd95d8a41e16661a57ec519052d91ff93747478ba29d8b4882e1e1c7207297427df4af973f55bed324af70758aca83a078cc81f27e16939c27d334ff8212e2f
|
|
7
|
+
data.tar.gz: 5f56f58dc3a2074ab355f2694ae40356f10d5623b1f8186790c75cfbba5dd78e075017bd55d77b37bb324e027b67d624d703041d9904aee952ea6442cb4da0b1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
|
-
**
|
|
2
|
-
_extremely_ unfinished game.
|
|
3
|
-
should come back later when there's something worth playing.
|
|
1
|
+
**good luck, wizard**. you're going to need it. not least of all because this is
|
|
2
|
+
an _extremely_ unfinished game. not really a game at all, yet. come back later.
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
good_luck_wizard` and run it with `glw`.
|
|
4
|
+
if you absolutely must try it, you can install it with `gem install
|
|
5
|
+
good_luck_wizard` and run it with `glw`. this assumes you have a working Ruby
|
|
7
6
|
environment and a new enough version of Ruby.
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
this project is not seeking contributions, but bug reports are accepted [on
|
|
10
9
|
GitHub](https://github.com/jarednorman/good_luck_wizard).
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
this project is intended to be a safe, welcoming space for collaboration. yes,
|
|
12
|
+
even though i don't want you to contribute, i will still ensure you aren't
|
|
13
|
+
descriminated against if you try. everyone interacting in the _good luck,
|
|
14
|
+
wizard_ project’s codebases, issue trackers, chat rooms and mailing lists is
|
|
15
|
+
expected to follow the [code of
|
|
15
16
|
conduct](https://github.com/jarednorman/good_luck_wizard/blob/master/CODE_OF_CONDUCT.md).
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
install dependencies. The tests are run with `bundle exec rspec`. You can also
|
|
21
|
-
run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
22
|
-
|
|
23
|
-
To release a new version, update the version number in `version.rb`, and then
|
|
24
|
-
run `bundle exec rake release`, which will create a git tag for the version,
|
|
25
|
-
push git commits and tags, and push the `.gem` file to
|
|
26
|
-
[rubygems.org](https://rubygems.org).
|
|
18
|
+
to run the project locally: check out the repo and run `bin/setup` to install
|
|
19
|
+
dependencies. the tests are run with `bundle exec rspec`. you can also run
|
|
20
|
+
`bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
data/bin/release
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "date"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
# Parse version argument
|
|
8
|
+
if ARGV.empty?
|
|
9
|
+
puts "Usage: bin/release VERSION"
|
|
10
|
+
puts "Example: bin/release 1.2.3"
|
|
11
|
+
exit 1
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
version = ARGV[0]
|
|
15
|
+
unless version.match?(/^\d+\.\d+\.\d+$/)
|
|
16
|
+
puts "Error: Version must be in format X.Y.Z (e.g., 1.2.3)"
|
|
17
|
+
exit 1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
puts "Releasing version #{version}..."
|
|
21
|
+
|
|
22
|
+
# 1. Update lib/glw/version.rb
|
|
23
|
+
version_file = "lib/glw/version.rb"
|
|
24
|
+
version_content = File.read(version_file)
|
|
25
|
+
updated_version_content = version_content.gsub(
|
|
26
|
+
/VERSION = "[^"]+"/,
|
|
27
|
+
%(VERSION = "#{version}")
|
|
28
|
+
)
|
|
29
|
+
File.write(version_file, updated_version_content)
|
|
30
|
+
puts "✓ Updated #{version_file}"
|
|
31
|
+
|
|
32
|
+
# 4. Commit changes
|
|
33
|
+
commit_message = "v#{version}"
|
|
34
|
+
system("jj", "commit", "-m", commit_message) || exit(1)
|
|
35
|
+
puts "✓ Committed changes with message '#{commit_message}'"
|
|
36
|
+
|
|
37
|
+
# 5. Move main branch to the change we just made
|
|
38
|
+
system("jj", "bookmark", "set", "main", "-r", "@-") || exit(1)
|
|
39
|
+
puts "✓ Moved main branch to release commit"
|
|
40
|
+
|
|
41
|
+
# 6. Tag the version
|
|
42
|
+
tag_name = "v#{version}"
|
|
43
|
+
tag_message = "Version #{version}"
|
|
44
|
+
system("git", "tag", "-m", tag_message, tag_name) || exit(1)
|
|
45
|
+
puts "✓ Created tag #{tag_name}"
|
|
46
|
+
|
|
47
|
+
# 7. Push changes and tags
|
|
48
|
+
system("jj", "git", "push", "-b", "main") || exit(1)
|
|
49
|
+
puts "✓ Pushed main branch"
|
|
50
|
+
|
|
51
|
+
system("git", "push", "--tags") || exit(1)
|
|
52
|
+
puts "✓ Pushed tags"
|
|
53
|
+
|
|
54
|
+
# 8. Build and push gem
|
|
55
|
+
gem_file = "good_luck_wizard-#{version}.gem"
|
|
56
|
+
system("gem", "build", "good_luck_wizard.gemspec") || exit(1)
|
|
57
|
+
puts "✓ Built gem"
|
|
58
|
+
|
|
59
|
+
system("gem", "push", gem_file) || exit(1)
|
|
60
|
+
puts "✓ Pushed gem"
|
|
61
|
+
|
|
62
|
+
system("rm", gem_file)
|
|
63
|
+
puts "✓ Cleaned up gem file"
|
|
64
|
+
|
|
65
|
+
puts "\n🎉 Successfully released version #{version}!"
|
data/exe/glw
CHANGED
data/good_luck_wizard.gemspec
CHANGED
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
|
|
25
25
|
spec.required_ruby_version = ">= 3.4.0"
|
|
26
26
|
|
|
27
|
-
spec.add_dependency "curses", "~> 1.4.0"
|
|
28
27
|
spec.add_dependency "zeitwerk", "~> 2.4"
|
|
28
|
+
spec.add_dependency "concurrent-ruby"
|
|
29
|
+
spec.add_dependency "concurrent-ruby-edge", "~> 0.7"
|
|
29
30
|
end
|
data/lib/glw/input.rb
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GLW
|
|
4
|
+
module Input
|
|
5
|
+
class << self
|
|
6
|
+
ESCAPE_TIMEOUT = 0.02 # 20ms
|
|
7
|
+
|
|
8
|
+
BYTES = {
|
|
9
|
+
"\t" => :k_tab,
|
|
10
|
+
"\r" => :k_enter,
|
|
11
|
+
"\n" => :k_enter,
|
|
12
|
+
"\x7F" => :k_backspace,
|
|
13
|
+
"\b" => :k_backspace,
|
|
14
|
+
" " => :k_space,
|
|
15
|
+
"\x03" => :k_ctrl_c,
|
|
16
|
+
"[" => :k_left_bracket,
|
|
17
|
+
"]" => :k_right_bracket,
|
|
18
|
+
";" => :k_semicolon,
|
|
19
|
+
"'" => :k_single_quote,
|
|
20
|
+
"," => :k_comma,
|
|
21
|
+
"." => :k_period
|
|
22
|
+
}.tap do |h|
|
|
23
|
+
("a".."z").each { |c| h[c] = :"k_#{c}" }
|
|
24
|
+
("A".."Z").each { |c| h[c] = :"k_#{c}" }
|
|
25
|
+
("0".."9").each { |c| h[c] = :"k_#{c}" }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def pop
|
|
29
|
+
@queue.pop
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def start!
|
|
33
|
+
return if @queue
|
|
34
|
+
|
|
35
|
+
@queue = Thread::Queue.new
|
|
36
|
+
|
|
37
|
+
Thread.new do
|
|
38
|
+
loop do
|
|
39
|
+
byte = read_byte
|
|
40
|
+
|
|
41
|
+
if byte == "\e"
|
|
42
|
+
handle_escape byte
|
|
43
|
+
else
|
|
44
|
+
handle_byte byte
|
|
45
|
+
end
|
|
46
|
+
rescue EOFError
|
|
47
|
+
break
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def handle_escape(first_byte)
|
|
55
|
+
second_byte = read_byte(timeout: true)
|
|
56
|
+
|
|
57
|
+
if second_byte.nil?
|
|
58
|
+
@queue << :k_escape
|
|
59
|
+
nil
|
|
60
|
+
elsif second_byte == "["
|
|
61
|
+
third_byte = read_byte(timeout: true)
|
|
62
|
+
|
|
63
|
+
case third_byte
|
|
64
|
+
when "A"
|
|
65
|
+
@queue << :k_up
|
|
66
|
+
when "B"
|
|
67
|
+
@queue << :k_down
|
|
68
|
+
when "C"
|
|
69
|
+
@queue << :k_right
|
|
70
|
+
when "D"
|
|
71
|
+
@queue << :k_left
|
|
72
|
+
else
|
|
73
|
+
@queue << :k_escape
|
|
74
|
+
handle_byte second_byte
|
|
75
|
+
handle_byte third_byte if third_byte
|
|
76
|
+
end
|
|
77
|
+
else
|
|
78
|
+
@queue << :k_escape
|
|
79
|
+
handle_byte second_byte
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def handle_byte(byte)
|
|
84
|
+
return unless BYTES.key?(byte)
|
|
85
|
+
|
|
86
|
+
@queue << BYTES[byte]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def read_byte(timeout: false)
|
|
90
|
+
return if timeout && !IO.select([STDIN], nil, nil, 0.02)
|
|
91
|
+
|
|
92
|
+
STDIN.readpartial(1)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/glw/screen.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module GLW
|
|
2
|
+
module Screen
|
|
3
|
+
class << self
|
|
4
|
+
UpdateBlock = Data.define(:start_index, :cells) do
|
|
5
|
+
def self.make(start_index) = new(start_index, [])
|
|
6
|
+
|
|
7
|
+
def to_s(current_fg: nil, current_bg: nil)
|
|
8
|
+
output = ""
|
|
9
|
+
fg = current_fg
|
|
10
|
+
bg = current_bg
|
|
11
|
+
|
|
12
|
+
cells.each do |cell|
|
|
13
|
+
if cell.fg_color != fg
|
|
14
|
+
output << Terminal.set_fg(cell.fg_color)
|
|
15
|
+
fg = cell.fg_color
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if cell.bg_color != bg
|
|
19
|
+
output << Terminal.set_bg(cell.bg_color)
|
|
20
|
+
bg = cell.bg_color
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
output << cell.char
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
[output, fg, bg]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def start!
|
|
31
|
+
@render_queue = Thread::Queue.new
|
|
32
|
+
|
|
33
|
+
@render_queue.push BufferState.blank(
|
|
34
|
+
height: IO.console.winsize[0],
|
|
35
|
+
width: IO.console.winsize[1]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
Thread.new do
|
|
39
|
+
STDOUT.print Terminal.hide_cursor
|
|
40
|
+
|
|
41
|
+
last_state = nil
|
|
42
|
+
|
|
43
|
+
loop do
|
|
44
|
+
state = @render_queue.pop
|
|
45
|
+
|
|
46
|
+
# Throw away stale states until we have the newest one.
|
|
47
|
+
state = @render_queue.pop until @render_queue.empty?
|
|
48
|
+
|
|
49
|
+
render(last_state, state)
|
|
50
|
+
last_state = state
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def push_state(state)
|
|
56
|
+
@render_queue.push(state)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def render(last_state, state)
|
|
62
|
+
updates = []
|
|
63
|
+
current_block = nil
|
|
64
|
+
|
|
65
|
+
state.cells.each_with_index do |cell, index|
|
|
66
|
+
next if last_state && cell == last_state.cells[index]
|
|
67
|
+
|
|
68
|
+
if current_block && current_block.start_index + current_block.cells.length == index
|
|
69
|
+
current_block.cells << cell
|
|
70
|
+
else
|
|
71
|
+
updates << current_block if current_block
|
|
72
|
+
|
|
73
|
+
current_block = UpdateBlock.new(index, [cell])
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
updates << current_block if current_block
|
|
78
|
+
|
|
79
|
+
current_fg = nil
|
|
80
|
+
current_bg = nil
|
|
81
|
+
|
|
82
|
+
STDOUT.print(
|
|
83
|
+
updates.flat_map do |block|
|
|
84
|
+
y = block.start_index / state.width
|
|
85
|
+
x = block.start_index % state.width
|
|
86
|
+
|
|
87
|
+
block_output, current_fg, current_bg = block.to_s(
|
|
88
|
+
current_fg:,
|
|
89
|
+
current_bg:
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
[
|
|
93
|
+
Terminal.move_to(x, y),
|
|
94
|
+
block_output
|
|
95
|
+
]
|
|
96
|
+
end.join
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
STDOUT.flush
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
data/lib/glw/terminal.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module GLW
|
|
2
|
+
module Terminal
|
|
3
|
+
class << self
|
|
4
|
+
PALETTE = {
|
|
5
|
+
black: [0, 0, 0],
|
|
6
|
+
white: [255, 255, 255]
|
|
7
|
+
}.transform_values do |(r, g, b)|
|
|
8
|
+
[
|
|
9
|
+
"\e[38;2;#{r};#{g};#{b}m",
|
|
10
|
+
"\e[48;2;#{r};#{g};#{b}m"
|
|
11
|
+
]
|
|
12
|
+
end.freeze
|
|
13
|
+
|
|
14
|
+
def move_to(x, y)
|
|
15
|
+
"\e[#{y + 1};#{x + 1}H"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def set_fg(color)
|
|
19
|
+
PALETTE.fetch(color)[0]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def set_bg(color)
|
|
23
|
+
PALETTE.fetch(color)[1]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def hide_cursor
|
|
27
|
+
"\e[?25l"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/glw/version.rb
CHANGED
data/lib/glw.rb
CHANGED
|
@@ -1,33 +1,31 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "io/console"
|
|
2
|
+
require "concurrent/actor"
|
|
3
|
+
|
|
2
4
|
require "zeitwerk"
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
Zeitwerk::Loader.for_gem.tap do |loader|
|
|
7
|
+
loader.inflector.inflect(
|
|
8
|
+
"glw" => "GLW"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
loader.setup
|
|
12
|
+
end
|
|
5
13
|
|
|
6
14
|
module GLW
|
|
7
15
|
class << self
|
|
8
16
|
def start!
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
g = Game.new(term: t)
|
|
17
|
+
IO.console.raw do
|
|
18
|
+
Screen.start!
|
|
19
|
+
Input.start!
|
|
13
20
|
|
|
14
21
|
loop do
|
|
15
|
-
|
|
16
|
-
break if g.send_key(t.getch) == :quit
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def initialize_zeitwerk
|
|
22
|
-
return if @zeitwerk_enabled
|
|
22
|
+
content = Input.pop
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
loader.push_dir(__dir__)
|
|
27
|
-
loader.setup
|
|
24
|
+
exit(0) if content == :k_escape || content == :k_ctrl_c
|
|
25
|
+
end
|
|
28
26
|
end
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
rescue
|
|
28
|
+
raise
|
|
31
29
|
end
|
|
32
30
|
end
|
|
33
31
|
end
|
data/test_input.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "lib/glw"
|
|
5
|
+
|
|
6
|
+
puts "Input Test - Press keys to see symbols (press 'q' or Ctrl-C to quit)"
|
|
7
|
+
puts "Try: letters, numbers, arrows, ESC, space, tab, enter, backspace, Ctrl-C"
|
|
8
|
+
puts "-" * 60
|
|
9
|
+
|
|
10
|
+
IO.console.raw do
|
|
11
|
+
GLW::Input.start!
|
|
12
|
+
|
|
13
|
+
loop do
|
|
14
|
+
key = GLW::Input.pop
|
|
15
|
+
puts "Received: #{key.inspect}"
|
|
16
|
+
|
|
17
|
+
break if key == :k_q || key == :k_ctrl_c
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
puts "\nExiting..."
|
metadata
CHANGED
|
@@ -1,42 +1,56 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: good_luck_wizard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jared Norman
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: zeitwerk
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: '2.4'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
25
|
+
version: '2.4'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: concurrent-ruby
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: concurrent-ruby-edge
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
29
43
|
requirements:
|
|
30
44
|
- - "~>"
|
|
31
45
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
46
|
+
version: '0.7'
|
|
33
47
|
type: :runtime
|
|
34
48
|
prerelease: false
|
|
35
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
50
|
requirements:
|
|
37
51
|
- - "~>"
|
|
38
52
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
53
|
+
version: '0.7'
|
|
40
54
|
description: An unfinished terminal-based roguelike game
|
|
41
55
|
email:
|
|
42
56
|
- jared@super.gd
|
|
@@ -53,16 +67,19 @@ files:
|
|
|
53
67
|
- README.md
|
|
54
68
|
- Rakefile
|
|
55
69
|
- bin/console
|
|
70
|
+
- bin/release
|
|
56
71
|
- bin/setup
|
|
57
72
|
- exe/glw
|
|
58
73
|
- good_luck_wizard.gemspec
|
|
59
74
|
- lib/glw.rb
|
|
60
|
-
- lib/glw/
|
|
61
|
-
- lib/glw/
|
|
75
|
+
- lib/glw/buffer_state.rb
|
|
76
|
+
- lib/glw/input.rb
|
|
62
77
|
- lib/glw/random.rb
|
|
63
|
-
- lib/glw/
|
|
64
|
-
- lib/glw/
|
|
78
|
+
- lib/glw/screen.rb
|
|
79
|
+
- lib/glw/screen_cell.rb
|
|
80
|
+
- lib/glw/terminal.rb
|
|
65
81
|
- lib/glw/version.rb
|
|
82
|
+
- test_input.rb
|
|
66
83
|
homepage: http://github.com/jarednorman/good_luck_wizard
|
|
67
84
|
licenses: []
|
|
68
85
|
metadata: {}
|
|
@@ -80,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
80
97
|
- !ruby/object:Gem::Version
|
|
81
98
|
version: '0'
|
|
82
99
|
requirements: []
|
|
83
|
-
rubygems_version:
|
|
100
|
+
rubygems_version: 4.0.2
|
|
84
101
|
specification_version: 4
|
|
85
102
|
summary: An unfinished terminal-based roguelike game
|
|
86
103
|
test_files: []
|
data/lib/glw/game.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
module GLW
|
|
2
|
-
class Game
|
|
3
|
-
def initialize(term:)
|
|
4
|
-
@map = Map.new
|
|
5
|
-
@term = term
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def send_key(key)
|
|
9
|
-
case key
|
|
10
|
-
when "q"
|
|
11
|
-
:quit
|
|
12
|
-
when "h"
|
|
13
|
-
@map.send_event :left
|
|
14
|
-
when "l"
|
|
15
|
-
@map.send_event :right
|
|
16
|
-
when "k"
|
|
17
|
-
@map.send_event :up
|
|
18
|
-
when "j"
|
|
19
|
-
@map.send_event :down
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def render
|
|
24
|
-
map.render(term, width: term.width - 60, height: term.height)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
attr_reader :term, :map
|
|
30
|
-
end
|
|
31
|
-
end
|
data/lib/glw/map.rb
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
module GLW
|
|
2
|
-
class Map
|
|
3
|
-
MAP = <<~TXT
|
|
4
|
-
############
|
|
5
|
-
#..........# ##########
|
|
6
|
-
#..........############....#...#
|
|
7
|
-
#..............................#
|
|
8
|
-
#.......g..############....#...#
|
|
9
|
-
#..........# #....#...#
|
|
10
|
-
############ ##########
|
|
11
|
-
TXT
|
|
12
|
-
|
|
13
|
-
def initialize
|
|
14
|
-
@player_x = 3
|
|
15
|
-
@player_y = 3
|
|
16
|
-
|
|
17
|
-
@map = Hash.new(" ")
|
|
18
|
-
MAP.lines.each_with_index do |line, y|
|
|
19
|
-
line.chars.each_with_index do |c, x|
|
|
20
|
-
@map[[x, y]] = c
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
@offset_x = 1
|
|
25
|
-
@offset_y = 1
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def send_event(e)
|
|
29
|
-
case e
|
|
30
|
-
when :left
|
|
31
|
-
@player_x -= 1 if valid_player_position?(@player_x - 1, @player_y)
|
|
32
|
-
when :right
|
|
33
|
-
@player_x += 1 if valid_player_position?(@player_x + 1, @player_y)
|
|
34
|
-
when :up
|
|
35
|
-
@player_y -= 1 if valid_player_position?(@player_x, @player_y - 1)
|
|
36
|
-
when :down
|
|
37
|
-
@player_y += 1 if valid_player_position?(@player_x, @player_y + 1)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def render(term, width:, height:)
|
|
42
|
-
(0..width - 1).each do |x|
|
|
43
|
-
(0..height - 1).each do |y|
|
|
44
|
-
|
|
45
|
-
if [@player_x + @offset_x, @player_y + @offset_y] == [x, y]
|
|
46
|
-
term.set(
|
|
47
|
-
x: x,
|
|
48
|
-
y: y,
|
|
49
|
-
c: "@",
|
|
50
|
-
fg: 220
|
|
51
|
-
)
|
|
52
|
-
else
|
|
53
|
-
term.set(
|
|
54
|
-
x: x,
|
|
55
|
-
y: y,
|
|
56
|
-
c: @map[[x - @offset_x, y - @offset_y]]
|
|
57
|
-
)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
term.refresh
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
def valid_player_position?(x, y)
|
|
68
|
-
@map[[x, y]] == "."
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
data/lib/glw/term.rb
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
module GLW
|
|
2
|
-
# This class is responsible for handling all interactions with the terminal
|
|
3
|
-
# so that this thing can be half-ways frontend independent, though I have no
|
|
4
|
-
# intention of ever switching frontends.
|
|
5
|
-
class Term
|
|
6
|
-
DEFAULT_FG = 255
|
|
7
|
-
DEFAULT_BG = 16
|
|
8
|
-
|
|
9
|
-
Cell = Struct.new(:c, :fg, :bg)
|
|
10
|
-
|
|
11
|
-
DEFAULT_CELL = Cell.new(" ", DEFAULT_FG, DEFAULT_BG)
|
|
12
|
-
|
|
13
|
-
class << self
|
|
14
|
-
def with_term
|
|
15
|
-
Curses.init_screen
|
|
16
|
-
Curses.start_color
|
|
17
|
-
Curses.curs_set(0)
|
|
18
|
-
Curses.noecho
|
|
19
|
-
|
|
20
|
-
Curses.assume_default_colors(DEFAULT_FG, DEFAULT_BG)
|
|
21
|
-
|
|
22
|
-
yield new(Curses::Window.new(0, 0, 0, 0))
|
|
23
|
-
ensure
|
|
24
|
-
Curses.close_screen
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def initialize(window)
|
|
29
|
-
@window = window
|
|
30
|
-
@tiles = Hash.new { DEFAULT_CELL }
|
|
31
|
-
@next_tiles = {}
|
|
32
|
-
@colors = TermColors.new
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def set(x:, y:, c:, fg: DEFAULT_FG, bg: DEFAULT_BG)
|
|
36
|
-
cell = Cell.new(c, fg, bg)
|
|
37
|
-
|
|
38
|
-
@next_tiles[[x, y]] = cell unless @tiles[[x, y]] == cell
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def width
|
|
42
|
-
Curses.cols
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def height
|
|
46
|
-
Curses.lines
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def getch
|
|
50
|
-
window.getch
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def refresh
|
|
54
|
-
@next_tiles.each do |coords, cell|
|
|
55
|
-
x, y = *coords
|
|
56
|
-
window.setpos(y, x)
|
|
57
|
-
|
|
58
|
-
window.attron(colors[cell.fg, cell.bg]) do
|
|
59
|
-
window << cell.c
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
@tiles = @tiles.merge(@next_tiles)
|
|
64
|
-
|
|
65
|
-
window.refresh
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
private
|
|
69
|
-
|
|
70
|
-
attr_reader :window, :colors
|
|
71
|
-
end
|
|
72
|
-
end
|
data/lib/glw/term_colors.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module GLW
|
|
2
|
-
class TermColors
|
|
3
|
-
def initialize(curses = Curses)
|
|
4
|
-
index = 1
|
|
5
|
-
|
|
6
|
-
@colors = Hash.new do |hash, key|
|
|
7
|
-
fg, bg = *key
|
|
8
|
-
|
|
9
|
-
curses.init_pair(index, fg, bg)
|
|
10
|
-
hash[key] = curses.color_pair(index)
|
|
11
|
-
|
|
12
|
-
index += 1
|
|
13
|
-
|
|
14
|
-
hash[key]
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def [](fg, bg)
|
|
19
|
-
@colors[[fg, bg]]
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|