RSokoban 0.71

Sign up to get free protection for your applications and to get access to all the features.
@@ -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