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,155 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve/component/movement'
4
+ require 'mocha/setup'
5
+
6
+ class MovementComponentTest < Minitest::Test
7
+
8
+ def setup
9
+ @parent = mock('object')
10
+ @position = mock('object')
11
+ @collision = mock('object')
12
+ @fourway = MovementComponent.new @parent
13
+ @eightway = MovementComponent.new @parent, :eightway
14
+ end
15
+
16
+ # test all movement styles
17
+
18
+ def test_id_is_movement
19
+ assert_equal :movement, @fourway.id
20
+ end
21
+
22
+ def test_initialize_component_with_nil_parent_fails
23
+ assert_raises RuntimeError do
24
+ MovementComponent.new nil, :fourway
25
+ end
26
+ end
27
+
28
+ def test_initialize_component_with_nil_movement_style_defaults_to_fourway
29
+ move = MovementComponent.new @parent, nil
30
+ assert_equal :fourway, move.style
31
+ end
32
+
33
+ def test_initialize_with_eight_way_movement
34
+ move = MovementComponent.new @parent, :eightway
35
+ assert_equal :eightway, move.style
36
+ end
37
+
38
+ def test_initialize_with_invalid_movement_style
39
+ assert_raises RuntimeError do
40
+ MovementComponent.new @parent, :unknown
41
+ end
42
+ end
43
+
44
+ def test_moving_north_west_in_fourway_fails
45
+ assert_raises RuntimeError do
46
+ @fourway.north_west
47
+ end
48
+ end
49
+
50
+ def test_moving_north_east_in_fourway_fails
51
+ assert_raises RuntimeError do
52
+ @fourway.north_east
53
+ end
54
+ end
55
+
56
+ def test_moving_south_west_in_fourway_fails
57
+ assert_raises RuntimeError do
58
+ @fourway.south_west
59
+ end
60
+ end
61
+
62
+ def test_moving_south_east_in_fourway_fails
63
+ assert_raises RuntimeError do
64
+ @fourway.south_east
65
+ end
66
+ end
67
+
68
+ def test_move_north
69
+ set_movement_expectations 0, -1
70
+ @parent.expects(:has?).with(:collision).returns(false)
71
+ @eightway.north
72
+ end
73
+
74
+ def test_move_north_east
75
+ set_movement_expectations 1, -1
76
+ @parent.expects(:has?).with(:collision).returns(false)
77
+ @eightway.north_east
78
+ end
79
+
80
+ def test_move_east
81
+ set_movement_expectations 1, 0
82
+ @parent.expects(:has?).with(:collision).returns(false)
83
+ @eightway.east
84
+ end
85
+
86
+ def test_move_south_east
87
+ set_movement_expectations 1, 1
88
+ @parent.expects(:has?).with(:collision).returns(false)
89
+ @eightway.south_east
90
+ end
91
+
92
+ def test_move_south
93
+ set_movement_expectations 0, 1
94
+ @parent.expects(:has?).with(:collision).returns(false)
95
+ @eightway.south
96
+ end
97
+
98
+ def test_move_south_west
99
+ set_movement_expectations -1, 1
100
+ @parent.expects(:has?).with(:collision).returns(false)
101
+ @eightway.south_west
102
+ end
103
+
104
+ def test_move_west
105
+ set_movement_expectations -1, 0
106
+ @parent.expects(:has?).with(:collision).returns(false)
107
+ @eightway.west
108
+ end
109
+
110
+ def test_move_north_west
111
+ set_movement_expectations -1, -1
112
+ @parent.expects(:has?).with(:collision).returns(false)
113
+ @eightway.north_west
114
+ end
115
+
116
+ def test_move_when_there_is_no_collision
117
+ @parent.expects(:has?).with(:collision).returns(true)
118
+ @parent.expects(:get).with(:collision).returns(@collision)
119
+ @collision.expects(:free?).returns(true)
120
+ @position.expects(:x).returns(1)
121
+ @position.expects(:y).returns(1)
122
+
123
+ set_movement_expectations 0, 1
124
+
125
+ @fourway.south
126
+ end
127
+
128
+ def test_dont_move_when_there_is_collision
129
+ @parent.expects(:has?).with(:collision).returns(true)
130
+ @parent.expects(:get).with(:collision).returns(@collision)
131
+ @collision.expects(:free?).returns(false)
132
+ @position.expects(:x).returns(1)
133
+ @position.expects(:y).returns(1)
134
+
135
+ @parent.expects(:has?).with(:position).returns(true)
136
+ @parent.expects(:get).with(:position).returns(@position)
137
+
138
+ @fourway.south
139
+ end
140
+
141
+ def test_always_move_if_no_collision_component
142
+ set_movement_expectations 0, -1
143
+ @parent.expects(:has?).with(:collision).returns(false)
144
+
145
+ @fourway.north
146
+ end
147
+
148
+ private
149
+ def set_movement_expectations(dx, dy)
150
+ @parent.expects(:has?).with(:position).returns(true)
151
+ @parent.expects(:get).with(:position).returns(@position)
152
+ @position.expects(:displace).with(dx, dy)
153
+ end
154
+
155
+ end
@@ -0,0 +1,43 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve/component/position'
4
+ require 'mocha/setup'
5
+
6
+ class PositionComponentTest < Minitest::Test
7
+
8
+ def setup
9
+ @parent = mock('object')
10
+ @pos = PositionComponent.new @parent
11
+ end
12
+
13
+ def test_initialize_component_with_nil_parent_fails
14
+ assert_raises RuntimeError do
15
+ PositionComponent.new nil
16
+ end
17
+ end
18
+
19
+ def test_initial_position_is_zero_zero
20
+ assert_equal 0, @pos.x
21
+ assert_equal 0, @pos.y
22
+ end
23
+
24
+ def test_id_is_position
25
+ assert_equal :position, @pos.id
26
+ end
27
+
28
+ def test_set_position
29
+ @pos.set 4, 6
30
+
31
+ assert_equal 4, @pos.x
32
+ assert_equal 6, @pos.y
33
+ end
34
+
35
+ def test_displace_position
36
+ @pos.set 4, 6
37
+ @pos.displace -1, 1
38
+
39
+ assert_equal 3, @pos.x
40
+ assert_equal 7, @pos.y
41
+ end
42
+
43
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve/component/symbol'
4
+ require 'mocha/setup'
5
+
6
+ class SymbolComponentTest < Minitest::Test
7
+
8
+ def setup
9
+ @parent = mock('object')
10
+ @symbol = 'x'
11
+ @component = SymbolComponent.new @parent, @symbol
12
+ end
13
+
14
+ def test_initialize_component_with_nil_parent_fails
15
+ assert_raises RuntimeError do
16
+ SymbolComponent.new nil, @symbol
17
+ end
18
+ end
19
+
20
+ def test_initialize_component_with_nil_symbol_fails
21
+ assert_raises RuntimeError do
22
+ SymbolComponent.new @parent, nil
23
+ end
24
+ end
25
+
26
+ def test_get_symbol
27
+ assert_equal({ :char => @symbol, :color => :white }, @component.symbol)
28
+ end
29
+
30
+ end
@@ -0,0 +1,61 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve'
4
+ require 'fileutils'
5
+
6
+ class DelveTest < Minitest::Test
7
+
8
+ def setup
9
+ @base_path = '/home/me'
10
+ @name = 'crawler'
11
+ @full_path = "#{@base_path}/#{@name}"
12
+ @delve = Delve.new @name
13
+ end
14
+
15
+ def test_initialize_without_name_fails
16
+ assert_raises RuntimeError do
17
+ Delve.new nil
18
+ end
19
+ end
20
+
21
+ def test_set_unknown_renderer_fails
22
+ assert_raises RuntimeError do
23
+ @delve.use_renderer :train
24
+ end
25
+ end
26
+
27
+ def test_default_renderer_is_curses
28
+ assert_equal :curses, @delve.renderer
29
+ end
30
+
31
+ def test_set_unknown_generator_fails
32
+ assert_raises RuntimeError do
33
+ @delve.use_generator :window
34
+ end
35
+ end
36
+
37
+ def test_default_generator_is_rogue
38
+ assert_equal :rogue, @delve.generator
39
+ end
40
+
41
+ def test_create_project_fails_if_directory_already_exists
42
+ Dir.expects(:exist?).with(@full_path).returns(true)
43
+ assert_raises RuntimeError do
44
+ @delve.create_game @base_path
45
+ end
46
+ end
47
+
48
+ def test_directory_structure_is_created
49
+ Dir.expects(:exist?).with(@full_path).returns(false)
50
+ FileUtils.expects(:mkdir).with(@full_path)
51
+ FileUtils.expects(:mkdir).with(@full_path + '/bin')
52
+ FileUtils.expects(:mkdir).with(@full_path + '/lib')
53
+ FileUtils.expects(:mkdir).with(@full_path + '/lib/' + @name)
54
+ FileUtils.expects(:mkdir).with(@full_path + '/lib/' + @name + '/screens')
55
+
56
+ #TODO: test all files
57
+
58
+ @delve.create_game @base_path
59
+ end
60
+
61
+ end
@@ -0,0 +1,60 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'mocha/setup'
4
+ require 'curses'
5
+ require 'delve/display/curses_renderer'
6
+
7
+ class CursesRendererTests < Minitest::Test
8
+
9
+ def setup
10
+ @renderer = CursesRenderer.new
11
+ end
12
+
13
+ def test_init_calls_curses_init
14
+ Curses.expects(:init_screen)
15
+ Curses.expects(:nl)
16
+ Curses.expects(:noecho)
17
+ Curses.expects(:curs_set).with(0)
18
+ @renderer.init
19
+ end
20
+
21
+ def test_exit_calls_curses_close
22
+ Curses.expects(:close_screen)
23
+ @renderer.exit
24
+ end
25
+
26
+ def test_draw
27
+ Curses.expects(:setpos)
28
+ Curses.expects(:addstr)
29
+ Curses.expects(:init_screen)
30
+ Curses.expects(:nl)
31
+ Curses.expects(:noecho)
32
+ Curses.expects(:curs_set).with(0)
33
+ @renderer.init
34
+ @renderer.draw 2, 2, '@', :white, :black
35
+ @renderer.exit
36
+ end
37
+
38
+ def test_render
39
+ Curses.expects(:refresh)
40
+ Curses.expects(:init_screen)
41
+ Curses.expects(:nl)
42
+ Curses.expects(:noecho)
43
+ Curses.expects(:curs_set).with(0)
44
+ Curses.expects(:clear)
45
+ @renderer.expects(:draw).with(2, 2, '@', :white, :black)
46
+ @renderer.init
47
+ @renderer.render({ '1,1' => {:x => 2, :y => 2, :char => '@', :foreground => :white, :background => :black} })
48
+ @renderer.exit
49
+ end
50
+
51
+ def test_height
52
+ Curses.expects(:lines)
53
+ @renderer.height
54
+ end
55
+
56
+ def test_width
57
+ Curses.expects(:cols)
58
+ @renderer.width
59
+ end
60
+ end
@@ -0,0 +1,86 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve/display/display'
4
+ require 'mocha/setup'
5
+
6
+ class DisplayTests < MiniTest::Test
7
+
8
+ def setup
9
+ @renderer = mock('object')
10
+ @renderer.expects(:init)
11
+ @display = Display.new @renderer
12
+ end
13
+
14
+ def test_create_display_with_no_renderer_raises_error
15
+ assert_raises RuntimeError do
16
+ @display = Display.new nil
17
+ end
18
+ end
19
+
20
+ def test_create_display_with_no_options_sets_defaults
21
+ opts = @display.options
22
+
23
+ assert_equal 80, opts[:width]
24
+ assert_equal 24, opts[:height]
25
+ assert_equal :white, opts[:foreground]
26
+ assert_equal :black, opts[:background]
27
+ end
28
+
29
+ def test_partially_setting_options_keeps_changes_and_defults
30
+ renderer = mock('object')
31
+ renderer.expects(:init)
32
+ @display = Display.new(renderer, { :height => 36, :width => 120 })
33
+ opts = @display.options
34
+
35
+ assert_equal 120, opts[:width]
36
+ assert_equal 36, opts[:height]
37
+ assert_equal :white, opts[:foreground]
38
+ assert_equal :black, opts[:background]
39
+ end
40
+
41
+ def test_completely_define_options
42
+ renderer = mock('object')
43
+ renderer.expects(:init)
44
+ @display = Display.new(renderer, { :height => 36, :width => 120, :background => :gray, :foreground => :yellow })
45
+ opts = @display.options
46
+
47
+ assert_equal 120, opts[:width]
48
+ assert_equal 36, opts[:height]
49
+ assert_equal :yellow, opts[:foreground]
50
+ assert_equal :gray, opts[:background]
51
+ end
52
+
53
+ def test_not_initially_dirty_so_no_rendering_is_done
54
+ @display.render
55
+ # If it was dirty, then the renderer would be called, and the mock would report an error
56
+ end
57
+
58
+ def test_draw_with_no_colors_uses_default
59
+ @display.draw 1, 1, '@'
60
+
61
+ @renderer.expects(:render).with({ '1,1' => { :x => 1, :y => 1, :char => '@', :foreground => :white, :background => :black } })
62
+ @display.render
63
+ end
64
+
65
+ def test_draw_with_colors
66
+ @display.draw 1, 1, '@', :red, :gray
67
+
68
+ @renderer.expects(:render).with({ '1,1' => { :x => 1, :y => 1, :char => '@', :foreground => :red, :background => :gray} })
69
+ @display.render
70
+ end
71
+
72
+ def test_display_exit_defers_to_renderer
73
+ @renderer.expects(:exit)
74
+ @display.exit
75
+ end
76
+
77
+ def test_height_defers_to_renderer
78
+ @renderer.expects(:height)
79
+ @display.height
80
+ end
81
+
82
+ def test_width_defers_to_renderer
83
+ @renderer.expects(:width)
84
+ @display.width
85
+ end
86
+ end
@@ -0,0 +1,36 @@
1
+ require 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'delve/engine'
4
+
5
+ class EngineTest < Minitest::Test
6
+
7
+ def setup
8
+ @scheduler = mock('object')
9
+ @actor = mock('object')
10
+ @engine = Engine.new @scheduler
11
+ end
12
+
13
+ def test_create_engine_without_scheduler_fails
14
+ assert_raises RuntimeError do
15
+ Engine.new nil
16
+ end
17
+ end
18
+
19
+ def test_engine_initially_locked
20
+ assert @engine.locked?
21
+ end
22
+
23
+ def test_unlock_with_no_actors_calls_scheduler_then_relocks
24
+ @scheduler.expects(:next).returns(nil)
25
+ @engine.unlock
26
+ assert @engine.locked?
27
+ end
28
+
29
+ def test_scheduled_actor_acts_when_unlocked
30
+ @scheduler.expects(:next).twice.returns(@actor).returns(nil)
31
+ @actor.expects(:act)
32
+ @engine.unlock
33
+ assert @engine.locked?
34
+ end
35
+
36
+ end