summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/FILES2
-rw-r--r--apps/plugins/bitmaps/native/SOURCES8
-rw-r--r--apps/plugins/sokoban.c1355
-rw-r--r--apps/plugins/sokoban.levels1816
-rw-r--r--apps/plugins/sokobanlevels.sok1277
-rw-r--r--apps/plugins/viewers.config1
-rw-r--r--manual/plugins/images/ss-sokoban-112x64x1.pngbin337 -> 353 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-128x128x16.pngbin1135 -> 665 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-138x110x2.pngbin481 -> 455 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-160x128x16.pngbin1269 -> 699 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-160x128x2.pngbin514 -> 615 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-176x132x16.pngbin1323 -> 709 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-176x220x16.pngbin1366 -> 875 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-220x176x16.pngbin1645 -> 888 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-240x320x16.pngbin2035 -> 972 bytes
-rw-r--r--manual/plugins/images/ss-sokoban-320x240x16.pngbin2255 -> 1205 bytes
-rw-r--r--manual/plugins/sokoban.tex83
-rwxr-xr-xtools/buildzip.pl2
18 files changed, 2222 insertions, 2322 deletions
diff --git a/apps/FILES b/apps/FILES
index 85d70cbe74..06b7b38b9a 100644
--- a/apps/FILES
+++ b/apps/FILES
@@ -42,7 +42,7 @@ plugins/*.pl
42plugins/Makefile 42plugins/Makefile
43plugins/plugin.lds 43plugins/plugin.lds
44plugins/snake2.levels 44plugins/snake2.levels
45plugins/sokoban.levels 45plugins/sokobanlevels.sok
46plugins/viewers.config 46plugins/viewers.config
47plugins/SOURCES 47plugins/SOURCES
48plugins/SUBDIRS 48plugins/SUBDIRS
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index 90a635ef01..00a6e3ab30 100644
--- a/apps/plugins/bitmaps/native/SOURCES
+++ b/apps/plugins/bitmaps/native/SOURCES
@@ -331,11 +331,13 @@ sokoban_tiles.14x14.bmp
331#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 212) || \ 331#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 212) || \
332 (LCD_HEIGHT >= 169) && (LCD_WIDTH >= 180-4) 332 (LCD_HEIGHT >= 169) && (LCD_WIDTH >= 180-4)
333sokoban_tiles.9x9.bmp 333sokoban_tiles.9x9.bmp
334#else 334#elif (LCD_HEIGHT >= 96 && LCD_WIDTH >= 152) || \
335/* LCD_HEIGHT >= 96~121 && LCD_WIDTH >= 152~120 */ 335 (LCD_HEIGHT >= 121 && LCD_WIDTH >= 120)
336sokoban_tiles.6x6.bmp 336sokoban_tiles.6x6.bmp
337#endif 337#endif
338#elif LCD_DEPTH >= 2 338#elif LCD_DEPTH >= 2 && \
339 ((LCD_HEIGHT >= 96 && LCD_WIDTH >= 152) || \
340 (LCD_HEIGHT >= 121 && LCD_WIDTH >= 120))
339sokoban_tiles.6x6x2.bmp 341sokoban_tiles.6x6x2.bmp
340#endif 342#endif
341 343
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
index 40a2f549ad..976f552dbd 100644
--- a/apps/plugins/sokoban.c
+++ b/apps/plugins/sokoban.c
@@ -10,6 +10,7 @@
10 * Copyright (C) 2002 Eric Linenberg 10 * Copyright (C) 2002 Eric Linenberg
11 * February 2003: Robert Hak performs a cleanup/rewrite/feature addition. 11 * February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
12 * Eric smiles. Bjorn cries. Linus say 'huh?'. 12 * Eric smiles. Bjorn cries. Linus say 'huh?'.
13 * March 2007: Sean Morrisey performs a major rewrite/feature addition.
13 * 14 *
14 * All files in this archive are subject to the GNU General Public License. 15 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement. 16 * See the file COPYING in the source tree root for full license agreement.
@@ -19,95 +20,126 @@
19 * 20 *
20 ****************************************************************************/ 21 ****************************************************************************/
21#include "plugin.h" 22#include "plugin.h"
23#include "lib/playback_control.h"
22 24
23#ifdef HAVE_LCD_BITMAP 25#ifdef HAVE_LCD_BITMAP
24 26
25PLUGIN_HEADER 27PLUGIN_HEADER
26 28
27#if LCD_DEPTH >= 2 29#if LCD_DEPTH >= 2 && ((LCD_HEIGHT >= 96 && LCD_WIDTH >= 152) || \
30 (LCD_HEIGHT >= 121 && LCD_WIDTH >= 120))
28extern const fb_data sokoban_tiles[]; 31extern const fb_data sokoban_tiles[];
29#endif 32#endif
30 33
31#define SOKOBAN_TITLE "Sokoban" 34#define SOKOBAN_TITLE "Sokoban"
32 35
33#define LEVELS_FILE PLUGIN_DIR "/sokoban.levels" 36#define SOKOBAN_LEVELS_FILE PLUGIN_DIR "/sokobanlevels.sok"
37#define SOKOBAN_SAVE_FILE PLUGIN_DIR "/sokobansave.sok"
34 38
35#define ROWS 16 39/* Magnify is the number of pixels for each block.
36#define COLS 20 40 * Set dynamically so all targets can support levels
37#define SOKOBAN_LEVEL_SIZE (ROWS*COLS) 41 * that fill their entire screen, less the stat box.
38#define MAX_BUFFERED_BOARDS 500 42 * 16 rows & 20 cols minimum */
39/* Use either all but 12k of the plugin buffer for board data 43#if (LCD_HEIGHT >= 224) && (LCD_WIDTH >= 320)
40 or just enough for MAX_BUFFERED_BOARDS, which ever is less */ 44#define MAGNIFY 14
41#if (PLUGIN_BUFFER_SIZE - 0x3000)/SOKOBAN_LEVEL_SIZE < MAX_BUFFERED_BOARDS 45#define ROWS (LCD_HEIGHT/MAGNIFY)
42#define NUM_BUFFERED_BOARDS (PLUGIN_BUFFER_SIZE - 0x3000)/SOKOBAN_LEVEL_SIZE 46#define COLS ((LCD_WIDTH-40)/MAGNIFY)
47#elif (LCD_HEIGHT >= 249) && (LCD_WIDTH >= 280)
48#define MAGNIFY 14
49#define ROWS ((LCD_HEIGHT-25)/MAGNIFY)
50#define COLS (LCD_WIDTH/MAGNIFY)
51#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 220)
52#define MAGNIFY 9
53#define ROWS (LCD_HEIGHT/MAGNIFY)
54#define COLS ((LCD_WIDTH-40)/MAGNIFY)
55#elif (LCD_HEIGHT >= 169) && (LCD_WIDTH+4 >= 180) /* plus 4 for sansa */
56#define MAGNIFY 9
57#define ROWS ((LCD_HEIGHT-25)/MAGNIFY)
58#define COLS ((LCD_WIDTH+4)/MAGNIFY)
59#elif (LCD_HEIGHT >= 96) && (LCD_WIDTH >= 160)
60#define MAGNIFY 6
61#define ROWS (LCD_HEIGHT/MAGNIFY)
62#define COLS ((LCD_WIDTH-40)/MAGNIFY)
63#elif (LCD_HEIGHT >= 121) && (LCD_WIDTH >= 120)
64#define MAGNIFY 6
65#define ROWS ((LCD_HEIGHT-25)/MAGNIFY)
66#define COLS (LCD_WIDTH/MAGNIFY)
43#else 67#else
44#define NUM_BUFFERED_BOARDS MAX_BUFFERED_BOARDS 68#define MAGNIFY 4
69#define ROWS 16
70#define COLS 20
45#endif 71#endif
46/* Use 4k plus remaining plugin buffer (-8k for prog) for undo, up to 32k */ 72
47#if PLUGIN_BUFFER_SIZE - NUM_BUFFERED_BOARDS*SOKOBAN_LEVEL_SIZE - 0x2000 > \ 73/* Use either all but 16k of the plugin buffer for level data
48 0x7FFF 74 * or 128k, which ever is less */
49#define MAX_UNDOS 0x7FFF 75#if PLUGIN_BUFFER_SIZE - 0x4000 < 0x20000
76#define MAX_LEVEL_DATA (PLUGIN_BUFFER_SIZE - 0x4000)
77#else
78#define MAX_LEVEL_DATA 0x20000
79#endif
80
81/* Number of levels for which to allocate buffer indexes */
82#define MAX_LEVELS MAX_LEVEL_DATA/70
83
84/* Use 4k plus remaining plugin buffer (-12k for prog) for undo, up to 64k */
85#if PLUGIN_BUFFER_SIZE - MAX_LEVEL_DATA - 0x3000 > 0x10000
86#define MAX_UNDOS 0x10000
50#else 87#else
51#define MAX_UNDOS PLUGIN_BUFFER_SIZE - \ 88#define MAX_UNDOS (PLUGIN_BUFFER_SIZE - MAX_LEVEL_DATA - 0x3000)
52 NUM_BUFFERED_BOARDS*SOKOBAN_LEVEL_SIZE - 0x2000
53#endif 89#endif
54 90
55/* Move/push definitions for undo */ 91/* Move/push definitions for undo */
56enum { 92#define SOKOBAN_PUSH_LEFT 'L'
57 SOKOBAN_PUSH_LEFT, 93#define SOKOBAN_PUSH_RIGHT 'R'
58 SOKOBAN_PUSH_RIGHT, 94#define SOKOBAN_PUSH_UP 'U'
59 SOKOBAN_PUSH_UP, 95#define SOKOBAN_PUSH_DOWN 'D'
60 SOKOBAN_PUSH_DOWN, 96#define SOKOBAN_MOVE_LEFT 'l'
61 SOKOBAN_MOVE_LEFT, 97#define SOKOBAN_MOVE_RIGHT 'r'
62 SOKOBAN_MOVE_RIGHT, 98#define SOKOBAN_MOVE_UP 'u'
63 SOKOBAN_MOVE_UP, 99#define SOKOBAN_MOVE_DOWN 'd'
64 SOKOBAN_MOVE_DOWN 100
65}; 101#define SOKOBAN_MOVE_DIFF (SOKOBAN_MOVE_LEFT-SOKOBAN_PUSH_LEFT)
66#define SOKOBAN_MOVE_DIFF (SOKOBAN_MOVE_LEFT-SOKOBAN_PUSH_LEFT) 102#define SOKOBAN_MOVE_MIN SOKOBAN_MOVE_DOWN
67#define SOKOBAN_MOVE_MIN SOKOBAN_MOVE_LEFT
68 103
69/* variable button definitions */ 104/* variable button definitions */
70#if CONFIG_KEYPAD == RECORDER_PAD 105#if (CONFIG_KEYPAD == RECORDER_PAD) || \
106 (CONFIG_KEYPAD == ARCHOS_AV300_PAD)
71#define SOKOBAN_UP BUTTON_UP 107#define SOKOBAN_UP BUTTON_UP
72#define SOKOBAN_DOWN BUTTON_DOWN 108#define SOKOBAN_DOWN BUTTON_DOWN
73#define SOKOBAN_QUIT BUTTON_OFF 109#define SOKOBAN_MENU BUTTON_OFF
74#define SOKOBAN_UNDO BUTTON_ON 110#define SOKOBAN_UNDO BUTTON_ON
75#define SOKOBAN_REDO BUTTON_PLAY 111#define SOKOBAN_REDO BUTTON_PLAY
76#define SOKOBAN_LEVEL_UP BUTTON_F3
77#define SOKOBAN_LEVEL_DOWN BUTTON_F1 112#define SOKOBAN_LEVEL_DOWN BUTTON_F1
78#define SOKOBAN_LEVEL_REPEAT BUTTON_F2 113#define SOKOBAN_LEVEL_REPEAT BUTTON_F2
79
80#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
81#define SOKOBAN_UP BUTTON_UP
82#define SOKOBAN_DOWN BUTTON_DOWN
83#define SOKOBAN_QUIT BUTTON_OFF
84#define SOKOBAN_UNDO BUTTON_ON
85#define SOKOBAN_REDO BUTTON_PLAY
86#define SOKOBAN_LEVEL_UP BUTTON_F3 114#define SOKOBAN_LEVEL_UP BUTTON_F3
87#define SOKOBAN_LEVEL_DOWN BUTTON_F1 115#define BUTTON_SAVE BUTTON_ON
88#define SOKOBAN_LEVEL_REPEAT BUTTON_F2 116#define BUTTON_SAVE_NAME "ON"
89 117
90#elif CONFIG_KEYPAD == ONDIO_PAD 118#elif CONFIG_KEYPAD == ONDIO_PAD
91#define SOKOBAN_UP BUTTON_UP 119#define SOKOBAN_UP BUTTON_UP
92#define SOKOBAN_DOWN BUTTON_DOWN 120#define SOKOBAN_DOWN BUTTON_DOWN
93#define SOKOBAN_QUIT BUTTON_OFF 121#define SOKOBAN_MENU BUTTON_OFF
94#define SOKOBAN_UNDO_PRE BUTTON_MENU 122#define SOKOBAN_UNDO_PRE BUTTON_MENU
95#define SOKOBAN_UNDO (BUTTON_MENU | BUTTON_REL) 123#define SOKOBAN_UNDO (BUTTON_MENU | BUTTON_REL)
96#define SOKOBAN_REDO (BUTTON_MENU | BUTTON_DOWN) 124#define SOKOBAN_REDO (BUTTON_MENU | BUTTON_DOWN)
97#define SOKOBAN_LEVEL_UP (BUTTON_MENU | BUTTON_RIGHT)
98#define SOKOBAN_LEVEL_DOWN (BUTTON_MENU | BUTTON_LEFT) 125#define SOKOBAN_LEVEL_DOWN (BUTTON_MENU | BUTTON_LEFT)
99#define SOKOBAN_LEVEL_REPEAT (BUTTON_MENU | BUTTON_UP) 126#define SOKOBAN_LEVEL_REPEAT (BUTTON_MENU | BUTTON_UP)
127#define SOKOBAN_LEVEL_UP (BUTTON_MENU | BUTTON_RIGHT)
128#define BUTTON_SAVE BUTTON_MENU
129#define BUTTON_SAVE_NAME "MENU"
100 130
101#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 131#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
102 (CONFIG_KEYPAD == IRIVER_H300_PAD) 132 (CONFIG_KEYPAD == IRIVER_H300_PAD)
103#define SOKOBAN_UP BUTTON_UP 133#define SOKOBAN_UP BUTTON_UP
104#define SOKOBAN_DOWN BUTTON_DOWN 134#define SOKOBAN_DOWN BUTTON_DOWN
105#define SOKOBAN_QUIT BUTTON_OFF 135#define SOKOBAN_MENU BUTTON_OFF
106#define SOKOBAN_UNDO BUTTON_REC 136#define SOKOBAN_UNDO BUTTON_REC
107#define SOKOBAN_REDO BUTTON_MODE 137#define SOKOBAN_REDO BUTTON_MODE
108#define SOKOBAN_LEVEL_UP (BUTTON_ON | BUTTON_UP)
109#define SOKOBAN_LEVEL_DOWN (BUTTON_ON | BUTTON_DOWN) 138#define SOKOBAN_LEVEL_DOWN (BUTTON_ON | BUTTON_DOWN)
110#define SOKOBAN_LEVEL_REPEAT BUTTON_ON 139#define SOKOBAN_LEVEL_REPEAT BUTTON_ON
140#define SOKOBAN_LEVEL_UP (BUTTON_ON | BUTTON_UP)
141#define BUTTON_SAVE BUTTON_MODE
142#define BUTTON_SAVE_NAME "MODE"
111 143
112#define SOKOBAN_RC_QUIT BUTTON_RC_STOP 144#define SOKOBAN_RC_QUIT BUTTON_RC_STOP
113 145
@@ -115,65 +147,70 @@ enum {
115 (CONFIG_KEYPAD == IPOD_3G_PAD) 147 (CONFIG_KEYPAD == IPOD_3G_PAD)
116#define SOKOBAN_UP BUTTON_MENU 148#define SOKOBAN_UP BUTTON_MENU
117#define SOKOBAN_DOWN BUTTON_PLAY 149#define SOKOBAN_DOWN BUTTON_PLAY
118#define SOKOBAN_QUIT (BUTTON_SELECT | BUTTON_MENU) 150#define SOKOBAN_MENU (BUTTON_SELECT | BUTTON_MENU)
119#define SOKOBAN_UNDO_PRE BUTTON_SELECT 151#define SOKOBAN_UNDO_PRE BUTTON_SELECT
120#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL) 152#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL)
121#define SOKOBAN_REDO (BUTTON_SELECT | BUTTON_PLAY) 153#define SOKOBAN_REDO (BUTTON_SELECT | BUTTON_PLAY)
122#define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
123#define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT) 154#define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
155#define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
156#define BUTTON_SAVE BUTTON_SELECT
157#define BUTTON_SAVE_NAME "SELECT"
124 158
125/* fixme: if/when simultaneous button presses work for X5, 159/* FIXME: if/when simultaneous button presses work for X5,
126 add redo & level repeat */ 160 * add redo & level repeat */
127#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 161#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
128#define SOKOBAN_UP BUTTON_UP 162#define SOKOBAN_UP BUTTON_UP
129#define SOKOBAN_DOWN BUTTON_DOWN 163#define SOKOBAN_DOWN BUTTON_DOWN
130#define SOKOBAN_QUIT BUTTON_POWER 164#define SOKOBAN_MENU BUTTON_POWER
131#define SOKOBAN_UNDO_PRE BUTTON_SELECT 165#define SOKOBAN_UNDO_PRE BUTTON_SELECT
132#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL) 166#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL)
133#define SOKOBAN_LEVEL_UP BUTTON_PLAY
134#define SOKOBAN_LEVEL_DOWN BUTTON_REC 167#define SOKOBAN_LEVEL_DOWN BUTTON_REC
168#define SOKOBAN_LEVEL_UP BUTTON_PLAY
169#define BUTTON_SAVE BUTTON_SELECT
170#define BUTTON_SAVE_NAME "SELECT"
135 171
136#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 172#elif CONFIG_KEYPAD == IRIVER_H10_PAD
173#define SOKOBAN_UP BUTTON_SCROLL_UP
174#define SOKOBAN_DOWN BUTTON_SCROLL_DOWN
175#define SOKOBAN_MENU BUTTON_POWER
176#define SOKOBAN_UNDO_PRE BUTTON_REW
177#define SOKOBAN_UNDO (BUTTON_REW | BUTTON_REL)
178#define SOKOBAN_REDO BUTTON_FF
179#define SOKOBAN_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
180#define SOKOBAN_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT)
181#define SOKOBAN_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP)
182#define BUTTON_SAVE BUTTON_PLAY
183#define BUTTON_SAVE_NAME "PLAY"
184
185#elif CONFIG_KEYPAD == GIGABEAT_PAD
137#define SOKOBAN_UP BUTTON_UP 186#define SOKOBAN_UP BUTTON_UP
138#define SOKOBAN_DOWN BUTTON_DOWN 187#define SOKOBAN_DOWN BUTTON_DOWN
139#define SOKOBAN_QUIT BUTTON_POWER 188#define SOKOBAN_MENU BUTTON_POWER
140#define SOKOBAN_UNDO BUTTON_SELECT 189#define SOKOBAN_UNDO BUTTON_SELECT
141#define SOKOBAN_REDO BUTTON_A 190#define SOKOBAN_REDO BUTTON_A
142#define SOKOBAN_LEVEL_UP BUTTON_VOL_UP
143#define SOKOBAN_LEVEL_DOWN BUTTON_VOL_DOWN 191#define SOKOBAN_LEVEL_DOWN BUTTON_VOL_DOWN
144#define SOKOBAN_LEVEL_REPEAT BUTTON_MENU 192#define SOKOBAN_LEVEL_REPEAT BUTTON_MENU
193#define SOKOBAN_LEVEL_UP BUTTON_VOL_UP
194#define BUTTON_SAVE BUTTON_SELECT
195#define BUTTON_SAVE_NAME "SELECT"
145 196
146#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 197#elif CONFIG_KEYPAD == SANSA_E200_PAD
147#define SOKOBAN_UP BUTTON_UP 198#define SOKOBAN_UP BUTTON_UP
148#define SOKOBAN_DOWN BUTTON_DOWN 199#define SOKOBAN_DOWN BUTTON_DOWN
149#define SOKOBAN_QUIT BUTTON_POWER 200#define SOKOBAN_MENU BUTTON_POWER
150#define SOKOBAN_UNDO_PRE BUTTON_SELECT 201#define SOKOBAN_UNDO_PRE BUTTON_SELECT
151#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL) 202#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL)
152#define SOKOBAN_REDO BUTTON_REC 203#define SOKOBAN_REDO BUTTON_REC
153#define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_UP)
154#define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_DOWN) 204#define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_DOWN)
155#define SOKOBAN_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_RIGHT) 205#define SOKOBAN_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_RIGHT)
156 206#define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_UP)
157#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) 207#define BUTTON_SAVE BUTTON_SELECT
158#define SOKOBAN_UP BUTTON_SCROLL_UP 208#define BUTTON_SAVE_NAME "SELECT"
159#define SOKOBAN_DOWN BUTTON_SCROLL_DOWN
160#define SOKOBAN_QUIT BUTTON_POWER
161#define SOKOBAN_UNDO_PRE BUTTON_REW
162#define SOKOBAN_UNDO (BUTTON_REW | BUTTON_REL)
163#define SOKOBAN_REDO BUTTON_FF
164#define SOKOBAN_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP)
165#define SOKOBAN_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
166#define SOKOBAN_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT)
167 209
168#endif 210#endif
169 211
170#ifdef HAVE_LCD_COLOR 212#define SOKOBAN_FONT FONT_SYSFIXED
171/* Background color. Default Rockbox light blue. */
172#define BG_COLOR LCD_RGBPACK(181, 199, 231)
173 213
174#elif LCD_DEPTH >= 2
175#define MEDIUM_GRAY LCD_BRIGHTNESS(127)
176#endif
177 214
178/* The Location, Undo and LevelInfo structs are OO-flavored. 215/* The Location, Undo and LevelInfo structs are OO-flavored.
179 * (oooh!-flavored as Schnueff puts it.) It makes more you have to know, 216 * (oooh!-flavored as Schnueff puts it.) It makes more you have to know,
@@ -181,10 +218,12 @@ enum {
181 218
182/* Level data & stats */ 219/* Level data & stats */
183struct LevelInfo { 220struct LevelInfo {
184 short level; 221 short index; /* Level index (level number - 1) */
185 short moves; 222 int moves; /* Moves & pushes for the stats */
186 short pushes; 223 int pushes;
187 short boxes_to_go; 224 short boxes_to_go; /* Number of unplaced boxes remaining in level */
225 short height; /* Height & width for centering level display */
226 short width;
188}; 227};
189 228
190struct Location { 229struct Location {
@@ -192,39 +231,42 @@ struct Location {
192 short col; 231 short col;
193}; 232};
194 233
195struct Board {
196 char spaces[ROWS][COLS];
197};
198
199/* Our full undo history */ 234/* Our full undo history */
200static struct UndoInfo { 235static struct UndoInfo {
201 short count; /* How many undos are left */ 236 int count; /* How many undos have been done */
202 short current; /* Which history is the current undo */ 237 int current; /* Which history is the current undo */
203 short max; /* Which history is the max redoable */ 238 int max; /* Which history is the max redoable */
204 char history[MAX_UNDOS]; 239 char history[MAX_UNDOS];
205} undo_info; 240} undo_info;
206 241
207/* Our playing board */ 242/* Our playing board */
208static struct BoardInfo { 243static struct BoardInfo {
209 char board[ROWS][COLS]; 244 char board[ROWS][COLS]; /* The current board data */
210 struct LevelInfo level; 245 struct LevelInfo level; /* Level data & stats */
211 struct Location player; 246 struct Location player; /* Where the player is */
212 int max_level; /* How many levels do we have? */ 247 int max_level; /* The number of levels we have */
213 int loaded_level; /* Which level is in memory */
214} current_info; 248} current_info;
215 249
216static struct BufferedBoards { 250static struct BufferedBoards {
217 struct Board levels[NUM_BUFFERED_BOARDS]; 251 char filename[MAX_PATH]; /* Filename of the levelset we're using */
218 int low; 252 char data[MAX_LEVEL_DATA]; /* Buffered level data */
253 int index[MAX_LEVELS + 1]; /* Where each buffered board begins & ends */
254 int start; /* Index of first buffered board */
255 int end; /* Index of last buffered board */
256 short prebuffered_boards; /* Number of boards before current to store */
219} buffered_boards; 257} buffered_boards;
220 258
259
221static struct plugin_api* rb; 260static struct plugin_api* rb;
222 261
262static char buf[ROWS*(COLS + 1)]; /* Enough for a whole board or a filename */
263
264
223static void init_undo(void) 265static void init_undo(void)
224{ 266{
225 undo_info.count = 0; 267 undo_info.count = 0;
226 undo_info.current = -1; 268 undo_info.current = 0;
227 undo_info.max = -1; 269 undo_info.max = 0;
228} 270}
229 271
230static void get_delta(char direction, short *d_r, short *d_c) 272static void get_delta(char direction, short *d_r, short *d_c)
@@ -261,9 +303,17 @@ static void undo(void)
261 bool undo_push = false; 303 bool undo_push = false;
262 304
263 /* If no more undos or we've wrapped all the way around, quit */ 305 /* If no more undos or we've wrapped all the way around, quit */
264 if (undo_info.count == 0 || undo_info.current-1 == undo_info.max) 306 if (undo_info.count == 0 || undo_info.current - 1 == undo_info.max)
265 return; 307 return;
266 308
309 /* Move to previous undo in the list */
310 if (undo_info.current == 0 && undo_info.count > 1)
311 undo_info.current = MAX_UNDOS - 1;
312 else
313 undo_info.current--;
314
315 undo_info.count--;
316
267 undo = undo_info.history[undo_info.current]; 317 undo = undo_info.history[undo_info.current];
268 318
269 if (undo < SOKOBAN_MOVE_MIN) 319 if (undo < SOKOBAN_MOVE_MIN)
@@ -281,17 +331,17 @@ static void undo(void)
281 331
282 /* Update board info */ 332 /* Update board info */
283 if (undo_push) { 333 if (undo_push) {
284 /* Moving box from goal to blank */ 334 /* Moving box from goal to floor */
285 if (*space_next == '%' && *space_cur == '@') 335 if (*space_next == '*' && *space_cur == '@')
286 current_info.level.boxes_to_go++; 336 current_info.level.boxes_to_go++;
287 /* Moving box from blank to goal */ 337 /* Moving box from floor to goal */
288 else if (*space_next == '$' && *space_cur == '+') 338 else if (*space_next == '$' && *space_cur == '+')
289 current_info.level.boxes_to_go--; 339 current_info.level.boxes_to_go--;
290 340
291 /* Move box off of next space... */ 341 /* Move box off of next space... */
292 *space_next = (*space_next == '%' ? '.' : ' '); 342 *space_next = (*space_next == '*' ? '.' : ' ');
293 /* ...and on to current space */ 343 /* ...and on to current space */
294 *space_cur = (*space_cur == '+' ? '%' : '$'); 344 *space_cur = (*space_cur == '+' ? '*' : '$');
295 345
296 current_info.level.pushes--; 346 current_info.level.pushes--;
297 } else 347 } else
@@ -306,27 +356,19 @@ static void undo(void)
306 356
307 current_info.level.moves--; 357 current_info.level.moves--;
308 358
309 /* Move to previous undo in the list */
310 if (undo_info.current == 0 && undo_info.count > 1)
311 undo_info.current = MAX_UNDOS - 1;
312 else
313 undo_info.current--;
314
315 undo_info.count--;
316
317 return; 359 return;
318} 360}
319 361
320static void add_undo(char undo) 362static void add_undo(char undo)
321{ 363{
364 undo_info.history[undo_info.current] = undo;
365
322 /* Wrap around if MAX_UNDOS exceeded */ 366 /* Wrap around if MAX_UNDOS exceeded */
323 if (undo_info.current < (MAX_UNDOS - 1)) 367 if (undo_info.current < (MAX_UNDOS - 1))
324 undo_info.current++; 368 undo_info.current++;
325 else 369 else
326 undo_info.current = 0; 370 undo_info.current = 0;
327 371
328 undo_info.history[undo_info.current] = undo;
329
330 if (undo_info.count < MAX_UNDOS) 372 if (undo_info.count < MAX_UNDOS)
331 undo_info.count++; 373 undo_info.count++;
332} 374}
@@ -353,34 +395,37 @@ static bool move(char direction, bool redo)
353 space_next = &current_info.board[r + d_r][c + d_c]; 395 space_next = &current_info.board[r + d_r][c + d_c];
354 space_beyond = &current_info.board[r + 2*d_r][c + 2*d_c]; 396 space_beyond = &current_info.board[r + 2*d_r][c + 2*d_c];
355 397
356 if (*space_next == '$' || *space_next == '%') { 398 if (*space_next == '$' || *space_next == '*') {
357 /* Change direction from move to push for undo */ 399 /* Change direction from move to push for undo */
358 if (direction >= SOKOBAN_MOVE_MIN) 400 if (direction >= SOKOBAN_MOVE_MIN)
359 direction -= SOKOBAN_MOVE_DIFF; 401 direction -= SOKOBAN_MOVE_DIFF;
360 push = true; 402 push = true;
361 } 403 }
404 else if (direction < SOKOBAN_MOVE_MIN)
405 /* Change back to move if redo/solution playback push is invalid */
406 direction += SOKOBAN_MOVE_DIFF;
362 407
363 /* Update board info */ 408 /* Update board info */
364 if (push) { 409 if (push) {
365 /* Moving box from goal to blank */ 410 /* Moving box from goal to floor */
366 if (*space_next == '%' && *space_beyond == ' ') 411 if (*space_next == '*' && *space_beyond == ' ')
367 current_info.level.boxes_to_go++; 412 current_info.level.boxes_to_go++;
368 /* Moving box from blank to goal */ 413 /* Moving box from floor to goal */
369 else if (*space_next == '$' && *space_beyond == '.') 414 else if (*space_next == '$' && *space_beyond == '.')
370 current_info.level.boxes_to_go--; 415 current_info.level.boxes_to_go--;
371 /* Check for illegal move */ 416 /* Check for invalid move */
372 else if (*space_beyond != '.' && *space_beyond != ' ') 417 else if (*space_beyond != '.' && *space_beyond != ' ')
373 return false; 418 return false;
374 419
375 /* Move player onto next space */ 420 /* Move player onto next space */
376 *space_next = (*space_next == '%' ? '+' : '@'); 421 *space_next = (*space_next == '*' ? '+' : '@');
377 /* Move box onto space beyond next */ 422 /* Move box onto space beyond next */
378 *space_beyond = (*space_beyond == '.' ? '%' : '$'); 423 *space_beyond = (*space_beyond == '.' ? '*' : '$');
379 424
380 current_info.level.pushes++; 425 current_info.level.pushes++;
381 } else { 426 } else {
382 /* Check for illegal move */ 427 /* Check for invalid move */
383 if (*space_next == '#' || *space_next == 'X') 428 if (*space_next != '.' && *space_next != ' ')
384 return false; 429 return false;
385 430
386 /* Move player onto next space */ 431 /* Move player onto next space */
@@ -396,19 +441,19 @@ static bool move(char direction, bool redo)
396 current_info.level.moves++; 441 current_info.level.moves++;
397 442
398 /* Update undo_info.max to current on every normal move, 443 /* Update undo_info.max to current on every normal move,
399 except if it's the same as a redo. */ 444 * except if it's the same as a redo. */
400 /* normal move */ 445 /* normal move and either */
401 if (!redo && 446 if (!redo &&
402 /* moves have been undone */ 447 /* moves have been undone... */
403 ((undo_info.max != undo_info.current && 448 ((undo_info.max != undo_info.current &&
404 /* and the current move is NOT the same as the one in history */ 449 /* ...and the current move is NOT the same as the one in history */
405 undo_info.history[undo_info.current+1] != direction) || 450 undo_info.history[undo_info.current] != direction) ||
406 /* or moves have not been undone */ 451 /* or moves have not been undone */
407 undo_info.max == undo_info.current)) { 452 undo_info.max == undo_info.current)) {
408 add_undo(direction); 453 add_undo(direction);
409 undo_info.max = undo_info.current; 454 undo_info.max = undo_info.current;
410 } else /* redo move or move was same as redo */ 455 } else /* redo move or move was same as redo */
411 add_undo(direction); /* (just to update current) */ 456 add_undo(direction); /* add_undo to update current */
412 457
413 return true; 458 return true;
414} 459}
@@ -420,290 +465,370 @@ static bool redo(void)
420 if (undo_info.current == undo_info.max) 465 if (undo_info.current == undo_info.max)
421 return false; 466 return false;
422 467
423 return move(undo_info.history[(undo_info.current+1 < MAX_UNDOS ? 468 return move(undo_info.history[(undo_info.current < MAX_UNDOS ?
424 undo_info.current+1 : 0)], true); 469 undo_info.current : 0)], true);
425} 470}
426#endif 471#endif
427 472
428static void init_boards(void) 473static void init_boards(void)
429{ 474{
430 current_info.level.level = 0; 475 rb->strncpy(buffered_boards.filename, SOKOBAN_LEVELS_FILE, MAX_PATH);
431 current_info.level.moves = 0; 476
432 current_info.level.pushes = 0; 477 current_info.level.index = 0;
433 current_info.level.boxes_to_go = 0;
434 current_info.player.row = 0; 478 current_info.player.row = 0;
435 current_info.player.col = 0; 479 current_info.player.col = 0;
436 current_info.max_level = 0; 480 current_info.max_level = 0;
437 current_info.loaded_level = 0;
438 481
439 buffered_boards.low = 0; 482 buffered_boards.start = 0;
483 buffered_boards.end = 0;
484 buffered_boards.prebuffered_boards = 0;
440 485
441 init_undo(); 486 init_undo();
442} 487}
443 488
444static int read_levels(int initialize_count) 489static bool read_levels(bool initialize)
445{ 490{
446 int fd = 0; 491 int fd = 0;
447 int len; 492 short len;
448 int lastlen = 0; 493 short lastlen = 0;
449 int row = 0; 494 short row = 0;
450 int level_count = 0; 495 int level_count = 0;
451 char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
452 int endpoint = current_info.level.level-1;
453
454 if (endpoint < buffered_boards.low)
455 endpoint = current_info.level.level - NUM_BUFFERED_BOARDS;
456 496
457 if (endpoint < 0) endpoint = 0; 497 int i = 0;
498 int level_len = 0;
499 bool index_set = false;
458 500
459 buffered_boards.low = endpoint; 501 /* Get the index of the first level to buffer */
460 endpoint += NUM_BUFFERED_BOARDS; 502 if (current_info.level.index > buffered_boards.prebuffered_boards &&
503 !initialize)
504 buffered_boards.start = current_info.level.index -
505 buffered_boards.prebuffered_boards;
506 else
507 buffered_boards.start = 0;
461 508
462 if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) { 509 if ((fd = rb->open(buffered_boards.filename, O_RDONLY)) < 0) {
463 rb->splash(HZ*2, "Unable to open %s", LEVELS_FILE); 510 rb->splash(HZ*2, "Unable to open %s", buffered_boards.filename);
464 return -1; 511 return false;
465 } 512 }
466 513
467 do { 514 do {
468 len = rb->read_line(fd, buffer, sizeof(buffer)); 515 len = rb->read_line(fd, buf, sizeof(buf));
469 if (len >= 3) { 516
470 /* This finds lines that are more than 1 or 2 characters 517 /* Correct len when trailing \r's or \n's are counted */
471 * shorter than they should be. Due to the possibility of 518 if (len > 2 && buf[len - 2] == '\0')
472 * a mixed unix and dos CR/LF file format, I'm not going to 519 len -= 2;
473 * do a precise check */ 520 else if (len > 1 && buf[len - 1] == '\0')
474 if (len < COLS) { 521 len--;
475 rb->splash(HZ*2, "Error in levels file: short line"); 522
476 return -1; 523 /* Skip short lines & lines with non-level data */
477 } 524 if (len >= 3 && ((buf[0] >= '1' && buf[0] <= '9') || buf[0] == '#' ||
478 if (level_count >= buffered_boards.low && level_count < endpoint) { 525 buf[0] == ' ' || buf[0] == '-' || buf[0] == '_')) {
479 int index = level_count - buffered_boards.low; 526 if (level_count >= buffered_boards.start) {
480 rb->memcpy( 527 /* Set the index of this level */
481 buffered_boards.levels[index].spaces[row], buffer, COLS); 528 if (!index_set &&
529 level_count - buffered_boards.start < MAX_LEVELS) {
530 buffered_boards.index[level_count - buffered_boards.start]
531 = i;
532 index_set = true;
533 }
534 /* Copy buffer to board data */
535 if (i + level_len + len < MAX_LEVEL_DATA) {
536 rb->memcpy(&buffered_boards.data[i + level_len], buf, len);
537 buffered_boards.data[i + level_len + len] = '\n';
538 }
482 } 539 }
540 level_len += len + 1;
483 row++; 541 row++;
484 } else if (len) { 542
485 if (lastlen < 3) { 543 /* If newline & level is tall enough or is RLE */
486 /* Two short lines in a row means new level */ 544 } else if (buf[0] == '\0' && (row > 2 || lastlen > 22)) {
487 level_count++; 545 level_count++;
488 if (level_count >= endpoint && !initialize_count) break; 546 if (level_count >= buffered_boards.start) {
489 if (level_count && row != ROWS) { 547 i += level_len;
490 rb->splash(HZ*2, "Error in levels file: short board"); 548 if (i < MAX_LEVEL_DATA)
491 return -1; 549 buffered_boards.end = level_count;
492 } 550 else if (!initialize)
493 row = 0; 551 break;
494 } 552 }
495 } 553 row = 0;
496 } while ((lastlen=len)); 554 level_len = 0;
555 index_set = false;
497 556
498 rb->close(fd); 557 } else if (len > 22)
499 if (initialize_count) { 558 len = 1;
500 /* Plus one because there aren't trailing short lines in the file */ 559
501 current_info.max_level = level_count + 1; 560 } while ((lastlen = len));
561
562 /* Set the index of the end of the last level */
563 if (level_count - buffered_boards.start < MAX_LEVELS)
564 buffered_boards.index[level_count - buffered_boards.start] = i;
565
566 if (initialize) {
567 current_info.max_level = level_count;
568 buffered_boards.prebuffered_boards = buffered_boards.end/2;
502 } 569 }
503 return 0; 570
571 rb->close(fd);
572
573 return true;
504} 574}
505 575
506/* return non-zero on error */
507static void load_level(void) 576static void load_level(void)
508{ 577{
509 int c = 0; 578 int c, r;
510 int r = 0; 579 int i, n;
511 int index = current_info.level.level - buffered_boards.low - 1; 580 int level_size;
512 struct Board *level; 581 int index = current_info.level.index - buffered_boards.start;
513 582 char *level;
514 if (index < 0 || index >= NUM_BUFFERED_BOARDS) { 583
584 /* Get the buffered board index of the current level */
585 if (current_info.level.index < buffered_boards.start ||
586 current_info.level.index >= buffered_boards.end) {
515 read_levels(false); 587 read_levels(false);
516 index = index < 0 ? NUM_BUFFERED_BOARDS-1 : 0; 588 if (current_info.level.index > buffered_boards.prebuffered_boards)
589 index = buffered_boards.prebuffered_boards;
590 else
591 index = current_info.level.index;
517 } 592 }
518 level = &buffered_boards.levels[index]; 593 level = &buffered_boards.data[buffered_boards.index[index]];
519 594
520 current_info.level.boxes_to_go = 0; 595 /* Reset level info */
521 current_info.level.moves = 0; 596 current_info.level.moves = 0;
522 current_info.level.pushes = 0; 597 current_info.level.pushes = 0;
523 current_info.loaded_level = current_info.level.level; 598 current_info.level.boxes_to_go = 0;
599 current_info.level.width = 0;
600
601 /* Clear board */
602 for (r = 0; r < ROWS; r++)
603 for (c = 0; c < COLS; c++)
604 current_info.board[r][c] = 'X';
605
606 level_size = buffered_boards.index[index + 1] -
607 buffered_boards.index[index];
608
609 for (r = 0, c = 0, n = 1, i = 0; i < level_size; i++) {
610 if (level[i] == '\n' || level[i] == '|') {
611 if (c > 3) {
612 /* Update max width of level & go to next row */
613 if (c > current_info.level.width)
614 current_info.level.width = c;
615 c = 0;
616 r++;
617 if (r >= ROWS)
618 break;
619 }
620 } else if (c < COLS) {
621 /* Read RLE character's length into n */
622 if (level[i] >= '0' && level[i] <= '9') {
623 n = level[i++] - '0';
624 if (level[i] >= '0' && level[i] <= '9')
625 n = n*10 + level[i++] - '0';
626 }
627
628 /* Cleanup & replace */
629 if (level[i] == '%')
630 level[i] = '*';
631 else if (level[i] == '-' || level[i] == '_')
632 level[i] = ' ';
633
634 if (n > 1) {
635 if (c + n >= COLS)
636 n = COLS - c;
524 637
525 for (r = 0; r < ROWS; r++) { 638 if (level[i] == '.')
526 for (c = 0; c < COLS; c++) { 639 current_info.level.boxes_to_go += n;
527 current_info.board[r][c] = level->spaces[r][c];
528 640
529 if (current_info.board[r][c] == '.' || 641 /* Put RLE character n times */
530 current_info.board[r][c] == '+') 642 while (n--)
531 current_info.level.boxes_to_go++; 643 current_info.board[r][c++] = level[i];
644 n = 1;
532 645
533 if (current_info.board[r][c] == '@' || 646 } else {
534 current_info.board[r][c] == '+') { 647 if (level[i] == '.' || level[i] == '+')
535 current_info.player.row = r; 648 current_info.level.boxes_to_go++;
536 current_info.player.col = c; 649
650 if (level[i] == '@' ||level[i] == '+') {
651 current_info.player.row = r;
652 current_info.player.col = c;
653 }
654
655 current_info.board[r][c++] = level[i];
537 } 656 }
538 } 657 }
539 } 658 }
659
660 current_info.level.height = r;
661
662#if LCD_DEPTH > 2
663 /* Fill in blank space outside level on color targets */
664 for (r = 0; r < ROWS; r++)
665 for (c = 0; current_info.board[r][c] == ' ' && c < COLS; c++)
666 current_info.board[r][c] = 'X';
667
668 for (c = 0; c < COLS; c++) {
669 for (r = 0; (current_info.board[r][c] == ' ' ||
670 current_info.board[r][c] == 'X') && r < ROWS; r++)
671 current_info.board[r][c] = 'X';
672 for (r = ROWS - 1; (current_info.board[r][c] == ' ' ||
673 current_info.board[r][c] == 'X') && r >= 0; r--)
674 current_info.board[r][c] = 'X';
675 }
676#endif
540} 677}
541 678
542static void update_screen(void) 679static void update_screen(void)
543{ 680{
544 int b = 0, c = 0; 681 int c, r;
545 int rows = 0, cols = 0; 682 int rows, cols;
546 char s[25];
547
548/* magnify is the number of pixels for each block */
549#if (LCD_HEIGHT >= 224) && (LCD_WIDTH >= 312) || \
550 (LCD_HEIGHT >= 249) && (LCD_WIDTH >= 280) /* ipod 5g */
551#define MAGNIFY 14
552#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 212) || \
553 (LCD_HEIGHT >= 169) && (LCD_WIDTH >= 180-4) /* h3x0, ipod color/photo */
554#define MAGNIFY 9
555#elif (LCD_HEIGHT >= 96) && (LCD_WIDTH >= 152) || \
556 (LCD_HEIGHT >= 121) && (LCD_WIDTH >= 120) /* h1x0, ipod nano/mini */
557#define MAGNIFY 6
558#else /* other */
559#define MAGNIFY 4
560#endif
561 683
562#if LCD_DEPTH < 2 684#if LCD_DEPTH < 2 || ((LCD_HEIGHT < 96 || LCD_WIDTH < 152) && \
685 (LCD_HEIGHT < 121 || LCD_WIDTH < 120))
563 int i, j; 686 int i, j;
564 int max = MAGNIFY - 1; 687 int max = MAGNIFY - 1;
565 int middle = max / 2; 688 int middle = max/2;
566 int ldelta = (middle + 1) / 2; 689 int ldelta = (middle + 1)/2;
567#endif 690#endif
568 691
569 /* load the board to the screen */ 692#if LCD_WIDTH - (COLS*MAGNIFY) < 32
570 for (rows=0; rows < ROWS; rows++) { 693#define STAT_HEIGHT 25
571 for (cols = 0; cols < COLS; cols++) { 694#define STAT_X (LCD_WIDTH - 120)/2
572 c = cols * MAGNIFY; 695#define STAT_Y (LCD_HEIGHT - STAT_HEIGHT)
573 b = rows * MAGNIFY; 696#define BOARD_WIDTH LCD_WIDTH
574 697#define BOARD_HEIGHT (LCD_HEIGHT - STAT_HEIGHT)
575 switch(current_info.board[rows][cols]) { 698 rb->lcd_putsxy(STAT_X + 4, STAT_Y + 4, "Level");
576 case 'X': /* black space */ 699 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.index + 1);
577 break; 700 rb->lcd_putsxy(STAT_X + 7, STAT_Y + 14, buf);
578 701 rb->lcd_putsxy(STAT_X + 41, STAT_Y + 4, "Moves");
579 case '#': /* this is a wall */ 702 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.moves);
580#if LCD_DEPTH >= 2 703 rb->lcd_putsxy(STAT_X + 44, STAT_Y + 14, buf);
581 rb->lcd_bitmap_part(sokoban_tiles, 0, 1*MAGNIFY, MAGNIFY, 704 rb->lcd_putsxy(STAT_X + 79, STAT_Y + 4, "Pushes");
582 c, b, MAGNIFY, MAGNIFY); 705 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.pushes);
706 rb->lcd_putsxy(STAT_X + 82, STAT_Y + 14, buf);
707
708 rb->lcd_drawrect(STAT_X, STAT_Y, 38, STAT_HEIGHT);
709 rb->lcd_drawrect(STAT_X + 37, STAT_Y, 39, STAT_HEIGHT);
710 rb->lcd_drawrect(STAT_X + 75, STAT_Y, 45, STAT_HEIGHT);
583#else 711#else
584 for (i = c; i < c + MAGNIFY; i++) 712#if LCD_WIDTH - (COLS*MAGNIFY) > 40
585 for (j = b; j < b + MAGNIFY; j++) 713#define STAT_X (LCD_WIDTH - 40)
586 if ((i ^ j) & 1) 714#else
587 rb->lcd_drawpixel(i, j); 715#define STAT_X COLS*MAGNIFY
588#endif 716#endif
589 break; 717#if LCD_HEIGHT >= 70
590 718#define STAT_Y (LCD_HEIGHT - 70)/2
591 case '$': /* this is a box */
592#if LCD_DEPTH >= 2
593 rb->lcd_bitmap_part(sokoban_tiles, 0, 2*MAGNIFY, MAGNIFY,
594 c, b, MAGNIFY, MAGNIFY);
595#else 719#else
596 /* Free boxes are not filled in */ 720#define STAT_Y (LCD_HEIGHT - 47)/2
597 rb->lcd_drawrect(c, b, MAGNIFY, MAGNIFY);
598#endif 721#endif
599 break; 722#define STAT_WIDTH (LCD_WIDTH - STAT_X)
723#define BOARD_WIDTH (LCD_WIDTH - STAT_WIDTH)
724#define BOARD_HEIGHT LCD_HEIGHT
725 rb->lcd_putsxy(STAT_X + 1, STAT_Y + 3, "Level");
726 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.index + 1);
727 rb->lcd_putsxy(STAT_X + 4, STAT_Y + 13, buf);
728 rb->lcd_putsxy(STAT_X + 1, STAT_Y + 26, "Moves");
729 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.moves);
730 rb->lcd_putsxy(STAT_X + 4, STAT_Y + 36, buf);
731
732 rb->lcd_drawrect(STAT_X, STAT_Y + 0, STAT_WIDTH, 24);
733 rb->lcd_drawrect(STAT_X, STAT_Y + 23, STAT_WIDTH, 24);
600 734
601 case '*': 735#if LCD_HEIGHT >= 70
602 case '%': /* this is a box on a goal */ 736 rb->lcd_putsxy(STAT_X + 1, STAT_Y + 49, "Pushes");
737 rb->snprintf(buf, sizeof(buf), "%d", current_info.level.pushes);
738 rb->lcd_putsxy(STAT_X + 4, STAT_Y + 59, buf);
603 739
604#if LCD_DEPTH >= 2 740 rb->lcd_drawrect(STAT_X, STAT_Y + 46, STAT_WIDTH, 24);
605 rb->lcd_bitmap_part(sokoban_tiles, 0, 3*MAGNIFY, MAGNIFY,
606 c, b, MAGNIFY, MAGNIFY );
607#else
608 rb->lcd_drawrect(c, b, MAGNIFY, MAGNIFY);
609 rb->lcd_drawrect(c+(MAGNIFY/2)-1, b+(MAGNIFY/2)-1, MAGNIFY/2,
610 MAGNIFY/2);
611#endif 741#endif
612 break;
613 742
614 case '.': /* this is a goal */
615#if LCD_DEPTH >= 2
616 rb->lcd_bitmap_part(sokoban_tiles, 0, 4*MAGNIFY, MAGNIFY,
617 c, b, MAGNIFY, MAGNIFY);
618#else
619 rb->lcd_drawrect(c+(MAGNIFY/2)-1, b+(MAGNIFY/2)-1, MAGNIFY/2,
620 MAGNIFY/2);
621#endif 743#endif
622 break;
623 744
624 case '@': /* this is you */ 745 /* load the board to the screen */
625#if LCD_DEPTH >= 2 746 for (rows = 0; rows < ROWS; rows++) {
626 rb->lcd_bitmap_part(sokoban_tiles, 0, 5*MAGNIFY, MAGNIFY, 747 for (cols = 0; cols < COLS; cols++) {
627 c, b, MAGNIFY, MAGNIFY); 748 c = cols*MAGNIFY +
628#else 749 (BOARD_WIDTH - current_info.level.width*MAGNIFY)/2;
629 rb->lcd_drawline(c, b+middle, c+max, b+middle); 750 r = rows*MAGNIFY +
630 rb->lcd_drawline(c+middle, b, c+middle, b+max-ldelta); 751 (BOARD_HEIGHT - current_info.level.height*MAGNIFY)/2;
631 rb->lcd_drawline(c+max-middle, b,
632 c+max-middle, b+max-ldelta);
633 rb->lcd_drawline(c+middle, b+max-ldelta,
634 c+middle-ldelta, b+max);
635 rb->lcd_drawline(c+max-middle, b+max-ldelta,
636 c+max-middle+ldelta, b+max);
637#endif
638 break;
639 752
640 case '+': /* this is you on drugs, erm, on a goal */ 753 switch(current_info.board[rows][cols]) {
641#if LCD_DEPTH >= 2 754 case 'X': /* blank space outside of level */
642 rb->lcd_bitmap_part(sokoban_tiles, 0, 6*MAGNIFY, MAGNIFY, 755 break;
643 c, b, MAGNIFY, MAGNIFY );
644#else
645 rb->lcd_drawline(c, b+middle, c+max, b+middle);
646 rb->lcd_drawline(c+middle, b, c+middle, b+max-ldelta);
647 rb->lcd_drawline(c+max-middle, b, c+max-middle, b+max-ldelta);
648 rb->lcd_drawline(c+middle, b+max-ldelta, c+middle-ldelta,
649 b+max);
650 rb->lcd_drawline(c+max-middle, b+max-ldelta,
651 c+max-middle+ldelta, b+max);
652 rb->lcd_drawline(c+middle-1, b+middle+1, c+max-middle+1,
653 b+middle+1);
654#endif
655 break;
656 756
657#if LCD_DEPTH >= 2 757#if LCD_DEPTH >= 2 && ((LCD_HEIGHT >= 96 && LCD_WIDTH >= 152) || \
658 default: 758 (LCD_HEIGHT >= 121 && LCD_WIDTH >= 120))
659 rb->lcd_bitmap_part(sokoban_tiles, 0, 0*MAGNIFY, MAGNIFY, 759 case ' ': /* floor */
660 c, b, MAGNIFY, MAGNIFY ); 760 rb->lcd_bitmap_part(sokoban_tiles, 0, 0*MAGNIFY, MAGNIFY,
661#endif 761 c, r, MAGNIFY, MAGNIFY);
662 } 762 break;
663 }
664 }
665 763
666#if LCD_WIDTH-(COLS*MAGNIFY) < 32 764 case '#': /* wall */
667#define STAT_SIZE 25 765 rb->lcd_bitmap_part(sokoban_tiles, 0, 1*MAGNIFY, MAGNIFY,
668#define STAT_POS LCD_HEIGHT-STAT_SIZE 766 c, r, MAGNIFY, MAGNIFY);
669#define STAT_CENTER (LCD_WIDTH-120)/2 767 break;
670 768
671 rb->lcd_putsxy(4+STAT_CENTER, STAT_POS+4, "Level"); 769 case '$': /* box */
672 rb->snprintf(s, sizeof(s), "%d", current_info.level.level); 770 rb->lcd_bitmap_part(sokoban_tiles, 0, 2*MAGNIFY, MAGNIFY,
673 rb->lcd_putsxy(7+STAT_CENTER, STAT_POS+14, s); 771 c, r, MAGNIFY, MAGNIFY);
674 rb->lcd_putsxy(41+STAT_CENTER, STAT_POS+4, "Moves"); 772 break;
675 rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
676 rb->lcd_putsxy(44+STAT_CENTER, STAT_POS+14, s);
677 rb->lcd_putsxy(79+STAT_CENTER, STAT_POS+4, "Pushes");
678 rb->snprintf(s, sizeof(s), "%d", current_info.level.pushes);
679 rb->lcd_putsxy(82+STAT_CENTER, STAT_POS+14, s);
680
681 rb->lcd_drawrect(STAT_CENTER, STAT_POS, 38, STAT_SIZE);
682 rb->lcd_drawrect(37+STAT_CENTER, STAT_POS, 39, STAT_SIZE);
683 rb->lcd_drawrect(75+STAT_CENTER, STAT_POS, 45, STAT_SIZE);
684 773
774 case '*': /* box on goal */
775 rb->lcd_bitmap_part(sokoban_tiles, 0, 3*MAGNIFY, MAGNIFY,
776 c, r, MAGNIFY, MAGNIFY);
777 break;
778
779 case '.': /* goal */
780 rb->lcd_bitmap_part(sokoban_tiles, 0, 4*MAGNIFY, MAGNIFY,
781 c, r, MAGNIFY, MAGNIFY);
782 break;
783
784 case '@': /* player */
785 rb->lcd_bitmap_part(sokoban_tiles, 0, 5*MAGNIFY, MAGNIFY,
786 c, r, MAGNIFY, MAGNIFY);
787 break;
788
789 case '+': /* player on goal */
790 rb->lcd_bitmap_part(sokoban_tiles, 0, 6*MAGNIFY, MAGNIFY,
791 c, r, MAGNIFY, MAGNIFY);
792 break;
685#else 793#else
686#define STAT_POS COLS*MAGNIFY 794 case '#': /* wall */
687#define STAT_SIZE LCD_WIDTH-STAT_POS 795 for (i = c; i < c + MAGNIFY; i++)
796 for (j = r; j < r + MAGNIFY; j++)
797 if ((i ^ j) & 1)
798 rb->lcd_drawpixel(i, j);
799 break;
688 800
689 rb->lcd_putsxy(STAT_POS+1, 3, "Level"); 801 case '$': /* box */
690 rb->snprintf(s, sizeof(s), "%d", current_info.level.level); 802 rb->lcd_drawrect(c, r, MAGNIFY, MAGNIFY);
691 rb->lcd_putsxy(STAT_POS+4, 13, s); 803 break;
692 rb->lcd_putsxy(STAT_POS+1, 26, "Moves");
693 rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
694 rb->lcd_putsxy(STAT_POS+4, 36, s);
695 804
696 rb->lcd_drawrect(STAT_POS, 0, STAT_SIZE, 24); 805 case '*': /* box on goal */
697 rb->lcd_drawrect(STAT_POS, 23, STAT_SIZE, 24); 806 rb->lcd_drawrect(c, r, MAGNIFY, MAGNIFY);
807 rb->lcd_drawrect(c + MAGNIFY/2 - 1, r + MAGNIFY/2 - 1,
808 MAGNIFY/2, MAGNIFY/2);
809 break;
698 810
699#if LCD_HEIGHT >= 70 811 case '.': /* goal */
700 rb->lcd_putsxy(STAT_POS+1, 49, "Pushes"); 812 rb->lcd_drawrect(c + MAGNIFY/2 - 1, r + MAGNIFY/2 - 1,
701 rb->snprintf(s, sizeof(s), "%d", current_info.level.pushes); 813 MAGNIFY/2, MAGNIFY/2);
702 rb->lcd_putsxy(STAT_POS+4, 59, s); 814 break;
703 815
704 rb->lcd_drawrect(STAT_POS, 46, STAT_SIZE, 24); 816 case '@': /* player */
705#endif 817 case '+': /* player on goal */
818 rb->lcd_drawline(c, r + middle, c + max, r + middle);
819 rb->lcd_drawline(c + middle, r, c + middle,
820 r + max - ldelta);
821 rb->lcd_drawline(c + max - middle, r, c + max - middle,
822 r + max - ldelta);
823 rb->lcd_drawline(c + middle, r + max - ldelta,
824 c + middle - ldelta, r + max);
825 rb->lcd_drawline(c + max - middle, r + max - ldelta,
826 c + max - middle + ldelta, r + max);
827 break;
706#endif 828#endif
829 }
830 }
831 }
707 832
708 /* print out the screen */ 833 /* print out the screen */
709 rb->lcd_update(); 834 rb->lcd_update();
@@ -716,21 +841,320 @@ static void draw_level(void)
716 update_screen(); 841 update_screen();
717} 842}
718 843
844static bool save(char *filename, bool solution)
845{
846 int fd;
847
848 rb->splash(0, "Saving...");
849
850 if (filename[0] == '\0' ||
851 (fd = rb->open(filename, O_WRONLY|O_CREAT|O_TRUNC)) < 0) {
852 rb->splash(HZ*2, "Unable to open %s", filename);
853 return false;
854 }
855
856 /* Sokoban: S/P for solution/progress : level number : current undo */
857 rb->snprintf(buf, sizeof(buf), "Sokoban:%c:%d:%d\n", (solution ? 'S' : 'P'),
858 current_info.level.index + 1, undo_info.current);
859 rb->write(fd, buf, rb->strlen(buf));
860
861 /* Filename of levelset */
862 rb->write(fd, buffered_boards.filename,
863 rb->strlen(buffered_boards.filename));
864 rb->write(fd, "\n", 1);
865
866 /* Full undo history */
867 rb->write(fd, undo_info.history, undo_info.max);
868
869 rb->close(fd);
870
871 return true;
872}
873
874static bool load(char *filename, bool silent)
875{
876 int fd;
877 int i = 0, n;
878 int len;
879 bool play_solution;
880 int button;
881 int step_delay = HZ/4;
882
883 if (filename[0] == '\0' || (fd = rb->open(filename, O_RDONLY)) < 0) {
884 if (!silent)
885 rb->splash(HZ*2, "Unable to open %s", filename);
886 return false;
887 }
888
889 /* Read header, level number, & current undo */
890 rb->read_line(fd, buf, sizeof(buf));
891
892 /* If we're opening a level file, not a solution/progress file */
893 if (rb->strncmp(buf, "Sokoban", 7) != 0) {
894 rb->close(fd);
895
896 rb->strncpy(buffered_boards.filename, filename, MAX_PATH);
897 if (!read_levels(true))
898 return false;
899
900 current_info.level.index = 0;
901 load_level();
902
903 /* If there aren't any boxes to go or the player position wasn't set,
904 * the file probably wasn't a Sokoban level file */
905 if (current_info.level.boxes_to_go == 0 ||
906 current_info.player.row == 0 || current_info.player.col == 0) {
907 if (!silent)
908 rb->splash(HZ*2, "File is not a Sokoban level file");
909 return false;
910 }
911
912 } else {
913
914 /* Read filename of levelset */
915 rb->read_line(fd, buffered_boards.filename,
916 sizeof(buffered_boards.filename));
917
918 /* Read full undo history */
919 len = rb->read_line(fd, undo_info.history, MAX_UNDOS);
920
921 /* Correct len when trailing \r's or \n's are counted */
922 if (len > 2 && undo_info.history[len - 2] == '\0')
923 len -= 2;
924 else if (len > 1 && undo_info.history[len - 1] == '\0')
925 len--;
926
927 rb->close(fd);
928
929 /* Check to see if we're going to play a solution or resume progress */
930 play_solution = (buf[8] == 'S');
931
932 /* Get level number */
933 for (n = 0, i = 10; buf[i] >= '0' && buf[i] <= '9' && i < 15; i++)
934 n = n*10 + buf[i] - '0';
935 current_info.level.index = n - 1;
936
937 /* Get current undo index */
938 for (n = 0, i++; buf[i] >= '0' && buf[i] <= '9' && i < 21; i++)
939 n = n*10 + buf[i] - '0';
940 if (n > len)
941 n = len;
942
943 if (current_info.level.index < 0) {
944 if (!silent)
945 rb->splash(HZ*2, "Error loading level");
946 return false;
947 }
948 if (!read_levels(true))
949 return false;
950 if (current_info.level.index >= current_info.max_level) {
951 if (!silent)
952 rb->splash(HZ*2, "Error loading level");
953 return false;
954 }
955
956 load_level();
957
958 if (play_solution) {
959 rb->lcd_clear_display();
960 update_screen();
961 rb->sleep(2*step_delay);
962
963 /* Replay solution until the end or quit button is pressed */
964 for (i = 0; i < len; i++) {
965 if (!move(undo_info.history[i], true)) {
966 n = i;
967 break;
968 }
969
970 rb->lcd_clear_display();
971 update_screen();
972 rb->sleep(step_delay);
973
974 /* Ignore keypresses except for quit & changing speed */
975 while ((button = rb->button_get(false)) != BUTTON_NONE) {
976 switch (button) {
977 case SOKOBAN_MENU:
978 /* Pretend the level is complete so we'll quit */
979 current_info.level.boxes_to_go = 0;
980 return true;
981
982 case SOKOBAN_UP:
983 if (step_delay > HZ/12)
984 step_delay = 5*step_delay/6;
985 break;
986
987 case SOKOBAN_DOWN:
988 if (step_delay < 3*HZ/4)
989 step_delay = 6*step_delay/5;
990 }
991 }
992 }
993
994 /* If level complete, wait for keypress before quitting */
995 if (current_info.level.boxes_to_go == 0)
996 rb->button_get(true);
997
998 } else {
999 /* Advance to current undo */
1000 for (i = 0; i < n; i++) {
1001 if (!move(undo_info.history[i], true)) {
1002 n = i;
1003 break;
1004 }
1005 }
1006
1007 rb->button_clear_queue();
1008 rb->lcd_clear_display();
1009 }
1010
1011 undo_info.max = len;
1012 undo_info.current = n;
1013 }
1014
1015 return true;
1016}
1017
1018static int sokoban_menu(void)
1019{
1020 int button;
1021 int selection = 0;
1022 int i;
1023 bool menu_quit;
1024 int start_selected = 0;
1025
1026 MENUITEM_STRINGLIST(menu, "Sokoban Menu", NULL,
1027 "Resume", "Audio Playback", "Keys",
1028 "Load Default Level Set", "Quit Without Saving",
1029 "Save Progress & Quit");
1030
1031 do {
1032 menu_quit = true;
1033 selection = rb->do_menu(&menu, &start_selected);
1034
1035 switch (selection) {
1036 case 0: /* Resume */
1037 break;
1038
1039 case 1: /* Audio playback control */
1040 playback_control(rb);
1041 menu_quit = false;
1042 break;
1043
1044 case 2: /* Keys */
1045 FOR_NB_SCREENS(i)
1046 rb->screens[i]->clear_display();
1047 rb->lcd_setfont(SOKOBAN_FONT);
1048
1049#if (CONFIG_KEYPAD == RECORDER_PAD) || \
1050 (CONFIG_KEYPAD == ARCHOS_AV300_PAD)
1051 rb->lcd_putsxy(3, 6, "[OFF] Menu");
1052 rb->lcd_putsxy(3, 16, "[ON] Undo");
1053 rb->lcd_putsxy(3, 26, "[PLAY] Redo");
1054 rb->lcd_putsxy(3, 36, "[F1] Down a Level");
1055 rb->lcd_putsxy(3, 46, "[F2] Restart Level");
1056 rb->lcd_putsxy(3, 56, "[F3] Up a Level");
1057#elif CONFIG_KEYPAD == ONDIO_PAD
1058 rb->lcd_putsxy(3, 6, "[OFF] Menu");
1059 rb->lcd_putsxy(3, 16, "[MODE] Undo");
1060 rb->lcd_putsxy(3, 26, "[MODE+DOWN] Redo");
1061 rb->lcd_putsxy(3, 36, "[MODE+LEFT] Previous Level");
1062 rb->lcd_putsxy(3, 46, "[MODE+UP] Restart Level");
1063 rb->lcd_putsxy(3, 56, "[MODE+RIGHT] Up Level");
1064#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
1065 (CONFIG_KEYPAD == IRIVER_H300_PAD)
1066 rb->lcd_putsxy(3, 6, "[STOP] Menu");
1067 rb->lcd_putsxy(3, 16, "[REC] Undo");
1068 rb->lcd_putsxy(3, 26, "[MODE] Redo");
1069 rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Previous Level");
1070 rb->lcd_putsxy(3, 46, "[PLAY] Restart Level");
1071 rb->lcd_putsxy(3, 56, "[PLAY+UP] Next Level");
1072#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1073 (CONFIG_KEYPAD == IPOD_3G_PAD)
1074 rb->lcd_putsxy(3, 6, "[SELECT+MENU] Menu");
1075 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
1076 rb->lcd_putsxy(3, 26, "[SELECT+PLAY] Redo");
1077 rb->lcd_putsxy(3, 36, "[SELECT+LEFT] Previous Level");
1078 rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Next Level");
1079#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
1080 rb->lcd_putsxy(3, 6, "[POWER] Menu");
1081 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
1082 rb->lcd_putsxy(3, 26, "[REC] Previous Level");
1083 rb->lcd_putsxy(3, 36, "[PLAY] Next Level");
1084#elif CONFIG_KEYPAD == IRIVER_H10_PAD
1085 rb->lcd_putsxy(3, 6, "[POWER] Menu");
1086 rb->lcd_putsxy(3, 16, "[REW] Undo");
1087 rb->lcd_putsxy(3, 26, "[FF] Redo");
1088 rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Previous Level");
1089 rb->lcd_putsxy(3, 46, "[PLAY+RIGHT] Restart Level");
1090 rb->lcd_putsxy(3, 56, "[PLAY+UP] Next Level");
1091#elif CONFIG_KEYPAD == GIGABEAT_PAD
1092 rb->lcd_putsxy(3, 6, "[POWER] Menu");
1093 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
1094 rb->lcd_putsxy(3, 26, "[A] Redo");
1095 rb->lcd_putsxy(3, 36, "[VOL-] Previous Level");
1096 rb->lcd_putsxy(3, 46, "[MENU] Restart Level");
1097 rb->lcd_putsxy(3, 56, "[VOL+] Next Level");
1098#elif CONFIG_KEYPAD == SANSA_E200_PAD
1099 rb->lcd_putsxy(3, 6, "[POWER] Menu");
1100 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
1101 rb->lcd_putsxy(3, 26, "[REC] Redo");
1102 rb->lcd_putsxy(3, 36, "[SELECT+DOWN] Previous Level");
1103 rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Restart Level");
1104 rb->lcd_putsxy(3, 56, "[SELECT+UP] Next Level");
1105#endif
1106
1107 FOR_NB_SCREENS(i)
1108 rb->screens[i]->update();
1109
1110 /* Display until keypress */
1111 do {
1112 rb->sleep(HZ/20);
1113 button = rb->button_get(false);
1114 } while (!button || button & BUTTON_REL ||
1115 button & BUTTON_REPEAT);
1116
1117 menu_quit = false;
1118 break;
1119
1120 case 3: /* Load default levelset */
1121 init_boards();
1122 if (!read_levels(true))
1123 return 4;
1124 load_level();
1125 break;
1126
1127 case 4: /* Quit */
1128 break;
1129
1130 case 5: /* Save & quit */
1131 save(SOKOBAN_SAVE_FILE, false);
1132 rb->reload_directory();
1133 }
1134
1135 } while (!menu_quit);
1136
1137 /* Restore font */
1138 rb->lcd_setfont(SOKOBAN_FONT);
1139
1140 FOR_NB_SCREENS(i) {
1141 rb->screens[i]->clear_display();
1142 rb->screens[i]->update();
1143 }
1144
1145 return selection;
1146}
1147
719static bool sokoban_loop(void) 1148static bool sokoban_loop(void)
720{ 1149{
721 bool moved = true; 1150 bool moved;
722 int i = 0, button = 0, lastbutton = 0; 1151 int i = 0, button = 0, lastbutton = 0;
723 short r = 0, c = 0; 1152 short r = 0, c = 0;
724 int w, h; 1153 int w, h;
725 char s[25]; 1154 char *loc;
726 1155
727 current_info.level.level = 1; 1156 while (true) {
728 1157 moved = false;
729 load_level();
730 update_screen();
731
732 while (1) {
733 moved = true;
734 1158
735 r = current_info.player.row; 1159 r = current_info.player.row;
736 c = current_info.player.col; 1160 c = current_info.player.col;
@@ -742,24 +1166,25 @@ static bool sokoban_loop(void)
742#ifdef SOKOBAN_RC_QUIT 1166#ifdef SOKOBAN_RC_QUIT
743 case SOKOBAN_RC_QUIT: 1167 case SOKOBAN_RC_QUIT:
744#endif 1168#endif
745 case SOKOBAN_QUIT: 1169 case SOKOBAN_MENU:
746 /* get out of here */ 1170 switch (sokoban_menu()) {
747#ifdef HAVE_LCD_COLOR /* reset background color */ 1171 case 4: /* Quit */
748 rb->lcd_set_background(rb->global_settings->bg_color); 1172 case 5: /* Save & quit */
749#endif 1173 return PLUGIN_OK;
750 return PLUGIN_OK; 1174 }
1175 update_screen();
1176 break;
751 1177
752 case SOKOBAN_UNDO: 1178 case SOKOBAN_UNDO:
753#ifdef SOKOBAN_UNDO_PRE 1179#ifdef SOKOBAN_UNDO_PRE
754 if (lastbutton != SOKOBAN_UNDO_PRE) 1180 if (lastbutton != SOKOBAN_UNDO_PRE)
755 break; 1181 break;
756#else /* repeat can't work here for Ondio et al */ 1182#else /* repeat can't work here for Ondio, iPod, et al */
757 case SOKOBAN_UNDO | BUTTON_REPEAT: 1183 case SOKOBAN_UNDO | BUTTON_REPEAT:
758#endif 1184#endif
759 undo(); 1185 undo();
760 rb->lcd_clear_display(); 1186 rb->lcd_clear_display();
761 update_screen(); 1187 update_screen();
762 moved = false;
763 break; 1188 break;
764 1189
765#ifdef SOKOBAN_REDO 1190#ifdef SOKOBAN_REDO
@@ -775,22 +1200,20 @@ static bool sokoban_loop(void)
775 case SOKOBAN_LEVEL_UP | BUTTON_REPEAT: 1200 case SOKOBAN_LEVEL_UP | BUTTON_REPEAT:
776 /* next level */ 1201 /* next level */
777 init_undo(); 1202 init_undo();
778 if (current_info.level.level < current_info.max_level) 1203 if (current_info.level.index + 1 < current_info.max_level)
779 current_info.level.level++; 1204 current_info.level.index++;
780 1205
781 draw_level(); 1206 draw_level();
782 moved = false;
783 break; 1207 break;
784 1208
785 case SOKOBAN_LEVEL_DOWN: 1209 case SOKOBAN_LEVEL_DOWN:
786 case SOKOBAN_LEVEL_DOWN | BUTTON_REPEAT: 1210 case SOKOBAN_LEVEL_DOWN | BUTTON_REPEAT:
787 /* previous level */ 1211 /* previous level */
788 init_undo(); 1212 init_undo();
789 if (current_info.level.level > 1) 1213 if (current_info.level.index > 0)
790 current_info.level.level--; 1214 current_info.level.index--;
791 1215
792 draw_level(); 1216 draw_level();
793 moved = false;
794 break; 1217 break;
795 1218
796#ifdef SOKOBAN_LEVEL_REPEAT 1219#ifdef SOKOBAN_LEVEL_REPEAT
@@ -799,7 +1222,6 @@ static bool sokoban_loop(void)
799 /* same level */ 1222 /* same level */
800 init_undo(); 1223 init_undo();
801 draw_level(); 1224 draw_level();
802 moved = false;
803 break; 1225 break;
804#endif 1226#endif
805 1227
@@ -826,13 +1248,10 @@ static bool sokoban_loop(void)
826 default: 1248 default:
827 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) 1249 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
828 return PLUGIN_USB_CONNECTED; 1250 return PLUGIN_USB_CONNECTED;
829
830 moved = false;
831 break; 1251 break;
832 } 1252 }
833 1253
834 if (button != BUTTON_NONE) 1254 lastbutton = button;
835 lastbutton = button;
836 1255
837 if (moved) { 1256 if (moved) {
838 rb->lcd_clear_display(); 1257 rb->lcd_clear_display();
@@ -844,58 +1263,102 @@ static bool sokoban_loop(void)
844 1263
845 if (moved) { 1264 if (moved) {
846 rb->lcd_clear_display(); 1265 rb->lcd_clear_display();
847 /* Center level completed message */ 1266
848 rb->snprintf(s, sizeof(s), "Level %d Complete!", 1267 /* Show level complete message & stats */
849 current_info.level.level); 1268 rb->snprintf(buf, sizeof(buf), "Level %d Complete!",
850 rb->lcd_getstringsize(s, &w, &h); 1269 current_info.level.index + 1);
851 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - 16 , s); 1270 rb->lcd_getstringsize(buf, &w, &h);
852 rb->snprintf(s, sizeof(s), "%4d Moves ", 1271 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h*3, buf);
1272
1273 rb->snprintf(buf, sizeof(buf), "%4d Moves ",
853 current_info.level.moves); 1274 current_info.level.moves);
854 rb->lcd_getstringsize(s, &w, &h); 1275 rb->lcd_getstringsize(buf, &w, &h);
855 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + 0 , s); 1276 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h, buf);
856 rb->snprintf(s, sizeof(s), "%4d Pushes", 1277
1278 rb->snprintf(buf, sizeof(buf), "%4d Pushes",
857 current_info.level.pushes); 1279 current_info.level.pushes);
858 rb->lcd_getstringsize(s, &w, &h); 1280 rb->lcd_getstringsize(buf, &w, &h);
859 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + 8 , s); 1281 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, buf);
1282
1283 if (undo_info.count < MAX_UNDOS) {
1284 rb->snprintf(buf, sizeof(buf), "%s: Save solution",
1285 BUTTON_SAVE_NAME);
1286 rb->lcd_getstringsize(buf, &w, &h);
1287 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h*2, buf);
1288 }
1289
860 rb->lcd_update(); 1290 rb->lcd_update();
861 rb->button_get(false); 1291 rb->sleep(HZ/4);
1292 rb->button_clear_queue();
862 1293
863 rb->sleep(HZ/2); 1294 /* Display for 4 seconds or until new keypress */
864 for (i = 0; i < 30; i++) { 1295 for (i = 0; i < 75; i++) {
865 rb->sleep(HZ/20); 1296 rb->sleep(HZ/20);
866 button = rb->button_get(false); 1297 button = rb->button_get(false);
867 if (button && ((button & BUTTON_REL) != BUTTON_REL)) 1298 if (button && !(button & BUTTON_REL) &&
1299 !(button & BUTTON_REPEAT))
868 break; 1300 break;
869 } 1301 }
1302
1303 if (button == BUTTON_SAVE) {
1304 if (undo_info.count < MAX_UNDOS) {
1305 /* Default filename to current levelset plus
1306 * level number and .sok extension */
1307 loc = rb->strrchr(buffered_boards.filename, '.');
1308 if (loc != NULL)
1309 *loc = '\0';
1310 rb->snprintf(buf, sizeof(buf), "%s.%d.sok",
1311 buffered_boards.filename,
1312 current_info.level.index + 1);
1313 if (loc != NULL)
1314 *loc = '.';
1315
1316 if (!rb->kbd_input(buf, MAX_PATH))
1317 save(buf, true);
1318 } else
1319 rb->splash(HZ*2, "Solution too long to save");
1320
1321 rb->lcd_setfont(SOKOBAN_FONT); /* Restore font */
1322 }
870 } 1323 }
871 1324
872 current_info.level.level++; 1325 FOR_NB_SCREENS(i) {
1326 rb->screens[i]->clear_display();
1327 rb->screens[i]->update();
1328 }
1329
1330 current_info.level.index++;
873 1331
874 /* clear undo stats */ 1332 /* clear undo stats */
875 init_undo(); 1333 init_undo();
876 1334
877 rb->lcd_clear_display(); 1335 if (current_info.level.index >= current_info.max_level) {
878 1336 /* Show levelset complete message */
879 if (current_info.level.level > current_info.max_level) { 1337 rb->snprintf(buf, sizeof(buf), "You WIN!!");
880 /* Center "You WIN!!" on all screen sizes */ 1338 rb->lcd_getstringsize(buf, &w, &h);
881 rb->snprintf(s, sizeof(s), "You WIN!!"); 1339 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, buf);
882 rb->lcd_getstringsize(s, &w, &h);
883 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, s);
884 1340
885 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1341 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
886 /* Display for 10 seconds or until keypress */ 1342 /* Display for 4 seconds or until keypress */
887 for (i = 0; i < 200; i++) { 1343 for (i = 0; i < 80; i++) {
888 rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT); 1344 rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
889 rb->lcd_update(); 1345 rb->lcd_update();
890 rb->sleep(HZ/20); 1346 rb->sleep(HZ/10);
891 1347
892 button = rb->button_get(false); 1348 button = rb->button_get(false);
893 if (button && ((button & BUTTON_REL) != BUTTON_REL)) 1349 if (button && !(button & BUTTON_REL))
894 break; 1350 break;
895 } 1351 }
896 rb->lcd_set_drawmode(DRMODE_SOLID); 1352 rb->lcd_set_drawmode(DRMODE_SOLID);
897 1353
898 return PLUGIN_OK; 1354 /* Reset to first level & show quit menu */
1355 current_info.level.index = 0;
1356
1357 switch (sokoban_menu()) {
1358 case 4: /* Quit */
1359 case 5: /* Save & quit */
1360 return PLUGIN_OK;
1361 }
899 } 1362 }
900 1363
901 load_level(); 1364 load_level();
@@ -911,99 +1374,41 @@ static bool sokoban_loop(void)
911enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 1374enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
912{ 1375{
913 int w, h; 1376 int w, h;
914 int i;
915 int button = 0;
916 1377
917 (void)(parameter); 1378 (void)(parameter);
918 rb = api; 1379 rb = api;
919 1380
920 rb->lcd_setfont(FONT_SYSFIXED); 1381 rb->lcd_setfont(SOKOBAN_FONT);
921
922#ifdef HAVE_LCD_COLOR
923 rb->lcd_set_background(BG_COLOR);
924#endif
925 1382
926 rb->lcd_clear_display(); 1383 rb->lcd_clear_display();
927 rb->lcd_getstringsize(SOKOBAN_TITLE, &w, &h); 1384 rb->lcd_getstringsize(SOKOBAN_TITLE, &w, &h);
928 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, SOKOBAN_TITLE); 1385 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, SOKOBAN_TITLE);
929 rb->lcd_update(); 1386 rb->lcd_update();
930 rb->sleep(HZ); 1387 rb->sleep(HZ); /* Show title for 1 second */
931 1388
932 rb->lcd_clear_display(); 1389 init_boards();
933 1390
934#if (CONFIG_KEYPAD == RECORDER_PAD) || \ 1391 if (parameter == NULL) {
935 (CONFIG_KEYPAD == ARCHOS_AV300_PAD) 1392 /* Attempt to resume saved progress, otherwise start at beginning */
936 rb->lcd_putsxy(3, 6, "[OFF] Quit"); 1393 if (!load(SOKOBAN_SAVE_FILE, true)) {
937 rb->lcd_putsxy(3, 16, "[ON] Undo"); 1394 init_boards();
938 rb->lcd_putsxy(3, 26, "[PLAY] Redo"); 1395 if (!read_levels(true))
939 rb->lcd_putsxy(3, 36, "[F1] Down a Level"); 1396 return PLUGIN_OK;
940 rb->lcd_putsxy(3, 46, "[F2] Restart Level"); 1397 load_level();
941 rb->lcd_putsxy(3, 56, "[F3] Up a Level"); 1398 }
942#elif CONFIG_KEYPAD == ONDIO_PAD
943 rb->lcd_putsxy(3, 6, "[OFF] Quit");
944 rb->lcd_putsxy(3, 16, "[MODE] Undo");
945 rb->lcd_putsxy(3, 26, "[MODE+DOWN] Redo");
946 rb->lcd_putsxy(3, 36, "[MODE+LEFT] Down a Level");
947 rb->lcd_putsxy(3, 46, "[MODE+UP] Restart Level");
948 rb->lcd_putsxy(3, 56, "[MODE+RIGHT] Up Level");
949#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
950 (CONFIG_KEYPAD == IRIVER_H300_PAD)
951 rb->lcd_putsxy(3, 6, "[STOP] Quit");
952 rb->lcd_putsxy(3, 16, "[REC] Undo");
953 rb->lcd_putsxy(3, 26, "[MODE] Redo");
954 rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Down a Level");
955 rb->lcd_putsxy(3, 46, "[PLAY] Restart Level");
956 rb->lcd_putsxy(3, 56, "[PLAY+UP] Up a Level");
957#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
958 (CONFIG_KEYPAD == IPOD_3G_PAD)
959 rb->lcd_putsxy(3, 6, "[SELECT+MENU] Quit");
960 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
961 rb->lcd_putsxy(3, 26, "[SELECT+PLAY] Redo");
962 rb->lcd_putsxy(3, 36, "[SELECT+LEFT] Down a Level");
963 rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Up a Level");
964#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
965 rb->lcd_putsxy(3, 6, "[POWER] Quit");
966 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
967 rb->lcd_putsxy(3, 26, "[REC] Down a Level");
968 rb->lcd_putsxy(3, 36, "[PLAY] Up Level");
969#elif CONFIG_KEYPAD == GIGABEAT_PAD
970 rb->lcd_putsxy(3, 6, "[POWER] Quit");
971 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
972 rb->lcd_putsxy(3, 26, "[A] Redo");
973 rb->lcd_putsxy(3, 36, "[VOL-] Down a Level");
974 rb->lcd_putsxy(3, 46, "[MENU] Restart Level");
975 rb->lcd_putsxy(3, 56, "[VOL+] Up Level");
976#elif CONFIG_KEYPAD == SANSA_E200_PAD
977 rb->lcd_putsxy(3, 6, "[POWER] Quit");
978 rb->lcd_putsxy(3, 16, "[SELECT] Undo");
979 rb->lcd_putsxy(3, 26, "[REC] Redo");
980 rb->lcd_putsxy(3, 36, "[SELECT+DOWN] Down a Level");
981 rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Restart Level");
982 rb->lcd_putsxy(3, 56, "[SELECT+UP] Up Level");
983#elif CONFIG_KEYPAD == IRIVER_H10_PAD
984 rb->lcd_putsxy(3, 6, "[POWER] Quit");
985 rb->lcd_putsxy(3, 16, "[REW] Undo");
986 rb->lcd_putsxy(3, 26, "[FF] Redo");
987 rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Down a Level");
988 rb->lcd_putsxy(3, 46, "[PLAY+RIGHT] Restart Level");
989 rb->lcd_putsxy(3, 56, "[PLAY+UP] Up Level");
990#endif
991 1399
992 rb->lcd_update(); 1400 } else {
993 rb->button_get(false); 1401 /* The plugin is being used to open a file */
994 /* Display for 3 seconds or until keypress */ 1402 if (load((char*) parameter, false)) {
995 for (i = 0; i < 60; i++) { 1403 /* If we loaded & played a solution, quit */
996 rb->sleep(HZ/20); 1404 if (current_info.level.boxes_to_go == 0)
997 button = rb->button_get(false); 1405 return PLUGIN_OK;
998 if (button && ((button & BUTTON_REL) != BUTTON_REL)) 1406 } else
999 break; 1407 return PLUGIN_OK;
1000 } 1408 }
1001 rb->lcd_clear_display();
1002
1003 init_boards();
1004 1409
1005 if (read_levels(1) != 0) 1410 rb->lcd_clear_display();
1006 return PLUGIN_OK; 1411 update_screen();
1007 1412
1008 return sokoban_loop(); 1413 return sokoban_loop();
1009} 1414}
diff --git a/apps/plugins/sokoban.levels b/apps/plugins/sokoban.levels
deleted file mode 100644
index 4d73a5ed9d..0000000000
--- a/apps/plugins/sokoban.levels
+++ /dev/null
@@ -1,1816 +0,0 @@
1XXXXXXXXXXXXXXXXXXXX
2XXXXXXXXXXXXXXXXXXXX
3XXXXXXXXXXXXXXXXXXXX
4XXXXXXXXXXXXXXXXXXXX
5XXXXXXXX###XXXXXXXXX
6XXXXXXXX#.#XXXXXXXXX
7XXXXXXXX# ####XXXXXX
8XXXXXX###$ $.#XXXXXX
9XXXXXX#. $@###XXXXXX
10XXXXXX####$#XXXXXXXX
11XXXXXXXXX#.#XXXXXXXX
12XXXXXXXXX###XXXXXXXX
13XXXXXXXXXXXXXXXXXXXX
14XXXXXXXXXXXXXXXXXXXX
15XXXXXXXXXXXXXXXXXXXX
16XXXXXXXXXXXXXXXXXXXX
17
18
19XXXXXXXXXXXXXXXXXXXX
20XXXXXXXXXXXXXXXXXXXX
21XXXXXXXXXXXXXXXXXXXX
22XXXXXXXXXXXXXXXXXXXX
23XXXXX#####XXXXXXXXXX
24XXXXX# #XXXXXXXXXX
25XXXXX#@$$#X###XXXXXX
26XXXXX# $ #X#.#XXXXXX
27XXXXX### ###.#XXXXXX
28XXXXXX## .#XXXXXX
29XXXXXX# # #XXXXXX
30XXXXXX# ####XXXXXX
31XXXXXX#####XXXXXXXXX
32XXXXXXXXXXXXXXXXXXXX
33XXXXXXXXXXXXXXXXXXXX
34XXXXXXXXXXXXXXXXXXXX
35
36
37XXXXXXXXXXXXXXXXXXXX
38XXXXXXXXXXXXXXXXXXXX
39XXXXXXXXXXXXXXXXXXXX
40XXXXXXXXXXXXXXXXXXXX
41XXXXXXXXXXXXXXXXXXXX
42XXXXXX#######XXXXXXX
43XXXXXX# ###XXXXX
44XXXXX##$### #XXXXX
45XXXXX# @ $ $ #XXXXX
46XXXXX# ..# $ ##XXXXX
47XXXXX##..# #XXXXXX
48XXXXXX########XXXXXX
49XXXXXXXXXXXXXXXXXXXX
50XXXXXXXXXXXXXXXXXXXX
51XXXXXXXXXXXXXXXXXXXX
52XXXXXXXXXXXXXXXXXXXX
53
54
55XXXXXXXXXXXXXXXXXXXX
56XXXXXXXXXXXXXXXXXXXX
57XXXXXXXXXXXXXXXXXXXX
58XXXXXXXXXXXXXXXXXXXX
59XXXXXXXXXXXXXXXXXXXX
60XXXXXXXXX#####XXXXXX
61XXXXXX#### .#XXXXXX
62XXXXXX# $ %#XXXXXX
63XXXXXX# $$ $.#XXXXXX
64XXXXXX##@##..#XXXXXX
65XXXXXXX#######XXXXXX
66XXXXXXXXXXXXXXXXXXXX
67XXXXXXXXXXXXXXXXXXXX
68XXXXXXXXXXXXXXXXXXXX
69XXXXXXXXXXXXXXXXXXXX
70XXXXXXXXXXXXXXXXXXXX
71
72
73XXXXXXXXXXXXXXXXXXXX
74XXXXXXXXXXXXXXXXXXXX
75XXXXXXXXXXXXXXXXXXXX
76XXXXXXXXXXXXXXXXXXXX
77XXXXXXX####XXXXXXXXX
78XXXXXXX#@ ###XXXXXXX
79XXXXXXX# $ #XXXXXXX
80XXXXXX### # ##XXXXXX
81XXXXXX#.# # #XXXXXX
82XXXXXX#.$ # #XXXXXX
83XXXXXX#. $ #XXXXXX
84XXXXXX########XXXXXX
85XXXXXXXXXXXXXXXXXXXX
86XXXXXXXXXXXXXXXXXXXX
87XXXXXXXXXXXXXXXXXXXX
88XXXXXXXXXXXXXXXXXXXX
89
90
91XXXXXXXXXXXXXXXXXXXX
92XXXXXXXXXXXXXXXXXXXX
93XXXXXXXXXXXXXXXXXXXX
94XXXXXXXXXXXXXXXXXXXX
95XXXXXXXX#######XXXXX
96XXXXXXX## # @#XXXXX
97XXXXXXX# # #XXXXX
98XXXXXXX#$ $ $ #XXXXX
99XXXXXXX# $## #XXXXX
100XXXXX### $ # ##XXXXX
101XXXXX#..... #XXXXXX
102XXXXX#########XXXXXX
103XXXXXXXXXXXXXXXXXXXX
104XXXXXXXXXXXXXXXXXXXX
105XXXXXXXXXXXXXXXXXXXX
106XXXXXXXXXXXXXXXXXXXX
107
108
109XXXXXXXXXXXXXXXXXXXX
110XXXXXXXXXXXXXXXXXXXX
111XXXXXXXXXXXXXXXXXXXX
112XXXXXXXXXXXXXXXXXXXX
113XXXXXXXXXXXXXXXXXXXX
114XXXXXXXX######XXXXXX
115XXXXXX### #XXXXXX
116XXXXX##. $## ##XXXXX
117XXXXX#..$ $ @#XXXXX
118XXXXX#.. $ $ ##XXXXX
119XXXXX###### #XXXXXX
120XXXXXXXXXX####XXXXXX
121XXXXXXXXXXXXXXXXXXXX
122XXXXXXXXXXXXXXXXXXXX
123XXXXXXXXXXXXXXXXXXXX
124XXXXXXXXXXXXXXXXXXXX
125
126
127XXXXXXXXXXXXXXXXXXXX
128XXXXXXXXXXXXXXXXXXXX
129XXXXXXXXXXXXXXXXXXXX
130XXXXXXXXXXXXXXXXXXXX
131XXXXXXXX######XXXXXX
132XXXXXXXX# #XXXXXX
133XXXXXX###$$$ #XXXXXX
134XXXXXX#@ $.. #XXXXXX
135XXXXXX# $...##XXXXXX
136XXXXXX#### #XXXXXXX
137XXXXXXXXX####XXXXXXX
138XXXXXXXXXXXXXXXXXXXX
139XXXXXXXXXXXXXXXXXXXX
140XXXXXXXXXXXXXXXXXXXX
141XXXXXXXXXXXXXXXXXXXX
142XXXXXXXXXXXXXXXXXXXX
143
144
145XXXXXXXXXXXXXXXXXXXX
146XXXXXXXXXXXXXXXXXXXX
147XXXXXXXXXXXXXXXXXXXX
148XXXXXXXXXXXXXXXXXXXX
149XXXXXXXX####XXXXXXXX
150XXXXXXXX#..#XXXXXXXX
151XXXXXXX## .##XXXXXXX
152XXXXXXX# $.#XXXXXXX
153XXXXXX## $ ##XXXXXX
154XXXXXX# #$$ #XXXXXX
155XXXXXX# @ #XXXXXX
156XXXXXX########XXXXXX
157XXXXXXXXXXXXXXXXXXXX
158XXXXXXXXXXXXXXXXXXXX
159XXXXXXXXXXXXXXXXXXXX
160XXXXXXXXXXXXXXXXXXXX
161
162
163XXXXXXXXXXXXXXXXXXXX
164XXXXXXXXXXXXXXXXXXXX
165XXXXXXXXXXXXXXXXXXXX
166XXXXXXXXXXXXXXXXXXXX
167XXXXXXXXXXXXXXXXXXXX
168XXXXXXXX#####XXXXXXX
169XXXXXX### @#XXXXXXX
170XXXXXX# $. ##XXXXXX
171XXXXXX# .$. #XXXXXX
172XXXXXX### %$ #XXXXXX
173XXXXXXXX# ##XXXXXX
174XXXXXXXX#####XXXXXXX
175XXXXXXXXXXXXXXXXXXXX
176XXXXXXXXXXXXXXXXXXXX
177XXXXXXXXXXXXXXXXXXXX
178XXXXXXXXXXXXXXXXXXXX
179
180
181XXXXXXXXXXXXXXXXXXXX
182XXXXXXXXXXXXXXXXXXXX
183XXXXXXXXXXXXXXXXXXXX
184XXXXXXXXXXXXXXXXXXXX
185XXXXXX########XXXXXX
186XXXXXX# # #XXXXXX
187XXXXXX# $..$ #XXXXXX
188XXXXXX#@$.% ##XXXXXX
189XXXXXX# $..$ #XXXXXX
190XXXXXX# # #XXXXXX
191XXXXXX########XXXXXX
192XXXXXXXXXXXXXXXXXXXX
193XXXXXXXXXXXXXXXXXXXX
194XXXXXXXXXXXXXXXXXXXX
195XXXXXXXXXXXXXXXXXXXX
196XXXXXXXXXXXXXXXXXXXX
197
198
199XXXXXXXXXXXXXXXXXXXX
200XXXXXXXXXXXXXXXXXXXX
201XXXXXXXXXXXXXXXXXXXX
202XXXXXXXXXXXXXXXXXXXX
203XXXXXXX######XXXXXXX
204XXXXXXX# ###XXXXX
205XXXXXXX# $ #XXXXX
206XXXXX### $ ## #XXXXX
207XXXXX#... $ #XXXXX
208XXXXX#...$#$ ##XXXXX
209XXXXX#### # $ #XXXXX
210XXXXXXXX# @ #XXXXX
211XXXXXXXX#######XXXXX
212XXXXXXXXXXXXXXXXXXXX
213XXXXXXXXXXXXXXXXXXXX
214XXXXXXXXXXXXXXXXXXXX
215
216
217XXXXXXXXXXXXXXXXXXXX
218XXXXXXXXXXXXXXXXXXXX
219XXXXXXXXXXXXXXXXXXXX
220XXXXXXXXXXXXXXXXXXXX
221XXXXXX######XXXXXXXX
222XXXXXX# #XXXXXXXX
223XXXXXX# $$$##XXXXXXX
224XXXXXX# #..###XXXXX
225XXXXXX## ..$ #XXXXX
226XXXXXXX# @ #XXXXX
227XXXXXXX########XXXXX
228XXXXXXXXXXXXXXXXXXXX
229XXXXXXXXXXXXXXXXXXXX
230XXXXXXXXXXXXXXXXXXXX
231XXXXXXXXXXXXXXXXXXXX
232XXXXXXXXXXXXXXXXXXXX
233
234
235XXXXXXXXXXXXXXXXXXXX
236XXXXXXXXXXXXXXXXXXXX
237XXXXXXXXXXXXXXXXXXXX
238XXXXXXXXXXXXXXXXXXXX
239XXXXXXX########XXXXX
240XXXXXXX# #. #XXXXX
241XXXXXX## $...#XXXXX
242XXXXXX# $ #%.#XXXXX
243XXXXX## ##$# ##XXXXX
244XXXXX# $ $ #XXXXX
245XXXXX# # #XXXXX
246XXXXX#######@ #XXXXX
247XXXXXXXXXXX####XXXXX
248XXXXXXXXXXXXXXXXXXXX
249XXXXXXXXXXXXXXXXXXXX
250XXXXXXXXXXXXXXXXXXXX
251
252
253XXXXXXXXXXXXXXXXXXXX
254XXXXXXXXXXXXXXXXXXXX
255XXXXXXXXXXXXXXXXXXXX
256XXXXXXXXXXXXXXXXXXXX
257XXXXXX#######XXXXXXX
258XXXXXX#.... #XXXXXXX
259XXXXX###...$###XXXXX
260XXXXX# $#$ $ #XXXXX
261XXXXX# $$ #$ #XXXXX
262XXXXX# # #XXXXX
263XXXXX#### @ ###XXXXX
264XXXXXXXX#####XXXXXXX
265XXXXXXXXXXXXXXXXXXXX
266XXXXXXXXXXXXXXXXXXXX
267XXXXXXXXXXXXXXXXXXXX
268XXXXXXXXXXXXXXXXXXXX
269
270
271XXXXXXXXXXXXXXXXXXXX
272XXXXXXXXXXXXXXXXXXXX
273XXXXXXXXXXXXXXXXXXXX
274XXXXXXXXXXXXXXXXXXXX
275XXXXXX########XXXXXX
276XXXXXX#.. #XXXXXX
277XXXXXX#..$ $@#XXXXXX
278XXXXXX#$#$$$##XXXXXX
279XXXXXX#..$ $ #XXXXXX
280XXXXXX#.. #XXXXXX
281XXXXXX########XXXXXX
282XXXXXXXXXXXXXXXXXXXX
283XXXXXXXXXXXXXXXXXXXX
284XXXXXXXXXXXXXXXXXXXX
285XXXXXXXXXXXXXXXXXXXX
286XXXXXXXXXXXXXXXXXXXX
287
288
289XXXXXXXXXXXXXXXXXXXX
290XXXXXXXXXXXXXXXXXXXX
291XXXXXXXXXXXXXXXXXXXX
292XXXXXXXXXXXXXXXXXXXX
293XXXXX########XXXXXXX
294XXXXX# #XXXXXXX
295XXXXX# #$$ #XXXXXXX
296XXXXX# ...# #XXXXXXX
297XXXXX##...$ ##XXXXXX
298XXXXXX# ## $ #XXXXXX
299XXXXXX#$ $ #XXXXXX
300XXXXXX# # @#XXXXXX
301XXXXXX########XXXXXX
302XXXXXXXXXXXXXXXXXXXX
303XXXXXXXXXXXXXXXXXXXX
304XXXXXXXXXXXXXXXXXXXX
305
306
307XXXXXXXXXXXXXXXXXXXX
308XXXXXXXXXXXXXXXXXXXX
309XXXXXXXXXXXXXXXXXXXX
310XXXXXXXXXXXXXXXXXXXX
311XXXXXXX#####XXXXXXXX
312XXXXX### ####XXXXX
313XXXXX# $ $ #XXXXX
314XXXXX# $ $ @#XXXXX
315XXXXX###$$#####XXXXX
316XXXXXXX# ..#XXXXXXX
317XXXXXXX#....#XXXXXXX
318XXXXXXX######XXXXXXX
319XXXXXXXXXXXXXXXXXXXX
320XXXXXXXXXXXXXXXXXXXX
321XXXXXXXXXXXXXXXXXXXX
322XXXXXXXXXXXXXXXXXXXX
323
324
325XXXXXXXXXXXXXXXXXXXX
326XXXXXXXXXXXXXXXXXXXX
327XXXXXXXXXXXXXXXXXXXX
328XXXXXXXXXXXXXXXXXXXX
329XXXXX#########XXXXXX
330XXXXX# % #XXXXXX
331XXXXX# $.$. @#XXXXXX
332XXXXX# .$.$. #XXXXXX
333XXXXX# $.$.$ #XXXXXX
334XXXXX# % #XXXXXX
335XXXXX#########XXXXXX
336XXXXXXXXXXXXXXXXXXXX
337XXXXXXXXXXXXXXXXXXXX
338XXXXXXXXXXXXXXXXXXXX
339XXXXXXXXXXXXXXXXXXXX
340XXXXXXXXXXXXXXXXXXXX
341
342
343XXXXXXXXXXXXXXXXXXXX
344XXXXXXXXXXXXXXXXXXXX
345XXXXXXXXXXXXXXXXXXXX
346XXXXXXXXXXXXXXXXXXXX
347XXXXXXXXXXXXXXXXXXXX
348XXXXXX#########XXXXX
349XXXXX## #XXXXX
350XXXXX# #$#$ #XXXXX
351XXXXX# $$ .$.#XXXXX
352XXXXX# @###...#XXXXX
353XXXXX####X#####XXXXX
354XXXXXXXXXXXXXXXXXXXX
355XXXXXXXXXXXXXXXXXXXX
356XXXXXXXXXXXXXXXXXXXX
357XXXXXXXXXXXXXXXXXXXX
358XXXXXXXXXXXXXXXXXXXX
359
360
361XXXXXXXXXXXXXXXXXXXX
362XXXXXXXXXXXXXXXXXXXX
363XXXXXXXXXXXXXXXXXXXX
364XXXXXXXXXXXXXXXXXXXX
365XXXXXXX######XXXXXXX
366XXXXXXX#. ..#XXXXXXX
367XXXXXXX#. $.#XXXXXXX
368XXXXXX### $##XXXXXX
369XXXXXX# $ $ #XXXXXX
370XXXXXX# #$## #XXXXXX
371XXXXXX# @ #XXXXXX
372XXXXXX########XXXXXX
373XXXXXXXXXXXXXXXXXXXX
374XXXXXXXXXXXXXXXXXXXX
375XXXXXXXXXXXXXXXXXXXX
376XXXXXXXXXXXXXXXXXXXX
377
378
379XXXXXXXXXXXXXXXXXXXX
380XXXXXXXXXXXXXXXXXXXX
381XXXXXXXXXXXXXXXXXXXX
382XXXXXXXXXXXXXXXXXXXX
383XXXXXXXXXXXXXXXXXXXX
384XXXXXX#####XXXXXXXXX
385XXXXXX# ####XXXXXX
386XXXXX## #$ #XXXXXX
387XXXXX# $ $$ #XXXXXX
388XXXXX# #$#.%.#XXXXXX
389XXXXX# @...#XXXXXX
390XXXXX#########XXXXXX
391XXXXXXXXXXXXXXXXXXXX
392XXXXXXXXXXXXXXXXXXXX
393XXXXXXXXXXXXXXXXXXXX
394XXXXXXXXXXXXXXXXXXXX
395
396
397XXXXXXXXXXXXXXXXXXXX
398XXXXXXXXXXXXXXXXXXXX
399XXXXXXXXXXXXXXXXXXXX
400XXXXXXXXXXXXXXXXXXXX
401XXXXXXXXX#####XXXXXX
402XXXXXX#### ##XXXXX
403XXXXXX# $ $ #XXXXX
404XXXXXX#@#.%.# #XXXXX
405XXXXXX# #.%.# #XXXXX
406XXXXXX# $ $ #XXXXX
407XXXXXX## ####XXXXX
408XXXXXXX#####XXXXXXXX
409XXXXXXXXXXXXXXXXXXXX
410XXXXXXXXXXXXXXXXXXXX
411XXXXXXXXXXXXXXXXXXXX
412XXXXXXXXXXXXXXXXXXXX
413
414
415XXXXXXXXXXXXXXXXXXXX
416XXXXXXXXXXXXXXXXXXXX
417XXXXXXXXXXXXXXXXXXXX
418XXXXXXXXXXXXXXXXXXXX
419XXXXXXXX#####XXXXXXX
420XXXXX####. ##XXXXXX
421XXXXX# $.$. #XXXXXX
422XXXXX#@$# #$ #XXXXXX
423XXXXX# $. . #XXXXXX
424XXXXX####$#$ #XXXXXX
425XXXXXXX#. . #XXXXXX
426XXXXXXX#######XXXXXX
427XXXXXXXXXXXXXXXXXXXX
428XXXXXXXXXXXXXXXXXXXX
429XXXXXXXXXXXXXXXXXXXX
430XXXXXXXXXXXXXXXXXXXX
431
432
433XXXXXXXXXXXXXXXXXXXX
434XXXXXXXXXXXXXXXXXXXX
435XXXXXXXXXXXXXXXXXXXX
436XXXXXXXXXXXXXXXXXXXX
437XXXXXXXX########XXXX
438XXXXX#### . #XXXX
439XXXXX# $ $ $. #XXXX
440XXXXX# .####.##XXXX
441XXXXX# $.$ $ @#XXXXX
442XXXXX# . ##XXXXX
443XXXXX#########XXXXXX
444XXXXXXXXXXXXXXXXXXXX
445XXXXXXXXXXXXXXXXXXXX
446XXXXXXXXXXXXXXXXXXXX
447XXXXXXXXXXXXXXXXXXXX
448XXXXXXXXXXXXXXXXXXXX
449
450
451XXXXXXXXXXXXXXXXXXXX
452XXXXXXXXXXXXXXXXXXXX
453XXXXXXXXXXXXXXXXXXXX
454XXXXXXXXXXXXXXXXXXXX
455XXXXXXXXXXXXXXXXXXXX
456XXXXX#######XXXXXXXX
457XXXXX# #####XXXX
458XXXXX# $ .%. $ #XXXX
459XXXXX#@$.% %.$ #XXXX
460XXXXX# $ .%. $ #XXXX
461XXXXX###### #XXXX
462XXXXXXXXXX######XXXX
463XXXXXXXXXXXXXXXXXXXX
464XXXXXXXXXXXXXXXXXXXX
465XXXXXXXXXXXXXXXXXXXX
466XXXXXXXXXXXXXXXXXXXX
467
468
469XXXXXXXXXXXXXXXXXXXX
470XXXXXXXXXXXXXXXXXXXX
471XXXXXXXXXXXXXXXXXXXX
472XXXXXXXXXXXXXXXXXXXX
473XXXXX######XXXXXXXXX
474XXXXX# #XXXXXXXXX
475XXXXX# $ ####XXXXXX
476XXXXX# $%..% #XXXXXX
477XXXXX# %..%$ #XXXXXX
478XXXXX#### $ #XXXXXX
479XXXXXXXX# @ #XXXXXX
480XXXXXXXX######XXXXXX
481XXXXXXXXXXXXXXXXXXXX
482XXXXXXXXXXXXXXXXXXXX
483XXXXXXXXXXXXXXXXXXXX
484XXXXXXXXXXXXXXXXXXXX
485
486
487XXXXXXXXXXXXXXXXXXXX
488XXXXXXXXXXXXXXXXXXXX
489XXXXXXXXXXXXXXXXXXXX
490XXXXXXXXXXXXXXXXXXXX
491XXXXXXXXX######XXXXX
492XXXXXX####. @#XXXXX
493XXXXXX# $$$ #XXXXX
494XXXXXX#.##.##.#XXXXX
495XXXXXX# $ #XXXXX
496XXXXXX# $.# ##XXXXX
497XXXXXX#### #XXXXXX
498XXXXXXXXX#####XXXXXX
499XXXXXXXXXXXXXXXXXXXX
500XXXXXXXXXXXXXXXXXXXX
501XXXXXXXXXXXXXXXXXXXX
502XXXXXXXXXXXXXXXXXXXX
503
504
505XXXXXXXXXXXXXXXXXXXX
506XXXXXXXXXXXXXXXXXXXX
507XXXXXXXXXXXXXXXXXXXX
508XXXXXXXXXXXXXXXXXXXX
509XXXXXX#########XXXXX
510XXXXXX#. $. @#XXXXX
511XXXXXX# .$.$ #XXXXX
512XXXXXX##$.$ $##XXXXX
513XXXXXX# .$.$ #XXXXX
514XXXXXX#. $. #XXXXX
515XXXXXX#########XXXXX
516XXXXXXXXXXXXXXXXXXXX
517XXXXXXXXXXXXXXXXXXXX
518XXXXXXXXXXXXXXXXXXXX
519XXXXXXXXXXXXXXXXXXXX
520XXXXXXXXXXXXXXXXXXXX
521
522
523XXXXXXXXXXXXXXXXXXXX
524XXXXXXXXXXXXXXXXXXXX
525XXXXXXXXXXXXXXXXXXXX
526XXXXXXXXXXXXXXXXXXXX
527XXXXXXXXXXXXXXXXXXXX
528XXXXXXX#######XXXXXX
529XXXXXXX# @ #XXXXXX
530XXXXXXX##$ $ #XXXXXX
531XXXXXXX# $$##XXXXXX
532XXXXXXX#....#XXXXXXX
533XXXXXXX######XXXXXXX
534XXXXXXXXXXXXXXXXXXXX
535XXXXXXXXXXXXXXXXXXXX
536XXXXXXXXXXXXXXXXXXXX
537XXXXXXXXXXXXXXXXXXXX
538XXXXXXXXXXXXXXXXXXXX
539
540
541XXXXXXXXXXXXXXXXXXXX
542XXXXXXXXXXXXXXXXXXXX
543XXXXXXXXXXXXXXXXXXXX
544XXXXXXXXXXXXXXXXXXXX
545XXXXXX####XXXXXXXXXX
546XXXXXX# #####XXXXXX
547XXXXX##$ ## #XXXXXX
548XXXXX# $@$ #XXXXXX
549XXXXX# ##$ #XXXXXX
550XXXXX###.## ###XXXXX
551XXXXXX#...$ $ #XXXXX
552XXXXXX##.. #XXXXX
553XXXXXXX########XXXXX
554XXXXXXXXXXXXXXXXXXXX
555XXXXXXXXXXXXXXXXXXXX
556XXXXXXXXXXXXXXXXXXXX
557
558
559XXXXXXXXXXXXXXXXXXXX
560XXXXXXXXXXXXXXXXXXXX
561XXXXXXXXXXXXXXXXXXXX
562XXXXXXXXXXXXXXXXXXXX
563XXXXXXXXXXXXXXXXXXXX
564XXXXXX########XXXXXX
565XXXXXX# #.. ##XXXXX
566XXXXXX# $. $% #XXXXX
567XXXXXX# $@$ #XXXXX
568XXXXXX# %$ .$ #XXXXX
569XXXXXX## ..# #XXXXX
570XXXXXXX########XXXXX
571XXXXXXXXXXXXXXXXXXXX
572XXXXXXXXXXXXXXXXXXXX
573XXXXXXXXXXXXXXXXXXXX
574XXXXXXXXXXXXXXXXXXXX
575
576
577XXXXXXXXXXXXXXXXXXXX
578XXXXXXXXXXXXXXXXXXXX
579XXXXXXXXXXXXXXXXXXXX
580XXXXXXXXXXXXXXXXXXXX
581XXXXXX#######XXXXXXX
582XXXXX## % ##XXXXXX
583XXXXX# . . . #XXXXXX
584XXXXX# $ % #XXXXXX
585XXXXX#%$$%$$%#XXXXXX
586XXXXX# % $ #XXXXXX
587XXXXX# . .@. #XXXXXX
588XXXXX## % ##XXXXXX
589XXXXXX#######XXXXXXX
590XXXXXXXXXXXXXXXXXXXX
591XXXXXXXXXXXXXXXXXXXX
592XXXXXXXXXXXXXXXXXXXX
593
594
595XXXXXXXXXXXXXXXXXXXX
596XXXXXXXXXXXXXXXXXXXX
597XXXXXXXXXXXXXXXXXXXX
598XXXXXXXXXXXXXXXXXXXX
599XXXXX#########XXXXXX
600XXXXX# .$ @#XXXXXX
601XXXXX# $ % $ #XXXXXX
602XXXXX#%...%.%#XXXXXX
603XXXXX# $$% #XXXXXX
604XXXXX# . $ #XXXXXX
605XXXXX#########XXXXXX
606XXXXXXXXXXXXXXXXXXXX
607XXXXXXXXXXXXXXXXXXXX
608XXXXXXXXXXXXXXXXXXXX
609XXXXXXXXXXXXXXXXXXXX
610XXXXXXXXXXXXXXXXXXXX
611
612
613XXXXXXXXXXXXXXXXXXXX
614XXXXXXXXXXXXXXXXXXXX
615XXXXXXXXXXXXXXXXXXXX
616XXXXXXXXX######XXXXX
617XXXXX#####. #XXXXX
618XXXXX# #..## #XXXXX
619XXXXX# $.. #XXXXX
620XXXXX# # .# ##XXXXX
621XXXX### ##$# #XXXXX
622XXXX# $ $$ #XXXXX
623XXXX# #$# # #XXXXX
624XXXX#@ #######XXXXX
625XXXX#####XXXXXXXXXXX
626XXXXXXXXXXXXXXXXXXXX
627XXXXXXXXXXXXXXXXXXXX
628XXXXXXXXXXXXXXXXXXXX
629
630
631XXXXXXXXXXXXXXXXXXXX
632XXXXXXXXXXXXXXXXXXXX
633XXXXXXXXXXXXXXXXXXXX
634XXXXXXXXXXXXXXXXXXXX
635XXXXXXX######XXXXXXX
636XXXXXXX# ...#XXXXXXX
637XXXX####....#XXXXXXX
638XXXX# ###$ ###XXXXX
639XXXX# $ $ $$ #XXXXX
640XXXX#@ $ $ #XXXXX
641XXXX# #### #XXXXX
642XXXX####XX#####XXXXX
643XXXXXXXXXXXXXXXXXXXX
644XXXXXXXXXXXXXXXXXXXX
645XXXXXXXXXXXXXXXXXXXX
646XXXXXXXXXXXXXXXXXXXX
647
648
649XXXXXXXXXXXXXXXXXXXX
650XXXXXXXXXXXXXXXXXXXX
651XXXXXXXXXXXXXXXXXXXX
652XXXXXXXXXXXXXXXXXXXX
653XXXXXX#########XXXXX
654XXXXXX# ## #XXXXX
655XXXXXX# $ #XXXXX
656XXXXXX#$ ### $#XXXXX
657XXXXXX# #...# #XXXXX
658XXXXX## #...# ##XXXX
659XXXXX# $ $ $ #XXXX
660XXXXX# # @ #XXXX
661XXXXX###########XXXX
662XXXXXXXXXXXXXXXXXXXX
663XXXXXXXXXXXXXXXXXXXX
664XXXXXXXXXXXXXXXXXXXX
665
666
667XXXXXXXXXXXXXXXXXXXX
668XXXXXXXXXXXXXXXXXXXX
669XXXXXXXX#######XXXXX
670XXXXXX### #XXXXX
671XXXXX## # # #XXXXX
672XXXXX# #.$$$ #XXXXX
673XXXXX# #.%# ###XXXXX
674XXXXX# ..# #XXXXXXX
675XXXXX###..$ ##XXXXXX
676XXXXXXX#.# $ #XXXXXX
677XXXXXX## # #@#XXXXXX
678XXXXXX# $ $ #XXXXXX
679XXXXXX# ###XXXXXX
680XXXXXX######XXXXXXXX
681XXXXXXXXXXXXXXXXXXXX
682XXXXXXXXXXXXXXXXXXXX
683
684
685XXXXXXXXXXXXXXXXXXXX
686XXXXXXXXXXXXXXXXXXXX
687XXXXXX##########XXXX
688XXXXX## #XXXX
689XXXXX#@ $$$ $ #XXXX
690XXXXX## $ $ $ #XXXX
691XXXXXX## #### ##XXXX
692XXXXXXX# $ ##XXXX
693XXXXX### ##$ $ #XXXX
694XXXXX# # #XXXX
695XXXXX# ######XXXX
696XXXXX# ##XXXXXXXX
697XXXXX#.....#XXXXXXXX
698XXXXX#.....#XXXXXXXX
699XXXXX#######XXXXXXXX
700XXXXXXXXXXXXXXXXXXXX
701
702
703XXXXXXXXXXXXXXXXXXXX
704XXXXXXXXXXXXXXXXXXXX
705XXXXX########XXXXXXX
706XXXXX# #XXXXXXX
707XXXXX# @ $# #XXXXXXX
708XXXXX## # #XXXXXXX
709XXXXX# $#.# #XXXXXXX
710XXXXX# .%.$#XXXXXXX
711XXXXX## #.# #XXXXXXX
712XXXXXX# #. ##XXXXXX
713XXXXX## $.# #XXXXXX
714XXXXX# # $ #XXXXXX
715XXXXX# $ ###XXXXXX
716XXXXX# ####XXXXXXXX
717XXXXX####XXXXXXXXXXX
718XXXXXXXXXXXXXXXXXXXX
719
720
721XXXXXXXXXXXXXXXXXXXX
722XXXXXXXXXXX####XXXXX
723XXXXXXXXXXX#@ #XXXXX
724XXXXXXX##### #XXXXX
725XXXX#### #XXXXX
726XXXX# .### ##XXXXX
727XXXX# # # ##XXXXX
728XXXX# # $ $#. #XXXXX
729XXXX# # % # #XXXXX
730XXXX# .#$ $ # #XXXXX
731XXXX## # # #XXXXX
732XXXXX# ###. #XXXXX
733XXXXX# ####XXXXX
734XXXXX#######XXXXXXXX
735XXXXXXXXXXXXXXXXXXXX
736XXXXXXXXXXXXXXXXXXXX
737
738
739XXXXXXXXXXXXXXXXXXXX
740XXXXXXXXXXXXXXXXXXXX
741XXXXXXX#####XXXXXXXX
742XXXXXXX# ##XXXXXXX
743XXXXXXX# $ #XXXXXXX
744XXXXXXX# $ @#XXXXXXX
745XXXXXXX###. #XXXXXXX
746XXXXXXXXX#.##XXXXXXX
747XXXXXXXXX#. #XXXXXXX
748XXXXXXX###. #XXXXXXX
749XXXXXXX# $ #XXXXXXX
750XXXXXXX# $ #XXXXXXX
751XXXXXXX## ##XXXXXXX
752XXXXXXXX####XXXXXXXX
753XXXXXXXXXXXXXXXXXXXX
754XXXXXXXXXXXXXXXXXXXX
755
756
757XXXXXXXXXXXXXXXXXXXX
758XXXXXXXXXXXXXXXXXXXX
759XXXXXX####XXXXXXXXXX
760XXXXXX# #####XXXXXX
761XXXXXX# # #XXXXXX
762XXXXXX# . # #XXXXXX
763XXXXXX##$# .#XXXXXX
764XXXXXXX# #$# #XXXXXX
765XXXXXX##. . #XXXXXX
766XXXXXX# ## #XXXXXX
767XXXXXX# # %#XXXXXX
768XXXXXX# $ $ #XXXXXX
769XXXXXX# $#% @#XXXXXX
770XXXXXX# #.###XXXXXX
771XXXXXX######XXXXXXXX
772XXXXXXXXXXXXXXXXXXXX
773
774
775XXXXXXXXXXXXXXXXXXXX
776XXXXXXXXXXXXXXXXXXXX
777XXXXXXXX###XXXXXXXXX
778XXXXXXXX#.######XXXX
779XXXXXX###.$ # #XXXX
780XXXXXX#... #$ #XXXX
781XXXXXX#.## $ #XXXX
782XXXXX##.$ $## ##XXXX
783XXXXX#.$ # ## #XXXXX
784XXXXX#.#$ #XXXXX
785XXXXX#.$ #$ $#XXXXX
786XXXXX#. $## @ #XXXXX
787XXXXX#.$ $ #XXXXX
788XXXXX#. #######XXXXX
789XXXXX####XXXXXXXXXXX
790XXXXXXXXXXXXXXXXXXXX
791
792
793XXXXXXXXXXXXXXXXXXXX
794XXXXXXXXXXXXXXXXXXXX
795XXXXXXXXX####XXXXXXX
796XXXXXXX### ##XXXXXX
797XXXXXX## ##XXXXX
798XXXXXX# # ..#XXXXX
799XXXXX## $#%#$.#XXXXX
800XXXXX# $ # $.#XXXXX
801XXXXX# $ @ $.#XXXXX
802XXXXX# $ # $.#XXXXX
803XXXXX##$$#%#$.#XXXXX
804XXXXXX#. # ..#XXXXX
805XXXXXX##. ##XXXXX
806XXXXXXX### ##XXXXXX
807XXXXXXXXX####XXXXXXX
808XXXXXXXXXXXXXXXXXXXX
809
810
811XXXXXXXXXXXXXXXXXXXX
812XXXXXXXXXXXXXXXXXXXX
813XXXXXX#########XXXXX
814XXXXXX# #XXXXX
815XXXXXX# # ### #XXXXX
816XXXXXX# $$ # #XXXXX
817XXXXXX#@$ # #XXXXX
818XXXXXX## ## # #XXXXX
819XXXXXX# $ $ #XXXXX
820XXXXXX# $## # #XXXXX
821XXXXXX# #$# #XXXXX
822XXXXXX#...# #XXXXX
823XXXXXX#.#.#$###XXXXX
824XXXXXX#... #XXXXXXX
825XXXXXX#######XXXXXXX
826XXXXXXXXXXXXXXXXXXXX
827
828
829XXXXXXXXXXXXXXXXXXXX
830XXXXXXXXXXXXXXXXXXXX
831XXXXX########XXXXXXX
832XXXXX# .#XXXXXXX
833XXXXX# #$#..##XXXXXX
834XXXXX# $...#XXXXXX
835XXXXX## ##.$.#XXXXXX
836XXXXXX# ## ##XXXXXX
837XXXXXX#$## #XXXXXXX
838XXXXX## #$#XXXXXXX
839XXXXX# # #XXXXXXX
840XXXXX# $ ####XXXXX
841XXXXX# $ $ @#XXXXX
842XXXXX# ### #XXXXX
843XXXXX####X#####XXXXX
844XXXXXXXXXXXXXXXXXXXX
845
846
847XXXXXXXXXXXXXXXXXXXX
848XXXXXXXXXXXXXXXXXXXX
849XXXXXX####XXXXXXXXXX
850XXXXXX# ####XXXXXXX
851XXXXXX# $ #XXXXXXX
852XXXXXX# #.# #XXXXXXX
853XXXXXX# # # #XXXXXXX
854XXXXXX#.$.$.#XXXXXXX
855XXXXXX# # # #XXXXXXX
856XXXXXX# #.# #XXXXXXX
857XXXXXX# $$ #XXXXXXX
858XXXXXX## @ #XXXXXXX
859XXXXXXX# ###XXXXXXX
860XXXXXXX####XXXXXXXXX
861XXXXXXXXXXXXXXXXXXXX
862XXXXXXXXXXXXXXXXXXXX
863
864
865XXXXXXXXXXXXXXXXXXXX
866XXXXXXXXXXXXXXXXXXXX
867XXXX######X####XXXXX
868XXXX# ### #XXXXX
869XXXX# $$ ## #XXXXX
870XXXX# # $ #XXXXX
871XXXX## ## $# #XXXXX
872XXXXX# #... ##XXXXX
873XXXXX# ...#$##XXXXX
874XXXXX# #...# #XXXXX
875XXXX## # ###@ #XXXXX
876XXXX# $ $ $ #XXXXX
877XXXX# #$#### #XXXXX
878XXXX# #XX####XXXXX
879XXXX#####XXXXXXXXXXX
880XXXXXXXXXXXXXXXXXXXX
881
882
883XXXXXXXXXXXXXXXXXXXX
884XXXXXXXXXXXXXXXXXXXX
885XXXXX##########XXXXX
886XXXXX#..$ $ %.#XXXXX
887XXXXX#.% $ $..#XXXXX
888XXXXX##.$ $ %##XXXXX
889XXXXXX#% $ $.#XXXXXX
890XXXXXX#.$ $ .#XXXXXX
891XXXXXX#. $ $.#XXXXXX
892XXXXXX#.$@$ %#XXXXXX
893XXXXX##% $ $.##XXXXX
894XXXXX#..$ $ %.#XXXXX
895XXXXX#.% $ $..#XXXXX
896XXXXX##########XXXXX
897XXXXXXXXXXXXXXXXXXXX
898XXXXXXXXXXXXXXXXXXXX
899
900
901XXXXXXXXXXXXXXXXXXXX
902XXXXXXXXXXXXXXXXXXXX
903XXXX#####XXXXXXXXXXX
904XXXX# #XXXXXXXXXXX
905XXXX#$ #XXXXXXXXXXX
906XX### $##XXXXXXXXXX
907XX# $ $ #XXXXXXXXXX
908### # ## #XXX######X
909# # ## ##### ..#X
910# $ $ ..#X
911##### ### #@## ..#X
912XXXX# #########X
913XXXX#######XXXXXXXXX
914XXXXXXXXXXXXXXXXXXXX
915XXXXXXXXXXXXXXXXXXXX
916XXXXXXXXXXXXXXXXXXXX
917
918
919XXXXXXXXXXXXXXXXXXXX
920XXXXXXXXXXXXXXXXXXXX
921XXXXXXXXXXXXXXXXXXXX
922XXX############XXXXX
923XXX#.. # ###XXX
924XXX#.. # $ $ #XXX
925XXX#.. #$#### #XXX
926XXX#.. @ ## #XXX
927XXX#.. # $ ##XXX
928XXX###### ##$ $ #XXX
929XXXXX# $ $ $ $ #XXX
930XXXXX# # #XXX
931XXXXX############XXX
932XXXXXXXXXXXXXXXXXXXX
933XXXXXXXXXXXXXXXXXXXX
934XXXXXXXXXXXXXXXXXXXX
935
936
937XXXXXXXXXXXXXXXXXXXX
938XXXXXXXXXXXXXXXXXXXX
939XXXXXXXXXXXXXXXXXXXX
940XXXXXXXXX########XXX
941XXXXXXXXX# @#XXX
942XXXXXXXXX# $#$ ##XXX
943XXXXXXXXX# $ $#XXXX
944XXXXXXXXX##$ $ #XXXX
945X######### $ # ###XX
946X#.... ## $ $ #XX
947X##... $ $ #XX
948X#.... ##########XX
949X########XXXXXXXXXXX
950XXXXXXXXXXXXXXXXXXXX
951XXXXXXXXXXXXXXXXXXXX
952XXXXXXXXXXXXXXXXXXXX
953
954
955XXXXXXXXXXXXXXXXXXXX
956XXXXXXXXXXXX########
957XXXXXXXXXXXX# ....#
958X############ ....#
959X# # $ $ ....#
960X# $$$#$ $ # ....#
961X# $ $ # ....#
962X# $$ #$ $ $########
963X# $ # #XXXXXXX
964X## #########XXXXXXX
965X# # ##XXXXXXX
966X# $ ##XXXXXXX
967X# $$#$$ @#XXXXXXX
968X# # ##XXXXXXX
969X###########XXXXXXXX
970XXXXXXXXXXXXXXXXXXXX
971
972
973XXXXXXXXXXXXXXXXXXXX
974XXXXXXXXXXXXXXXXXXXX
975XXXXXXXXX#####XXXXXX
976XXXXXXXXX# #####XX
977XXXXXXXXX# #$## #XX
978XXXXXXXXX# $ #XX
979X######### ### #XX
980X#.... ## $ $###XX
981X#.... $ $$ ##XXX
982X#.... ##$ $ @#XXX
983X######### $ ##XXX
984XXXXXXXXX# $ $ #XXX
985XXXXXXXXX### ## #XXX
986XXXXXXXXXXX# #XXX
987XXXXXXXXXXX######XXX
988XXXXXXXXXXXXXXXXXXXX
989
990
991XXXXXXXXXXXXXXXXXXXX
992XXXXXXXXXXXXXXXXXXXX
993XXXXXXXXXXXXXXXXXXXX
994XXXX######XX###XXXXX
995XXXX#.. #X##@##XXXX
996XXXX#.. ### #XXXX
997XXXX#.. $$ #XXXX
998XXXX#.. # # $ #XXXX
999XXXX#..### # $ #XXXX
1000XXXX#### $ #$ #XXXX
1001XXXXXXX# $# $ #XXXX
1002XXXXXXX# $ $ #XXXX
1003XXXXXXX# ## #XXXX
1004XXXXXXX#########XXXX
1005XXXXXXXXXXXXXXXXXXXX
1006XXXXXXXXXXXXXXXXXXXX
1007
1008
1009XXXXXXXXXXXXXXXXXXXX
1010XXXXXXXXXXXXXXXXXXXX
1011XXXXXXXXXXX#####XXXX
1012XXXXX####### ##XXX
1013XXXX## # @## $$ #XXX
1014XXXX# $ #XXX
1015XXXX# $ ### #XXX
1016XXXX### #####$###XXX
1017XXXX# $ ### ..#XXXX
1018XXXX# $ $ $ ...#XXXX
1019XXXX# ###...#XXXX
1020XXXX# $$ #X#...#XXXX
1021XXXX# ###X#####XXXX
1022XXXX####XXXXXXXXXXXX
1023XXXXXXXXXXXXXXXXXXXX
1024XXXXXXXXXXXXXXXXXXXX
1025
1026
1027XXXX####XXXXXXXXXXXX
1028XXXX# ###########XX
1029XXXX# $ $ $ #XX
1030XXXX# $# $ # $ #XX
1031XXXX# $ $ # #XX
1032XX### $# # #### #XX
1033XX#@#$ $ $ ## #XX
1034XX# $ #$# # #XX
1035XX# $ $ $ $ #XX
1036XX##### #########XX
1037XXXX# #XXXXXXXX
1038XXXX#......#XXXXXXXX
1039XXXX#......#XXXXXXXX
1040XXXX#......#XXXXXXXX
1041XXXX########XXXXXXXX
1042XXXXXXXXXXXXXXXXXXXX
1043
1044
1045XXXXXXXXXXXXXXXXXXXX
1046XXXXXXXXXXX#######XX
1047XXXXXXXXXXX# ...#XX
1048XXXXXXX##### ...#XX
1049XXXXXXX# . .#XX
1050XXXXXXX# ## ...#XX
1051XXXXXXX## ## ...#XX
1052XXXXXX### ########XX
1053XXXXXX# $$$ ##XXXXXX
1054XX##### $ $ #####XX
1055X## #$ $ # #XX
1056X#@ $ $ $ $ #XX
1057X###### $$ $ #####XX
1058XXXXXX# #XXXXXX
1059XXXXXX########XXXXXX
1060XXXXXXXXXXXXXXXXXXXX
1061
1062
1063X###XX#############X
1064##@#### # #X
1065# $$ $$ $ $ ...#X
1066# $$$# $ #...#X
1067# $ # $$ $$ #...#X
1068### # $ #...#X
1069# # $ $ $ #...#X
1070# ###### ###...#X
1071## # # $ $ #...#X
1072# ## # $$ $ $##..#X
1073# ..# # $ #.#X
1074# ..# # $$$ $$$ #.#X
1075##### # # #.#X
1076XXXX# ######### #.#X
1077XXXX# #.#X
1078XXXX###############X
1079
1080
1081XXXXXXXXXXXXXXXXXXXX
1082XXXXXXXXXXX####XXXXX
1083XXXXXX####X# #XXXXX
1084XXXX### ###$ #XXXXX
1085XXX## @ $ #XXXXX
1086XX## $ $$## ##XXXXX
1087XX# #$## #XXXXX
1088XX# # $ $$ # ###XXXX
1089XX# $ # # $ #####
1090X#### # $$ # #
1091X#### ## $ #
1092X#. ### ########
1093X#.. ..#X####XXXXXXX
1094X#...#.#XXXXXXXXXXXX
1095X#.....#XXXXXXXXXXXX
1096X#######XXXXXXXXXXXX
1097
1098
1099XXXXXXXXXXXXXXXXXXXX
1100XXXXXXXXXXXXXXXXXXXX
1101XX################XX
1102XX# #XX
1103XX# # ###### #XX
1104XX# # $ $ $ $# #XX
1105XX# # $@$ ## ##X
1106XX# # #$ $ $###...#X
1107XX# # $ $ ##...#X
1108XX# ###$$$ $ ##...#X
1109XX# # ## ##...#X
1110XX##### ## ##...#X
1111XXXXXX##### ###X
1112XXXXXXXXXX# #XXX
1113XXXXXXXXXX#######XXX
1114XXXXXXXXXXXXXXXXXXXX
1115
1116
1117XXXXXXXXXXXXXXXXXXXX
1118XXXXXXXXXXXXXXXXXXXX
1119XXX#########XXXXXXXX
1120XX## ## ######XXX
1121### # # ###X
1122# $ #$ # # ... #X
1123# # $#@$## # #.#. #X
1124# # #$ # . . #X
1125# $ $ # # #.#. #X
1126# ## ##$ $ . . #X
1127# $ # # #$#.#. #X
1128## $ $ $ $... #X
1129X#$ ###### ## #X
1130X# #XXXX##########X
1131X####XXXXXXXXXXXXXXX
1132XXXXXXXXXXXXXXXXXXXX
1133
1134
1135XXXXXXXX#######XXXXX
1136XX####### #XXXXX
1137XX# # $@$ #XXXXX
1138XX#$$ # #########X
1139XX# ###......## #X
1140XX# $......## # #X
1141XX# ###...... #X
1142X## #### ### #$##X
1143X# #$ # $ # #XX
1144X# $ $$$ # $## #XX
1145X# $ $ ###$$ # #XX
1146X##### $ # #XX
1147XXXXX### ### # #XX
1148XXXXXXX# # #XX
1149XXXXXXX######## #XX
1150XXXXXXXXXXXXXX####XX
1151
1152
1153XXXXX########XXXXXXX
1154XXXXX# # #XXXXXXX
1155XXXXX# $ #XXXXXXX
1156XXX### #$ ####XXXX
1157XXX# $ ##$ #XXXX
1158XXX# # @ $ # $#XXXX
1159XXX# # $ ####X
1160XXX## ####$## #X
1161XXX# $#.....# # #X
1162XXX# $..%%. $# ###X
1163XX## #.....# #XXX
1164XX# ### #######XXX
1165XX# $$ # #XXXXXXXX
1166XX# # #XXXXXXXX
1167XX###### #XXXXXXXX
1168XXXXXXX#####XXXXXXXX
1169
1170
1171XXX#####XXXXXXXXXXXX
1172XXX# ##XXXXXXXXXXX
1173XXX# #XX####XXXXX
1174XXX# $ #### #XXXXX
1175XXX# $$ $ $#XXXXX
1176XXX###@ #$ ##XXXX
1177XXXX# ## $ $ ##XXX
1178XXXX# $ ## ## .#XXX
1179XXXX# #$##$ #.#XXX
1180XXXX### $..##.#XXX
1181XXXXX# #.%...#XXX
1182XXXXX# $$ #.....#XXX
1183XXXXX# #########XXX
1184XXXXX# #XXXXXXXXXXX
1185XXXXX####XXXXXXXXXXX
1186XXXXXXXXXXXXXXXXXXXX
1187
1188
1189XXXXXXXXXXXXXXXXXXXX
1190XXXXX##########XXXXX
1191XXXXX#.. # #XXXXX
1192XXXXX#.. #XXXXX
1193XXXXX#.. # ####XXX
1194XXXX####### # ##XX
1195XXXX# #XX
1196XXXX# # ## # #XX
1197XX#### ## #### ##XX
1198XX# $ ##### # #XX
1199XX# # $ $ # $ #XX
1200XX# @$ $ # ##XX
1201XX#### ## #######XXX
1202XXXXX# #XXXXXXXXX
1203XXXXX######XXXXXXXXX
1204XXXXXXXXXXXXXXXXXXXX
1205
1206
1207XXXXXXXXXXXXXXXXXXXX
1208XXXXX###########XXXX
1209XXXXX# . # #XXXX
1210XXXXX# #. @ #XXXX
1211X##### ##..# ####XXX
1212## # ..### ###X
1213# $ #... $ # $ #X
1214# .. ## ## ## #X
1215####$##$# $ # # #X
1216XX## # #$ $$ # #X
1217XX# $ # # # $## #X
1218XX# #X
1219XX# ########### #X
1220XX####XXXXXXXXX####X
1221XXXXXXXXXXXXXXXXXXXX
1222XXXXXXXXXXXXXXXXXXXX
1223
1224
1225XXX######XXXXXXXXXXX
1226XXX# @####XXXXXXXX
1227X##### $ #XXXXXXXX
1228X# ## ####XXXXX
1229X# $ # ## #XXXXX
1230X# $ # ##### #XXXXX
1231X## $ $ # #XXXXX
1232X## $ $ ### # #XXXXX
1233X## # $ # # #XXXXX
1234X## # #$# # #XXXXX
1235X## ### # # ######
1236X# $ #### # #....#
1237X# $ $ ..#.#
1238X####$ $# $ ....#
1239X# # ## ....#
1240X###################
1241
1242
1243XXXXX##########XXXXX
1244X##### ####XX
1245X# # $ #@ #XX
1246X# #######$#### ###
1247X# # ## # #$ ..#
1248X# # $ $ # # #.#
1249X# # $ # #$ ..#
1250X# # ### ## #.#
1251X# ### # # #$ ..#
1252X# # # $#### #.#
1253X# #$ $ $ #% ..#
1254X# $ # $ $ # #.#
1255X#### $### #% ..#
1256XXXX# $$ ###....#
1257XXXX# ##X######
1258XXXX########XXXXXXXX
1259
1260
1261XXXXXXXXXXXXXXXXXXXX
1262XXX#########XXXXXXXX
1263XXX# #XXXXXXXX
1264XXX# ####XXXXX
1265XXX## #### # #XXXXX
1266XXX## #@## #XXXXX
1267XXX# $$$ $ $$#XXXXX
1268XXX# # ## $ #XXXXX
1269XXX# # ## $ ####XX
1270XXX#### $$$ $# #XX
1271XXXX# ## ....#XX
1272XXXX# # # #.. .#XX
1273XXXX# # # ##...#XX
1274XXXX##### $ #...#XX
1275XXXXXXXX## #####XX
1276XXXXXXXXX#####XXXXXX
1277
1278
1279X######XXXXX####XXXX
1280X# ####### #####
1281X# $# # $ # #
1282X# $ $ $ # $ $ #
1283X##$ $ # @# $ #
1284X# $ ########### ##
1285X# # #.......# $#X
1286X# ## # ......# #X
1287X# # $........$ #X
1288X# # $ #.... ..# #X
1289X# $ $####$#### $#X
1290X# $ ### $ $ ##
1291X# $ $ $ $ #
1292X## ###### $ ##### #
1293X# # #
1294X###################
1295
1296
1297XXXXXXXXXXXXXXXXXXXX
1298XXXXX#######XXXXXXXX
1299XXXXX# # ####XXXXX
1300X##### $#$ # ##XXXX
1301X#.. # # # ####X
1302X#.. # $#$ # $# #X
1303X#. # #$ # #X
1304X#.. $# # $ #X
1305X#..@# #$ #$ # #X
1306X#.. # $# $# #X
1307X#.. # #$$#$ # ##
1308X#.. # $# # $#$ #
1309X#.. # # # # #
1310X##. #### ##### #
1311XX####XX####XXX#####
1312XXXXXXXXXXXXXXXXXXXX
1313
1314
1315X###############XXXX
1316X#.......... .####X
1317X#..........$$.# #X
1318X###########$ # ##
1319X# $ $ $ #
1320X## #### # $ # #
1321X# # ## # ##
1322X# $# # ## ### ##
1323X# $ #$### ### ##
1324X### $ # # ### ##
1325XX## $ ## # # ##
1326XX# $ # $ $ $ #
1327XX# $ $#$$$ # #
1328XX# # $ #####
1329XX# @## # #XXXX
1330XX##############XXXX
1331
1332
1333X####XXXXXXXXXXXXXXX
1334X# ##############XX
1335X# # ..#......#XX
1336X# # # ##### ...#XX
1337X##$# ........#XX
1338X# ##$###### ####
1339X# $ # ######@ #
1340X##$ # $ ###### #
1341X# $ #$$$## #
1342X# # #$#$###
1343X# #### #$$$$$ #X
1344X# # $ # #X
1345X# # ## ## ###
1346X# ######$###### $ #
1347X# #XXXX# #
1348X##########XXXX#####
1349
1350
1351XXXXXXXXXXXXXXXXXXXX
1352XXXXXXXXXXXXXXXXXXXX
1353XXX#######XXXXXXXXXX
1354XXX# # #####XXXXXX
1355XX## # #...###XXXX
1356XX# $# #... #XXXX
1357XX# $ #$$ ... #XXXX
1358XX# $# #... .#XXXX
1359XX# # $########XXX
1360XX##$ $ $ #XXX
1361XX## # $$ # #XXX
1362XXX###### ##$$@#XXX
1363XXXXXXXX# ##XXX
1364XXXXXXXX########XXXX
1365XXXXXXXXXXXXXXXXXXXX
1366XXXXXXXXXXXXXXXXXXXX
1367
1368
1369XXXXXXXXXXXXXXXXXXXX
1370XXXXXXXXXXXXXXXXXXXX
1371X#################XX
1372X#... # # ##X
1373##..... $## # #$ #X
1374#......# $ # #X
1375#......# # # # #X
1376######### $ $ $ #X
1377XX# #$##$ ##$##X
1378X## $ # $ #X
1379X# ## ### # ##$ #X
1380X# $ $$ $ $ #X
1381X# $ $##$ ######X
1382X####### @ ##XXXXXX
1383XXXXXXX######XXXXXXX
1384XXXXXXXXXXXXXXXXXXXX
1385
1386
1387XXXXXXXXXXX#####XXXX
1388XXXXXXX##### #XXXX
1389XXXXXX## $ $ ####X
1390XX##### $ $ $ ##.#X
1391XX# $$ ##..#X
1392XX# ###### ###.. #X
1393XX## # # #... #X
1394XX# $ # #... #X
1395XX#@ #$ ## ####...#X
1396XX#### $ $$ ##..#X
1397XXXXX## $ $ $...#X
1398XXXXXX# $$ $ # .#X
1399XXXXXX# $ $ ####X
1400XXXXXX###### #XXXX
1401XXXXXXXXXXX#####XXXX
1402XXXXXXXXXXXXXXXXXXXX
1403
1404
1405XXXXXXXXXXXXXXXXXXXX
1406X#####XXXXXXXXXXXXXX
1407X# ##XXXXXXXXXXXXX
1408X# $ #########XXXXX
1409X## # # ######
1410X## # $#$#@ # #
1411X# # $ # $ #
1412X# ### ######### ##
1413X# ## ..%..... # ##
1414X## ## %.%..%.% # ##
1415X# $########## ##$ #
1416X# $ $ $ $ #
1417X# # # # # #
1418X###################
1419XXXXXXXXXXXXXXXXXXXX
1420XXXXXXXXXXXXXXXXXXXX
1421
1422
1423XXXXXXXXXXXXXXXXXXXX
1424XXXXXXXX###########X
1425XXXXXXXX# # #X
1426X#####XX# $ $ #X
1427X# ##### $## # ##X
1428X# $ ## # ## $ #X
1429X# $ @$$ # ##$$$ #X
1430X## ### # ## #X
1431X## # ### #####$#X
1432X## # $ #....#X
1433X# ### ## $ #....##
1434X# $ $ # #..$. #
1435X# ## $ # ##.... #
1436X##### ######...##
1437XXXXX#####XXXX#####X
1438XXXXXXXXXXXXXXXXXXXX
1439
1440
1441XXX####XXXXXXXXXXXXX
1442XXX# #########XXXXX
1443XX## ## # #XXXXX
1444XX# $# $@$ ####XX
1445XX#$ $ # $ $# ##X
1446X## $## #$ $ #X
1447X# # # # $$$ #X
1448X# $ $ $## ####X
1449X# $ $ #$# # #XXXX
1450X## ### ###$ #XXXX
1451XX# #.... #XXXX
1452XX####......####XXXX
1453XXXX#....####XXXXXXX
1454XXXX#...##XXXXXXXXXX
1455XXXX#...#XXXXXXXXXXX
1456XXXX#####XXXXXXXXXXX
1457
1458
1459XXXXXXXXXXXXXXXXXXXX
1460XXXXXXXXXX####XXXXXX
1461XXXXXX##### #XXXXXX
1462XXXXX## $#XXXXXX
1463XXXX## $ ## ###XXXX
1464XXXX#@$ $ # $ #XXXX
1465XXXX#### ## $#XXXX
1466XXXXX#....#$ $ #XXXX
1467XXXXX#....# $#XXXX
1468XXXXX#.... $$ ##XXX
1469XXXXX#... # $ #XXX
1470XXXXX######$ $ #XXX
1471XXXXXXXXXX# ###XXX
1472XXXXXXXXXX#$ ###XXXX
1473XXXXXXXXXX# #XXXXXX
1474XXXXXXXXXX####XXXXXX
1475
1476
1477XXXXXXXXXXXXXXXXXXXX
1478XXXX############XXXX
1479XXXX## ## #XXXX
1480XXXX## $ $ #XXXX
1481XXXX#### ## $$ #XXXX
1482XXXX# $ # #XXXX
1483XXXX# $$$ # ####XXXX
1484XXXX# # # $ ##XXXX
1485XXXX# # # $ #XXXX
1486XXXX# $# $# #XXXX
1487XXXX# ..# ####XXXX
1488XXXX####.. $ #@#XXXX
1489XXXX#.....# $# #XXXX
1490XXXX##....# $ #XXXX
1491XXXX###..## #XXXX
1492XXXX############XXXX
1493
1494
1495XXXXXXXXXXXXXXXXXXXX
1496XXXX#########XXXXXXX
1497XXXX#.... ##XXXXXX
1498XXXX#.#.# $ ##XXXXX
1499XXX##....# # @##XXXX
1500XXX# ....# # ##XXX
1501XXX# #$ ##$ #XXX
1502XXX## ### $ #XXX
1503XXXX#$ $ $ $# #XXX
1504XXXX# # $ $ ## #XXX
1505XXXX# ### ## #XXX
1506XXXX# ## ## ##XXX
1507XXXX# $ # $ #XXXX
1508XXXX###$ $ ###XXXX
1509XXXXXX# #####XXXXXX
1510XXXXXX####XXXXXXXXXX
1511
1512
1513############X######X
1514# # # ###....#X
1515# $$# @ .....#X
1516# # ### # ....#X
1517## ## ### # ....#X
1518X# $ $ # # ####X
1519X# $ $## # #X
1520#### # #### # ## #X
1521# # #$ ## # #X
1522# $ $ # ## # ##X
1523# # $ $ # # #XX
1524# $ ## ## # #####XX
1525# $$ $$ #XXXXXX
1526## ## ### $ #XXXXXX
1527X# #X# #XXXXXX
1528X######X######XXXXXX
1529
1530
1531XXXXXXXXXXXXX#####XX
1532X#####XX###### #XX
1533X# #### $ $ $ #XX
1534X# $ ## ## ## ##X
1535X# $ $ $ $ #X
1536X### $ ## ## ##
1537XXX# ##### #####$$ #
1538XX##$##### @## #
1539XX# $ ###$### $ ##
1540XX# $ # ### ###X
1541XX# $$ $ # $$ #XXX
1542XX# # ## #XXX
1543XX#######.. .####XXX
1544XXXXX#.........#XXXX
1545XXXXX#.........#XXXX
1546XXXXX###########XXXX
1547
1548
1549XXXXXXXXXXXXXXXXXXXX
1550###########XXXXXXXXX
1551#...... #########X
1552#...... # ## #X
1553#..### $ $ #X
1554#... $ $ # ### #X
1555#...#$##### # #X
1556### # #$ #$ #X
1557XX# $$ $ $ $## #X
1558XX# $ #$#$ ##$ #X
1559XX### ## # ## #X
1560XXX# $ $ ## ######X
1561XXX# $ $ #XXXXX
1562XXX## # # #XXXXX
1563XXXX#####@#####XXXXX
1564XXXXXXXX###XXXXXXXXX
1565
1566
1567XXXXXXXXXXXXXXXXXXXX
1568XXXXXXXXXXXXXXXXXXXX
1569XXXXXXXXXXXXXXXXXXXX
1570XXXXXXXXXX####XXXXXX
1571XXXX####### @#XXXXXX
1572XXXX# $ #XXXXXX
1573XXXX# $## $#XXXXXX
1574XXXX##$#...# #XXXXXX
1575XXXXX# $... #XXXXXX
1576XXXXX# #. .# ##XXXXX
1577XXXXX# # #$ #XXXXX
1578XXXXX#$ $ #XXXXX
1579XXXXX# #######XXXXX
1580XXXXX####XXXXXXXXXXX
1581XXXXXXXXXXXXXXXXXXXX
1582XXXXXXXXXXXXXXXXXXXX
1583
1584
1585XXXXXXXXXXXXXX######
1586XX#############....#
1587X## ## ##....#
1588X# $$## $ @##....#
1589X# $$ $# ....#
1590X# $ ## $$ # # ...#
1591X# $ ## $ # ....#
1592X## ##### ### ##.###
1593X## $ $ ## . #
1594X# $### # ##### ###
1595X# $ # #XX
1596X# $ #$ $ $### #XX
1597X# $$$# $ #X####XX
1598X# # $$ #XXXXXXX
1599X###### ###XXXXXXX
1600XXXXXX#####XXXXXXXXX
1601
1602
1603XXXXXX############XX
1604XXXXXX# ##X
1605XXXXXX# # #$$ $ #X
1606XXXXXX#$ #$# ## @#X
1607XXXXX## ## # $ # ##X
1608XXXXX# $ #$ # #XX
1609XXXXX# # $ # #XX
1610XXXXX## $ $ ## #XX
1611XXXXX# # ## $ #XX
1612XXXXX# ## $$# #XX
1613XX######$$ # #XX
1614XX#....# ########XX
1615XX#.#... ##XXXXXXXXX
1616XX#.... #XXXXXXXXX
1617XX#.... #XXXXXXXXX
1618XX#########XXXXXXXXX
1619
1620
1621XXXXXXXXXXX#####XXXX
1622XXXXXXXXXX## ##XXX
1623XXXXXXXXX## #XXX
1624XXXXXXXX## $$ #XXX
1625XXXXXXX## $$ $ #XXX
1626XXXXXXX# $ $ #XXX
1627####XXX# $$ #####X
1628# ######## ## #X
1629#. $$$@#X
1630#.# ####### ## ##X
1631#.# #######. #$ $##X
1632#........... # #X
1633############## $ #X
1634XXXXXXXXXXXXX## ##X
1635XXXXXXXXXXXXXX####XX
1636XXXXXXXXXXXXXXXXXXXX
1637
1638
1639XXXXXXXXXXXXXXXXXXXX
1640XXXXXXXXXXXXXXXXXXXX
1641XXXXXX########XXXXXX
1642XXX#### ######X
1643XXX# ## $ $ @#X
1644XXX# ## ##$#$ $ $##X
1645X### ......# $$ ##X
1646X# ......# # #X
1647X# # ......#$ $ #X
1648X# # ...... $$# $ #X
1649X# $### ###$ $ ##X
1650X### $ $ $ $ #XX
1651XXX# $ $ $ $ #XX
1652XXX###### ######XX
1653XXXXXXXX#####XXXXXXX
1654XXXXXXXXXXXXXXXXXXXX
1655
1656
1657XXXXXXXXXXXXXXXXXXXX
1658XXXXXXXXXXXXXXXXXXXX
1659XXXXXXXX#######XXXXX
1660XXXX##### # ####XX
1661XXXX# # $ #XX
1662X#### #$$ ## ## #XX
1663## # # ## ###X
1664# ### $#$ $ $ #X
1665#... # ## # #X
1666#...# @ # ### ##X
1667#...# ### $ $ #X
1668########X## # #X
1669XXXXXXXXXX#########X
1670XXXXXXXXXXXXXXXXXXXX
1671XXXXXXXXXXXXXXXXXXXX
1672XXXXXXXXXXXXXXXXXXXX
1673
1674
1675X#####XXXXXXXXXXXXXX
1676X# #XXXXXXXXXXXXXX
1677X# # #######XXXXXXXX
1678X# $@######XXXX
1679X# $ ##$ ### #XXXX
1680X# #### $ $ #XXXX
1681X# ##### # #$ ####X
1682## #### ##$ #X
1683# $# $ # ## ## #X
1684# # #...# #X
1685###### ### ... #X
1686XXXXX####X# #...# #X
1687XXXXXXXXXX# ### # #X
1688XXXXXXXXXX# #X
1689XXXXXXXXXX#########X
1690XXXXXXXXXXXXXXXXXXXX
1691
1692
1693XXXXXXXXXXXXXXXXXXXX
1694XXX#####X####XXXXXXX
1695XXX#...#X# ####XXXX
1696XXX#...### $ #XXXX
1697XXX#....## $ $###XX
1698XXX##....## $ #XX
1699XXX###... ## $ $ #XX
1700XXX# ## # $ #XX
1701XXX# ## # ### ####X
1702XXX# $ # #$ $ #X
1703XXX# $ @ $ $ #X
1704XXX# # $ $$ $ ###X
1705XXX# ###### ###XXX
1706XXX# ##XXXX####XXXXX
1707XXX###XXXXXXXXXXXXXX
1708XXXXXXXXXXXXXXXXXXXX
1709
1710
1711XXX##########XXXXXXX
1712XXX# ####XXXX
1713XXX# ###### # ##XXX
1714XXX# # $ $ $ $ #XXX
1715XXX# #$ #XXX
1716XXX###$ $$# ###XXX
1717XXXXX# ## # $##XXXX
1718XXXXX##$# $ @#XXXX
1719XXXXXX# $ $ ###XXXX
1720XXXXXX# # $ #XXXX
1721XXXXXX# ## # #XXXX
1722XXXXX## ##### #XXXX
1723XXXXX# #XXXX
1724XXXXX#.......###XXXX
1725XXXXX#.......#XXXXXX
1726XXXXX#########XXXXXX
1727
1728
1729XXXXXXXXXXXXXXXXXXXX
1730XXXXXXXXXXXXXXXXXXXX
1731XXXXXXXXXXXXXXXXXXXX
1732XXXXXXXXXX####XXXXXX
1733XX######### ##XXXXX
1734X## $ $ #####X
1735X# ## ## ##...#X
1736X# #$$ $ $$#$##...#X
1737X# # @ # ...#X
1738X# $# ###$$ ...#X
1739X# $ $$ $ ##....#X
1740X###$ #######X
1741XXX# #######XXXXXXX
1742XXX####XXXXXXXXXXXXX
1743XXXXXXXXXXXXXXXXXXXX
1744XXXXXXXXXXXXXXXXXXXX
1745
1746
1747XXXXX#########XXXXXX
1748XXXXX#%.%#%.%#XXXXXX
1749XXXXX#.%.%.%.#XXXXXX
1750XXXXX#%.%.%.%#XXXXXX
1751XXXXX#.%.%.%.#XXXXXX
1752XXXXX#%.%.%.%#XXXXXX
1753XXXXX### ###XXXXXX
1754XXXXXXX# #XXXXXXXX
1755XXX###### ######XXXX
1756XXX# #XXXX
1757XXX# $ $ $ $ $ #XXXX
1758XXX## $ $ $ $ ##XXXX
1759XXXX#$ $ $ $ $#XXXXX
1760XXXX# $@$ #XXXXX
1761XXXX# ##### #XXXXX
1762XXXX####XXX####XXXXX
1763
1764
1765XXXXXXXX####XXXXXXXX
1766XXXXXXXX# ##XXXXXXX
1767XXXXXXXX# ##XXXXXX
1768XXXXXXXX# $$ ##XXXXX
1769XXXXXX###$ $ ##XXXX
1770XXX#### $ #XXXX
1771X### # ##### #XXXX
1772X# # #....$ #XXXX
1773X# # $ ....# #XXXX
1774X# $ # #.%..# #XXXX
1775X### #### ### #XXXX
1776XXX#### @$ ##$##XXX
1777XXXXXX### $ #XXX
1778XXXXXXXX# ## #XXX
1779XXXXXXXX#########XXX
1780XXXXXXXXXXXXXXXXXXXX
1781
1782
1783XXXXXX############XX
1784XXXXX##.. #XX
1785XXXX##..% $ $ #XX
1786XXX##..%.# # #$ ##XX
1787XXX#..%.# # # $ #XX
1788####...# # # #XX
1789# ## # #XX
1790# @$ $ ### # # ##XX
1791# $ $ # # #XXX
1792###$$ # # # # #XXX
1793XX# $ # # #####X
1794XX# $# ##### #X
1795XX#$ #XXX# # #X
1796XX# ###XXX## #X
1797XX# #XXXXXX# ##X
1798XX####XXXXXX######XX
1799
1800
1801###################X
1802# ### # #X
1803# ##$ $ # $$ # $ #X
1804#.# . .$ # #..# #.#X
1805#.####.# # # ## # #X
1806# # # # # # #X
1807# $ # # ### # ## #X
1808# # # # #.$ # # #X
1809# $$.# # ## # ## #X
1810#$ # # # # ## # #X
1811# .# # ## # # ## #X
1812# # # # # ## #X
1813## ## # # # # $.#X
1814### ### $.# $.# $.#X
1815####### # # @#X
1816XXXXXX#############X
diff --git a/apps/plugins/sokobanlevels.sok b/apps/plugins/sokobanlevels.sok
new file mode 100644
index 0000000000..869dcfe76e
--- /dev/null
+++ b/apps/plugins/sokobanlevels.sok
@@ -0,0 +1,1277 @@
1 ###
2 #.#
3 # ####
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 ####
36 #@ ###
37 # $ #
38### # ##
39#.# # #
40#.$ # #
41#. $ #
42########
43
44 #######
45 ## # @#
46 # # #
47 #$ $ $ #
48 # $## #
49### $ # ##
50#..... #
51#########
52
53 ######
54 ### #
55##. $## ##
56#..$ $ @#
57#.. $ $ ##
58###### #
59 ####
60
61 ######
62 # #
63###$$$ #
64#@ $.. #
65# $...##
66#### #
67 ####
68
69 ####
70 #..#
71 ## .##
72 # $.#
73## $ ##
74# #$$ #
75# @ #
76########
77
78 #####
79### @#
80# $. ##
81# .$. #
82### *$ #
83 # ##
84 #####
85
86########
87# # #
88# $..$ #
89#@$.* ##
90# $..$ #
91# # #
92########
93
94 ######
95 # ###
96 # $ #
97### $ ## #
98#... $ #
99#...$#$ ##
100#### # $ #
101 # @ #
102 #######
103
104######
105# #
106# $$$##
107# #..###
108## ..$ #
109 # @ #
110 ########
111
112 ########
113 # #. #
114 ## $...#
115 # $ #*.#
116## ##$# ##
117# $ $ #
118# # #
119#######@ #
120 ####
121
122 #######
123 #.... #
124###...$###
125# $#$ $ #
126# $$ #$ #
127# # #
128#### @ ###
129 #####
130
131########
132#.. #
133#..$ $@#
134#$#$$$##
135#..$ $ #
136#.. #
137########
138
139########
140# #
141# #$$ #
142# ...# #
143##...$ ##
144 # ## $ #
145 #$ $ #
146 # # @#
147 ########
148
149 #####
150### ####
151# $ $ #
152# $ $ @#
153###$$#####
154 # ..#
155 #....#
156 ######
157
158#########
159# * #
160# $.$. @#
161# .$.$. #
162# $.$.$ #
163# * #
164#########
165
166 #########
167## #
168# #$#$ #
169# $$ .$.#
170# @###...#
171#### #####
172
173 ######
174 #. ..#
175 #. $.#
176### $##
177# $ $ #
178# #$## #
179# @ #
180########
181
182 #####
183 # ####
184## #$ #
185# $ $$ #
186# #$#.*.#
187# @...#
188#########
189
190 #####
191#### ##
192# $ $ #
193#@#.*.# #
194# #.*.# #
195# $ $ #
196## ####
197 #####
198
199 #####
200####. ##
201# $.$. #
202#@$# #$ #
203# $. . #
204####$#$ #
205 #. . #
206 #######
207
208 ########
209#### . #
210# $ $ $. #
211# .####.##
212# $.$ $ @#
213# . ##
214#########
215
216#######
217# #####
218# $ .*. $ #
219#@$.* *.$ #
220# $ .*. $ #
221###### #
222 ######
223
224######
225# #
226# $ ####
227# $*..* #
228# *..*$ #
229#### $ #
230 # @ #
231 ######
232
233 ######
234####. @#
235# $$$ #
236#.##.##.#
237# $ #
238# $.# ##
239#### #
240 #####
241
242#########
243#. $. @#
244# .$.$ #
245##$.$ $##
246# .$.$ #
247#. $. #
248#########
249
250#######
251# @ #
252##$ $ #
253# $$##
254#....#
255######
256
257 ####
258 # #####
259##$ ## #
260# $@$ #
261# ##$ #
262###.## ###
263 #...$ $ #
264 ##.. #
265 ########
266
267########
268# #.. ##
269# $. $* #
270# $@$ #
271# *$ .$ #
272## ..# #
273 ########
274
275 #######
276## * ##
277# . . . #
278# $ * #
279#*$$*$$*#
280# * $ #
281# . .@. #
282## * ##
283 #######
284
285#########
286# .$ @#
287# $ * $ #
288#*...*.*#
289# $$* #
290# . $ #
291#########
292
293 ######
294 #####. #
295 # #..## #
296 # $.. #
297 # # .# ##
298### ##$# #
299# $ $$ #
300# #$# # #
301#@ #######
302#####
303
304 ######
305 # ...#
306####....#
307# ###$ ###
308# $ $ $$ #
309#@ $ $ #
310# #### #
311#### #####
312
313 #########
314 # ## #
315 # $ #
316 #$ ### $#
317 # #...# #
318## #...# ##
319# $ $ $ #
320# # @ #
321###########
322
323 #######
324 ### #
325## # # #
326# #.$$$ #
327# #.*# ###
328# ..# #
329###..$ ##
330 #.# $ #
331 ## # #@#
332 # $ $ #
333 # ###
334 ######
335
336 ##########
337## #
338#@ $$$ $ #
339## $ $ $ #
340 ## #### ##
341 # $ ##
342### ##$ $ #
343# # #
344# ######
345# ##
346#.....#
347#.....#
348#######
349
350########
351# #
352# @ $# #
353## # #
354# $#.# #
355# .*.$#
356## #.# #
357 # #. ##
358## $.# #
359# # $ #
360# $ ###
361# ####
362####
363
364 ####
365 #@ #
366 ##### #
367#### #
368# .### ##
369# # # ##
370# # $ $#. #
371# # * # #
372# .#$ $ # #
373## # # #
374 # ###. #
375 # ####
376 #######
377
378#####
379# ##
380# $ #
381# $ @#
382###. #
383 #.##
384 #. #
385###. #
386# $ #
387# $ #
388## ##
389 ####
390
391####
392# #####
393# # #
394# . # #
395##$# .#
396 # #$# #
397##. . #
398# ## #
399# # *#
400# $ $ #
401# $#* @#
402# #.###
403######
404
405 ###
406 #.######
407 ###.$ # #
408 #... #$ #
409 #.## $ #
410##.$ $## ##
411#.$ # ## #
412#.#$ #
413#.$ #$ $#
414#. $## @ #
415#.$ $ #
416#. #######
417####
418
419 ####
420 ### ##
421 ## ##
422 # # ..#
423## $#*#$.#
424# $ # $.#
425# $ @ $.#
426# $ # $.#
427##$$#*#$.#
428 #. # ..#
429 ##. ##
430 ### ##
431 ####
432
433#########
434# #
435# # ### #
436# $$ # #
437#@$ # #
438## ## # #
439# $ $ #
440# $## # #
441# #$# #
442#...# #
443#.#.#$###
444#... #
445#######
446
447########
448# .#
449# #$#..##
450# $...#
451## ##.$.#
452 # ## ##
453 #$## #
454## #$#
455# # #
456# $ ####
457# $ $ @#
458# ### #
459#### #####
460
461####
462# ####
463# $ #
464# #.# #
465# # # #
466#.$.$.#
467# # # #
468# #.# #
469# $$ #
470## @ #
471 # ###
472 ####
473
474###### ####
475# ### #
476# $$ ## #
477# # $ #
478## ## $# #
479 # #... ##
480 # ...#$##
481 # #...# #
482## # ###@ #
483# $ $ $ #
484# #$#### #
485# # ####
486#####
487
488##########
489#..$ $ *.#
490#.* $ $..#
491##.$ $ *##
492 #* $ $.#
493 #.$ $ .#
494 #. $ $.#
495 #.$@$ *#
496##* $ $.##
497#..$ $ *.#
498#.* $ $..#
499##########
500
501 #####
502 # #
503 #$ #
504 ### $##
505 # $ $ #
506### # ## # ######
507# # ## ##### ..#
508# $ $ ..#
509##### ### #@## ..#
510 # #########
511 #######
512
513############
514#.. # ###
515#.. # $ $ #
516#.. #$#### #
517#.. @ ## #
518#.. # # $ ##
519###### ##$ $ #
520 # $ $ $ $ #
521 # # #
522 ############
523
524 ########
525 # @#
526 # $#$ ##
527 # $ $#
528 ##$ $ #
529######### $ # ###
530#.... ## $ $ #
531##... $ $ #
532#.... ##########
533########
534
535 ########
536 # ....#
537############ ....#
538# # $ $ ....#
539# $$$#$ $ # ....#
540# $ $ # ....#
541# $$ #$ $ $########
542# $ # #
543## #########
544# # ##
545# $ ##
546# $$#$$ @#
547# # ##
548###########
549
550 #####
551 # #####
552 # #$## #
553 # $ #
554######### ### #
555#.... ## $ $###
556#.... $ $$ ##
557#.... ##$ $ @#
558######### $ ##
559 # $ $ #
560 ### ## #
561 # #
562 ######
563
564###### ###
565#.. # ##@##
566#.. ### #
567#.. $$ #
568#.. # # $ #
569#..### # $ #
570#### $ #$ #
571 # $# $ #
572 # $ $ #
573 # ## #
574 #########
575
576 #####
577 ####### ##
578## # @## $$ #
579# $ #
580# $ ### #
581### #####$###
582# $ ### ..#
583# $ $ $ ...#
584# ###...#
585# $$ # #...#
586# ### #####
587####
588
589 ####
590 # ###########
591 # $ $ $ #
592 # $# $ # $ #
593 # $ $ # #
594### $# # #### #
595#@#$ $ $ ## #
596# $ #$# # #
597# $ $ $ $ #
598##### #########
599 # #
600 # #
601 #......#
602 #......#
603 #......#
604 ########
605
606 #######
607 # ...#
608 ##### ...#
609 # . .#
610 # ## ...#
611 ## ## ...#
612 ### ########
613 # $$$ ##
614 ##### $ $ #####
615## #$ $ # #
616#@ $ $ $ $ #
617###### $$ $ #####
618 # #
619 ########
620
621 ### #############
622##@#### # #
623# $$ $$ $ $ ...#
624# $$$# $ #...#
625# $ # $$ $$ #...#
626### # $ #...#
627# # $ $ $ #...#
628# ###### ###...#
629## # # $ $ #...#
630# ## # $$ $ $##..#
631# ..# # $ #.#
632# ..# # $$$ $$$ #.#
633##### # # #.#
634 # ######### #.#
635 # #.#
636 ###############
637
638 ####
639 #### # #
640 ### @###$ #
641 ## $ #
642 ## $ $$## ##
643 # #$## #
644 # # $ $$ # ###
645 # $ # # $ #####
646#### # $$ # #
647#### ## $ #
648#. ### ########
649#.. ..# ####
650#...#.#
651#.....#
652#######
653
654################
655# #
656# # ###### #
657# # $ $ $ $# #
658# # $@$ ## ##
659# # $ $ $###...#
660# # $ $ ##...#
661# ###$$$ $ ##...#
662# # ## ##...#
663##### ## ##...#
664 ##### ###
665 # #
666 #######
667
668 #########
669 ## ## ######
670### # # ###
671# $ #$ # # ... #
672# # $#@$## # #.#. #
673# # #$ # . . #
674# $ $ # # #.#. #
675# ## ##$ $ . . #
676# $ # # #$#.#. #
677## $ $ $ $... #
678 #$ ###### ## #
679 # # ##########
680 ####
681
682 #######
683 ####### #
684 # # $@$ #
685 #$$ # #########
686 # ###......## #
687 # $......## # #
688 # ###...... #
689## #### ### #$##
690# #$ # $ # #
691# $ $$$ # $## #
692# $ $ ###$$ # #
693##### $ # #
694 ### ### # #
695 # # #
696 ######## #
697 ####
698
699 ########
700 # # #
701 # $ #
702 ### #$ ####
703 # $ ##$ #
704 # # @ $ # $#
705 # # $ ####
706 ## ####$## #
707 # $#.....# # #
708 # $..**. $# ###
709## #.....# #
710# ### #######
711# $$ # #
712# # #
713###### #
714 #####
715
716#####
717# ##
718# # ####
719# $ #### #
720# $$ $ $#
721###@ #$ ##
722 # ## $ $ ##
723 # $ ## ## .#
724 # #$##$ #.#
725 ### $..##.#
726 # #.*...#
727 # $$ #.....#
728 # #########
729 # #
730 ####
731
732 ##########
733 #.. # #
734 #.. #
735 #.. # ####
736 ####### # ##
737 # #
738 # # ## # #
739#### ## #### ##
740# $ ##### # #
741# # $ $ # $ #
742# @$ $ # ##
743#### ## #######
744 # #
745 ######
746
747 ###########
748 # . # #
749 # #. @ #
750 ##### ##..# ####
751## # ..### ###
752# $ #... $ # $ #
753# .. ## ## ## #
754####$##$# $ # # #
755 ## # #$ $$ # #
756 # $ # # # $## #
757 # #
758 # ########### #
759 #### ####
760
761 ######
762 # @####
763##### $ #
764# ## ####
765# $ # ## #
766# $ # ##### #
767## $ $ # #
768## $ $ ### # #
769## # $ # # #
770## # #$# # #
771## ### # # ######
772# $ #### # #....#
773# $ $ ..#.#
774####$ $# $ ....#
775# # ## ....#
776###################
777
778 ##########
779##### ####
780# # $ #@ #
781# #######$#### ###
782# # ## # #$ ..#
783# # $ # # #.#
784# # $ # #$ ..#
785# # ### ## #.#
786# ### # # #$ ..#
787# # # #### #.#
788# #$ $ $ #$ ..#
789# $ # $ $ # #.#
790#### $### #$ ..#
791 # $$ ###....#
792 # ## ######
793 ########
794
795#########
796# #
797# ####
798## #### # #
799## #@## #
800# $$$ $ $$#
801# # ## $ #
802# # ## $ ####
803#### $$$ $# #
804 # ## ....#
805 # # # #.. .#
806 # # # ##...#
807 ##### $ #...#
808 ## #####
809 #####
810
811###### ####
812# ####### #####
813# $# # $ # #
814# $ $ $ # $ $ #
815##$ $ # @# $ #
816# $ ########### ##
817# # #.......# $#
818# ## # ......# #
819# # $........$ #
820# # $ #.... ..# #
821# $ $####$#### $#
822# $ ### $ $ ##
823# $ $ $ $ #
824## ###### $ ##### #
825# # #
826###################
827
828 #######
829 # # ####
830##### $#$ # ##
831#.. # # # #
832#.. # $#$ # $####
833#. # #$ # #
834#.. $# # $ #
835#..@# #$ #$ # #
836#.. # $# $# #
837#.. # #$$#$ # ##
838#.. # $# # $#$ #
839#.. # # # # #
840##. #### ##### #
841 #### #### #####
842
843###############
844#.......... .####
845#..........$$.# #
846###########$ # ##
847# $ $ $ #
848## #### # $ # #
849# # ## # ##
850# $# # ## ### ##
851# $ #$### ### ##
852### $ # # ### ##
853### $ ## # # ##
854 # $ # $ $ $ #
855 # $ $#$$$ # #
856 # # $ #####
857 # @## # # #
858 ##############
859
860####
861# ##############
862# # ..#......#
863# # # ##### ...#
864##$# ........#
865# ##$###### ####
866# $ # ######@ #
867##$ # $ ###### #
868# $ #$$$## #
869# # #$#$###
870# #### #$$$$$ #
871# # $ # #
872# # ## ###
873# ######$###### $ #
874# # # #
875########## #####
876
877 #######
878 # # #####
879## # #...###
880# $# #... #
881# $ #$$ ... #
882# $# #... .#
883# # $########
884##$ $ $ #
885## # $$ # #
886 ###### ##$$@#
887 # ##
888 ########
889
890 #################
891 #... # # ##
892##..... $## # #$ #
893#......# $ # #
894#......# # # # #
895######### $ $ $ #
896 # #$##$ ##$##
897 ## $ # $ #
898 # ## ### # ##$ #
899 # $ $$ $ $ #
900 # $ $##$ ######
901 ####### @ ##
902 ######
903
904 #####
905 ##### #
906 ## $ $ ####
907##### $ $ $ ##.#
908# $$ ##..#
909# ###### ###.. #
910## # # #... #
911# $ # #... #
912#@ #$ ## ####...#
913#### $ $$ ##..#
914 ## $ $ $...#
915 # $$ $ # .#
916 # $ $ ####
917 ###### #
918 #####
919
920#####
921# ##
922# $ #########
923## # # ######
924## # $#$#@ # #
925# # $ # $ #
926# ### ######### ##
927# ## ..*..... # ##
928## ## *.*..*.* # ##
929# $########## ##$ #
930# $ $ $ $ #
931# # # # # #
932###################
933
934 ###########
935 # # #
936##### # $ $ #
937# ##### $## # ##
938# $ ## # ## $ #
939# $ @$$ # ##$$$ #
940## ### # ## #
941## # ### #####$#
942## # $ #....#
943# ### ## $ #....##
944# $ $ # #..$. #
945# ## $ # ##.... #
946##### ######...##
947 ##### #####
948
949 ####
950 # #########
951 ## ## # #
952 # $# $@$ ####
953 #$ $ # $ $# ##
954## $## #$ $ #
955# # # # $$$ #
956# $ $ $## ####
957# $ $ #$# # #
958## ### ###$ #
959 # #.... #
960 ####......####
961 #....####
962 #...##
963 #...#
964 #####
965
966 ####
967 ##### #
968 ## $#
969## $ ## ###
970#@$ $ # $ #
971#### ## $#
972 #....#$ $ #
973 #....# $#
974 #.... $$ ##
975 #... # $ #
976 ######$ $ #
977 # ###
978 #$ ###
979 # #
980 ####
981
982############
983## ## #
984## $ $ #
985#### ## $$ #
986# $ # #
987# $$$ # ####
988# # # $ ##
989# # # $ #
990# $# $# #
991# ..# ####
992####.. $ #@#
993#.....# $# #
994##....# $ #
995###..## #
996############
997
998 #########
999 #.... ##
1000 #.#.# $ ##
1001##....# # @##
1002# ....# # ##
1003# #$ ##$ #
1004## ### $ #
1005 #$ $ $ $# #
1006 # # $ $ ## #
1007 # ### ## #
1008 # ## ## ##
1009 # $ # $ #
1010 ###$ $ ###
1011 # #####
1012 ####
1013
1014############ ######
1015# # # ###....#
1016# $$# @ .....#
1017# # ### # ....#
1018## ## ### # ....#
1019 # $ $ # # ####
1020 # $ $## # #
1021#### # #### # ## #
1022# # #$ ## # #
1023# $ $ # ## # ##
1024# # $ $ # # #
1025# $ ## ## # #####
1026# $$ $$ #
1027## ## ### $ #
1028 # # # #
1029 ###### ######
1030
1031 #####
1032##### ###### #
1033# #### $ $ $ #
1034# $ ## ## ## ##
1035# $ $ $ $ #
1036### $ ## ## ##
1037 # ##### #####$$ #
1038 ##$##### @## #
1039 # $ ###$### $ ##
1040 # $ # ### ###
1041 # $$ $ # $$ #
1042 # # ## #
1043 #######.. .####
1044 #.........#
1045 #.........#
1046 ###########
1047
1048###########
1049#...... #########
1050#...... # ## #
1051#..### $ $ #
1052#... $ $ # ## #
1053#...#$##### # #
1054### # #$ #$ #
1055 # $$ $ $ $## #
1056 # $ #$#$ ##$ #
1057 ### ## # ## #
1058 # $ $ ## ######
1059 # $ $ #
1060 ## # # #
1061 #####@#####
1062 ###
1063
1064 ####
1065####### @#
1066# $ #
1067# $## $#
1068##$#...# #
1069 # $... #
1070 # #. .# ##
1071 # # #$ #
1072 #$ $ #
1073 # #######
1074 ####
1075
1076 ######
1077 #############....#
1078## ## ##....#
1079# $$## $ @##....#
1080# $$ $# ....#
1081# $ ## $$ # # ...#
1082# $ ## $ # ....#
1083## ##### ### ##.###
1084## $ $ ## . #
1085# $### # ##### ###
1086# $ # #
1087# $ #$ $ $### #
1088# $$$# $ # ####
1089# # $$ #
1090###### ###
1091 #####
1092
1093 ############
1094 # ##
1095 # # #$$ $ #
1096 #$ #$# ## @#
1097 ## ## # $ # ##
1098 # $ #$ # #
1099 # # $ # #
1100 ## $ $ ## #
1101 # # ## $ #
1102 # ## $$# #
1103######$$ # #
1104#....# ########
1105#.#... ##
1106#.... #
1107#.... #
1108#########
1109
1110 #####
1111 ## ##
1112 ## #
1113 ## $$ #
1114 ## $$ $ #
1115 # $ $ #
1116#### # $$ #####
1117# ######## ## #
1118#. $$$@#
1119#.# ####### ## ##
1120#.# #######. #$ $##
1121#........... # #
1122############## $ #
1123 ## ##
1124 ####
1125
1126 ########
1127 #### ######
1128 # ## $ $ @#
1129 # ## ##$#$ $ $##
1130### ......# $$ ##
1131# ......# # #
1132# # ......#$ $ #
1133# #$...... $$# $ #
1134# ### ###$ $ ##
1135### $ $ $ $ #
1136 # $ $ $ $ #
1137 ###### ######
1138 #####
1139
1140 #######
1141 ##### # ####
1142 # # $ #
1143 #### #$$ ## ## #
1144## # # ## ###
1145# ### $#$ $ $ #
1146#... # ## # #
1147#...# @ # ### ##
1148#...# ### $ $ #
1149######## ## # #
1150 #########
1151
1152 #####
1153 # #
1154 # # #######
1155 # $@######
1156 # $ ##$ ### #
1157 # #### $ $ #
1158 # ##### # #$ ####
1159## #### ##$ #
1160# $# $ # ## ## #
1161# # #...# #
1162###### ### ... #
1163 #### # #...# #
1164 # ### # #
1165 # #
1166 #########
1167
1168##### ####
1169#...# # ####
1170#...### $ #
1171#....## $ $###
1172##....## $ #
1173###... ## $ $ #
1174# ## # $ #
1175# ## # ### ####
1176# $ # #$ $ #
1177# $ @ $ $ #
1178# # $ $$ $ ###
1179# ###### ###
1180# ## ####
1181###
1182
1183##########
1184# ####
1185# ###### # ##
1186# # $ $ $ $ #
1187# #$ #
1188###$ $$# ###
1189 # ## # $##
1190 ##$# $ @#
1191 # $ $ ###
1192 # # $ #
1193 # ## # #
1194 ## ##### #
1195 # #
1196 #.......###
1197 #.......#
1198 #########
1199
1200 ####
1201 ######### ##
1202## $ $ #####
1203# ## ## ##...#
1204# #$$ $ $$#$##...#
1205# # @ # ...#
1206# $# ###$$ ...#
1207# $ $$ $ ##....#
1208###$ #######
1209 # #######
1210 ####
1211
1212 #########
1213 #*.*#*.*#
1214 #.*.*.*.#
1215 #*.*.*.*#
1216 #.*.*.*.#
1217 #*.*.*.*#
1218 ### ###
1219 # #
1220###### ######
1221# #
1222# $ $ $ $ $ #
1223## $ $ $ $ ##
1224 #$ $ $ $ $#
1225 # $@$ #
1226 # ##### #
1227 #### ####
1228
1229 ####
1230 # ##
1231 # ##
1232 # $$ ##
1233 ###$ $ ##
1234 #### $ #
1235### # ##### #
1236# # #....$ #
1237# # $ ....# #
1238# $ # #.*..# #
1239### #### ### #
1240 #### @$ ##$##
1241 ### $ #
1242 # ## #
1243 #########
1244
1245 ############
1246 ##.. # #
1247 ##..* $ $ #
1248 ##..*.# # # $##
1249 #..*.# # # $ #
1250####...# # # #
1251# ## # #
1252# @$ $ ### # ##
1253# $ $ # # #
1254###$$ # # # # #
1255 # $ # # #####
1256 # $# ##### #
1257 #$ # # # #
1258 # ### ## #
1259 # # # ##
1260 #### ######
1261
1262###################
1263# ### # #
1264# ##$ $ # $$ # $ #
1265#.# . .$ # #..# #.#
1266#.####.# # # ## # #
1267# # # # # # #
1268# $ # # ### # ## #
1269# # # # #.$ # # #
1270# $$.# # ## # ## #
1271#$ # # # # ## # #
1272# .# # ## # # ## #
1273# # # # # ## #
1274## ## # # # # $.#
1275### ### $.# $.# $.#
1276####### # # @#
1277 #############
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 95a7757e53..cf5ceccac5 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -16,6 +16,7 @@ m3u,viewers/iriverify,-
16mid,viewers/midiplay,7 16mid,viewers/midiplay,7
17rmi,viewers/midiplay,7 17rmi,viewers/midiplay,7
18rsp,viewers/searchengine,8 18rsp,viewers/searchengine,8
19sok,rocks/sokoban,1
19pgn,rocks/chessbox,1 20pgn,rocks/chessbox,1
20ss,rocks/sudoku,1 21ss,rocks/sudoku,1
21wav,viewers/wav2wv,- 22wav,viewers/wav2wv,-
diff --git a/manual/plugins/images/ss-sokoban-112x64x1.png b/manual/plugins/images/ss-sokoban-112x64x1.png
index c0fa584d0c..c0bb499ded 100644
--- a/manual/plugins/images/ss-sokoban-112x64x1.png
+++ b/manual/plugins/images/ss-sokoban-112x64x1.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-128x128x16.png b/manual/plugins/images/ss-sokoban-128x128x16.png
index fc45da89c9..2655b6c426 100644
--- a/manual/plugins/images/ss-sokoban-128x128x16.png
+++ b/manual/plugins/images/ss-sokoban-128x128x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-138x110x2.png b/manual/plugins/images/ss-sokoban-138x110x2.png
index a824ab0561..f6e077eee5 100644
--- a/manual/plugins/images/ss-sokoban-138x110x2.png
+++ b/manual/plugins/images/ss-sokoban-138x110x2.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-160x128x16.png b/manual/plugins/images/ss-sokoban-160x128x16.png
index b267cf70b6..53761aca5b 100644
--- a/manual/plugins/images/ss-sokoban-160x128x16.png
+++ b/manual/plugins/images/ss-sokoban-160x128x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-160x128x2.png b/manual/plugins/images/ss-sokoban-160x128x2.png
index 8cd23bdadb..6f3833da73 100644
--- a/manual/plugins/images/ss-sokoban-160x128x2.png
+++ b/manual/plugins/images/ss-sokoban-160x128x2.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-176x132x16.png b/manual/plugins/images/ss-sokoban-176x132x16.png
index e176a81059..0602220414 100644
--- a/manual/plugins/images/ss-sokoban-176x132x16.png
+++ b/manual/plugins/images/ss-sokoban-176x132x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-176x220x16.png b/manual/plugins/images/ss-sokoban-176x220x16.png
index 157499dbec..7251d244c5 100644
--- a/manual/plugins/images/ss-sokoban-176x220x16.png
+++ b/manual/plugins/images/ss-sokoban-176x220x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-220x176x16.png b/manual/plugins/images/ss-sokoban-220x176x16.png
index 554fcf7798..afef9c6806 100644
--- a/manual/plugins/images/ss-sokoban-220x176x16.png
+++ b/manual/plugins/images/ss-sokoban-220x176x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-240x320x16.png b/manual/plugins/images/ss-sokoban-240x320x16.png
index 5abc7d04e9..aded2fb1da 100644
--- a/manual/plugins/images/ss-sokoban-240x320x16.png
+++ b/manual/plugins/images/ss-sokoban-240x320x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-sokoban-320x240x16.png b/manual/plugins/images/ss-sokoban-320x240x16.png
index 816e5de680..7f6fc472fe 100644
--- a/manual/plugins/images/ss-sokoban-320x240x16.png
+++ b/manual/plugins/images/ss-sokoban-320x240x16.png
Binary files differ
diff --git a/manual/plugins/sokoban.tex b/manual/plugins/sokoban.tex
index 755c4e8295..246eceda51 100644
--- a/manual/plugins/sokoban.tex
+++ b/manual/plugins/sokoban.tex
@@ -5,44 +5,75 @@ The object of the game is to push boxes into their correct position in a
5crowded warehouse with a minimal number of pushes and moves. The boxes 5crowded warehouse with a minimal number of pushes and moves. The boxes
6can only be pushed, never pulled, and only one can be pushed at a time. 6can only be pushed, never pulled, and only one can be pushed at a time.
7 7
8Sokoban may be used as a viewer for viewing saved solutions and playing
9external level sets with the \fname{.sok} extension. Level sets should be in
10the standard Sokoban text format or RLE (Run Length Encoded). For more
11information about the level format, see
12\url{http://sokobano.de/wiki/index.php?title=Level_format}
13
8\begin{table} 14\begin{table}
9\begin{btnmap}{}{} 15\begin{btnmap}{}{}
10\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD} 16\opt{RECORDER_PAD,ARCHOS_AV300_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,SANSA_E200_PAD}
11 {\ButtonUp, \ButtonDown,} 17 {\ButtonUp, \ButtonDown,}
12\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu, \ButtonPlay,} 18\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu, \ButtonPlay,}
13\opt{IRIVER_H10_PAD}{\ButtonScrollUp, \ButtonScrollDown,} 19\opt{IRIVER_H10_PAD}{\ButtonScrollUp, \ButtonScrollDown,}
14 \ButtonLeft, \ButtonRight 20 \ButtonLeft, \ButtonRight
15 & Move the ``sokoban'' up, down, left or right\\ 21 & Move the ``sokoban'' up, down, left or right\\
16\opt{RECORDER_PAD}{\ButtonFOne} 22\opt{RECORDER_PAD,ARCHOS_AV300_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
17\opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft} 23\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonMenu}
24\opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,GIGABEAT_PAD,SANSA_E200_PAD}{\ButtonPower}
25 & Menu \\
26\opt{RECORDER_PAD,ARCHOS_AV300_PAD}{\ButtonOn}
27\opt{ONDIO_PAD}{\ButtonMenu}
18\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonRec} 28\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonRec}
19\opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonSelect+\ButtonLeft} 29\opt{IPOD_4G_PAD,IPOD_3G_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,SANSA_E200_PAD}{\ButtonSelect}
20\opt{IAUDIO_X5_PAD}{\ButtonPlay+\ButtonDown} 30\opt{IRIVER_H10_PAD}{\ButtonRew}
21\opt{IRIVER_H10_PAD}{\ButtonPlay+\ButtonScrollDown} 31 & Undo last movement \\
22 & Back to previous level \\ 32\opt{RECORDER_PAD,ARCHOS_AV300_PAD}{\ButtonPlay}
23\opt{RECORDER_PAD}{\ButtonFTwo} 33\opt{ONDIO_PAD}{\ButtonMenu+\ButtonDown}
24\opt{ONDIO_PAD}{\ButtonMenu+\ButtonRight} 34\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}
25\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonSelect}
26\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonPlay} 35\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonPlay}
27\opt{IAUDIO_X5_PAD,SANSA_E200_PAD}{\ButtonRec} 36\opt{IAUDIO_X5_PAD}{n/a}
28\opt{IRIVER_H10_PAD}{\ButtonFF} 37\opt{IRIVER_H10_PAD}{\ButtonFF}
29 & Restart level \\ 38\opt{GIGABEAT_PAD}{\ButtonA}
30\opt{RECORDER_PAD}{\ButtonFThree} 39\opt{SANSA_E200_PAD}{\ButtonRec}
40 & Redo previously undone move \\
41\opt{RECORDER_PAD,ARCHOS_AV300_PAD}{\ButtonFOne}
42\opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft}
43\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn+\ButtonDown}
44\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonLeft}
45\opt{IAUDIO_X5_PAD}{\ButtonRec}
46\opt{IRIVER_H10_PAD}{\ButtonPlay+\ButtonScrollDown}
47\opt{GIGABEAT_PAD}{\ButtonVolDown}
48\opt{SANSA_E200_PAD}{\ButtonSelect+\ButtonDown}
49 & Back to previous level \\
50\opt{RECORDER_PAD,ARCHOS_AV300_PAD}{\ButtonFTwo}
31\opt{ONDIO_PAD}{\ButtonMenu+\ButtonUp} 51\opt{ONDIO_PAD}{\ButtonMenu+\ButtonUp}
32\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} 52\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn}
33\opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonSelect+\ButtonRight} 53\opt{IPOD_4G_PAD,IPOD_3G_PAD,IAUDIO_X5_PAD}{n/a}
34\opt{IAUDIO_X5_PAD}{\ButtonPlay+\ButtonUp} 54\opt{IRIVER_H10_PAD}{\ButtonPlay+\ButtonRight}
55\opt{GIGABEAT_PAD}{\ButtonMenu}
56\opt{SANSA_E200_PAD}{\ButtonSelect+\ButtonRight}
57 & Restart level \\
58\opt{RECORDER_PAD,ARCHOS_AV300_PAD}{\ButtonFThree}
59\opt{ONDIO_PAD}{\ButtonMenu+\ButtonRight}
60\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn+\ButtonUp}
61\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonRight}
62\opt{IAUDIO_X5_PAD}{\ButtonPlay}
35\opt{IRIVER_H10_PAD}{\ButtonPlay+\ButtonScrollUp} 63\opt{IRIVER_H10_PAD}{\ButtonPlay+\ButtonScrollUp}
64\opt{GIGABEAT_PAD}{\ButtonVolUp}
65\opt{SANSA_E200_PAD}{\ButtonSelect+\ButtonUp}
36 & Go to next level \\ 66 & Go to next level \\
37\opt{RECORDER_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn} 67\opt{RECORDER_PAD,ARCHOS_AV300_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,SANSA_E200_PAD}
38\opt{ONDIO_PAD}{\ButtonMenu} 68 {\ButtonUp/\ButtonDown,}
39\opt{IPOD_4G_PAD,IPOD_3G_PAD,IAUDIO_X5_PAD}{\ButtonSelect} 69\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu/\ButtonPlay,}
40\opt{IRIVER_H10_PAD}{\ButtonRew} 70\opt{IRIVER_H10_PAD}{\ButtonScrollUp/\ButtonScrollDown,}
41\opt{SANSA_E200_PAD}{\ButtonUp} 71 & Increase/decrease solution playback speed
42 & Undo last movement \\
43\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
44\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonMenu}
45\opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonPower}
46 & Exit sokoban \\
47\end{btnmap} 72\end{btnmap}
48\end{table} 73\end{table}
74
75Some places where can you can find level sets:
76\begin{itemize}
77\item \url{http://www.sourcecode.se/sokoban/levels.php}
78\item \url{http://sokobano.de/en/levels.php}
79\end{itemize}
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 8c78b82170..404342b68e 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -329,7 +329,7 @@ STOP
329 `cp $ROOT/apps/tagnavi.config .rockbox/`; 329 `cp $ROOT/apps/tagnavi.config .rockbox/`;
330 330
331 if($bitmap) { 331 if($bitmap) {
332 `cp $ROOT/apps/plugins/sokoban.levels .rockbox/rocks/`; # sokoban levels 332 `cp $ROOT/apps/plugins/sokobanlevels.sok .rockbox/rocks/`; # sokoban levels
333 `cp $ROOT/apps/plugins/snake2.levels .rockbox/rocks/`; # snake2 levels 333 `cp $ROOT/apps/plugins/snake2.levels .rockbox/rocks/`; # snake2 levels
334 } 334 }
335 335