Skip to content

Commit

Permalink
Split up location modules into separate files and improve passible logic
Browse files Browse the repository at this point in the history
  • Loading branch information
David Henry committed Feb 13, 2012
1 parent 7470530 commit a8388af
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 121 deletions.
13 changes: 6 additions & 7 deletions lib/game/location.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
require 'lib/game/location/modules'
require 'lib/game/location/wall'
require 'lib/game/location/movement'
require 'lib/game/location/passible'

require 'lib/game/location/edge'
require 'lib/game/location/empty'
require 'lib/game/location/wall'

class Game
class Location
include Game::Modules::ObjectManagement
include Game::Location::Base
include Game::Location::Passible
include Game::Location::Movement

EMPTY_CELL = 0
WALL_90 = 1
WALL_CORNER_LEFT = 4
Expand All @@ -28,7 +27,7 @@ def class_for(location_type)
WALL_CORNER_LEFT, WALL_CORNER
Wall
when EMPTY_CELL
self
Empty
else
raise 'unknown???'
end
Expand Down
11 changes: 11 additions & 0 deletions lib/game/location/empty.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Game
class Location
class Empty
include Game::Modules::ObjectManagement
include Game::Location::Base
include Game::Location::Passible
include Game::Location::Movement

end
end
end
22 changes: 1 addition & 21 deletions lib/game/location/modules.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
class Game
class Location
module Movement
def at(direction)
tile = Game::Location.at(@x - 1, @y) if direction == :up
tile = Game::Location.at(@x + 1, @y) if direction == :down
tile = Game::Location.at(@x, @y - 1) if direction == :left
tile = Game::Location.at(@x, @y + 1) if direction == :right

tile.try(:end_point) || Game::Location::Edge.instance
end

def end_point
if has_object?(Game::Object::LocationModifier)
Game::Location.at(*get_object(Game::Object::LocationModifier).end_point)
else
self
end
end
private :end_point
end

module Impassible
def passible?(player_objects)
false
Expand All @@ -28,7 +8,7 @@ def passible?(player_objects)

module Passible
def passible?(player_objects)
true
objects.all?(&:passible?)
end
end

Expand Down
23 changes: 23 additions & 0 deletions lib/game/location/movement.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Game
class Location
module Movement
def at(direction)
tile = Game::Location.at(@x - 1, @y) if direction == :up
tile = Game::Location.at(@x + 1, @y) if direction == :down
tile = Game::Location.at(@x, @y - 1) if direction == :left
tile = Game::Location.at(@x, @y + 1) if direction == :right

tile.try(:end_point) || Game::Location::Edge.instance
end

def end_point
if has_object?(Game::Object::LocationModifier)
Game::Location.at(*get_object(Game::Object::LocationModifier).end_point)
else
self
end
end
private :end_point
end
end
end
9 changes: 9 additions & 0 deletions lib/game/location/passible.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Game
class Location
module Passible
def passible?(player_objects)
objects.all?(&:passible?)
end
end
end
end
4 changes: 2 additions & 2 deletions lib/game/location/wall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ def passible?(player_objects)
return false unless has_object?(Game::Object::Passage)
passage = get_object(Game::Object::Passage)
return true if passage.passible?

key = player_objects.detect{|obj| obj.id == passage.id}
passage.open if key
key.try(:use)
passage.open if key.try(:use)
end
end
end
Expand Down
52 changes: 52 additions & 0 deletions spec/game/location/movement_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'spec_helper'

describe Game::Location::Movement do
subject { Game::Location.build(0, 1, 1) }

describe '#at' do
context 'retrieves the tile via the class at method' do
it 'for up' do
Game::Location.should_receive(:at).with(0, 1)
subject.at(:up)
end

it 'for down' do
Game::Location.should_receive(:at).with(2, 1)
subject.at(:down)
end

it 'for left' do
Game::Location.should_receive(:at).with(1, 0)
subject.at(:left)
end

it 'for right' do
Game::Location.should_receive(:at).with(1, 2)
subject.at(:right)
end
end

it 'returns an edge element if the tile does not exist' do
subject.at(:right).should be_a(Game::Location::Edge)
end

context 'if the tile exists' do
context 'if a location effecting object exists' do
it 'return the endpint instead' do
end_point_tile = Game::Location.build(0, 2, 2)
up_tile = Game::Location.build(0, 0, 1)
up_tile.add(Game::Object.instance('Transport', "end_point" => [2, 2], 'modules' => ['LocationModifier']))
subject.at(:up).should == end_point_tile
end
end

context 'if no location effecting object exists' do
it 'returns the tile' do
up_tile = Game::Location.build(0, 0, 1)
subject.at(:up).should == up_tile
end
end
end
end

end
28 changes: 28 additions & 0 deletions spec/game/location/passible_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'spec_helper'

describe Game::Location::Passible do
subject { Game::Location.build(0, 0, 0) }

describe '#passible?' do
context 'when no objects' do
it 'should be true' do
subject.should be_passible([])
end
end

context 'when objects' do
let(:passible) { mock(:object, :location= => true, :passible? => true) }
let(:impassible) { mock(:object, :location= => true, :passible? => false) }

it 'true when all objects are passible' do
subject.add(passible)
subject.should be_passible([])
end

