summaryrefslogtreecommitdiff
path: root/apps/plugins/sudoku
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-04-01 18:38:34 +0000
committerDave Chapman <dave@dchapman.com>2006-04-01 18:38:34 +0000
commit0f619c65bab2465ffa84eb64cc62fe56506121f8 (patch)
treef8a9387673b1f6f7764620cbf10978e3b05d26f4 /apps/plugins/sudoku
parent9fad701934a784e110edbff5556e21efe9c059d9 (diff)
downloadrockbox-0f619c65bab2465ffa84eb64cc62fe56506121f8.tar.gz
rockbox-0f619c65bab2465ffa84eb64cc62fe56506121f8.zip
Move Sudoku plugin into its own subdirectory and add a random game generator.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9407 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/sudoku')
-rw-r--r--apps/plugins/sudoku/Makefile117
-rw-r--r--apps/plugins/sudoku/SOURCES3
-rw-r--r--apps/plugins/sudoku/generator.c1097
-rw-r--r--apps/plugins/sudoku/generator.h1
-rw-r--r--apps/plugins/sudoku/sudoku.c1124
-rw-r--r--apps/plugins/sudoku/sudoku.h104
-rw-r--r--apps/plugins/sudoku/templates.c2877
-rw-r--r--apps/plugins/sudoku/templates.h8
8 files changed, 5331 insertions, 0 deletions
diff --git a/apps/plugins/sudoku/Makefile b/apps/plugins/sudoku/Makefile
new file mode 100644
index 0000000000..9b9c1c6b2e
--- /dev/null
+++ b/apps/plugins/sudoku/Makefile
@@ -0,0 +1,117 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
11 -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR)
12CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
13 -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN
14
15ifdef APPEXTRA
16 INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
17endif
18
19LINKFILE := $(OBJDIR)/link.lds
20DEPFILE = $(OBJDIR)/dep-sudoku
21
22# This sets up 'SRC' based on the files mentioned in SOURCES
23include $(TOOLSDIR)/makesrc.inc
24
25SOURCES = $(SRC)
26OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
27DIRS = .
28
29ifndef SIMVER
30 LDS := ../plugin.lds
31 OUTPUT = $(OUTDIR)/sudoku.rock
32else ## simulators
33 OUTPUT = $(OUTDIR)/sudoku.rock
34endif
35
36all: $(OUTPUT)
37
38ifndef SIMVER
39$(OBJDIR)/sudoku.elf: $(OBJS) $(LINKFILE) $(BITMAPLIBS)
40 @echo "LD "`basename $@`
41 @$(CC) $(GCCOPTS) -O -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \
42 $(LINKBITMAPS) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/sudoku.map
43
44$(OUTPUT): $(OBJDIR)/sudoku.elf
45 @echo "OBJCOPY "`basename $@`
46 @$(OC) -O binary $< $@
47else
48
49ifeq ($(SIMVER), x11)
50###################################################
51# This is the X11 simulator version
52
53$(OUTPUT): $(OBJS)
54 @echo "LD $<"
55 @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin $(LINKBITMAPS) -o $@
56ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
57# 'x' must be kept or you'll have "Win32 error 5"
58# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
59# #define ERROR_ACCESS_DENIED 5L
60else
61 @chmod -x $@
62endif
63
64else # end of x11-simulator
65ifeq ($(SIMVER), sdl)
66###################################################
67# This is the SDL simulator version
68
69$(OUTPUT): $(OBJS)
70 @echo "LD $<"
71 @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin $(LINKBITMAPS) -o $@
72ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
73# 'x' must be kept or you'll have "Win32 error 5"
74# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
75# #define ERROR_ACCESS_DENIED 5L
76else
77 @chmod -x $@
78endif
79
80else # end of sdl-simulator
81###################################################
82# This is the win32 simulator version
83DLLTOOLFLAGS = --export-all
84DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
85
86$(OUTPUT): $(OBJS)
87 @echo "DLL "`basename $@`
88 @$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
89 @$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
90 $(BUILDDIR)/libplugin.a $(BITMAPLIBS) -o $@
91ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
92# 'x' must be kept or you'll have "Win32 error 5"
93# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
94# #define ERROR_ACCESS_DENIED 5L
95else
96 @chmod -x $@
97endif
98endif # end of win32-simulator
99endif
100endif # end of simulator section
101
102
103include $(TOOLSDIR)/make.inc
104
105# MEMORYSIZE should be passed on to this makefile with the chosen memory size
106# given in number of MB
107$(LINKFILE): $(LDS)
108 @echo "build "`basename $@`
109 @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) \
110 $(DEFINES) -E -P - >$@
111
112clean:
113 @echo "cleaning sudoku"
114 @rm -rf $(OBJDIR)/sudoku
115 @rm -f $(OBJDIR)/sudoku.* $(DEPFILE)
116
117-include $(DEPFILE)
diff --git a/apps/plugins/sudoku/SOURCES b/apps/plugins/sudoku/SOURCES
new file mode 100644
index 0000000000..7cce555c93
--- /dev/null
+++ b/apps/plugins/sudoku/SOURCES
@@ -0,0 +1,3 @@
1sudoku.c
2generator.c
3templates.c
diff --git a/apps/plugins/sudoku/generator.c b/apps/plugins/sudoku/generator.c
new file mode 100644
index 0000000000..d43e970ab8
--- /dev/null
+++ b/apps/plugins/sudoku/generator.c
@@ -0,0 +1,1097 @@
1/* sudoku.c - sudoku game
2 *
3 * Writing a fun Su-Do-Ku game has turned out to be a difficult exercise.
4 * The biggest difficulty is keeping the game fun - and this means allowing
5 * the user to make mistakes. The game is not much fun if it prevents the
6 * user from making moves, or if it informs them of an incorrect move.
7 * With movement constraints, the 'game' is little more than an automated
8 * solver (and no fun at all).
9 *
10 * Another challenge is generating good puzzles that are entertaining to
11 * solve. It is certainly true that there is an art to creating good
12 * Su-Do-Ku puzzles, and that good hand generated puzzles are more
13 * entertaining than many computer generated puzzles - I just hope that
14 * the algorithm implemented here provides fun puzzles. It is an area
15 * that needs work. The puzzle classification is very simple, and could
16 * also do with work. Finally, understanding the automatically generated
17 * hints is sometimes more work than solving the puzzle - a better, and
18 * more human friendly, mechanism is needed.
19 *
20 * Comments, suggestions, and contributions are always welcome - send email
21 * to: mike 'at' laurasia.com.au. Note that this code assumes a single
22 * threaded process, makes extensive use of global variables, and has
23 * not been written to be reused in other applications. The code makes no
24 * use of dynamic memory allocation, and hence, requires no heap. It should
25 * also run with minimal stack space.
26 *
27 * This code and accompanying files have been placed into the public domain
28 * by Michael Kennett, July 2005. It is provided without any warranty
29 * whatsoever, and in no event shall Michael Kennett be liable for
30 * any damages of any kind, however caused, arising from this software.
31 */
32
33#include "plugin.h"
34
35#include "sudoku.h"
36#include "templates.h"
37
38extern struct plugin_api* rb;
39
40#define assert(x)
41
42/* Common state encoding in a 32-bit integer:
43 * bits 0-6 index
44 * 7-15 state [bit high signals digits not possible]
45 * 16-19 digit
46 * 20 fixed [set if digit initially fixed]
47 * 21 choice [set if solver chose this digit]
48 * 22 ignore [set if ignored by reapply()]
49 * 23 unused
50 * 24-26 hint
51 * 27-31 unused
52 */
53#define INDEX_MASK 0x0000007f
54#define GET_INDEX(val) (INDEX_MASK&(val))
55#define SET_INDEX(val) (val)
56
57#define STATE_MASK 0x0000ff80
58#define STATE_SHIFT (7-1) /* digits 1..9 */
59#define DIGIT_STATE(digit) (1<<(STATE_SHIFT+(digit)))
60
61#define DIGIT_MASK 0x000f0000
62#define DIGIT_SHIFT 16
63#define GET_DIGIT(val) (((val)&DIGIT_MASK)>>(DIGIT_SHIFT))
64#define SET_DIGIT(val) ((val)<<(DIGIT_SHIFT))
65
66#define FIXED 0x00100000
67#define CHOICE 0x00200000
68#define IGNORED 0x00400000
69
70/* Hint codes (c.f. singles(), pairs(), findmoves()) */
71#define HINT_ROW 0x01000000
72#define HINT_COLUMN 0x02000000
73#define HINT_BLOCK 0x04000000
74
75/* For a general board it may be necessary to do backtracking (i.e. to
76 * rewind the board to an earlier state), and make choices during the
77 * solution process. This can be implemented naturally using recursion,
78 * but it is more efficient to maintain a single board.
79 */
80static int board[ 81 ];
81
82/* Addressing board elements: linear array 0..80 */
83#define ROW(idx) ((idx)/9)
84#define COLUMN(idx) ((idx)%9)
85#define BLOCK(idx) (3*(ROW(idx)/3)+(COLUMN(idx)/3))
86#define INDEX(row,col) (9*(row)+(col))
87
88/* Blocks indexed 0..9 */
89#define IDX_BLOCK(row,col) (3*((row)/3)+((col)/3))
90#define TOP_LEFT(block) (INDEX(block/3,block%3))
91
92/* Board state */
93#define STATE(idx) ((board[idx])&STATE_MASK)
94#define DIGIT(idx) (GET_DIGIT(board[idx]))
95#define HINT(idx) ((board[idx])&HINT_MASK)
96#define IS_EMPTY(idx) (0 == DIGIT(idx))
97#define DISALLOWED(idx,digit) ((board[idx])&DIGIT_STATE(digit))
98#define IS_FIXED(idx) (board[idx]&FIXED)
99
100/* Record move history, and maintain a counter for the current
101 * move number. Concessions are made for the user interface, and
102 * allow digit 0 to indicate clearing a square. The move history
103 * is used to support 'undo's for the user interface, and hence
104 * is larger than required - there is sufficient space to solve
105 * the puzzle, undo every move, and then redo the puzzle - and
106 * if the user requires more space, then the full history will be
107 * lost.
108 */
109static int idx_history;
110static int history[ 3 * 81 ];
111
112/* Possible moves for a given board (c.f. fillmoves()).
113 * Also used by choice() when the deterministic solver has failed,
114 * and for calculating user hints. The number of hints is stored
115 * in num_hints, or -1 if no hints calculated. The number of hints
116 * requested by the user since their last move is stored in req_hints;
117 * if the user keeps requesting hints, start giving more information.
118 * Finally, record the last hint issued to the user; attempt to give
119 * different hints each time.
120 */
121static int idx_possible;
122static int possible[ 81 ];
123
124static int pass; /* count # passes of deterministic solver */
125
126/* Support for template file */
127static int tmplt[ 81 ]; /* Template indices */
128static int len_tmplt; /* Number of template indices */
129
130/* Reset global state */
131static
132void
133reset( void )
134{
135 rb->memset( board, 0x00, sizeof( board ) );
136 rb->memset( history, 0x00, sizeof( history ) );
137 idx_history = 0;
138 pass = 0;
139}
140
141/* Management of the move history - compression */
142static
143void
144compress( int limit )
145{
146 int i, j;
147 for( i = j = 0 ; i < idx_history && j < limit ; ++i )
148 if( !( history[ i ] & IGNORED ) )
149 history[ j++ ] = history[ i ];
150 for( ; i < idx_history ; ++i )
151 history[ j++ ] = history[ i ];
152 idx_history = j;
153}
154
155/* Management of the move history - adding a move */
156static
157void
158add_move( int idx, int digit, int choice )
159{
160 int i;
161
162 if( sizeof( history ) / sizeof( int ) == idx_history )
163 compress( 81 );
164
165 /* Never ignore the last move */
166 history[ idx_history++ ] = SET_INDEX( idx ) | SET_DIGIT( digit ) | choice;
167
168 /* Ignore all previous references to idx */
169 for( i = idx_history - 2 ; 0 <= i ; --i )
170 if( GET_INDEX( history[ i ] ) == idx )
171 {
172 history[ i ] |= IGNORED;
173 break;
174 }
175}
176
177/* Iteration over rows/columns/blocks handled by specialised code.
178 * Each function returns a block index - call must manage element/idx.
179 */
180static
181int
182idx_row( int el, int idx ) /* Index within a row */
183{
184 return INDEX( el, idx );
185}
186
187static
188int
189idx_column( int el, int idx ) /* Index within a column */
190{
191 return INDEX( idx, el );
192}
193
194static
195int
196idx_block( int el, int idx ) /* Index within a block */
197{
198 return INDEX( 3 * ( el / 3 ) + idx / 3, 3 * ( el % 3 ) + idx % 3 );
199}
200
201/* Update board state after setting a digit (clearing not handled)
202 */
203static
204void
205update( int idx )
206{
207 const int row = ROW( idx );
208 const int col = COLUMN( idx );
209 const int block = IDX_BLOCK( row, col );
210 const int mask = DIGIT_STATE( DIGIT( idx ) );
211 int i;
212
213 board[ idx ] |= STATE_MASK; /* filled - no choice possible */
214
215 /* Digit cannot appear in row, column or block */
216 for( i = 0 ; i < 9 ; ++i )
217 {
218 board[ idx_row( row, i ) ] |= mask;
219 board[ idx_column( col, i ) ] |= mask;
220 board[ idx_block( block, i ) ] |= mask;
221 }
222}
223
224/* Refresh board state, given move history. Note that this can yield
225 * an incorrect state if the user has made errors - return -1 if an
226 * incorrect state is generated; else return 0 for a correct state.
227 */
228static
229int
230reapply( void )
231{
232 int digit, idx, j;
233 int allok = 0;
234 rb->memset( board, 0x00, sizeof( board ) );
235 for( j = 0 ; j < idx_history ; ++j )
236 if( !( history[ j ] & IGNORED ) && 0 != GET_DIGIT( history[ j ] ) )
237 {
238 idx = GET_INDEX( history[ j ] );
239 digit = GET_DIGIT( history[ j ] );
240 if( !IS_EMPTY( idx ) || DISALLOWED( idx, digit ) )
241 allok = -1;
242 board[ idx ] = SET_DIGIT( digit );
243 if( history[ j ] & FIXED )
244 board[ idx ] |= FIXED;
245 update( idx );
246 }
247 return allok;
248}
249
250/* Clear moves, leaving fixed squares
251 */
252static
253void
254clear_moves( void )
255{
256 for( idx_history = 0 ; history[ idx_history ] & FIXED ; ++idx_history )
257 ;
258 reapply( );
259}
260
261static int digits[ 9 ]; /* # digits expressed in element square */
262static int counts[ 9 ]; /* Count of digits (c.f. count_set_digits()) */
263
264/* Count # set bits (within STATE_MASK) */
265static
266int
267numset( int mask )
268{
269 int i, n = 0;
270 for( i = STATE_SHIFT + 1 ; i <= STATE_SHIFT + 9 ; ++i )
271 if( mask & (1<<i) )
272 ++n;
273 else
274 ++counts[ i - STATE_SHIFT - 1 ];
275 return n;
276}
277
278static
279void
280count_set_digits( int el, int (*idx_fn)( int, int ) )
281{
282 int i;
283 rb->memset( counts, 0x00, sizeof( counts ) );
284 for( i = 0 ; i < 9 ; ++i )
285 digits[ i ] = numset( board[ (*idx_fn)( el, i ) ] );
286}
287
288/* Fill square with given digit, and update state.
289 * Returns 0 on success, else -1 on error (i.e. invalid fill)
290 */
291static
292int
293fill( int idx, int digit )
294{
295 assert( 0 != digit );
296
297 if( !IS_EMPTY( idx ) )
298 return ( DIGIT( idx ) == digit ) ? 0 : -1;
299
300 if( DISALLOWED( idx, digit ) )
301 return -1;
302
303 board[ idx ] = SET_DIGIT( digit );
304 update( idx );
305 add_move( idx, digit, 0 );
306
307 return 0;
308}
309
310/* Find all squares with a single digit allowed -- do not mutate board */
311static
312void
313singles( int el, int (*idx_fn)( int, int ), int hintcode )
314{
315 int i, j, idx;
316
317 count_set_digits( el, idx_fn );
318
319 for( i = 0 ; i < 9 ; ++i )
320 {
321 if( 1 == counts[ i ] )
322 {
323 /* Digit 'i+1' appears just once in the element */
324 for( j = 0 ; j < 9 ; ++j )
325 {
326 idx = (*idx_fn)( el, j );
327 if( !DISALLOWED( idx, i + 1 ) && idx_possible < 81 )
328 possible[ idx_possible++ ] = SET_INDEX( idx )
329 | SET_DIGIT( i + 1 )
330 | hintcode;
331 }
332 }
333 if( 8 == digits[ i ] )
334 {
335 /* 8 digits are masked at this position - just one remaining */
336 idx = (*idx_fn)( el, i );
337 for( j = 1 ; j <= 9 ; ++j )
338 if( 0 == ( STATE( idx ) & DIGIT_STATE( j ) ) && idx_possible < 81 )
339 possible[ idx_possible++ ] = SET_INDEX( idx )
340 | SET_DIGIT( j )
341 | hintcode;
342 }
343 }
344}
345
346/* Given the board state, find all possible 'moves' (i.e. squares with just
347 * a single digit).
348 *
349 * Returns the number of (deterministic) moves (and fills the moves array),
350 * or 0 if no moves are possible. This function does not mutate the board
351 * state, and hence, can return the same move multiple times (with
352 * different hints).
353 */
354static
355int
356findmoves( void )
357{
358 int i;
359
360 idx_possible = 0;
361 for( i = 0 ; i < 9 ; ++i )
362 {
363 singles( i, idx_row, HINT_ROW );
364 singles( i, idx_column, HINT_COLUMN );
365 singles( i, idx_block, HINT_BLOCK );
366 }
367 return idx_possible;
368}
369
370/* Strategies for refining the board state
371 * - 'pairs' if there are two unfilled squares in a given row/column/
372 * block with the same state, and just two possibilities,
373 * then all other unfilled squares in the row/column/block
374 * CANNOT be either of these digits.
375 * - 'block' if the unknown squares in a block all appear in the same
376 * row or column, then all unknown squares outside the block
377 * and in the same row/column cannot be any of the unknown
378 * squares in the block.
379 * - 'common' if all possible locations for a digit in a block appear
380 * in a row or column, then that digit cannot appear outside
381 * the block in the same row or column.
382 * - 'position2' if the positions of 2 unknown digits in a block match
383 * identically in precisely 2 positions, then those 2 positions
384 * can only contain the 2 unknown digits.
385 *
386 * Recall that each state bit uses a 1 to prevent a digit from
387 * filling that square.
388 */
389
390static
391void
392pairs( int el, int (*idx_fn)( int, int ) )
393{
394 int i, j, k, mask, idx;
395 for( i = 0 ; i < 8 ; ++i )
396 if( 7 == digits[ i ] ) /* 2 digits unknown */
397 for( j = i + 1 ; j < 9 ; ++j )
398 {
399 idx = (*idx_fn)( el, i );
400 if( STATE( idx ) == STATE( (*idx_fn)( el, j ) ) )
401 {
402 /* Found a row/column pair - mask other entries */
403 mask = STATE_MASK ^ (STATE_MASK & board[ idx ] );
404 for( k = 0 ; k < i ; ++k )
405 board[ (*idx_fn)( el, k ) ] |= mask;
406 for( k = i + 1 ; k < j ; ++k )
407 board[ (*idx_fn)( el, k ) ] |= mask;
408 for( k = j + 1 ; k < 9 ; ++k )
409 board[ (*idx_fn)( el, k ) ] |= mask;
410 digits[ j ] = -1; /* now processed */
411 }
412 }
413}
414
415/* Worker: mask elements outside block */
416static
417void
418exmask( int mask, int block, int el, int (*idx_fn)( int, int ) )
419{
420 int i, idx;
421
422 for( i = 0 ; i < 9 ; ++i )
423 {
424 idx = (*idx_fn)( el, i );
425 if( block != BLOCK( idx ) && IS_EMPTY( idx ) )
426 board[ idx ] |= mask;
427 }
428}
429
430/* Worker for block() */
431static
432void
433exblock( int block, int el, int (*idx_fn)( int, int ) )
434{
435 int i, idx, mask;
436
437 /* By assumption, all unknown squares in the block appear in the
438 * same row/column, so to construct a mask for these squares, it
439 * is sufficient to invert the mask for the known squares in the
440 * block.
441 */
442 mask = 0;
443 for( i = 0 ; i < 9 ; ++i )
444 {
445 idx = idx_block( block, i );
446 if( !IS_EMPTY( idx ) )
447 mask |= DIGIT_STATE( DIGIT( idx ) );
448 }
449 exmask( mask ^ STATE_MASK, block, el, idx_fn );
450}
451
452static
453void
454block( int el )
455{
456 int i, idx = 0, row, col;
457
458 /* Find first unknown square */
459 for( i = 0 ; i < 9 && !IS_EMPTY( idx = idx_block( el, i ) ) ; ++i )
460 ;
461 if( i < 9 )
462 {
463 assert( IS_EMPTY( idx ) );
464 row = ROW( idx );
465 col = COLUMN( idx );
466 for( ++i ; i < 9 ; ++i )
467 {
468 idx = idx_block( el, i );
469 if( IS_EMPTY( idx ) )
470 {
471 if( ROW( idx ) != row )
472 row = -1;
473 if( COLUMN( idx ) != col )
474 col = -1;
475 }
476 }
477 if( 0 <= row )
478 exblock( el, row, idx_row );
479 if( 0 <= col )
480 exblock( el, col, idx_column );
481 }
482}
483
484static
485void
486common( int el )
487{
488 int i, idx, row, col, digit, mask;
489
490 for( digit = 1 ; digit <= 9 ; ++digit )
491 {
492 mask = DIGIT_STATE( digit );
493 row = col = -1; /* Value '9' indicates invalid */
494 for( i = 0 ; i < 9 ; ++i )
495 {
496 /* Digit possible? */
497 idx = idx_block( el, i );
498 if( IS_EMPTY( idx ) && 0 == ( board[ idx ] & mask ) )
499 {
500 if( row < 0 )
501 row = ROW( idx );
502 else
503 if( row != ROW( idx ) )
504 row = 9; /* Digit appears in multiple rows */
505 if( col < 0 )
506 col = COLUMN( idx );
507 else
508 if( col != COLUMN( idx ) )
509 col = 9; /* Digit appears in multiple columns */
510 }
511 }
512 if( -1 != row && row < 9 )
513 exmask( mask, el, row, idx_row );
514 if( -1 != col && col < 9 )
515 exmask( mask, el, col, idx_column );
516 }
517}
518
519/* Encoding of positions of a digit (c.f. position2()) - abuse DIGIT_STATE */
520static int posn_digit[ 10 ];
521
522static
523void
524position2( int el )
525{
526 int digit, digit2, i, mask, mask2, posn, count, idx;
527
528 /* Calculate positions of each digit within block */
529 for( digit = 1 ; digit <= 9 ; ++digit )
530 {
531 mask = DIGIT_STATE( digit );
532 posn_digit[ digit ] = count = posn = 0;
533 for( i = 0 ; i < 9 ; ++i )
534 if( 0 == ( mask & board[ idx_block( el, i ) ] ) )
535 {
536 ++count;
537 posn |= DIGIT_STATE( i );
538 }
539 if( 2 == count )
540 posn_digit[ digit ] = posn;
541 }
542 /* Find pairs of matching positions, and mask */
543 for( digit = 1 ; digit < 9 ; ++digit )
544 if( 0 != posn_digit[ digit ] )
545 for( digit2 = digit + 1 ; digit2 <= 9 ; ++digit2 )
546 if( posn_digit[ digit ] == posn_digit[ digit2 ] )
547 {
548 mask = STATE_MASK
549 ^ ( DIGIT_STATE( digit ) | DIGIT_STATE( digit2 ) );
550 mask2 = DIGIT_STATE( digit );
551 for( i = 0 ; i < 9 ; ++i )
552 {
553 idx = idx_block( el, i );
554 if( 0 == ( mask2 & board[ idx ] ) )
555 {
556 assert( 0 == (DIGIT_STATE(digit2) & board[idx]) );
557 board[ idx ] |= mask;
558 }
559 }
560 posn_digit[ digit ] = posn_digit[ digit2 ] = 0;
561 break;
562 }
563}
564
565/* Find some moves for the board; starts with a simple approach (finding
566 * singles), and if no moves found, starts using more involved strategies
567 * until a move is found. The more advanced strategies can mask states
568 * in the board, making this an efficient mechanism, but difficult for
569 * a human to understand.
570 */
571static
572int
573allmoves( void )
574{
575 int i, n;
576
577 n = findmoves( );
578 if( 0 < n )
579 return n;
580
581 for( i = 0 ; i < 9 ; ++i )
582 {
583 count_set_digits( i, idx_row );
584 pairs( i, idx_row );
585
586 count_set_digits( i, idx_column );
587 pairs( i, idx_column );
588
589 count_set_digits( i, idx_block );
590 pairs( i, idx_block );
591 }
592 n = findmoves( );
593 if( 0 < n )
594 return n;
595
596 for( i = 0 ; i < 9 ; ++i )
597 {
598 block( i );
599 common( i );
600 position2( i );
601 }
602 return findmoves( );
603}
604
605/* Helper: sort based on index */
606static
607int
608cmpindex( const void * a, const void * b )
609{
610 return GET_INDEX( *((const int *)b) ) - GET_INDEX( *((const int *)a) );
611}
612
613/* Return number of hints. The hints mechanism should attempt to find
614 * 'easy' moves first, and if none are possible, then try for more
615 * cryptic moves.
616 */
617int
618findhints( void )
619{
620 int i, n, mutated = 0;
621
622 n = findmoves( );
623 if( n < 2 )
624 {
625 /* Each call to pairs() can mutate the board state, making the
626 * hints very, very cryptic... so later undo the mutations.
627 */
628 for( i = 0 ; i < 9 ; ++i )
629 {
630 count_set_digits( i, idx_row );
631 pairs( i, idx_row );
632
633 count_set_digits( i, idx_column );
634 pairs( i, idx_column );
635
636 count_set_digits( i, idx_block );
637 pairs( i, idx_block );
638 }
639 mutated = 1;
640 n = findmoves( );
641 }
642 if( n < 2 )
643 {
644 for( i = 0 ; i < 9 ; ++i )
645 {
646 block( i );
647 common( i );
648 }
649 mutated = 1;
650 n = findmoves( );
651 }
652
653 /* Sort the possible moves, and allow just one hint per square */
654 if( 0 < n )
655 {
656 int i, j;
657
658 rb->qsort( possible, n, sizeof( int ), cmpindex );
659 for( i = 0, j = 1 ; j < n ; ++j )
660 {
661 if( GET_INDEX( possible[ i ] ) == GET_INDEX( possible[ j ] ) )
662 {
663 /* Let the user make mistakes - do not assume the
664 * board is in a consistent state.
665 */
666 if( GET_DIGIT( possible[i] ) == GET_DIGIT( possible[j] ) )
667 possible[ i ] |= possible[ j ];
668 }
669 else
670 i = j;
671 }
672 n = i + 1;
673 }
674
675 /* Undo any mutations of the board state */
676 if( mutated )
677 reapply( );
678
679 return n;
680}
681
682/* Deterministic solver; return 0 on success, else -1 on error.
683 */
684static
685int
686deterministic( void )
687{
688 int i, n;
689
690 n = allmoves( );
691 while( 0 < n )
692 {
693 ++pass;
694 for( i = 0 ; i < n ; ++i )
695 if( -1 == fill( GET_INDEX( possible[ i ] ),
696 GET_DIGIT( possible[ i ] ) ) )
697 return -1;
698 n = allmoves( );
699 }
700 return 0;
701}
702
703/* Return index of square for choice.
704 *
705 * If no choice is possible (i.e. board solved or inconsistent),
706 * return -1.
707 *
708 * The current implementation finds a square with the minimum
709 * number of unknown digits (i.e. maximum # masked digits).
710 */
711static
712int
713cmp( const void * e1, const void * e2 )
714{
715 return GET_DIGIT( *(const int *)e2 ) - GET_DIGIT( *(const int *)e1 );
716}
717
718static
719int
720choice( void )
721{
722 int i, n;
723 for( n = i = 0 ; i < 81 ; ++i )
724 if( IS_EMPTY( i ) )
725 {
726 possible[ n ] = SET_INDEX( i ) | SET_DIGIT( numset( board[ i ] ) );
727
728 /* Inconsistency if square unknown, but nothing possible */
729 if( 9 == GET_DIGIT( possible[ n ] ) )
730 return -2;
731 ++n;
732 }
733
734 if( 0 == n )
735 return -1; /* All squares known */
736
737 rb->qsort( possible, n, sizeof( possible[ 0 ] ), cmp );
738 return GET_INDEX( possible[ 0 ] );
739}
740
741/* Choose a digit for the given square.
742 * The starting digit is passed as a parameter.
743 * Returns -1 if no choice possible.
744 */
745static
746int
747choose( int idx, int digit )
748{
749 for( ; digit <= 9 ; ++digit )
750 if( !DISALLOWED( idx, digit ) )
751 {
752 board[ idx ] = SET_DIGIT( digit );
753 update( idx );
754 add_move( idx, digit, CHOICE );
755 return digit;
756 }
757
758 return -1;
759}
760
761/* Backtrack to a previous choice point, and attempt to reseed
762 * the search. Return -1 if no further choice possible, or
763 * the index of the changed square.
764 *
765 * Assumes that the move history and board are valid.
766 */
767static
768int
769backtrack( void )
770{
771 int digit, idx;
772
773 for( ; 0 <= --idx_history ; )
774 if( history[ idx_history ] & CHOICE )
775 {
776 /* Remember the last choice, and advance */
777 idx = GET_INDEX( history[ idx_history ] );
778 digit = GET_DIGIT( history[ idx_history ] ) + 1;
779 reapply( );
780 if( -1 != choose( idx, digit ) )
781 return idx;
782 }
783
784 return -1;
785}
786
787/* Attempt to solve 'board'; return 0 on success else -1 on error.
788 *
789 * The solution process attempts to fill-in deterministically as
790 * much of the board as possible. Once that is no longer possible,
791 * need to choose a square to fill in.
792 */
793static
794int
795solve( void )
796{
797 int idx;
798
799 while( 1 )
800 {
801 if( 0 == deterministic( ) )
802 {
803 /* Solved, make a new choice, or rewind a previous choice */
804 idx = choice( );
805 if( -1 == idx )
806 return 0;
807 else
808 if( ( idx < 0 || -1 == choose( idx, 1 ) ) && -1 == backtrack( ) )
809 return -1;
810 }
811 else /* rewind to a previous choice */
812 if( -1 == backtrack( ) )
813 return -1;
814 }
815 return -1;
816}
817
818static
819int
820init_template( int template )
821{
822 int i, row, col;
823 int mask;
824
825 reset( );
826 len_tmplt = 0;
827
828 /* Consume grid - allow leading spaces and comments at end */
829 for( row = 0 ; row < 9 ; ++row )
830 {
831 mask=0x100;
832 for( col = 0 ; col < 9 ; ++col )
833 {
834 if (templates[template][row] & mask)
835 tmplt[ len_tmplt++ ] = INDEX( row, col );
836 mask /= 2;
837 }
838 }
839
840 /* Construct move history for a template */
841 idx_history = 0;
842 for( i = 0 ; i < 81 ; ++i )
843 if( 0 != DIGIT( i ) )
844 history[ idx_history++ ] = i | (DIGIT( i )<<8);
845
846 /* Finally, markup all of these moves as 'fixed' */
847 for( i = 0 ; i < idx_history ; ++i )
848 history[ i ] |= FIXED;
849
850 return 0;
851}
852
853/* Classify a SuDoKu, given its solution.
854 *
855 * The classification is based on the average number of possible moves
856 * for each pass of the deterministic solver - it is a rather simplistic
857 * measure, but gives reasonable results. Note also that the classification
858 * is based on the first solution found (but does handle the pathological
859 * case of multiple solutions). Note that the average moves per pass
860 * depends just on the number of squares initially set... this simplifies
861 * the statistics collection immensely, requiring just the number of passes
862 * to be counted.
863 *
864 * Return 0 on error, else a string classification.
865 */
866
867static
868char *
869classify( void )
870{
871 int i, score;
872
873 pass = 0;
874 clear_moves( );
875 if( -1 == solve( ) )
876 return 0;
877
878 score = 81;
879 for( i = 0 ; i < 81 ; ++i )
880 if( IS_FIXED( i ) )
881 --score;
882
883 assert( 81 == idx_history );
884
885 for( i = 0 ; i < 81 ; ++i )
886 if( history[ i ] & CHOICE )
887 score -= 5;
888
889 if( 15 * pass < score )
890 return "very easy";
891 else
892 if( 11 * pass < score )
893 return "easy";
894 else
895 if( 7 * pass < score )
896 return "medium";
897 else
898 if( 4 * pass < score )
899 return "hard";
900 else
901 return "fiendish";
902}
903
904/* exchange disjoint, identical length blocks of data */
905static
906void
907exchange( int * a, int * b, int len )
908{
909 int i, tmp;
910 for( i = 0 ; i < len ; ++i )
911 {
912 tmp = a[ i ];
913 a[ i ] = b[ i ];
914 b[ i ] = tmp;
915 }
916}
917
918/* rotate left */
919static
920void
921rotate1_left( int * a, int len )
922{
923 int i, tmp;
924 tmp = a[ 0 ];
925 for( i = 1 ; i < len ; ++i )
926 a[ i - 1 ] = a[ i ];
927 a[ len - 1 ] = tmp;
928}
929
930/* rotate right */
931static
932void
933rotate1_right( int * a, int len )
934{
935 int i, tmp;
936 tmp = a[ len - 1 ];
937 for( i = len - 1 ; 0 < i ; --i )
938 a[ i ] = a[ i - 1 ];
939 a[ 0 ] = tmp;
940}
941
942/* Generalised left rotation - there is a naturally recursive
943 * solution that is best implementation using iteration.
944 * Note that it is not necessary to do repeated unit rotations.
945 *
946 * This function is analogous to 'cutting' a 'pack of cards'.
947 *
948 * On entry: 0 < idx < len
949 */
950static
951void
952rotate( int * a, int len, int idx )
953{
954 int xdi = len - idx;
955 int delta = idx - xdi;
956
957 while( 0 != delta && 0 != idx )
958 {
959 if( delta < 0 )
960 {
961 if( 1 == idx )
962 {
963 rotate1_left( a, len );
964 idx = 0;
965 }
966 else
967 {
968 exchange( a, a + xdi, idx );
969 len = xdi;
970 }
971 }
972 else /* 0 < delta */
973 {
974 if( 1 == xdi )
975 {
976 rotate1_right( a, len );
977 idx = 0;
978 }
979 else
980 {
981 exchange( a, a + idx, xdi );
982 a += xdi;
983 len = idx;
984 idx -= xdi;
985 }
986 }
987 xdi = len - idx;
988 delta = idx - xdi;
989 }
990 if( 0 < idx )
991 exchange( a, a + idx, idx );
992}
993
994/* Shuffle an array of integers */
995static
996void
997shuffle( int * a, int len )
998{
999 int i, j, tmp;
1000
1001 i = len;
1002 while( 1 <= i )
1003 {
1004 j = rb->rand( ) % i;
1005 tmp = a[ --i ];
1006 a[ i ] = a[ j ];
1007 a[ j ] = tmp;
1008 }
1009}
1010
1011/* Generate a SuDoKu puzzle
1012 *
1013 * The generation process selects a random template, and then attempts
1014 * to fill in the exposed squares to generate a board. The order of the
1015 * digits and of filling in the exposed squares are random.
1016 */
1017
1018/* Select random template; sets tmplt, len_tmplt */
1019static
1020void
1021select_template( void )
1022{
1023 int i = rb->rand( ) % NUM_TEMPLATES;
1024 init_template( i );
1025}
1026
1027
1028static
1029void
1030generate( void )
1031{
1032 static int digits[ 9 ];
1033
1034 int i;
1035
1036start:
1037 for( i = 0 ; i < 9 ; ++i )
1038 digits[ i ] = i + 1;
1039
1040 rotate( digits, 9, 1 + rb->rand( ) % 8 );
1041 shuffle( digits, 9 );
1042 select_template( );
1043
1044 rotate( tmplt, len_tmplt, 1 + rb->rand( ) % ( len_tmplt - 1 ) );
1045 shuffle( tmplt, len_tmplt );
1046
1047 reset( ); /* construct a new board */
1048
1049 for( i = 0 ; i < len_tmplt ; ++i )
1050 fill( tmplt[ i ], digits[ i % 9 ] );
1051
1052 if( 0 != solve( ) || idx_history < 81 )
1053 goto start;
1054
1055 for( i = 0 ; i < len_tmplt ; ++i )
1056 board[ tmplt[ i ] ] |= FIXED;
1057
1058 /* Construct fixed squares */
1059 for( idx_history = i = 0 ; i < 81 ; ++i )
1060 if( IS_FIXED( i ) )
1061 history[ idx_history++ ] = SET_INDEX( i )
1062 | SET_DIGIT( DIGIT( i ) )
1063 | FIXED;
1064 clear_moves( );
1065
1066 if( 0 != solve( ) || idx_history < 81 )
1067 goto start;
1068 if( -1 != backtrack( ) && 0 == solve( ) )
1069 goto start;
1070
1071 clear_moves( );
1072}
1073
1074bool sudoku_generate_board(struct sudoku_state_t* state, char** difficulty)
1075{
1076 int r,c,i;
1077
1078 rb->srand(*rb->current_tick);
1079
1080 generate();
1081
1082 i=0;
1083 for (r=0;r<9;r++) {
1084 for (c=0;c<9;c++) {
1085 if( IS_EMPTY( i ) )
1086 state->startboard[r][c]='0';
1087 else
1088 state->startboard[r][c]='0'+GET_DIGIT( board[ i ] );
1089
1090 state->currentboard[r][c]=state->startboard[r][c];
1091 i++;
1092 }
1093 }
1094
1095 *difficulty = classify( );
1096 return true;
1097}
diff --git a/apps/plugins/sudoku/generator.h b/apps/plugins/sudoku/generator.h
new file mode 100644
index 0000000000..3caa98ee19
--- /dev/null
+++ b/apps/plugins/sudoku/generator.h
@@ -0,0 +1 @@
bool sudoku_generate_board(struct sudoku_state_t* state, char** difficulty);
diff --git a/apps/plugins/sudoku/sudoku.c b/apps/plugins/sudoku/sudoku.c
new file mode 100644
index 0000000000..798936b384
--- /dev/null
+++ b/apps/plugins/sudoku/sudoku.c
@@ -0,0 +1,1124 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/***
21Sudoku by Dave Chapman
22
23User instructions
24-----------------
25
26Use the arrow keys to move cursor, and press SELECT/ON/F2 to increment
27the number under the cursor.
28
29At any time during the game, press On to bring up the game menu with
30further options:
31
32 Save
33 Reload
34 Clear
35 Solve
36
37Sudoku is implemented as a "viewer" for a ".ss" file, as generated by
38Simple Sudoku and other applications - http://angusj.com/sudoku/
39
40In-progress game positions are saved in the original .ss file, with
41A-I used to indicate numbers entered by the user.
42
43Example ".ss" file, and one with a saved state:
44
45...|...|... ...|...|...
462..|8.4|9.1 2.C|8.4|9.1
47...|1.6|32. E..|1.6|32.
48----------- -----------
49...|..5|.4. ...|..5|.4.
508..|423|..6 8..|423|..6
51.3.|9..|... .3D|9..|A..
52----------- -----------
53.63|7.9|... .63|7.9|...
544.9|5.2|..8 4.9|5.2|.C8
55...|...|... ...|...|...
56
57*/
58
59#include "plugin.h"
60
61#ifdef HAVE_LCD_BITMAP
62
63#include "sudoku.h"
64#include "generator.h"
65
66PLUGIN_HEADER
67
68struct plugin_api* rb;
69
70/* The bitmaps */
71extern const fb_data sudoku_normal[];
72extern const fb_data sudoku_start[];
73extern const fb_data sudoku_inverse[];
74
75#if (LCD_HEIGHT==128) && (LCD_WIDTH==160)
76/* For iriver H1x0 - 160x128, 9 cells @ 12x12 with 14 border lines*/
77
78/* Internal dimensions of a cell */
79#define CELL_WIDTH 12
80#define CELL_HEIGHT 12
81
82#define BOARD_WIDTH (CELL_WIDTH*9+10+4)
83#define BOARD_HEIGHT (CELL_HEIGHT*9+10+4)
84
85#define XOFS (((LCD_WIDTH-BOARD_WIDTH)/2)+10)
86#define YOFS ((LCD_HEIGHT-BOARD_HEIGHT)/2)
87
88#define XOFSSCRATCHPAD 3
89
90/* Locations of each cell */
91static unsigned char cellxpos[9]={ 2, 15, 28, 42, 55, 68, 82, 95, 108 };
92static unsigned char cellypos[9]={ 2, 15, 28, 42, 55, 68, 82, 95, 108 };
93
94/* The height of one cell in the bitmap */
95#define BITMAP_HEIGHT 12
96#define BITMAP_STRIDE 12
97
98#elif (LCD_HEIGHT==64) && (LCD_WIDTH==112)
99/* For Archos Recorder, FM and Ondio (112x64):
100 9 cells @ 8x6 with 10 border lines
101*/
102
103/* Internal dimensions of a cell */
104#define CELL_WIDTH 8
105#define CELL_HEIGHT 6
106
107#define BOARD_WIDTH (CELL_WIDTH*9+10)
108#define BOARD_HEIGHT (CELL_HEIGHT*9+10)
109
110#define XOFS (((LCD_WIDTH-BOARD_WIDTH)/2)+7)
111#define YOFS ((LCD_HEIGHT-BOARD_HEIGHT)/2)
112
113#define XOFSSCRATCHPAD 2
114
115/* Locations of each cell */
116static unsigned char cellxpos[9]={ 1, 10, 19, 28, 37, 46, 55, 64, 73 };
117static unsigned char cellypos[9]={ 1, 8, 15, 22, 29, 36, 43, 50, 57 };
118
119/* The height of one cell in the bitmap */
120#define BITMAP_HEIGHT 8
121#define BITMAP_STRIDE 8
122
123#elif (LCD_HEIGHT>=176) && (LCD_WIDTH>=220)
124/* iriver h300 */
125
126/* Internal dimensions of a cell */
127#define CELL_WIDTH 16
128#define CELL_HEIGHT 16
129
130#define BOARD_WIDTH (CELL_WIDTH*9+10+4)
131#define BOARD_HEIGHT (CELL_HEIGHT*9+10+4)
132
133#define XOFS (((LCD_WIDTH-BOARD_WIDTH)/2)+15)
134#define YOFS ((LCD_HEIGHT-BOARD_HEIGHT)/2)
135
136#define XOFSSCRATCHPAD 10
137
138/* Locations of each cell */
139static unsigned char cellxpos[9]={ 2, 19, 36, 54, 71, 88, 106, 123, 140 };
140static unsigned char cellypos[9]={ 2, 19, 36, 54, 71, 88, 106, 123, 140 };
141
142/* The height of one cell in the bitmap */
143#define BITMAP_HEIGHT 16
144#define BITMAP_STRIDE 16
145
146#else
147 #error SUDOKU: Unsupported LCD size
148#endif
149
150/****** Solver routine by Tom Shackell <shackell@cs.york.ac.uk>
151
152Downloaded from:
153
154http://www-users.cs.york.ac.uk/~shackell/sudoku/Sudoku.html
155
156Released under GPLv2
157
158*/
159
160typedef unsigned int Bitset;
161
162#define BLOCK 3
163#define SIZE (BLOCK*BLOCK)
164
165#define true 1
166#define false 0
167
168typedef struct _Sudoku {
169 Bitset table[SIZE][SIZE];
170}Sudoku;
171
172typedef struct _Stats {
173 int numTries;
174 int backTracks;
175 int numEmpty;
176 bool solutionFound;
177}Stats;
178
179typedef struct _Options {
180 bool allSolutions;
181 bool uniquenessCheck;
182}Options;
183
184void sudoku_init(Sudoku* sud);
185void sudoku_set(Sudoku* sud, int x, int y, int num, bool original);
186int sudoku_get(Sudoku* sud, int x, int y, bool* original);
187
188#define BIT(n) ((Bitset)(1<<(n)))
189#define BIT_TEST(v,n) ((((Bitset)v) & BIT(n)) != 0)
190#define BIT_CLEAR(v,n) (v) &= ~BIT(n)
191#define MARK_BIT BIT(0)
192#define ORIGINAL_BIT BIT(SIZE+1)
193
194#define ALL_BITS (BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9))
195
196/* initialize a sudoku problem, should be called before using set or get */
197void sudoku_init(Sudoku* sud)
198{
199 int y, x;
200 for (y = 0; y < SIZE; y++){
201 for (x = 0; x < SIZE; x++){
202 sud->table[x][y] = ALL_BITS;
203 }
204 }
205}
206
207/* set the number at a particular x and y column */
208void sudoku_set(Sudoku* sud, int x, int y, int num, bool original)
209{
210 int i, j;
211 int bx, by;
212 Bitset orig;
213
214 /* clear the row and columns */
215 for (i = 0; i < SIZE; i++){
216 BIT_CLEAR(sud->table[i][y], num);
217 BIT_CLEAR(sud->table[x][i], num);
218 }
219 /* clear the block */
220 bx = x - (x % BLOCK);
221 by = y - (y % BLOCK);
222 for (i = 0; i < BLOCK; i++){
223 for (j = 0; j < BLOCK; j++){
224 BIT_CLEAR(sud->table[bx+j][by+i], num);
225 }
226 }
227 /* mark the table */
228 orig = original ? ORIGINAL_BIT : 0;
229 sud->table[x][y] = BIT(num) | MARK_BIT | orig;
230}
231
232/* get the number at a particular x and y column, if this
233 is not unique return 0 */
234int sudoku_get(Sudoku* sud, int x, int y, bool* original)
235{
236 Bitset val = sud->table[x][y];
237 int result = 0;
238 int i;
239
240 if (original) {
241 *original = val & ORIGINAL_BIT;
242 }
243 for (i = 1; i <= SIZE; i++){
244 if (BIT_TEST(val, i)){
245 if (result != 0){
246 return 0;
247 }
248 result = i;
249 }
250 }
251 return result;
252}
253
254/* returns true if this is a valid problem, this is necessary because the input
255 problem might be degenerate which breaks the solver algorithm. */
256static bool is_valid(const Sudoku* sud)
257{
258 int x, y;
259
260 for (y = 0; y < SIZE; y++){
261 for (x = 0; x < SIZE; x++){
262 if ((sud->table[x][y] & ALL_BITS) == 0){
263 return false;
264 }
265 }
266 }
267 return true;
268}
269
270/* scan the table for the most constrained item, giving all it's options, sets
271 the best x and y coordinates, the number of options and the options for
272 that coordinate and returns true if the puzzle is finished */
273static bool scan(const Sudoku* sud, int* rX, int* rY, int *num, int* options)
274{
275 int x, y, i, j;
276 int bestCount = SIZE+1;
277 Bitset val;
278 bool allMarked = true;
279
280 for (y = 0; y < SIZE; y++){
281 for (x = 0; x < SIZE; x++){
282 Bitset val = sud->table[x][y];
283 int i;
284 int count = 0;
285
286 if (val & MARK_BIT) {
287 /* already set */
288 continue;
289 }
290 allMarked = false;
291 for (i = 1; i <= SIZE; i++){
292 if (BIT_TEST(val, i)){
293 count++;
294 }
295 }
296 if (count < bestCount){
297 bestCount = count;
298 *rX = x;
299 *rY = y;
300 if (count == 0){
301 /* can't possibly be beaten */
302 *num = 0;
303 return false;
304 }
305 }
306 }
307 }
308 /* now copy into options */
309 *num = bestCount;
310 val = sud->table[*rX][*rY];
311 for (i = 1, j = 0; i <= SIZE; i++){
312 if (BIT_TEST(val, i)){
313 options[j++] = i;
314 }
315 }
316 return allMarked;
317}
318
319static bool solve(Sudoku* sud, Stats* stats, const Options* options);
320
321/* try a particular option and return true if that gives a solution or false
322 if it doesn't, restores board on backtracking */
323static bool spawn_option(Sudoku* sud, Stats* stats, const Options* options,
324 int x, int y, int num)
325{
326 Sudoku copy;
327
328 rb->memcpy(&copy,sud,sizeof(Sudoku));
329 sudoku_set(&copy, x, y, num, false);
330 stats->numTries += 1;
331 if (solve(&copy, stats, options)){
332 if (!options->allSolutions && stats->solutionFound){
333 rb->memcpy(sud,&copy,sizeof(Sudoku));
334 }
335 return true;
336 }else{
337 stats->backTracks++;
338 }
339 return false;
340}
341
342/* solve a sudoku problem, returns true if there is a solution and false
343 otherwise. stats is used to track statisticss */
344static bool solve(Sudoku* sud, Stats* stats, const Options* options)
345{
346 while (true){
347 int x, y, i, num;
348 int places[SIZE];
349
350 if (scan(sud, &x, &y, &num, places)){
351 /* a solution was found! */
352 if (options->uniquenessCheck && stats->solutionFound){
353 /*printf("\n\t... But the solution is not unique!\n"); */
354 return true;
355 }
356 stats->solutionFound = true;
357 if (options->allSolutions || options->uniquenessCheck){
358 /*printf("\n\tSolution after %d iterations\n", stats->numTries); */
359 /*sudoku_print(sud); */
360 return false;
361 }
362 else{
363 return true;
364 }
365 }
366 if (num == 0){
367 /* can't be satisfied */
368 return false;
369 }
370 /* try all the places (except the last one) */
371 for (i = 0; i < num-1; i++){
372 if (spawn_option(sud, stats, options, x, y, places[i])){
373 /* solution found! */
374 if (!options->allSolutions && stats->solutionFound){
375 return true;
376 }
377 }
378 }
379 /* take the last place ourself */
380 stats->numTries += 1;
381 sudoku_set(sud, x, y, places[num-1], false);
382 }
383}
384
385/******** END OF IMPORTED CODE */
386
387
388/* A wrapper function between the Sudoku plugin and the above solver code */
389void sudoku_solve(struct sudoku_state_t* state)
390{
391 bool ret;
392 Stats stats;
393 Options options;
394 Sudoku sud;
395 bool original;
396 int r,c;
397
398 /* Initialise the parameters */
399 sudoku_init(&sud);
400 rb->memset(&stats,0,sizeof(stats));
401 options.allSolutions=false;
402 options.uniquenessCheck=false;
403
404 /* Convert Rockbox format into format for solver */
405 for (r=0;r<9;r++) {
406 for (c=0;c<9;c++) {
407 if (state->startboard[r][c]!='0') {
408 sudoku_set(&sud, c, r, state->startboard[r][c]-'0', true);
409 }
410 }
411 }
412
413 /* need to check for degenerate input problems ... */
414 if (is_valid(&sud)){
415 ret = solve(&sud, &stats, &options);
416 } else {
417 ret = false;
418 }
419
420 if (ret) {
421 /* Populate the board with the solution. */
422 for (r=0;r<9;r++) {
423 for (c=0;c<9;c++) {
424 state->currentboard[r][c]='0'+
425 sudoku_get(&sud, c, r, &original);
426 }
427 }
428 } else {
429 rb->splash(HZ*2, true, "Solve failed");
430 }
431
432 return;
433}
434
435
436void clear_state(struct sudoku_state_t* state)
437{
438 int r,c;
439
440 state->filename[0]=0;
441 for (r=0;r<9;r++) {
442 for (c=0;c<9;c++) {
443 state->startboard[r][c]='0';
444 state->currentboard[r][c]='0';
445#ifdef SUDOKU_BUTTON_POSSIBLE
446 state->possiblevals[r][c]=0;
447#endif
448 }
449 }
450
451 state->x=0;
452 state->y=0;
453 state->editmode=0;
454}
455
456/* Load game - only ".ss" is officially supported, but any sensible
457 text representation (one line per row) may load.
458*/
459bool load_sudoku(struct sudoku_state_t* state, char* filename)
460{
461 int fd;
462 size_t n;
463 int r = 0, c = 0;
464 unsigned int i;
465 int valid=0;
466 char buf[300]; /* A buffer to read a sudoku board from */
467
468 fd=rb->open(filename, O_RDONLY);
469 if (fd < 0) {
470 LOGF("Invalid sudoku file: %s\n",filename);
471 return(false);
472 }
473
474 rb->strncpy(state->filename,filename,MAX_PATH);
475 n=rb->read(fd,buf,300);
476 if (n <= 0) {
477 return(false);
478 }
479 rb->close(fd);
480
481 r=0;
482 c=0;
483 i=0;
484 while ((i < n) && (r < 9)) {
485 switch (buf[i]){
486 case ' ': case '\t':
487 if (c > 0)
488 valid=1;
489 break;
490 case '|':
491 case '*':
492 case '-':
493 case '\r':
494 break;
495 case '\n':
496 if (valid) {
497 r++;
498 valid=0;
499 }
500 c = 0;
501 break;
502 case '_': case '.':
503 valid=1;
504 if (c >= SIZE || r >= SIZE){
505 LOGF("ERROR: sudoku problem is the wrong size (%d,%d)\n",
506 c, r);
507 return(false);
508 }
509 c++;
510 break;
511 default:
512 if (((buf[i]>='A') && (buf[i]<='I')) ||
513 ((buf[i]>='0') && (buf[i]<='9'))) {
514 valid=1;
515 if (r >= SIZE || c >= SIZE){
516 LOGF("ERROR: sudoku problem is the wrong size "
517 "(%d,%d)\n", c, r);
518 return(false);
519 }
520 if ((buf[i]>='0') && (buf[i]<='9')) {
521 state->startboard[r][c]=buf[i];
522 state->currentboard[r][c]=buf[i];
523 } else {
524 state->currentboard[r][c]='1'+(buf[i]-'A');
525 }
526 c++;
527 }
528 /* Ignore any other characters */
529 break;
530 }
531 i++;
532 }
533
534 /* Save a copy of the saved state - so we can reload without using the
535 disk */
536 rb->memcpy(state->savedboard,state->currentboard,81);
537 return(true);
538}
539
540bool save_sudoku(struct sudoku_state_t* state)
541{
542 int fd;
543 int r,c;
544 int i;
545 char line[13];
546 char sep[13];
547
548 rb->memcpy(line,"...|...|...\r\n",13);
549 rb->memcpy(sep,"-----------\r\n",13);
550
551 if (state->filename[0]==0) {
552 return false;
553 }
554
555 fd=rb->open(state->filename, O_WRONLY|O_CREAT);
556 if (fd >= 0) {
557 for (r=0;r<9;r++) {
558 i=0;
559 for (c=0;c<9;c++) {
560 if (state->startboard[r][c]!='0') {
561 line[i]=state->startboard[r][c];
562 } else if (state->currentboard[r][c]!='0') {
563 line[i]='A'+(state->currentboard[r][c]-'1');
564 } else {
565 line[i]='.';
566 }
567 i++;
568 if ((c==2) || (c==5)) {
569 i++;
570 }
571 }
572 rb->write(fd,line,sizeof(line));
573 if ((r==2) || (r==5)) {
574 rb->write(fd,sep,sizeof(sep));
575 }
576 }
577 /* Add a blank line at end */
578 rb->write(fd,"\r\n",2);
579 rb->close(fd);
580 /* Save a copy of the saved state - so we can reload without
581 using the disk */
582 rb->memcpy(state->savedboard,state->currentboard,81);
583 return true;
584 } else {
585 return false;
586 }
587}
588
589void restore_state(struct sudoku_state_t* state)
590{
591 rb->memcpy(state->currentboard,state->savedboard,81);
592}
593
594void clear_board(struct sudoku_state_t* state)
595{
596 int r,c;
597
598 for (r=0;r<9;r++) {
599 for (c=0;c<9;c++) {
600 state->currentboard[r][c]=state->startboard[r][c];
601 }
602 }
603 state->x=0;
604 state->y=0;
605}
606
607void update_cell(struct sudoku_state_t* state, int r, int c)
608{
609 /* We have four types of cell:
610 1) User-entered number
611 2) Starting number
612 3) Cursor in cell
613 */
614
615 if ((r==state->y) && (c==state->x)) {
616 rb->lcd_bitmap_part(sudoku_inverse,0,
617 BITMAP_HEIGHT*(state->currentboard[r][c]-'0'),
618 BITMAP_STRIDE,
619 XOFS+cellxpos[c],YOFS+cellypos[r],CELL_WIDTH,
620 CELL_HEIGHT);
621 } else {
622 if (state->startboard[r][c]!='0') {
623 rb->lcd_bitmap_part(sudoku_start,0,
624 BITMAP_HEIGHT*(state->startboard[r][c]-'0'),
625 BITMAP_STRIDE,
626 XOFS+cellxpos[c],YOFS+cellypos[r],
627 CELL_WIDTH,CELL_HEIGHT);
628 } else {
629 rb->lcd_bitmap_part(sudoku_normal,0,
630 BITMAP_HEIGHT*(state->currentboard[r][c]-'0'),
631 BITMAP_STRIDE,
632 XOFS+cellxpos[c],YOFS+cellypos[r],
633 CELL_WIDTH,CELL_HEIGHT);
634 }
635 }
636
637 rb->lcd_update_rect(cellxpos[c],cellypos[r],CELL_WIDTH,CELL_HEIGHT);
638}
639
640
641void display_board(struct sudoku_state_t* state)
642{
643 int r,c;
644
645 /* Clear the display buffer */
646 rb->lcd_clear_display();
647
648 /* Draw the gridlines - differently for different targets */
649
650#if LCD_HEIGHT > 64
651 /* Large targets - draw single/double lines */
652 for (r=0;r<9;r++) {
653 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-1);
654 rb->lcd_vline(XOFS+cellxpos[r]-1,YOFS,YOFS+BOARD_HEIGHT-1);
655 if ((r % 3)==0) {
656 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-2);
657 rb->lcd_vline(XOFS+cellxpos[r]-2,YOFS,YOFS+BOARD_HEIGHT-1);
658 }
659 }
660 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT);
661 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT+1);
662 rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFS,YOFS+BOARD_HEIGHT-1);
663 rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH+1,YOFS,YOFS+BOARD_HEIGHT-1);
664#elif (LCD_HEIGHT==64)
665 /* Small targets - draw dotted/single lines */
666 for (r=0;r<9;r++) {
667 if ((r % 3)==0) {
668 /* Solid Line */
669 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[r]-1);
670 rb->lcd_vline(XOFS+cellxpos[r]-1,YOFS,YOFS+BOARD_HEIGHT-1);
671 } else {
672 /* Dotted line */
673 for (c=XOFS;c<XOFS+BOARD_WIDTH;c+=2) {
674 rb->lcd_drawpixel(c,YOFS+cellypos[r]-1);
675 }
676 for (c=YOFS;c<YOFS+BOARD_HEIGHT;c+=2) {
677 rb->lcd_drawpixel(XOFS+cellxpos[r]-1,c);
678 }
679 }
680 }
681 rb->lcd_hline(XOFS,XOFS+BOARD_WIDTH-1,YOFS+cellypos[8]+CELL_HEIGHT);
682 rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFS,YOFS+BOARD_HEIGHT-1);
683#else
684#error SUDOKU: Unsupported LCD height
685#endif
686
687#ifdef SUDOKU_BUTTON_POSSIBLE
688 rb->lcd_vline(XOFSSCRATCHPAD,YOFS,YOFS+BOARD_HEIGHT-1);
689 rb->lcd_vline(XOFSSCRATCHPAD+CELL_WIDTH+1,YOFS,YOFS+BOARD_HEIGHT-1);
690 for (r=0;r<9;r++) {
691#if LCD_HEIGHT > 64
692 /* Large targets - draw single/double lines */
693 rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1,
694 YOFS+cellypos[r]-1);
695 if ((r % 3)==0)
696 rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1,
697 YOFS+cellypos[r]-2);
698#elif LCD_HEIGHT == 64
699 /* Small targets - draw dotted/single lines */
700 if ((r % 3)==0) {
701 /* Solid Line */
702 rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1,
703 YOFS+cellypos[r]-1);
704 } else {
705 /* Dotted line */
706 for (c=XOFSSCRATCHPAD;c<XOFSSCRATCHPAD+CELL_WIDTH+1;c+=2) {
707 rb->lcd_drawpixel(c,YOFS+cellypos[r]-1);
708 }
709 }
710#endif
711 if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r)))
712 rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE,
713 XOFSSCRATCHPAD+1,YOFS+cellypos[r-1],
714 CELL_WIDTH,CELL_HEIGHT);
715 }
716 rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1,
717 YOFS+cellypos[8]+CELL_HEIGHT);
718#if LCD_HEIGHT > 64
719 rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1,
720 YOFS+cellypos[8]+CELL_HEIGHT+1);
721#endif
722 if (state->possiblevals[state->y][state->x]&(1<<(r)))
723 rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE,
724 XOFSSCRATCHPAD+1,YOFS+cellypos[8],
725 CELL_WIDTH,CELL_HEIGHT);
726#endif
727
728 /* Draw the numbers */
729 for (r=0;r<9;r++) {
730 for (c=0;c<9;c++) {
731 /* We have four types of cell:
732 1) User-entered number
733 2) Starting number
734 3) Cursor in cell
735 */
736
737 if ((r==state->y) && (c==state->x)) {
738 rb->lcd_bitmap_part(sudoku_inverse,0,
739 BITMAP_HEIGHT*(state->currentboard[r][c]-
740 '0'),
741 BITMAP_STRIDE,
742 XOFS+cellxpos[c],YOFS+cellypos[r],
743 CELL_WIDTH,CELL_HEIGHT);
744 } else {
745 if (state->startboard[r][c]!='0') {
746 rb->lcd_bitmap_part(sudoku_start,0,
747 BITMAP_HEIGHT*(state->startboard[r][c]-
748 '0'),
749 BITMAP_STRIDE,
750 XOFS+cellxpos[c],YOFS+cellypos[r],
751 CELL_WIDTH,CELL_HEIGHT);
752 } else {
753 rb->lcd_bitmap_part(sudoku_normal,0,
754 BITMAP_HEIGHT*
755 (state->currentboard[r][c]-'0'),
756 BITMAP_STRIDE,
757 XOFS+cellxpos[c],YOFS+cellypos[r],
758 CELL_WIDTH,CELL_HEIGHT);
759 }
760 }
761 }
762 }
763
764 /* update the screen */
765 rb->lcd_update();
766}
767
768/* Check the status of the board, assuming a change at the cursor location */
769bool check_status(struct sudoku_state_t* state)
770{
771 int check[9];
772 int r,c;
773 int r1,c1;
774 int cell;
775
776 /* First, check the column */
777 for (cell=0;cell<9;cell++) {
778 check[cell]=0;
779 }
780 for (r=0;r<9;r++) {
781 cell=state->currentboard[r][state->x];
782 if (cell!='0') {
783 if (check[cell-'1']==1) {
784 return true;
785 }
786 check[cell-'1']=1;
787 }
788 }
789
790 /* Second, check the row */
791 for (cell=0;cell<9;cell++) {
792 check[cell]=0;
793 }
794 for (c=0;c<9;c++) {
795 cell=state->currentboard[state->y][c];
796 if (cell!='0') {
797 if (check[cell-'1']==1) {
798 return true;
799 }
800 check[cell-'1']=1;
801 }
802 }
803
804 /* Finally, check the 3x3 sub-grid */
805 for (cell=0;cell<9;cell++) {
806 check[cell]=0;
807 }
808 r1=(state->y/3)*3;
809 c1=(state->x/3)*3;
810 for (r=r1;r<r1+3;r++) {
811 for (c=c1;c<c1+3;c++) {
812 cell=state->currentboard[r][c];
813 if (cell!='0') {
814 if (check[cell-'1']==1) {
815 return true;
816 }
817 check[cell-'1']=1;
818 }
819 }
820 }
821
822 /* We passed all the checks :) */
823
824 return false;
825}
826
827void sudoku_generate(struct sudoku_state_t* state)
828{
829 char* difficulty;
830 char str[80];
831
832 clear_state(state);
833 display_board(state);
834 rb->splash(0, true, "Generating...");
835
836 sudoku_generate_board(state,&difficulty);
837
838 rb->snprintf(str,sizeof(str),"Difficulty: %s",difficulty);
839 display_board(state);
840 rb->splash(3*HZ, true, str);
841 rb->strncpy(state->filename,GAME_FILE,MAX_PATH);
842}
843
844int sudoku_menu_cb(int key, int m)
845{
846 (void)m;
847 switch(key)
848 {
849#ifdef MENU_ENTER2
850 case MENU_ENTER2:
851#endif
852 case MENU_ENTER:
853 key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */
854 break;
855
856#ifdef MENU_ENTER2
857 case MENU_ENTER2 | BUTTON_REL:
858#endif
859 case MENU_ENTER | BUTTON_REL:
860 key = MENU_ENTER; /* fake downpress, next menu doesn't like release */
861 break;
862 }
863
864 return key;
865}
866
867bool sudoku_menu(struct sudoku_state_t* state)
868{
869 int m;
870 int result;
871
872 static const struct menu_item items[] = {
873 { "Save", NULL },
874 { "Reload", NULL },
875 { "Clear", NULL },
876 { "Solve", NULL },
877 { "Generate", NULL },
878 { "New", NULL },
879 { "Quit", NULL },
880 };
881
882 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
883 sudoku_menu_cb, NULL, NULL, NULL);
884
885 result=rb->menu_show(m);
886
887 switch (result) {
888 case 0: /* Save state */
889 save_sudoku(state);
890 break;
891
892 case 1: /* Restore state */
893 restore_state(state);
894 break;
895
896 case 2: /* Clear all */
897 clear_board(state);
898 break;
899
900 case 3: /* Solve */
901 sudoku_solve(state);
902 break;
903
904 case 4: /* Generate Game */
905 sudoku_generate(state);
906 break;
907
908 case 5: /* Create a new game manually */
909 clear_state(state);
910 state->editmode=1;
911 break;
912
913 case 6: /* Quit */
914 save_sudoku(state);
915 rb->menu_exit(m);
916 return true;
917 break;
918
919 default:
920 break;
921 }
922
923 rb->menu_exit(m);
924
925 return (result==MENU_ATTACHED_USB);
926}
927
928void move_cursor(struct sudoku_state_t* state, int newx, int newy)
929{
930 int oldx, oldy;
931
932 /* Check that the character at the cursor position is legal */
933 if (check_status(state)) {
934 rb->splash(HZ*2, true, "Illegal move!");
935 /* Ignore any button presses during the splash */
936 rb->button_clear_queue();
937 return;
938 }
939
940 /* Move Cursor */
941 oldx=state->x;
942 oldy=state->y;
943 state->x=newx;
944 state->y=newy;
945
946 /* Redraw current and old cells */
947 update_cell(state,oldx,oldy);
948 update_cell(state,newx,newy);
949}
950
951/* plugin entry point */
952enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
953{
954 bool exit;
955 int button;
956 int lastbutton = BUTTON_NONE;
957 long ticks;
958 struct sudoku_state_t state;
959
960 /* plugin init */
961 rb = api;
962 /* end of plugin init */
963
964 clear_state(&state);
965
966 if (parameter==NULL) {
967 /* We have been started as a plugin - try default sudoku.ss */
968 if (!load_sudoku(&state,GAME_FILE)) {
969 /* No previous game saved, generate one */
970 sudoku_generate(&state);
971 }
972 } else {
973 if (!load_sudoku(&state,(char*)parameter)) {
974 rb->splash(HZ*2, true, "Load error");
975 return(PLUGIN_ERROR);
976 }
977 }
978
979 display_board(&state);
980
981 /* The main game loop */
982 exit=false;
983 ticks=0;
984 while(!exit) {
985 button = rb->button_get(true);
986
987 switch(button){
988 /* Exit game */
989 case SUDOKU_BUTTON_QUIT:
990 exit=1;
991 break;
992
993 /* Increment digit */
994#ifdef SUDOKU_BUTTON_ALTTOGGLE
995 case SUDOKU_BUTTON_ALTTOGGLE | BUTTON_REPEAT:
996#endif
997 case SUDOKU_BUTTON_TOGGLE | BUTTON_REPEAT:
998 /* Slow down the repeat speed to 1/3 second */
999 if ((*rb->current_tick-ticks) < (HZ/3)) {
1000 break;
1001 }
1002
1003#ifdef SUDOKU_BUTTON_ALTTOGGLE
1004 case SUDOKU_BUTTON_ALTTOGGLE:
1005#endif
1006 case SUDOKU_BUTTON_TOGGLE:
1007#ifdef SUDOKU_BUTTON_TOGGLE_PRE
1008 if ((button == SUDOKU_BUTTON_TOGGLE)
1009 && (lastbutton != SUDOKU_BUTTON_TOGGLE_PRE))
1010 break;
1011#endif
1012 /* Increment digit */
1013 ticks=*rb->current_tick;
1014 if (state.editmode) {
1015 if (state.startboard[state.y][state.x]=='9') {
1016 state.startboard[state.y][state.x]='0';
1017 state.currentboard[state.y][state.x]='0';
1018 } else {
1019 state.startboard[state.y][state.x]++;
1020 state.currentboard[state.y][state.x]++;
1021 }
1022 } else {
1023 if (state.startboard[state.y][state.x]=='0') {
1024 if (state.currentboard[state.y][state.x]=='9') {
1025 state.currentboard[state.y][state.x]='0';
1026 } else {
1027 state.currentboard[state.y][state.x]++;
1028 }
1029 }
1030 }
1031 update_cell(&state,state.y,state.x);
1032 break;
1033
1034 /* move cursor left */
1035 case BUTTON_LEFT:
1036 case (BUTTON_LEFT | BUTTON_REPEAT):
1037 if (state.x==0) {
1038 move_cursor(&state,8,state.y);
1039 } else {
1040 move_cursor(&state,state.x-1,state.y);
1041 }
1042 break;
1043
1044 /* move cursor right */
1045 case BUTTON_RIGHT:
1046 case (BUTTON_RIGHT | BUTTON_REPEAT):
1047 if (state.x==8) {
1048 move_cursor(&state,0,state.y);
1049 } else {
1050 move_cursor(&state,state.x+1,state.y);
1051 }
1052 break;
1053
1054 /* move cursor up */
1055 case SUDOKU_BUTTON_UP:
1056 case (SUDOKU_BUTTON_UP | BUTTON_REPEAT):
1057 if (state.y==0) {
1058 move_cursor(&state,state.x,8);
1059 } else {
1060 move_cursor(&state,state.x,state.y-1);
1061 }
1062 break;
1063
1064 /* move cursor down */
1065 case SUDOKU_BUTTON_DOWN:
1066 case (SUDOKU_BUTTON_DOWN | BUTTON_REPEAT):
1067 if (state.y==8) {
1068 move_cursor(&state,state.x,0);
1069 } else {
1070 move_cursor(&state,state.x,state.y+1);
1071 }
1072 break;
1073
1074 case SUDOKU_BUTTON_MENU:
1075#ifdef SUDOKU_BUTTON_MENU_PRE
1076 if (lastbutton != SUDOKU_BUTTON_MENU_PRE)
1077 break;
1078#endif
1079 /* Don't let the user leave a game in a bad state */
1080 if (check_status(&state)) {
1081 rb->splash(HZ*2, true, "Illegal move!");
1082 /* Ignore any button presses during the splash */
1083 rb->button_clear_queue();
1084 } else {
1085 if (state.editmode) {
1086 rb->kbd_input(state.filename,MAX_PATH);
1087 if (save_sudoku(&state)) {
1088 state.editmode=0;
1089 } else {
1090 rb->splash(HZ*2, true, "Save failed");
1091 }
1092 } else {
1093 if (sudoku_menu(&state)) {
1094 return PLUGIN_USB_CONNECTED;
1095 }
1096 }
1097 }
1098 break;
1099#ifdef SUDOKU_BUTTON_POSSIBLE
1100 case SUDOKU_BUTTON_POSSIBLE:
1101 /* Toggle current number in the possiblevals structure */
1102 if (state.currentboard[state.y][state.x]!='0') {
1103 state.possiblevals[state.y][state.x]^=
1104 (1 << (state.currentboard[state.y][state.x] - '0'));
1105 }
1106 break;
1107#endif
1108 default:
1109 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) {
1110 /* Quit if USB has been connected */
1111 return PLUGIN_USB_CONNECTED;
1112 }
1113 break;
1114 }
1115 if (button != BUTTON_NONE)
1116 lastbutton = button;
1117
1118 display_board(&state);
1119 }
1120
1121 return PLUGIN_OK;
1122}
1123
1124#endif
diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h
new file mode 100644
index 0000000000..cdad581767
--- /dev/null
+++ b/apps/plugins/sudoku/sudoku.h
@@ -0,0 +1,104 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _SUDOKU_H
21#define _SUDOKU_H
22
23#include "plugin.h"
24
25/* here is a global api struct pointer. while not strictly necessary,
26 it's nice not to have to pass the api pointer in all function calls
27 in the plugin */
28
29#define STATE_FILE PLUGIN_DIR "/sudoku.state"
30#define GAME_FILE PLUGIN_DIR "/sudoku.ss"
31
32/* variable button definitions */
33#if CONFIG_KEYPAD == RECORDER_PAD
34#define SUDOKU_BUTTON_QUIT BUTTON_OFF
35#define SUDOKU_BUTTON_UP BUTTON_UP
36#define SUDOKU_BUTTON_DOWN BUTTON_DOWN
37#define SUDOKU_BUTTON_TOGGLE BUTTON_PLAY
38#define SUDOKU_BUTTON_MENU BUTTON_F1
39#define SUDOKU_BUTTON_POSSIBLE BUTTON_F2
40
41#elif CONFIG_KEYPAD == ONDIO_PAD
42#define SUDOKU_BUTTON_QUIT BUTTON_OFF
43#define SUDOKU_BUTTON_UP BUTTON_UP
44#define SUDOKU_BUTTON_DOWN BUTTON_DOWN
45#define SUDOKU_BUTTON_ALTTOGGLE (BUTTON_MENU | BUTTON_DOWN)
46#define SUDOKU_BUTTON_TOGGLE_PRE BUTTON_MENU
47#define SUDOKU_BUTTON_TOGGLE (BUTTON_MENU | BUTTON_REL)
48#define SUDOKU_BUTTON_MENU_PRE BUTTON_MENU
49#define SUDOKU_BUTTON_MENU (BUTTON_MENU | BUTTON_REPEAT)
50#define SUDOKU_BUTTON_POSSIBLE (BUTTON_MENU | BUTTON_LEFT)
51
52#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
53 (CONFIG_KEYPAD == IRIVER_H300_PAD)
54#define SUDOKU_BUTTON_QUIT BUTTON_OFF
55#define SUDOKU_BUTTON_UP BUTTON_UP
56#define SUDOKU_BUTTON_DOWN BUTTON_DOWN
57#define SUDOKU_BUTTON_ALTTOGGLE BUTTON_ON
58#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT
59#define SUDOKU_BUTTON_MENU BUTTON_MODE
60#define SUDOKU_BUTTON_POSSIBLE BUTTON_REC
61
62#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
63 (CONFIG_KEYPAD == IPOD_3G_PAD)
64#define SUDOKU_BUTTON_QUIT (BUTTON_SELECT | BUTTON_MENU)
65#define SUDOKU_BUTTON_UP BUTTON_SCROLL_BACK
66#define SUDOKU_BUTTON_DOWN BUTTON_SCROLL_FWD
67#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT
68#define SUDOKU_BUTTON_MENU BUTTON_MENU
69#define SUDOKU_BUTTON_POSSIBLE (BUTTON_SELECT | BUTTON_LEFT)
70
71#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
72#define SUDOKU_BUTTON_QUIT BUTTON_POWER
73#define SUDOKU_BUTTON_UP BUTTON_UP
74#define SUDOKU_BUTTON_DOWN BUTTON_DOWN
75#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT
76#define SUDOKU_BUTTON_MENU BUTTON_PLAY
77#define SUDOKU_BUTTON_POSSIBLE BUTTON_REC
78
79#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
80#define SUDOKU_BUTTON_QUIT BUTTON_A
81#define SUDOKU_BUTTON_UP BUTTON_UP
82#define SUDOKU_BUTTON_DOWN BUTTON_DOWN
83#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT
84#define SUDOKU_BUTTON_MENU BUTTON_MENU
85#define SUDOKU_BUTTON_POSSIBLE BUTTON_POWER
86
87#elif
88 #error SUDOKU: Unsupported keypad
89#endif
90
91struct sudoku_state_t {
92 char filename[MAX_PATH]; /* Filename */
93 char startboard[9][9]; /* The initial state of the game */
94 char currentboard[9][9]; /* The current state of the game */
95 char savedboard[9][9]; /* Cached copy of saved state */
96 int x,y; /* Cursor position */
97 int editmode; /* We are editing the start board */
98#ifdef SUDOKU_BUTTON_POSSIBLE
99 short possiblevals[9][9]; /* possible values a cell could be, user sets them */
100#endif
101};
102
103
104#endif
diff --git a/apps/plugins/sudoku/templates.c b/apps/plugins/sudoku/templates.c
new file mode 100644
index 0000000000..9f2117d8d4
--- /dev/null
+++ b/apps/plugins/sudoku/templates.c
@@ -0,0 +1,2877 @@
1/* Template boards for the game generator */
2
3#include "templates.h"
4
5const unsigned short templates[NUM_TEMPLATES][9] = {
6{
7 0x016d, /* #.##.##.# */
8 0x006c, /* ..##.##.. */
9 0x0089, /* .#...#..# */
10 0x0116, /* #...#.##. */
11 0x0082, /* .#.....#. */
12 0x00d1, /* .##.#...# */
13 0x0122, /* #..#...#. */
14 0x006c, /* ..##.##.. */
15 0x016d, /* #.##.##.# */
16},
17{
18 0x0143, /* #.#....## */
19 0x0031, /* ...##...# */
20 0x01d1, /* ###.#...# */
21 0x0023, /* ...#...## */
22 0x016d, /* #.##.##.# */
23 0x0188, /* ##...#... */
24 0x0117, /* #...#.### */
25 0x0118, /* #...##... */
26 0x0185, /* ##....#.# */
27},
28{
29 0x0185, /* ##....#.# */
30 0x00e3, /* .###...## */
31 0x0132, /* #..##..#. */
32 0x002e, /* ...#.###. */
33 0x0054, /* ..#.#.#.. */
34 0x00e8, /* .###.#... */
35 0x0099, /* .#..##..# */
36 0x018e, /* ##...###. */
37 0x0143, /* #.#....## */
38},
39{
40 0x0189, /* ##...#..# */
41 0x001a, /* ....##.#. */
42 0x01e2, /* ####...#. */
43 0x0055, /* ..#.#.#.# */
44 0x0129, /* #..#.#..# */
45 0x0154, /* #.#.#.#.. */
46 0x008f, /* .#...#### */
47 0x00b0, /* .#.##.... */
48 0x0123, /* #..#...## */
49},
50{
51 0x018b, /* ##...#.## */
52 0x0199, /* ##..##..# */
53 0x0014, /* ....#.#.. */
54 0x008e, /* .#...###. */
55 0x006c, /* ..##.##.. */
56 0x00e2, /* .###...#. */
57 0x0050, /* ..#.#.... */
58 0x0133, /* #..##..## */
59 0x01a3, /* ##.#...## */
60},
61{
62 0x002e, /* ...#.###. */
63 0x018a, /* ##...#.#. */
64 0x0164, /* #.##..#.. */
65 0x01ad, /* ##.#.##.# */
66 0x0000, /* ......... */
67 0x016b, /* #.##.#.## */
68 0x004d, /* ..#..##.# */
69 0x00a3, /* .#.#...## */
70 0x00e8, /* .###.#... */
71},
72{
73 0x005c, /* ..#.###.. */
74 0x01a8, /* ##.#.#... */
75 0x00d4, /* .##.#.#.. */
76 0x0195, /* ##..#.#.# */
77 0x0082, /* .#.....#. */
78 0x0153, /* #.#.#..## */
79 0x0056, /* ..#.#.##. */
80 0x002b, /* ...#.#.## */
81 0x0074, /* ..###.#.. */
82},
83{
84 0x006c, /* ..##.##.. */
85 0x00e2, /* .###...#. */
86 0x0113, /* #...#..## */
87 0x0113, /* #...#..## */
88 0x006c, /* ..##.##.. */
89 0x0191, /* ##..#...# */
90 0x0191, /* ##..#...# */
91 0x008e, /* .#...###. */
92 0x006c, /* ..##.##.. */
93},
94{
95 0x0098, /* .#..##... */
96 0x0195, /* ##..#.#.# */
97 0x0066, /* ..##..##. */
98 0x00cb, /* .##..#.## */
99 0x0028, /* ...#.#... */
100 0x01a6, /* ##.#..##. */
101 0x00cc, /* .##..##.. */
102 0x0153, /* #.#.#..## */
103 0x0032, /* ...##..#. */
104},
105{
106 0x0164, /* #.##..#.. */
107 0x00a5, /* .#.#..#.# */
108 0x00aa, /* .#.#.#.#. */
109 0x005c, /* ..#.###.. */
110 0x0183, /* ##.....## */
111 0x0074, /* ..###.#.. */
112 0x00aa, /* .#.#.#.#. */
113 0x014a, /* #.#..#.#. */
114 0x004d, /* ..#..##.# */
115},
116{
117 0x0144, /* #.#...#.. */
118 0x00dc, /* .##.###.. */
119 0x00aa, /* .#.#.#.#. */
120 0x01a2, /* ##.#...#. */
121 0x0038, /* ...###... */
122 0x008b, /* .#...#.## */
123 0x00aa, /* .#.#.#.#. */
124 0x0076, /* ..###.##. */
125 0x0045, /* ..#...#.# */
126},
127{
128 0x0113, /* #...#..## */
129 0x01a2, /* ##.#...#. */
130 0x006c, /* ..##.##.. */
131 0x0056, /* ..#.#.##. */
132 0x0129, /* #..#.#..# */
133 0x00d4, /* .##.#.#.. */
134 0x006c, /* ..##.##.. */
135 0x008b, /* .#...#.## */
136 0x0191, /* ##..#...# */
137},
138{
139 0x006a, /* ..##.#.#. */
140 0x0174, /* #.###.#.. */
141 0x0083, /* .#.....## */
142 0x012b, /* #..#.#.## */
143 0x0092, /* .#..#..#. */
144 0x01a9, /* ##.#.#..# */
145 0x0182, /* ##.....#. */
146 0x005d, /* ..#.###.# */
147 0x00ac, /* .#.#.##.. */
148},
149{
150 0x00aa, /* .#.#.#.#. */
151 0x0129, /* #..#.#..# */
152 0x0092, /* .#..#..#. */
153 0x0044, /* ..#...#.. */
154 0x0183, /* ##.....## */
155 0x0044, /* ..#...#.. */
156 0x0092, /* .#..#..#. */
157 0x0129, /* #..#.#..# */
158 0x00aa, /* .#.#.#.#. */
159},
160{
161 0x00aa, /* .#.#.#.#. */
162 0x0101, /* #.......# */
163 0x006c, /* ..##.##.. */
164 0x00ba, /* .#.###.#. */
165 0x0082, /* .#.....#. */
166 0x00ba, /* .#.###.#. */
167 0x006c, /* ..##.##.. */
168 0x0101, /* #.......# */
169 0x00aa, /* .#.#.#.#. */
170},
171{
172 0x00ba, /* .#.###.#. */
173 0x0101, /* #.......# */
174 0x0044, /* ..#...#.. */
175 0x01ab, /* ##.#.#.## */
176 0x0010, /* ....#.... */
177 0x01ab, /* ##.#.#.## */
178 0x0044, /* ..#...#.. */
179 0x0101, /* #.......# */
180 0x00ba, /* .#.###.#. */
181},
182{
183 0x0082, /* .#.....#. */
184 0x00d6, /* .##.#.##. */
185 0x0129, /* #..#.#..# */
186 0x006c, /* ..##.##.. */
187 0x0000, /* ......... */
188 0x006c, /* ..##.##.. */
189 0x0129, /* #..#.#..# */
190 0x00d6, /* .##.#.##. */
191 0x0082, /* .#.....#. */
192},
193{
194 0x000a, /* .....#.#. */
195 0x018c, /* ##...##.. */
196 0x00a4, /* .#.#..#.. */
197 0x009a, /* .#..##.#. */
198 0x0101, /* #.......# */
199 0x00b2, /* .#.##..#. */
200 0x004a, /* ..#..#.#. */
201 0x0063, /* ..##...## */
202 0x00a0, /* .#.#..... */
203},
204{
205 0x00aa, /* .#.#.#.#. */
206 0x0101, /* #.......# */
207 0x0054, /* ..#.#.#.. */
208 0x00d6, /* .##.#.##. */
209 0x0092, /* .#..#..#. */
210 0x00d6, /* .##.#.##. */
211 0x0054, /* ..#.#.#.. */
212 0x0101, /* #.......# */
213 0x00aa, /* .#.#.#.#. */
214},
215{
216 0x00c6, /* .##...##. */
217 0x0028, /* ...#.#... */
218 0x0193, /* ##..#..## */
219 0x006c, /* ..##.##.. */
220 0x0101, /* #.......# */
221 0x006c, /* ..##.##.. */
222 0x0193, /* ##..#..## */
223 0x0028, /* ...#.#... */
224 0x00c6, /* .##...##. */
225},
226{
227 0x01b8, /* ##.###... */
228 0x0001, /* ........# */
229 0x00e4, /* .###..#.. */
230 0x0111, /* #...#...# */
231 0x0044, /* ..#...#.. */
232 0x0111, /* #...#...# */
233 0x004e, /* ..#..###. */
234 0x0100, /* #........ */
235 0x003b, /* ...###.## */
236},
237{
238 0x0000, /* ......... */
239 0x00aa, /* .#.#.#.#. */
240 0x00ee, /* .###.###. */
241 0x0129, /* #..#.#..# */
242 0x006c, /* ..##.##.. */
243 0x0129, /* #..#.#..# */
244 0x00ee, /* .###.###. */
245 0x00aa, /* .#.#.#.#. */
246 0x0000, /* ......... */
247},
248{
249 0x0031, /* ...##...# */
250 0x0154, /* #.#.#.#.. */
251 0x0009, /* .....#..# */
252 0x00f4, /* .####.#.. */
253 0x0044, /* ..#...#.. */
254 0x005e, /* ..#.####. */
255 0x0120, /* #..#..... */
256 0x0055, /* ..#.#.#.# */
257 0x0118, /* #...##... */
258},
259{
260 0x00b0, /* .#.##.... */
261 0x00a3, /* .#.#...## */
262 0x0064, /* ..##..#.. */
263 0x0007, /* ......### */
264 0x0111, /* #...#...# */
265 0x01c0, /* ###...... */
266 0x004c, /* ..#..##.. */
267 0x018a, /* ##...#.#. */
268 0x001a, /* ....##.#. */
269},
270{
271 0x0129, /* #..#.#..# */
272 0x0048, /* ..#..#... */
273 0x0012, /* ....#..#. */
274 0x0191, /* ##..#...# */
275 0x006c, /* ..##.##.. */
276 0x0113, /* #...#..## */
277 0x0090, /* .#..#.... */
278 0x0024, /* ...#..#.. */
279 0x0129, /* #..#.#..# */
280},
281{
282 0x00a0, /* .#.#..... */
283 0x0051, /* ..#.#...# */
284 0x005e, /* ..#.####. */
285 0x0041, /* ..#.....# */
286 0x00d6, /* .##.#.##. */
287 0x0104, /* #.....#.. */
288 0x00f4, /* .####.#.. */
289 0x0114, /* #...#.#.. */
290 0x000a, /* .....#.#. */
291},
292{
293 0x0008, /* .....#... */
294 0x0090, /* .#..#.... */
295 0x001f, /* ....##### */
296 0x00d3, /* .##.#..## */
297 0x006c, /* ..##.##.. */
298 0x0196, /* ##..#.##. */
299 0x01f0, /* #####.... */
300 0x0012, /* ....#..#. */
301 0x0020, /* ...#..... */
302},
303{
304 0x0145, /* #.#...#.# */
305 0x0155, /* #.#.#.#.# */
306 0x0028, /* ...#.#... */
307 0x006c, /* ..##.##.. */
308 0x0000, /* ......... */
309 0x006c, /* ..##.##.. */
310 0x0028, /* ...#.#... */
311 0x0155, /* #.#.#.#.# */
312 0x0145, /* #.#...#.# */
313},
314{
315 0x0006, /* ......##. */
316 0x0170, /* #.###.... */
317 0x0031, /* ...##...# */
318 0x00c3, /* .##....## */
319 0x0101, /* #.......# */
320 0x0186, /* ##....##. */
321 0x0118, /* #...##... */
322 0x001d, /* ....###.# */
323 0x00c0, /* .##...... */
324},
325{
326 0x0038, /* ...###... */
327 0x0129, /* #..#.#..# */
328 0x0044, /* ..#...#.. */
329 0x0145, /* #.#...#.# */
330 0x0082, /* .#.....#. */
331 0x0145, /* #.#...#.# */
332 0x0044, /* ..#...#.. */
333 0x0129, /* #..#.#..# */
334 0x0038, /* ...###... */
335},
336{
337 0x0082, /* .#.....#. */
338 0x0111, /* #...#...# */
339 0x0129, /* #..#.#..# */
340 0x006c, /* ..##.##.. */
341 0x0010, /* ....#.... */
342 0x006c, /* ..##.##.. */
343 0x0129, /* #..#.#..# */
344 0x0111, /* #...#...# */
345 0x0082, /* .#.....#. */
346},
347{
348 0x0183, /* ##.....## */
349 0x0092, /* .#..#..#. */
350 0x006c, /* ..##.##.. */
351 0x0028, /* ...#.#... */
352 0x0101, /* #.......# */
353 0x0028, /* ...#.#... */
354 0x006c, /* ..##.##.. */
355 0x0092, /* .#..#..#. */
356 0x0183, /* ##.....## */
357},
358{
359 0x00d0, /* .##.#.... */
360 0x0109, /* #....#..# */
361 0x0184, /* ##....#.. */
362 0x0160, /* #.##..... */
363 0x0044, /* ..#...#.. */
364 0x000d, /* .....##.# */
365 0x0043, /* ..#....## */
366 0x0121, /* #..#....# */
367 0x0016, /* ....#.##. */
368},
369{
370 0x0060, /* ..##..... */
371 0x0140, /* #.#...... */
372 0x0093, /* .#..#..## */
373 0x010e, /* #....###. */
374 0x0054, /* ..#.#.#.. */
375 0x00e1, /* .###....# */
376 0x0192, /* ##..#..#. */
377 0x0005, /* ......#.# */
378 0x000c, /* .....##.. */
379},
380{
381 0x001a, /* ....##.#. */
382 0x0091, /* .#..#...# */
383 0x00a1, /* .#.#....# */
384 0x00c2, /* .##....#. */
385 0x0028, /* ...#.#... */
386 0x0086, /* .#....##. */
387 0x010a, /* #....#.#. */
388 0x0112, /* #...#..#. */
389 0x00b0, /* .#.##.... */
390},
391{
392 0x0162, /* #.##...#. */
393 0x0049, /* ..#..#..# */
394 0x004c, /* ..#..##.. */
395 0x0016, /* ....#.##. */
396 0x0000, /* ......... */
397 0x00d0, /* .##.#.... */
398 0x0064, /* ..##..#.. */
399 0x0124, /* #..#..#.. */
400 0x008d, /* .#...##.# */
401},
402{
403 0x0025, /* ...#..#.# */
404 0x0050, /* ..#.#.... */
405 0x0053, /* ..#.#..## */
406 0x0032, /* ...##..#. */
407 0x0028, /* ...#.#... */
408 0x0098, /* .#..##... */
409 0x0194, /* ##..#.#.. */
410 0x0014, /* ....#.#.. */
411 0x0148, /* #.#..#... */
412},
413{
414 0x0129, /* #..#.#..# */
415 0x0000, /* ......... */
416 0x00c6, /* .##...##. */
417 0x00aa, /* .#.#.#.#. */
418 0x0092, /* .#..#..#. */
419 0x00aa, /* .#.#.#.#. */
420 0x00c6, /* .##...##. */
421 0x0000, /* ......... */
422 0x0129, /* #..#.#..# */
423},
424{
425 0x0095, /* .#..#.#.# */
426 0x002b, /* ...#.#.## */
427 0x0000, /* ......... */
428 0x00ca, /* .##..#.#. */
429 0x0028, /* ...#.#... */
430 0x00a6, /* .#.#..##. */
431 0x0000, /* ......... */
432 0x01a8, /* ##.#.#... */
433 0x0153, /* #.#.#..## */
434},
435{
436 0x0008, /* .....#... */
437 0x0153, /* #.#.#..## */
438 0x0070, /* ..###.... */
439 0x0141, /* #.#.....# */
440 0x0082, /* .#.....#. */
441 0x0105, /* #.....#.# */
442 0x001c, /* ....###.. */
443 0x0195, /* ##..#.#.# */
444 0x0020, /* ...#..... */
445},
446{
447 0x000c, /* .....##.. */
448 0x0100, /* #........ */
449 0x0076, /* ..###.##. */
450 0x0013, /* ....#..## */
451 0x0101, /* #.......# */
452 0x0190, /* ##..#.... */
453 0x00dc, /* .##.###.. */
454 0x0001, /* ........# */
455 0x0060, /* ..##..... */
456},
457{
458 0x00ba, /* .#.###.#. */
459 0x0101, /* #.......# */
460 0x0044, /* ..#...#.. */
461 0x00aa, /* .#.#.#.#. */
462 0x0000, /* ......... */
463 0x00aa, /* .#.#.#.#. */
464 0x0044, /* ..#...#.. */
465 0x0101, /* #.......# */
466 0x00ba, /* .#.###.#. */
467},
468{
469 0x0189, /* ##...#..# */
470 0x00a3, /* .#.#...## */
471 0x0010, /* ....#.... */
472 0x0102, /* #......#. */
473 0x0054, /* ..#.#.#.. */
474 0x0081, /* .#......# */
475 0x0010, /* ....#.... */
476 0x018a, /* ##...#.#. */
477 0x0123, /* #..#...## */
478},
479{
480 0x0189, /* ##...#..# */
481 0x00a3, /* .#.#...## */
482 0x0010, /* ....#.... */
483 0x0102, /* #......#. */
484 0x0054, /* ..#.#.#.. */
485 0x0081, /* .#......# */
486 0x0010, /* ....#.... */
487 0x018a, /* ##...#.#. */
488 0x0123, /* #..#...## */
489},
490{
491 0x0044, /* ..#...#.. */
492 0x00ee, /* .###.###. */
493 0x0183, /* ##.....## */
494 0x0038, /* ...###... */
495 0x0010, /* ....#.... */
496 0x0038, /* ...###... */
497 0x0183, /* ##.....## */
498 0x00ee, /* .###.###. */
499 0x0044, /* ..#...#.. */
500},
501{
502 0x0064, /* ..##..#.. */
503 0x0096, /* .#..#.##. */
504 0x0081, /* .#......# */
505 0x010a, /* #....#.#. */
506 0x0010, /* ....#.... */
507 0x00a1, /* .#.#....# */
508 0x0102, /* #......#. */
509 0x00d2, /* .##.#..#. */
510 0x004c, /* ..#..##.. */
511},
512{
513 0x0180, /* ##....... */
514 0x0190, /* ##..#.... */
515 0x00a8, /* .#.#.#... */
516 0x0124, /* #..#..#.. */
517 0x0145, /* #.#...#.# */
518 0x0049, /* ..#..#..# */
519 0x002a, /* ...#.#.#. */
520 0x0013, /* ....#..## */
521 0x0003, /* .......## */
522},
523{
524 0x010d, /* #....##.# */
525 0x0104, /* #.....#.. */
526 0x00a2, /* .#.#...#. */
527 0x0038, /* ...###... */
528 0x0044, /* ..#...#.. */
529 0x0038, /* ...###... */
530 0x008a, /* .#...#.#. */
531 0x0041, /* ..#.....# */
532 0x0161, /* #.##....# */
533},
534{
535 0x004c, /* ..#..##.. */
536 0x00b2, /* .#.##..#. */
537 0x0165, /* #.##..#.# */
538 0x0116, /* #...#.##. */
539 0x00aa, /* .#.#.#.#. */
540 0x00d1, /* .##.#...# */
541 0x014d, /* #.#..##.# */
542 0x009a, /* .#..##.#. */
543 0x0064, /* ..##..#.. */
544},
545{
546 0x0111, /* #...#...# */
547 0x0092, /* .#..#..#. */
548 0x0129, /* #..#.#..# */
549 0x0145, /* #.#...#.# */
550 0x006c, /* ..##.##.. */
551 0x0145, /* #.#...#.# */
552 0x0129, /* #..#.#..# */
553 0x0092, /* .#..#..#. */
554 0x0111, /* #...#...# */
555},
556{
557 0x00ac, /* .#.#.##.. */
558 0x0182, /* ##.....#. */
559 0x0032, /* ...##..#. */
560 0x001c, /* ....###.. */
561 0x0000, /* ......... */
562 0x0070, /* ..###.... */
563 0x0098, /* .#..##... */
564 0x0083, /* .#.....## */
565 0x006a, /* ..##.#.#. */
566},
567{
568 0x0052, /* ..#.#..#. */
569 0x0008, /* .....#... */
570 0x012a, /* #..#.#.#. */
571 0x01a4, /* ##.#..#.. */
572 0x0082, /* .#.....#. */
573 0x004b, /* ..#..#.## */
574 0x00a9, /* .#.#.#..# */
575 0x0020, /* ...#..... */
576 0x0094, /* .#..#.#.. */
577},
578{
579 0x0049, /* ..#..#..# */
580 0x0030, /* ...##.... */
581 0x0026, /* ...#..##. */
582 0x00c6, /* .##...##. */
583 0x0010, /* ....#.... */
584 0x00c6, /* .##...##. */
585 0x00c8, /* .##..#... */
586 0x0018, /* ....##... */
587 0x0124, /* #..#..#.. */
588},
589{
590 0x0029, /* ...#.#..# */
591 0x01a4, /* ##.#..#.. */
592 0x00a0, /* .#.#..... */
593 0x0005, /* ......#.# */
594 0x0183, /* ##.....## */
595 0x0140, /* #.#...... */
596 0x000a, /* .....#.#. */
597 0x004b, /* ..#..#.## */
598 0x0128, /* #..#.#... */
599},
600{
601 0x0014, /* ....#.#.. */
602 0x0164, /* #.##..#.. */
603 0x0161, /* #.##....# */
604 0x0040, /* ..#...... */
605 0x0038, /* ...###... */
606 0x0004, /* ......#.. */
607 0x010d, /* #....##.# */
608 0x004d, /* ..#..##.# */
609 0x0050, /* ..#.#.... */
610},
611{
612 0x0101, /* #.......# */
613 0x00c6, /* .##...##. */
614 0x0038, /* ...###... */
615 0x007c, /* ..#####.. */
616 0x0183, /* ##.....## */
617 0x007c, /* ..#####.. */
618 0x0038, /* ...###... */
619 0x00c6, /* .##...##. */
620 0x0101, /* #.......# */
621},
622{
623 0x0020, /* ...#..... */
624 0x0054, /* ..#.#.#.. */
625 0x0063, /* ..##...## */
626 0x0149, /* #.#..#..# */
627 0x0101, /* #.......# */
628 0x0125, /* #..#..#.# */
629 0x018c, /* ##...##.. */
630 0x0054, /* ..#.#.#.. */
631 0x0008, /* .....#... */
632},
633{
634 0x00aa, /* .#.#.#.#. */
635 0x0044, /* ..#...#.. */
636 0x002a, /* ...#.#.#. */
637 0x0081, /* .#......# */
638 0x0038, /* ...###... */
639 0x0102, /* #......#. */
640 0x00a8, /* .#.#.#... */
641 0x0044, /* ..#...#.. */
642 0x00aa, /* .#.#.#.#. */
643},
644{
645 0x0014, /* ....#.#.. */
646 0x0140, /* #.#...... */
647 0x000f, /* .....#### */
648 0x0003, /* .......## */
649 0x00aa, /* .#.#.#.#. */
650 0x0180, /* ##....... */
651 0x01e0, /* ####..... */
652 0x0005, /* ......#.# */
653 0x0050, /* ..#.#.... */
654},
655{
656 0x002d, /* ...#.##.# */
657 0x0010, /* ....#.... */
658 0x0091, /* .#..#...# */
659 0x0074, /* ..###.#.. */
660 0x0101, /* #.......# */
661 0x005c, /* ..#.###.. */
662 0x0112, /* #...#..#. */
663 0x0010, /* ....#.... */
664 0x0168, /* #.##.#... */
665},
666{
667 0x0096, /* .#..#.##. */
668 0x009a, /* .#..##.#. */
669 0x00e4, /* .###..#.. */
670 0x0190, /* ##..#.... */
671 0x01ab, /* ##.#.#.## */
672 0x0013, /* ....#..## */
673 0x004e, /* ..#..###. */
674 0x00b2, /* .#.##..#. */
675 0x00d2, /* .##.#..#. */
676},
677{
678 0x0150, /* #.#.#.... */
679 0x0022, /* ...#...#. */
680 0x0094, /* .#..#.#.. */
681 0x016c, /* #.##.##.. */
682 0x0082, /* .#.....#. */
683 0x006d, /* ..##.##.# */
684 0x0052, /* ..#.#..#. */
685 0x0088, /* .#...#... */
686 0x0015, /* ....#.#.# */
687},
688{
689 0x000d, /* .....##.# */
690 0x01b1, /* ##.##...# */
691 0x0080, /* .#....... */
692 0x014c, /* #.#..##.. */
693 0x0101, /* #.......# */
694 0x0065, /* ..##..#.# */
695 0x0002, /* .......#. */
696 0x011b, /* #...##.## */
697 0x0160, /* #.##..... */
698},
699{
700 0x0016, /* ....#.##. */
701 0x0160, /* #.##..... */
702 0x010a, /* #....#.#. */
703 0x0052, /* ..#.#..#. */
704 0x0129, /* #..#.#..# */
705 0x0094, /* .#..#.#.. */
706 0x00a1, /* .#.#....# */
707 0x000d, /* .....##.# */
708 0x00d0, /* .##.#.... */
709},
710{
711 0x00e9, /* .###.#..# */
712 0x00c1, /* .##.....# */
713 0x0120, /* #..#..... */
714 0x0188, /* ##...#... */
715 0x00c6, /* .##...##. */
716 0x0023, /* ...#...## */
717 0x0009, /* .....#..# */
718 0x0106, /* #.....##. */
719 0x012e, /* #..#.###. */
720},
721{
722 0x000d, /* .....##.# */
723 0x0090, /* .#..#.... */
724 0x0188, /* ##...#... */
725 0x0059, /* ..#.##..# */
726 0x0028, /* ...#.#... */
727 0x0134, /* #..##.#.. */
728 0x0023, /* ...#...## */
729 0x0012, /* ....#..#. */
730 0x0160, /* #.##..... */
731},
732{
733 0x0108, /* #....#... */
734 0x0116, /* #...#.##. */
735 0x0148, /* #.#..#... */
736 0x01c4, /* ###...#.. */
737 0x0101, /* #.......# */
738 0x0047, /* ..#...### */
739 0x0025, /* ...#..#.# */
740 0x00d1, /* .##.#...# */
741 0x0021, /* ...#....# */
742},
743{
744 0x0151, /* #.#.#...# */
745 0x0024, /* ...#..#.. */
746 0x004a, /* ..#..#.#. */
747 0x0042, /* ..#....#. */
748 0x006c, /* ..##.##.. */
749 0x0084, /* .#....#.. */
750 0x00a4, /* .#.#..#.. */
751 0x0048, /* ..#..#... */
752 0x0115, /* #...#.#.# */
753},
754{
755 0x00aa, /* .#.#.#.#. */
756 0x0044, /* ..#...#.. */
757 0x00aa, /* .#.#.#.#. */
758 0x00c6, /* .##...##. */
759 0x0101, /* #.......# */
760 0x00c6, /* .##...##. */
761 0x00aa, /* .#.#.#.#. */
762 0x0044, /* ..#...#.. */
763 0x00aa, /* .#.#.#.#. */
764},
765{
766 0x0004, /* ......#.. */
767 0x0061, /* ..##....# */
768 0x0023, /* ...#...## */
769 0x0184, /* ##....#.. */
770 0x0139, /* #..###..# */
771 0x0043, /* ..#....## */
772 0x0188, /* ##...#... */
773 0x010c, /* #....##.. */
774 0x0040, /* ..#...... */
775},
776{
777 0x0141, /* #.#.....# */
778 0x0082, /* .#.....#. */
779 0x00a2, /* .#.#...#. */
780 0x003d, /* ...####.# */
781 0x0010, /* ....#.... */
782 0x0178, /* #.####... */
783 0x008a, /* .#...#.#. */
784 0x0082, /* .#.....#. */
785 0x0105, /* #.....#.# */
786},
787{
788 0x01a3, /* ##.#...## */
789 0x01ac, /* ##.#.##.. */
790 0x0049, /* ..#..#..# */
791 0x0106, /* #.....##. */
792 0x0129, /* #..#.#..# */
793 0x00c1, /* .##.....# */
794 0x0124, /* #..#..#.. */
795 0x006b, /* ..##.#.## */
796 0x018b, /* ##...#.## */
797},
798{
799 0x0044, /* ..#...#.. */
800 0x0015, /* ....#.#.# */
801 0x0132, /* #..##..#. */
802 0x0021, /* ...#....# */
803 0x006c, /* ..##.##.. */
804 0x0108, /* #....#... */
805 0x0099, /* .#..##..# */
806 0x0150, /* #.#.#.... */
807 0x0044, /* ..#...#.. */
808},
809{
810 0x0112, /* #...#..#. */
811 0x0024, /* ...#..#.. */
812 0x014c, /* #.#..##.. */
813 0x0041, /* ..#.....# */
814 0x016d, /* #.##.##.# */
815 0x0104, /* #.....#.. */
816 0x0065, /* ..##..#.# */
817 0x0048, /* ..#..#... */
818 0x0091, /* .#..#...# */
819},
820{
821 0x0139, /* #..###..# */
822 0x008c, /* .#...##.. */
823 0x0010, /* ....#.... */
824 0x0142, /* #.#....#. */
825 0x00c6, /* .##...##. */
826 0x0085, /* .#....#.# */
827 0x0010, /* ....#.... */
828 0x0062, /* ..##...#. */
829 0x0139, /* #..###..# */
830},
831{
832 0x00e9, /* .###.#..# */
833 0x0078, /* ..####... */
834 0x00a0, /* .#.#..... */
835 0x0047, /* ..#...### */
836 0x0000, /* ......... */
837 0x01c4, /* ###...#.. */
838 0x000a, /* .....#.#. */
839 0x003c, /* ...####.. */
840 0x012e, /* #..#.###. */
841},
842{
843 0x0004, /* ......#.. */
844 0x0087, /* .#....### */
845 0x0023, /* ...#...## */
846 0x0025, /* ...#..#.# */
847 0x0111, /* #...#...# */
848 0x0148, /* #.#..#... */
849 0x0188, /* ##...#... */
850 0x01c2, /* ###....#. */
851 0x0040, /* ..#...... */
852},
853{
854 0x010e, /* #....###. */
855 0x0096, /* .#..#.##. */
856 0x0121, /* #..#....# */
857 0x0013, /* ....#..## */
858 0x0044, /* ..#...#.. */
859 0x0190, /* ##..#.... */
860 0x0109, /* #....#..# */
861 0x00d2, /* .##.#..#. */
862 0x00e1, /* .###....# */
863},
864{
865 0x010c, /* #....##.. */
866 0x0034, /* ...##.#.. */
867 0x0094, /* .#..#.#.. */
868 0x0138, /* #..###... */
869 0x0000, /* ......... */
870 0x0039, /* ...###..# */
871 0x0052, /* ..#.#..#. */
872 0x0058, /* ..#.##... */
873 0x0061, /* ..##....# */
874},
875{
876 0x0112, /* #...#..#. */
877 0x01a1, /* ##.#....# */
878 0x0048, /* ..#..#... */
879 0x0190, /* ##..#.... */
880 0x0082, /* .#.....#. */
881 0x0013, /* ....#..## */
882 0x0024, /* ...#..#.. */
883 0x010b, /* #....#.## */
884 0x0091, /* .#..#...# */
885},
886{
887 0x0031, /* ...##...# */
888 0x0004, /* ......#.. */
889 0x00a9, /* .#.#.#..# */
890 0x00c4, /* .##...#.. */
891 0x0054, /* ..#.#.#.. */
892 0x0046, /* ..#...##. */
893 0x012a, /* #..#.#.#. */
894 0x0040, /* ..#...... */
895 0x0118, /* #...##... */
896},
897{
898 0x01b0, /* ##.##.... */
899 0x010e, /* #....###. */
900 0x0000, /* ......... */
901 0x0102, /* #......#. */
902 0x00ba, /* .#.###.#. */
903 0x0081, /* .#......# */
904 0x0000, /* ......... */
905 0x00e1, /* .###....# */
906 0x001b, /* ....##.## */
907},
908{
909 0x006c, /* ..##.##.. */
910 0x00d2, /* .##.#..#. */
911 0x0147, /* #.#...### */
912 0x0129, /* #..#.#..# */
913 0x0092, /* .#..#..#. */
914 0x0129, /* #..#.#..# */
915 0x01c5, /* ###...#.# */
916 0x0096, /* .#..#.##. */
917 0x006c, /* ..##.##.. */
918},
919{
920 0x0111, /* #...#...# */
921 0x008e, /* .#...###. */
922 0x00b0, /* .#.##.... */
923 0x0084, /* .#....#.. */
924 0x0145, /* #.#...#.# */
925 0x0042, /* ..#....#. */
926 0x001a, /* ....##.#. */
927 0x00e2, /* .###...#. */
928 0x0111, /* #...#...# */
929},
930{
931 0x0040, /* ..#...... */
932 0x0096, /* .#..#.##. */
933 0x00cd, /* .##..##.# */
934 0x0050, /* ..#.#.... */
935 0x00ba, /* .#.###.#. */
936 0x0014, /* ....#.#.. */
937 0x0166, /* #.##..##. */
938 0x00d2, /* .##.#..#. */
939 0x0004, /* ......#.. */
940},
941{
942 0x000f, /* .....#### */
943 0x0152, /* #.#.#..#. */
944 0x011c, /* #...###.. */
945 0x00b1, /* .#.##...# */
946 0x0145, /* #.#...#.# */
947 0x011a, /* #...##.#. */
948 0x0071, /* ..###...# */
949 0x0095, /* .#..#.#.# */
950 0x01e0, /* ####..... */
951},
952{
953 0x0128, /* #..#.#... */
954 0x0183, /* ##.....## */
955 0x0094, /* .#..#.#.. */
956 0x00b1, /* .#.##...# */
957 0x0044, /* ..#...#.. */
958 0x011a, /* #...##.#. */
959 0x0052, /* ..#.#..#. */
960 0x0183, /* ##.....## */
961 0x0029, /* ...#.#..# */
962},
963{
964 0x0081, /* .#......# */
965 0x0060, /* ..##..... */
966 0x0159, /* #.#.##..# */
967 0x000b, /* .....#.## */
968 0x0054, /* ..#.#.#.. */
969 0x01a0, /* ##.#..... */
970 0x0135, /* #..##.#.# */
971 0x000c, /* .....##.. */
972 0x0102, /* #......#. */
973},
974{
975 0x00dc, /* .##.###.. */
976 0x0089, /* .#...#..# */
977 0x0030, /* ...##.... */
978 0x0046, /* ..#...##. */
979 0x0028, /* ...#.#... */
980 0x00c4, /* .##...#.. */
981 0x0018, /* ....##... */
982 0x0122, /* #..#...#. */
983 0x0076, /* ..###.##. */
984},
985{
986 0x00e0, /* .###..... */
987 0x0082, /* .#.....#. */
988 0x0081, /* .#......# */
989 0x0149, /* #.#..#..# */
990 0x0092, /* .#..#..#. */
991 0x0125, /* #..#..#.# */
992 0x0102, /* #......#. */
993 0x0082, /* .#.....#. */
994 0x000e, /* .....###. */
995},
996{
997 0x0199, /* ##..##..# */
998 0x0025, /* ...#..#.# */
999 0x0010, /* ....#.... */
1000 0x00a2, /* .#.#...#. */
1001 0x0044, /* ..#...#.. */
1002 0x008a, /* .#...#.#. */
1003 0x0010, /* ....#.... */
1004 0x0148, /* #.#..#... */
1005 0x0133, /* #..##..## */
1006},
1007{
1008 0x0101, /* #.......# */
1009 0x0129, /* #..#.#..# */
1010 0x007c, /* ..#####.. */
1011 0x00aa, /* .#.#.#.#. */
1012 0x0082, /* .#.....#. */
1013 0x00aa, /* .#.#.#.#. */
1014 0x007c, /* ..#####.. */
1015 0x0129, /* #..#.#..# */
1016 0x0101, /* #.......# */
1017},
1018{
1019 0x0112, /* #...#..#. */
1020 0x014e, /* #.#..###. */
1021 0x0002, /* .......#. */
1022 0x0108, /* #....#... */
1023 0x0038, /* ...###... */
1024 0x0021, /* ...#....# */
1025 0x0080, /* .#....... */
1026 0x00e5, /* .###..#.# */
1027 0x0091, /* .#..#...# */
1028},
1029{
1030 0x01c3, /* ###....## */
1031 0x0032, /* ...##..#. */
1032 0x0008, /* .....#... */
1033 0x00c4, /* .##...#.. */
1034 0x0028, /* ...#.#... */
1035 0x0046, /* ..#...##. */
1036 0x0020, /* ...#..... */
1037 0x0098, /* .#..##... */
1038 0x0187, /* ##....### */
1039},
1040{
1041 0x00e2, /* .###...#. */
1042 0x0001, /* ........# */
1043 0x00e0, /* .###..... */
1044 0x0052, /* ..#.#..#. */
1045 0x0145, /* #.#...#.# */
1046 0x0094, /* .#..#.#.. */
1047 0x000e, /* .....###. */
1048 0x0100, /* #........ */
1049 0x008e, /* .#...###. */
1050},
1051{
1052 0x0185, /* ##....#.# */
1053 0x0124, /* #..#..#.. */
1054 0x0060, /* ..##..... */
1055 0x0011, /* ....#...# */
1056 0x016d, /* #.##.##.# */
1057 0x0110, /* #...#.... */
1058 0x000c, /* .....##.. */
1059 0x0049, /* ..#..#..# */
1060 0x0143, /* #.#....## */
1061},
1062{
1063 0x0082, /* .#.....#. */
1064 0x0155, /* #.#.#.#.# */
1065 0x006c, /* ..##.##.. */
1066 0x0082, /* .#.....#. */
1067 0x0028, /* ...#.#... */
1068 0x0082, /* .#.....#. */
1069 0x006c, /* ..##.##.. */
1070 0x0155, /* #.#.#.#.# */
1071 0x0082, /* .#.....#. */
1072},
1073{
1074 0x008a, /* .#...#.#. */
1075 0x0169, /* #.##.#..# */
1076 0x014d, /* #.#..##.# */
1077 0x0118, /* #...##... */
1078 0x00c6, /* .##...##. */
1079 0x0031, /* ...##...# */
1080 0x0165, /* #.##..#.# */
1081 0x012d, /* #..#.##.# */
1082 0x00a2, /* .#.#...#. */
1083},
1084{
1085 0x0145, /* #.#...#.# */
1086 0x00aa, /* .#.#.#.#. */
1087 0x0129, /* #..#.#..# */
1088 0x006c, /* ..##.##.. */
1089 0x0000, /* ......... */
1090 0x006c, /* ..##.##.. */
1091 0x0129, /* #..#.#..# */
1092 0x00aa, /* .#.#.#.#. */
1093 0x0145, /* #.#...#.# */
1094},
1095{
1096 0x0122, /* #..#...#. */
1097 0x0011, /* ....#...# */
1098 0x010a, /* #....#.#. */
1099 0x0154, /* #.#.#.#.. */
1100 0x0000, /* ......... */
1101 0x0055, /* ..#.#.#.# */
1102 0x00a1, /* .#.#....# */
1103 0x0110, /* #...#.... */
1104 0x0089, /* .#...#..# */
1105},
1106{
1107 0x01c9, /* ###..#..# */
1108 0x00e6, /* .###..##. */
1109 0x0114, /* #...#.#.. */
1110 0x001e, /* ....####. */
1111 0x0028, /* ...#.#... */
1112 0x00f0, /* .####.... */
1113 0x0051, /* ..#.#...# */
1114 0x00ce, /* .##..###. */
1115 0x0127, /* #..#..### */
1116},
1117{
1118 0x0117, /* #...#.### */
1119 0x0009, /* .....#..# */
1120 0x005c, /* ..#.###.. */
1121 0x011c, /* #...###.. */
1122 0x0000, /* ......... */
1123 0x0071, /* ..###...# */
1124 0x0074, /* ..###.#.. */
1125 0x0120, /* #..#..... */
1126 0x01d1, /* ###.#...# */
1127},
1128{
1129 0x0091, /* .#..#...# */
1130 0x0023, /* ...#...## */
1131 0x0044, /* ..#...#.. */
1132 0x0031, /* ...##...# */
1133 0x0111, /* #...#...# */
1134 0x0118, /* #...##... */
1135 0x0044, /* ..#...#.. */
1136 0x0188, /* ##...#... */
1137 0x0112, /* #...#..#. */
1138},
1139{
1140 0x0020, /* ...#..... */
1141 0x011a, /* #...##.#. */
1142 0x00d7, /* .##.#.### */
1143 0x0086, /* .#....##. */
1144 0x0028, /* ...#.#... */
1145 0x00c2, /* .##....#. */
1146 0x01d6, /* ###.#.##. */
1147 0x00b1, /* .#.##...# */
1148 0x0008, /* .....#... */
1149},
1150{
1151 0x000c, /* .....##.. */
1152 0x0034, /* ...##.#.. */
1153 0x01c4, /* ###...#.. */
1154 0x012a, /* #..#.#.#. */
1155 0x0082, /* .#.....#. */
1156 0x00a9, /* .#.#.#..# */
1157 0x0047, /* ..#...### */
1158 0x0058, /* ..#.##... */
1159 0x0060, /* ..##..... */
1160},
1161{
1162 0x0101, /* #.......# */
1163 0x0028, /* ...#.#... */
1164 0x00ee, /* .###.###. */
1165 0x0092, /* .#..#..#. */
1166 0x0101, /* #.......# */
1167 0x0092, /* .#..#..#. */
1168 0x00ee, /* .###.###. */
1169 0x0028, /* ...#.#... */
1170 0x0101, /* #.......# */
1171},
1172{
1173 0x0111, /* #...#...# */
1174 0x0155, /* #.#.#.#.# */
1175 0x006c, /* ..##.##.. */
1176 0x0101, /* #.......# */
1177 0x0028, /* ...#.#... */
1178 0x0101, /* #.......# */
1179 0x006c, /* ..##.##.. */
1180 0x0155, /* #.#.#.#.# */
1181 0x0111, /* #...#...# */
1182},
1183{
1184 0x0188, /* ##...#... */
1185 0x0110, /* #...#.... */
1186 0x008c, /* .#...##.. */
1187 0x0091, /* .#..#...# */
1188 0x0155, /* #.#.#.#.# */
1189 0x0112, /* #...#..#. */
1190 0x0062, /* ..##...#. */
1191 0x0011, /* ....#...# */
1192 0x0023, /* ...#...## */
1193},
1194{
1195 0x00b5, /* .#.##.#.# */
1196 0x0100, /* #........ */
1197 0x0048, /* ..#..#... */
1198 0x0019, /* ....##..# */
1199 0x0183, /* ##.....## */
1200 0x0130, /* #..##.... */
1201 0x0024, /* ...#..#.. */
1202 0x0001, /* ........# */
1203 0x015a, /* #.#.##.#. */
1204},
1205{
1206 0x0195, /* ##..#.#.# */
1207 0x0041, /* ..#.....# */
1208 0x010a, /* #....#.#. */
1209 0x0068, /* ..##.#... */
1210 0x0111, /* #...#...# */
1211 0x002c, /* ...#.##.. */
1212 0x00a1, /* .#.#....# */
1213 0x0104, /* #.....#.. */
1214 0x0153, /* #.#.#..## */
1215},
1216{
1217 0x0000, /* ......... */
1218 0x0032, /* ...##..#. */
1219 0x007b, /* ..####.## */
1220 0x004e, /* ..#..###. */
1221 0x0000, /* ......... */
1222 0x00e4, /* .###..#.. */
1223 0x01bc, /* ##.####.. */
1224 0x0098, /* .#..##... */
1225 0x0000, /* ......... */
1226},
1227{
1228 0x0019, /* ....##..# */
1229 0x0060, /* ..##..... */
1230 0x0105, /* #.....#.# */
1231 0x0142, /* #.#....#. */
1232 0x0044, /* ..#...#.. */
1233 0x0085, /* .#....#.# */
1234 0x0141, /* #.#.....# */
1235 0x000c, /* .....##.. */
1236 0x0130, /* #..##.... */
1237},
1238{
1239 0x00f0, /* .####.... */
1240 0x008f, /* .#...#### */
1241 0x00a9, /* .#.#.#..# */
1242 0x00c5, /* .##...#.# */
1243 0x0111, /* #...#...# */
1244 0x0146, /* #.#...##. */
1245 0x012a, /* #..#.#.#. */
1246 0x01e2, /* ####...#. */
1247 0x001e, /* ....####. */
1248},
1249{
1250 0x0105, /* #.....#.# */
1251 0x0068, /* ..##.#... */
1252 0x0108, /* #....#... */
1253 0x0042, /* ..#....#. */
1254 0x00fe, /* .#######. */
1255 0x0084, /* .#....#.. */
1256 0x0021, /* ...#....# */
1257 0x002c, /* ...#.##.. */
1258 0x0141, /* #.#.....# */
1259},
1260{
1261 0x01b0, /* ##.##.... */
1262 0x0071, /* ..###...# */
1263 0x010e, /* #....###. */
1264 0x014a, /* #.#..#.#. */
1265 0x00aa, /* .#.#.#.#. */
1266 0x00a5, /* .#.#..#.# */
1267 0x00e1, /* .###....# */
1268 0x011c, /* #...###.. */
1269 0x001b, /* ....##.## */
1270},
1271{
1272 0x0038, /* ...###... */
1273 0x0092, /* .#..#..#. */
1274 0x00c6, /* .##...##. */
1275 0x0044, /* ..#...#.. */
1276 0x0155, /* #.#.#.#.# */
1277 0x0044, /* ..#...#.. */
1278 0x00c6, /* .##...##. */
1279 0x0092, /* .#..#..#. */
1280 0x0038, /* ...###... */
1281},
1282{
1283 0x00a2, /* .#.#...#. */
1284 0x0051, /* ..#.#...# */
1285 0x0080, /* .#....... */
1286 0x0191, /* ##..#...# */
1287 0x0054, /* ..#.#.#.. */
1288 0x0113, /* #...#..## */
1289 0x0002, /* .......#. */
1290 0x0114, /* #...#.#.. */
1291 0x008a, /* .#...#.#. */
1292},
1293{
1294 0x0139, /* #..###..# */
1295 0x000c, /* .....##.. */
1296 0x00e4, /* .###..#.. */
1297 0x01ad, /* ##.#.##.# */
1298 0x0101, /* #.......# */
1299 0x016b, /* #.##.#.## */
1300 0x004e, /* ..#..###. */
1301 0x0060, /* ..##..... */
1302 0x0139, /* #..###..# */
1303},
1304{
1305 0x00c4, /* .##...#.. */
1306 0x0031, /* ...##...# */
1307 0x0109, /* #....#..# */
1308 0x006a, /* ..##.#.#. */
1309 0x0092, /* .#..#..#. */
1310 0x00ac, /* .#.#.##.. */
1311 0x0121, /* #..#....# */
1312 0x0118, /* #...##... */
1313 0x0046, /* ..#...##. */
1314},
1315{
1316 0x0122, /* #..#...#. */
1317 0x0024, /* ...#..#.. */
1318 0x008a, /* .#...#.#. */
1319 0x0112, /* #...#..#. */
1320 0x0054, /* ..#.#.#.. */
1321 0x0091, /* .#..#...# */
1322 0x00a2, /* .#.#...#. */
1323 0x0048, /* ..#..#... */
1324 0x0089, /* .#...#..# */
1325},
1326{
1327 0x0052, /* ..#.#..#. */
1328 0x0004, /* ......#.. */
1329 0x01f1, /* #####...# */
1330 0x0164, /* #.##..#.. */
1331 0x0010, /* ....#.... */
1332 0x004d, /* ..#..##.# */
1333 0x011f, /* #...##### */
1334 0x0040, /* ..#...... */
1335 0x0094, /* .#..#.#.. */
1336},
1337{
1338 0x00e4, /* .###..#.. */
1339 0x0015, /* ....#.#.# */
1340 0x0189, /* ##...#..# */
1341 0x0041, /* ..#.....# */
1342 0x0082, /* .#.....#. */
1343 0x0104, /* #.....#.. */
1344 0x0123, /* #..#...## */
1345 0x0150, /* #.#.#.... */
1346 0x004e, /* ..#..###. */
1347},
1348{
1349 0x0063, /* ..##...## */
1350 0x0120, /* #..#..... */
1351 0x0080, /* .#....... */
1352 0x0052, /* ..#.#..#. */
1353 0x00ee, /* .###.###. */
1354 0x0094, /* .#..#.#.. */
1355 0x0002, /* .......#. */
1356 0x0009, /* .....#..# */
1357 0x018c, /* ##...##.. */
1358},
1359{
1360 0x0082, /* .#.....#. */
1361 0x0044, /* ..#...#.. */
1362 0x01bb, /* ##.###.## */
1363 0x00aa, /* .#.#.#.#. */
1364 0x0101, /* #.......# */
1365 0x00aa, /* .#.#.#.#. */
1366 0x01bb, /* ##.###.## */
1367 0x0044, /* ..#...#.. */
1368 0x0082, /* .#.....#. */
1369},
1370{
1371 0x0028, /* ...#.#... */
1372 0x0044, /* ..#...#.. */
1373 0x01ab, /* ##.#.#.## */
1374 0x0082, /* .#.....#. */
1375 0x0145, /* #.#...#.# */
1376 0x0082, /* .#.....#. */
1377 0x01ab, /* ##.#.#.## */
1378 0x0044, /* ..#...#.. */
1379 0x0028, /* ...#.#... */
1380},
1381{
1382 0x0121, /* #..#....# */
1383 0x0034, /* ...##.#.. */
1384 0x0088, /* .#...#... */
1385 0x0043, /* ..#....## */
1386 0x0092, /* .#..#..#. */
1387 0x0184, /* ##....#.. */
1388 0x0022, /* ...#...#. */
1389 0x0058, /* ..#.##... */
1390 0x0109, /* #....#..# */
1391},
1392{
1393 0x00ac, /* .#.#.##.. */
1394 0x0098, /* .#..##... */
1395 0x0042, /* ..#....#. */
1396 0x0049, /* ..#..#..# */
1397 0x0101, /* #.......# */
1398 0x0124, /* #..#..#.. */
1399 0x0084, /* .#....#.. */
1400 0x0032, /* ...##..#. */
1401 0x006a, /* ..##.#.#. */
1402},
1403{
1404 0x0092, /* .#..#..#. */
1405 0x006c, /* ..##.##.. */
1406 0x0101, /* #.......# */
1407 0x0145, /* #.#...#.# */
1408 0x0028, /* ...#.#... */
1409 0x0145, /* #.#...#.# */
1410 0x0101, /* #.......# */
1411 0x006c, /* ..##.##.. */
1412 0x0092, /* .#..#..#. */
1413},
1414{
1415 0x000c, /* .....##.. */
1416 0x0091, /* .#..#...# */
1417 0x0089, /* .#...#..# */
1418 0x0048, /* ..#..#... */
1419 0x0183, /* ##.....## */
1420 0x0024, /* ...#..#.. */
1421 0x0122, /* #..#...#. */
1422 0x0112, /* #...#..#. */
1423 0x0060, /* ..##..... */
1424},
1425{
1426 0x006c, /* ..##.##.. */
1427 0x0146, /* #.#...##. */
1428 0x0018, /* ....##... */
1429 0x001d, /* ....###.# */
1430 0x0101, /* #.......# */
1431 0x0170, /* #.###.... */
1432 0x0030, /* ...##.... */
1433 0x00c5, /* .##...#.# */
1434 0x006c, /* ..##.##.. */
1435},
1436{
1437 0x0015, /* ....#.#.# */
1438 0x0088, /* .#...#... */
1439 0x0140, /* #.#...... */
1440 0x009a, /* .#..##.#. */
1441 0x0101, /* #.......# */
1442 0x00b2, /* .#.##..#. */
1443 0x0005, /* ......#.# */
1444 0x0022, /* ...#...#. */
1445 0x0150, /* #.#.#.... */
1446},
1447{
1448 0x0000, /* ......... */
1449 0x00aa, /* .#.#.#.#. */
1450 0x01c7, /* ###...### */
1451 0x007c, /* ..#####.. */
1452 0x0000, /* ......... */
1453 0x007c, /* ..#####.. */
1454 0x01c7, /* ###...### */
1455 0x00aa, /* .#.#.#.#. */
1456 0x0000, /* ......... */
1457},
1458{
1459 0x0192, /* ##..#..#. */
1460 0x0093, /* .#..#..## */
1461 0x0088, /* .#...#... */
1462 0x0068, /* ..##.#... */
1463 0x0101, /* #.......# */
1464 0x002c, /* ...#.##.. */
1465 0x0022, /* ...#...#. */
1466 0x0192, /* ##..#..#. */
1467 0x0093, /* .#..#..## */
1468},
1469{
1470 0x0129, /* #..#.#..# */
1471 0x00aa, /* .#.#.#.#. */
1472 0x0044, /* ..#...#.. */
1473 0x006c, /* ..##.##.. */
1474 0x0101, /* #.......# */
1475 0x006c, /* ..##.##.. */
1476 0x0044, /* ..#...#.. */
1477 0x00aa, /* .#.#.#.#. */
1478 0x0129, /* #..#.#..# */
1479},
1480{
1481 0x0113, /* #...#..## */
1482 0x0130, /* #..##.... */
1483 0x01c0, /* ###...... */
1484 0x0025, /* ...#..#.# */
1485 0x0082, /* .#.....#. */
1486 0x0148, /* #.#..#... */
1487 0x0007, /* ......### */
1488 0x0019, /* ....##..# */
1489 0x0191, /* ##..#...# */
1490},
1491{
1492 0x0094, /* .#..#.#.. */
1493 0x0013, /* ....#..## */
1494 0x001d, /* ....###.# */
1495 0x018a, /* ##...#.#. */
1496 0x0010, /* ....#.... */
1497 0x00a3, /* .#.#...## */
1498 0x0170, /* #.###.... */
1499 0x0190, /* ##..#.... */
1500 0x0052, /* ..#.#..#. */
1501},
1502{
1503 0x0017, /* ....#.### */
1504 0x01b2, /* ##.##..#. */
1505 0x0004, /* ......#.. */
1506 0x0021, /* ...#....# */
1507 0x01ab, /* ##.#.#.## */
1508 0x0108, /* #....#... */
1509 0x0040, /* ..#...... */
1510 0x009b, /* .#..##.## */
1511 0x01d0, /* ###.#.... */
1512},
1513{
1514 0x0129, /* #..#.#..# */
1515 0x0000, /* ......... */
1516 0x01c7, /* ###...### */
1517 0x006c, /* ..##.##.. */
1518 0x0101, /* #.......# */
1519 0x006c, /* ..##.##.. */
1520 0x01c7, /* ###...### */
1521 0x0000, /* ......... */
1522 0x0129, /* #..#.#..# */
1523},
1524{
1525 0x00d8, /* .##.##... */
1526 0x0093, /* .#..#..## */
1527 0x008a, /* .#...#.#. */
1528 0x0110, /* #...#.... */
1529 0x0145, /* #.#...#.# */
1530 0x0011, /* ....#...# */
1531 0x00a2, /* .#.#...#. */
1532 0x0192, /* ##..#..#. */
1533 0x0036, /* ...##.##. */
1534},
1535{
1536 0x0056, /* ..#.#.##. */
1537 0x01a2, /* ##.#...#. */
1538 0x0048, /* ..#..#... */
1539 0x0050, /* ..#.#.... */
1540 0x0145, /* #.#...#.# */
1541 0x0014, /* ....#.#.. */
1542 0x0024, /* ...#..#.. */
1543 0x008b, /* .#...#.## */
1544 0x00d4, /* .##.#.#.. */
1545},
1546{
1547 0x0066, /* ..##..##. */
1548 0x0105, /* #.....#.# */
1549 0x0091, /* .#..#...# */
1550 0x008c, /* .#...##.. */
1551 0x0028, /* ...#.#... */
1552 0x0062, /* ..##...#. */
1553 0x0112, /* #...#..#. */
1554 0x0141, /* #.#.....# */
1555 0x00cc, /* .##..##.. */
1556},
1557{
1558 0x01a0, /* ##.#..... */
1559 0x00b9, /* .#.###..# */
1560 0x000b, /* .....#.## */
1561 0x0120, /* #..#..... */
1562 0x0101, /* #.......# */
1563 0x0009, /* .....#..# */
1564 0x01a0, /* ##.#..... */
1565 0x013a, /* #..###.#. */
1566 0x000b, /* .....#.## */
1567},
1568{
1569 0x0000, /* ......... */
1570 0x01ad, /* ##.#.##.# */
1571 0x0056, /* ..#.#.##. */
1572 0x0018, /* ....##... */
1573 0x0145, /* #.#...#.# */
1574 0x0030, /* ...##.... */
1575 0x00d4, /* .##.#.#.. */
1576 0x016b, /* #.##.#.## */
1577 0x0000, /* ......... */
1578},
1579{
1580 0x0028, /* ...#.#... */
1581 0x0082, /* .#.....#. */
1582 0x01c7, /* ###...### */
1583 0x006c, /* ..##.##.. */
1584 0x0101, /* #.......# */
1585 0x006c, /* ..##.##.. */
1586 0x01c7, /* ###...### */
1587 0x0082, /* .#.....#. */
1588 0x0028, /* ...#.#... */
1589},
1590{
1591 0x0024, /* ...#..#.. */
1592 0x0152, /* #.#.#..#. */
1593 0x0124, /* #..#..#.. */
1594 0x0059, /* ..#.##..# */
1595 0x0082, /* .#.....#. */
1596 0x0134, /* #..##.#.. */
1597 0x0049, /* ..#..#..# */
1598 0x0095, /* .#..#.#.# */
1599 0x0048, /* ..#..#... */
1600},
1601{
1602 0x016d, /* #.##.##.# */
1603 0x006c, /* ..##.##.. */
1604 0x0082, /* .#.....#. */
1605 0x0028, /* ...#.#... */
1606 0x0101, /* #.......# */
1607 0x0028, /* ...#.#... */
1608 0x0082, /* .#.....#. */
1609 0x006c, /* ..##.##.. */
1610 0x016d, /* #.##.##.# */
1611},
1612{
1613 0x0091, /* .#..#...# */
1614 0x0069, /* ..##.#..# */
1615 0x0038, /* ...###... */
1616 0x0084, /* .#....#.. */
1617 0x0183, /* ##.....## */
1618 0x0042, /* ..#....#. */
1619 0x0038, /* ...###... */
1620 0x012c, /* #..#.##.. */
1621 0x0112, /* #...#..#. */
1622},
1623{
1624 0x0101, /* #.......# */
1625 0x0021, /* ...#....# */
1626 0x01d4, /* ###.#.#.. */
1627 0x012a, /* #..#.#.#. */
1628 0x0082, /* .#.....#. */
1629 0x00a9, /* .#.#.#..# */
1630 0x0057, /* ..#.#.### */
1631 0x0108, /* #....#... */
1632 0x0101, /* #.......# */
1633},
1634{
1635 0x0156, /* #.#.#.##. */
1636 0x00c0, /* .##...... */
1637 0x0021, /* ...#....# */
1638 0x0160, /* #.##..... */
1639 0x0129, /* #..#.#..# */
1640 0x000d, /* .....##.# */
1641 0x0108, /* #....#... */
1642 0x0006, /* ......##. */
1643 0x00d5, /* .##.#.#.# */
1644},
1645{
1646 0x00c2, /* .##....#. */
1647 0x010a, /* #....#.#. */
1648 0x012c, /* #..#.##.. */
1649 0x0095, /* .#..#.#.# */
1650 0x0000, /* ......... */
1651 0x0152, /* #.#.#..#. */
1652 0x0069, /* ..##.#..# */
1653 0x00a1, /* .#.#....# */
1654 0x0086, /* .#....##. */
1655},
1656{
1657 0x0003, /* .......## */
1658 0x0048, /* ..#..#... */
1659 0x0168, /* #.##.#... */
1660 0x0195, /* ##..#.#.# */
1661 0x0028, /* ...#.#... */
1662 0x0153, /* #.#.#..## */
1663 0x002d, /* ...#.##.# */
1664 0x0024, /* ...#..#.. */
1665 0x0180, /* ##....... */
1666},
1667{
1668 0x00c2, /* .##....#. */
1669 0x01b0, /* ##.##.... */
1670 0x000d, /* .....##.# */
1671 0x0007, /* ......### */
1672 0x0082, /* .#.....#. */
1673 0x01c0, /* ###...... */
1674 0x0160, /* #.##..... */
1675 0x001b, /* ....##.## */
1676 0x0086, /* .#....##. */
1677},
1678{
1679 0x016d, /* #.##.##.# */
1680 0x0044, /* ..#...#.. */
1681 0x0082, /* .#.....#. */
1682 0x006c, /* ..##.##.. */
1683 0x0101, /* #.......# */
1684 0x006c, /* ..##.##.. */
1685 0x0082, /* .#.....#. */
1686 0x0044, /* ..#...#.. */
1687 0x016d, /* #.##.##.# */
1688},
1689{
1690 0x0022, /* ...#...#. */
1691 0x0006, /* ......##. */
1692 0x0135, /* #..##.#.# */
1693 0x0112, /* #...#..#. */
1694 0x0183, /* ##.....## */
1695 0x0091, /* .#..#...# */
1696 0x0159, /* #.#.##..# */
1697 0x00c0, /* .##...... */
1698 0x0088, /* .#...#... */
1699},
1700{
1701 0x0044, /* ..#...#.. */
1702 0x006c, /* ..##.##.. */
1703 0x0111, /* #...#...# */
1704 0x00ee, /* .###.###. */
1705 0x0000, /* ......... */
1706 0x00ee, /* .###.###. */
1707 0x0111, /* #...#...# */
1708 0x006c, /* ..##.##.. */
1709 0x0044, /* ..#...#.. */
1710},
1711{
1712 0x0043, /* ..#....## */
1713 0x014c, /* #.#..##.. */
1714 0x0050, /* ..#.#.... */
1715 0x0034, /* ...##.#.. */
1716 0x0129, /* #..#.#..# */
1717 0x0058, /* ..#.##... */
1718 0x0014, /* ....#.#.. */
1719 0x0065, /* ..##..#.# */
1720 0x0184, /* ##....#.. */
1721},
1722{
1723 0x00a8, /* .#.#.#... */
1724 0x018c, /* ##...##.. */
1725 0x0010, /* ....#.... */
1726 0x0184, /* ##....#.. */
1727 0x0101, /* #.......# */
1728 0x0043, /* ..#....## */
1729 0x0010, /* ....#.... */
1730 0x0063, /* ..##...## */
1731 0x002a, /* ...#.#.#. */
1732},
1733{
1734 0x0145, /* #.#...#.# */
1735 0x00ee, /* .###.###. */
1736 0x0101, /* #.......# */
1737 0x0028, /* ...#.#... */
1738 0x0092, /* .#..#..#. */
1739 0x0028, /* ...#.#... */
1740 0x0101, /* #.......# */
1741 0x00ee, /* .###.###. */
1742 0x0145, /* #.#...#.# */
1743},
1744{
1745 0x01a0, /* ##.#..... */
1746 0x0054, /* ..#.#.#.. */
1747 0x0021, /* ...#....# */
1748 0x008a, /* .#...#.#. */
1749 0x0129, /* #..#.#..# */
1750 0x00a2, /* .#.#...#. */
1751 0x0108, /* #....#... */
1752 0x0054, /* ..#.#.#.. */
1753 0x000b, /* .....#.## */
1754},
1755{
1756 0x00aa, /* .#.#.#.#. */
1757 0x006c, /* ..##.##.. */
1758 0x0101, /* #.......# */
1759 0x0054, /* ..#.#.#.. */
1760 0x0101, /* #.......# */
1761 0x0054, /* ..#.#.#.. */
1762 0x0101, /* #.......# */
1763 0x006c, /* ..##.##.. */
1764 0x00aa, /* .#.#.#.#. */
1765},
1766{
1767 0x0074, /* ..###.#.. */
1768 0x0041, /* ..#.....# */
1769 0x0126, /* #..#..##. */
1770 0x00d8, /* .##.##... */
1771 0x0000, /* ......... */
1772 0x0036, /* ...##.##. */
1773 0x00c9, /* .##..#..# */
1774 0x0104, /* #.....#.. */
1775 0x005c, /* ..#.###.. */
1776},
1777{
1778 0x0111, /* #...#...# */
1779 0x0183, /* ##.....## */
1780 0x0028, /* ...#.#... */
1781 0x0093, /* .#..#..## */
1782 0x0044, /* ..#...#.. */
1783 0x0192, /* ##..#..#. */
1784 0x0028, /* ...#.#... */
1785 0x0183, /* ##.....## */
1786 0x0111, /* #...#...# */
1787},
1788{
1789 0x0044, /* ..#...#.. */
1790 0x0028, /* ...#.#... */
1791 0x0183, /* ##.....## */
1792 0x006c, /* ..##.##.. */
1793 0x0183, /* ##.....## */
1794 0x006c, /* ..##.##.. */
1795 0x0183, /* ##.....## */
1796 0x0028, /* ...#.#... */
1797 0x0044, /* ..#...#.. */
1798},
1799{
1800 0x0037, /* ...##.### */
1801 0x0013, /* ....#..## */
1802 0x0044, /* ..#...#.. */
1803 0x0122, /* #..#...#. */
1804 0x0044, /* ..#...#.. */
1805 0x0089, /* .#...#..# */
1806 0x0044, /* ..#...#.. */
1807 0x0190, /* ##..#.... */
1808 0x01d8, /* ###.##... */
1809},
1810{
1811 0x0007, /* ......### */
1812 0x014a, /* #.#..#.#. */
1813 0x0094, /* .#..#.#.. */
1814 0x0112, /* #...#..#. */
1815 0x0082, /* .#.....#. */
1816 0x0091, /* .#..#...# */
1817 0x0052, /* ..#.#..#. */
1818 0x00a5, /* .#.#..#.# */
1819 0x01c0, /* ###...... */
1820},
1821{
1822 0x00ee, /* .###.###. */
1823 0x0000, /* ......... */
1824 0x0183, /* ##.....## */
1825 0x006c, /* ..##.##.. */
1826 0x0092, /* .#..#..#. */
1827 0x006c, /* ..##.##.. */
1828 0x0183, /* ##.....## */
1829 0x0000, /* ......... */
1830 0x00ee, /* .###.###. */
1831},
1832{
1833 0x01ab, /* ##.#.#.## */
1834 0x00aa, /* .#.#.#.#. */
1835 0x0101, /* #.......# */
1836 0x0028, /* ...#.#... */
1837 0x0082, /* .#.....#. */
1838 0x0028, /* ...#.#... */
1839 0x0101, /* #.......# */
1840 0x00aa, /* .#.#.#.#. */
1841 0x01ab, /* ##.#.#.## */
1842},
1843{
1844 0x01aa, /* ##.#.#.#. */
1845 0x0152, /* #.#.#..#. */
1846 0x0012, /* ....#..#. */
1847 0x002c, /* ...#.##.. */
1848 0x0000, /* ......... */
1849 0x0068, /* ..##.#... */
1850 0x0090, /* .#..#.... */
1851 0x0095, /* .#..#.#.# */
1852 0x00ab, /* .#.#.#.## */
1853},
1854{
1855 0x0046, /* ..#...##. */
1856 0x0182, /* ##.....#. */
1857 0x002c, /* ...#.##.. */
1858 0x004d, /* ..#..##.# */
1859 0x0028, /* ...#.#... */
1860 0x0164, /* #.##..#.. */
1861 0x0068, /* ..##.#... */
1862 0x0083, /* .#.....## */
1863 0x00c4, /* .##...#.. */
1864},
1865{
1866 0x00a9, /* .#.#.#..# */
1867 0x0015, /* ....#.#.# */
1868 0x0016, /* ....#.##. */
1869 0x0083, /* .#.....## */
1870 0x0028, /* ...#.#... */
1871 0x0182, /* ##.....#. */
1872 0x00d0, /* .##.#.... */
1873 0x0150, /* #.#.#.... */
1874 0x012a, /* #..#.#.#. */
1875},
1876{
1877 0x00a4, /* .#.#..#.. */
1878 0x0121, /* #..#....# */
1879 0x0059, /* ..#.##..# */
1880 0x0059, /* ..#.##..# */
1881 0x0000, /* ......... */
1882 0x0134, /* #..##.#.. */
1883 0x0134, /* #..##.#.. */
1884 0x0109, /* #....#..# */
1885 0x004a, /* ..#..#.#. */
1886},
1887{
1888 0x00e4, /* .###..#.. */
1889 0x0094, /* .#..#.#.. */
1890 0x00a8, /* .#.#.#... */
1891 0x0022, /* ...#...#. */
1892 0x0129, /* #..#.#..# */
1893 0x0088, /* .#...#... */
1894 0x002a, /* ...#.#.#. */
1895 0x0052, /* ..#.#..#. */
1896 0x004e, /* ..#..###. */
1897},
1898{
1899 0x0128, /* #..#.#... */
1900 0x0044, /* ..#...#.. */
1901 0x0025, /* ...#..#.# */
1902 0x004e, /* ..#..###. */
1903 0x0111, /* #...#...# */
1904 0x00e4, /* .###..#.. */
1905 0x0148, /* #.#..#... */
1906 0x0044, /* ..#...#.. */
1907 0x0029, /* ...#.#..# */
1908},
1909{
1910 0x002d, /* ...#.##.# */
1911 0x0062, /* ..##...#. */
1912 0x01c1, /* ###.....# */
1913 0x0010, /* ....#.... */
1914 0x0183, /* ##.....## */
1915 0x0010, /* ....#.... */
1916 0x0107, /* #.....### */
1917 0x008c, /* .#...##.. */
1918 0x0168, /* #.##.#... */
1919},
1920{
1921 0x0101, /* #.......# */
1922 0x00ba, /* .#.###.#. */
1923 0x0082, /* .#.....#. */
1924 0x006c, /* ..##.##.. */
1925 0x0082, /* .#.....#. */
1926 0x006c, /* ..##.##.. */
1927 0x0082, /* .#.....#. */
1928 0x00ba, /* .#.###.#. */
1929 0x0101, /* #.......# */
1930},
1931{
1932 0x016d, /* #.##.##.# */
1933 0x0044, /* ..#...#.. */
1934 0x0183, /* ##.....## */
1935 0x0028, /* ...#.#... */
1936 0x0082, /* .#.....#. */
1937 0x0028, /* ...#.#... */
1938 0x0183, /* ##.....## */
1939 0x0044, /* ..#...#.. */
1940 0x016d, /* #.##.##.# */
1941},
1942{
1943 0x00e1, /* .###....# */
1944 0x001b, /* ....##.## */
1945 0x00c0, /* .##...... */
1946 0x0051, /* ..#.#...# */
1947 0x0082, /* .#.....#. */
1948 0x0114, /* #...#.#.. */
1949 0x0006, /* ......##. */
1950 0x01b0, /* ##.##.... */
1951 0x010e, /* #....###. */
1952},
1953{
1954 0x0103, /* #......## */
1955 0x01a9, /* ##.#.#..# */
1956 0x0110, /* #...#.... */
1957 0x0088, /* .#...#... */
1958 0x0145, /* #.#...#.# */
1959 0x0022, /* ...#...#. */
1960 0x0011, /* ....#...# */
1961 0x012b, /* #..#.#.## */
1962 0x0181, /* ##......# */
1963},
1964{
1965 0x0082, /* .#.....#. */
1966 0x00ee, /* .###.###. */
1967 0x0145, /* #.#...#.# */
1968 0x0038, /* ...###... */
1969 0x0010, /* ....#.... */
1970 0x0038, /* ...###... */
1971 0x0145, /* #.#...#.# */
1972 0x00ee, /* .###.###. */
1973 0x0082, /* .#.....#. */
1974},
1975{
1976 0x0052, /* ..#.#..#. */
1977 0x00d0, /* .##.#.... */
1978 0x0148, /* #.#..#... */
1979 0x00c1, /* .##.....# */
1980 0x00aa, /* .#.#.#.#. */
1981 0x0106, /* #.....##. */
1982 0x0025, /* ...#..#.# */
1983 0x0016, /* ....#.##. */
1984 0x0094, /* .#..#.#.. */
1985},
1986{
1987 0x0017, /* ....#.### */
1988 0x0041, /* ..#.....# */
1989 0x008a, /* .#...#.#. */
1990 0x0024, /* ...#..#.. */
1991 0x01ab, /* ##.#.#.## */
1992 0x0048, /* ..#..#... */
1993 0x00a2, /* .#.#...#. */
1994 0x0104, /* #.....#.. */
1995 0x01d0, /* ###.#.... */
1996},
1997{
1998 0x0162, /* #.##...#. */
1999 0x0010, /* ....#.... */
2000 0x0019, /* ....##..# */
2001 0x014c, /* #.#..##.. */
2002 0x0145, /* #.#...#.# */
2003 0x0065, /* ..##..#.# */
2004 0x0130, /* #..##.... */
2005 0x0010, /* ....#.... */
2006 0x008d, /* .#...##.# */
2007},
2008{
2009 0x00a6, /* .#.#..##. */
2010 0x0032, /* ...##..#. */
2011 0x0100, /* #........ */
2012 0x00e9, /* .###.#..# */
2013 0x0082, /* .#.....#. */
2014 0x012e, /* #..#.###. */
2015 0x0001, /* ........# */
2016 0x0098, /* .#..##... */
2017 0x00ca, /* .##..#.#. */
2018},
2019{
2020 0x0123, /* #..#...## */
2021 0x0090, /* .#..#.... */
2022 0x018a, /* ##...#.#. */
2023 0x0158, /* #.#.##... */
2024 0x0000, /* ......... */
2025 0x0035, /* ...##.#.# */
2026 0x00a3, /* .#.#...## */
2027 0x0012, /* ....#..#. */
2028 0x0189, /* ##...#..# */
2029},
2030{
2031 0x0145, /* #.#...#.# */
2032 0x00aa, /* .#.#.#.#. */
2033 0x0101, /* #.......# */
2034 0x006c, /* ..##.##.. */
2035 0x0082, /* .#.....#. */
2036 0x006c, /* ..##.##.. */
2037 0x0101, /* #.......# */
2038 0x00aa, /* .#.#.#.#. */
2039 0x0145, /* #.#...#.# */
2040},
2041{
2042 0x002d, /* ...#.##.# */
2043 0x01a1, /* ##.#....# */
2044 0x0008, /* .....#... */
2045 0x00e3, /* .###...## */
2046 0x0000, /* ......... */
2047 0x018e, /* ##...###. */
2048 0x0020, /* ...#..... */
2049 0x010b, /* #....#.## */
2050 0x0168, /* #.##.#... */
2051},
2052{
2053 0x019c, /* ##..###.. */
2054 0x00a5, /* .#.#..#.# */
2055 0x0180, /* ##....... */
2056 0x0021, /* ...#....# */
2057 0x0028, /* ...#.#... */
2058 0x0108, /* #....#... */
2059 0x0003, /* .......## */
2060 0x014a, /* #.#..#.#. */
2061 0x0073, /* ..###..## */
2062},
2063{
2064 0x0068, /* ..##.#... */
2065 0x0086, /* .#....##. */
2066 0x018c, /* ##...##.. */
2067 0x0162, /* #.##...#. */
2068 0x0010, /* ....#.... */
2069 0x008d, /* .#...##.# */
2070 0x0063, /* ..##...## */
2071 0x00c2, /* .##....#. */
2072 0x002c, /* ...#.##.. */
2073},
2074{
2075 0x0023, /* ...#...## */
2076 0x0188, /* ##...#... */
2077 0x0113, /* #...#..## */
2078 0x0094, /* .#..#.#.. */
2079 0x0101, /* #.......# */
2080 0x0052, /* ..#.#..#. */
2081 0x0191, /* ##..#...# */
2082 0x0023, /* ...#...## */
2083 0x0188, /* ##...#... */
2084},
2085{
2086 0x00f3, /* .####..## */
2087 0x0040, /* ..#...... */
2088 0x01a4, /* ##.#..#.. */
2089 0x0094, /* .#..#.#.. */
2090 0x0000, /* ......... */
2091 0x0052, /* ..#.#..#. */
2092 0x004b, /* ..#..#.## */
2093 0x0004, /* ......#.. */
2094 0x019e, /* ##..####. */
2095},
2096{
2097 0x00aa, /* .#.#.#.#. */
2098 0x00c6, /* .##...##. */
2099 0x0101, /* #.......# */
2100 0x007c, /* ..#####.. */
2101 0x0000, /* ......... */
2102 0x007c, /* ..#####.. */
2103 0x0101, /* #.......# */
2104 0x00c6, /* .##...##. */
2105 0x00aa, /* .#.#.#.#. */
2106},
2107{
2108 0x00ae, /* .#.#.###. */
2109 0x0009, /* .....#..# */
2110 0x0105, /* #.....#.# */
2111 0x00a6, /* .#.#..##. */
2112 0x0010, /* ....#.... */
2113 0x00ca, /* .##..#.#. */
2114 0x0141, /* #.#.....# */
2115 0x0120, /* #..#..... */
2116 0x00ea, /* .###.#.#. */
2117},
2118{
2119 0x0009, /* .....#..# */
2120 0x0194, /* ##..#.#.. */
2121 0x0029, /* ...#.#..# */
2122 0x0034, /* ...##.#.. */
2123 0x0145, /* #.#...#.# */
2124 0x0058, /* ..#.##... */
2125 0x0128, /* #..#.#... */
2126 0x0053, /* ..#.#..## */
2127 0x0120, /* #..#..... */
2128},
2129{
2130 0x0106, /* #.....##. */
2131 0x011a, /* #...##.#. */
2132 0x0080, /* .#....... */
2133 0x002c, /* ...#.##.. */
2134 0x00ee, /* .###.###. */
2135 0x0068, /* ..##.#... */
2136 0x0002, /* .......#. */
2137 0x00b1, /* .#.##...# */
2138 0x00c1, /* .##.....# */
2139},
2140{
2141 0x00aa, /* .#.#.#.#. */
2142 0x006c, /* ..##.##.. */
2143 0x00c6, /* .##...##. */
2144 0x0028, /* ...#.#... */
2145 0x0101, /* #.......# */
2146 0x0028, /* ...#.#... */
2147 0x00c6, /* .##...##. */
2148 0x006c, /* ..##.##.. */
2149 0x00aa, /* .#.#.#.#. */
2150},
2151{
2152 0x0024, /* ...#..#.. */
2153 0x0182, /* ##.....#. */
2154 0x004a, /* ..#..#.#. */
2155 0x00f2, /* .####..#. */
2156 0x0101, /* #.......# */
2157 0x009e, /* .#..####. */
2158 0x00a4, /* .#.#..#.. */
2159 0x0083, /* .#.....## */
2160 0x0048, /* ..#..#... */
2161},
2162{
2163 0x010b, /* #....#.## */
2164 0x0021, /* ...#....# */
2165 0x0122, /* #..#...#. */
2166 0x003a, /* ...###.#. */
2167 0x0082, /* .#.....#. */
2168 0x00b8, /* .#.###... */
2169 0x0089, /* .#...#..# */
2170 0x0108, /* #....#... */
2171 0x01a1, /* ##.#....# */
2172},
2173{
2174 0x0064, /* ..##..#.. */
2175 0x0198, /* ##..##... */
2176 0x0122, /* #..#...#. */
2177 0x0111, /* #...#...# */
2178 0x0044, /* ..#...#.. */
2179 0x0111, /* #...#...# */
2180 0x0089, /* .#...#..# */
2181 0x0033, /* ...##..## */
2182 0x004c, /* ..#..##.. */
2183},
2184{
2185 0x00a2, /* .#.#...#. */
2186 0x0023, /* ...#...## */
2187 0x006e, /* ..##.###. */
2188 0x00c0, /* .##...... */
2189 0x0101, /* #.......# */
2190 0x0006, /* ......##. */
2191 0x00ec, /* .###.##.. */
2192 0x0188, /* ##...#... */
2193 0x008a, /* .#...#.#. */
2194},
2195{
2196 0x0075, /* ..###.#.# */
2197 0x0161, /* #.##....# */
2198 0x0080, /* .#....... */
2199 0x0148, /* #.#..#... */
2200 0x0044, /* ..#...#.. */
2201 0x0025, /* ...#..#.# */
2202 0x0002, /* .......#. */
2203 0x010d, /* #....##.# */
2204 0x015c, /* #.#.###.. */
2205},
2206{
2207 0x0088, /* .#...#... */
2208 0x0136, /* #..##.##. */
2209 0x0142, /* #.#....#. */
2210 0x00d0, /* .##.#.... */
2211 0x0028, /* ...#.#... */
2212 0x0016, /* ....#.##. */
2213 0x0085, /* .#....#.# */
2214 0x00d9, /* .##.##..# */
2215 0x0022, /* ...#...#. */
2216},
2217{
2218 0x0023, /* ...#...## */
2219 0x00a2, /* .#.#...#. */
2220 0x004c, /* ..#..##.. */
2221 0x0118, /* #...##... */
2222 0x00c6, /* .##...##. */
2223 0x0031, /* ...##...# */
2224 0x0064, /* ..##..#.. */
2225 0x008a, /* .#...#.#. */
2226 0x0188, /* ##...#... */
2227},
2228{
2229 0x012c, /* #..#.##.. */
2230 0x006a, /* ..##.#.#. */
2231 0x0004, /* ......#.. */
2232 0x0098, /* .#..##... */
2233 0x006c, /* ..##.##.. */
2234 0x0032, /* ...##..#. */
2235 0x0040, /* ..#...... */
2236 0x00ac, /* .#.#.##.. */
2237 0x0069, /* ..##.#..# */
2238},
2239{
2240 0x00d4, /* .##.#.#.. */
2241 0x0101, /* #.......# */
2242 0x0150, /* #.#.#.... */
2243 0x0164, /* #.##..#.. */
2244 0x0082, /* .#.....#. */
2245 0x004d, /* ..#..##.# */
2246 0x0015, /* ....#.#.# */
2247 0x0101, /* #.......# */
2248 0x0056, /* ..#.#.##. */
2249},
2250{
2251 0x000e, /* .....###. */
2252 0x0164, /* #.##..#.. */
2253 0x0010, /* ....#.... */
2254 0x0103, /* #......## */
2255 0x01ab, /* ##.#.#.## */
2256 0x0181, /* ##......# */
2257 0x0010, /* ....#.... */
2258 0x004d, /* ..#..##.# */
2259 0x00e0, /* .###..... */
2260},
2261{
2262 0x010a, /* #....#.#. */
2263 0x0032, /* ...##..#. */
2264 0x00a1, /* .#.#....# */
2265 0x00d0, /* .##.#.... */
2266 0x0129, /* #..#.#..# */
2267 0x0016, /* ....#.##. */
2268 0x010a, /* #....#.#. */
2269 0x0098, /* .#..##... */
2270 0x00a1, /* .#.#....# */
2271},
2272{
2273 0x014a, /* #.#..#.#. */
2274 0x0019, /* ....##..# */
2275 0x0114, /* #...#.#.. */
2276 0x0042, /* ..#....#. */
2277 0x006c, /* ..##.##.. */
2278 0x0084, /* .#....#.. */
2279 0x0051, /* ..#.#...# */
2280 0x0130, /* #..##.... */
2281 0x00a5, /* .#.#..#.# */
2282},
2283{
2284 0x0120, /* #..#..... */
2285 0x0159, /* #.#.##..# */
2286 0x00e0, /* .###..... */
2287 0x0006, /* ......##. */
2288 0x0145, /* #.#...#.# */
2289 0x00c0, /* .##...... */
2290 0x000e, /* .....###. */
2291 0x0135, /* #..##.#.# */
2292 0x0009, /* .....#..# */
2293},
2294{
2295 0x0131, /* #..##...# */
2296 0x0086, /* .#....##. */
2297 0x0099, /* .#..##..# */
2298 0x0009, /* .....#..# */
2299 0x0044, /* ..#...#.. */
2300 0x0120, /* #..#..... */
2301 0x0132, /* #..##..#. */
2302 0x00c2, /* .##....#. */
2303 0x0119, /* #...##..# */
2304},
2305{
2306 0x0044, /* ..#...#.. */
2307 0x00aa, /* .#.#.#.#. */
2308 0x0183, /* ##.....## */
2309 0x006c, /* ..##.##.. */
2310 0x0101, /* #.......# */
2311 0x006c, /* ..##.##.. */
2312 0x0183, /* ##.....## */
2313 0x00aa, /* .#.#.#.#. */
2314 0x0044, /* ..#...#.. */
2315},
2316{
2317 0x0168, /* #.##.#... */
2318 0x010c, /* #....##.. */
2319 0x008a, /* .#...#.#. */
2320 0x0091, /* .#..#...# */
2321 0x0082, /* .#.....#. */
2322 0x0112, /* #...#..#. */
2323 0x00a2, /* .#.#...#. */
2324 0x0061, /* ..##....# */
2325 0x002d, /* ...#.##.# */
2326},
2327{
2328 0x0043, /* ..#....## */
2329 0x00d8, /* .##.##... */
2330 0x0120, /* #..#..... */
2331 0x0168, /* #.##.#... */
2332 0x0082, /* .#.....#. */
2333 0x002d, /* ...#.##.# */
2334 0x0009, /* .....#..# */
2335 0x0036, /* ...##.##. */
2336 0x0184, /* ##....#.. */
2337},
2338{
2339 0x01ab, /* ##.#.#.## */
2340 0x0010, /* ....#.... */
2341 0x0082, /* .#.....#. */
2342 0x006c, /* ..##.##.. */
2343 0x0101, /* #.......# */
2344 0x006c, /* ..##.##.. */
2345 0x0082, /* .#.....#. */
2346 0x0010, /* ....#.... */
2347 0x01ab, /* ##.#.#.## */
2348},
2349{
2350 0x0120, /* #..#..... */
2351 0x0190, /* ##..#.... */
2352 0x0046, /* ..#...##. */
2353 0x00a9, /* .#.#.#..# */
2354 0x0129, /* #..#.#..# */
2355 0x012a, /* #..#.#.#. */
2356 0x00c4, /* .##...#.. */
2357 0x0013, /* ....#..## */
2358 0x0009, /* .....#..# */
2359},
2360{
2361 0x00a0, /* .#.#..... */
2362 0x0185, /* ##....#.# */
2363 0x0051, /* ..#.#...# */
2364 0x0158, /* #.#.##... */
2365 0x0082, /* .#.....#. */
2366 0x0035, /* ...##.#.# */
2367 0x0114, /* #...#.#.. */
2368 0x0143, /* #.#....## */
2369 0x000a, /* .....#.#. */
2370},
2371{
2372 0x0101, /* #.......# */
2373 0x00d6, /* .##.#.##. */
2374 0x0145, /* #.#...#.# */
2375 0x006c, /* ..##.##.. */
2376 0x0000, /* ......... */
2377 0x006c, /* ..##.##.. */
2378 0x0145, /* #.#...#.# */
2379 0x00d6, /* .##.#.##. */
2380 0x0101, /* #.......# */
2381},
2382{
2383 0x00e0, /* .###..... */
2384 0x0111, /* #...#...# */
2385 0x0011, /* ....#...# */
2386 0x014a, /* #.#..#.#. */
2387 0x0183, /* ##.....## */
2388 0x00a5, /* .#.#..#.# */
2389 0x0110, /* #...#.... */
2390 0x0111, /* #...#...# */
2391 0x000e, /* .....###. */
2392},
2393{
2394 0x0183, /* ##.....## */
2395 0x0028, /* ...#.#... */
2396 0x0145, /* #.#...#.# */
2397 0x006c, /* ..##.##.. */
2398 0x0082, /* .#.....#. */
2399 0x006c, /* ..##.##.. */
2400 0x0145, /* #.#...#.# */
2401 0x0028, /* ...#.#... */
2402 0x0183, /* ##.....## */
2403},
2404{
2405 0x018c, /* ##...##.. */
2406 0x0131, /* #..##...# */
2407 0x000c, /* .....##.. */
2408 0x0051, /* ..#.#...# */
2409 0x0082, /* .#.....#. */
2410 0x0114, /* #...#.#.. */
2411 0x0060, /* ..##..... */
2412 0x0119, /* #...##..# */
2413 0x0063, /* ..##...## */
2414},
2415{
2416 0x0163, /* #.##...## */
2417 0x0018, /* ....##... */
2418 0x000b, /* .....#.## */
2419 0x0043, /* ..#....## */
2420 0x0000, /* ......... */
2421 0x0184, /* ##....#.. */
2422 0x01a0, /* ##.#..... */
2423 0x0030, /* ...##.... */
2424 0x018d, /* ##...##.# */
2425},
2426{
2427 0x0155, /* #.#.#.#.# */
2428 0x0000, /* ......... */
2429 0x0027, /* ...#..### */
2430 0x0031, /* ...##...# */
2431 0x0129, /* #..#.#..# */
2432 0x0118, /* #...##... */
2433 0x01c8, /* ###..#... */
2434 0x0000, /* ......... */
2435 0x0155, /* #.#.#.#.# */
2436},
2437{
2438 0x0033, /* ...##..## */
2439 0x0199, /* ##..##..# */
2440 0x0000, /* ......... */
2441 0x008a, /* .#...#.#. */
2442 0x00c6, /* .##...##. */
2443 0x00a2, /* .#.#...#. */
2444 0x0000, /* ......... */
2445 0x0133, /* #..##..## */
2446 0x0198, /* ##..##... */
2447},
2448{
2449 0x0183, /* ##.....## */
2450 0x006c, /* ..##.##.. */
2451 0x0101, /* #.......# */
2452 0x006c, /* ..##.##.. */
2453 0x0101, /* #.......# */
2454 0x006c, /* ..##.##.. */
2455 0x0101, /* #.......# */
2456 0x006c, /* ..##.##.. */
2457 0x0183, /* ##.....## */
2458},
2459{
2460 0x008e, /* .#...###. */
2461 0x0043, /* ..#....## */
2462 0x0015, /* ....#.#.# */
2463 0x0031, /* ...##...# */
2464 0x0082, /* .#.....#. */
2465 0x0118, /* #...##... */
2466 0x0150, /* #.#.#.... */
2467 0x0184, /* ##....#.. */
2468 0x00e2, /* .###...#. */
2469},
2470{
2471 0x00b8, /* .#.###... */
2472 0x0021, /* ...#....# */
2473 0x0081, /* .#......# */
2474 0x0103, /* #......## */
2475 0x00ee, /* .###.###. */
2476 0x0181, /* ##......# */
2477 0x0102, /* #......#. */
2478 0x0108, /* #....#... */
2479 0x003a, /* ...###.#. */
2480},
2481{
2482 0x0162, /* #.##...#. */
2483 0x0034, /* ...##.#.. */
2484 0x0108, /* #....#... */
2485 0x0103, /* #......## */
2486 0x0145, /* #.#...#.# */
2487 0x0181, /* ##......# */
2488 0x0021, /* ...#....# */
2489 0x0058, /* ..#.##... */
2490 0x008d, /* .#...##.# */
2491},
2492{
2493 0x0132, /* #..##..#. */
2494 0x00c8, /* .##..#... */
2495 0x0090, /* .#..#.... */
2496 0x005e, /* ..#.####. */
2497 0x0010, /* ....#.... */
2498 0x00f4, /* .####.#.. */
2499 0x0012, /* ....#..#. */
2500 0x0026, /* ...#..##. */
2501 0x0099, /* .#..##..# */
2502},
2503{
2504 0x0031, /* ...##...# */
2505 0x0107, /* #.....### */
2506 0x0042, /* ..#....#. */
2507 0x0031, /* ...##...# */
2508 0x00aa, /* .#.#.#.#. */
2509 0x0118, /* #...##... */
2510 0x0084, /* .#....#.. */
2511 0x01c1, /* ###.....# */
2512 0x0118, /* #...##... */
2513},
2514{
2515 0x0042, /* ..#....#. */
2516 0x0183, /* ##.....## */
2517 0x0066, /* ..##..##. */
2518 0x011a, /* #...##.#. */
2519 0x0010, /* ....#.... */
2520 0x00b1, /* .#.##...# */
2521 0x00cc, /* .##..##.. */
2522 0x0183, /* ##.....## */
2523 0x0084, /* .#....#.. */
2524},
2525{
2526 0x00aa, /* .#.#.#.#. */
2527 0x0028, /* ...#.#... */
2528 0x0145, /* #.#...#.# */
2529 0x006c, /* ..##.##.. */
2530 0x0101, /* #.......# */
2531 0x006c, /* ..##.##.. */
2532 0x0145, /* #.#...#.# */
2533 0x0028, /* ...#.#... */
2534 0x00aa, /* .#.#.#.#. */
2535},
2536{
2537 0x0032, /* ...##..#. */
2538 0x003a, /* ...###.#. */
2539 0x010c, /* #....##.. */
2540 0x0105, /* #.....#.# */
2541 0x0028, /* ...#.#... */
2542 0x0141, /* #.#.....# */
2543 0x0061, /* ..##....# */
2544 0x00b8, /* .#.###... */
2545 0x0098, /* .#..##... */
2546},
2547{
2548 0x0106, /* #.....##. */
2549 0x00c8, /* .##..#... */
2550 0x004c, /* ..#..##.. */
2551 0x0112, /* #...#..#. */
2552 0x00c6, /* .##...##. */
2553 0x0091, /* .#..#...# */
2554 0x0064, /* ..##..#.. */
2555 0x0026, /* ...#..##. */
2556 0x00c1, /* .##.....# */
2557},
2558{
2559 0x0049, /* ..#..#..# */
2560 0x0110, /* #...#.... */
2561 0x0046, /* ..#...##. */
2562 0x0131, /* #..##...# */
2563 0x0129, /* #..#.#..# */
2564 0x0119, /* #...##..# */
2565 0x00c4, /* .##...#.. */
2566 0x0011, /* ....#...# */
2567 0x0124, /* #..#..#.. */
2568},
2569{
2570 0x0095, /* .#..#.#.# */
2571 0x0118, /* #...##... */
2572 0x0021, /* ...#....# */
2573 0x003e, /* ...#####. */
2574 0x0010, /* ....#.... */
2575 0x00f8, /* .#####... */
2576 0x0108, /* #....#... */
2577 0x0031, /* ...##...# */
2578 0x0152, /* #.#.#..#. */
2579},
2580{
2581 0x0009, /* .....#..# */
2582 0x014c, /* #.#..##.. */
2583 0x0083, /* .#.....## */
2584 0x0051, /* ..#.#...# */
2585 0x0028, /* ...#.#... */
2586 0x0114, /* #...#.#.. */
2587 0x0182, /* ##.....#. */
2588 0x0065, /* ..##..#.# */
2589 0x0120, /* #..#..... */
2590},
2591{
2592 0x0014, /* ....#.#.. */
2593 0x008b, /* .#...#.## */
2594 0x0110, /* #...#.... */
2595 0x004b, /* ..#..#.## */
2596 0x0101, /* #.......# */
2597 0x01a4, /* ##.#..#.. */
2598 0x0011, /* ....#...# */
2599 0x01a2, /* ##.#...#. */
2600 0x0050, /* ..#.#.... */
2601},
2602{
2603 0x0114, /* #...#.#.. */
2604 0x010d, /* #....##.# */
2605 0x0024, /* ...#..#.. */
2606 0x006d, /* ..##.##.# */
2607 0x0000, /* ......... */
2608 0x016c, /* #.##.##.. */
2609 0x0048, /* ..#..#... */
2610 0x0161, /* #.##....# */
2611 0x0051, /* ..#.#...# */
2612},
2613{
2614 0x0092, /* .#..#..#. */
2615 0x002a, /* ...#.#.#. */
2616 0x0013, /* ....#..## */
2617 0x010e, /* #....###. */
2618 0x00aa, /* .#.#.#.#. */
2619 0x00e1, /* .###....# */
2620 0x0190, /* ##..#.... */
2621 0x00a8, /* .#.#.#... */
2622 0x0092, /* .#..#..#. */
2623},
2624{
2625 0x00d1, /* .##.#...# */
2626 0x0084, /* .#....#.. */
2627 0x0158, /* #.#.##... */
2628 0x0064, /* ..##..#.. */
2629 0x0028, /* ...#.#... */
2630 0x004c, /* ..#..##.. */
2631 0x0035, /* ...##.#.# */
2632 0x0042, /* ..#....#. */
2633 0x0116, /* #...#.##. */
2634},
2635{
2636 0x000b, /* .....#.## */
2637 0x0180, /* ##....... */
2638 0x000d, /* .....##.# */
2639 0x019a, /* ##..##.#. */
2640 0x0082, /* .#.....#. */
2641 0x00b3, /* .#.##..## */
2642 0x0160, /* #.##..... */
2643 0x0003, /* .......## */
2644 0x01a0, /* ##.#..... */
2645},
2646{
2647 0x00a6, /* .#.#..##. */
2648 0x0115, /* #...#.#.# */
2649 0x0110, /* #...#.... */
2650 0x00ca, /* .##..#.#. */
2651 0x0010, /* ....#.... */
2652 0x00a6, /* .#.#..##. */
2653 0x0011, /* ....#...# */
2654 0x0151, /* #.#.#...# */
2655 0x00ca, /* .##..#.#. */
2656},
2657{
2658 0x0058, /* ..#.##... */
2659 0x0064, /* ..##..#.. */
2660 0x0023, /* ...#...## */
2661 0x0065, /* ..##..#.# */
2662 0x0082, /* .#.....#. */
2663 0x014c, /* #.#..##.. */
2664 0x0188, /* ##...#... */
2665 0x004c, /* ..#..##.. */
2666 0x0034, /* ...##.#.. */
2667},
2668{
2669 0x0120, /* #..#..... */
2670 0x00b9, /* .#.###..# */
2671 0x005a, /* ..#.##.#. */
2672 0x0108, /* #....#... */
2673 0x0044, /* ..#...#.. */
2674 0x0021, /* ...#....# */
2675 0x00b4, /* .#.##.#.. */
2676 0x013a, /* #..###.#. */
2677 0x0009, /* .....#..# */
2678},
2679{
2680 0x0183, /* ##.....## */
2681 0x0064, /* ..##..#.. */
2682 0x0128, /* #..#.#... */
2683 0x0116, /* #...#.##. */
2684 0x0010, /* ....#.... */
2685 0x00d1, /* .##.#...# */
2686 0x0029, /* ...#.#..# */
2687 0x004c, /* ..#..##.. */
2688 0x0183, /* ##.....## */
2689},
2690{
2691 0x006c, /* ..##.##.. */
2692 0x00aa, /* .#.#.#.#. */
2693 0x0101, /* #.......# */
2694 0x007c, /* ..#####.. */
2695 0x0000, /* ......... */
2696 0x007c, /* ..#####.. */
2697 0x0101, /* #.......# */
2698 0x00aa, /* .#.#.#.#. */
2699 0x006c, /* ..##.##.. */
2700},
2701{
2702 0x009a, /* .#..##.#. */
2703 0x0100, /* #........ */
2704 0x001b, /* ....##.## */
2705 0x0154, /* #.#.#.#.. */
2706 0x0028, /* ...#.#... */
2707 0x0055, /* ..#.#.#.# */
2708 0x01b0, /* ##.##.... */
2709 0x0001, /* ........# */
2710 0x00b2, /* .#.##..#. */
2711},
2712{
2713 0x0188, /* ##...#... */
2714 0x0023, /* ...#...## */
2715 0x0171, /* #.###...# */
2716 0x00b0, /* .#.##.... */
2717 0x0000, /* ......... */
2718 0x001a, /* ....##.#. */
2719 0x011d, /* #...###.# */
2720 0x0188, /* ##...#... */
2721 0x0023, /* ...#...## */
2722},
2723{
2724 0x011d, /* #...###.# */
2725 0x0182, /* ##.....#. */
2726 0x001a, /* ....##.#. */
2727 0x0084, /* .#....#.. */
2728 0x0028, /* ...#.#... */
2729 0x0042, /* ..#....#. */
2730 0x00b0, /* .#.##.... */
2731 0x0083, /* .#.....## */
2732 0x0171, /* #.###...# */
2733},
2734{
2735 0x0082, /* .#.....#. */
2736 0x0054, /* ..#.#.#.. */
2737 0x0183, /* ##.....## */
2738 0x007c, /* ..#####.. */
2739 0x0000, /* ......... */
2740 0x007c, /* ..#####.. */
2741 0x0183, /* ##.....## */
2742 0x0054, /* ..#.#.#.. */
2743 0x0082, /* .#.....#. */
2744},
2745{
2746 0x0028, /* ...#.#... */
2747 0x0082, /* .#.....#. */
2748 0x0145, /* #.#...#.# */
2749 0x007c, /* ..#####.. */
2750 0x0101, /* #.......# */
2751 0x007c, /* ..#####.. */
2752 0x0145, /* #.#...#.# */
2753 0x0082, /* .#.....#. */
2754 0x0028, /* ...#.#... */
2755},
2756{
2757 0x0044, /* ..#...#.. */
2758 0x000b, /* .....#.## */
2759 0x01b0, /* ##.##.... */
2760 0x0003, /* .......## */
2761 0x01c7, /* ###...### */
2762 0x0180, /* ##....... */
2763 0x001b, /* ....##.## */
2764 0x01a0, /* ##.#..... */
2765 0x0044, /* ..#...#.. */
2766},
2767{
2768 0x0116, /* #...#.##. */
2769 0x00b4, /* .#.##.#.. */
2770 0x0008, /* .....#... */
2771 0x00c5, /* .##...#.# */
2772 0x0101, /* #.......# */
2773 0x0146, /* #.#...##. */
2774 0x0020, /* ...#..... */
2775 0x005a, /* ..#.##.#. */
2776 0x00d1, /* .##.#...# */
2777},
2778{
2779 0x0081, /* .#......# */
2780 0x0039, /* ...###..# */
2781 0x010e, /* #....###. */
2782 0x0088, /* .#...#... */
2783 0x0044, /* ..#...#.. */
2784 0x0022, /* ...#...#. */
2785 0x00e1, /* .###....# */
2786 0x0138, /* #..###... */
2787 0x0102, /* #......#. */
2788},
2789{
2790 0x0014, /* ....#.#.. */
2791 0x0182, /* ##.....#. */
2792 0x00e4, /* .###..#.. */
2793 0x0066, /* ..##..##. */
2794 0x0028, /* ...#.#... */
2795 0x00cc, /* .##..##.. */
2796 0x004e, /* ..#..###. */
2797 0x0083, /* .#.....## */
2798 0x0050, /* ..#.#.... */
2799},
2800{
2801 0x00a1, /* .#.#....# */
2802 0x0023, /* ...#...## */
2803 0x01a0, /* ##.#..... */
2804 0x00b5, /* .#.##.#.# */
2805 0x0000, /* ......... */
2806 0x015a, /* #.#.##.#. */
2807 0x000b, /* .....#.## */
2808 0x0188, /* ##...#... */
2809 0x010a, /* #....#.#. */
2810},
2811{
2812 0x0159, /* #.#.##..# */
2813 0x00a1, /* .#.#....# */
2814 0x00a2, /* .#.#...#. */
2815 0x0102, /* #......#. */
2816 0x006c, /* ..##.##.. */
2817 0x0081, /* .#......# */
2818 0x008a, /* .#...#.#. */
2819 0x010a, /* #....#.#. */
2820 0x0134, /* #..##.#.. */
2821},
2822{
2823 0x008b, /* .#...#.## */
2824 0x004c, /* ..#..##.. */
2825 0x0001, /* ........# */
2826 0x01a4, /* ##.#..#.. */
2827 0x0129, /* #..#.#..# */
2828 0x004b, /* ..#..#.## */
2829 0x0100, /* #........ */
2830 0x0064, /* ..##..#.. */
2831 0x01a2, /* ##.#...#. */
2832},
2833{
2834 0x0028, /* ...#.#... */
2835 0x00ee, /* .###.###. */
2836 0x00c6, /* .##...##. */
2837 0x0028, /* ...#.#... */
2838 0x0101, /* #.......# */
2839 0x0028, /* ...#.#... */
2840 0x00c6, /* .##...##. */
2841 0x00ee, /* .###.###. */
2842 0x0028, /* ...#.#... */
2843},
2844{
2845 0x0159, /* #.#.##..# */
2846 0x005c, /* ..#.###.. */
2847 0x0000, /* ......... */
2848 0x0052, /* ..#.#..#. */
2849 0x0145, /* #.#...#.# */
2850 0x0094, /* .#..#.#.. */
2851 0x0000, /* ......... */
2852 0x0074, /* ..###.#.. */
2853 0x0135, /* #..##.#.# */
2854},
2855{
2856 0x0130, /* #..##.... */
2857 0x0116, /* #...#.##. */
2858 0x0088, /* .#...#... */
2859 0x0107, /* #.....### */
2860 0x0028, /* ...#.#... */
2861 0x01c1, /* ###.....# */
2862 0x0022, /* ...#...#. */
2863 0x00d1, /* .##.#...# */
2864 0x0019, /* ....##..# */
2865},
2866{
2867 0x0102, /* #......#. */
2868 0x012c, /* #..#.##.. */
2869 0x000b, /* .....#.## */
2870 0x01c8, /* ###..#... */
2871 0x0044, /* ..#...#.. */
2872 0x0027, /* ...#..### */
2873 0x01a0, /* ##.#..... */
2874 0x0069, /* ..##.#..# */
2875 0x0081, /* .#......# */
2876}
2877};
diff --git a/apps/plugins/sudoku/templates.h b/apps/plugins/sudoku/templates.h
new file mode 100644
index 0000000000..a8d639b4f6
--- /dev/null
+++ b/apps/plugins/sudoku/templates.h
@@ -0,0 +1,8 @@
1
2#ifndef _TEMPLATES_H
3#define _TEMPLATES_H
4
5#define NUM_TEMPLATES 261
6extern const unsigned short templates[NUM_TEMPLATES][9];
7
8#endif