smash_and_grab 0.0.1alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG.txt +0 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +61 -0
  4. data/README.md +92 -0
  5. data/Rakefile +69 -0
  6. data/bin/smash_and_grab +3 -0
  7. data/bin/smash_and_grab.rbw +3 -0
  8. data/config/gui/schema.yml +61 -0
  9. data/config/levels/01_bank.sgl +0 -0
  10. data/config/map/entities.yml +373 -0
  11. data/config/map/objects.yml +14 -0
  12. data/config/map/tiles.yml +46 -0
  13. data/config/map/vehicles.yml +19 -0
  14. data/config/map/walls.yml +77 -0
  15. data/lib/smash_and_grab/abilities/ability.rb +104 -0
  16. data/lib/smash_and_grab/abilities/area.rb +37 -0
  17. data/lib/smash_and_grab/abilities/melee.rb +39 -0
  18. data/lib/smash_and_grab/abilities/move.rb +32 -0
  19. data/lib/smash_and_grab/abilities/ranged.rb +34 -0
  20. data/lib/smash_and_grab/abilities/sprint.rb +42 -0
  21. data/lib/smash_and_grab/abilities.rb +10 -0
  22. data/lib/smash_and_grab/fidgit_ext/container.rb +10 -0
  23. data/lib/smash_and_grab/fidgit_ext/cursor.rb +7 -0
  24. data/lib/smash_and_grab/fidgit_ext/element.rb +27 -0
  25. data/lib/smash_and_grab/game_window.rb +27 -0
  26. data/lib/smash_and_grab/gosu_ext/font.rb +39 -0
  27. data/lib/smash_and_grab/gui/editor_selector.rb +174 -0
  28. data/lib/smash_and_grab/gui/entity_summary.rb +58 -0
  29. data/lib/smash_and_grab/gui/info_panel.rb +105 -0
  30. data/lib/smash_and_grab/gui/minimap.rb +92 -0
  31. data/lib/smash_and_grab/history/action_history.rb +60 -0
  32. data/lib/smash_and_grab/history/editor_action_history.rb +21 -0
  33. data/lib/smash_and_grab/history/editor_actions/erase_object.rb +20 -0
  34. data/lib/smash_and_grab/history/editor_actions/place_object.rb +34 -0
  35. data/lib/smash_and_grab/history/editor_actions/set_tile_type.rb +18 -0
  36. data/lib/smash_and_grab/history/editor_actions/set_wall_type.rb +18 -0
  37. data/lib/smash_and_grab/history/game_action_history.rb +43 -0
  38. data/lib/smash_and_grab/history/game_actions/ability.rb +26 -0
  39. data/lib/smash_and_grab/history/game_actions/end_turn.rb +18 -0
  40. data/lib/smash_and_grab/log.rb +30 -0
  41. data/lib/smash_and_grab/main.rb +75 -0
  42. data/lib/smash_and_grab/map/faction.rb +84 -0
  43. data/lib/smash_and_grab/map/map.rb +262 -0
  44. data/lib/smash_and_grab/map/tile.rb +181 -0
  45. data/lib/smash_and_grab/map/wall.rb +139 -0
  46. data/lib/smash_and_grab/mouse_selection.rb +154 -0
  47. data/lib/smash_and_grab/objects/entity.rb +359 -0
  48. data/lib/smash_and_grab/objects/floating_text.rb +27 -0
  49. data/lib/smash_and_grab/objects/static.rb +47 -0
  50. data/lib/smash_and_grab/objects/vehicle.rb +100 -0
  51. data/lib/smash_and_grab/objects/world_object.rb +94 -0
  52. data/lib/smash_and_grab/path.rb +147 -0
  53. data/lib/smash_and_grab/players/player.rb +71 -0
  54. data/lib/smash_and_grab/sprite_sheet.rb +16 -0
  55. data/lib/smash_and_grab/states/edit_level.rb +180 -0
  56. data/lib/smash_and_grab/states/main_menu.rb +71 -0
  57. data/lib/smash_and_grab/states/play_level.rb +148 -0
  58. data/lib/smash_and_grab/states/world.rb +216 -0
  59. data/lib/smash_and_grab/std_ext/array.rb +18 -0
  60. data/lib/smash_and_grab/std_ext/hash.rb +18 -0
  61. data/lib/smash_and_grab/texplay_ext/color.rb +7 -0
  62. data/lib/smash_and_grab/texplay_ext/image.rb +146 -0
  63. data/lib/smash_and_grab/texplay_ext/window.rb +10 -0
  64. data/lib/smash_and_grab/version.rb +3 -0
  65. data/lib/smash_and_grab/z_order.rb +12 -0
  66. data/lib/smash_and_grab/z_order_recorder.rb +59 -0
  67. data/lib/smash_and_grab.rb +107 -0
  68. data/media/fonts/UnmaskedBB.ttf +0 -0
  69. data/media/fonts/fontinfo.txt +25 -0
  70. data/media/icon.ico +0 -0
  71. data/media/images/entities.png +0 -0
  72. data/media/images/entity_portraits.png +0 -0
  73. data/media/images/floor_tiles.png +0 -0
  74. data/media/images/mouse_cursor.png +0 -0
  75. data/media/images/mouse_hover.png +0 -0
  76. data/media/images/mouse_hover_wall.png +0 -0
  77. data/media/images/objects.png +0 -0
  78. data/media/images/path.png +0 -0
  79. data/media/images/tile_selection.png +0 -0
  80. data/media/images/vehicles.png +0 -0
  81. data/media/images/walls.png +0 -0
  82. data/smash_and_grab.gemspec +35 -0
  83. data/test/smash_and_grab/abilities/helpers/ability_helper.rb +6 -0
  84. data/test/smash_and_grab/abilities/melee_test.rb +105 -0
  85. data/test/smash_and_grab/abilities/move_test.rb +87 -0
  86. data/test/smash_and_grab/abilities/sprint_test.rb +75 -0
  87. data/test/smash_and_grab/map/faction_test.rb +62 -0
  88. data/test/smash_and_grab/map/map_test.rb +114 -0
  89. data/test/smash_and_grab/map/tile_test.rb +17 -0
  90. data/test/smash_and_grab/map/wall_test.rb +5 -0
  91. data/test/smash_and_grab/std_ext/hash_test.rb +21 -0
  92. data/test/teststrap.rb +108 -0
  93. metadata +226 -0
