delve 0.0.7

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +24 -0
  5. data/LICENSE +25 -0
  6. data/README.md +6 -0
  7. data/ROADMAP.md +92 -0
  8. data/Rakefile +25 -0
  9. data/bin/delve +15 -0
  10. data/delve.gemspec +17 -0
  11. data/doc/examples/ascii.rb +34 -0
  12. data/doc/examples/astar.rb +39 -0
  13. data/doc/examples/border.rb +13 -0
  14. data/doc/examples/cellular.rb +15 -0
  15. data/doc/examples/display.rb +27 -0
  16. data/doc/examples/engine.rb +29 -0
  17. data/doc/examples/menu.rb +22 -0
  18. data/doc/examples/noise.rb +37 -0
  19. data/doc/examples/progress.rb +25 -0
  20. data/doc/examples/rogue.rb +15 -0
  21. data/lib/delve.rb +109 -0
  22. data/lib/delve/component/collision.rb +17 -0
  23. data/lib/delve/component/movement.rb +78 -0
  24. data/lib/delve/component/position.rb +30 -0
  25. data/lib/delve/component/symbol.rb +23 -0
  26. data/lib/delve/display/curses_renderer.rb +63 -0
  27. data/lib/delve/display/display.rb +51 -0
  28. data/lib/delve/engine.rb +30 -0
  29. data/lib/delve/entity.rb +23 -0
  30. data/lib/delve/event_queue.rb +48 -0
  31. data/lib/delve/fov/discrete_shadowcasting.rb +78 -0
  32. data/lib/delve/fov/fov.rb +83 -0
  33. data/lib/delve/game.rb +22 -0
  34. data/lib/delve/generator/cellular.rb +111 -0
  35. data/lib/delve/generator/dungeon.rb +19 -0
  36. data/lib/delve/generator/map.rb +30 -0
  37. data/lib/delve/generator/noise.rb +33 -0
  38. data/lib/delve/generator/rogue.rb +403 -0
  39. data/lib/delve/input/curses_input.rb +28 -0
  40. data/lib/delve/input/input.rb +12 -0
  41. data/lib/delve/path/astar.rb +83 -0
  42. data/lib/delve/path/path.rb +70 -0
  43. data/lib/delve/scheduler/action_scheduler.rb +38 -0
  44. data/lib/delve/scheduler/scheduler.rb +37 -0
  45. data/lib/delve/scheduler/simple_scheduler.rb +21 -0
  46. data/lib/delve/screen_manager.rb +41 -0
  47. data/lib/delve/widgets/border.rb +44 -0
  48. data/lib/delve/widgets/key_value.rb +36 -0
  49. data/lib/delve/widgets/menu.rb +84 -0
  50. data/lib/delve/widgets/multi_line.rb +51 -0
  51. data/lib/delve/widgets/progress.rb +37 -0
  52. data/lib/delve/widgets/text.rb +37 -0
  53. data/lib/delve/widgets/viewport.rb +67 -0
  54. data/rot.js.LICENSE +25 -0
  55. data/templates/Gemfile.erb +4 -0
  56. data/templates/README.md.erb +22 -0
  57. data/templates/binfile.erb +21 -0
  58. data/templates/game_screen.rb.erb +51 -0
  59. data/templates/gemspec.erb +27 -0
  60. data/templates/loading_screen.rb.erb +46 -0
  61. data/templates/player_factory.rb.erb +19 -0
  62. data/templates/title_screen.rb.erb +42 -0
  63. data/templates/world.rb.erb +63 -0
  64. data/test/component/collision_test.rb +39 -0
  65. data/test/component/movement_test.rb +155 -0
  66. data/test/component/position_test.rb +43 -0
  67. data/test/component/symbol_test.rb +30 -0
  68. data/test/delve_test.rb +61 -0
  69. data/test/display/curses_renderer_test.rb +60 -0
  70. data/test/display/display_test.rb +86 -0
  71. data/test/engine_test.rb +36 -0
  72. data/test/entity_test.rb +48 -0
  73. data/test/event_queue_test.rb +86 -0
  74. data/test/game_test.rb +47 -0
  75. data/test/generator/dungeon_test.rb +21 -0
  76. data/test/generator/map_test.rb +31 -0
  77. data/test/generator/noise_test.rb +49 -0
  78. data/test/input/curses_input_test.rb +24 -0
  79. data/test/input/input_test.rb +21 -0
  80. data/test/path/astar_test.rb +22 -0
  81. data/test/path/path_test.rb +41 -0
  82. data/test/scheduler/action_scheduler_test.rb +54 -0
  83. data/test/scheduler/scheduler_test.rb +50 -0
  84. data/test/scheduler/simple_scheduler_test.rb +33 -0
  85. data/test/screen_manager_test.rb +92 -0
  86. data/test/widgets/border_test.rb +60 -0
  87. data/test/widgets/key_value_test.rb +68 -0
  88. data/test/widgets/menu_test.rb +103 -0
  89. data/test/widgets/multi_line_test.rb +73 -0
  90. data/test/widgets/progress_test.rb +96 -0
  91. data/test/widgets/text_test.rb +66 -0
  92. data/test/widgets/viewport_test.rb +154 -0
  93. metadata +193 -0
