RSokoban 0.74 → 0.76
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/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
|