RSokoban 0.71
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/COPYING +674 -0
- data/README.rdoc +47 -0
- data/TODO +34 -0
- data/bin/rsokoban +10 -0
- data/data/microban.xsb +1838 -0
- data/data/original.xsb +1497 -0
- data/data/test.xsb +30 -0
- data/lib/rsokoban/crate.rb +16 -0
- data/lib/rsokoban/exception.rb +7 -0
- data/lib/rsokoban/game.rb +105 -0
- data/lib/rsokoban/level.rb +269 -0
- data/lib/rsokoban/level_loader.rb +58 -0
- data/lib/rsokoban/level_set.rb +31 -0
- data/lib/rsokoban/man.rb +17 -0
- data/lib/rsokoban/moveable.rb +22 -0
- data/lib/rsokoban/option.rb +93 -0
- data/lib/rsokoban/position.rb +24 -0
- data/lib/rsokoban/raw_level.rb +16 -0
- data/lib/rsokoban/storage.rb +14 -0
- data/lib/rsokoban/ui/console.rb +107 -0
- data/lib/rsokoban/ui/curses_console.rb +123 -0
- data/lib/rsokoban/ui/ui.rb +44 -0
- data/lib/rsokoban.rb +29 -0
- data/test/original.xsb +1497 -0
- data/test/tc_level.rb +773 -0
- data/test/tc_level_loader.rb +88 -0
- data/test/tc_level_set.rb +42 -0
- data/test/tc_man.rb +55 -0
- data/test/tc_moveable.rb +41 -0
- data/test/tc_position.rb +75 -0
- data/test/tc_raw_level.rb +35 -0
- data/test/test.rb +16 -0
- data/test/test_file1.xsb +9 -0
- data/test/test_file2.xsb +49 -0
- data/test/ui/tc_console.rb +75 -0
- metadata +102 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
module RSokoban::UI
|
3
|
+
|
4
|
+
# I am a portable console for the user interface.
|
5
|
+
# In addition to what BaseUI want from me, I offer the user
|
6
|
+
# an help feature.
|
7
|
+
# I assume 24 lines height.
|
8
|
+
class Console < BaseUI
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super()
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_action(type, level, message)
|
15
|
+
@level_title = message if type == 'START'
|
16
|
+
message = 'OK move 0' if type == 'START'
|
17
|
+
display level, message
|
18
|
+
if type == 'DISPLAY' or type == 'START'
|
19
|
+
askPlayer
|
20
|
+
else
|
21
|
+
# assuming type == 'WIN'
|
22
|
+
askForNextLevel
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def display level, message
|
29
|
+
blankConsole = "\n" * 24 # assuming a console window of 24 lines height
|
30
|
+
puts blankConsole
|
31
|
+
puts @level_title
|
32
|
+
puts "--------------------"
|
33
|
+
puts message
|
34
|
+
puts ''
|
35
|
+
level.each {|line| puts line }
|
36
|
+
puts ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def askForNextLevel
|
40
|
+
printf "Play next level ? "
|
41
|
+
line = readline.chomp
|
42
|
+
if ['yes', 'ye', 'y', 'YES', 'YE', 'Y'].include?(line)
|
43
|
+
:next
|
44
|
+
else
|
45
|
+
:quit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def askPlayer
|
50
|
+
printf "Your choice ? "
|
51
|
+
line = readline.chomp
|
52
|
+
response = parse line
|
53
|
+
if response.nil?
|
54
|
+
puts "Error : #{line}"
|
55
|
+
askPlayer
|
56
|
+
elsif response == :help
|
57
|
+
displayHelp
|
58
|
+
askPlayer
|
59
|
+
else
|
60
|
+
response
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse str
|
65
|
+
case str
|
66
|
+
when 'quit', 'up', 'down', 'right', 'left', 'retry', 'help'
|
67
|
+
str.to_sym
|
68
|
+
when 'z'
|
69
|
+
:up
|
70
|
+
when 's'
|
71
|
+
:down
|
72
|
+
when 'q'
|
73
|
+
:left
|
74
|
+
when 'd'
|
75
|
+
:right
|
76
|
+
when '1'..'999'
|
77
|
+
str.to_i
|
78
|
+
when /\.xsb$/
|
79
|
+
str
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def displayHelp
|
84
|
+
help=<<EOS
|
85
|
+
------------------------------
|
86
|
+
General commands :
|
87
|
+
|
88
|
+
quit : Quit game
|
89
|
+
help : Display this screen
|
90
|
+
retry : Restart level
|
91
|
+
1 to 999 : Play this level
|
92
|
+
file.xsb : Load this set of levels
|
93
|
+
|
94
|
+
How to move :
|
95
|
+
|
96
|
+
up (or z) : Move up
|
97
|
+
down (or s) : Move down
|
98
|
+
left (or q) : Move left
|
99
|
+
right (or d) : Move right
|
100
|
+
------------------------------
|
101
|
+
EOS
|
102
|
+
puts help
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'curses'
|
2
|
+
|
3
|
+
module RSokoban::UI
|
4
|
+
|
5
|
+
# I am a console user interface using curses library.
|
6
|
+
# I assume 24 lines height.
|
7
|
+
class CursesConsole < BaseUI
|
8
|
+
|
9
|
+
@@TITLE_LINE = 0
|
10
|
+
@@MOVES_LINE = 1
|
11
|
+
@@STATUS_LINE = 2
|
12
|
+
@@PICTURE_LINE = 4
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super()
|
16
|
+
init_screen
|
17
|
+
ensure
|
18
|
+
Curses.close_screen
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_action(type, level, message)
|
22
|
+
if type == 'START' or type == 'END_OF_SET'
|
23
|
+
@level_title = message
|
24
|
+
message = 'OK move 0'
|
25
|
+
Curses.clear
|
26
|
+
end
|
27
|
+
if type == 'DISPLAY' or type == 'START' or type == 'END_OF_SET'
|
28
|
+
ask_player level, message
|
29
|
+
else
|
30
|
+
# assuming type == 'WIN'
|
31
|
+
askForNextLevel level, message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def init_screen
|
38
|
+
Curses.noecho # do not show typed keys
|
39
|
+
Curses.init_screen
|
40
|
+
Curses.stdscr.keypad(true) # enable arrow keys
|
41
|
+
Curses.curs_set 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def display level, message
|
45
|
+
write @@TITLE_LINE, 0, @level_title
|
46
|
+
move_index = message =~ /\d+/
|
47
|
+
write @@MOVES_LINE, 0, 'moves : ' + message[move_index..-1] if move_index
|
48
|
+
write @@STATUS_LINE, 0, 'arrows=move (q)uit (r)etry (l)oad level/set'
|
49
|
+
line_num = @@PICTURE_LINE
|
50
|
+
level.each {|line|
|
51
|
+
write line_num, 0, line
|
52
|
+
line_num += 1
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(line, column, text)
|
57
|
+
Curses.setpos(line, column)
|
58
|
+
Curses.addstr(text);
|
59
|
+
end
|
60
|
+
|
61
|
+
def askForNextLevel level, message
|
62
|
+
display level, message
|
63
|
+
write @@STATUS_LINE, 0, "LEVEL COMPLETED ! Play next level ? (yes, no) "
|
64
|
+
case Curses.getch
|
65
|
+
when ?n, ?N then :quit
|
66
|
+
when ?y, ?Y then :next
|
67
|
+
else
|
68
|
+
askForNextLevel level, message
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def ask_player level, message
|
73
|
+
display level, message
|
74
|
+
response = get_player_input
|
75
|
+
if response.nil?
|
76
|
+
ask_player level, message
|
77
|
+
else
|
78
|
+
response
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_player_input
|
83
|
+
case Curses.getch
|
84
|
+
when Curses::Key::UP then :up
|
85
|
+
when Curses::Key::DOWN then :down
|
86
|
+
when Curses::Key::LEFT then :left
|
87
|
+
when Curses::Key::RIGHT then :right
|
88
|
+
when ?q, ?Q then :quit
|
89
|
+
when ?r, ?R then :retry
|
90
|
+
when ?l, ?L then ask_level_or_set
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def ask_level_or_set
|
97
|
+
Curses.curs_set 1
|
98
|
+
Curses.echo
|
99
|
+
Curses.clear
|
100
|
+
help=<<EOS
|
101
|
+
------------------------------------------------------------
|
102
|
+
To load a level from this set, type its number.
|
103
|
+
To load a set of level, type its name (with .xsb).
|
104
|
+
Int 1 : Don't forget to hit return.
|
105
|
+
Int 2 : type any letter to cancel and restart previous level
|
106
|
+
------------------------------------------------------------
|
107
|
+
|
108
|
+
EOS
|
109
|
+
write 0, 0, help
|
110
|
+
str = Curses.getstr
|
111
|
+
Curses.curs_set 0
|
112
|
+
Curses.noecho
|
113
|
+
case str
|
114
|
+
when '1'..'999' then str.to_i
|
115
|
+
when /\.xsb$/ then str
|
116
|
+
else
|
117
|
+
:retry
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
# Module dedicated to user interfaces.
|
4
|
+
module UI
|
5
|
+
|
6
|
+
# Every concrete UI should inherits from me.
|
7
|
+
class BaseUI
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@level_title = ''
|
11
|
+
end
|
12
|
+
|
13
|
+
# Based on things found in the arguments, I display the game
|
14
|
+
# to the user. Then he can tell what it want to do. Whatever
|
15
|
+
# my childs permit the user to do, they can only return one
|
16
|
+
# of the following actions.
|
17
|
+
#
|
18
|
+
# List of action I must be able to parse and return :
|
19
|
+
# :quit to quit game
|
20
|
+
# :next to load and play next level
|
21
|
+
# :retry to restart the current level
|
22
|
+
# :up, :down, :left, :right to move the man
|
23
|
+
# a number to load this level number
|
24
|
+
# an .xsb filename to load the set with this name
|
25
|
+
#
|
26
|
+
# @param ['START'|'DISPLAY'|'WIN'] type the type of message
|
27
|
+
# @param [Array<String>] level the picture of the level
|
28
|
+
# @param [String] message a message to be displayed. See Level#move
|
29
|
+
# to learn more about the message format and content.
|
30
|
+
# @return [Object] the user's action
|
31
|
+
# @since 0.71
|
32
|
+
# @todo write some examples
|
33
|
+
# @todo action diserves its own class
|
34
|
+
# @todo picture diserves its own class
|
35
|
+
# @todo document better +type+
|
36
|
+
def get_action(type, level, message)
|
37
|
+
raise "Please implement me !"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/rsokoban.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rsokoban/level"
|
2
|
+
require "rsokoban/level_loader"
|
3
|
+
require "rsokoban/exception"
|
4
|
+
require "rsokoban/position"
|
5
|
+
require "rsokoban/man"
|
6
|
+
require "rsokoban/crate"
|
7
|
+
require "rsokoban/storage"
|
8
|
+
require "rsokoban/game"
|
9
|
+
require "rsokoban/option"
|
10
|
+
require "rsokoban/level_set"
|
11
|
+
require "rsokoban/raw_level"
|
12
|
+
require "rsokoban/ui/ui"
|
13
|
+
|
14
|
+
# I am the main module of the game.
|
15
|
+
module RSokoban
|
16
|
+
# Version of the program
|
17
|
+
VERSION = '0.71'
|
18
|
+
|
19
|
+
# Game elements.
|
20
|
+
# Those constants are used intensively.
|
21
|
+
MAN = '@'
|
22
|
+
FLOOR = ' '
|
23
|
+
CRATE = '$'
|
24
|
+
STORAGE = '.'
|
25
|
+
WALL = '#'
|
26
|
+
MAN_ON_STORAGE = '+'
|
27
|
+
CRATE_ON_STORAGE = '*'
|
28
|
+
|
29
|
+
end
|