@@ -0,0 +1,70 @@
1
+ class Path
2
+
3
+ @@default_options = { topology: :eight }
4
+
5
+ def initialize(to_x, to_y, free_checker, options = Hash.new)
6
+ raise 'Cannot initialize path if to_x is nil' if to_x.nil?
7
+ raise 'Cannot initialize path if to_y is nil' if to_y.nil?
8
+ raise 'Cannot initialize path if free checker is nil' if free_checker.nil?
9
+ raise 'Cannot initialize path if free checker does not respond to #free?' unless free_checker.respond_to? :free?
10
+
11
+ @to_x = to_x
12
+ @to_y = to_y
13
+ @from_x = nil
14
+ @from_y = nil
15
+ @free_checker = free_checker
16
+ @options = @@default_options.merge options
17
+
18
+ @dirs = directions(options[:topology])
19
+ end
20
+
21
+ def compute(from_x, from_y)
22
+ end
23
+
24
+ private
25
+ def get_neighbours(cx, cy)
26
+ result = Array.new
27
+ (0..@dirs.length-1).each do |i|
28
+ dir = @dirs[i]
29
+ x = cx + dir[0]
30
+ y = cy + dir[1]
31
+
32
+ next unless @free_checker.free? x, y
33
+ result << [x, y]
34
+ end
35
+
36
+ result
37
+ end
38
+
39
+ def directions(v)
40
+ dirs = {
41
+ :four => [
42
+ [ 0, -1],
43
+ [ 1, 0],
44
+ [ 0, 1],
45
+ [-1, 0]
46
+ ],
47
+ :eight => [
48
+ [ 0, -1],
49
+ [ 1, -1],
50
+ [ 1, 0],
51
+ [ 1, 1],
52
+ [ 0, 1],
53
+ [-1, 1],
54
+ [-1, 0],
55
+ [-1, -1]
56
+ ],
57
+ :six => [
58
+ [-1, -1],
59
+ [ 1, -1],
60
+ [ 2, 0],
61
+ [ 1, 1],
62
+ [-1, 1],
63
+ [-2, 0]
64
+ ]
65
+ }
66
+
67
+ dirs[v]
68
+ end
69
+
70
+ end
@@ -0,0 +1,38 @@
1
+ require 'delve/scheduler/scheduler'
2
+
3
+ class ActionScheduler < Scheduler
4
+
5
+ @@default_duration = 1
6
+
7
+ def initialize(event_queue)
8
+ @duration = @@default_duration
9
+ super event_queue
10
+ end
11
+
12
+ def clear
13
+ super
14
+ end
15
+
16
+ def remove(item)
17
+ @duration = @@default_duration if item == @current
18
+ super item
19
+ end
20
+
21
+ def add(item, repeat, time=@@default_duration)
22
+ @queue.add item, time
23
+ super item, repeat
24
+ end
25
+
26
+ def set_duration(time)
27
+ @duration = time if @current
28
+ end
29
+
30
+ def next
31
+ if @current and !@repeat.index(@current).nil?
32
+ @queue.add(@current, @duration || @@default_duration)
33
+ @duration = @@default_duration
34
+ end
35
+ super
36
+ end
37
+
38
+ end
@@ -0,0 +1,37 @@
1
+ class Scheduler
2
+
3
+ def initialize(event_queue)
4
+ @queue = event_queue
5
+ @current = nil
6
+ @repeat = Array.new
7
+ end
8
+
9
+ def time
10
+ @queue.time
11
+ end
12
+
13
+ def next
14
+ @current = @queue.get
15
+ @current
16
+ end
17
+
18
+ def remove(item)
19
+ result = @queue.remove item
20
+
21
+ index = @repeat.index item
22
+ @events.delete_at index if index
23
+
24
+ result
25
+ end
26
+
27
+ def clear
28
+ @queue.clear
29
+ @current = nil
30
+ @repeat = Array.new
31
+ end
32
+
33
+ def add(item, repeat=false)
34
+ @repeat << item if repeat
35
+ end
36
+
37
+ end
@@ -0,0 +1,21 @@
1
+ require 'delve/scheduler/scheduler'
2
+
3
+ class SimpleScheduler < Scheduler
4
+
5
+ def initialize(event_queue)
6
+ super event_queue
7
+ end
8
+
9
+ def add(item, repeat)
10
+ @queue.add item, 0
11
+ super item, repeat
12
+ end
13
+
14
+ def next
15
+ if @current and !@repeat.index(@current).nil?
16
+ @queue.add(@current, 0)
17
+ end
18
+ super
19
+ end
20
+
21
+ end
@@ -0,0 +1,41 @@
1
+ class ScreenManager
2
+ def initialize
3
+ @screen_stack = Array.new
4
+ end
5
+
6
+ def empty?
7
+ @screen_stack.empty?
8
+ end
9
+
10
+ def push_screen(screen)
11
+ @screen_stack.push screen
12
+ end
13
+
14
+ def pop_screen
15
+ @screen_stack.pop
16
+ end
17
+
18
+ def update(input)
19
+ raise 'Cannot handle key when no screens are present' if empty?
20
+ raise 'Cannot handle key when input is nil' unless input
21
+ @screen_stack.last.update input
22
+ end
23
+
24
+ def render(display)
25
+ raise 'Cannot render when no screens are present' if empty?
26
+ raise 'Cannot render when display is nil' unless display
27
+
28
+ bottom = @screen_stack.length - 1
29
+ screens = @screen_stack.length - 1
30
+
31
+ (0..screens).reverse_each do |i|
32
+ if !@screen_stack[i].partial?
33
+ break
34
+ end
35
+ bottom = i-1
36
+ end
37
+ (bottom..screens).each do |i|
38
+ @screen_stack[i].render display
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ class BorderWidget
2
+ def initialize(x, y, width, height, heading=nil, fg=:white, bg=:black)
3
+ raise 'Cannot initialize border widget when x is nil' unless x
4
+ raise 'Cannot initialize border widget when y is nil' unless y
5
+ raise 'Cannot initailize border widget when width is nil' unless width
6
+ raise 'Cannot initialize border widget when height is nil' unless height
7
+ raise 'Cannot initialize border widget when heading is wider than width + 4' if heading and heading.length > width + 4
8
+
9
+ @x = x
10
+ @y = y
11
+ @width = width
12
+ @height = height
13
+ @heading = heading
14
+ @fg = fg
15
+ @bg = bg
16
+ end
17
+
18
+ def draw(display)
19
+ raise 'Cannot draw text when display is nil' unless display
20
+
21
+ header_text = " #{@heading} "
22
+ if header_text.length.odd?
23
+ header_text = "#{header_text} "
24
+ end
25
+ center_point = ((@x + @width) / 2).floor
26
+ half_text = (header_text.length / 2).ceil
27
+ header_start = center_point - half_text
28
+ header_end = center_point + half_text
29
+
30
+ (@x..(@x+@width-1)).each do |x|
31
+ char = (x == @x || x == (@x+@width-1)) ? '+' : '-'
32
+ if @heading and x > header_start and x <= header_end
33
+ char = header_text[x-header_start-1]
34
+ end
35
+ display.draw x, @y, char, @fg, @bg
36
+ display.draw x, (@y+@height-1), (x == @x || x == (@x+@width-1)) ? '+' : '-', @fg, @bg
37
+ end
38
+
39
+ ((@y+1)..(@y+@height-2)).each do |y|
40
+ display.draw @x, y, '|', @fg, @bg
41
+ display.draw (@x+@width-1), y, '|', @fg, @bg
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,36 @@
1
+ class KeyValueWidget
2
+ attr_accessor :value
3
+
4
+ def initialize(x, y, label, value)
5
+ raise 'Cannot initialize key value widget when x is nil' unless x
6
+ raise 'Cannot initialize key value widget when y is nil' unless y
7
+ raise 'Cannot initialize key value widget when label is nil' unless label
8
+ raise 'Cannot initialize key value widget when value is nil' unless value
9
+
10
+ @x = x
11
+ @y = y
12
+ @label = label
13
+ @value = value
14
+ end
15
+
16
+ def draw(display)
17
+ raise 'Cannot draw text when display is nil' unless display
18
+
19
+ x = @x
20
+ @label.each_char do |c|
21
+ display.draw x, @y, c
22
+ x += 1
23
+ end
24
+
25
+ display.draw x, @y, ':'
26
+ x += 1
27
+ display.draw x, @y, ' '
28
+ x += 1
29
+
30
+ @value.each_char do |c|
31
+ display.draw x, @y, c
32
+ x += 1
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,84 @@
1
+ class MenuWidget
2
+ def initialize(x, y, items, foreground=:white, background=:black, highlight=:red)
3
+ raise 'Cannot initialize menu widget when x is nil' unless x
4
+ raise 'Cannot initialize menu widget when y is nil' unless y
5
+ raise 'Cannot initialize menu widget when items is nil' unless items
6
+ raise 'Cannot initialize menu widget when items is empty' if items.empty?
7
+
8
+ @x = x
9
+ @y = y
10
+ @items = items
11
+ @selected_index = 0
12
+ @fg = foreground
13
+ @bg = background
14
+ @highlight = highlight
15
+ end
16
+
17
+ def selected_item
18
+ key = @items.keys[@selected_index]
19
+ @items[key]
20
+ end
21
+
22
+ def next
23
+ @selected_index += 1
24
+ if @selected_index >= @items.keys.length
25
+ @selected_index = 0
26
+ end
27
+ end
28
+
29
+ def previous
30
+ @selected_index -= 1
31
+ if @selected_index < 0
32
+ @selected_index = @items.keys.length - 1
33
+ end
34
+ end
35
+
36
+ def select(key)
37
+ return false if !@items.keys.include? key
38
+ @selected_index = @items.keys.index key
39
+ end
40
+
41
+ def draw(display)
42
+ raise 'Cannot draw text when display is nil' unless display
43
+
44
+ items = 0
45
+ @items.keys.each do |key|
46
+ chars = 0
47
+ y = determine_y display
48
+ @items[key].each_char do |c|
49
+ fg = @selected_index == items ? @bg : @fg
50
+ bg = @selected_index == items ? @fg : @bg
51
+ x = determine_x display
52
+ text_color = (c == key || c == key.upcase) ? @highlight : fg
53
+ display.draw(x + chars, y + items, c, text_color, bg)
54
+ chars += 1
55
+ end
56
+ items += 1
57
+ end
58
+ end
59
+
60
+ private
61
+ def determine_x display
62
+ if @x == :center
63
+ return (display.width / 2.0).ceil - (longest_line / 2.0).floor
64
+ end
65
+ @x
66
+ end
67
+
68
+ def determine_y display
69
+ if @y == :center
70
+ return ((display.height / 2.0).ceil) - (@items.keys.length / 2.0).floor
71
+ end
72
+ @y
73
+ end
74
+
75
+ def longest_line
76
+ value = -1
77
+ @items.keys.each do |key|
78
+ if value < @items[key].length
79
+ value = @items[key].length
80
+ end
81
+ end
82
+ return value
83
+ end
84
+ end
@@ -0,0 +1,51 @@
1
+ class MultiLineWidget
2
+ def initialize(x, y, lines)
3
+ raise 'Cannot initialize text widget when x is nil' unless x
4
+ raise 'Cannot initialize text widget when y is nil' unless y
5
+ raise 'Cannot initialize text widget when lines is nil' unless lines
6
+
7
+ @x = x
8
+ @y = y
9
+ @lines = lines
10
+ end
11
+
12
+ def draw(display)
13
+ raise 'Cannot draw text when display is nil' unless display
14
+
15
+ y = determine_y(display)
16
+ @lines.each do |line|
17
+ x = determine_x(display)
18
+ line.each_char do |c|
19
+ display.draw x, y, c
20
+ x += 1
21
+ end
22
+ y += 1
23
+ end
24
+ end
25
+
26
+ private
27
+ def determine_x display
28
+ if @x == :center
29
+ return (display.width / 2.0).ceil - (longest_line / 2.0).floor
30
+ end
31
+ @x
32
+ end
33
+
34
+ def determine_y display
35
+ if @y == :center
36
+ return ((display.height / 2.0).ceil) - (@lines.length / 2.0).floor
37
+ end
38
+ @y
39
+ end
40
+
41
+ def longest_line
42
+ value = -1
43
+ @lines.each do |line|
44
+ if value < line.length
45
+ value = line.length
46
+ end
47
+ end
48
+ return value
49
+ end
50
+
51
+ end
@@ -0,0 +1,37 @@
1
+ class ProgressWidget
2
+ attr_accessor :current, :max
3
+
4
+ def initialize(x, y, width, current, max, fg, bg)
5
+ raise 'Cannot initialize progress widget when x is nil' unless x
6
+ raise 'Cannot initialize progress widget when y is nil' unless y
7
+ raise 'Cannot initialize progress widget when width is nil' unless width
8
+ raise 'Cannot initialize progress widget when current value is nil' unless current
9
+ raise 'Cannot initialize progress widget when max value is nil' unless max
10
+ raise 'Cannot initialize progress widget when foreground color is nil' unless fg
11
+ raise 'Cannot initialize progress widget when background color is nil' unless bg
12
+
13
+ @x = x
14
+ @y = y
15
+ @width = width
16
+ @current = current
17
+ @max = max
18
+ @fg = fg
19
+ @bg = bg
20
+ end
21
+
22
+ def draw(display)
23
+ raise 'Cannot draw text when display is nil' unless display
24
+
25
+ percent = 1.0 * @current / @max
26
+ to_fill = (percent * @width).ceil
27
+
28
+ x = @x
29
+ (0..@width-1).each do |i|
30
+ color = i < to_fill ? @fg : @bg
31
+ display.draw x, @y, ' ', color, color
32
+ x += 1
33
+ end
34
+
35
+ end
36
+
37
+ end