@@ -0,0 +1,107 @@
1
+ require 'optparse'
2
+
3
+ begin
4
+ EXTRACT_PATH = File.dirname(File.dirname(File.expand_path(__FILE__)))
5
+
6
+ ROOT_PATH = if ENV['OCRA_EXECUTABLE']
7
+ File.dirname(File.expand_path(ENV['OCRA_EXECUTABLE']))
8
+ elsif defined? OSX_EXECUTABLE_FOLDER
9
+ File.dirname(OSX_EXECUTABLE_FOLDER)
10
+ else
11
+ EXTRACT_PATH
12
+ end
13
+
14
+ APP_NAME = File.basename(__FILE__).chomp(File.extname(__FILE__))
15
+
16
+ RUNNING_FROM_EXECUTABLE = (ENV['OCRA_EXECUTABLE'] or defined?(OSX_EXECUTABLE))
17
+
18
+ DEFAULT_LOG_FILE = "#{APP_NAME}.log"
19
+ DEFAULT_LOG_FILE_PATH = File.join(ROOT_PATH, DEFAULT_LOG_FILE)
20
+
21
+ def parse_options
22
+ options = {}
23
+
24
+ OptionParser.new do |parser|
25
+ parser.banner =<<TEXT
26
+ Usage: #{File.basename(__FILE__)} [options]
27
+
28
+ Defaults to using --#{RUNNING_FROM_EXECUTABLE ? 'log' : 'console'}
29
+
30
+ TEXT
31
+
32
+ parser.on('-?', '-h', '--help', 'Display this screen') do
33
+ puts parser
34
+ exit
35
+ end
36
+
37
+ options[:dev] = false
38
+ parser.on('--dev', 'Development mode') do
39
+ options[:dev] = true
40
+ end
41
+
42
+ parser.on('--console', 'Console mode (no log file)') do
43
+ options[:log] = nil # Write to console.
44
+ end
45
+
46
+ parser.on('--log [FILE]', "Write log to a file (defaults to '#{DEFAULT_LOG_FILE}')") do |file|
47
+ options[:log] = file ? file : DEFAULT_LOG_FILE_PATH
48
+ end
49
+
50
+ parser.on('--timestamp', "Adds a timestamp to the log file") do
51
+ options[:timestamp] = true
52
+ end
53
+
54
+ begin
55
+ parser.parse!
56
+ rescue OptionParser::ParseError => ex
57
+ puts "ERROR: #{ex.message}"
58
+ puts
59
+ puts parser
60
+ exit
61
+ end
62
+ end
63
+
64
+ options
65
+ end
66
+
67
+ options = parse_options
68
+
69
+ # Default to console mode normally; default to logfile when running executable.
70
+ if RUNNING_FROM_EXECUTABLE and not options.has_key?(:log)
71
+ options[:log] = DEFAULT_LOG_FILE_PATH
72
+ end
73
+
74
+ LOG_FILE = options[:log]
75
+ DEVELOPMENT_MODE = options[:dev]
76
+
77
+ ENV['PATH'] = File.join(EXTRACT_PATH, 'bin') + File::PATH_SEPARATOR + ENV['PATH']
78
+
79
+ if LOG_FILE
80
+ # Add a timestamp to the end of the log file-name.
81
+ if options[:timestamp]
82
+ LOG_FILE.sub!(/(\.\w+)$/, "_#{Time.now.to_s.gsub(/[^\d]/, "_")}_#{Time.now.usec.to_s.rjust(6, '0')}\\1")
83
+ end
84
+
85
+ puts "Redirecting output to '#{LOG_FILE}'"
86
+
87
+ original_stderr = $stderr.dup
88
+ $stderr.reopen LOG_FILE
89
+ $stderr.sync = true
90
+
91
+ original_stdout = $stdout.dup
92
+ $stdout.reopen LOG_FILE
93
+ $stdout.sync = true
94
+ end
95
+
96
+ require_relative "smash_and_grab/main"
97
+
98
+ exit_message = ""
99
+
100
+ rescue => ex
101
+ $stderr.puts "FATAL ERROR - #{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}"
102
+ raise ex # Just to make sure that the user sees the error in the CLI/IDE too.
103
+ ensure
104
+ $stderr.reopen(original_stderr) if defined?(original_stderr) and original_stderr
105
+ $stderr.puts exit_message if exit_message
106
+ $stdout.reopen(original_stdout) if defined?(original_stdout) and original_stdout
107
+ end
Binary file
@@ -0,0 +1,25 @@
1
+ This font is � 2010 Nate Piekos. All Rights Reserved.
2
+ Created for Blambot Fonts
3
+
4
+ This font is freeware for independent comic book creation and
5
+ non-profit use ONLY. This excludes use by "mainstream" publishers
6
+ (Marvel, DC, Dark Horse, Oni, Image, SLG, Top Cow, Crossgen and their
7
+ subsidiaries) without a license fee. Use by a "mainstream" publisher
8
+ (or its employee) and use for commercial non-comic book production
9
+ (e.g. magazine ads, merchandise labels) requires a license fee
10
+ be paid to the designer, Nate Piekos.
11
+ This font may not be redistributed without the author's permission and
12
+ must always include this text file in the .zip, .sit or .hqx.
13
+
14
+ Blambot/Nate Piekos makes no guarantees about these font files,
15
+ the completeness of character sets, or safety of these files on your
16
+ computer. By installing these fonts on your system, you prove that
17
+ you have read and understand the above.
18
+
19
+ If you have any questions, visit http://www.blambot.com/license.shtml
20
+
21
+ For more free and original fonts visit Blambot.
22
+ www.blambot.com
23
+
24
+ Nate Piekos
25
+ studio@blambot.com
data/media/icon.ico ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
+ require "smash_and_grab/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "smash_and_grab"
7
+ s.version = SmashAndGrab::VERSION
8
+
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Bil Bas (Spooner)"]
11
+ s.email = ["bil.bagpuss@gmail.com"]
12
+ s.homepage = "http://spooner.github.com/games/smash_and_grab/"
13
+ s.summary = %q{Turn-based isometric heist game}
14
+ s.description = <<END
15
+ #{s.summary}
16
+ END
17
+
18
+ s.files = `git ls-files`.split("\n").reject {|f| f =~ /^(?:\.|raw_media|build)/ }
19
+ s.licenses = ["MIT"]
20
+ s.rubyforge_project = "smash_and_grab"
21
+
22
+ s.executable = "smash_and_grab"
23
+ s.test_files = Dir["test/**/*_test.rb"]
24
+ s.required_ruby_version = "~> 1.9.2"
25
+
26
+ s.add_runtime_dependency "gosu", "~> 0.7.41"
27
+ s.add_runtime_dependency "chingu", "~> 0.9rc7"
28
+ s.add_runtime_dependency "fidgit", "~> 0.1.10"
29
+ s.add_runtime_dependency "texplay", "~> 0.3"
30
+ #s.add_runtime_dependency "r18n-desktop", "~> 0.4.9"
31
+
32
+ s.add_development_dependency "releasy", "~> 0.2.2"
33
+ s.add_development_dependency "rake", "~> 0.9.2.2"
34
+ s.add_development_dependency "bacon-rr", "~> 0.1.0"
35
+ end
@@ -0,0 +1,6 @@
1
+ shared SmashAndGrab::Abilities::Ability do
2
+ should "behave like an Abilities::Ability" do
3
+ subject.should.be.kind_of SmashAndGrab::Abilities::Ability
4
+ [true, false].should.include subject.can_be_undone?
5
+ end
6
+ end
@@ -0,0 +1,105 @@
1
+ require_relative "../../teststrap"
2
+ require_relative "helpers/ability_helper"
3
+
4
+ describe SmashAndGrab::Abilities::Melee do
5
+ helper(:entity) {@entity ||= Object.new }
6
+ helper(:enemy) { @enemy ||= Object.new }
7
+ helper(:tile) { @tile ||= SmashAndGrab::Tile.new(:grass, nil, 1, 1) }
8
+
9
+ subject { SmashAndGrab::Abilities.ability entity, type: :melee, action_cost: 1, skill: 5 }
10
+
11
+ behaves_like SmashAndGrab::Abilities::Ability
12
+
13
+ should "fail if not given the required arguments" do
14
+ ->{ SmashAndGrab::Abilities.ability entity, type: :melee }.should.raise(ArgumentError).message.should.match /No skill value for/
15
+ end
16
+
17
+ should "be initialized" do
18
+ subject.owner.should.equal entity
19
+ subject.can_be_undone?.should.be.false
20
+ subject.skill.should.equal 5
21
+ subject.action_cost.should.equal 1
22
+ end
23
+
24
+ should "serialize to json correctly" do
25
+ JSON.parse(subject.to_json).symbolize.should.equal(
26
+ type: :melee,
27
+ skill: 5,
28
+ action_cost: 1
29
+ )
30
+ end
31
+
32
+ should "generate appropriate action_data" do
33
+ stub(entity).id.returns 12
34
+ stub(enemy).id.returns 13
35
+ stub(tile).object.returns enemy
36
+ stub(subject).random_damage.returns 5
37
+ subject.action_data(tile).should.equal(
38
+ ability: :melee,
39
+ skill: 5,
40
+ action_cost: 1,
41
+
42
+ owner_id: 12,
43
+ target_id: 13,
44
+ target_position: [1, 1],
45
+ damage: 5
46
+ )
47
+ end
48
+
49
+ describe "#random_damage" do
50
+ should "never give a value greater than skill" do
51
+ stub(subject).rand(is_a(Integer)) {|x| x - 1 }
52
+ subject.random_damage == 5
53
+ end
54
+
55
+ should "never give a value less than 1" do
56
+ stub(subject).rand(is_a(Integer)) { 0 }
57
+ subject.random_damage == 1
58
+ end
59
+ end
60
+
61
+ describe "#do" do
62
+ should "remove action points and health" do
63
+ stub(enemy).health.returns 20
64
+ mock(enemy, :health=).with 15
65
+
66
+ stub(entity).map.stub!.object_by_id(13).returns enemy
67
+ stub(entity).action_points.returns 1
68
+ mock(entity, :action_points=).with 0
69
+
70
+ subject.do action_cost: 1, target_id: 13, damage: 5 #, target_position: [1, 1]
71
+ true
72
+ end
73
+ end
74
+
75
+ describe "#undo" do
76
+ should "give action points and health (if target alive)" do
77
+ stub(enemy).tile.returns tile
78
+ stub(enemy).health.returns 15
79
+ mock(enemy, :health=).with 20
80
+
81
+ stub(entity).map.stub!.object_by_id(13).returns enemy
82
+ stub(entity).action_points.returns 0
83
+ mock(entity, :action_points=).with 1
84
+
85
+ subject.undo action_cost: 1, target_id: 13, damage: 5, target_position: [1, 1]
86
+ end
87
+
88
+ should "give action points, health and return to map (if target dead)" do
89
+ stub(enemy).tile.returns nil
90
+ stub(enemy).health.returns 0
91
+ mock(enemy, :tile=).with tile
92
+ mock(enemy, :health=).with 5
93
+
94
+ stub(entity).map do
95
+ map = Object.new
96
+ stub(map).object_by_id(13).returns enemy
97
+ stub(map).tile_at_grid([1, 1]).returns tile
98
+ end
99
+ stub(entity).action_points.returns 0
100
+ mock(entity, :action_points=).with 1
101
+
102
+ subject.undo action_cost: 1, target_id: 13, damage: 5, target_position: [1, 1]
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,87 @@
1
+ require_relative "../../teststrap"
2
+ require_relative "helpers/ability_helper"
3
+
4
+ describe SmashAndGrab::Abilities::Move do
5
+ helper :tile do |i|
6
+ @tiles ||= Hash.new do |hash, key|
7
+ hash[key] = SmashAndGrab::Tile.new(:grass, nil, 0, key)
8
+ end
9
+ @tiles[i]
10
+ end
11
+
12
+ helper(:entity) { @entity ||= Object.new }
13
+ helper(:tiles) { [tile(0), tile(1), tile(2)] }
14
+ helper(:tile_positions) { tiles.map {|t| t.grid_position } }
15
+
16
+ subject { SmashAndGrab::Abilities.ability entity, type: :move }
17
+
18
+ behaves_like SmashAndGrab::Abilities::Ability
19
+
20
+ should "be initialized" do
21
+ subject.owner.should.equal entity
22
+ subject.can_be_undone?.should.be.true
23
+ subject.skill.should.equal 0
24
+ subject.action_cost.should.equal 0
25
+ end
26
+
27
+ should "serialize to json correctly" do
28
+ JSON.parse(subject.to_json).symbolize.should.equal(
29
+ type: :move,
30
+ skill: 0, # TODO: Irrelevant for move?
31
+ action_cost: 0 # TODO: Irrelevant for move? Not sure; perhaps some entities can move OR attack?
32
+ )
33
+ end
34
+
35
+ should "generate appropriate action_data" do
36
+ stub(subject.owner).id.returns 12 # Don't know why I need to repeat this.
37
+ path = Object.new
38
+ mock(path).tiles.returns tiles
39
+ mock(path).move_distance.returns 3
40
+ mock(path).last.returns tiles.last
41
+ mock(tiles.last).object.returns nil
42
+ subject.action_data(path).should.equal(
43
+ ability: :move,
44
+ skill: 0, # TODO: Irrelevant for move?
45
+ action_cost: 0, # TODO: Irrelevant for move? Not sure; perhaps some entities can move OR attack?
46
+
47
+ owner_id: 12,
48
+ movement_cost: 3,
49
+ target_id: nil, # TODO: Irrelevant for move?
50
+ target_position: [0, 2], # TODO: Irrelevant for move?
51
+ path: [[0, 0], [0, 1], [0, 2]]
52
+ )
53
+ end
54
+
55
+ describe "#target_valid?" do
56
+ should "if target contains an object" do
57
+ mock(tile(2)).empty?.returns false
58
+ subject.target_valid?(tile(2)).should.be.false
59
+ end
60
+
61
+ should "if target is an empty tile without a path" do
62
+ mock(tile(2)).empty?.returns true
63
+ mock(entity).path_to(tile(2)).returns nil
64
+ subject.target_valid?(tile(2)).should.be.false
65
+ end
66
+
67
+ should "if target is an empty tile with a path" do
68
+ mock(tile(2)).empty?.returns true
69
+ mock(entity).path_to(tile(2)).returns tiles
70
+ subject.target_valid?(tile(2)).should.be.true
71
+ end
72
+ end
73
+
74
+ describe "#do" do
75
+ should "move the entity forwards" do
76
+ mock(entity).move tile_positions, 4
77
+ subject.do action_cost: 0, path: tile_positions, movement_cost: 4
78
+ end
79
+ end
80
+
81
+ describe "#undo" do
82
+ should "move the entity backwards" do
83
+ mock(entity).move tile_positions.reverse, -4
84
+ subject.undo action_cost: 0, path: tile_positions, movement_cost: 4
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,75 @@
1
+ require_relative "../../teststrap"
2
+ require_relative "helpers/ability_helper"
3
+
4
+ describe SmashAndGrab::Abilities::Sprint do
5
+ helper(:entity) { @entity ||= Object.new }
6
+
7
+ subject { SmashAndGrab::Abilities.ability entity, type: :sprint, skill: 3 }
8
+
9
+ behaves_like SmashAndGrab::Abilities::Ability
10
+
11
+ should "fail if not given the required arguments" do
12
+ ->{ SmashAndGrab::Abilities.ability entity, type: :sprint }.should.raise(ArgumentError).message.should.match /No skill value for/
13
+ end
14
+
15
+ should "be initialized" do
16
+ subject.owner.should.equal entity
17
+ subject.can_be_undone?.should.be.true
18
+ subject.skill.should.equal 3
19
+
20
+ stub(entity).max_action_points.returns 2
21
+ subject.action_cost.should.equal 2
22
+ end
23
+
24
+ should "serialize to json correctly" do
25
+ JSON.parse(subject.to_json).symbolize.should.equal(
26
+ type: :sprint,
27
+ skill: 3,
28
+ action_cost: :all,
29
+ )
30
+ end
31
+
32
+ should "generate appropriate action_data" do
33
+ mock(entity).id.returns 12
34
+ mock(entity).max_movement_points.returns 11
35
+ mock(entity).max_action_points.returns 2
36
+ subject.action_data.should.equal(
37
+ ability: :sprint,
38
+ skill: 3,
39
+ action_cost: 2,
40
+
41
+ owner_id: 12,
42
+ movement_bonus: 5
43
+ )
44
+ end
45
+
46
+ describe "owner has max_mp == 100" do
47
+ { 1 => 1, 2 => 25, 3 => 50, 4 => 75, 5 => 100 }.each do |skill, expected_bonus|
48
+ should "have #movement_bonus == #{expected_bonus} with #skill == #{skill}" do
49
+ mock(entity).max_movement_points.returns 100
50
+ mock(subject).skill.returns skill
51
+ subject.movement_bonus.should.equal expected_bonus
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#do" do
57
+ should "increase movement points and decrease action points" do
58
+ stub(entity).action_points.returns 2
59
+ mock(entity, :action_points=).with 0
60
+ mock(entity).movement_points.returns 5
61
+ mock(entity, :movement_points=).with 10
62
+ subject.do action_cost: 2, movement_bonus: 5
63
+ end
64
+ end
65
+
66
+ describe "#undo" do
67
+ should "decrease movement points and increase action points" do
68
+ stub(entity).action_points.returns 0
69
+ mock(entity, :action_points=).with 2
70
+ stub(entity).movement_points.returns 10
71
+ mock(entity, :movement_points=).with 5
72
+ subject.undo action_cost: 2, movement_bonus: 5
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,62 @@
1
+ require_relative "../../teststrap"
2
+
3
+ shared SmashAndGrab::Factions::Faction do
4
+ should "not be active" do
5
+ subject.should.not.be.active
6
+ end
7
+
8
+ should "have no entities" do
9
+ subject.entities.should.be.kind_of Array
10
+ subject.entities.should.be.empty
11
+ end
12
+ end
13
+
14
+ describe SmashAndGrab::Factions::Faction do
15
+ helper(:baddies) { SmashAndGrab::Factions::Baddies.new nil }
16
+ helper(:goodies) { SmashAndGrab::Factions::Goodies.new nil }
17
+ helper(:bystanders) { SmashAndGrab::Factions::Bystanders.new nil }
18
+
19
+ subject { described.new nil }
20
+
21
+ describe SmashAndGrab::Factions::Goodies do
22
+ behaves_like SmashAndGrab::Factions::Faction
23
+
24
+ should "dislike baddies" do
25
+ subject.should.be.enemy? baddies
26
+ subject.should.not.be.friend? baddies
27
+ end
28
+
29
+ should "like bystanders" do
30
+ subject.should.not.be.enemy? bystanders
31
+ subject.should.be.friend? bystanders
32
+ end
33
+ end
34
+
35
+ describe SmashAndGrab::Factions::Baddies do
36
+ behaves_like SmashAndGrab::Factions::Faction
37
+
38
+ should "dislike goodies" do
39
+ subject.should.be.enemy? goodies
40
+ subject.should.not.be.friend? goodies
41
+ end
42
+
43
+ should "dislike bystanders" do
44
+ subject.should.be.enemy? bystanders
45
+ subject.should.not.be.friend? bystanders
46
+ end
47
+ end
48
+
49
+ describe SmashAndGrab::Factions::Bystanders do
50
+ behaves_like SmashAndGrab::Factions::Faction
51
+
52
+ should "like goodies" do
53
+ subject.should.not.be.enemy? goodies
54
+ subject.should.be.friend? goodies
55
+ end
56
+
57
+ should "dislike baddies" do
58
+ subject.should.be.enemy? baddies
59
+ subject.should.not.be.friend? baddies
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,114 @@
1
+ require_relative "../../teststrap"
2
+
3
+ describe SmashAndGrab::Map do
4
+ helper :objects_data do
5
+ [
6
+ {
7
+ "class" => "entity",
8
+ "type" => "professor_goggles",
9
+ "id" => 0,
10
+ "health" => 8,
11
+ "movement_points" => 7,
12
+ "action_points" => 1,
13
+ "facing" => "left",
14
+ "tile" => [
15
+ 1,
16
+ 0
17
+ ],
18
+ },
19
+ {
20
+ "class" => "object",
21
+ "type" => "tree",
22
+ "id" => 1,
23
+ "tile" => [
24
+ 0,
25
+ 1
26
+ ]
27
+ }
28
+ ]
29
+ end
30
+
31
+ helper :walls_data do
32
+ [
33
+ {
34
+ "type" => "low_fence",
35
+ "tiles" => [
36
+ [
37
+ 0,
38
+ 0
39
+ ],
40
+ [
41
+ 0,
42
+ 1
43
+ ]
44
+ ]
45
+ }
46
+ ]
47
+ end
48
+
49
+ helper :tiles_data do
50
+ [
51
+ ['grass', 'concrete'],
52
+ ['dirt', 'dirt'],
53
+ ]
54
+ end
55
+
56
+ helper :map_data do
57
+ {
58
+ 'tiles' => tiles_data,
59
+ 'objects' => objects_data,
60
+ 'actions' => [],
61
+ 'walls' => walls_data
62
+ }
63
+ end
64
+
65
+ subject { SmashAndGrab::Map.new map_data.symbolize }
66
+
67
+ describe "#tile_at_grid" do
68
+ should "find the correct tile" do
69
+ subject.tile_at_grid(0, 0).type.should.equal :grass
70
+ subject.tile_at_grid(1, 0).type.should.equal :concrete
71
+ end
72
+
73
+ should "return nil for positions outside the grid" do
74
+ subject.tile_at_grid(-1, 0).should.be.nil
75
+ subject.tile_at_grid(2, 0).should.be.nil
76
+ end
77
+ end
78
+
79
+ describe "#tile_at_position" do
80
+ should "find the correct tile" do
81
+ subject.tile_at_position(0, 0).type.should.equal :grass
82
+ subject.tile_at_position(4, 8).type.should.equal :dirt
83
+ end
84
+
85
+ should "return nil outside the grid" do
86
+ subject.tile_at_position(-8, -8).should.be.nil
87
+ subject.tile_at_position(64, 0).should.be.nil
88
+ end
89
+ end
90
+
91
+ describe "#objects" do
92
+ should "give correct object" do
93
+ subject.object_by_id(0).id.should.equal 0
94
+ subject.object_by_id(1).id.should.equal 1
95
+ end
96
+
97
+ should "raise error with bad id" do
98
+ ->{ subject.object_by_id(-1) }.should.raise(RuntimeError)
99
+ ->{ subject.object_by_id(2) }.should.raise(RuntimeError)
100
+ end
101
+ end
102
+
103
+ describe "#save_data" do
104
+ subject { SmashAndGrab::Map.new(map_data.symbolize).save_data }
105
+
106
+ should "contain the same data as was loaded" do
107
+ subject[:version].should.equal SmashAndGrab::VERSION
108
+ subject[:map_size].should.equal [2, 2]
109
+ JSON.parse(subject[:tiles].to_json).should.equal tiles_data
110
+ JSON.parse(subject[:walls].to_json).should.equal walls_data
111
+ JSON.parse(subject[:objects].to_json).should.equal objects_data
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "../../teststrap"
2
+
3
+ describe SmashAndGrab::Tile do
4
+ subject { described.new :grass, nil, 0, 0 }
5
+
6
+ should "have correct initial state" do
7
+ subject.type.should.equal :grass
8
+ subject.x.should.equal 0
9
+ subject.y.should.equal 0
10
+ subject.grid_x.should.equal 0
11
+ subject.grid_y.should.equal 0
12
+ subject.minimap_color.should.be.kind_of Gosu::Color
13
+ subject.movement_cost.should.be.kind_of Integer
14
+ subject.image.should.be.kind_of Gosu::Image
15
+ subject.to_json.should.equal "\"grass\""
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ require_relative "../../teststrap"
2
+
3
+ describe SmashAndGrab::Wall do
4
+
5
+ end