RSokoban 0.74 → 0.76
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +33 -1
- data/README.rdoc +21 -14
- data/TODO +6 -12
- data/VERSION +1 -1
- data/bin/rsokoban +40 -3
- data/data/big.xsb +35 -0
- data/lib/rsokoban/config.rb +34 -0
- data/lib/rsokoban/crate.rb +4 -5
- data/lib/rsokoban/exception.rb +2 -0
- data/lib/rsokoban/game/game.rb +153 -0
- data/lib/rsokoban/game/game_curses.rb +11 -0
- data/lib/rsokoban/game/game_factory.rb +23 -0
- data/lib/rsokoban/game/game_gui.rb +27 -0
- data/lib/rsokoban/game/game_portable.rb +10 -0
- data/lib/rsokoban/game/game_tk.rb +11 -0
- data/lib/rsokoban/game/game_ui.rb +81 -0
- data/lib/rsokoban/game.rb +7 -238
- data/lib/rsokoban/install.rb +22 -0
- data/lib/rsokoban/layered_map.rb +139 -0
- data/lib/rsokoban/level.rb +112 -166
- data/lib/rsokoban/level_set.rb +4 -4
- data/lib/rsokoban/man.rb +3 -4
- data/lib/rsokoban/map.rb +91 -15
- data/lib/rsokoban/move_result.rb +2 -2
- data/lib/rsokoban/option.rb +4 -4
- data/lib/rsokoban/position.rb +1 -1
- data/lib/rsokoban/raw_level.rb +11 -2
- data/lib/rsokoban/record.rb +51 -0
- data/lib/rsokoban/set_loader.rb +108 -0
- data/lib/rsokoban/ui/base_ui.rb +1 -0
- data/lib/rsokoban/ui/console.rb +56 -25
- data/lib/rsokoban/ui/curses_console.rb +59 -33
- data/lib/rsokoban/ui/player_action.rb +13 -7
- data/lib/rsokoban/ui/skin.rb +105 -0
- data/lib/rsokoban/ui/tk_dialogs.rb +104 -18
- data/lib/rsokoban/ui/tk_ui.rb +410 -233
- data/lib/rsokoban/ui.rb +1 -0
- data/lib/rsokoban.rb +14 -2
- data/skins/AntiqueDesk/crate.bmp +0 -0
- data/skins/AntiqueDesk/crate_store.bmp +0 -0
- data/skins/AntiqueDesk/floor.bmp +0 -0
- data/skins/AntiqueDesk/man_down.bmp +0 -0
- data/skins/AntiqueDesk/man_left.bmp +0 -0
- data/skins/AntiqueDesk/man_right.bmp +0 -0
- data/skins/AntiqueDesk/man_store_down.bmp +0 -0
- data/skins/AntiqueDesk/man_store_left.bmp +0 -0
- data/skins/AntiqueDesk/man_store_right.bmp +0 -0
- data/skins/AntiqueDesk/man_store_up.bmp +0 -0
- data/skins/AntiqueDesk/man_up.bmp +0 -0
- data/skins/AntiqueDesk/outside.bmp +0 -0
- data/skins/AntiqueDesk/skin.conf +3 -0
- data/skins/AntiqueDesk/store.bmp +0 -0
- data/skins/AntiqueDesk/wall.bmp +0 -0
- data/skins/BlueGranite/outside.bmp +0 -0
- data/skins/BlueGranite/skin.conf +3 -0
- data/skins/HeavyMetal/crate.bmp +0 -0
- data/skins/HeavyMetal/crate_store.bmp +0 -0
- data/skins/HeavyMetal/floor.bmp +0 -0
- data/skins/HeavyMetal/man.bmp +0 -0
- data/skins/HeavyMetal/man_store.bmp +0 -0
- data/skins/HeavyMetal/outside.bmp +0 -0
- data/skins/HeavyMetal/skin.conf +3 -0
- data/skins/HeavyMetal/store.bmp +0 -0
- data/skins/HeavyMetal/wall.bmp +0 -0
- data/skins/HeavyMetal/wall_d.bmp +0 -0
- data/skins/HeavyMetal/wall_dl.bmp +0 -0
- data/skins/HeavyMetal/wall_dlr.bmp +0 -0
- data/skins/HeavyMetal/wall_dr.bmp +0 -0
- data/skins/HeavyMetal/wall_l.bmp +0 -0
- data/skins/HeavyMetal/wall_lr.bmp +0 -0
- data/skins/HeavyMetal/wall_r.bmp +0 -0
- data/skins/HeavyMetal/wall_u.bmp +0 -0
- data/skins/HeavyMetal/wall_ud.bmp +0 -0
- data/skins/HeavyMetal/wall_udl.bmp +0 -0
- data/skins/HeavyMetal/wall_udlr.bmp +0 -0
- data/skins/HeavyMetal/wall_udr.bmp +0 -0
- data/skins/HeavyMetal/wall_ul.bmp +0 -0
- data/skins/HeavyMetal/wall_ulr.bmp +0 -0
- data/skins/HeavyMetal/wall_ur.bmp +0 -0
- data/test/record/original.yaml +2 -0
- data/test/tc_game.rb +24 -15
- data/test/tc_game_factory.rb +40 -0
- data/test/tc_game_gui.rb +26 -0
- data/test/tc_game_ui.rb +153 -0
- data/test/tc_install.rb +12 -0
- data/test/tc_layered_map.rb +105 -0
- data/test/tc_level.rb +109 -107
- data/test/tc_level_set.rb +4 -4
- data/test/tc_map.rb +46 -10
- data/test/tc_record.rb +100 -0
- data/test/{tc_level_loader.rb → tc_set_loader.rb} +25 -24
- data/test/test.rb +9 -2
- data/test/ui/tc_skin.rb +71 -0
- metadata +89 -26
- data/lib/rsokoban/level_loader.rb +0 -81
- data/lib/rsokoban/ui/tk_box.rb +0 -21
- data/skins/default/outside.bmp +0 -0
- data/skins/default/readme +0 -1
- /data/skins/{default → BlueGranite}/crate.bmp +0 -0
- /data/skins/{default → BlueGranite}/crate_store.bmp +0 -0
- /data/skins/{default → BlueGranite}/floor.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_down.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_left.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_right.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_store_down.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_store_left.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_store_right.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_store_up.bmp +0 -0
- /data/skins/{default → BlueGranite}/man_up.bmp +0 -0
- /data/skins/{default → BlueGranite}/store.bmp +0 -0
- /data/skins/{default → BlueGranite}/wall.bmp +0 -0
data/NEWS
CHANGED
@@ -1,6 +1,38 @@
|
|
1
|
+
version 0.76 2011-02-21
|
2
|
+
|
3
|
+
* All UIs
|
4
|
+
+ save/display score
|
5
|
+
+ program opens on the last played level
|
6
|
+
|
7
|
+
* Tk GUI
|
8
|
+
+ you can change the skin
|
9
|
+
+ 3 skins shipped with the software
|
10
|
+
+ you can add your own skins
|
11
|
+
+ skins are of any size
|
12
|
+
+ better integration of Tk (new dependence: tk-tile library)
|
13
|
+
|
14
|
+
|
15
|
+
version 0.75.1 2011-02-12
|
16
|
+
|
17
|
+
* Tk GUI
|
18
|
+
+ unlimited map size
|
19
|
+
+ auto scrolling
|
20
|
+
+ user scrolling
|
21
|
+
+ window size follows map size
|
22
|
+
|
23
|
+
* fix
|
24
|
+
+ bug#3
|
25
|
+
+ bug#9
|
26
|
+
|
27
|
+
|
28
|
+
version 0.74.1 2011-02-09
|
29
|
+
|
30
|
+
* Tk GUI: nicer background
|
31
|
+
|
32
|
+
|
1
33
|
version 0.74 2011-01-31
|
2
34
|
|
3
|
-
|
35
|
+
* New: redo feature (only available with Tk GUI)
|
4
36
|
|
5
37
|
* Tk GUI
|
6
38
|
+ add a 'next level' feature
|
data/README.rdoc
CHANGED
@@ -1,33 +1,42 @@
|
|
1
1
|
= Welcome to RSokoban !
|
2
2
|
|
3
3
|
RSokoban is a clone of the famous {Sokoban}[http://en.wikipedia.org/wiki/Sokoban] game.
|
4
|
-
I wrote this program just to improve my skills in Ruby.
|
4
|
+
I wrote this program just to improve my skills in Ruby with GUI.
|
5
5
|
|
6
6
|
*Features*
|
7
7
|
* Graphical user interface with Tk
|
8
|
-
*
|
8
|
+
* Skinning
|
9
9
|
* 200+ levels
|
10
10
|
* Undo/redo
|
11
11
|
* Use xsb file format to load sets of levels
|
12
|
+
* Additional console user interfaces (curses and straight text mode)
|
12
13
|
|
13
14
|
Enjoy the game.
|
14
15
|
|
15
16
|
|
16
17
|
== Documentation
|
17
18
|
|
18
|
-
|
19
|
+
Look at {the wiki}[https://github.com/lkdjiin/RSokoban/wiki].
|
19
20
|
|
20
|
-
Developpers can look at Level, Game and TkUI.
|
21
21
|
|
22
|
+
== Installing
|
22
23
|
|
23
|
-
|
24
|
+
=== Installing dependencies
|
24
25
|
|
25
|
-
Ruby >= 1.8.7
|
26
|
+
You need Ruby >= 1.8.7
|
26
27
|
|
28
|
+
To play with the graphical user interface you need to be sre that the following
|
29
|
+
packages are installed on your system:
|
27
30
|
|
28
|
-
|
31
|
+
* libtcltk-ruby
|
32
|
+
* libtk-img
|
33
|
+
* tk-tile
|
29
34
|
|
30
|
-
|
35
|
+
|
36
|
+
=== Installing RSokoban
|
37
|
+
|
38
|
+
<b>First method, install from the sources</b>
|
39
|
+
This is the method I recommend.
|
31
40
|
To install RSokoban from the source, go to the RSokoban folder and build the gem:
|
32
41
|
|
33
42
|
gem build rsokoban.gemspec
|
@@ -45,17 +54,15 @@ If you prefer using rake to build and install:
|
|
45
54
|
rake build
|
46
55
|
rake install
|
47
56
|
|
48
|
-
|
57
|
+
<b>Second method</b>
|
49
58
|
Or install via RubyGem in one command (you need ruby 1.9 or higher).
|
50
|
-
Note that I don't certify you will get the latest release
|
59
|
+
<em>Note that I don't certify you will get the latest release</em>:
|
51
60
|
|
52
61
|
gem install RSokoban
|
53
62
|
|
54
|
-
|
55
|
-
Or you can play without installing it. Go to the RSokoban/bin folder and type:
|
56
|
-
|
57
|
-
./rsokoban
|
63
|
+
== Licence
|
58
64
|
|
65
|
+
GPLv3
|
59
66
|
|
60
67
|
== Questions and/or Comments
|
61
68
|
|
data/TODO
CHANGED
@@ -1,18 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
2
|
+
-------------------------------------------------------
|
3
|
+
Think about:
|
3
4
|
* gnome GUI (gtk only to be windows compatible ?)
|
4
5
|
* give a try to rubygame ?
|
5
|
-
*
|
6
|
-
|
7
|
-
+ several size of tiles or resizing ?)
|
8
|
-
* Console UI should provide a way to know names of sets
|
9
|
-
* save a game
|
10
|
-
* reload a saved game
|
11
|
-
* multi player support
|
12
|
-
* save score
|
13
|
-
* scoring moves and pushes
|
14
|
-
* level preview
|
6
|
+
* scoring moves and pushes ?
|
7
|
+
* level preview ?
|
15
8
|
* solver (plugin ?)
|
9
|
+
* zoom ?
|
16
10
|
* format fichier niveau xml (.slc)
|
17
11
|
* other GUI(s) ?
|
18
12
|
* mouse support
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.76
|
data/bin/rsokoban
CHANGED
@@ -24,10 +24,21 @@ $RSOKOBAN_DATA_PATH = File.expand_path(File.dirname(__FILE__) + '/../data')
|
|
24
24
|
|
25
25
|
require 'rsokoban'
|
26
26
|
|
27
|
+
unless File.exist? File.join(RSokoban::CONFIG_FOLDER, RSokoban::CONFIG_FILE)
|
28
|
+
RSokoban::Install.create_config RSokoban::CONFIG_FOLDER
|
29
|
+
end
|
30
|
+
|
31
|
+
unless File.exist? RSokoban::RECORD_FOLDER
|
32
|
+
RSokoban::Install.create_folder RSokoban::RECORD_FOLDER
|
33
|
+
end
|
34
|
+
|
27
35
|
tk_failed=<<EOS
|
28
36
|
Sorry, failed to load tk or tkimg library.
|
29
|
-
Please, be sure that
|
30
|
-
|
37
|
+
Please, be sure that:
|
38
|
+
libtcltk-ruby
|
39
|
+
libtk-img
|
40
|
+
tk-tile
|
41
|
+
are correctly installed on your system.
|
31
42
|
Now trying to start with curses library:
|
32
43
|
rsokoban --curses
|
33
44
|
|
@@ -51,6 +62,7 @@ if option[:ui] == :tk
|
|
51
62
|
begin
|
52
63
|
require 'tk'
|
53
64
|
require 'tkextlib/tkimg'
|
65
|
+
require 'tkextlib/tile'
|
54
66
|
rescue LoadError => e
|
55
67
|
puts tk_failed
|
56
68
|
option.interface = :curses
|
@@ -68,5 +80,30 @@ if option[:ui] == :curses
|
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
71
|
-
|
83
|
+
# Find last set
|
84
|
+
conf = RSokoban::Config.new
|
85
|
+
last_set = conf['set']
|
86
|
+
conf = nil # to be GCed ?
|
87
|
+
|
88
|
+
case option[:ui]
|
89
|
+
when :curses
|
90
|
+
require "rsokoban/ui/curses_console"
|
91
|
+
ui = RSokoban::UI::CursesConsole.new
|
92
|
+
game = RSokoban::GameFactory.create RSokoban::GameCurses, ui, last_set
|
93
|
+
when :portable
|
94
|
+
require "rsokoban/ui/console"
|
95
|
+
ui = RSokoban::UI::Console.new
|
96
|
+
game = RSokoban::GameFactory.create RSokoban::GamePortable, ui, last_set
|
97
|
+
when :tk
|
98
|
+
require "rsokoban/ui/tk_ui"
|
99
|
+
require "rsokoban/ui/tk_dialogs"
|
100
|
+
game = RSokoban::GameFactory.create RSokoban::GameTk, 'fake ui', last_set
|
101
|
+
game.ui = RSokoban::UI::TkUI.new(game)
|
102
|
+
end
|
103
|
+
|
104
|
+
at_exit do
|
105
|
+
conf = RSokoban::Config.new
|
106
|
+
conf.save_set_and_level game.set_name, game.level_number
|
107
|
+
end
|
108
|
+
|
72
109
|
game.run
|
data/data/big.xsb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
; Big maps test file
|
2
|
+
|
3
|
+
; Some big maps without interests except for testing purposes.
|
4
|
+
|
5
|
+
##############################
|
6
|
+
# #
|
7
|
+
# #
|
8
|
+
# #
|
9
|
+
# @ .. #
|
10
|
+
# #
|
11
|
+
# $ #
|
12
|
+
# #
|
13
|
+
# #
|
14
|
+
# #
|
15
|
+
# #
|
16
|
+
# #
|
17
|
+
# #
|
18
|
+
# #
|
19
|
+
# #
|
20
|
+
# #
|
21
|
+
# #
|
22
|
+
# #
|
23
|
+
# #
|
24
|
+
# #
|
25
|
+
# #
|
26
|
+
# #
|
27
|
+
# #
|
28
|
+
# #
|
29
|
+
# $ #
|
30
|
+
# #
|
31
|
+
# #
|
32
|
+
# #
|
33
|
+
# #
|
34
|
+
##############################
|
35
|
+
; 30x30 square
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
class Config
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@conf = YAML.load_file File.join(CONFIG_FOLDER, CONFIG_FILE)
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
@conf[key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []= (key, value)
|
14
|
+
@conf[key] = value
|
15
|
+
write_config
|
16
|
+
end
|
17
|
+
|
18
|
+
def save_set_and_level setname, level_number
|
19
|
+
@conf['set'] = setname
|
20
|
+
@conf['level'] = level_number
|
21
|
+
write_config
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def write_config
|
27
|
+
f = File.new(File.join(CONFIG_FOLDER, CONFIG_FILE), "w")
|
28
|
+
f.write @conf.to_yaml
|
29
|
+
f.close
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/rsokoban/crate.rb
CHANGED
@@ -2,14 +2,13 @@ require "rsokoban/moveable"
|
|
2
2
|
|
3
3
|
module RSokoban
|
4
4
|
|
5
|
-
# I am a moveable crate.
|
5
|
+
# I am a positionable, moveable crate.
|
6
6
|
class Crate < Position
|
7
7
|
include RSokoban::Moveable
|
8
8
|
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
super(x, y)
|
9
|
+
# Coordinates must be Fixnum
|
10
|
+
def initialize x_coord, y_coord
|
11
|
+
super(x_coord, y_coord)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
data/lib/rsokoban/exception.rb
CHANGED
@@ -0,0 +1,153 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
# I provide the basic API to run a game.
|
4
|
+
# I am user interface agnostic.
|
5
|
+
# @since 0.74.1
|
6
|
+
module Game
|
7
|
+
# @return [Fixnum]
|
8
|
+
attr_reader :level_number, :set_name
|
9
|
+
|
10
|
+
# Construct a new game that you can later run.
|
11
|
+
# @param [UI] the user interface associated to this game
|
12
|
+
# @param [String] setname The set of levels to begin with
|
13
|
+
def initialize ui, setname = 'microban.xsb'
|
14
|
+
@set_name = setname
|
15
|
+
@level_loader = SetLoader.new setname
|
16
|
+
conf = Config.new
|
17
|
+
@level_number = conf['level']
|
18
|
+
@ui = ui
|
19
|
+
end
|
20
|
+
|
21
|
+
# Start the game loop.
|
22
|
+
# @note You must override me in a concrete class.
|
23
|
+
def run
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Fixnum]
|
28
|
+
def level_width
|
29
|
+
@level.width
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Fixnum]
|
33
|
+
def level_height
|
34
|
+
@level.height
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String]
|
38
|
+
def level_title
|
39
|
+
@level.title
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get current map of the game as an array of strings
|
43
|
+
# @return [Array<String>]
|
44
|
+
def map_as_array
|
45
|
+
@level.map_as_array
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get x coordinate of the man
|
49
|
+
# @return [Fixnum]
|
50
|
+
def man_x
|
51
|
+
@level.man.x
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get y coordinate of the man
|
55
|
+
# @return [Fixnum]
|
56
|
+
def man_y
|
57
|
+
@level.man.y
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get result of the move
|
61
|
+
# @param [:up|:down|:right|:left] direction
|
62
|
+
# @return [Object]
|
63
|
+
def move direction
|
64
|
+
@level.move direction
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get current move number
|
68
|
+
# @return [Fixnum]
|
69
|
+
def move_number
|
70
|
+
@level.move_number
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get result of undo last move
|
74
|
+
# @return [MoveResult]
|
75
|
+
def undo
|
76
|
+
@level.undo
|
77
|
+
end
|
78
|
+
|
79
|
+
# Get result of redo last undone move
|
80
|
+
# @return [MoveResult]
|
81
|
+
def redo
|
82
|
+
@level.redo
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get title of the current set
|
86
|
+
# @return [String]
|
87
|
+
def set_title
|
88
|
+
@level_loader.title
|
89
|
+
end
|
90
|
+
|
91
|
+
# Get numbers of level from the current set
|
92
|
+
# @return [Fixnum]
|
93
|
+
def set_size
|
94
|
+
@level_loader.size
|
95
|
+
end
|
96
|
+
|
97
|
+
# @note You must override me.
|
98
|
+
def start_level
|
99
|
+
raise NotImplementedError
|
100
|
+
end
|
101
|
+
|
102
|
+
# Load and start the next level of the set
|
103
|
+
# @return See the implementation of start_level in a descendant module (GameUI or GameGUI).
|
104
|
+
def next_level
|
105
|
+
@level_number += 1
|
106
|
+
start_level
|
107
|
+
end
|
108
|
+
|
109
|
+
# Load a level from the current set.
|
110
|
+
# @param [Fixnum] num the number of the set (base 1)
|
111
|
+
# @return See the implementation of start_level in a descendant module (GameUI or GameGUI).
|
112
|
+
def load_level num
|
113
|
+
@level_number = num
|
114
|
+
start_level
|
115
|
+
end
|
116
|
+
|
117
|
+
# Restart current set from level 1.
|
118
|
+
# @return See the implementation of start_level in a descendant module (GameUI or GameGUI).
|
119
|
+
def restart_set
|
120
|
+
@level_number = 1
|
121
|
+
start_level
|
122
|
+
end
|
123
|
+
|
124
|
+
# Load a new set of levels and start its first level.
|
125
|
+
# @param [String] setname the name of the set (with .xsb extension)
|
126
|
+
def load_a_new_set setname
|
127
|
+
@set_name = setname
|
128
|
+
@level_loader = SetLoader.new setname
|
129
|
+
@level_number = 1
|
130
|
+
@level = @level_loader.level(@level_number)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get record for current level (in # of moves)
|
134
|
+
# @since 0.76
|
135
|
+
def record
|
136
|
+
@level.record
|
137
|
+
end
|
138
|
+
|
139
|
+
# Update record if needed.
|
140
|
+
# @return true if old record is beaten.
|
141
|
+
# @since 0.76
|
142
|
+
def update_record
|
143
|
+
if record.nil? or move_number < record
|
144
|
+
@level.update_record
|
145
|
+
true
|
146
|
+
else
|
147
|
+
false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
# @since 0.74.1
|
4
|
+
module GameFactory
|
5
|
+
|
6
|
+
# @param [GamePortable|GameCurses|GameTk] a_class
|
7
|
+
# @param [UI] ui associated user interface
|
8
|
+
# @param [String] level_set set to start playing with
|
9
|
+
def self.create a_class, ui, level_set = 'microban.xsb'
|
10
|
+
if GamePortable == a_class
|
11
|
+
GamePortable.new(ui, level_set)
|
12
|
+
elsif GameCurses == a_class
|
13
|
+
GameCurses.new(ui, level_set)
|
14
|
+
elsif GameTk == a_class
|
15
|
+
GameTk.new(ui, level_set)
|
16
|
+
else
|
17
|
+
raise ArgumentError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
# I extends/implements the API of module Game, to run the game
|
4
|
+
# within a GUI. I don't define the user interface, you can use me
|
5
|
+
# to run game with Tk, Gnome, etc.
|
6
|
+
# @since 0.74.1
|
7
|
+
module GameGUI
|
8
|
+
include Game
|
9
|
+
|
10
|
+
attr_writer :ui
|
11
|
+
|
12
|
+
def initialize ui, setname = 'microban.xsb'
|
13
|
+
super(ui, setname)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
@ui.run
|
18
|
+
end
|
19
|
+
|
20
|
+
def start_level
|
21
|
+
@level = @level_loader.level(@level_number)
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module RSokoban
|
2
|
+
|
3
|
+
# I extends/implements the API of module Game, to run the game
|
4
|
+
# in a console window. I don't define the user interface, you can use me
|
5
|
+
# to run game with curses, n-curses, straight text-mode, etc.
|
6
|
+
# @since 0.74.1
|
7
|
+
module GameUI
|
8
|
+
include Game
|
9
|
+
|
10
|
+
def initialize ui, setname = 'microban.xsb'
|
11
|
+
super(ui, setname)
|
12
|
+
end
|
13
|
+
|
14
|
+
# I am the game loop for UIs.
|
15
|
+
def run
|
16
|
+
player_action = start_level
|
17
|
+
loop do
|
18
|
+
if player_action.level_number?
|
19
|
+
player_action = load_level player_action.action
|
20
|
+
next
|
21
|
+
elsif player_action.set_name?
|
22
|
+
player_action = load_a_new_set player_action.action
|
23
|
+
next
|
24
|
+
elsif player_action.quit?
|
25
|
+
break
|
26
|
+
elsif player_action.next?
|
27
|
+
player_action = next_level
|
28
|
+
next
|
29
|
+
elsif player_action.retry?
|
30
|
+
player_action = start_level
|
31
|
+
next
|
32
|
+
elsif player_action.move?
|
33
|
+
result = @level.move(player_action.action)
|
34
|
+
elsif player_action.undo?
|
35
|
+
result = @level.undo
|
36
|
+
end
|
37
|
+
|
38
|
+
hash = {:map=>@level.map_as_array, :move=>result[:move_number]}
|
39
|
+
case result[:status]
|
40
|
+
when :win
|
41
|
+
update_record
|
42
|
+
player_action = @ui.get_action(hash.merge({:type=>:win}))
|
43
|
+
when :ok then player_action = @ui.get_action(hash.merge({:type=>:display}))
|
44
|
+
else
|
45
|
+
player_action = @ui.get_action(:type=>:display, :map=>@level.map_as_array, :error=>result[:message])
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [PlayerAction]
|
53
|
+
def start_level
|
54
|
+
begin
|
55
|
+
@level = @level_loader.level(@level_number)
|
56
|
+
@ui.get_action(get_hash_after_loading_set)
|
57
|
+
rescue LevelNumberTooHighError
|
58
|
+
@ui.get_action(:type=>:end_of_set, :map=>Map.new)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_a_new_set setname
|
63
|
+
begin
|
64
|
+
super(setname)
|
65
|
+
@ui.get_action(get_hash_after_loading_set)
|
66
|
+
rescue NoFileError
|
67
|
+
error = "Error, no such file : #{setname}"
|
68
|
+
@ui.get_action(get_hash_after_loading_set.merge({:error=>error}))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def get_hash_after_loading_set
|
75
|
+
{:type=>:start, :map=>@level.map_as_array, :title=>@level.title, :set=>@level_loader.title,
|
76
|
+
:number=>@level_number, :total=>@level_loader.size, :record => @level.record}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|