smash_and_grab 0.0.1alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +0 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +61 -0
- data/README.md +92 -0
- data/Rakefile +69 -0
- data/bin/smash_and_grab +3 -0
- data/bin/smash_and_grab.rbw +3 -0
- data/config/gui/schema.yml +61 -0
- data/config/levels/01_bank.sgl +0 -0
- data/config/map/entities.yml +373 -0
- data/config/map/objects.yml +14 -0
- data/config/map/tiles.yml +46 -0
- data/config/map/vehicles.yml +19 -0
- data/config/map/walls.yml +77 -0
- data/lib/smash_and_grab/abilities/ability.rb +104 -0
- data/lib/smash_and_grab/abilities/area.rb +37 -0
- data/lib/smash_and_grab/abilities/melee.rb +39 -0
- data/lib/smash_and_grab/abilities/move.rb +32 -0
- data/lib/smash_and_grab/abilities/ranged.rb +34 -0
- data/lib/smash_and_grab/abilities/sprint.rb +42 -0
- data/lib/smash_and_grab/abilities.rb +10 -0
- data/lib/smash_and_grab/fidgit_ext/container.rb +10 -0
- data/lib/smash_and_grab/fidgit_ext/cursor.rb +7 -0
- data/lib/smash_and_grab/fidgit_ext/element.rb +27 -0
- data/lib/smash_and_grab/game_window.rb +27 -0
- data/lib/smash_and_grab/gosu_ext/font.rb +39 -0
- data/lib/smash_and_grab/gui/editor_selector.rb +174 -0
- data/lib/smash_and_grab/gui/entity_summary.rb +58 -0
- data/lib/smash_and_grab/gui/info_panel.rb +105 -0
- data/lib/smash_and_grab/gui/minimap.rb +92 -0
- data/lib/smash_and_grab/history/action_history.rb +60 -0
- data/lib/smash_and_grab/history/editor_action_history.rb +21 -0
- data/lib/smash_and_grab/history/editor_actions/erase_object.rb +20 -0
- data/lib/smash_and_grab/history/editor_actions/place_object.rb +34 -0
- data/lib/smash_and_grab/history/editor_actions/set_tile_type.rb +18 -0
- data/lib/smash_and_grab/history/editor_actions/set_wall_type.rb +18 -0
- data/lib/smash_and_grab/history/game_action_history.rb +43 -0
- data/lib/smash_and_grab/history/game_actions/ability.rb +26 -0
- data/lib/smash_and_grab/history/game_actions/end_turn.rb +18 -0
- data/lib/smash_and_grab/log.rb +30 -0
- data/lib/smash_and_grab/main.rb +75 -0
- data/lib/smash_and_grab/map/faction.rb +84 -0
- data/lib/smash_and_grab/map/map.rb +262 -0
- data/lib/smash_and_grab/map/tile.rb +181 -0
- data/lib/smash_and_grab/map/wall.rb +139 -0
- data/lib/smash_and_grab/mouse_selection.rb +154 -0
- data/lib/smash_and_grab/objects/entity.rb +359 -0
- data/lib/smash_and_grab/objects/floating_text.rb +27 -0
- data/lib/smash_and_grab/objects/static.rb +47 -0
- data/lib/smash_and_grab/objects/vehicle.rb +100 -0
- data/lib/smash_and_grab/objects/world_object.rb +94 -0
- data/lib/smash_and_grab/path.rb +147 -0
- data/lib/smash_and_grab/players/player.rb +71 -0
- data/lib/smash_and_grab/sprite_sheet.rb +16 -0
- data/lib/smash_and_grab/states/edit_level.rb +180 -0
- data/lib/smash_and_grab/states/main_menu.rb +71 -0
- data/lib/smash_and_grab/states/play_level.rb +148 -0
- data/lib/smash_and_grab/states/world.rb +216 -0
- data/lib/smash_and_grab/std_ext/array.rb +18 -0
- data/lib/smash_and_grab/std_ext/hash.rb +18 -0
- data/lib/smash_and_grab/texplay_ext/color.rb +7 -0
- data/lib/smash_and_grab/texplay_ext/image.rb +146 -0
- data/lib/smash_and_grab/texplay_ext/window.rb +10 -0
- data/lib/smash_and_grab/version.rb +3 -0
- data/lib/smash_and_grab/z_order.rb +12 -0
- data/lib/smash_and_grab/z_order_recorder.rb +59 -0
- data/lib/smash_and_grab.rb +107 -0
- data/media/fonts/UnmaskedBB.ttf +0 -0
- data/media/fonts/fontinfo.txt +25 -0
- data/media/icon.ico +0 -0
- data/media/images/entities.png +0 -0
- data/media/images/entity_portraits.png +0 -0
- data/media/images/floor_tiles.png +0 -0
- data/media/images/mouse_cursor.png +0 -0
- data/media/images/mouse_hover.png +0 -0
- data/media/images/mouse_hover_wall.png +0 -0
- data/media/images/objects.png +0 -0
- data/media/images/path.png +0 -0
- data/media/images/tile_selection.png +0 -0
- data/media/images/vehicles.png +0 -0
- data/media/images/walls.png +0 -0
- data/smash_and_grab.gemspec +35 -0
- data/test/smash_and_grab/abilities/helpers/ability_helper.rb +6 -0
- data/test/smash_and_grab/abilities/melee_test.rb +105 -0
- data/test/smash_and_grab/abilities/move_test.rb +87 -0
- data/test/smash_and_grab/abilities/sprint_test.rb +75 -0
- data/test/smash_and_grab/map/faction_test.rb +62 -0
- data/test/smash_and_grab/map/map_test.rb +114 -0
- data/test/smash_and_grab/map/tile_test.rb +17 -0
- data/test/smash_and_grab/map/wall_test.rb +5 -0
- data/test/smash_and_grab/std_ext/hash_test.rb +21 -0
- data/test/teststrap.rb +108 -0
- 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,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
|