it 'false if any objects are impassible' do
subject.add(impassible)
subject.should_not be_passible([])
end
end
end
end
91 changes: 2 additions & 89 deletions spec/game/location_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
require 'spec_helper'

describe Game::Location do
let(:exit) { Game::Object.instance('LevelExit', 'modules' => ['Exit']) }
subject { Game::Location.new(0, 1, 1) }

describe '#class_methods' do
before do
Game::Location.clear
Expand All @@ -16,13 +13,13 @@ def board
describe '#build' do
it 'creates a new insatnce of the class and stores it for retreival' do
Game::Location.build(0, 0, 0)
board.should == {[0, 0] => Game::Location.new(0, 0, 0)}
board.should == {[0, 0] => Game::Location::Empty.new(0, 0, 0)}
end
end

describe "#class_for" do
it 'returns the appropriate class to for the location_type' do
Game::Location.class_for(Game::Location::EMPTY_CELL).should == Game::Location
Game::Location.class_for(Game::Location::EMPTY_CELL).should == Game::Location::Empty
Game::Location.class_for(Game::Location::WALL_0).should == Game::Location::Wall
Game::Location.class_for(Game::Location::WALL_90).should == Game::Location::Wall
Game::Location.class_for(Game::Location::WALL_CORNER_RIGHT).should == Game::Location::Wall
Expand All @@ -49,89 +46,5 @@ def board
end
end
end

describe '#at' do
context 'retrieves the tile via the class at method' do
it 'for up' do
Game::Location.should_receive(:at).with(0, 1)
subject.at(:up)
end

it 'for down' do
Game::Location.should_receive(:at).with(2, 1)
subject.at(:down)
end

it 'for left' do
Game::Location.should_receive(:at).with(1, 0)
subject.at(:left)
end

it 'for right' do
Game::Location.should_receive(:at).with(1, 2)
subject.at(:right)
end
end

it 'returns an edge element if the tile does not exist' do
subject.at(:right).should be_a(Game::Location::Edge)
end

context 'if the tile exists' do
context 'if a location effecting object exists' do
it 'return the endpint instead' do
end_point_tile = Game::Location.build(0, 2, 2)
up_tile = Game::Location.build(0, 0, 1)
up_tile.add(Game::Object.instance('Transport', "end_point" => [2, 2], 'modules' => ['LocationModifier']))
subject.at(:up).should == end_point_tile
end
end

context 'if no location effecting object exists' do
it 'returns the tile' do
up_tile = Game::Location.build(0, 0, 1)
subject.at(:up).should == up_tile
end
end
end
end

describe '#passible?' do
it 'true' do
subject.should be_passible([])
end
end

describe '#add' do
it 'adds an object to the object list for the tile' do
subject.add(exit)
subject.should have_object(Game::Object::Exit)
end
end

describe '#remove' do
it 'removes an object from the object list for the tile' do
subject.add(exit)
subject.remove(exit)
subject.should_not have_object(Game::Object::Exit)
end
end

describe '#has_object?' do
it 'returns true if tile has an instance of the object class' do
subject.add(exit)
subject.has_object?(Game::Object::Exit).should be_true
end

it 'returns true if an instance of a sub-class of the object class' do
object = Game::Object.instance('SubClassOfExit', 'modules' => ['LocationModifier'])
subject.add(object)
subject.has_object?(Game::Object::LocationModifier).should be_true
end

it 'returns false if tile doesnt have an instance of the object class' do
subject.has_object?(Game::Player).should be_false
end
end
end

4 changes: 2 additions & 2 deletions spec/game/map_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

describe '#data' do
it 'returns the board elements mapped to Game::Locations' do
subject.data.should == [[Game::Location.new(0, 0, 0), Game::Location.new(1, 0, 1)],
[Game::Location.new(2, 1, 0), Game::Location.new(3, 1, 1)]]
subject.data.should == [[Game::Location::Empty.new(0, 0, 0), Game::Location::Empty.new(1, 0, 1)],
[Game::Location::Empty.new(2, 1, 0), Game::Location::Empty.new(3, 1, 1)]]
end
end

Expand Down
38 changes: 38 additions & 0 deletions spec/game/modules/object_management_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'spec_helper'

describe Game::Modules::ObjectManagement do
let(:exit) { Game::Object.instance('LevelExit', 'modules' => ['Exit']) }
subject { Game::Location.build(0, 0, 0) }

describe '#add' do
it 'adds an object to the object list for the tile' do
subject.add(exit)
subject.should have_object(Game::Object::Exit)
end
end

describe '#remove' do
it 'removes an object from the object list for the tile' do
subject.add(exit)
subject.remove(exit)
subject.should_not have_object(Game::Object::Exit)
end
end

describe '#has_object?' do
it 'returns true if tile has an instance of the object class' do
subject.add(exit)
subject.has_object?(Game::Object::Exit).should be_true
end

it 'returns true if an instance of a sub-class of the object class' do
object = Game::Object.instance('SubClassOfExit', 'modules' => ['LocationModifier'])
subject.add(object)
subject.has_object?(Game::Object::LocationModifier).should be_true
end

it 'returns false if tile doesnt have an instance of the object class' do
subject.has_object?(Game::Player).should be_false
end
end
end

0 comments on commit a8388af

Please sign in to comment.