rsokoban 1.0.0

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.
data/lib/level.rb ADDED
@@ -0,0 +1,68 @@
1
+ require 'happymapper'
2
+
3
+ module RSokoban
4
+ attr_accessor :levels
5
+
6
+ class LevelData
7
+ include HappyMapper
8
+
9
+ tag 'Level'
10
+ element :id, String
11
+ element :copyright, String
12
+ element :width, Integer
13
+ element :height, Integer
14
+ has_many :lines, String, :tag => 'L'
15
+ end
16
+
17
+ class Level
18
+ attr_accessor :walls
19
+ attr_accessor :boxes
20
+ attr_accessor :player
21
+ attr_accessor :goals
22
+
23
+ def initialize(data)
24
+ @walls = {}
25
+ @boxes = {}
26
+ @player = {}
27
+ @goals = {}
28
+
29
+ data.lines.each_with_index do |line, row|
30
+ line.split(//).each_with_index do |char, col|
31
+ case char
32
+ when '#'
33
+ @walls[[row, col]] = true
34
+ when '$'
35
+ @boxes[[row, col]] = true
36
+ when '.'
37
+ @goals[[row, col]] = true
38
+ when '@'
39
+ @player = {row: row, col: col}
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def draw(window)
46
+ @walls.keys.each do |k|
47
+ window.move k[0], k[1]
48
+ window.addstr '#'
49
+ end
50
+
51
+ @goals.keys.each do |k|
52
+ window.move k[0], k[1]
53
+ window.addstr '.'
54
+ end
55
+ end
56
+
57
+ def self.parse(string)
58
+ LevelData.parse(string).map do |level|
59
+ Level.new level
60
+ end
61
+ end
62
+
63
+ def self.load(filename)
64
+ self.parse(File.open(filename).read)
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,140 @@
1
+ module RSokoban
2
+ class RSokobanGame
3
+ # Add these to [@player[:row], @player[:col]] to move the player
4
+ # in the indicated direction.
5
+ DIRECTIONS = {
6
+ left: [ 0, -1],
7
+ right: [ 0, 1],
8
+ up: [-1, 0],
9
+ down: [ 1, 0]
10
+ }
11
+
12
+ def initialize(window)
13
+ @window = window
14
+ end
15
+
16
+ def can_move?(direction)
17
+ # Calculate the player's new position if this move is to be executed. Remember that
18
+ # `new_player` is an Array whereas @player is a Hash.
19
+ new_player = [@player[:row], @player[:col]].zip(DIRECTIONS[direction]).map{|a, b| a + b}
20
+
21
+ if @walls[new_player] then
22
+ return false
23
+ else
24
+ if @boxes[new_player] then
25
+ # Calculate the position of any box that's in the player's way.
26
+ new_box = new_player.zip(DIRECTIONS[direction]).map{|a, b| a + b}
27
+ if @walls[new_box] or @boxes[new_box] then
28
+ return false
29
+ else
30
+ return true
31
+ end
32
+ else
33
+ return true
34
+ end
35
+ end
36
+ end
37
+
38
+ def draw
39
+ @current_level.walls.keys.each do |k|
40
+ @window.move k[0], k[1]
41
+ @window.addstr '#'
42
+ end
43
+ @goals.keys.each do |k|
44
+ @window.move k[0], k[1]
45
+ @window.addstr '.'
46
+ end
47
+ @boxes.keys.each do |k|
48
+ @window.move k[0], k[1]
49
+ if @goals[k] then
50
+ @window.addstr '+'
51
+ else
52
+ @window.addstr '$'
53
+ end
54
+ end
55
+ @window.move @player[:row], @player[:col]
56
+ @window.addstr '@'
57
+ @window.refresh
58
+ end
59
+
60
+ def level_complete?
61
+ (@boxes.keys - @goals.keys).empty?
62
+ end
63
+
64
+ def move(direction, undoing = false)
65
+ return unless can_move?(direction)
66
+
67
+ new_player = [@player[:row], @player[:col]].zip(DIRECTIONS[direction]).map{|a, b| a + b}
68
+ if @boxes[new_player] then
69
+ new_box = new_player.zip(DIRECTIONS[direction]).map{|a, b| a + b}
70
+ @boxes[new_box] = true
71
+ @boxes.delete new_player
72
+ end
73
+
74
+ # Cover up the space behind the player with a space.
75
+ @window.move @player[:row], @player[:col]
76
+ @window.addstr ' '
77
+
78
+ @player[:row], @player[:col] = new_player
79
+ @moves.push direction unless undoing
80
+ end
81
+
82
+ def play_level(level)
83
+ @current_level = level.dup
84
+
85
+ @walls = level.walls.dup
86
+ @boxes = level.boxes.dup
87
+ @player = level.player.dup
88
+ @goals = level.goals.dup
89
+
90
+ @moves = []
91
+
92
+ draw
93
+
94
+ until level_complete?
95
+ ch = @window.getch
96
+
97
+ case ch
98
+ when 'q'.ord
99
+ exit
100
+ when 'r'.ord
101
+ @window.clear
102
+ return play_level(level)
103
+ when 'n'.ord
104
+ return
105
+ when 'z'.ord
106
+ undo
107
+ when Ncurses::KEY_DOWN, 's'.ord
108
+ move :down
109
+ when Ncurses::KEY_UP, 'w'.ord
110
+ move :up
111
+ when Ncurses::KEY_RIGHT, 'd'.ord
112
+ move :right
113
+ when Ncurses::KEY_LEFT, 'a'.ord
114
+ move :left
115
+ end
116
+
117
+ draw
118
+ end
119
+
120
+ end
121
+
122
+ def undo
123
+ return if @moves.empty?
124
+
125
+ direction = case @moves.pop
126
+ when :left
127
+ :right
128
+ when :right
129
+ :left
130
+ when :up
131
+ :down
132
+ when :down
133
+ :up
134
+ end
135
+
136
+ move direction, true
137
+ end
138
+
139
+ end
140
+ end
data/rsokoban.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "rsokoban"
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Max Thom Stahl"]
12
+ s.date = "2012-05-18"
13
+ s.description = "A Sokoban clone written in Ruby using the ncurses library."
14
+ s.email = "max@dangerouscuteness.com"
15
+ s.executables = ["rsokoban"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".rspec",
23
+ ".rvmrc",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "bin/rsokoban",
31
+ "levels/default.xml",
32
+ "lib/level.rb",
33
+ "lib/rsokoban_game.rb",
34
+ "rsokoban.gemspec",
35
+ "spec/rsokoban_spec.rb",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = "http://github.com/mstahl/rsokoban"
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = "1.8.17"
42
+ s.summary = "Sokoban, written in Ruby."
43
+
44
+ if s.respond_to? :specification_version then
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_runtime_dependency(%q<happymapper>, [">= 0"])
49
+ s.add_runtime_dependency(%q<ncurses-ruby>, [">= 0"])
50
+ s.add_development_dependency(%q<awesome_print>, [">= 0"])
51
+ s.add_development_dependency(%q<rspec>, [">= 0"])
52
+ s.add_development_dependency(%q<yard>, [">= 0"])
53
+ s.add_development_dependency(%q<bundler>, [">= 0"])
54
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
55
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<happymapper>, [">= 0"])
58
+ s.add_dependency(%q<ncurses-ruby>, [">= 0"])
59
+ s.add_dependency(%q<awesome_print>, [">= 0"])
60
+ s.add_dependency(%q<rspec>, [">= 0"])
61
+ s.add_dependency(%q<yard>, [">= 0"])
62
+ s.add_dependency(%q<bundler>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ s.add_dependency(%q<simplecov>, [">= 0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<happymapper>, [">= 0"])
68
+ s.add_dependency(%q<ncurses-ruby>, [">= 0"])
69
+ s.add_dependency(%q<awesome_print>, [">= 0"])
70
+ s.add_dependency(%q<rspec>, [">= 0"])
71
+ s.add_dependency(%q<yard>, [">= 0"])
72
+ s.add_dependency(%q<bundler>, [">= 0"])
73
+ s.add_dependency(%q<jeweler>, [">= 0"])
74
+ s.add_dependency(%q<simplecov>, [">= 0"])
75
+ end
76
+ end
77
+
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Rsokoban" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'rsokoban'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsokoban
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Max Thom Stahl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: happymapper
16
+ requirement: &70276082784920 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70276082784920
25
+ - !ruby/object:Gem::Dependency
26
+ name: ncurses-ruby
27
+ requirement: &70276082783860 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70276082783860
36
+ - !ruby/object:Gem::Dependency
37
+ name: awesome_print
38
+ requirement: &70276082783120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70276082783120
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &70276082782300 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70276082782300
58
+ - !ruby/object:Gem::Dependency
59
+ name: yard
60
+ requirement: &70276082781620 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70276082781620
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: &70276082780460 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70276082780460
80
+ - !ruby/object:Gem::Dependency
81
+ name: jeweler
82
+ requirement: &70276082779740 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70276082779740
91
+ - !ruby/object:Gem::Dependency
92
+ name: simplecov
93
+ requirement: &70276082778940 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70276082778940
102
+ description: A Sokoban clone written in Ruby using the ncurses library.
103
+ email: max@dangerouscuteness.com
104
+ executables:
105
+ - rsokoban
106
+ extensions: []
107
+ extra_rdoc_files:
108
+ - LICENSE.txt
109
+ - README.md
110
+ files:
111
+ - .document
112
+ - .rspec
113
+ - .rvmrc
114
+ - Gemfile
115
+ - Gemfile.lock
116
+ - LICENSE.txt
117
+ - README.md
118
+ - Rakefile
119
+ - VERSION
120
+ - bin/rsokoban
121
+ - levels/default.xml
122
+ - lib/level.rb
123
+ - lib/rsokoban_game.rb
124
+ - rsokoban.gemspec
125
+ - spec/rsokoban_spec.rb
126
+ - spec/spec_helper.rb
127
+ homepage: http://github.com/mstahl/rsokoban
128
+ licenses:
129
+ - MIT
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ segments:
141
+ - 0
142
+ hash: -1397569013250805758
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 1.8.17
152
+ signing_key:
153
+ specification_version: 3
154
+ summary: Sokoban, written in Ruby.
155
+ test_files: []