Here is my very simple solution, you controll the player using WASD for
moving up, left, down and right and R for restarting the game. It should
run on any Ruby 1.8.
class Level
def initialize(level)
@level = level
end
def play
while count_free_crates > 0
printf "\n%s\n\n> ", self
c = gets
c.each_byte do |command|
case command
when ?w
move(0, -1)
when ?a
move(-1, 0)
when ?s
move(0, 1)
when ?d
move(1, 0)
when ?r
return false
end
end
end
printf "\n%s\nCongratulations, on to the next level!\n", self
return true
end
private
def move(dx, dy)
x, y = find_player
dest = self[x+dx, y+dy]
case dest
when ?#
return
when ?o, ?*
dest2 = self[x+dx*2, y+dy*2]
if dest2 == 32
self[x+dx*2, y+dy*2] = ?o
elsif dest2 == ?.
self[x+dx*2, y+dy*2] = ?*
else
return
end
dest = (dest == ?o) ? 32 : ?.
end
self[x+dx, y+dy] = (dest == 32) ? ?@ : ?+
self[x, y] = (self[x, y] == ?@) ? 32 : ?.
end
def count_free_crates
@level.scan(/o/).size
end
def find_player
pos = @level.index(/@|\+/)
return pos % 19, pos / 19
end
def [](x, y)
@level[x + y * 19]
end
def []=(x, y, v)
@level[x + y * 19] = v
end
def to_s
(0...16).map {|i| @level[i * 19, 19]}.join("\n")
end
end
levels = File.readlines('sokoban_levels.txt')
levels = levels.map {|line| line.chomp.ljust(19)}.join("\n")
levels = levels.split(/\n {19}\n/).map{|level| level.gsub(/\n/, '')}
levels.each do |level|
redo unless Level.new(level.ljust(19*16)).play
end
--
exoticorn/farbrausch