From 09aa8de52cb962f1ceebfb1fd44f2c54a924fc5c Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Mon, 22 Jul 2024 21:43:25 -0400 Subject: puzzles: resync with upstream This brings the puzzles source in sync with Simon's branch, commit fd304c5 (from March 2024), with some added Rockbox-specific compatibility changes: https://www.franklinwei.com/git/puzzles/commit/?h=rockbox-devel&id=516830d9d76bdfe64fe5ccf2a9b59c33f5c7c078 There are quite a lot of backend changes, including a new "Mosaic" puzzle. In addition, some new frontend changes were necessary: - New "Preferences" menu to access the user preferences system. - Enabled spacebar input for several games. Change-Id: I94c7df674089c92f32d5f07025f6a1059068af1e --- apps/plugins/CATEGORIES | 1 + apps/plugins/puzzles/SOURCES | 4 + apps/plugins/puzzles/SOURCES.games | 4 +- apps/plugins/puzzles/genhelp.sh | 23 +- apps/plugins/puzzles/help/blackbox.c | 653 +++---- apps/plugins/puzzles/help/bridges.c | 672 +++---- apps/plugins/puzzles/help/cube.c | 307 ++-- apps/plugins/puzzles/help/dominosa.c | 328 ++-- apps/plugins/puzzles/help/fifteen.c | 240 +-- apps/plugins/puzzles/help/filling.c | 260 +-- apps/plugins/puzzles/help/flip.c | 236 +-- apps/plugins/puzzles/help/flood.c | 338 ++-- apps/plugins/puzzles/help/galaxies.c | 390 ++-- apps/plugins/puzzles/help/guess.c | 419 +++-- apps/plugins/puzzles/help/inertia.c | 331 ++-- apps/plugins/puzzles/help/keen.c | 495 ++--- apps/plugins/puzzles/help/lightup.c | 345 ++-- apps/plugins/puzzles/help/loopy.c | 424 +++-- apps/plugins/puzzles/help/magnets.c | 353 ++-- apps/plugins/puzzles/help/map.c | 502 ++--- apps/plugins/puzzles/help/mines.c | 494 ++--- apps/plugins/puzzles/help/mosaic.c | 150 ++ apps/plugins/puzzles/help/net.c | 543 +++--- apps/plugins/puzzles/help/netslide.c | 91 +- apps/plugins/puzzles/help/nullgame.c | 1 + apps/plugins/puzzles/help/palisade.c | 145 +- apps/plugins/puzzles/help/pattern.c | 182 +- apps/plugins/puzzles/help/pearl.c | 407 +++-- apps/plugins/puzzles/help/pegs.c | 267 +-- apps/plugins/puzzles/help/range.c | 303 ++-- apps/plugins/puzzles/help/rect.c | 493 +++-- apps/plugins/puzzles/help/samegame.c | 347 ++-- apps/plugins/puzzles/help/signpost.c | 406 +++-- apps/plugins/puzzles/help/singles.c | 251 +-- apps/plugins/puzzles/help/sixteen.c | 369 ++-- apps/plugins/puzzles/help/slant.c | 319 ++-- apps/plugins/puzzles/help/solo.c | 743 ++++---- apps/plugins/puzzles/help/tents.c | 299 +-- apps/plugins/puzzles/help/towers.c | 480 ++--- apps/plugins/puzzles/help/tracks.c | 233 +-- apps/plugins/puzzles/help/twiddle.c | 385 ++-- apps/plugins/puzzles/help/undead.c | 456 ++--- apps/plugins/puzzles/help/unequal.c | 490 ++--- apps/plugins/puzzles/help/unruly.c | 263 +-- apps/plugins/puzzles/help/untangle.c | 150 +- apps/plugins/puzzles/rbcompat.h | 2 + apps/plugins/puzzles/resync.sh | 5 +- apps/plugins/puzzles/rockbox.c | 75 +- apps/plugins/puzzles/src/CMakeLists.txt | 287 +++ apps/plugins/puzzles/src/LICENCE | 4 +- apps/plugins/puzzles/src/README | 46 +- apps/plugins/puzzles/src/blackbox.R | 19 - apps/plugins/puzzles/src/blackbox.c | 115 +- apps/plugins/puzzles/src/bridges.R | 21 - apps/plugins/puzzles/src/bridges.c | 210 ++- apps/plugins/puzzles/src/combi.c | 37 - apps/plugins/puzzles/src/cube.R | 19 - apps/plugins/puzzles/src/cube.c | 110 +- apps/plugins/puzzles/src/devel.but | 1607 +++++++++++++--- apps/plugins/puzzles/src/divvy.c | 141 +- apps/plugins/puzzles/src/dominosa.R | 24 - apps/plugins/puzzles/src/dominosa.c | 136 +- apps/plugins/puzzles/src/drawing.c | 16 +- apps/plugins/puzzles/src/dsf.c | 411 +++-- apps/plugins/puzzles/src/emcc.c | 483 +++-- apps/plugins/puzzles/src/emcccopy.but | 128 ++ apps/plugins/puzzles/src/fifteen.R | 22 - apps/plugins/puzzles/src/fifteen.c | 259 +-- apps/plugins/puzzles/src/filling.R | 24 - apps/plugins/puzzles/src/filling.c | 198 +- apps/plugins/puzzles/src/flip.R | 21 - apps/plugins/puzzles/src/flip.c | 89 +- apps/plugins/puzzles/src/flood.R | 19 - apps/plugins/puzzles/src/flood.c | 184 +- apps/plugins/puzzles/src/fuzzpuzz.c | 250 +++ apps/plugins/puzzles/src/galaxies.R | 28 - apps/plugins/puzzles/src/galaxies.c | 734 ++++++-- apps/plugins/puzzles/src/grid.c | 1357 ++++++++++---- apps/plugins/puzzles/src/grid.h | 23 +- apps/plugins/puzzles/src/gtk.c | 550 +++++- apps/plugins/puzzles/src/gtk.h | 7 + apps/plugins/puzzles/src/guess.R | 19 - apps/plugins/puzzles/src/guess.c | 221 ++- apps/plugins/puzzles/src/hat-internal.h | 271 +++ apps/plugins/puzzles/src/hat-tables.h | 2120 ++++++++++++++++++++++ apps/plugins/puzzles/src/hat.c | 891 +++++++++ apps/plugins/puzzles/src/hat.h | 67 + apps/plugins/puzzles/src/inertia.R | 19 - apps/plugins/puzzles/src/inertia.c | 76 +- apps/plugins/puzzles/src/keen.R | 25 - apps/plugins/puzzles/src/keen.c | 250 +-- apps/plugins/puzzles/src/latin.c | 164 +- apps/plugins/puzzles/src/latin.h | 9 +- apps/plugins/puzzles/src/lightup.R | 24 - apps/plugins/puzzles/src/lightup.c | 137 +- apps/plugins/puzzles/src/list.c | 17 + apps/plugins/puzzles/src/loopgen.c | 16 +- apps/plugins/puzzles/src/loopgen.h | 6 +- apps/plugins/puzzles/src/loopy.R | 31 - apps/plugins/puzzles/src/loopy.c | 576 +++--- apps/plugins/puzzles/src/magnets.R | 24 - apps/plugins/puzzles/src/magnets.c | 125 +- apps/plugins/puzzles/src/malloc.c | 13 +- apps/plugins/puzzles/src/map.R | 24 - apps/plugins/puzzles/src/map.c | 259 ++- apps/plugins/puzzles/src/matching.c | 424 +---- apps/plugins/puzzles/src/matching.h | 28 + apps/plugins/puzzles/src/midend.c | 797 ++++++-- apps/plugins/puzzles/src/mines.R | 24 - apps/plugins/puzzles/src/mines.c | 218 ++- apps/plugins/puzzles/src/misc.c | 278 ++- apps/plugins/puzzles/src/mosaic.c | 1626 +++++++++++++++++ apps/plugins/puzzles/src/nestedvm.c | 14 +- apps/plugins/puzzles/src/net.R | 23 - apps/plugins/puzzles/src/net.c | 231 ++- apps/plugins/puzzles/src/netslide.R | 21 - apps/plugins/puzzles/src/netslide.c | 105 +- apps/plugins/puzzles/src/no-icon.c | 2 + apps/plugins/puzzles/src/nullfe.c | 24 +- apps/plugins/puzzles/src/nullgame.R | 12 - apps/plugins/puzzles/src/nullgame.c | 80 +- apps/plugins/puzzles/src/obfusc.c | 130 -- apps/plugins/puzzles/src/palisade.R | 21 - apps/plugins/puzzles/src/palisade.c | 172 +- apps/plugins/puzzles/src/pattern.R | 25 - apps/plugins/puzzles/src/pattern.c | 224 ++- apps/plugins/puzzles/src/pearl.R | 23 - apps/plugins/puzzles/src/pearl.c | 499 +++-- apps/plugins/puzzles/src/pegs.R | 21 - apps/plugins/puzzles/src/pegs.c | 172 +- apps/plugins/puzzles/src/penrose-internal.h | 289 +++ apps/plugins/puzzles/src/penrose-legacy.c | 506 ++++++ apps/plugins/puzzles/src/penrose-legacy.h | 63 + apps/plugins/puzzles/src/penrose.c | 1271 ++++++++----- apps/plugins/puzzles/src/penrose.h | 119 +- apps/plugins/puzzles/src/printing.c | 15 +- apps/plugins/puzzles/src/ps.c | 2 +- apps/plugins/puzzles/src/puzzles.but | 341 +++- apps/plugins/puzzles/src/puzzles.h | 165 +- apps/plugins/puzzles/src/random.c | 6 +- apps/plugins/puzzles/src/range.R | 21 - apps/plugins/puzzles/src/range.c | 182 +- apps/plugins/puzzles/src/rect.R | 19 - apps/plugins/puzzles/src/rect.c | 82 +- apps/plugins/puzzles/src/resource.h | 20 - apps/plugins/puzzles/src/samegame.R | 19 - apps/plugins/puzzles/src/samegame.c | 182 +- apps/plugins/puzzles/src/signpost.R | 23 - apps/plugins/puzzles/src/signpost.c | 185 +- apps/plugins/puzzles/src/singles.R | 23 - apps/plugins/puzzles/src/singles.c | 111 +- apps/plugins/puzzles/src/sixteen.R | 19 - apps/plugins/puzzles/src/sixteen.c | 87 +- apps/plugins/puzzles/src/slant.R | 24 - apps/plugins/puzzles/src/slant.c | 180 +- apps/plugins/puzzles/src/solo.R | 24 - apps/plugins/puzzles/src/solo.c | 197 +- apps/plugins/puzzles/src/sort.c | 91 +- apps/plugins/puzzles/src/spectre-internal.h | 327 ++++ apps/plugins/puzzles/src/spectre-tables-auto.h | 1220 +++++++++++++ apps/plugins/puzzles/src/spectre-tables-manual.h | 160 ++ apps/plugins/puzzles/src/spectre.c | 599 ++++++ apps/plugins/puzzles/src/spectre.h | 72 + apps/plugins/puzzles/src/tents.R | 24 - apps/plugins/puzzles/src/tents.c | 121 +- apps/plugins/puzzles/src/towers.R | 25 - apps/plugins/puzzles/src/towers.c | 199 +- apps/plugins/puzzles/src/tracks.R | 24 - apps/plugins/puzzles/src/tracks.c | 351 ++-- apps/plugins/puzzles/src/tree234.c | 782 +------- apps/plugins/puzzles/src/tree234.h | 24 +- apps/plugins/puzzles/src/twiddle.R | 19 - apps/plugins/puzzles/src/twiddle.c | 94 +- apps/plugins/puzzles/src/undead.R | 18 - apps/plugins/puzzles/src/undead.c | 210 ++- apps/plugins/puzzles/src/unequal.R | 25 - apps/plugins/puzzles/src/unequal.c | 193 +- apps/plugins/puzzles/src/unruly.R | 21 - apps/plugins/puzzles/src/unruly.c | 189 +- apps/plugins/puzzles/src/untangle.R | 21 - apps/plugins/puzzles/src/untangle.c | 512 ++++-- apps/plugins/puzzles/src/version.c | 1 + apps/plugins/puzzles/src/version.h | 2 + apps/plugins/puzzles/src/windows.c | 807 +++----- 184 files changed, 27699 insertions(+), 15438 deletions(-) create mode 100644 apps/plugins/puzzles/help/mosaic.c create mode 100644 apps/plugins/puzzles/help/nullgame.c create mode 100644 apps/plugins/puzzles/src/CMakeLists.txt delete mode 100644 apps/plugins/puzzles/src/blackbox.R delete mode 100644 apps/plugins/puzzles/src/bridges.R delete mode 100644 apps/plugins/puzzles/src/cube.R delete mode 100644 apps/plugins/puzzles/src/dominosa.R create mode 100644 apps/plugins/puzzles/src/emcccopy.but delete mode 100644 apps/plugins/puzzles/src/fifteen.R delete mode 100644 apps/plugins/puzzles/src/filling.R delete mode 100644 apps/plugins/puzzles/src/flip.R delete mode 100644 apps/plugins/puzzles/src/flood.R create mode 100644 apps/plugins/puzzles/src/fuzzpuzz.c delete mode 100644 apps/plugins/puzzles/src/galaxies.R create mode 100644 apps/plugins/puzzles/src/gtk.h delete mode 100644 apps/plugins/puzzles/src/guess.R create mode 100644 apps/plugins/puzzles/src/hat-internal.h create mode 100644 apps/plugins/puzzles/src/hat-tables.h create mode 100644 apps/plugins/puzzles/src/hat.c create mode 100644 apps/plugins/puzzles/src/hat.h delete mode 100644 apps/plugins/puzzles/src/inertia.R delete mode 100644 apps/plugins/puzzles/src/keen.R delete mode 100644 apps/plugins/puzzles/src/lightup.R create mode 100644 apps/plugins/puzzles/src/list.c delete mode 100644 apps/plugins/puzzles/src/loopy.R delete mode 100644 apps/plugins/puzzles/src/magnets.R delete mode 100644 apps/plugins/puzzles/src/map.R delete mode 100644 apps/plugins/puzzles/src/mines.R create mode 100644 apps/plugins/puzzles/src/mosaic.c delete mode 100644 apps/plugins/puzzles/src/net.R delete mode 100644 apps/plugins/puzzles/src/netslide.R delete mode 100644 apps/plugins/puzzles/src/nullgame.R delete mode 100644 apps/plugins/puzzles/src/obfusc.c delete mode 100644 apps/plugins/puzzles/src/palisade.R delete mode 100644 apps/plugins/puzzles/src/pattern.R delete mode 100644 apps/plugins/puzzles/src/pearl.R delete mode 100644 apps/plugins/puzzles/src/pegs.R create mode 100644 apps/plugins/puzzles/src/penrose-internal.h create mode 100644 apps/plugins/puzzles/src/penrose-legacy.c create mode 100644 apps/plugins/puzzles/src/penrose-legacy.h delete mode 100644 apps/plugins/puzzles/src/range.R delete mode 100644 apps/plugins/puzzles/src/rect.R delete mode 100644 apps/plugins/puzzles/src/resource.h delete mode 100644 apps/plugins/puzzles/src/samegame.R delete mode 100644 apps/plugins/puzzles/src/signpost.R delete mode 100644 apps/plugins/puzzles/src/singles.R delete mode 100644 apps/plugins/puzzles/src/sixteen.R delete mode 100644 apps/plugins/puzzles/src/slant.R delete mode 100644 apps/plugins/puzzles/src/solo.R create mode 100644 apps/plugins/puzzles/src/spectre-internal.h create mode 100644 apps/plugins/puzzles/src/spectre-tables-auto.h create mode 100644 apps/plugins/puzzles/src/spectre-tables-manual.h create mode 100644 apps/plugins/puzzles/src/spectre.c create mode 100644 apps/plugins/puzzles/src/spectre.h delete mode 100644 apps/plugins/puzzles/src/tents.R delete mode 100644 apps/plugins/puzzles/src/towers.R delete mode 100644 apps/plugins/puzzles/src/tracks.R delete mode 100644 apps/plugins/puzzles/src/twiddle.R delete mode 100644 apps/plugins/puzzles/src/undead.R delete mode 100644 apps/plugins/puzzles/src/unequal.R delete mode 100644 apps/plugins/puzzles/src/unruly.R delete mode 100644 apps/plugins/puzzles/src/untangle.R (limited to 'apps/plugins') diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 366c42c75b..814fb2f130 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -128,6 +128,7 @@ sgt-loopy,games sgt-magnets,games sgt-map,games sgt-mines,games +sgt-mosaic,games sgt-net,games sgt-netslide,games sgt-palisade,games diff --git a/apps/plugins/puzzles/SOURCES b/apps/plugins/puzzles/SOURCES index 5301ceef3d..58a16bc9b9 100644 --- a/apps/plugins/puzzles/SOURCES +++ b/apps/plugins/puzzles/SOURCES @@ -17,6 +17,7 @@ src/matching.c src/midend.c src/misc.c src/penrose.c +src/penrose-legacy.c src/printing.c src/random.c src/sort.c @@ -24,6 +25,9 @@ src/tdq.c src/tree234.c src/version.c +src/hat.c +src/spectre.c + #ifdef COMBINED src/list.c #endif diff --git a/apps/plugins/puzzles/SOURCES.games b/apps/plugins/puzzles/SOURCES.games index 2b80ea3300..29af18e7b8 100644 --- a/apps/plugins/puzzles/SOURCES.games +++ b/apps/plugins/puzzles/SOURCES.games @@ -16,6 +16,7 @@ src/lightup.c src/magnets.c src/map.c src/mines.c +src/mosaic.c src/net.c src/netslide.c src/palisade.c @@ -37,7 +38,8 @@ src/unequal.c src/unruly.c src/untangle.c -/* disabled for now (fix puzzles.make and CATEGORIES to accomodate these) */ +/* Disabled for now. Fix puzzles.make and CATEGORIES to accomodate these. */ +/* The help system would also need to be patched to compile these. */ /*src/unfinished/group.c*/ /*src/unfinished/separate.c*/ /*src/unfinished/slide.c*/ diff --git a/apps/plugins/puzzles/genhelp.sh b/apps/plugins/puzzles/genhelp.sh index 3df7706b5d..f515bb25dc 100755 --- a/apps/plugins/puzzles/genhelp.sh +++ b/apps/plugins/puzzles/genhelp.sh @@ -36,6 +36,9 @@ BEGIN { if($3 ~ "Rectangles") file = "help/rect.c"; + if($3 ~ "Train") + file = "help/tracks.c"; + print "/* auto-generated by genhelp.sh (intermediate file) */" > file; print "/* DO NOT EDIT! */" > file; print "const char help_text[] = " > file; @@ -87,8 +90,24 @@ do mv $f.tmp $f done -# generate quick help from all the .R files -cat src/*.R | awk 'print_next { print_next = 0; print; } /!begin/ && />/ && /gamedesc.txt/ { print_next = 1; }' | awk -F ":" '{print "const char quick_help_text[] = \""$5"\";" >> "help/"$1".c" }' +# Generate quick help by parsing the CMakeLists.txt file to isolate +# the "Objective" text for each puzzle. +cat < parsed_cmakelists.txt +function(puzzle NAME) + cmake_parse_arguments(OPT + "" "DISPLAYNAME;DESCRIPTION;OBJECTIVE;WINDOWS_EXE_NAME" "" \${ARGN}) + + message("\${NAME}:\${OPT_OBJECTIVE}") +endfunction() +EOF + +# This parses out the puzzle(...) definitions from CMakeLists. + +# TODO: Perhaps ask Simon to include special header/footer comments to +# make this less brittle? +cat src/CMakeLists.txt | awk '/puzzle\(/{p=1} p{print} /\)/{p=0}' >> parsed_cmakelists.txt +cmake -P parsed_cmakelists.txt 2>&1 | awk -F ":" '{print "const char quick_help_text[] = \""$2"\";" >> "help/"$1".c" }' +rm parsed_cmakelists.txt rm puzzles.txt rm compress diff --git a/apps/plugins/puzzles/help/blackbox.c b/apps/plugins/puzzles/help/blackbox.c index 0121ee3f93..f01852becf 100644 --- a/apps/plugins/puzzles/help/blackbox.c +++ b/apps/plugins/puzzles/help/blackbox.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,337 +6,338 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 450, TEXT_UNDERLINE }, - { 476, TEXT_UNDERLINE }, - { 503, TEXT_CENTER | C_RED }, - { 869, TEXT_UNDERLINE }, - { 897, TEXT_CENTER | C_RED }, - { 914, TEXT_UNDERLINE }, + { 451, TEXT_UNDERLINE }, + { 477, TEXT_UNDERLINE }, + { 504, TEXT_CENTER | C_RED }, + { 870, TEXT_UNDERLINE }, + { 898, TEXT_CENTER | C_RED }, { 915, TEXT_UNDERLINE }, - { 927, TEXT_UNDERLINE }, - { 929, TEXT_UNDERLINE }, - { 942, TEXT_UNDERLINE }, + { 916, TEXT_UNDERLINE }, + { 928, TEXT_UNDERLINE }, + { 930, TEXT_UNDERLINE }, + { 943, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 5458 comp 3139 ratio 0.575119 level 10 saved 2319 */ +/* orig 5480 comp 3142 ratio 0.573358 level 10 saved 2338 */ const char help_text[] = { -0xf0, 0x37, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x09, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x39, 0x3a, 0x20, 0x42, 0x6c, 0x61, 0x63, 0x6b, 0x20, -0x42, 0x6f, 0x78, 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x6e, -0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x6f, 0x66, 0x00, 0x62, -0x61, 0x6c, 0x6c, 0x73, 0x00, 0x61, 0x72, 0x65, 0x00, 0x68, -0x69, 0x64, 0x64, 0x65, 0x6e, 0x00, 0x69, 0x6e, 0x00, 0x61, -0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x75, 0x6c, -0x61, 0x72, 0x1c, 0x00, 0xf0, 0x15, 0x6e, 0x61, 0x2e, 0x00, -0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x74, -0x6f, 0x00, 0x64, 0x65, 0x64, 0x75, 0x63, 0x65, 0x00, 0x74, -0x68, 0x65, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, -0x6e, 0x73, 0x4d, 0x00, 0x00, 0x11, 0x00, 0x02, 0x51, 0x00, -0xf5, 0x01, 0x62, 0x79, 0x00, 0x66, 0x69, 0x72, 0x69, 0x6e, -0x67, 0x00, 0x6c, 0x61, 0x73, 0x65, 0x72, 0x73, 0x28, 0x00, -0x51, 0x65, 0x64, 0x00, 0x61, 0x74, 0x29, 0x00, 0x45, 0x65, -0x64, 0x67, 0x65, 0x36, 0x00, 0x01, 0x65, 0x00, 0xb0, 0x00, -0x61, 0x6e, 0x64, 0x00, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, -0x3a, 0x00, 0x30, 0x68, 0x6f, 0x77, 0x1c, 0x00, 0x72, 0x69, -0x72, 0x00, 0x62, 0x65, 0x61, 0x6d, 0xa5, 0x00, 0xe1, 0x64, -0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, 0x00, -0x00, 0x00, 0x42, 0x17, 0x00, 0xf3, 0x0a, 0x77, 0x69, 0x6c, -0x6c, 0x00, 0x74, 0x72, 0x61, 0x76, 0x65, 0x6c, 0x00, 0x73, -0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0x00, 0x66, 0x72, -0x6f, 0x6d, 0x3d, 0x00, 0xc0, 0x6f, 0x72, 0x69, 0x67, 0x69, -0x6e, 0x00, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x13, 0x00, 0x42, -0x79, 0x00, 0x68, 0x69, 0x82, 0x00, 0x21, 0x6f, 0x70, 0x96, -0x00, 0x6a, 0x65, 0x00, 0x73, 0x69, 0x64, 0x65, 0x8a, 0x00, -0xf2, 0x00, 0x28, 0x61, 0x74, 0x00, 0x77, 0x68, 0x69, 0x63, -0x68, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0xf1, -0x04, 0x65, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x29, 0x2c, 0x00, -0x75, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x00, 0x61, 0x66, 0x66, -0x8c, 0x00, 0x00, 0xee, 0x00, 0x02, 0xf7, 0x00, 0x55, 0x69, -0x6e, 0x00, 0x6f, 0x6e, 0x4b, 0x00, 0x60, 0x66, 0x6f, 0x6c, -0x6c, 0x6f, 0x77, 0xcb, 0x00, 0xb1, 0x77, 0x61, 0x79, 0x73, -0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x41, 0xcd, 0x00, 0x50, -0x00, 0x74, 0x68, 0x61, 0x74, 0x88, 0x00, 0x31, 0x73, 0x00, -0x61, 0x3b, 0x00, 0xf1, 0x05, 0x00, 0x68, 0x65, 0x61, 0x64, -0x2d, 0x6f, 0x6e, 0x00, 0x69, 0x73, 0x00, 0x61, 0x62, 0x73, -0x6f, 0x72, 0x62, 0x65, 0x64, 0x0f, 0x01, 0x01, 0xde, 0x00, -0x93, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x00, 0x72, 0x65, 0x2d, -0x83, 0x00, 0x50, 0x2e, 0x00, 0x54, 0x68, 0x69, 0x6e, 0x00, -0x63, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x01, 0x01, -0x54, 0x00, 0x44, 0x6d, 0x65, 0x65, 0x74, 0x54, 0x00, 0x22, -0x6f, 0x6e, 0x87, 0x00, 0x99, 0x69, 0x72, 0x73, 0x74, 0x00, -0x72, 0x61, 0x6e, 0x6b, 0xe4, 0x00, 0x18, 0x2e, 0x90, 0x00, -0x44, 0x77, 0x69, 0x74, 0x68, 0x37, 0x00, 0x30, 0x69, 0x6e, -0x00, 0x99, 0x00, 0xe0, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x2d, -0x6c, 0x65, 0x66, 0x74, 0x00, 0x73, 0x71, 0x75, 0x7d, 0x01, -0x00, 0x90, 0x00, 0x22, 0x6e, 0x6f, 0x25, 0x00, 0x10, 0x61, -0xb1, 0x00, 0x00, 0x50, 0x00, 0x76, 0x69, 0x74, 0x00, 0x67, -0x65, 0x74, 0x73, 0x9a, 0x01, 0xb0, 0x00, 0x39, 0x30, 0x00, -0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x2c, 0x02, 0x00, -0x70, 0x00, 0x10, 0x72, 0x94, 0x01, 0x0f, 0x70, 0x00, 0x13, -0x01, 0x2b, 0x00, 0x0f, 0x71, 0x00, 0x12, 0x97, 0x73, 0x69, -0x6d, 0x69, 0x6c, 0x61, 0x72, 0x6c, 0x79, 0x7b, 0x00, 0x03, -0x70, 0x00, 0x00, 0xb5, 0x00, 0x1d, 0x2e, 0x6f, 0x01, 0x50, -0x77, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x01, 0x02, 0x45, 0x01, -0x02, 0x24, 0x02, 0x00, 0x7a, 0x00, 0xc2, 0x65, 0x6e, 0x74, -0x72, 0x79, 0x00, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x83, -0x01, 0x30, 0x63, 0x6f, 0x6e, 0x14, 0x02, 0x12, 0x72, 0x53, -0x00, 0x54, 0x62, 0x65, 0x00, 0x60, 0x72, 0x64, 0x00, 0x1a, -0x27, 0xc8, 0x00, 0x01, 0x24, 0x02, 0x02, 0x5a, 0x00, 0x37, -0x67, 0x65, 0x74, 0x8b, 0x00, 0x60, 0x62, 0x65, 0x66, 0x6f, -0x72, 0x65, 0x5c, 0x00, 0x11, 0x65, 0x08, 0x03, 0x06, 0x5c, -0x02, 0x24, 0x62, 0x79, 0xfa, 0x00, 0x03, 0xaf, 0x00, 0x07, -0x6a, 0x01, 0x29, 0x6f, 0x72, 0x08, 0x01, 0x27, 0x6f, 0x66, -0xa1, 0x00, 0x02, 0x8a, 0x02, 0x00, 0x21, 0x02, 0x3f, 0x6c, -0x73, 0x6f, 0xa3, 0x00, 0x0e, 0x16, 0x42, 0x14, 0x02, 0x00, -0x4b, 0x01, 0x15, 0x72, 0x99, 0x00, 0x40, 0x61, 0x70, 0x70, -0x65, 0xd7, 0x03, 0x00, 0x7b, 0x02, 0x48, 0x60, 0x52, 0x27, -0x3b, 0x3e, 0x02, 0x00, 0x1a, 0x03, 0x02, 0xca, 0x02, 0x01, -0x90, 0x02, 0x00, 0x42, 0x02, 0x06, 0x2f, 0x00, 0xf4, 0x02, -0x60, 0x48, 0x27, 0x2e, 0x00, 0x4f, 0x74, 0x68, 0x65, 0x72, -0x77, 0x69, 0x73, 0x65, 0x2c, 0x00, 0x61, 0x47, 0x04, 0x02, -0x23, 0x00, 0x14, 0x73, 0xd9, 0x03, 0x03, 0xf9, 0x03, 0x02, -0xaf, 0x00, 0x00, 0xc3, 0x01, 0x01, 0x93, 0x01, 0x04, 0x5e, -0x01, 0x42, 0x77, 0x68, 0x65, 0x72, 0x3b, 0x04, 0x01, 0x41, -0x01, 0x02, 0x8c, 0x01, 0x40, 0x73, 0x00, 0x28, 0x74, 0xd2, -0x02, 0x03, 0x51, 0x00, 0x81, 0x69, 0x73, 0x00, 0x75, 0x6e, -0x69, 0x71, 0x75, 0x6d, 0x04, 0x01, 0x99, 0x00, 0x50, 0x73, -0x68, 0x6f, 0x74, 0x29, 0xd7, 0x00, 0x00, 0x87, 0x04, 0xf5, -0x04, 0x63, 0x61, 0x6e, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, -0x00, 0x67, 0x75, 0x65, 0x73, 0x73, 0x65, 0x73, 0x00, 0x61, -0x6b, 0x02, 0x05, 0x68, 0x00, 0x08, 0x8f, 0x04, 0x74, 0x2c, -0x00, 0x62, 0x61, 0x73, 0x65, 0x64, 0x11, 0x03, 0x02, 0x4f, -0x01, 0x00, 0x9a, 0x00, 0xb7, 0x65, 0x78, 0x69, 0x74, 0x00, -0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0xc2, 0x04, 0x00, 0x10, -0x01, 0x84, 0x3b, 0x00, 0x6f, 0x6e, 0x63, 0x65, 0x00, 0x79, -0xf6, 0x04, 0x01, 0x70, 0x00, 0x84, 0x64, 0x00, 0x65, 0x6e, -0x6f, 0x75, 0x67, 0x68, 0x36, 0x05, 0x55, 0x00, 0x62, 0x75, -0x74, 0x74, 0x24, 0x01, 0x00, 0xa8, 0x01, 0x30, 0x61, 0x62, -0x6c, 0xfc, 0x00, 0x00, 0x37, 0x00, 0x22, 0x74, 0x6f, 0x3a, -0x00, 0x45, 0x79, 0x6f, 0x75, 0x72, 0xa9, 0x00, 0x52, 0x63, -0x68, 0x65, 0x63, 0x6b, 0xbe, 0x04, 0x10, 0x48, 0x08, 0x01, -0x10, 0x69, 0x46, 0x00, 0x70, 0x64, 0x69, 0x61, 0x67, 0x72, -0x61, 0x6d, 0xe5, 0x00, 0x17, 0x77, 0xf9, 0x04, 0x0a, 0x5c, -0x05, 0x02, 0x73, 0x00, 0x00, 0xfb, 0x00, 0xb8, 0x63, 0x72, -0x65, 0x61, 0x74, 0x65, 0x00, 0x65, 0x61, 0x63, 0x68, 0xb3, -0x00, 0xb1, 0x00, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, -0x75, 0x72, 0x73, 0x4a, 0x00, 0x70, 0x6e, 0x00, 0x61, 0x62, -0x6f, 0x76, 0x65, 0x77, 0x04, 0xf3, 0x09, 0x31, 0x52, 0x48, -0x52, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 0x00, 0x7c, 0x2e, 0x2e, -0x4f, 0x2e, 0x4f, 0x2e, 0x2e, 0x2e, 0x7c, 0x00, 0x00, 0x32, -0x2e, 0x01, 0x00, 0x11, 0x33, 0x18, 0x00, 0x02, 0x01, 0x00, -0x1a, 0x7c, 0x0c, 0x00, 0x1e, 0x33, 0x18, 0x00, 0x10, 0x4f, -0x0c, 0x00, 0x1d, 0x48, 0x18, 0x00, 0x11, 0x4f, 0x0c, 0x00, -0x51, 0x31, 0x32, 0x2d, 0x52, 0x52, 0x6a, 0x00, 0x33, 0x00, -0x00, 0x41, 0x88, 0x00, 0x10, 0x2c, 0xb3, 0x03, 0x11, 0x69, -0x03, 0x06, 0x40, 0x73, 0x69, 0x62, 0x6c, 0x18, 0x05, 0x33, -0x72, 0x00, 0x61, 0x99, 0x03, 0x10, 0x6f, 0x6c, 0x06, 0xc5, -0x65, 0x69, 0x76, 0x65, 0x00, 0x6d, 0x75, 0x6c, 0x74, 0x69, -0x70, 0x6c, 0xab, 0x02, 0x01, 0xf9, 0x00, 0x03, 0x46, 0x03, -0x04, 0xb5, 0x03, 0x00, 0x1e, 0x01, 0xf4, 0x00, 0x28, 0x73, -0x65, 0x65, 0x00, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x33, 0x29, -0x2e, 0x00, 0x53, 0x06, 0x04, 0x14, 0x2c, 0x53, 0x00, 0x58, -0x6d, 0x61, 0x79, 0x00, 0x62, 0xf1, 0x02, 0x13, 0x28, 0x79, -0x00, 0x41, 0x79, 0x00, 0x6d, 0x6f, 0x7b, 0x02, 0x21, 0x61, -0x6e, 0xdd, 0x01, 0x16, 0x29, 0x5e, 0x00, 0x00, 0x82, 0x00, -0x00, 0x5c, 0x00, 0x11, 0x61, 0x02, 0x03, 0x10, 0x28, 0x53, -0x01, 0x34, 0x60, 0x48, 0x27, 0x30, 0x02, 0x02, 0x04, 0x05, -0x07, 0x24, 0x06, 0x71, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, -0x65, 0x91, 0x02, 0x43, 0x4e, 0x6f, 0x74, 0x65, 0x67, 0x03, -0x92, 0x6e, 0x79, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, -0xdf, 0x04, 0x06, 0x6e, 0x00, 0x13, 0x34, 0xbe, 0x01, 0x00, -0x9b, 0x00, 0x01, 0x14, 0x02, 0x63, 0x61, 0x00, 0x6e, 0x6f, -0x6e, 0x2d, 0xe4, 0x02, 0x40, 0x73, 0x6f, 0x6c, 0x75, 0xee, -0x00, 0x00, 0xd6, 0x05, 0x08, 0x35, 0x06, 0x04, 0x17, 0x02, -0x40, 0x69, 0x6c, 0x6c, 0x75, 0xd9, 0x06, 0x20, 0x74, 0x65, -0xa6, 0x03, 0x61, 0x69, 0x73, 0x3b, 0x00, 0x69, 0x66, 0x62, -0x02, 0x23, 0x6b, 0x6e, 0x29, 0x02, 0x50, 0x62, 0x6f, 0x61, -0x72, 0x64, 0x12, 0x04, 0x74, 0x74, 0x61, 0x69, 0x6e, 0x73, -0x00, 0x35, 0xf6, 0x02, 0x02, 0x78, 0x01, 0x25, 0x69, 0x6d, -0x7a, 0x01, 0x01, 0xbc, 0x07, 0x77, 0x74, 0x65, 0x72, 0x6d, -0x69, 0x6e, 0x65, 0x8a, 0x03, 0x53, 0x66, 0x69, 0x66, 0x74, -0x68, 0x8d, 0x05, 0x15, 0x73, 0x30, 0x01, 0x08, 0x81, 0x02, -0x63, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0xb7, 0x05, 0x41, -0x6e, 0x00, 0x78, 0x29, 0xce, 0x06, 0x03, 0x01, 0x00, 0x0f, -0x3f, 0x02, 0x07, 0x11, 0x7c, 0x18, 0x02, 0x15, 0x4f, 0x18, -0x00, 0x3e, 0x78, 0x78, 0x2e, 0x0c, 0x00, 0x0b, 0x24, 0x00, -0x0e, 0x48, 0x00, 0x08, 0x6a, 0x00, 0x61, 0x00, 0x00, 0x46, -0x6f, 0x72, 0x00, 0x2d, 0x04, 0x70, 0x72, 0x65, 0x61, 0x73, -0x6f, 0x6e, 0x2c, 0xc8, 0x00, 0x16, 0x6e, 0xa9, 0x03, 0x0f, -0x6f, 0x03, 0x01, 0x11, 0x2c, 0xe6, 0x00, 0x42, 0x67, 0x61, -0x6d, 0x65, 0x50, 0x07, 0x01, 0x17, 0x00, 0x02, 0xb5, 0x01, -0x01, 0x2f, 0x00, 0x04, 0x82, 0x01, 0x40, 0x00, 0x70, 0x72, -0x6f, 0xda, 0x08, 0xf2, 0x02, 0x73, 0x20, 0x74, 0x68, 0x65, -0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, -0x6c, 0x74, 0x62, 0x04, 0xf0, 0x02, 0x68, 0x65, 0x00, 0x63, -0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x27, 0x73, 0x2c, -0x00, 0x72, 0x61, 0x0c, 0x05, 0x02, 0xe2, 0x01, 0x0e, 0x4c, -0x00, 0x01, 0x7a, 0x01, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x69, -0x63, 0x61, 0xea, 0x05, 0x06, 0x3f, 0x00, 0x62, 0x2e, 0x00, -0x53, 0x6f, 0x00, 0x69, 0x60, 0x02, 0x01, 0xa8, 0x03, 0x04, -0x55, 0x02, 0x11, 0x2c, 0xcb, 0x00, 0x11, 0x63, 0x52, 0x06, -0x3c, 0x70, 0x75, 0x74, 0xa0, 0x01, 0x03, 0x68, 0x02, 0x29, -0x6f, 0x66, 0xee, 0x04, 0x0e, 0xa1, 0x01, 0x11, 0x2c, 0xe0, -0x04, 0x00, 0x4b, 0x00, 0x02, 0x9d, 0x06, 0x20, 0x73, 0x74, -0xf9, 0x00, 0x31, 0x77, 0x69, 0x6e, 0x1c, 0x06, 0x00, 0x0e, -0x0a, 0x81, 0x00, 0x42, 0x6f, 0x78, 0x00, 0x77, 0x61, 0x73, -0x38, 0x02, 0x45, 0x72, 0x69, 0x62, 0x75, 0x41, 0x07, 0x01, -0x01, 0x07, 0x13, 0x6c, 0x84, 0x03, 0x00, 0xaf, 0x06, 0xd0, -0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, -0x65, 0x79, 0x2e, 0x50, 0x04, 0x37, 0x39, 0x2e, 0x31, 0x53, -0x0a, 0x01, 0x41, 0x00, 0x30, 0x6f, 0x6c, 0x73, 0x5c, 0x0a, -0x20, 0x54, 0x6f, 0x00, 0x06, 0x00, 0xe2, 0x02, 0x01, 0xf9, -0x09, 0x01, 0x93, 0x03, 0x11, 0x2c, 0x42, 0x03, 0x62, 0x2d, -0x63, 0x6c, 0x69, 0x63, 0x6b, 0x60, 0x0a, 0x04, 0xe0, 0x07, -0x55, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0e, 0x0a, 0x0b, 0x9f, -0x08, 0x00, 0x0e, 0x03, 0x04, 0x7f, 0x01, 0x01, 0xb7, 0x01, -0xf0, 0x0c, 0x62, 0x65, 0x00, 0x64, 0x69, 0x73, 0x70, 0x6c, -0x61, 0x79, 0x65, 0x64, 0x00, 0x69, 0x6d, 0x6d, 0x65, 0x64, -0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x2e, 0x00, 0x43, 0x5b, -0x00, 0x00, 0x34, 0x03, 0x74, 0x6f, 0x72, 0x00, 0x68, 0x6f, -0x6c, 0x64, 0x71, 0x07, 0x01, 0xba, 0x03, 0x03, 0xa5, 0x05, -0x18, 0x6f, 0x9c, 0x09, 0x23, 0x73, 0x65, 0x84, 0x00, 0x03, -0x5b, 0x00, 0x51, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x73, 0x07, -0x01, 0xa7, 0x01, 0xb1, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, -0x00, 0x67, 0x6f, 0x00, 0x28, 0xac, 0x04, 0x30, 0x70, 0x72, -0x65, 0x5a, 0x05, 0x71, 0x73, 0x00, 0x67, 0x6f, 0x29, 0x00, -0x74, 0x7d, 0x07, 0x31, 0x66, 0x69, 0x72, 0x62, 0x0a, 0x03, -0x44, 0x06, 0x01, 0xed, 0x06, 0x00, 0xd9, 0x04, 0x01, 0x0a, -0x02, 0x01, 0xfc, 0x00, 0x10, 0x2c, 0xa8, 0x03, 0xb2, 0x61, -0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x2e, -0x1e, 0x01, 0x01, 0x9b, 0x02, 0x0d, 0xab, 0x06, 0x02, 0x11, -0x08, 0x09, 0x29, 0x01, 0x00, 0xcb, 0x01, 0x2b, 0x69, 0x6e, -0x1e, 0x0b, 0x31, 0x61, 0x00, 0x62, 0xbc, 0x01, 0x53, 0x63, -0x69, 0x72, 0x63, 0x6c, 0xce, 0x02, 0x03, 0xa2, 0x07, 0x00, -0x02, 0x02, 0x04, 0xf8, 0x00, 0x01, 0x65, 0x00, 0x22, 0x3b, -0x00, 0x49, 0x00, 0x52, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x6a, -0x05, 0x10, 0x6d, 0x69, 0x02, 0x05, 0x21, 0x00, 0x21, 0x65, -0x64, 0x76, 0x00, 0x00, 0x99, 0x00, 0x15, 0x4c, 0x49, 0x02, -0x09, 0x73, 0x00, 0x03, 0x4c, 0x05, 0x20, 0x6c, 0x6f, 0x46, -0x03, 0x02, 0x49, 0x00, 0xb4, 0x73, 0x74, 0x00, 0x6d, 0x6f, -0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x1f, 0x02, 0x01, 0xac, -0x08, 0x33, 0x2d, 0x00, 0x63, 0x85, 0x01, 0x50, 0x3b, 0x00, -0x77, 0x68, 0x6f, 0xc8, 0x05, 0x31, 0x6f, 0x77, 0x73, 0xb5, -0x00, 0x74, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x4e, -0x00, 0x06, 0xb9, 0x09, 0x03, 0x58, 0x00, 0x0e, 0x43, 0x00, -0x04, 0x86, 0x00, 0x02, 0x44, 0x02, 0x04, 0x2e, 0x02, 0x00, -0x27, 0x03, 0x62, 0x2f, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x66, -0x01, 0x02, 0x58, 0x00, 0x10, 0x2c, 0xf5, 0x01, 0x07, 0xf9, -0x09, 0x15, 0x2f, 0x3b, 0x09, 0x01, 0x25, 0x00, 0x31, 0x72, -0x6f, 0x77, 0x7a, 0x01, 0x02, 0xd7, 0x01, 0x72, 0x73, 0x6f, -0x72, 0x00, 0x6b, 0x65, 0x79, 0x8c, 0x00, 0x01, 0x48, 0x09, -0x52, 0x62, 0x65, 0x00, 0x75, 0x73, 0xfa, 0x02, 0x01, 0x1e, -0x01, 0x07, 0x94, 0x02, 0xb4, 0x67, 0x72, 0x69, 0x64, 0x2e, -0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x59, 0x01, 0x10, 0x45, -0xcf, 0x09, 0x00, 0x42, 0x00, 0x02, 0x7b, 0x01, 0x09, 0xeb, -0x02, 0x00, 0x2a, 0x02, 0x20, 0x64, 0x64, 0xdc, 0x05, 0x21, -0x65, 0x77, 0x59, 0x01, 0x15, 0x2d, 0xe2, 0x01, 0x01, 0x6f, -0x01, 0x02, 0x93, 0x03, 0x14, 0x70, 0x4f, 0x00, 0x43, 0x53, -0x70, 0x61, 0x63, 0xc2, 0x01, 0x20, 0x6c, 0x6f, 0xa7, 0x01, -0x30, 0x00, 0x63, 0x65, 0x03, 0x02, 0x31, 0x72, 0x6f, 0x77, -0xd3, 0x00, 0x02, 0xde, 0x00, 0x00, 0xbc, 0x00, 0x10, 0x57, -0xe1, 0x04, 0x11, 0x61, 0x67, 0x08, 0x40, 0x72, 0x6f, 0x70, -0x72, 0xf5, 0x02, 0x0d, 0xc2, 0x0d, 0x01, 0xfc, 0x04, 0x44, -0x62, 0x65, 0x65, 0x6e, 0xdb, 0x01, 0x16, 0x2c, 0x9f, 0x08, -0x08, 0x26, 0x02, 0x03, 0xa4, 0x09, 0x32, 0x74, 0x6f, 0x70, -0x71, 0x0a, 0x42, 0x63, 0x6f, 0x72, 0x6e, 0x48, 0x00, 0x04, -0xf2, 0x00, 0x16, 0x3b, 0x86, 0x01, 0x01, 0x41, 0x01, 0x13, -0x28, 0xcd, 0x06, 0x31, 0x75, 0x73, 0x65, 0x97, 0x00, 0x01, -0x45, 0x01, 0x18, 0x29, 0x49, 0x05, 0x08, 0x73, 0x05, 0x00, -0xb0, 0x00, 0x12, 0x49, 0x9f, 0x06, 0x02, 0x7e, 0x02, 0x01, -0x4c, 0x07, 0x01, 0x28, 0x00, 0x15, 0x27, 0x2f, 0x09, 0x2a, -0x6e, 0x64, 0xa7, 0x05, 0x00, 0xde, 0x01, 0x21, 0x6e, 0x6f, -0x8d, 0x00, 0x00, 0x7a, 0x0e, 0x0c, 0xaf, 0x05, 0x00, 0x46, -0x08, 0x02, 0x53, 0x09, 0xf2, 0x02, 0x68, 0x65, 0x00, 0x6d, -0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x00, 0x69, 0x6e, 0x66, -0x6f, 0x72, 0x6d, 0x5f, 0x01, 0x92, 0x6e, 0x65, 0x63, 0x65, -0x73, 0x73, 0x61, 0x72, 0x79, 0xe1, 0x06, 0x32, 0x6d, 0x6f, -0x6e, 0x30, 0x07, 0x02, 0xcc, 0x04, 0x20, 0x74, 0x6f, 0x3d, -0x00, 0x31, 0x2c, 0x00, 0x73, 0x08, 0x00, 0x01, 0x43, 0x09, -0x01, 0x00, 0x0a, 0x00, 0xce, 0x02, 0x13, 0x2e, 0xad, 0x00, -0x12, 0x72, 0x5e, 0x05, 0x06, 0xf1, 0x06, 0x06, 0x93, 0x00, -0x73, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0xd5, 0x07, -0x05, 0x6e, 0x09, 0x51, 0x70, 0x61, 0x74, 0x68, 0x73, 0x51, -0x00, 0x72, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x8f, -0x07, 0x61, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x2c, 0x6a, 0x04, -0x05, 0x27, 0x00, 0x05, 0xbe, 0x04, 0x02, 0xb6, 0x03, 0x01, -0x6c, 0x02, 0x30, 0x69, 0x6e, 0x64, 0x42, 0x03, 0x03, 0x3b, -0x08, 0x20, 0x69, 0x74, 0x7b, 0x06, 0x32, 0x76, 0x65, 0x73, -0xb2, 0x05, 0x46, 0x72, 0x6f, 0x6e, 0x67, 0x9a, 0x00, 0x08, -0x86, 0x07, 0x41, 0x74, 0x63, 0x68, 0x00, 0x3a, 0x0c, 0x02, -0x79, 0x04, 0x20, 0x73, 0x74, 0xa7, 0x01, 0x07, 0x90, 0x00, -0x22, 0x62, 0x75, 0xef, 0x0b, 0x03, 0xef, 0x05, 0x00, 0x49, -0x00, 0x02, 0x8d, 0x00, 0x01, 0x94, 0x02, 0x0d, 0x91, 0x00, -0x60, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x24, 0x09, 0x52, -0x77, 0x72, 0x69, 0x74, 0x74, 0xff, 0x0f, 0x43, 0x72, 0x65, -0x64, 0x29, 0xd9, 0x0c, 0x2f, 0x69, 0x73, 0x05, 0x01, 0x02, -0x01, 0x97, 0x00, 0x05, 0x25, 0x05, 0x0d, 0xf9, 0x01, 0x51, -0x64, 0x65, 0x63, 0x69, 0x64, 0x6d, 0x08, 0x10, 0x67, 0xd9, -0x09, 0x21, 0x75, 0x70, 0xf8, 0x06, 0x20, 0x6c, 0x65, 0xac, -0x05, 0x15, 0x2c, 0x84, 0x01, 0x20, 0x73, 0x65, 0x62, 0x06, -0x42, 0x00, 0x53, 0x6f, 0x6c, 0x55, 0x10, 0x02, 0x8c, 0x00, -0x02, 0x7d, 0x04, 0x5b, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x93, -0x01, 0x42, 0x2e, 0x00, 0x41, 0x74, 0xd1, 0x01, 0x01, 0x6d, -0x05, 0x14, 0x2c, 0x2e, 0x02, 0x33, 0x6c, 0x79, 0x2d, 0x9d, -0x0b, 0x02, 0x0a, 0x03, 0x0e, 0x2b, 0x06, 0x60, 0x61, 0x73, -0x00, 0x66, 0x69, 0x6c, 0xe7, 0x00, 0x08, 0x3d, 0x05, 0x00, -0x20, 0x09, 0x1f, 0x6e, 0x44, 0x00, 0x04, 0x0f, 0x32, 0x00, -0x04, 0x02, 0xfe, 0x00, 0x00, 0x73, 0x0d, 0x30, 0x63, 0x72, -0x6f, 0xf5, 0x00, 0x02, 0xd3, 0x03, 0x22, 0x6d, 0x69, 0xd2, -0x03, 0x0c, 0x3c, 0x00, 0x01, 0x29, 0x00, 0x02, 0x3a, 0x00, -0x40, 0x2e, 0x00, 0x49, 0x6e, 0x1e, 0x04, 0x01, 0xcb, 0x00, -0x00, 0x9b, 0x03, 0x06, 0x1c, 0x00, 0x01, 0xb9, 0x05, 0x13, -0x73, 0x3e, 0x0a, 0x00, 0x48, 0x04, 0x02, 0xcb, 0x08, 0x15, -0x64, 0x58, 0x02, 0x00, 0x65, 0x04, 0x1f, 0x64, 0x91, 0x01, -0x10, 0x01, 0x2f, 0x01, 0x03, 0x81, 0x0a, 0x50, 0x28, 0x6a, -0x75, 0x73, 0x74, 0x8b, 0x00, 0x05, 0x1d, 0x09, 0x01, 0x78, -0x04, 0x0f, 0x8e, 0x03, 0x00, 0x12, 0x29, 0xc4, 0x00, 0x01, -0x48, 0x0e, 0x3e, 0x65, 0x78, 0x74, 0x8e, 0x00, 0x05, 0x8e, -0x08, 0x01, 0x63, 0x04, 0x02, 0x8d, 0x00, 0x00, 0xe8, 0x10, -0x41, 0x72, 0x64, 0x65, 0x72, 0x70, 0x03, 0x02, 0x86, 0x02, -0x3e, 0x75, 0x69, 0x73, 0x88, 0x00, 0x05, 0x88, 0x11, 0x04, -0xad, 0x01, 0x00, 0x8c, 0x02, 0x00, 0x2a, 0x02, 0x35, 0x28, -0x41, 0x6c, 0xeb, 0x01, 0x01, 0xdb, 0x02, 0x72, 0x64, 0x65, -0x73, 0x63, 0x72, 0x69, 0x62, 0x5c, 0x00, 0x13, 0x73, 0x7b, -0x08, 0x31, 0x32, 0x2e, 0x31, 0xce, 0x02, 0x01, 0xa9, 0x05, -0x51, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x49, 0x07, 0x12, 0x29, -0x83, 0x08, 0x17, 0x32, 0x83, 0x08, 0x50, 0x70, 0x61, 0x72, -0x61, 0x6d, 0xda, 0x0a, 0x02, 0x85, 0x08, 0x01, 0xe1, 0x07, -0x06, 0x14, 0x00, 0x02, 0x45, 0x00, 0x04, 0x40, 0x00, 0x06, -0x95, 0x00, 0xe2, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, -0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x8c, 0x07, 0x12, -0x6e, 0x1a, 0x00, 0xa1, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0x82, 0x05, 0x81, 0x69, 0x64, 0x74, -0x68, 0x2c, 0x00, 0x48, 0x65, 0x5b, 0x06, 0x51, 0x00, 0x00, -0x53, 0x69, 0x7a, 0x4a, 0x08, 0x00, 0x30, 0x05, 0x01, 0xb1, -0x00, 0x02, 0x4c, 0x08, 0x01, 0xb4, 0x08, 0x21, 0x72, 0x65, -0x6f, 0x00, 0x32, 0x32, 0x00, 0x78, 0x37, 0x00, 0x24, 0x00, -0x78, 0x38, 0x00, 0x04, 0x0b, 0x13, 0x21, 0x65, 0x72, 0x39, -0x00, 0x51, 0x2c, 0x00, 0x74, 0x77, 0x6f, 0x0e, 0x00, 0x32, -0x72, 0x6f, 0x77, 0x29, 0x0f, 0x03, 0x10, 0x00, 0x06, 0xfb, -0x05, 0x72, 0x4e, 0x6f, 0x2e, 0x20, 0x6f, 0x66, 0x20, 0x5a, -0x02, 0x3b, 0x00, 0x00, 0x4e, 0xf6, 0x05, 0x23, 0x74, 0x6f, -0x09, 0x0f, 0x27, 0x69, 0x6e, 0xb2, 0x06, 0x01, 0x1d, 0x12, -0x00, 0x63, 0x03, 0x10, 0x62, 0x9d, 0x06, 0x00, 0x9b, 0x02, -0x14, 0x6c, 0x31, 0x06, 0x11, 0x2c, 0xa6, 0x06, 0x00, 0x0d, -0x12, 0x20, 0x67, 0x65, 0x4a, 0x0d, 0x00, 0x24, 0x01, 0x15, -0x74, 0x38, 0x0a, 0xf3, 0x04, 0x00, 0x68, 0x79, 0x70, 0x68, -0x65, 0x6e, 0x2c, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0x00, 0x60, -0x32, 0x2d, 0x36, 0x27, 0x1f, 0x02, 0x05, 0x36, 0x0c, 0x02, -0x43, 0x02, 0x1f, 0x6e, 0x88, 0x00, 0x05, 0x1a, 0x6f, 0x88, -0x00, 0x01, 0x96, 0x10, 0x00, 0xd7, 0x03, 0x05, 0xfc, 0x05, -0x72, 0x69, 0x73, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x2b, 0x0f, -0x00, 0xee, 0x01, 0x16, 0x66, 0xbb, 0x0b, 0x04, 0x95, 0x08, -0x0f, 0xeb, 0x06, 0x0b, 0x33, 0x3b, 0x00, 0x61, 0x45, 0x09, -0x11, 0x75, 0x76, 0x03, 0x00, 0x40, 0x0f, 0x31, 0x66, 0x66, -0x65, 0x8c, 0x04, 0x03, 0x2b, 0x00, 0x03, 0x0e, 0x08, 0x02, -0xfa, 0x13, 0x29, 0x61, 0x6c, 0x94, 0x0b, 0x02, 0x1a, 0x05, -0x60, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x83, 0x00, 0x02, -0xa6, 0x09, 0x26, 0x6c, 0x6c, 0xda, 0x05, 0x62, 0x69, 0x6e, -0x70, 0x75, 0x74, 0x73, 0x8d, 0x14, 0x21, 0x75, 0x74, 0x0c, -0x00, 0x70, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x00, +0x42, 0x6f, 0x78, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x01, 0xf0, +0x21, 0x00, 0x00, 0x00, 0x41, 0x00, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0x00, 0x6f, 0x66, 0x00, 0x62, 0x61, 0x6c, 0x6c, +0x73, 0x00, 0x61, 0x72, 0x65, 0x00, 0x68, 0x69, 0x64, 0x64, +0x65, 0x6e, 0x00, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x72, 0x65, +0x63, 0x74, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x1c, +0x00, 0xf0, 0x15, 0x6e, 0x61, 0x2e, 0x00, 0x59, 0x6f, 0x75, +0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x74, 0x6f, 0x00, 0x64, +0x65, 0x64, 0x75, 0x63, 0x65, 0x00, 0x74, 0x68, 0x65, 0x00, +0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4d, +0x00, 0x00, 0x11, 0x00, 0x02, 0x51, 0x00, 0xf5, 0x01, 0x62, +0x79, 0x00, 0x66, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x6c, +0x61, 0x73, 0x65, 0x72, 0x73, 0x28, 0x00, 0x51, 0x65, 0x64, +0x00, 0x61, 0x74, 0x29, 0x00, 0x45, 0x65, 0x64, 0x67, 0x65, +0x36, 0x00, 0x01, 0x65, 0x00, 0xb0, 0x00, 0x61, 0x6e, 0x64, +0x00, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x3a, 0x00, 0x30, +0x68, 0x6f, 0x77, 0x1c, 0x00, 0x72, 0x69, 0x72, 0x00, 0x62, +0x65, 0x61, 0x6d, 0xa5, 0x00, 0xe1, 0x64, 0x65, 0x66, 0x6c, +0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x00, 0x42, +0x17, 0x00, 0xf3, 0x0a, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x74, +0x72, 0x61, 0x76, 0x65, 0x6c, 0x00, 0x73, 0x74, 0x72, 0x61, +0x69, 0x67, 0x68, 0x74, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x3d, +0x00, 0xc0, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x00, 0x75, +0x6e, 0x74, 0x69, 0x6c, 0x13, 0x00, 0x42, 0x79, 0x00, 0x68, +0x69, 0x82, 0x00, 0x21, 0x6f, 0x70, 0x96, 0x00, 0x6a, 0x65, +0x00, 0x73, 0x69, 0x64, 0x65, 0x8a, 0x00, 0xf2, 0x00, 0x28, +0x61, 0x74, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x70, +0x6f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0xf1, 0x04, 0x65, 0x6d, +0x65, 0x72, 0x67, 0x65, 0x29, 0x2c, 0x00, 0x75, 0x6e, 0x6c, +0x65, 0x73, 0x73, 0x00, 0x61, 0x66, 0x66, 0x8c, 0x00, 0x00, +0xee, 0x00, 0x02, 0xf7, 0x00, 0x55, 0x69, 0x6e, 0x00, 0x6f, +0x6e, 0x4b, 0x00, 0x60, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, +0xcb, 0x00, 0xb1, 0x77, 0x61, 0x79, 0x73, 0x3a, 0x00, 0x00, +0x00, 0x2d, 0x00, 0x41, 0xcd, 0x00, 0x50, 0x00, 0x74, 0x68, +0x61, 0x74, 0x88, 0x00, 0x31, 0x73, 0x00, 0x61, 0x3b, 0x00, +0xf1, 0x05, 0x00, 0x68, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, +0x00, 0x69, 0x73, 0x00, 0x61, 0x62, 0x73, 0x6f, 0x72, 0x62, +0x65, 0x64, 0x0f, 0x01, 0x01, 0xde, 0x00, 0x93, 0x6e, 0x65, +0x76, 0x65, 0x72, 0x00, 0x72, 0x65, 0x2d, 0x83, 0x00, 0x50, +0x2e, 0x00, 0x54, 0x68, 0x69, 0x6e, 0x00, 0x63, 0x63, 0x6c, +0x75, 0x64, 0x65, 0x73, 0x20, 0x01, 0x01, 0x54, 0x00, 0x44, +0x6d, 0x65, 0x65, 0x74, 0x54, 0x00, 0x22, 0x6f, 0x6e, 0x87, +0x00, 0x99, 0x69, 0x72, 0x73, 0x74, 0x00, 0x72, 0x61, 0x6e, +0x6b, 0xe4, 0x00, 0x18, 0x2e, 0x90, 0x00, 0x44, 0x77, 0x69, +0x74, 0x68, 0x37, 0x00, 0x30, 0x69, 0x6e, 0x00, 0x99, 0x00, +0xe0, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x66, +0x74, 0x00, 0x73, 0x71, 0x75, 0x7d, 0x01, 0x00, 0x90, 0x00, +0x22, 0x6e, 0x6f, 0x25, 0x00, 0x10, 0x61, 0xb1, 0x00, 0x00, +0x50, 0x00, 0x76, 0x69, 0x74, 0x00, 0x67, 0x65, 0x74, 0x73, +0x9a, 0x01, 0xb0, 0x00, 0x39, 0x30, 0x00, 0x64, 0x65, 0x67, +0x72, 0x65, 0x65, 0x73, 0x2c, 0x02, 0x00, 0x70, 0x00, 0x10, +0x72, 0x94, 0x01, 0x0f, 0x70, 0x00, 0x13, 0x01, 0x2b, 0x00, +0x0f, 0x71, 0x00, 0x12, 0x97, 0x73, 0x69, 0x6d, 0x69, 0x6c, +0x61, 0x72, 0x6c, 0x79, 0x7b, 0x00, 0x03, 0x70, 0x00, 0x00, +0xb5, 0x00, 0x1d, 0x2e, 0x6f, 0x01, 0x50, 0x77, 0x6f, 0x75, +0x6c, 0x64, 0x46, 0x01, 0x02, 0x45, 0x01, 0x02, 0x24, 0x02, +0x00, 0x7a, 0x00, 0xc2, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x00, +0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x83, 0x01, 0x30, 0x63, +0x6f, 0x6e, 0x14, 0x02, 0x12, 0x72, 0x53, 0x00, 0x54, 0x62, +0x65, 0x00, 0x60, 0x72, 0x64, 0x00, 0x1a, 0x27, 0xc8, 0x00, +0x01, 0x24, 0x02, 0x02, 0x5a, 0x00, 0x37, 0x67, 0x65, 0x74, +0x8b, 0x00, 0x60, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5c, +0x00, 0x11, 0x65, 0x08, 0x03, 0x06, 0x5c, 0x02, 0x24, 0x62, +0x79, 0xfa, 0x00, 0x03, 0xaf, 0x00, 0x07, 0x6a, 0x01, 0x29, +0x6f, 0x72, 0x08, 0x01, 0x27, 0x6f, 0x66, 0xa1, 0x00, 0x02, +0x8a, 0x02, 0x00, 0x21, 0x02, 0x3f, 0x6c, 0x73, 0x6f, 0xa3, +0x00, 0x0e, 0x16, 0x42, 0x14, 0x02, 0x00, 0x4b, 0x01, 0x15, +0x72, 0x99, 0x00, 0x40, 0x61, 0x70, 0x70, 0x65, 0xd7, 0x03, +0x00, 0x7b, 0x02, 0x48, 0x60, 0x52, 0x27, 0x3b, 0x3e, 0x02, +0x00, 0x1a, 0x03, 0x02, 0xca, 0x02, 0x01, 0x90, 0x02, 0x00, +0x42, 0x02, 0x06, 0x2f, 0x00, 0xf4, 0x02, 0x60, 0x48, 0x27, +0x2e, 0x00, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, +0x65, 0x2c, 0x00, 0x61, 0x47, 0x04, 0x02, 0x23, 0x00, 0x14, +0x73, 0xd9, 0x03, 0x03, 0xf9, 0x03, 0x02, 0xaf, 0x00, 0x00, +0xc3, 0x01, 0x01, 0x93, 0x01, 0x04, 0x5e, 0x01, 0x42, 0x77, +0x68, 0x65, 0x72, 0x3b, 0x04, 0x01, 0x41, 0x01, 0x02, 0x8c, +0x01, 0x40, 0x73, 0x00, 0x28, 0x74, 0xd2, 0x02, 0x03, 0x51, +0x00, 0x81, 0x69, 0x73, 0x00, 0x75, 0x6e, 0x69, 0x71, 0x75, +0x6d, 0x04, 0x01, 0x99, 0x00, 0x50, 0x73, 0x68, 0x6f, 0x74, +0x29, 0xd7, 0x00, 0x00, 0x87, 0x04, 0xf5, 0x04, 0x63, 0x61, +0x6e, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x00, 0x67, 0x75, +0x65, 0x73, 0x73, 0x65, 0x73, 0x00, 0x61, 0x6b, 0x02, 0x05, +0x68, 0x00, 0x08, 0x8f, 0x04, 0x74, 0x2c, 0x00, 0x62, 0x61, +0x73, 0x65, 0x64, 0x11, 0x03, 0x02, 0x4f, 0x01, 0x00, 0x9a, +0x00, 0xb7, 0x65, 0x78, 0x69, 0x74, 0x00, 0x70, 0x61, 0x74, +0x74, 0x65, 0x72, 0xc2, 0x04, 0x00, 0x10, 0x01, 0x84, 0x3b, +0x00, 0x6f, 0x6e, 0x63, 0x65, 0x00, 0x79, 0xf6, 0x04, 0x01, +0x70, 0x00, 0x84, 0x64, 0x00, 0x65, 0x6e, 0x6f, 0x75, 0x67, +0x68, 0x36, 0x05, 0x55, 0x00, 0x62, 0x75, 0x74, 0x74, 0x24, +0x01, 0x00, 0xa8, 0x01, 0x30, 0x61, 0x62, 0x6c, 0xfc, 0x00, +0x00, 0x37, 0x00, 0x22, 0x74, 0x6f, 0x3a, 0x00, 0x45, 0x79, +0x6f, 0x75, 0x72, 0xa9, 0x00, 0x52, 0x63, 0x68, 0x65, 0x63, +0x6b, 0xbe, 0x04, 0x10, 0x48, 0x08, 0x01, 0x10, 0x69, 0x46, +0x00, 0x70, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0xe5, +0x00, 0x17, 0x77, 0xf9, 0x04, 0x0a, 0x5c, 0x05, 0x02, 0x73, +0x00, 0x00, 0xfb, 0x00, 0xb8, 0x63, 0x72, 0x65, 0x61, 0x74, +0x65, 0x00, 0x65, 0x61, 0x63, 0x68, 0xb3, 0x00, 0xb1, 0x00, +0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x75, 0x72, 0x73, +0x4a, 0x00, 0x70, 0x6e, 0x00, 0x61, 0x62, 0x6f, 0x76, 0x65, +0x77, 0x04, 0x42, 0x31, 0x52, 0x48, 0x52, 0xfc, 0x05, 0xe3, +0x7c, 0x2e, 0x2e, 0x4f, 0x2e, 0x4f, 0x2e, 0x2e, 0x2e, 0x7c, +0x00, 0x00, 0x32, 0x2e, 0x01, 0x00, 0x11, 0x33, 0x18, 0x00, +0x02, 0x01, 0x00, 0x1a, 0x7c, 0x0c, 0x00, 0x1e, 0x33, 0x18, +0x00, 0x10, 0x4f, 0x0c, 0x00, 0x1d, 0x48, 0x18, 0x00, 0x11, +0x4f, 0x0c, 0x00, 0x52, 0x31, 0x32, 0x2d, 0x52, 0x52, 0x66, +0x06, 0x23, 0x00, 0x41, 0x88, 0x00, 0x10, 0x2c, 0xb3, 0x03, +0x11, 0x69, 0x03, 0x06, 0x40, 0x73, 0x69, 0x62, 0x6c, 0x18, +0x05, 0x33, 0x72, 0x00, 0x61, 0x99, 0x03, 0x10, 0x6f, 0x6c, +0x06, 0xc5, 0x65, 0x69, 0x76, 0x65, 0x00, 0x6d, 0x75, 0x6c, +0x74, 0x69, 0x70, 0x6c, 0xab, 0x02, 0x01, 0xf9, 0x00, 0x03, +0x46, 0x03, 0x04, 0xb5, 0x03, 0x00, 0x1e, 0x01, 0xf4, 0x00, +0x28, 0x73, 0x65, 0x65, 0x00, 0x74, 0x75, 0x72, 0x6e, 0x00, +0x33, 0x29, 0x2e, 0x00, 0x53, 0x06, 0x04, 0x14, 0x2c, 0x53, +0x00, 0x58, 0x6d, 0x61, 0x79, 0x00, 0x62, 0xf1, 0x02, 0x13, +0x28, 0x79, 0x00, 0x41, 0x79, 0x00, 0x6d, 0x6f, 0x7b, 0x02, +0x21, 0x61, 0x6e, 0xdd, 0x01, 0x16, 0x29, 0x5e, 0x00, 0x00, +0x82, 0x00, 0x00, 0x5c, 0x00, 0x11, 0x61, 0x02, 0x03, 0x10, +0x28, 0x53, 0x01, 0x34, 0x60, 0x48, 0x27, 0x30, 0x02, 0x02, +0x04, 0x05, 0x07, 0x24, 0x06, 0x71, 0x65, 0x78, 0x61, 0x6d, +0x70, 0x6c, 0x65, 0x91, 0x02, 0x43, 0x4e, 0x6f, 0x74, 0x65, +0x67, 0x03, 0x92, 0x6e, 0x79, 0x00, 0x6c, 0x61, 0x79, 0x6f, +0x75, 0x74, 0xdf, 0x04, 0x06, 0x6e, 0x00, 0x13, 0x34, 0xbe, +0x01, 0x00, 0x9b, 0x00, 0x01, 0x14, 0x02, 0x63, 0x61, 0x00, +0x6e, 0x6f, 0x6e, 0x2d, 0xe4, 0x02, 0x40, 0x73, 0x6f, 0x6c, +0x75, 0xee, 0x00, 0x00, 0xd6, 0x05, 0x08, 0x35, 0x06, 0x04, +0x17, 0x02, 0x40, 0x69, 0x6c, 0x6c, 0x75, 0xd9, 0x06, 0x20, +0x74, 0x65, 0xa6, 0x03, 0x61, 0x69, 0x73, 0x3b, 0x00, 0x69, +0x66, 0x62, 0x02, 0x23, 0x6b, 0x6e, 0x29, 0x02, 0x50, 0x62, +0x6f, 0x61, 0x72, 0x64, 0x12, 0x04, 0x74, 0x74, 0x61, 0x69, +0x6e, 0x73, 0x00, 0x35, 0xf6, 0x02, 0x02, 0x78, 0x01, 0x25, +0x69, 0x6d, 0x7a, 0x01, 0x01, 0xbc, 0x07, 0x77, 0x74, 0x65, +0x72, 0x6d, 0x69, 0x6e, 0x65, 0x8a, 0x03, 0x53, 0x66, 0x69, +0x66, 0x74, 0x68, 0x8d, 0x05, 0x15, 0x73, 0x30, 0x01, 0x08, +0x81, 0x02, 0x63, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0xb7, +0x05, 0x41, 0x6e, 0x00, 0x78, 0x29, 0xce, 0x06, 0x05, 0x53, +0x08, 0x0f, 0x3f, 0x02, 0x05, 0x11, 0x7c, 0x18, 0x02, 0x15, +0x4f, 0x18, 0x00, 0x3e, 0x78, 0x78, 0x2e, 0x0c, 0x00, 0x0b, +0x24, 0x00, 0x0f, 0x48, 0x00, 0x01, 0x07, 0xbd, 0x08, 0x51, +0x00, 0x46, 0x6f, 0x72, 0x00, 0x2d, 0x04, 0x70, 0x72, 0x65, +0x61, 0x73, 0x6f, 0x6e, 0x2c, 0xc8, 0x00, 0x16, 0x6e, 0xa9, +0x03, 0x0f, 0x6f, 0x03, 0x01, 0x11, 0x2c, 0xe6, 0x00, 0x42, +0x67, 0x61, 0x6d, 0x65, 0x50, 0x07, 0x01, 0x17, 0x00, 0x02, +0xb5, 0x01, 0x01, 0x2f, 0x00, 0x04, 0x82, 0x01, 0x40, 0x00, +0x70, 0x72, 0x6f, 0xda, 0x08, 0xf2, 0x02, 0x73, 0x20, 0x74, +0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x72, 0x65, +0x73, 0x75, 0x6c, 0x74, 0x62, 0x04, 0xf0, 0x02, 0x68, 0x65, +0x00, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x27, +0x73, 0x2c, 0x00, 0x72, 0x61, 0x0c, 0x05, 0x02, 0xe2, 0x01, +0x0e, 0x4c, 0x00, 0x01, 0x7a, 0x01, 0x75, 0x64, 0x65, 0x6e, +0x74, 0x69, 0x63, 0x61, 0xea, 0x05, 0x06, 0x3f, 0x00, 0x62, +0x2e, 0x00, 0x53, 0x6f, 0x00, 0x69, 0x60, 0x02, 0x01, 0xa8, +0x03, 0x04, 0x55, 0x02, 0x11, 0x2c, 0xcb, 0x00, 0x11, 0x63, +0x52, 0x06, 0x3c, 0x70, 0x75, 0x74, 0xa0, 0x01, 0x03, 0x68, +0x02, 0x29, 0x6f, 0x66, 0xee, 0x04, 0x0e, 0xa1, 0x01, 0x11, +0x2c, 0xe0, 0x04, 0x00, 0x4b, 0x00, 0x02, 0x9d, 0x06, 0x20, +0x73, 0x74, 0xf9, 0x00, 0x31, 0x77, 0x69, 0x6e, 0x1c, 0x06, +0x00, 0x24, 0x0a, 0x81, 0x00, 0x42, 0x6f, 0x78, 0x00, 0x77, +0x61, 0x73, 0x38, 0x02, 0x45, 0x72, 0x69, 0x62, 0x75, 0x41, +0x07, 0x01, 0x01, 0x07, 0x13, 0x6c, 0x84, 0x03, 0x00, 0xaf, +0x06, 0xd0, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, +0x72, 0x76, 0x65, 0x79, 0x2e, 0x50, 0x04, 0x37, 0x39, 0x2e, +0x31, 0x69, 0x0a, 0x01, 0x41, 0x00, 0x90, 0x6f, 0x6c, 0x73, +0x20, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x00, 0x06, 0x00, 0xe2, +0x02, 0x01, 0xf9, 0x09, 0x01, 0x93, 0x03, 0x11, 0x2c, 0x42, +0x03, 0x62, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x60, 0x0a, +0x04, 0xe0, 0x07, 0x55, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0e, +0x0a, 0x0b, 0x9f, 0x08, 0x00, 0x0e, 0x03, 0x04, 0x7f, 0x01, +0x01, 0xb7, 0x01, 0xf0, 0x0c, 0x62, 0x65, 0x00, 0x64, 0x69, +0x73, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x00, 0x69, 0x6d, +0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x2e, +0x00, 0x43, 0x5b, 0x00, 0x00, 0x34, 0x03, 0x74, 0x6f, 0x72, +0x00, 0x68, 0x6f, 0x6c, 0x64, 0x71, 0x07, 0x01, 0xba, 0x03, +0x03, 0xa5, 0x05, 0x18, 0x6f, 0x9c, 0x09, 0x23, 0x73, 0x65, +0x84, 0x00, 0x03, 0x5b, 0x00, 0x51, 0x68, 0x69, 0x67, 0x68, +0x6c, 0x73, 0x07, 0x01, 0xa7, 0x01, 0xb1, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x00, 0x67, 0x6f, 0x00, 0x28, 0xac, 0x04, +0x30, 0x70, 0x72, 0x65, 0x5a, 0x05, 0x71, 0x73, 0x00, 0x67, +0x6f, 0x29, 0x00, 0x74, 0x7d, 0x07, 0x31, 0x66, 0x69, 0x72, +0x62, 0x0a, 0x03, 0x44, 0x06, 0x01, 0xed, 0x06, 0x00, 0xd9, +0x04, 0x01, 0x0a, 0x02, 0x01, 0xfc, 0x00, 0x10, 0x2c, 0xa8, +0x03, 0xb2, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, +0x6c, 0x65, 0x2e, 0x1e, 0x01, 0x01, 0x9b, 0x02, 0x0d, 0xab, +0x06, 0x02, 0x11, 0x08, 0x09, 0x29, 0x01, 0x00, 0xcb, 0x01, +0x2b, 0x69, 0x6e, 0x1e, 0x0b, 0x31, 0x61, 0x00, 0x62, 0xbc, +0x01, 0x53, 0x63, 0x69, 0x72, 0x63, 0x6c, 0xce, 0x02, 0x03, +0xa2, 0x07, 0x00, 0x02, 0x02, 0x04, 0xf8, 0x00, 0x01, 0x65, +0x00, 0x22, 0x3b, 0x00, 0x49, 0x00, 0x52, 0x61, 0x67, 0x61, +0x69, 0x6e, 0x6a, 0x05, 0x10, 0x6d, 0x69, 0x02, 0x05, 0x21, +0x00, 0x21, 0x65, 0x64, 0x76, 0x00, 0x00, 0x99, 0x00, 0x15, +0x4c, 0x49, 0x02, 0x09, 0x73, 0x00, 0x03, 0x4c, 0x05, 0x20, +0x6c, 0x6f, 0x46, 0x03, 0x02, 0x49, 0x00, 0xb4, 0x73, 0x74, +0x00, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x1f, +0x02, 0x01, 0xac, 0x08, 0x33, 0x2d, 0x00, 0x63, 0x85, 0x01, +0x50, 0x3b, 0x00, 0x77, 0x68, 0x6f, 0xc8, 0x05, 0x31, 0x6f, +0x77, 0x73, 0xb5, 0x00, 0x74, 0x63, 0x6f, 0x6c, 0x75, 0x6d, +0x6e, 0x73, 0x4e, 0x00, 0x06, 0xb9, 0x09, 0x03, 0x58, 0x00, +0x0e, 0x43, 0x00, 0x04, 0x86, 0x00, 0x02, 0x44, 0x02, 0x04, +0x2e, 0x02, 0x00, 0x27, 0x03, 0x62, 0x2f, 0x62, 0x65, 0x6c, +0x6f, 0x77, 0x66, 0x01, 0x02, 0x58, 0x00, 0x10, 0x2c, 0xf5, +0x01, 0x07, 0xf9, 0x09, 0x15, 0x2f, 0x3b, 0x09, 0x01, 0x25, +0x00, 0x31, 0x72, 0x6f, 0x77, 0x7a, 0x01, 0x02, 0xd7, 0x01, +0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x8c, 0x00, +0x01, 0x48, 0x09, 0x52, 0x62, 0x65, 0x00, 0x75, 0x73, 0xfa, +0x02, 0x01, 0x1e, 0x01, 0x07, 0x94, 0x02, 0xb4, 0x67, 0x72, +0x69, 0x64, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x59, +0x01, 0x10, 0x45, 0xcf, 0x09, 0x00, 0x42, 0x00, 0x02, 0x7b, +0x01, 0x09, 0xeb, 0x02, 0x00, 0x2a, 0x02, 0x20, 0x64, 0x64, +0xdc, 0x05, 0x21, 0x65, 0x77, 0x59, 0x01, 0x15, 0x2d, 0xe2, +0x01, 0x01, 0x6f, 0x01, 0x02, 0x93, 0x03, 0x14, 0x70, 0x4f, +0x00, 0x43, 0x53, 0x70, 0x61, 0x63, 0xc2, 0x01, 0x20, 0x6c, +0x6f, 0xa7, 0x01, 0x30, 0x00, 0x63, 0x65, 0x03, 0x02, 0x31, +0x72, 0x6f, 0x77, 0xd3, 0x00, 0x02, 0xde, 0x00, 0x00, 0xbc, +0x00, 0x10, 0x57, 0xe1, 0x04, 0x11, 0x61, 0x67, 0x08, 0x40, +0x72, 0x6f, 0x70, 0x72, 0xf5, 0x02, 0x0d, 0xc2, 0x0d, 0x01, +0xfc, 0x04, 0x44, 0x62, 0x65, 0x65, 0x6e, 0xdb, 0x01, 0x16, +0x2c, 0x9f, 0x08, 0x08, 0x26, 0x02, 0x03, 0xa4, 0x09, 0x32, +0x74, 0x6f, 0x70, 0x71, 0x0a, 0x42, 0x63, 0x6f, 0x72, 0x6e, +0x48, 0x00, 0x04, 0xf2, 0x00, 0x16, 0x3b, 0x86, 0x01, 0x01, +0x41, 0x01, 0x13, 0x28, 0xcd, 0x06, 0x31, 0x75, 0x73, 0x65, +0x97, 0x00, 0x01, 0x45, 0x01, 0x18, 0x29, 0x49, 0x05, 0x08, +0x73, 0x05, 0x00, 0xb0, 0x00, 0x12, 0x49, 0x9f, 0x06, 0x02, +0x7e, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x28, 0x00, 0x15, 0x27, +0x2f, 0x09, 0x2a, 0x6e, 0x64, 0xa7, 0x05, 0x00, 0xde, 0x01, +0x21, 0x6e, 0x6f, 0x8d, 0x00, 0x00, 0x7a, 0x0e, 0x0c, 0xaf, +0x05, 0x00, 0x46, 0x08, 0x02, 0x53, 0x09, 0xf2, 0x02, 0x68, +0x65, 0x00, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x00, +0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x01, 0x92, 0x6e, +0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0xe1, 0x06, +0x32, 0x6d, 0x6f, 0x6e, 0x30, 0x07, 0x02, 0xcc, 0x04, 0x20, +0x74, 0x6f, 0x3d, 0x00, 0x31, 0x2c, 0x00, 0x73, 0x08, 0x00, +0x01, 0x43, 0x09, 0x01, 0x00, 0x0a, 0x00, 0xce, 0x02, 0x13, +0x2e, 0xad, 0x00, 0x12, 0x72, 0x5e, 0x05, 0x06, 0xf1, 0x06, +0x06, 0x93, 0x00, 0x73, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, +0x6e, 0xd5, 0x07, 0x05, 0x6e, 0x09, 0x51, 0x70, 0x61, 0x74, +0x68, 0x73, 0x51, 0x00, 0x72, 0x61, 0x6c, 0x72, 0x65, 0x61, +0x64, 0x79, 0x8f, 0x07, 0x61, 0x61, 0x62, 0x6f, 0x75, 0x74, +0x2c, 0x6a, 0x04, 0x05, 0x27, 0x00, 0x05, 0xbe, 0x04, 0x02, +0xb6, 0x03, 0x01, 0x6c, 0x02, 0x30, 0x69, 0x6e, 0x64, 0x42, +0x03, 0x03, 0x3b, 0x08, 0x20, 0x69, 0x74, 0x7b, 0x06, 0x32, +0x76, 0x65, 0x73, 0xb2, 0x05, 0x46, 0x72, 0x6f, 0x6e, 0x67, +0x9a, 0x00, 0x08, 0x86, 0x07, 0x41, 0x74, 0x63, 0x68, 0x00, +0x3a, 0x0c, 0x02, 0x79, 0x04, 0x20, 0x73, 0x74, 0xa7, 0x01, +0x07, 0x90, 0x00, 0x22, 0x62, 0x75, 0xef, 0x0b, 0x03, 0xef, +0x05, 0x00, 0x49, 0x00, 0x02, 0x8d, 0x00, 0x01, 0x94, 0x02, +0x0d, 0x91, 0x00, 0x60, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, +0x24, 0x09, 0x52, 0x77, 0x72, 0x69, 0x74, 0x74, 0xff, 0x0f, +0x43, 0x72, 0x65, 0x64, 0x29, 0xd9, 0x0c, 0x2f, 0x69, 0x73, +0x05, 0x01, 0x02, 0x01, 0x97, 0x00, 0x05, 0x25, 0x05, 0x0d, +0xf9, 0x01, 0x51, 0x64, 0x65, 0x63, 0x69, 0x64, 0x6d, 0x08, +0x10, 0x67, 0xd9, 0x09, 0x21, 0x75, 0x70, 0xf8, 0x06, 0x20, +0x6c, 0x65, 0xac, 0x05, 0x15, 0x2c, 0x84, 0x01, 0x20, 0x73, +0x65, 0x62, 0x06, 0x42, 0x00, 0x53, 0x6f, 0x6c, 0x55, 0x10, +0x02, 0x8c, 0x00, 0x02, 0x7d, 0x04, 0x5b, 0x63, 0x74, 0x75, +0x61, 0x6c, 0x93, 0x01, 0x42, 0x2e, 0x00, 0x41, 0x74, 0xd1, +0x01, 0x01, 0x6d, 0x05, 0x14, 0x2c, 0x2e, 0x02, 0x33, 0x6c, +0x79, 0x2d, 0x9d, 0x0b, 0x02, 0x0a, 0x03, 0x0e, 0x2b, 0x06, +0x60, 0x61, 0x73, 0x00, 0x66, 0x69, 0x6c, 0xe7, 0x00, 0x08, +0x3d, 0x05, 0x00, 0x20, 0x09, 0x1f, 0x6e, 0x44, 0x00, 0x04, +0x0f, 0x32, 0x00, 0x04, 0x02, 0xfe, 0x00, 0x00, 0x73, 0x0d, +0x30, 0x63, 0x72, 0x6f, 0xf5, 0x00, 0x02, 0xd3, 0x03, 0x22, +0x6d, 0x69, 0xd2, 0x03, 0x0c, 0x3c, 0x00, 0x01, 0x29, 0x00, +0x02, 0x3a, 0x00, 0x40, 0x2e, 0x00, 0x49, 0x6e, 0x1e, 0x04, +0x01, 0xcb, 0x00, 0x00, 0x9b, 0x03, 0x06, 0x1c, 0x00, 0x01, +0xb9, 0x05, 0x13, 0x73, 0x3e, 0x0a, 0x00, 0x48, 0x04, 0x02, +0xcb, 0x08, 0x15, 0x64, 0x58, 0x02, 0x00, 0x65, 0x04, 0x1f, +0x64, 0x91, 0x01, 0x10, 0x01, 0x2f, 0x01, 0x03, 0x81, 0x0a, +0x50, 0x28, 0x6a, 0x75, 0x73, 0x74, 0x8b, 0x00, 0x05, 0x1d, +0x09, 0x01, 0x78, 0x04, 0x0f, 0x8e, 0x03, 0x00, 0x12, 0x29, +0xc4, 0x00, 0x01, 0x48, 0x0e, 0x3e, 0x65, 0x78, 0x74, 0x8e, +0x00, 0x05, 0x8e, 0x08, 0x01, 0x63, 0x04, 0x02, 0x8d, 0x00, +0x00, 0xe8, 0x10, 0x41, 0x72, 0x64, 0x65, 0x72, 0x70, 0x03, +0x02, 0x86, 0x02, 0x3e, 0x75, 0x69, 0x73, 0x88, 0x00, 0x05, +0x88, 0x11, 0x04, 0xad, 0x01, 0x00, 0x8c, 0x02, 0x00, 0x2a, +0x02, 0x35, 0x28, 0x41, 0x6c, 0xeb, 0x01, 0x01, 0xdb, 0x02, +0x72, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x5c, 0x00, +0x13, 0x73, 0x7b, 0x08, 0x31, 0x32, 0x2e, 0x31, 0xce, 0x02, +0x01, 0xa9, 0x05, 0x51, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x49, +0x07, 0x12, 0x29, 0x83, 0x08, 0x17, 0x32, 0x83, 0x08, 0x50, +0x70, 0x61, 0x72, 0x61, 0x6d, 0xda, 0x0a, 0x02, 0x85, 0x08, +0x01, 0xe1, 0x07, 0x06, 0x14, 0x00, 0x02, 0x45, 0x00, 0x04, +0x40, 0x00, 0x06, 0x95, 0x00, 0xe2, 0x60, 0x43, 0x75, 0x73, +0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, +0x8c, 0x07, 0x12, 0x6e, 0x1a, 0x00, 0xa1, 0x54, 0x79, 0x70, +0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x82, 0x05, 0x81, +0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x5b, 0x06, +0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x4a, 0x08, 0x00, 0x30, +0x05, 0x01, 0xb1, 0x00, 0x02, 0x4c, 0x08, 0x01, 0xb4, 0x08, +0x21, 0x72, 0x65, 0x6f, 0x00, 0x32, 0x32, 0x00, 0x78, 0x37, +0x00, 0x24, 0x00, 0x78, 0x38, 0x00, 0x04, 0x0b, 0x13, 0x21, +0x65, 0x72, 0x39, 0x00, 0x51, 0x2c, 0x00, 0x74, 0x77, 0x6f, +0x0e, 0x00, 0x32, 0x72, 0x6f, 0x77, 0x29, 0x0f, 0x03, 0x10, +0x00, 0x06, 0xfb, 0x05, 0x72, 0x4e, 0x6f, 0x2e, 0x20, 0x6f, +0x66, 0x20, 0x5a, 0x02, 0x3b, 0x00, 0x00, 0x4e, 0xf6, 0x05, +0x23, 0x74, 0x6f, 0x09, 0x0f, 0x27, 0x69, 0x6e, 0xb2, 0x06, +0x01, 0x1d, 0x12, 0x00, 0x63, 0x03, 0x10, 0x62, 0x9d, 0x06, +0x00, 0x9b, 0x02, 0x14, 0x6c, 0x31, 0x06, 0x11, 0x2c, 0xa6, +0x06, 0x00, 0x0d, 0x12, 0x20, 0x67, 0x65, 0x4a, 0x0d, 0x00, +0x24, 0x01, 0x15, 0x74, 0x38, 0x0a, 0xf3, 0x04, 0x00, 0x68, +0x79, 0x70, 0x68, 0x65, 0x6e, 0x2c, 0x00, 0x6c, 0x69, 0x6b, +0x65, 0x00, 0x60, 0x32, 0x2d, 0x36, 0x27, 0x1f, 0x02, 0x05, +0x36, 0x0c, 0x02, 0x43, 0x02, 0x1f, 0x6e, 0x88, 0x00, 0x05, +0x1a, 0x6f, 0x88, 0x00, 0x01, 0x96, 0x10, 0x00, 0xd7, 0x03, +0x05, 0xfc, 0x05, 0x72, 0x69, 0x73, 0x00, 0x6f, 0x6e, 0x6c, +0x79, 0x2b, 0x0f, 0x00, 0xee, 0x01, 0x16, 0x66, 0xbb, 0x0b, +0x04, 0x95, 0x08, 0x0f, 0xeb, 0x06, 0x0b, 0x33, 0x3b, 0x00, +0x61, 0x45, 0x09, 0x11, 0x75, 0x76, 0x03, 0x00, 0x40, 0x0f, +0x31, 0x66, 0x66, 0x65, 0x8c, 0x04, 0x03, 0x2b, 0x00, 0x03, +0x0e, 0x08, 0x02, 0xfa, 0x13, 0x29, 0x61, 0x6c, 0x94, 0x0b, +0x02, 0x1a, 0x05, 0x60, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, +0x83, 0x00, 0x02, 0xa6, 0x09, 0x26, 0x6c, 0x6c, 0xda, 0x05, +0x62, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x8d, 0x14, 0x21, +0x75, 0x74, 0x0c, 0x00, 0x70, 0x6d, 0x61, 0x74, 0x63, 0x68, +0x2e, 0x00, }; -const unsigned short help_text_len = 5458; -const unsigned short help_text_words = 1015; +const unsigned short help_text_len = 5480; +const unsigned short help_text_words = 1016; const char quick_help_text[] = "Find the hidden balls in the box by bouncing laser beams off them."; diff --git a/apps/plugins/puzzles/help/bridges.c b/apps/plugins/puzzles/help/bridges.c index be4469b5ac..bd01c53426 100644 --- a/apps/plugins/puzzles/help/bridges.c +++ b/apps/plugins/puzzles/help/bridges.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,336 +6,356 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 180, TEXT_CENTER | C_RED }, - { 312, TEXT_UNDERLINE }, - { 737, TEXT_CENTER | C_RED }, - { 754, TEXT_UNDERLINE }, - { 755, TEXT_UNDERLINE }, - { 765, TEXT_UNDERLINE }, - { 774, TEXT_UNDERLINE }, - { 813, TEXT_UNDERLINE }, - { 845, TEXT_UNDERLINE }, - { 880, TEXT_UNDERLINE }, + { 178, TEXT_CENTER | C_RED }, + { 310, TEXT_UNDERLINE }, + { 763, TEXT_CENTER | C_RED }, + { 780, TEXT_UNDERLINE }, + { 781, TEXT_UNDERLINE }, + { 791, TEXT_UNDERLINE }, + { 800, TEXT_UNDERLINE }, + { 839, TEXT_UNDERLINE }, + { 871, TEXT_UNDERLINE }, + { 906, TEXT_UNDERLINE }, + { 991, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 5230 comp 3126 ratio 0.597706 level 10 saved 2104 */ +/* orig 5613 comp 3312 ratio 0.590059 level 10 saved 2301 */ const char help_text[] = { -0xf3, 0x4b, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x36, 0x3a, 0x20, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, -0x73, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, -0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x73, 0x65, 0x74, 0x00, -0x6f, 0x66, 0x00, 0x69, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, -0x00, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, -0x65, 0x64, 0x00, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, -0x74, 0x68, 0x65, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, -0x67, 0x00, 0x61, 0x72, 0x65, 0x61, 0x2e, 0x00, 0x45, 0x61, -0x63, 0x68, 0x32, 0x00, 0xf0, 0x04, 0x00, 0x63, 0x6f, 0x6e, -0x74, 0x61, 0x69, 0x6e, 0x73, 0x00, 0x61, 0x00, 0x6e, 0x75, -0x6d, 0x62, 0x65, 0x72, 0x2e, 0x5e, 0x00, 0xb0, 0x72, 0x00, -0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x22, -0x00, 0x41, 0x6e, 0x65, 0x63, 0x74, 0x48, 0x00, 0x04, 0x67, -0x00, 0xf2, 0x00, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, -0x72, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x62, 0x9a, 0x00, -0xf3, 0x0b, 0x2c, 0x00, 0x69, 0x6e, 0x00, 0x73, 0x75, 0x63, -0x68, 0x00, 0x61, 0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, -0x61, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0xbb, 0x00, -0xa0, 0x00, 0x72, 0x75, 0x6e, 0x00, 0x68, 0x6f, 0x72, 0x69, -0x7a, 0x75, 0x00, 0xd0, 0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, -0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, 0x11, -0x2e, 0x2c, 0x00, 0x33, 0x54, 0x68, 0x65, 0x8a, 0x00, 0x00, -0xd8, 0x00, 0x13, 0x62, 0x3a, 0x00, 0x81, 0x74, 0x65, 0x72, -0x6d, 0x69, 0x6e, 0x61, 0x74, 0xc5, 0x00, 0x54, 0x74, 0x00, -0x61, 0x6e, 0x79, 0xc1, 0x00, 0x80, 0x69, 0x73, 0x00, 0x65, -0x71, 0x75, 0x61, 0x6c, 0xab, 0x00, 0x16, 0x74, 0x3c, 0x00, -0x70, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x93, 0x00, -0x00, 0x88, 0x00, 0x03, 0x2e, 0x00, 0x03, 0x63, 0x00, 0x25, -0x77, 0x6f, 0x59, 0x00, 0x31, 0x6d, 0x61, 0x79, 0x97, 0x00, -0xf1, 0x04, 0x69, 0x6e, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6c, -0x6c, 0x65, 0x6c, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, -0x6e, 0x4f, 0x00, 0x84, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x74, -0x77, 0x6f, 0xfb, 0x00, 0xd0, 0x2c, 0x00, 0x62, 0x75, 0x74, -0x00, 0x6e, 0x6f, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x5b, 0x00, -0x11, 0x6e, 0x1e, 0x00, 0x00, 0x47, 0x00, 0x52, 0x64, 0x6f, -0x00, 0x73, 0x6f, 0x62, 0x00, 0x14, 0x4e, 0x61, 0x00, 0x11, -0x00, 0x84, 0x01, 0x61, 0x65, 0x73, 0x00, 0x61, 0x6e, 0x6f, -0x31, 0x01, 0x02, 0x17, 0x00, 0x02, 0x26, 0x00, 0x39, 0x41, -0x6c, 0x6c, 0x56, 0x01, 0x34, 0x61, 0x72, 0x65, 0x6e, 0x01, -0x25, 0x65, 0x64, 0x64, 0x01, 0x00, 0x2c, 0x00, 0x51, 0x54, -0x68, 0x65, 0x72, 0x65, 0x20, 0x00, 0x31, 0x73, 0x6f, 0x6d, -0x25, 0x00, 0xf0, 0x00, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, -0x62, 0x6c, 0x65, 0x00, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x1b, -0x01, 0x60, 0x76, 0x65, 0x00, 0x6d, 0x6f, 0x64, 0x88, 0x01, -0x30, 0x77, 0x68, 0x69, 0xe2, 0x01, 0xc0, 0x6e, 0x76, 0x6f, -0x6c, 0x76, 0x65, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x39, -0x01, 0x01, 0x0a, 0x02, 0x03, 0xe5, 0x00, 0x13, 0x2d, 0xa0, -0x00, 0x50, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x3c, 0x01, 0x00, -0x59, 0x00, 0x20, 0x74, 0x68, 0x27, 0x00, 0x02, 0xa9, 0x00, -0x01, 0xdb, 0x00, 0x31, 0x32, 0x2c, 0x00, 0x64, 0x01, 0x74, -0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x45, 0x00, 0xa0, -0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, -0x8b, 0x00, 0x72, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, -0x68, 0x01, 0xb8, 0x6e, 0x6f, 0x00, 0x73, 0x65, 0x71, 0x75, -0x65, 0x6e, 0x63, 0x65, 0xc0, 0x01, 0x00, 0x20, 0x01, 0xf4, -0x05, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x61, 0x00, 0x6c, 0x6f, -0x6f, 0x70, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x6f, 0x6e, -0x65, 0xc6, 0x01, 0x44, 0x62, 0x61, 0x63, 0x6b, 0xc2, 0x01, -0x01, 0x73, 0x01, 0x04, 0xb0, 0x01, 0x00, 0x0f, 0x02, 0x91, -0x72, 0x75, 0x6c, 0x65, 0x73, 0x00, 0x73, 0x74, 0x61, 0xd6, -0x02, 0x32, 0x62, 0x6f, 0x76, 0x0b, 0x01, 0x00, 0x2c, 0x00, -0x70, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x00, -0x10, 0x73, 0x29, 0x01, 0x60, 0x43, 0x72, 0x65, 0x64, 0x69, -0x74, 0x6b, 0x00, 0xf1, 0x01, 0x00, 0x74, 0x68, 0x69, 0x73, -0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, -0x65, 0xcc, 0x02, 0xb0, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, -0x00, 0x5b, 0x31, 0x32, 0x5d, 0x2e, 0x00, 0x04, 0x98, 0x02, -0x31, 0x77, 0x61, 0x73, 0x09, 0x03, 0x04, 0x3a, 0x03, 0x01, -0x89, 0x00, 0x10, 0x69, 0x14, 0x00, 0x40, 0x6c, 0x6c, 0x65, -0x63, 0xea, 0x00, 0xf1, 0x00, 0x00, 0x62, 0x79, 0x00, 0x4a, -0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, -0xac, 0x02, 0x00, 0x46, 0x00, 0xd1, 0x00, 0x68, 0x74, 0x74, -0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x5d, -0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, -0x6e, 0x2f, 0x7c, 0x00, 0xf1, 0x0c, 0x73, 0x2f, 0x68, 0x61, -0x73, 0x68, 0x69, 0x77, 0x6f, 0x6b, 0x61, 0x6b, 0x65, 0x72, -0x6f, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, 0x28, 0x62, 0x65, -0x77, 0x61, 0x72, 0x22, 0x01, 0xd5, 0x46, 0x6c, 0x61, 0x73, -0x68, 0x29, 0x00, 0x00, 0x00, 0x32, 0x36, 0x2e, 0x31, 0xe5, -0x03, 0x01, 0x8e, 0x00, 0x21, 0x6f, 0x6c, 0xee, 0x03, 0x20, -0x54, 0x6f, 0xc0, 0x03, 0x10, 0x63, 0xee, 0x03, 0x03, 0xb5, -0x01, 0x05, 0xa1, 0x02, 0x08, 0x98, 0x02, 0x30, 0x63, 0x6c, -0x69, 0x44, 0x01, 0x10, 0x68, 0x06, 0x02, 0xb8, 0x75, 0x73, -0x65, 0x00, 0x64, 0x6f, 0x77, 0x6e, 0x00, 0x6f, 0x6e, 0x66, -0x01, 0x00, 0x04, 0x00, 0x51, 0x64, 0x72, 0x61, 0x67, 0x00, -0xf3, 0x01, 0x42, 0x77, 0x61, 0x72, 0x64, 0x1f, 0x04, 0x01, -0xf2, 0x01, 0x01, 0xf9, 0x03, 0x00, 0xc5, 0x02, 0x62, 0x6e, -0x6f, 0x74, 0x00, 0x6e, 0x65, 0x07, 0x01, 0x01, 0x2e, 0x00, -0x13, 0x61, 0xa8, 0x02, 0x01, 0xd5, 0x03, 0x16, 0x6f, 0x32, -0x00, 0x03, 0x57, 0x00, 0xa5, 0x3b, 0x00, 0x79, 0x6f, 0x75, -0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x37, 0x00, 0x10, 0x6d, 0xa4, -0x01, 0x06, 0x8b, 0x00, 0xa3, 0x66, 0x61, 0x72, 0x00, 0x65, -0x6e, 0x6f, 0x75, 0x67, 0x68, 0x9a, 0x01, 0x10, 0x65, 0x53, -0x02, 0x54, 0x65, 0x6e, 0x64, 0x65, 0x64, 0xd3, 0x00, 0x33, -0x64, 0x69, 0x72, 0x6a, 0x01, 0xf1, 0x07, 0x74, 0x6f, 0x00, -0x62, 0x65, 0x00, 0x75, 0x6e, 0x61, 0x6d, 0x62, 0x69, 0x67, -0x75, 0x6f, 0x75, 0x73, 0x2e, 0x00, 0x28, 0x53, 0x6f, 0x64, -0x00, 0x87, 0x63, 0x61, 0x6e, 0x00, 0x6b, 0x65, 0x65, 0x70, -0x5b, 0x00, 0x42, 0x6e, 0x65, 0x61, 0x72, 0x36, 0x02, 0x31, -0x74, 0x61, 0x72, 0x1f, 0x04, 0x07, 0xec, 0x00, 0xb0, 0x63, -0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x74, 0x6c, -0x8f, 0x04, 0x35, 0x72, 0x6f, 0x77, 0x91, 0x02, 0x32, 0x6f, -0x75, 0x74, 0x85, 0x02, 0x20, 0x69, 0x74, 0xfc, 0x03, 0x10, -0x6d, 0x52, 0x04, 0x05, 0x84, 0x00, 0x20, 0x73, 0x2e, 0x91, -0x01, 0x22, 0x44, 0x6f, 0xf0, 0x02, 0xd6, 0x69, 0x73, 0x00, -0x61, 0x67, 0x61, 0x69, 0x6e, 0x00, 0x77, 0x68, 0x65, 0x6e, -0x85, 0x01, 0x00, 0x17, 0x00, 0xf0, 0x04, 0x6c, 0x72, 0x65, -0x61, 0x64, 0x79, 0x00, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, -0x74, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x1d, 0x03, 0x05, 0xee, -0x03, 0x06, 0x53, 0x04, 0x03, 0xf7, 0x03, 0x45, 0x49, 0x66, -0x00, 0x74, 0xcc, 0x03, 0x04, 0x3f, 0x00, 0x22, 0x61, 0x73, -0x80, 0x00, 0x04, 0x9c, 0x00, 0x08, 0x80, 0x04, 0x07, 0xe3, -0x01, 0x00, 0x28, 0x00, 0x10, 0x70, 0x08, 0x05, 0x20, 0x74, -0x74, 0x38, 0x01, 0x11, 0x79, 0x20, 0x00, 0x40, 0x63, 0x75, -0x72, 0x72, 0x7b, 0x00, 0x34, 0x67, 0x61, 0x6d, 0x29, 0x03, -0x51, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x39, 0x00, 0x24, 0x62, -0x79, 0x21, 0x03, 0x26, 0x29, 0x2c, 0x5b, 0x03, 0x00, 0xd4, -0x01, 0x11, 0x67, 0x49, 0x05, 0x02, 0x71, 0x01, 0x01, 0xb6, -0x00, 0x21, 0x72, 0x65, 0xb4, 0x01, 0x00, 0xeb, 0x01, 0x11, -0x6f, 0xa4, 0x00, 0x10, 0x6d, 0xe3, 0x02, 0x21, 0x49, 0x66, -0x78, 0x01, 0x31, 0x77, 0x61, 0x6e, 0x24, 0x04, 0x60, 0x72, -0x65, 0x6d, 0x69, 0x6e, 0x64, 0x13, 0x00, 0x52, 0x72, 0x73, -0x65, 0x6c, 0x66, 0xf2, 0x03, 0x08, 0xa2, 0x00, 0x90, 0x64, -0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x6c, 0x0e, 0x05, -0x10, 0x20, 0x49, 0x02, 0x03, 0xa7, 0x06, 0x0c, 0xb9, 0x02, -0x45, 0x68, 0x65, 0x6d, 0x2c, 0xd3, 0x01, 0x61, 0x72, 0x69, -0x67, 0x68, 0x74, 0x2d, 0x6b, 0x02, 0x08, 0x21, 0x00, 0x27, -0x00, 0x69, 0x83, 0x05, 0x03, 0x7c, 0x02, 0xb3, 0x64, 0x72, -0x61, 0x77, 0x00, 0x61, 0x00, 0x60, 0x6e, 0x6f, 0x6e, 0xc2, -0x04, 0x87, 0x27, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, -0xaf, 0x00, 0x00, 0xc7, 0x04, 0x34, 0x6b, 0x00, 0x79, 0x25, -0x07, 0x00, 0x93, 0x00, 0x42, 0x73, 0x68, 0x65, 0x64, 0xad, -0x06, 0x24, 0x61, 0x6e, 0x22, 0x02, 0x02, 0x28, 0x01, 0x05, -0x27, 0x00, 0x01, 0x64, 0x03, 0x11, 0x64, 0x02, 0x01, 0x35, -0x69, 0x74, 0x73, 0x8d, 0x01, 0x01, 0x4c, 0x02, 0x13, 0x72, -0x74, 0x05, 0x24, 0x64, 0x65, 0xe8, 0x04, 0x41, 0x74, 0x68, -0x65, 0x79, 0x18, 0x00, 0x03, 0xa5, 0x00, 0x01, 0xc4, 0x00, -0x02, 0x44, 0x00, 0x26, 0x73, 0x29, 0xdb, 0x00, 0x00, 0x9c, -0x00, 0x07, 0xe4, 0x05, 0x00, 0xc3, 0x01, 0x05, 0x8f, 0x00, -0x81, 0x62, 0x79, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0xb9, -0x03, 0x01, 0x79, 0x05, 0x40, 0x6e, 0x00, 0x69, 0x74, 0xf3, -0x04, 0x22, 0x69, 0x73, 0x95, 0x01, 0x51, 0x68, 0x69, 0x67, -0x68, 0x6c, 0x59, 0x00, 0x22, 0x69, 0x74, 0x89, 0x00, 0x03, -0x8a, 0x03, 0x04, 0x9d, 0x00, 0x08, 0x2e, 0x06, 0x32, 0x00, -0x69, 0x74, 0xae, 0x05, 0x01, 0xb2, 0x01, 0x20, 0x69, 0x6c, -0xc8, 0x06, 0x00, 0x9a, 0x02, 0x30, 0x76, 0x65, 0x6e, 0x21, -0x00, 0x01, 0xed, 0x02, 0x31, 0x61, 0x63, 0x63, 0xc4, 0x00, -0x01, 0x7d, 0x07, 0x52, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x17, -0x08, 0x22, 0x6e, 0x79, 0xf6, 0x01, 0x26, 0x6f, 0x73, 0x5c, -0x00, 0xc9, 0x69, 0x6e, 0x00, 0x66, 0x75, 0x74, 0x75, 0x72, -0x65, 0x2e, 0x00, 0x4c, 0xa7, 0x00, 0x02, 0x0d, 0x03, 0x10, -0x6f, 0x0b, 0x03, 0x05, 0xa1, 0x00, 0x24, 0x65, 0x64, 0xe2, -0x00, 0x01, 0x7a, 0x00, 0x21, 0x75, 0x6e, 0xf9, 0x00, 0x03, -0xb6, 0x00, 0x40, 0x72, 0x65, 0x73, 0x74, 0x2e, 0x07, 0x11, -0x79, 0x59, 0x08, 0x51, 0x62, 0x69, 0x6c, 0x69, 0x74, 0xcd, -0x01, 0x02, 0x81, 0x00, 0x01, 0xf4, 0x00, 0x02, 0xd4, 0x08, -0x00, 0x32, 0x01, 0x50, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0xda, -0x03, 0x03, 0xde, 0x02, 0x85, 0x73, 0x6f, 0x72, 0x00, 0x6b, -0x65, 0x79, 0x73, 0x57, 0x04, 0x61, 0x61, 0x72, 0x6f, 0x75, -0x6e, 0x64, 0x1f, 0x00, 0xf9, 0x01, 0x67, 0x72, 0x69, 0x64, -0x3a, 0x00, 0x69, 0x66, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, -0x62, 0x6c, 0x35, 0x00, 0x02, 0x8d, 0x03, 0x52, 0x6c, 0x77, -0x61, 0x79, 0x73, 0x39, 0x00, 0x80, 0x6f, 0x72, 0x74, 0x68, -0x6f, 0x67, 0x6f, 0x6e, 0xfd, 0x00, 0x12, 0x2c, 0xc2, 0x04, -0x63, 0x77, 0x69, 0x73, 0x65, 0x00, 0x69, 0xb9, 0x03, 0x02, -0xb5, 0x04, 0x07, 0x17, 0x05, 0x00, 0x5c, 0x04, 0x24, 0x65, -0x73, 0x3c, 0x08, 0x04, 0xfb, 0x04, 0x51, 0x69, 0x6e, 0x64, -0x69, 0x63, 0x8b, 0x06, 0x05, 0x30, 0x04, 0x60, 0x2e, 0x00, -0x48, 0x6f, 0x6c, 0x64, 0x1c, 0x01, 0x12, 0x43, 0xb8, 0x05, -0x01, 0xf7, 0x00, 0x00, 0x16, 0x04, 0x11, 0x73, 0x31, 0x01, -0x07, 0xc8, 0x00, 0x02, 0x6b, 0x00, 0x37, 0x6c, 0x61, 0x79, -0x49, 0x04, 0x03, 0xa3, 0x08, 0x06, 0x03, 0x05, 0x90, 0x28, -0x69, 0x66, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0xe1, 0x07, -0x73, 0x29, 0x3b, 0x00, 0x53, 0x68, 0x69, 0x66, 0x01, 0x02, -0x0f, 0x4b, 0x00, 0x04, 0x01, 0x11, 0x03, 0x1c, 0x00, 0x12, -0x03, 0x14, 0x50, 0x82, 0x00, 0x01, 0xa2, 0x02, 0x40, 0x65, -0x74, 0x75, 0x72, 0x40, 0x05, 0x00, 0x8a, 0x07, 0x42, 0x6c, -0x6c, 0x6f, 0x77, 0x83, 0x02, 0x0e, 0x52, 0x00, 0x01, 0x82, -0x01, 0x0f, 0xa2, 0x00, 0x0b, 0x08, 0xb1, 0x01, 0x01, 0xea, -0x01, 0x2f, 0x61, 0x6e, 0xe2, 0x02, 0x04, 0x18, 0x70, 0x83, -0x00, 0x20, 0x73, 0x70, 0xc7, 0x06, 0x30, 0x62, 0x61, 0x72, -0xf9, 0x09, 0x0c, 0x1d, 0x00, 0x07, 0xa0, 0x00, 0x51, 0x74, -0x77, 0x69, 0x63, 0x65, 0xa1, 0x07, 0x07, 0x24, 0x00, 0x04, -0xa1, 0x0a, 0x00, 0x22, 0x00, 0x06, 0x61, 0x03, 0x45, 0x6a, -0x75, 0x6d, 0x70, 0xfb, 0x09, 0x0a, 0xb0, 0x01, 0x01, 0xef, -0x03, 0x02, 0x95, 0x08, 0x03, 0xda, 0x0a, 0xf0, 0x0c, 0x4c, -0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x00, 0x60, 0x61, 0x27, -0x2c, 0x00, 0x2e, 0x2e, 0x2e, 0x2c, 0x00, 0x60, 0x66, 0x27, -0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xb8, 0x00, 0x23, 0x31, -0x30, 0x16, 0x00, 0x21, 0x31, 0x35, 0x6d, 0x01, 0x31, 0x60, -0x30, 0x27, 0x17, 0x00, 0x10, 0x36, 0x8b, 0x00, 0x51, 0x56, -0x69, 0x6f, 0x6c, 0x61, 0x1d, 0x06, 0x03, 0x21, 0x05, 0x04, -0x5c, 0x08, 0x02, 0x75, 0x05, 0x04, 0x71, 0x03, 0x01, 0x7b, -0x01, 0x10, 0x64, 0x32, 0x01, 0x42, 0x72, 0x65, 0x64, 0x3a, -0xe7, 0x09, 0x1a, 0x6e, 0x92, 0x00, 0x2a, 0x6f, 0x6f, 0xef, -0x05, 0x04, 0x3b, 0x00, 0x09, 0x4d, 0x03, 0x01, 0x40, 0x00, -0x1f, 0x2e, 0x40, 0x00, 0x05, 0x3f, 0x66, 0x65, 0x77, 0x3f, -0x00, 0x10, 0x00, 0x1a, 0x03, 0x00, 0xdf, 0x06, 0x09, 0x98, -0x05, 0xf3, 0x03, 0x61, 0x6e, 0x00, 0x65, 0x72, 0x72, 0x6f, -0x72, 0x00, 0x28, 0x61, 0x73, 0x00, 0x6f, 0x70, 0x70, 0x6f, -0x73, 0xb3, 0x07, 0x20, 0x65, 0x72, 0x1f, 0x00, 0x00, 0xb4, -0x05, 0x20, 0x62, 0x65, 0x70, 0x01, 0x05, 0xc6, 0x01, 0x41, -0x79, 0x65, 0x74, 0x29, 0x66, 0x03, 0x21, 0x61, 0x64, 0xe4, -0x02, 0x03, 0xca, 0x07, 0x05, 0x80, 0x00, 0x45, 0x6f, 0x75, -0x6c, 0x64, 0x6d, 0x0a, 0x31, 0x68, 0x61, 0x76, 0xd1, 0x01, -0x12, 0x6f, 0xfa, 0x0a, 0x0b, 0xf8, 0x0a, 0x00, 0xf8, 0x01, -0x04, 0x6a, 0x06, 0x16, 0x00, 0xc4, 0x05, 0x03, 0xb1, 0x02, -0x10, 0x2c, 0x1f, 0x00, 0x28, 0x69, 0x66, 0x30, 0x05, 0x20, -0x68, 0x61, 0x0f, 0x07, 0x29, 0x65, 0x6e, 0xde, 0x00, 0x01, -0xae, 0x09, 0x54, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x49, 0x0b, -0x68, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x09, 0x0d, 0x01, -0x55, 0x0a, 0x07, 0x7d, 0x0a, 0x0f, 0x21, 0x01, 0x0c, 0x41, -0x61, 0x00, 0x63, 0x6c, 0x0a, 0x01, 0x33, 0x73, 0x75, 0x62, -0x53, 0x0d, 0x07, 0xe3, 0x01, 0x01, 0x78, 0x01, 0x24, 0x6e, -0x6f, 0x85, 0x06, 0x04, 0x12, 0x0d, 0x02, 0x39, 0x0b, 0x02, -0xbc, 0x02, 0x15, 0x73, 0x34, 0x00, 0x03, 0x82, 0x00, 0x90, -0x2e, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0xa9, -0x00, 0x32, 0x2c, 0x00, 0x69, 0x9b, 0x06, 0x02, 0x42, 0x03, -0x26, 0x6c, 0x79, 0x56, 0x0d, 0x4c, 0x77, 0x6f, 0x00, 0x31, -0x51, 0x0d, 0x05, 0x79, 0x03, 0x01, 0x77, 0x04, 0x04, 0x6a, -0x06, 0x22, 0x6e, 0x6f, 0x85, 0x0d, 0x01, 0x6a, 0x09, 0x08, -0x76, 0x07, 0x25, 0x6f, 0x6e, 0x0e, 0x05, 0x01, 0xe7, 0x07, -0x04, 0x1a, 0x04, 0x01, 0x3a, 0x06, 0x43, 0x75, 0x70, 0x00, -0x72, 0x20, 0x06, 0x03, 0xb9, 0x04, 0x02, 0x14, 0x03, 0x03, -0xa9, 0x0d, 0x02, 0x39, 0x01, 0x32, 0x63, 0x61, 0x6e, 0xf9, -0x01, 0x04, 0x10, 0x0e, 0x02, 0x23, 0x01, 0x00, 0xa6, 0x02, -0xa4, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x00, 0x73, 0x6f, 0x6c, -0x75, 0xf9, 0x03, 0x14, 0x2d, 0x68, 0x07, 0x01, 0x37, 0x07, -0x33, 0x73, 0x65, 0x6c, 0x82, 0x06, 0x40, 0x68, 0x65, 0x00, -0x28, 0xd4, 0x01, 0x04, 0x73, 0x08, 0x34, 0x00, 0x6f, 0x70, -0xd1, 0x09, 0x40, 0x64, 0x69, 0x73, 0x61, 0x73, 0x04, 0x01, -0xfd, 0x0b, 0x15, 0x73, 0xd9, 0x07, 0x03, 0x55, 0x00, 0x15, -0x2c, 0x88, 0x00, 0x07, 0x32, 0x0c, 0x02, 0xc4, 0x0c, 0x00, -0x34, 0x0c, 0x14, 0x73, 0x35, 0x0c, 0x0e, 0xea, 0x02, 0x01, -0x22, 0x03, 0x14, 0x28, 0x48, 0x0d, 0x02, 0xd0, 0x08, 0x00, -0xee, 0x02, 0x52, 0x73, 0x63, 0x72, 0x69, 0x62, 0xc4, 0x00, -0x13, 0x73, 0x54, 0x05, 0x33, 0x32, 0x2e, 0x31, 0x75, 0x09, -0x26, 0x73, 0x6f, 0x5d, 0x05, 0x13, 0x2e, 0x7a, 0x0b, 0x15, -0x32, 0x7a, 0x0b, 0x00, 0xb3, 0x09, 0x20, 0x6d, 0x65, 0x27, -0x04, 0x12, 0x20, 0x79, 0x0d, 0x36, 0x73, 0x65, 0x00, 0x14, -0x00, 0x02, 0x43, 0x00, 0x04, 0x3e, 0x00, 0x02, 0x55, 0x07, -0x00, 0x7b, 0x00, 0xb4, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, -0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0xf7, 0x00, 0x03, 0x96, 0x01, -0x40, 0x60, 0x54, 0x79, 0x70, 0x93, 0x05, 0x30, 0x65, 0x6e, -0x75, 0xad, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, -0x00, 0x48, 0x65, 0x9d, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, -0x7a, 0x07, 0x0c, 0x00, 0xbd, 0x01, 0x01, 0xaf, 0x00, 0x42, -0x71, 0x75, 0x61, 0x72, 0xcc, 0x0c, 0xaa, 0x44, 0x69, 0x66, -0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x0d, 0x00, 0x41, -0x6c, 0x65, 0x76, 0x65, 0xa6, 0x09, 0x02, 0x9e, 0x02, 0x00, -0x2b, 0x00, 0x10, 0x41, 0x5d, 0x01, 0x12, 0x20, 0x5d, 0x01, -0x12, 0x00, 0x41, 0x08, 0x21, 0x69, 0x73, 0x1c, 0x10, 0x06, -0x03, 0x0a, 0x01, 0x7d, 0x0a, 0x20, 0x63, 0x6c, 0x24, 0x05, -0x23, 0x64, 0x2c, 0x3c, 0x00, 0x06, 0x3e, 0x04, 0x51, 0x67, -0x65, 0x6e, 0x65, 0x72, 0xd6, 0x06, 0x0e, 0xc5, 0x0f, 0x06, -0x83, 0x02, 0x03, 0x4f, 0x07, 0x00, 0xb9, 0x01, 0x13, 0x62, -0x18, 0x03, 0x00, 0x49, 0x0b, 0x33, 0x63, 0x72, 0x65, 0x9b, -0x0f, 0x01, 0xa9, 0x01, 0x02, 0x87, 0x08, 0x04, 0xde, 0x01, -0x04, 0xcb, 0x01, 0x25, 0x64, 0x6f, 0x25, 0x04, 0x0b, 0xd0, -0x01, 0x04, 0x1e, 0x02, 0x02, 0xcf, 0x01, 0x64, 0x4d, 0x61, -0x78, 0x2e, 0x20, 0x62, 0x8e, 0x01, 0x36, 0x65, 0x72, 0x20, -0x18, 0x07, 0x01, 0x1d, 0x00, 0x4e, 0x69, 0x6d, 0x75, 0x6d, -0x22, 0x10, 0x04, 0xaf, 0x02, 0x20, 0x70, 0x61, 0x4f, 0x10, -0x48, 0x75, 0x6c, 0x61, 0x72, 0xae, 0x06, 0x17, 0x54, 0x2b, -0x0e, 0x42, 0x69, 0x73, 0x00, 0x32, 0xc6, 0x0f, 0x04, 0x44, -0x06, 0x01, 0x21, 0x0f, 0x13, 0x65, 0xcf, 0x03, 0x40, 0x31, -0x2c, 0x00, 0x33, 0x88, 0x04, 0x53, 0x34, 0x2e, 0x00, 0x49, -0x6e, 0x17, 0x01, 0x20, 0x6c, 0x2c, 0x72, 0x05, 0x21, 0x65, -0x72, 0x6d, 0x10, 0x32, 0x61, 0x73, 0x69, 0x6e, 0x0a, 0x82, -0x25, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x87, 0x03, -0x13, 0x20, 0xba, 0x01, 0x70, 0x00, 0x00, 0x00, 0x47, 0x69, -0x76, 0x65, 0xb5, 0x02, 0x11, 0x72, 0x28, 0x05, 0x40, 0x70, -0x65, 0x72, 0x63, 0x73, 0x09, 0x28, 0x67, 0x65, 0xa0, 0x04, -0x25, 0x74, 0x68, 0x74, 0x01, 0x04, 0xac, 0x08, 0x31, 0x74, -0x72, 0x79, 0x39, 0x01, 0x11, 0x6c, 0xaf, 0x04, 0x34, 0x66, -0x6f, 0x72, 0xbb, 0x0a, 0x05, 0xbc, 0x0f, 0x03, 0xf0, 0x01, -0x30, 0x43, 0x65, 0x72, 0xa4, 0x03, 0x00, 0x29, 0x00, 0x33, -0x6f, 0x75, 0x74, 0xc4, 0x01, 0x00, 0xc0, 0x03, 0x30, 0x6d, -0x61, 0x6e, 0x67, 0x00, 0x12, 0x74, 0xbf, 0x07, 0x03, 0xa8, -0x05, 0x03, 0x72, 0x00, 0x12, 0x3b, 0xca, 0x0c, 0x10, 0x69, -0x1b, 0x05, 0x40, 0x00, 0x75, 0x70, 0x70, 0x94, 0x05, 0x22, -0x6f, 0x75, 0x13, 0x11, 0xf0, 0x03, 0x45, 0x78, 0x70, 0x61, -0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61, 0x63, 0x74, -0x6f, 0x72, 0x20, 0x28, 0xdc, 0x00, 0x12, 0x29, 0x00, 0x03, -0x02, 0x9b, 0x02, 0x07, 0xac, 0x00, 0x41, 0x6f, 0x72, 0x6b, -0x73, 0xbe, 0x07, 0x04, 0x10, 0x0a, 0x69, 0x6e, 0x00, 0x65, -0x78, 0x69, 0x73, 0x7d, 0x0d, 0xf8, 0x05, 0x74, 0x00, 0x72, -0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x00, 0x28, 0x61, 0x66, 0x74, -0x65, 0x72, 0x00, 0x66, 0x69, 0x72, 0x73, 0x28, 0x02, 0x20, -0x6e, 0x00, 0x90, 0x06, 0x34, 0x69, 0x61, 0x6c, 0x32, 0x00, -0x00, 0x7f, 0x10, 0x10, 0x77, 0x1a, 0x0d, 0x41, 0x29, 0x2e, -0x00, 0x49, 0x72, 0x02, 0x40, 0x6e, 0x00, 0x64, 0x65, 0xae, -0x0a, 0x12, 0x73, 0x6b, 0x0a, 0x07, 0x1e, 0x09, 0x05, 0x5e, -0x00, 0x24, 0x29, 0x2c, 0x22, 0x05, 0x13, 0x6e, 0x97, 0x00, -0x00, 0x8e, 0x02, 0x31, 0x68, 0x6f, 0x77, 0x72, 0x0e, 0x41, -0x69, 0x74, 0x00, 0x63, 0x9c, 0x06, 0x20, 0x65, 0x78, 0x6c, -0x0e, 0x04, 0x54, 0x01, 0x07, 0x85, 0x00, 0x08, 0xc6, 0x0e, -0x03, 0x78, 0x0b, 0x05, 0xeb, 0x03, 0x32, 0x00, 0x64, 0x65, -0x75, 0x12, 0x21, 0x65, 0x73, 0x52, 0x00, 0x50, 0x6c, 0x69, -0x6b, 0x65, 0x6c, 0xad, 0x0a, 0x03, 0x17, 0x13, 0x03, 0x55, -0x00, 0x21, 0x61, 0x73, 0x6c, 0x00, 0x21, 0x61, 0x73, 0x6f, -0x00, 0x66, 0x61, 0x6e, 0x2c, 0x00, 0x72, 0x61, 0x40, 0x11, -0x41, 0x63, 0x68, 0x6f, 0x6f, 0xbd, 0x08, 0x05, 0xdf, 0x00, -0x02, 0x68, 0x06, 0x01, 0x40, 0x02, 0x64, 0x48, 0x69, 0x67, -0x68, 0x00, 0x65, 0x7b, 0x01, 0x12, 0x00, 0x7b, 0x01, 0x52, -0x73, 0x00, 0x75, 0x73, 0x75, 0x9f, 0x0b, 0x33, 0x65, 0x61, -0x6e, 0x6e, 0x02, 0x07, 0xae, 0x03, 0x23, 0x74, 0x68, 0x8b, -0x02, 0x05, 0xf3, 0x0a, 0x05, 0xe0, 0x01, 0x00, 0x60, 0x05, -0x0e, 0x4f, 0x00, 0x01, 0xe1, 0x02, 0x20, 0x72, 0x65, 0xf8, -0x05, 0x32, 0x6c, 0x6f, 0x74, 0xbd, 0x08, 0x00, 0x7c, 0x04, -0x73, 0x6c, 0x79, 0x2d, 0x70, 0x61, 0x63, 0x6b, 0xb9, 0x0b, -0x50, 0x6e, 0x64, 0x73, 0x2e, 0x00, +0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf3, 0x37, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, +0x61, 0x00, 0x73, 0x65, 0x74, 0x00, 0x6f, 0x66, 0x00, 0x69, +0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x00, 0x64, 0x69, 0x73, +0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x00, 0x61, +0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0x74, 0x68, 0x65, 0x00, +0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x72, +0x65, 0x61, 0x2e, 0x00, 0x45, 0x61, 0x63, 0x68, 0x32, 0x00, +0xf0, 0x04, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, +0x73, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, +0x2e, 0x5e, 0x00, 0xb0, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, +0x69, 0x73, 0x00, 0x74, 0x6f, 0x22, 0x00, 0x41, 0x6e, 0x65, +0x63, 0x74, 0x48, 0x00, 0x04, 0x67, 0x00, 0xf2, 0x00, 0x74, +0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x00, 0x77, 0x69, +0x74, 0x68, 0x00, 0x62, 0xae, 0x00, 0xf3, 0x0b, 0x2c, 0x00, +0x69, 0x6e, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x61, 0x00, +0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, 0x3a, 0x00, +0x00, 0x00, 0x2d, 0x00, 0xcf, 0x00, 0xa0, 0x00, 0x72, 0x75, +0x6e, 0x00, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x75, 0x00, 0xd0, +0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, +0x74, 0x69, 0x63, 0x0e, 0x00, 0x11, 0x2e, 0x2c, 0x00, 0x33, +0x54, 0x68, 0x65, 0x8a, 0x00, 0x00, 0xd8, 0x00, 0x13, 0x62, +0x3a, 0x00, 0x81, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, +0x74, 0xc5, 0x00, 0x54, 0x74, 0x00, 0x61, 0x6e, 0x79, 0xc1, +0x00, 0x80, 0x69, 0x73, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6c, +0xab, 0x00, 0x16, 0x74, 0x3c, 0x00, 0x70, 0x77, 0x72, 0x69, +0x74, 0x74, 0x65, 0x6e, 0x93, 0x00, 0x00, 0x88, 0x00, 0x03, +0x2e, 0x00, 0x03, 0x63, 0x00, 0x25, 0x77, 0x6f, 0x59, 0x00, +0x31, 0x6d, 0x61, 0x79, 0x97, 0x00, 0xf1, 0x04, 0x69, 0x6e, +0x00, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x00, +0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x4f, 0x00, 0x84, +0x73, 0x61, 0x6d, 0x65, 0x00, 0x74, 0x77, 0x6f, 0xfb, 0x00, +0xd0, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x6e, 0x6f, 0x00, +0x6d, 0x6f, 0x72, 0x65, 0x5b, 0x00, 0x11, 0x6e, 0x1e, 0x00, +0x00, 0x47, 0x00, 0x52, 0x64, 0x6f, 0x00, 0x73, 0x6f, 0x62, +0x00, 0x14, 0x4e, 0x61, 0x00, 0x11, 0x00, 0x84, 0x01, 0x61, +0x65, 0x73, 0x00, 0x61, 0x6e, 0x6f, 0x31, 0x01, 0x02, 0x17, +0x00, 0x02, 0x26, 0x00, 0x39, 0x41, 0x6c, 0x6c, 0x56, 0x01, +0x34, 0x61, 0x72, 0x65, 0x6e, 0x01, 0x25, 0x65, 0x64, 0x64, +0x01, 0x00, 0x2c, 0x00, 0x51, 0x54, 0x68, 0x65, 0x72, 0x65, +0x20, 0x00, 0x31, 0x73, 0x6f, 0x6d, 0x25, 0x00, 0xf0, 0x00, +0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, +0x61, 0x6c, 0x74, 0x65, 0x72, 0x1b, 0x01, 0x60, 0x76, 0x65, +0x00, 0x6d, 0x6f, 0x64, 0x88, 0x01, 0x30, 0x77, 0x68, 0x69, +0xe2, 0x01, 0xc0, 0x6e, 0x76, 0x6f, 0x6c, 0x76, 0x65, 0x00, +0x63, 0x68, 0x61, 0x6e, 0x67, 0x39, 0x01, 0x01, 0x0a, 0x02, +0x03, 0xe5, 0x00, 0x13, 0x2d, 0xa0, 0x00, 0x50, 0x6c, 0x69, +0x6d, 0x69, 0x74, 0x3c, 0x01, 0x00, 0x59, 0x00, 0x20, 0x74, +0x68, 0x27, 0x00, 0x02, 0xa9, 0x00, 0x01, 0xdb, 0x00, 0x31, +0x32, 0x2c, 0x00, 0x64, 0x01, 0x74, 0x6e, 0x74, 0x72, 0x6f, +0x64, 0x75, 0x63, 0x45, 0x00, 0xa0, 0x61, 0x64, 0x64, 0x69, +0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x8b, 0x00, 0x72, 0x73, +0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x68, 0x01, 0xb8, 0x6e, +0x6f, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, +0xc0, 0x01, 0x00, 0x20, 0x01, 0xf4, 0x05, 0x66, 0x6f, 0x72, +0x6d, 0x00, 0x61, 0x00, 0x6c, 0x6f, 0x6f, 0x70, 0x00, 0x66, +0x72, 0x6f, 0x6d, 0x00, 0x6f, 0x6e, 0x65, 0xc6, 0x01, 0x44, +0x62, 0x61, 0x63, 0x6b, 0xc2, 0x01, 0x01, 0x73, 0x01, 0x04, +0xb0, 0x01, 0x00, 0x0f, 0x02, 0x91, 0x72, 0x75, 0x6c, 0x65, +0x73, 0x00, 0x73, 0x74, 0x61, 0xd6, 0x02, 0x32, 0x62, 0x6f, +0x76, 0x0b, 0x01, 0x00, 0x2c, 0x00, 0x70, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6c, 0x74, 0x4b, 0x00, 0x10, 0x73, 0x29, 0x01, +0x60, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x6b, 0x00, 0xf1, +0x01, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, +0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0xcc, 0x02, 0xb0, +0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x31, 0x32, +0x5d, 0x2e, 0x00, 0x04, 0x98, 0x02, 0x31, 0x77, 0x61, 0x73, +0x09, 0x03, 0x04, 0x3a, 0x03, 0x01, 0x89, 0x00, 0x10, 0x69, +0x14, 0x00, 0x40, 0x6c, 0x6c, 0x65, 0x63, 0xea, 0x00, 0xf1, +0x00, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, +0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0xac, 0x02, 0x00, 0x46, +0x00, 0xe1, 0x00, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, +0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x5e, 0x00, 0xa2, 0x2e, +0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0x7d, +0x00, 0xf5, 0x08, 0x73, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, +0x77, 0x6f, 0x6b, 0x61, 0x6b, 0x65, 0x72, 0x6f, 0x2f, 0x00, +0x00, 0x00, 0x32, 0x36, 0x2e, 0x31, 0xe4, 0x03, 0x01, 0x79, +0x00, 0x40, 0x6f, 0x6c, 0x73, 0x20, 0xe8, 0x01, 0x10, 0x6f, +0xab, 0x03, 0x10, 0x63, 0xd9, 0x03, 0x03, 0xa0, 0x01, 0x05, +0x8c, 0x02, 0x08, 0x83, 0x02, 0x30, 0x63, 0x6c, 0x69, 0x2f, +0x01, 0x10, 0x68, 0xf1, 0x01, 0xb8, 0x75, 0x73, 0x65, 0x00, +0x64, 0x6f, 0x77, 0x6e, 0x00, 0x6f, 0x6e, 0x51, 0x01, 0x00, +0x04, 0x00, 0x51, 0x64, 0x72, 0x61, 0x67, 0x00, 0xde, 0x01, +0x42, 0x77, 0x61, 0x72, 0x64, 0x0a, 0x04, 0x01, 0xdd, 0x01, +0x01, 0xe4, 0x03, 0x00, 0xb0, 0x02, 0x62, 0x6e, 0x6f, 0x74, +0x00, 0x6e, 0x65, 0xf2, 0x00, 0x01, 0x2e, 0x00, 0x13, 0x61, +0x93, 0x02, 0x01, 0xc0, 0x03, 0x16, 0x6f, 0x32, 0x00, 0x03, +0x57, 0x00, 0xa5, 0x3b, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6f, +0x6e, 0x6c, 0x79, 0x37, 0x00, 0x10, 0x6d, 0x8f, 0x01, 0x06, +0x8b, 0x00, 0xa3, 0x66, 0x61, 0x72, 0x00, 0x65, 0x6e, 0x6f, +0x75, 0x67, 0x68, 0x85, 0x01, 0x10, 0x65, 0x3e, 0x02, 0x54, +0x65, 0x6e, 0x64, 0x65, 0x64, 0xd3, 0x00, 0x33, 0x64, 0x69, +0x72, 0x55, 0x01, 0xf1, 0x07, 0x74, 0x6f, 0x00, 0x62, 0x65, +0x00, 0x75, 0x6e, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, +0x75, 0x73, 0x2e, 0x00, 0x28, 0x53, 0x6f, 0x64, 0x00, 0x87, +0x63, 0x61, 0x6e, 0x00, 0x6b, 0x65, 0x65, 0x70, 0x5b, 0x00, +0x42, 0x6e, 0x65, 0x61, 0x72, 0x21, 0x02, 0x31, 0x74, 0x61, +0x72, 0x0a, 0x04, 0x07, 0xec, 0x00, 0xb0, 0x63, 0x6f, 0x6e, +0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x74, 0x6c, 0x7a, 0x04, +0x35, 0x72, 0x6f, 0x77, 0x7c, 0x02, 0x32, 0x6f, 0x75, 0x74, +0x70, 0x02, 0x20, 0x69, 0x74, 0xe7, 0x03, 0x10, 0x6d, 0x3d, +0x04, 0x05, 0x84, 0x00, 0x82, 0x73, 0x2e, 0x29, 0x00, 0x00, +0x00, 0x44, 0x6f, 0xdb, 0x02, 0xd6, 0x69, 0x73, 0x00, 0x61, +0x67, 0x61, 0x69, 0x6e, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x85, +0x01, 0x00, 0x17, 0x00, 0xf0, 0x04, 0x6c, 0x72, 0x65, 0x61, +0x64, 0x79, 0x00, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, +0x00, 0x77, 0x69, 0x6c, 0x6c, 0x08, 0x03, 0x05, 0xd9, 0x03, +0x06, 0x3e, 0x04, 0x03, 0xe2, 0x03, 0x45, 0x49, 0x66, 0x00, +0x74, 0xb7, 0x03, 0x04, 0x3f, 0x00, 0x22, 0x61, 0x73, 0x80, +0x00, 0x04, 0x9c, 0x00, 0x08, 0x6b, 0x04, 0x07, 0xe3, 0x01, +0x00, 0x28, 0x00, 0x10, 0x70, 0xf3, 0x04, 0x20, 0x74, 0x74, +0x38, 0x01, 0x11, 0x79, 0x20, 0x00, 0x40, 0x63, 0x75, 0x72, +0x72, 0x7b, 0x00, 0x34, 0x67, 0x61, 0x6d, 0x14, 0x03, 0x51, +0x28, 0x69, 0x2e, 0x65, 0x2e, 0x39, 0x00, 0x24, 0x62, 0x79, +0x0c, 0x03, 0x26, 0x29, 0x2c, 0x46, 0x03, 0x00, 0xd4, 0x01, +0x11, 0x67, 0x34, 0x05, 0x02, 0x71, 0x01, 0x01, 0xb6, 0x00, +0x21, 0x72, 0x65, 0xb4, 0x01, 0x00, 0xeb, 0x01, 0x11, 0x6f, +0xa4, 0x00, 0x10, 0x6d, 0xce, 0x02, 0x21, 0x49, 0x66, 0x78, +0x01, 0x31, 0x77, 0x61, 0x6e, 0x0f, 0x04, 0x60, 0x72, 0x65, +0x6d, 0x69, 0x6e, 0x64, 0x13, 0x00, 0x52, 0x72, 0x73, 0x65, +0x6c, 0x66, 0xdd, 0x03, 0x08, 0xa2, 0x00, 0x90, 0x64, 0x65, +0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x6c, 0xf9, 0x04, 0x10, +0x20, 0x49, 0x02, 0x03, 0x92, 0x06, 0x0c, 0xb9, 0x02, 0x45, +0x68, 0x65, 0x6d, 0x2c, 0xd3, 0x01, 0x61, 0x72, 0x69, 0x67, +0x68, 0x74, 0x2d, 0x6b, 0x02, 0x08, 0x21, 0x00, 0x27, 0x00, +0x69, 0x6e, 0x05, 0x03, 0x7c, 0x02, 0xb3, 0x64, 0x72, 0x61, +0x77, 0x00, 0x61, 0x00, 0x60, 0x6e, 0x6f, 0x6e, 0xad, 0x04, +0x87, 0x27, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0xaf, +0x00, 0x00, 0xb2, 0x04, 0x34, 0x6b, 0x00, 0x79, 0x10, 0x07, +0x00, 0x93, 0x00, 0x42, 0x73, 0x68, 0x65, 0x64, 0x98, 0x06, +0x24, 0x61, 0x6e, 0x22, 0x02, 0x02, 0x28, 0x01, 0x05, 0x27, +0x00, 0x01, 0x64, 0x03, 0x11, 0x64, 0x02, 0x01, 0x35, 0x69, +0x74, 0x73, 0x8d, 0x01, 0x01, 0x4c, 0x02, 0x13, 0x72, 0x5f, +0x05, 0x24, 0x64, 0x65, 0xd3, 0x04, 0x41, 0x74, 0x68, 0x65, +0x79, 0x18, 0x00, 0x03, 0xa5, 0x00, 0x01, 0xc4, 0x00, 0x02, +0x44, 0x00, 0x26, 0x73, 0x29, 0xdb, 0x00, 0x00, 0x9c, 0x00, +0x07, 0xcf, 0x05, 0x00, 0xc3, 0x01, 0x05, 0x8f, 0x00, 0x81, +0x62, 0x79, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0xb9, 0x03, +0x01, 0x64, 0x05, 0x40, 0x6e, 0x00, 0x69, 0x74, 0xde, 0x04, +0x22, 0x69, 0x73, 0x95, 0x01, 0x51, 0x68, 0x69, 0x67, 0x68, +0x6c, 0x59, 0x00, 0x22, 0x69, 0x74, 0x89, 0x00, 0x03, 0x8a, +0x03, 0x04, 0x9d, 0x00, 0x08, 0x19, 0x06, 0x32, 0x00, 0x69, +0x74, 0x99, 0x05, 0x01, 0xb2, 0x01, 0x20, 0x69, 0x6c, 0xb3, +0x06, 0x00, 0x9a, 0x02, 0x30, 0x76, 0x65, 0x6e, 0x21, 0x00, +0x01, 0xed, 0x02, 0x31, 0x61, 0x63, 0x63, 0xc4, 0x00, 0x01, +0x68, 0x07, 0x52, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x02, 0x08, +0x22, 0x6e, 0x79, 0xf6, 0x01, 0x26, 0x6f, 0x73, 0x5c, 0x00, +0xc9, 0x69, 0x6e, 0x00, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, +0x2e, 0x00, 0x4c, 0xa7, 0x00, 0x02, 0x0d, 0x03, 0x10, 0x6f, +0x0b, 0x03, 0x05, 0xa1, 0x00, 0x24, 0x65, 0x64, 0xe2, 0x00, +0x01, 0x7a, 0x00, 0x21, 0x75, 0x6e, 0xf9, 0x00, 0x03, 0xb6, +0x00, 0x40, 0x72, 0x65, 0x73, 0x74, 0x19, 0x07, 0x11, 0x79, +0x44, 0x08, 0x51, 0x62, 0x69, 0x6c, 0x69, 0x74, 0xcd, 0x01, +0x02, 0x81, 0x00, 0x01, 0xf4, 0x00, 0x02, 0xbf, 0x08, 0x00, +0x32, 0x01, 0x50, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0xda, 0x03, +0x03, 0xde, 0x02, 0x85, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, +0x79, 0x73, 0x57, 0x04, 0x61, 0x61, 0x72, 0x6f, 0x75, 0x6e, +0x64, 0x1f, 0x00, 0xf9, 0x01, 0x67, 0x72, 0x69, 0x64, 0x3a, +0x00, 0x69, 0x66, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, +0x6c, 0x35, 0x00, 0x02, 0x8d, 0x03, 0x52, 0x6c, 0x77, 0x61, +0x79, 0x73, 0x39, 0x00, 0x80, 0x6f, 0x72, 0x74, 0x68, 0x6f, +0x67, 0x6f, 0x6e, 0xfd, 0x00, 0x12, 0x2c, 0xc2, 0x04, 0x63, +0x77, 0x69, 0x73, 0x65, 0x00, 0x69, 0xb9, 0x03, 0x02, 0xb5, +0x04, 0x07, 0x17, 0x05, 0x00, 0x5c, 0x04, 0x24, 0x65, 0x73, +0x27, 0x08, 0x04, 0xfb, 0x04, 0x51, 0x69, 0x6e, 0x64, 0x69, +0x63, 0x76, 0x06, 0x05, 0x30, 0x04, 0x60, 0x2e, 0x00, 0x48, +0x6f, 0x6c, 0x64, 0x1c, 0x01, 0x12, 0x43, 0xb8, 0x05, 0x01, +0xf7, 0x00, 0x00, 0x16, 0x04, 0x11, 0x73, 0x31, 0x01, 0x07, +0xc8, 0x00, 0x02, 0x6b, 0x00, 0x37, 0x6c, 0x61, 0x79, 0x49, +0x04, 0x03, 0x8e, 0x08, 0x06, 0x03, 0x05, 0x90, 0x28, 0x69, +0x66, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0xcc, 0x07, 0x73, +0x29, 0x3b, 0x00, 0x53, 0x68, 0x69, 0x66, 0x01, 0x02, 0x0f, +0x4b, 0x00, 0x04, 0x01, 0x11, 0x03, 0x1c, 0x00, 0x12, 0x03, +0x14, 0x50, 0x82, 0x00, 0x01, 0xa2, 0x02, 0x40, 0x65, 0x74, +0x75, 0x72, 0x40, 0x05, 0x00, 0x75, 0x07, 0x42, 0x6c, 0x6c, +0x6f, 0x77, 0x83, 0x02, 0x0e, 0x52, 0x00, 0x01, 0x82, 0x01, +0x0f, 0xa2, 0x00, 0x0b, 0x08, 0xb1, 0x01, 0x01, 0xea, 0x01, +0x2f, 0x61, 0x6e, 0xe2, 0x02, 0x04, 0x18, 0x70, 0x83, 0x00, +0x20, 0x73, 0x70, 0xc7, 0x06, 0x30, 0x62, 0x61, 0x72, 0xe4, +0x09, 0x0c, 0x1d, 0x00, 0x07, 0xa0, 0x00, 0x51, 0x74, 0x77, +0x69, 0x63, 0x65, 0x8c, 0x07, 0x07, 0x24, 0x00, 0x04, 0x8c, +0x0a, 0x00, 0x22, 0x00, 0x06, 0x61, 0x03, 0x45, 0x6a, 0x75, +0x6d, 0x70, 0xe6, 0x09, 0x0a, 0xb0, 0x01, 0x01, 0xef, 0x03, +0x02, 0x80, 0x08, 0x03, 0xc5, 0x0a, 0xf0, 0x0c, 0x4c, 0x65, +0x74, 0x74, 0x65, 0x72, 0x73, 0x00, 0x60, 0x61, 0x27, 0x2c, +0x00, 0x2e, 0x2e, 0x2e, 0x2c, 0x00, 0x60, 0x66, 0x27, 0x00, +0x63, 0x6f, 0x75, 0x6e, 0x74, 0xb8, 0x00, 0x23, 0x31, 0x30, +0x16, 0x00, 0x21, 0x31, 0x35, 0x6d, 0x01, 0x31, 0x60, 0x30, +0x27, 0x17, 0x00, 0x13, 0x36, 0x6e, 0x09, 0x46, 0x00, 0x60, +0x47, 0x27, 0x27, 0x01, 0x03, 0x8b, 0x04, 0x86, 0x67, 0x72, +0x65, 0x79, 0x00, 0x6c, 0x69, 0x6e, 0xdd, 0x04, 0x10, 0x65, +0x4a, 0x0b, 0x48, 0x70, 0x61, 0x69, 0x72, 0x84, 0x0b, 0x01, +0x88, 0x00, 0x78, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x62, +0xd1, 0x09, 0x02, 0x94, 0x04, 0x04, 0x69, 0x01, 0x36, 0x6f, +0x72, 0x00, 0xda, 0x04, 0x01, 0x55, 0x0a, 0x25, 0x61, 0x72, +0xe4, 0x05, 0x00, 0x60, 0x07, 0x11, 0x6f, 0x2c, 0x03, 0x51, +0x56, 0x69, 0x6f, 0x6c, 0x61, 0xa9, 0x06, 0x03, 0xad, 0x05, +0x04, 0xd3, 0x08, 0x02, 0x01, 0x06, 0x04, 0xfd, 0x03, 0x01, +0x07, 0x02, 0x10, 0x64, 0xbe, 0x01, 0x42, 0x72, 0x65, 0x64, +0x3a, 0x5e, 0x0a, 0x1a, 0x6e, 0x1e, 0x01, 0x2a, 0x6f, 0x6f, +0x7b, 0x06, 0x04, 0x3b, 0x00, 0x09, 0xd9, 0x03, 0x01, 0x40, +0x00, 0x1f, 0x2e, 0x40, 0x00, 0x05, 0x3f, 0x66, 0x65, 0x77, +0x3f, 0x00, 0x10, 0x00, 0xa6, 0x03, 0x00, 0x6b, 0x07, 0x09, +0x24, 0x06, 0xf3, 0x03, 0x61, 0x6e, 0x00, 0x65, 0x72, 0x72, +0x6f, 0x72, 0x00, 0x28, 0x61, 0x73, 0x00, 0x6f, 0x70, 0x70, +0x6f, 0x73, 0x3f, 0x08, 0x32, 0x65, 0x72, 0x65, 0xee, 0x00, +0x30, 0x00, 0x62, 0x65, 0xfc, 0x01, 0x05, 0x52, 0x02, 0x41, +0x79, 0x65, 0x74, 0x29, 0xf2, 0x03, 0x21, 0x61, 0x64, 0x70, +0x03, 0x03, 0x56, 0x08, 0x05, 0x80, 0x00, 0x01, 0x61, 0x01, +0x04, 0xe4, 0x0a, 0x31, 0x68, 0x61, 0x76, 0x5d, 0x02, 0x12, +0x6f, 0x71, 0x0b, 0x0b, 0x6f, 0x0b, 0x00, 0x6d, 0x01, 0x04, +0xf6, 0x06, 0x08, 0x76, 0x01, 0x02, 0x3d, 0x03, 0x10, 0x2c, +0x1f, 0x00, 0x28, 0x69, 0x66, 0xbc, 0x05, 0x20, 0x68, 0x61, +0x9b, 0x07, 0x29, 0x65, 0x6e, 0xde, 0x00, 0x01, 0x25, 0x0a, +0x54, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0xc0, 0x0b, 0x68, 0x00, +0x67, 0x72, 0x6f, 0x75, 0x70, 0xfc, 0x01, 0x01, 0xcc, 0x0a, +0x07, 0xf4, 0x0a, 0x0f, 0x21, 0x01, 0x0c, 0x41, 0x61, 0x00, +0x63, 0x6c, 0x0a, 0x01, 0x33, 0x73, 0x75, 0x62, 0xca, 0x0d, +0x07, 0xe3, 0x01, 0x01, 0x78, 0x01, 0x24, 0x6e, 0x6f, 0x11, +0x07, 0x04, 0x89, 0x0d, 0x02, 0xb0, 0x0b, 0x02, 0x48, 0x03, +0x15, 0x73, 0x34, 0x00, 0x03, 0x82, 0x00, 0x90, 0x2e, 0x00, +0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0xa9, 0x00, 0x32, +0x2c, 0x00, 0x69, 0x27, 0x07, 0x02, 0xce, 0x03, 0x26, 0x6c, +0x79, 0xcd, 0x0d, 0x4c, 0x77, 0x6f, 0x00, 0x31, 0xc8, 0x0d, +0x05, 0x9c, 0x02, 0x01, 0x03, 0x05, 0x04, 0xf6, 0x06, 0x22, +0x6e, 0x6f, 0xfc, 0x0d, 0x01, 0xf6, 0x09, 0x08, 0x02, 0x08, +0x25, 0x6f, 0x6e, 0x9a, 0x05, 0x01, 0x73, 0x08, 0x04, 0xa6, +0x04, 0x01, 0xc6, 0x06, 0x43, 0x75, 0x70, 0x00, 0x72, 0xac, +0x06, 0x03, 0x45, 0x05, 0x02, 0x18, 0x03, 0x03, 0x20, 0x0e, +0x02, 0x39, 0x01, 0x32, 0x63, 0x61, 0x6e, 0xf9, 0x01, 0x04, +0x87, 0x0e, 0x02, 0x23, 0x01, 0x00, 0xa6, 0x02, 0xa4, 0x76, +0x61, 0x6c, 0x69, 0x64, 0x00, 0x73, 0x6f, 0x6c, 0x75, 0x85, +0x04, 0x14, 0x2d, 0xf4, 0x07, 0x01, 0xc3, 0x07, 0x33, 0x73, +0x65, 0x6c, 0x0e, 0x07, 0x40, 0x68, 0x65, 0x00, 0x28, 0xd4, +0x01, 0x04, 0xff, 0x08, 0x34, 0x00, 0x6f, 0x70, 0x5d, 0x0a, +0x40, 0x64, 0x69, 0x73, 0x61, 0xff, 0x04, 0x01, 0x74, 0x0c, +0x15, 0x73, 0x65, 0x08, 0x03, 0x55, 0x00, 0x15, 0x2c, 0x88, +0x00, 0x07, 0xa9, 0x0c, 0x02, 0x3b, 0x0d, 0x00, 0xab, 0x0c, +0x14, 0x73, 0xac, 0x0c, 0x0e, 0xea, 0x02, 0x01, 0x22, 0x03, +0x14, 0x28, 0xbf, 0x0d, 0x02, 0x5c, 0x09, 0x00, 0xee, 0x02, +0x52, 0x73, 0x63, 0x72, 0x69, 0x62, 0xc4, 0x00, 0x13, 0x73, +0xe0, 0x05, 0x33, 0x32, 0x2e, 0x31, 0x01, 0x0a, 0x26, 0x73, +0x6f, 0xe9, 0x05, 0x22, 0x2e, 0x29, 0x06, 0x0c, 0x15, 0x32, +0x06, 0x0c, 0x00, 0x3f, 0x0a, 0x20, 0x6d, 0x65, 0xb3, 0x04, +0x12, 0x20, 0x82, 0x04, 0x36, 0x73, 0x65, 0x00, 0x14, 0x00, +0x02, 0x43, 0x00, 0x04, 0x3e, 0x00, 0x02, 0xe1, 0x07, 0x10, +0x74, 0xa6, 0x04, 0xa4, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0xf7, 0x00, 0x03, 0x96, 0x01, 0x40, +0x60, 0x54, 0x79, 0x70, 0x1f, 0x06, 0x30, 0x65, 0x6e, 0x75, +0xad, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, +0x48, 0x65, 0x9d, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, +0xa0, 0x0d, 0x00, 0xbd, 0x01, 0x01, 0xaf, 0x00, 0x42, 0x71, +0x75, 0x61, 0x72, 0x43, 0x0d, 0xaa, 0x44, 0x69, 0x66, 0x66, +0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x0d, 0x00, 0x41, 0x6c, +0x65, 0x76, 0x65, 0x32, 0x0a, 0x02, 0x9e, 0x02, 0x00, 0x2b, +0x00, 0x10, 0x41, 0x5d, 0x01, 0x12, 0x20, 0x5d, 0x01, 0x12, +0x00, 0xcd, 0x08, 0x21, 0x69, 0x73, 0x93, 0x10, 0x06, 0x8f, +0x0a, 0x01, 0x09, 0x0b, 0x20, 0x63, 0x6c, 0xb0, 0x05, 0x23, +0x64, 0x2c, 0x3c, 0x00, 0x06, 0x3e, 0x04, 0x51, 0x67, 0x65, +0x6e, 0x65, 0x72, 0x62, 0x07, 0x0e, 0x3c, 0x10, 0x06, 0x83, +0x02, 0x03, 0xdb, 0x07, 0x00, 0xb9, 0x01, 0x13, 0x62, 0x18, +0x03, 0x00, 0xd5, 0x0b, 0x33, 0x63, 0x72, 0x65, 0x12, 0x10, +0x01, 0xa9, 0x01, 0x02, 0x13, 0x09, 0x04, 0xde, 0x01, 0x04, +0xcb, 0x01, 0x25, 0x64, 0x6f, 0x25, 0x04, 0x0b, 0xd0, 0x01, +0x04, 0x1e, 0x02, 0x02, 0xcf, 0x01, 0x64, 0x4d, 0x61, 0x78, +0x2e, 0x20, 0x62, 0x8e, 0x01, 0x36, 0x65, 0x72, 0x20, 0xa4, +0x07, 0x01, 0x1d, 0x00, 0x4e, 0x69, 0x6d, 0x75, 0x6d, 0x99, +0x10, 0x04, 0xaf, 0x02, 0x20, 0x70, 0x61, 0xc6, 0x10, 0x48, +0x75, 0x6c, 0x61, 0x72, 0x3a, 0x07, 0x17, 0x54, 0xa2, 0x0e, +0x42, 0x69, 0x73, 0x00, 0x32, 0x3d, 0x10, 0x04, 0xd0, 0x06, +0x01, 0x98, 0x0f, 0x13, 0x65, 0xcf, 0x03, 0x40, 0x31, 0x2c, +0x00, 0x33, 0x88, 0x04, 0x53, 0x34, 0x2e, 0x00, 0x49, 0x6e, +0x17, 0x01, 0x20, 0x6c, 0x2c, 0x72, 0x05, 0x21, 0x65, 0x72, +0xe4, 0x10, 0x32, 0x61, 0x73, 0x69, 0xfa, 0x0a, 0x82, 0x25, +0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x87, 0x03, 0x13, +0x20, 0xba, 0x01, 0x70, 0x00, 0x00, 0x00, 0x47, 0x69, 0x76, +0x65, 0xb5, 0x02, 0x11, 0x72, 0x28, 0x05, 0x40, 0x70, 0x65, +0x72, 0x63, 0xff, 0x09, 0x2a, 0x67, 0x65, 0x9c, 0x06, 0x05, +0x74, 0x01, 0x04, 0x38, 0x09, 0x31, 0x74, 0x72, 0x79, 0x39, +0x01, 0x11, 0x6c, 0xaf, 0x04, 0x34, 0x66, 0x6f, 0x72, 0x47, +0x0b, 0x05, 0x33, 0x10, 0x03, 0xf0, 0x01, 0x30, 0x43, 0x65, +0x72, 0xa4, 0x03, 0x00, 0x29, 0x00, 0x33, 0x6f, 0x75, 0x74, +0xc4, 0x01, 0x00, 0xc0, 0x03, 0x30, 0x6d, 0x61, 0x6e, 0x67, +0x00, 0x12, 0x74, 0x4b, 0x08, 0x03, 0xa8, 0x05, 0x03, 0x72, +0x00, 0x12, 0x3b, 0x56, 0x0d, 0x10, 0x69, 0x1b, 0x05, 0x40, +0x00, 0x75, 0x70, 0x70, 0x94, 0x05, 0x22, 0x6f, 0x75, 0x8a, +0x11, 0xf0, 0x03, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, +0x6f, 0x6e, 0x20, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x20, +0x28, 0xdc, 0x00, 0x13, 0x29, 0x82, 0x07, 0x01, 0x9b, 0x02, +0x07, 0xac, 0x00, 0x41, 0x6f, 0x72, 0x6b, 0x73, 0x4a, 0x08, +0x04, 0x9c, 0x0a, 0x69, 0x6e, 0x00, 0x65, 0x78, 0x69, 0x73, +0x09, 0x0e, 0xf8, 0x05, 0x74, 0x00, 0x72, 0x61, 0x6e, 0x64, +0x6f, 0x6d, 0x00, 0x28, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, +0x66, 0x69, 0x72, 0x73, 0x28, 0x02, 0x20, 0x6e, 0x00, 0x90, +0x06, 0x34, 0x69, 0x61, 0x6c, 0x32, 0x00, 0x00, 0xf6, 0x10, +0x10, 0x77, 0xa6, 0x0d, 0x41, 0x29, 0x2e, 0x00, 0x49, 0x72, +0x02, 0x40, 0x6e, 0x00, 0x64, 0x65, 0x3a, 0x0b, 0x12, 0x73, +0xf7, 0x0a, 0x07, 0xaa, 0x09, 0x05, 0x5e, 0x00, 0x24, 0x29, +0x2c, 0x22, 0x05, 0x13, 0x6e, 0x97, 0x00, 0x00, 0x8e, 0x02, +0x31, 0x68, 0x6f, 0x77, 0xfe, 0x0e, 0x14, 0x69, 0xfd, 0x07, +0x20, 0x65, 0x78, 0xf8, 0x0e, 0x04, 0x54, 0x01, 0x07, 0x85, +0x00, 0x08, 0x52, 0x0f, 0x03, 0x04, 0x0c, 0x05, 0xeb, 0x03, +0x32, 0x00, 0x64, 0x65, 0xec, 0x12, 0x21, 0x65, 0x73, 0x52, +0x00, 0x50, 0x6c, 0x69, 0x6b, 0x65, 0x6c, 0x39, 0x0b, 0x03, +0x8e, 0x13, 0x03, 0x55, 0x00, 0x21, 0x61, 0x73, 0x6c, 0x00, +0x21, 0x61, 0x73, 0x6f, 0x00, 0x66, 0x61, 0x6e, 0x2c, 0x00, +0x72, 0x61, 0xb7, 0x11, 0x41, 0x63, 0x68, 0x6f, 0x6f, 0x49, +0x09, 0x05, 0xdf, 0x00, 0x02, 0x68, 0x06, 0x01, 0x40, 0x02, +0x64, 0x48, 0x69, 0x67, 0x68, 0x00, 0x65, 0x7b, 0x01, 0x12, +0x00, 0x7b, 0x01, 0x52, 0x73, 0x00, 0x75, 0x73, 0x75, 0x2b, +0x0c, 0x33, 0x65, 0x61, 0x6e, 0x6e, 0x02, 0x07, 0xae, 0x03, +0x23, 0x74, 0x68, 0x8b, 0x02, 0x05, 0x7f, 0x0b, 0x05, 0xe0, +0x01, 0x00, 0x60, 0x05, 0x0e, 0x4f, 0x00, 0x01, 0xe1, 0x02, +0x20, 0x72, 0x65, 0xf8, 0x05, 0x32, 0x6c, 0x6f, 0x74, 0xbd, +0x08, 0x00, 0x7c, 0x04, 0x61, 0x6c, 0x79, 0x2d, 0x70, 0x61, +0x63, 0xac, 0x08, 0x04, 0xb1, 0x06, 0x01, 0x0a, 0x05, 0x15, +0x33, 0x0a, 0x05, 0xb0, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, +0x72, 0x65, 0x66, 0x65, 0x72, 0x46, 0x12, 0x01, 0x10, 0x05, +0x20, 0x4f, 0x6e, 0x70, 0x0d, 0x12, 0x74, 0x97, 0x05, 0x03, +0x48, 0x06, 0x60, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, +0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0xfe, 0x04, 0x16, +0x50, 0x12, 0x00, 0x0d, 0x1a, 0x05, 0x33, 0x47, 0x61, 0x6d, +0x1a, 0x05, 0x03, 0xb1, 0x06, 0x13, 0x65, 0x94, 0x03, 0x03, +0x56, 0x13, 0x10, 0x65, 0xfe, 0x0f, 0x28, 0x74, 0x68, 0xed, +0x00, 0x04, 0x2d, 0x13, 0x23, 0x6f, 0x63, 0x8c, 0x09, 0x01, +0x8b, 0x13, 0x80, 0x68, 0x6f, 0x77, 0x6e, 0x2e, 0x00, 0x55, +0x6e, 0xa4, 0x01, 0x26, 0x00, 0x74, 0x35, 0x0a, 0x00, 0x84, +0x00, 0x04, 0xd8, 0x0d, 0x75, 0x70, 0x65, 0x72, 0x73, 0x69, +0x73, 0x74, 0x32, 0x0a, 0x70, 0x67, 0x61, 0x6d, 0x65, 0x73, +0x2e, 0x00, }; -const unsigned short help_text_len = 5230; -const unsigned short help_text_words = 963; +const unsigned short help_text_len = 5613; +const unsigned short help_text_words = 1026; const char quick_help_text[] = "Connect all the islands with a network of bridges."; diff --git a/apps/plugins/puzzles/help/cube.c b/apps/plugins/puzzles/help/cube.c index 6857cbf733..21c3eb7cc3 100644 --- a/apps/plugins/puzzles/help/cube.c +++ b/apps/plugins/puzzles/help/cube.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,163 +6,164 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 207, TEXT_CENTER | C_RED }, - { 319, TEXT_CENTER | C_RED }, - { 336, TEXT_UNDERLINE }, - { 358, TEXT_UNDERLINE }, + { 208, TEXT_CENTER | C_RED }, + { 320, TEXT_CENTER | C_RED }, + { 337, TEXT_UNDERLINE }, { 359, TEXT_UNDERLINE }, + { 360, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2055 comp 1444 ratio 0.702676 level 10 saved 611 */ +/* orig 2071 comp 1451 ratio 0.700628 level 10 saved 620 */ const char help_text[] = { -0xf2, 0x37, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, -0x34, 0x3a, 0x20, 0x43, 0x75, 0x62, 0x65, 0x20, 0x00, 0x00, -0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x69, 0x73, 0x00, 0x61, -0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0x6f, 0x6e, 0x65, -0x00, 0x49, 0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, -0x6c, 0x6c, 0x79, 0x00, 0x73, 0x61, 0x77, 0x00, 0x61, 0x73, -0x00, 0x61, 0x00, 0x77, 0x65, 0x62, 0x00, 0x67, 0x61, 0x6d, -0x65, 0x2e, 0x34, 0x00, 0x00, 0x29, 0x00, 0x11, 0x77, 0x19, -0x00, 0x41, 0x4a, 0x61, 0x76, 0x61, 0x1a, 0x00, 0xf0, 0x28, -0x00, 0x5b, 0x32, 0x5d, 0x2c, 0x00, 0x62, 0x79, 0x00, 0x50, -0x61, 0x75, 0x6c, 0x00, 0x53, 0x63, 0x6f, 0x74, 0x74, 0x2e, -0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, -0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, -0x31, 0x36, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, -0x2c, 0x00, 0x73, 0x69, 0x78, 0x13, 0x00, 0xf1, 0x03, 0x77, -0x68, 0x69, 0x63, 0x68, 0x00, 0x61, 0x72, 0x65, 0x00, 0x62, -0x6c, 0x75, 0x65, 0x3b, 0x00, 0x6f, 0x6e, 0x61, 0x00, 0x02, -0x27, 0x00, 0x50, 0x00, 0x72, 0x65, 0x73, 0x74, 0x6a, 0x00, -0x41, 0x63, 0x75, 0x62, 0x65, 0x52, 0x00, 0x60, 0x72, 0x00, -0x6d, 0x6f, 0x76, 0x65, 0xb8, 0x00, 0xf1, 0x05, 0x74, 0x6f, -0x00, 0x75, 0x73, 0x65, 0x00, 0x74, 0x68, 0x65, 0x00, 0x61, -0x72, 0x72, 0x6f, 0x77, 0x00, 0x6b, 0x65, 0x79, 0x16, 0x00, -0x41, 0x72, 0x6f, 0x6c, 0x6c, 0x17, 0x00, 0x00, 0x35, 0x00, -0xf1, 0x0f, 0x00, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, -0x00, 0x39, 0x30, 0x00, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, -0x73, 0x00, 0x73, 0x6f, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, -0x69, 0x74, 0x4d, 0x00, 0x01, 0x35, 0x00, 0xb3, 0x61, 0x6e, -0x00, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x7c, -0x00, 0x8b, 0x2e, 0x00, 0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, -0x50, 0x00, 0x21, 0x6f, 0x6e, 0x2f, 0x00, 0x01, 0xae, 0x00, -0x03, 0x2a, 0x00, 0x11, 0x2c, 0x1e, 0x00, 0x07, 0x11, 0x00, -0x00, 0x9f, 0x00, 0x94, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x64, -0x00, 0x75, 0x70, 0xd2, 0x00, 0x40, 0x66, 0x61, 0x63, 0x65, -0xf1, 0x00, 0x04, 0x4a, 0x00, 0x37, 0x3b, 0x00, 0x69, 0x60, -0x00, 0x03, 0x51, 0x00, 0x0c, 0x25, 0x00, 0x05, 0x6f, 0x00, -0x4f, 0x6e, 0x6f, 0x6e, 0x2d, 0x73, 0x00, 0x02, 0x41, 0x6e, -0x65, 0x73, 0x73, 0x70, 0x00, 0xfe, 0x15, 0x75, 0x74, 0x00, -0x64, 0x6f, 0x77, 0x6e, 0x00, 0x61, 0x67, 0x61, 0x69, 0x6e, -0x2e, 0x00, 0x28, 0x49, 0x6e, 0x00, 0x67, 0x65, 0x6e, 0x65, -0x72, 0x61, 0x6c, 0x2c, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x65, -0x76, 0x65, 0x72, 0xd0, 0x00, 0x02, 0x49, 0x00, 0x31, 0x74, -0x77, 0x6f, 0x7b, 0x00, 0x12, 0x73, 0x19, 0x01, 0xf2, 0x11, -0x63, 0x6f, 0x6d, 0x65, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, -0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x00, 0x73, 0x77, -0x61, 0x70, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x73, -0x2e, 0x29, 0x89, 0x01, 0x33, 0x6a, 0x6f, 0x62, 0x88, 0x01, -0x71, 0x67, 0x65, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0xd3, 0x01, -0x07, 0xa5, 0x00, 0x13, 0x73, 0xbe, 0x00, 0x00, 0x62, 0x00, -0x00, 0x1b, 0x00, 0x02, 0x62, 0x00, 0x08, 0xde, 0x00, 0x22, -0x61, 0x74, 0x1d, 0x00, 0x00, 0x43, 0x02, 0x20, 0x74, 0x69, -0x62, 0x02, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x79, -0xe9, 0x01, 0x00, 0x9f, 0x02, 0x50, 0x64, 0x00, 0x74, 0x72, -0x79, 0x48, 0x00, 0x20, 0x64, 0x6f, 0xb3, 0x01, 0x20, 0x69, -0x6e, 0x96, 0x02, 0x21, 0x66, 0x65, 0x9d, 0x02, 0xf2, 0x02, -0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x2e, 0x00, -0x00, 0x00, 0x55, 0x6e, 0x6c, 0x69, 0x6b, 0x11, 0x02, 0x04, -0xc6, 0x02, 0x06, 0xa2, 0x02, 0xf2, 0x01, 0x2c, 0x00, 0x6d, -0x79, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, -0x68, 0x61, 0x73, 0xf1, 0x01, 0x50, 0x64, 0x69, 0x74, 0x69, -0x6f, 0x28, 0x00, 0xd0, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, -0x65, 0x3a, 0x00, 0x6f, 0x6e, 0x63, 0x65, 0x7f, 0x00, 0xc1, -0x27, 0x76, 0x65, 0x00, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, -0x65, 0x64, 0x53, 0x00, 0x01, 0xe7, 0x02, 0x43, 0x77, 0x69, -0x74, 0x68, 0x8e, 0x02, 0x01, 0x47, 0x01, 0x30, 0x69, 0x6e, -0x67, 0xe4, 0x00, 0x14, 0x61, 0xf8, 0x01, 0x00, 0xe8, 0x02, -0x11, 0x2c, 0x65, 0x01, 0xa2, 0x63, 0x61, 0x6e, 0x00, 0x63, -0x68, 0x61, 0x6e, 0x67, 0x65, 0xc0, 0x01, 0xa2, 0x74, 0x72, -0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x0d, 0x03, -0x00, 0xd7, 0x00, 0x02, 0xf9, 0x01, 0x20, 0x6e, 0x79, 0x13, -0x01, 0xe0, 0x61, 0x00, 0x74, 0x65, 0x74, 0x72, 0x61, 0x68, -0x65, 0x64, 0x72, 0x6f, 0x6e, 0x2c, 0x9e, 0x00, 0x33, 0x6f, -0x63, 0x74, 0x0f, 0x00, 0x30, 0x00, 0x6f, 0x72, 0x11, 0x00, -0x43, 0x69, 0x63, 0x6f, 0x73, 0x12, 0x00, 0x00, 0xef, 0x00, -0xf0, 0x13, 0x5b, 0x32, 0x5d, 0x00, 0x68, 0x74, 0x74, 0x70, -0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x33, 0x2e, 0x73, 0x79, -0x6d, 0x70, 0x61, 0x74, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x61, -0x2f, 0x70, 0x61, 0x75, 0x6c, 0x73, 0x87, 0x03, 0x10, 0x2f, -0xac, 0x00, 0x11, 0x2f, 0x3f, 0x03, 0x92, 0x68, 0x74, 0x6d, -0x00, 0x00, 0x00, 0x34, 0x2e, 0x31, 0x03, 0x04, 0x00, 0xdb, -0x01, 0x45, 0x72, 0x6f, 0x6c, 0x73, 0x0c, 0x04, 0x01, 0xe2, -0x00, 0x00, 0xb8, 0x00, 0x92, 0x62, 0x65, 0x00, 0x70, 0x6c, -0x61, 0x79, 0x65, 0x64, 0xf0, 0x00, 0x21, 0x65, 0x69, 0x20, -0x04, 0x00, 0x05, 0x01, 0xa2, 0x6b, 0x65, 0x79, 0x62, 0x6f, -0x61, 0x72, 0x64, 0x00, 0x6f, 0x10, 0x00, 0x41, 0x6d, 0x6f, -0x75, 0x73, 0x7c, 0x01, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, -0x63, 0x6c, 0x69, 0x63, 0x6b, 0x13, 0x01, 0x72, 0x61, 0x6e, -0x79, 0x77, 0x68, 0x65, 0x72, 0xbe, 0x02, 0x10, 0x68, 0x37, -0x01, 0x92, 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x77, 0x69, 0x6c, -0x6c, 0xbf, 0x03, 0x05, 0x01, 0x02, 0x42, 0x28, 0x6f, 0x72, -0x00, 0x7f, 0x04, 0xe6, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x29, -0x00, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x73, 0x5e, 0x00, -0x91, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2e, -0xa7, 0x00, 0x09, 0xec, 0x03, 0x10, 0x63, 0xc4, 0x01, 0x21, -0x6c, 0x73, 0x08, 0x04, 0x1e, 0x64, 0xfa, 0x03, 0x68, 0x6f, -0x6e, 0x00, 0x69, 0x74, 0x73, 0x9b, 0x01, 0x22, 0x00, 0x69, -0x90, 0x00, 0x10, 0x66, 0x5f, 0x02, 0x41, 0x63, 0x61, 0x72, -0x64, 0x24, 0x02, 0x50, 0x64, 0x69, 0x72, 0x65, 0x63, 0x08, -0x02, 0x42, 0x73, 0x2e, 0x00, 0x4f, 0x21, 0x00, 0x0b, 0xae, -0x01, 0x22, 0x73, 0x2c, 0x90, 0x00, 0x31, 0x61, 0x70, 0x70, -0xf2, 0x01, 0x1b, 0x66, 0x72, 0x04, 0x06, 0x42, 0x00, 0x00, -0x11, 0x03, 0xf2, 0x0a, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x61, -0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, -0x2e, 0x00, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0xfd, -0x00, 0x10, 0x6d, 0x63, 0x04, 0xb0, 0x69, 0x73, 0x00, 0x64, -0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x67, 0x01, 0x01, -0x2d, 0x01, 0x10, 0x69, 0xc1, 0x03, 0xe0, 0x65, 0x73, 0x6e, -0x27, 0x74, 0x00, 0x6d, 0x61, 0x6b, 0x65, 0x00, 0x73, 0x65, -0x6e, 0x5d, 0x01, 0x14, 0x54, 0xb1, 0x00, 0x01, 0x6e, 0x00, -0x80, 0x73, 0x75, 0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x88, -0x00, 0x0b, 0xfb, 0x04, 0x03, 0x6d, 0x01, 0x70, 0x6e, 0x75, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x14, 0x00, 0xc0, 0x70, 0x61, -0x64, 0x00, 0x28, 0x60, 0x37, 0x27, 0x2c, 0x00, 0x60, 0x39, -0x05, 0x00, 0x10, 0x31, 0x05, 0x00, 0x34, 0x33, 0x27, 0x29, -0xe6, 0x01, 0x01, 0x38, 0x01, 0xa7, 0x66, 0x6f, 0x72, 0x00, -0x64, 0x69, 0x61, 0x67, 0x6f, 0x6e, 0xa1, 0x00, 0x00, 0x6e, -0x01, 0x23, 0x28, 0x41, 0x4e, 0x01, 0x13, 0x61, 0xdc, 0x00, -0x81, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x48, -0x01, 0x12, 0x73, 0xf2, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, -0xbe, 0x05, 0x01, 0x89, 0x01, 0x60, 0x61, 0x76, 0x61, 0x69, -0x6c, 0x61, 0x90, 0x03, 0x11, 0x29, 0x6b, 0x02, 0x12, 0x32, -0x6b, 0x02, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, -0x65, 0x72, 0x6d, 0x02, 0x10, 0x65, 0xd7, 0x01, 0x05, 0x14, -0x00, 0x02, 0x3f, 0x00, 0x04, 0x3a, 0x00, 0x51, 0x00, 0x66, -0x72, 0x6f, 0x6d, 0x77, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, -0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, -0x6d, 0x00, 0x03, 0xe3, 0x00, 0xb1, 0x60, 0x54, 0x79, 0x70, -0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x17, 0x02, 0x71, -0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x02, 0x92, -0x00, 0x00, 0x00, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x44, -0x02, 0x02, 0x14, 0x00, 0x04, 0x1c, 0x02, 0x10, 0x28, 0x77, -0x03, 0x20, 0x68, 0x65, 0xe4, 0x03, 0x01, 0x1d, 0x00, 0x35, -0x68, 0x61, 0x70, 0x6f, 0x05, 0x00, 0xe9, 0x01, 0x2a, 0x29, -0x3a, 0x87, 0x03, 0x02, 0x22, 0x05, 0x06, 0x8a, 0x03, 0x10, -0x2c, 0xf9, 0x02, 0x0b, 0x88, 0x03, 0xf0, 0x0c, 0x57, 0x69, -0x64, 0x74, 0x68, 0x20, 0x2f, 0x20, 0x74, 0x6f, 0x70, 0x2c, -0x00, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2f, 0x20, -0x62, 0x6f, 0x74, 0x74, 0x6f, 0x70, 0x03, 0x1d, 0x4f, 0x1f, -0x04, 0x50, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x58, 0x05, 0x11, -0x6c, 0x06, 0x04, 0x14, 0x76, 0x1d, 0x02, 0x65, 0x64, 0x69, -0x6d, 0x65, 0x6e, 0x73, 0x88, 0x02, 0x0d, 0x34, 0x04, 0x14, -0x2c, 0xdf, 0x01, 0x10, 0x62, 0xae, 0x07, 0x13, 0x66, 0x1f, -0x00, 0x25, 0x6c, 0x65, 0xfa, 0x01, 0x31, 0x74, 0x6f, 0x70, -0x52, 0x00, 0x03, 0x7c, 0x00, 0x40, 0x72, 0x6f, 0x77, 0x73, -0x41, 0x07, 0xb0, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, -0x6c, 0x79, 0x2e, 0x00, +0xfa, 0x03, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0x34, 0x3a, 0x20, 0x43, 0x75, 0x62, 0x65, 0x20, 0x00, 0x2d, +0x01, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, +0x73, 0x00, 0x69, 0x73, 0x00, 0x61, 0x6e, 0x6f, 0x74, 0x68, +0x65, 0x72, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0x49, 0x00, 0x6f, +0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x00, +0x73, 0x61, 0x77, 0x00, 0x61, 0x73, 0x00, 0x61, 0x00, 0x77, +0x65, 0x62, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x34, 0x00, +0x00, 0x29, 0x00, 0x11, 0x77, 0x19, 0x00, 0x41, 0x4a, 0x61, +0x76, 0x61, 0x1a, 0x00, 0xf0, 0x28, 0x00, 0x5b, 0x32, 0x5d, +0x2c, 0x00, 0x62, 0x79, 0x00, 0x50, 0x61, 0x75, 0x6c, 0x00, +0x53, 0x63, 0x6f, 0x74, 0x74, 0x2e, 0x00, 0x59, 0x6f, 0x75, +0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, +0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x31, 0x36, 0x00, 0x73, +0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x69, +0x78, 0x13, 0x00, 0xf1, 0x03, 0x77, 0x68, 0x69, 0x63, 0x68, +0x00, 0x61, 0x72, 0x65, 0x00, 0x62, 0x6c, 0x75, 0x65, 0x3b, +0x00, 0x6f, 0x6e, 0x61, 0x00, 0x02, 0x27, 0x00, 0x50, 0x00, +0x72, 0x65, 0x73, 0x74, 0x6a, 0x00, 0x41, 0x63, 0x75, 0x62, +0x65, 0x52, 0x00, 0x60, 0x72, 0x00, 0x6d, 0x6f, 0x76, 0x65, +0xb8, 0x00, 0xf1, 0x05, 0x74, 0x6f, 0x00, 0x75, 0x73, 0x65, +0x00, 0x74, 0x68, 0x65, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, +0x00, 0x6b, 0x65, 0x79, 0x16, 0x00, 0x41, 0x72, 0x6f, 0x6c, +0x6c, 0x17, 0x00, 0x00, 0x35, 0x00, 0xf1, 0x0f, 0x00, 0x74, +0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x39, 0x30, 0x00, +0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x73, 0x00, 0x73, 0x6f, +0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x69, 0x74, 0x4d, 0x00, +0x01, 0x35, 0x00, 0xb3, 0x61, 0x6e, 0x00, 0x61, 0x64, 0x6a, +0x61, 0x63, 0x65, 0x6e, 0x74, 0x7c, 0x00, 0x8b, 0x2e, 0x00, +0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x50, 0x00, 0x21, 0x6f, +0x6e, 0x2f, 0x00, 0x01, 0xae, 0x00, 0x03, 0x2a, 0x00, 0x11, +0x2c, 0x1e, 0x00, 0x07, 0x11, 0x00, 0x00, 0x9f, 0x00, 0x94, +0x70, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x00, 0x75, 0x70, 0xd2, +0x00, 0x40, 0x66, 0x61, 0x63, 0x65, 0xf1, 0x00, 0x04, 0x4a, +0x00, 0x37, 0x3b, 0x00, 0x69, 0x60, 0x00, 0x03, 0x51, 0x00, +0x0c, 0x25, 0x00, 0x05, 0x6f, 0x00, 0x4f, 0x6e, 0x6f, 0x6e, +0x2d, 0x73, 0x00, 0x02, 0x41, 0x6e, 0x65, 0x73, 0x73, 0x70, +0x00, 0xfe, 0x15, 0x75, 0x74, 0x00, 0x64, 0x6f, 0x77, 0x6e, +0x00, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2e, 0x00, 0x28, 0x49, +0x6e, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x2c, +0x00, 0x77, 0x68, 0x65, 0x6e, 0x65, 0x76, 0x65, 0x72, 0xd0, +0x00, 0x02, 0x49, 0x00, 0x31, 0x74, 0x77, 0x6f, 0x7b, 0x00, +0x12, 0x73, 0x19, 0x01, 0xf2, 0x11, 0x63, 0x6f, 0x6d, 0x65, +0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6e, 0x74, +0x61, 0x63, 0x74, 0x00, 0x73, 0x77, 0x61, 0x70, 0x00, 0x63, +0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x73, 0x2e, 0x29, 0x89, 0x01, +0x33, 0x6a, 0x6f, 0x62, 0x88, 0x01, 0x71, 0x67, 0x65, 0x74, +0x00, 0x61, 0x6c, 0x6c, 0xd3, 0x01, 0x07, 0xa5, 0x00, 0x13, +0x73, 0xbe, 0x00, 0x00, 0x62, 0x00, 0x00, 0x1b, 0x00, 0x02, +0x62, 0x00, 0x08, 0xde, 0x00, 0x22, 0x61, 0x74, 0x1d, 0x00, +0x00, 0x43, 0x02, 0x20, 0x74, 0x69, 0x62, 0x02, 0x74, 0x43, +0x6f, 0x75, 0x6e, 0x74, 0x00, 0x79, 0xe9, 0x01, 0x00, 0x9f, +0x02, 0x50, 0x64, 0x00, 0x74, 0x72, 0x79, 0x48, 0x00, 0x20, +0x64, 0x6f, 0xb3, 0x01, 0x20, 0x69, 0x6e, 0x96, 0x02, 0x21, +0x66, 0x65, 0x9d, 0x02, 0xf2, 0x02, 0x70, 0x6f, 0x73, 0x73, +0x69, 0x62, 0x6c, 0x65, 0x2e, 0x00, 0x00, 0x00, 0x55, 0x6e, +0x6c, 0x69, 0x6b, 0x11, 0x02, 0x04, 0xc6, 0x02, 0x06, 0xa2, +0x02, 0xf2, 0x01, 0x2c, 0x00, 0x6d, 0x79, 0x00, 0x76, 0x65, +0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x68, 0x61, 0x73, 0xf1, +0x01, 0x50, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x28, 0x00, 0xd0, +0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x00, 0x6f, +0x6e, 0x63, 0x65, 0x7f, 0x00, 0xc1, 0x27, 0x76, 0x65, 0x00, +0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x53, 0x00, +0x01, 0xe7, 0x02, 0x43, 0x77, 0x69, 0x74, 0x68, 0x8e, 0x02, +0x01, 0x47, 0x01, 0x30, 0x69, 0x6e, 0x67, 0xe4, 0x00, 0x14, +0x61, 0xf8, 0x01, 0x00, 0xe8, 0x02, 0x11, 0x2c, 0x65, 0x01, +0xa2, 0x63, 0x61, 0x6e, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x67, +0x65, 0xc0, 0x01, 0xa2, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, +0x75, 0x6c, 0x61, 0x72, 0x0d, 0x03, 0x00, 0xd7, 0x00, 0x02, +0xf9, 0x01, 0x20, 0x6e, 0x79, 0x13, 0x01, 0xe0, 0x61, 0x00, +0x74, 0x65, 0x74, 0x72, 0x61, 0x68, 0x65, 0x64, 0x72, 0x6f, +0x6e, 0x2c, 0x9e, 0x00, 0x33, 0x6f, 0x63, 0x74, 0x0f, 0x00, +0x30, 0x00, 0x6f, 0x72, 0x11, 0x00, 0x43, 0x69, 0x63, 0x6f, +0x73, 0x12, 0x00, 0x00, 0xef, 0x00, 0xf0, 0x13, 0x5b, 0x32, +0x5d, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, +0x77, 0x77, 0x33, 0x2e, 0x73, 0x79, 0x6d, 0x70, 0x61, 0x74, +0x69, 0x63, 0x6f, 0x2e, 0x63, 0x61, 0x2f, 0x70, 0x61, 0x75, +0x6c, 0x73, 0x87, 0x03, 0x10, 0x2f, 0xac, 0x00, 0x11, 0x2f, +0x3f, 0x03, 0x92, 0x68, 0x74, 0x6d, 0x00, 0x00, 0x00, 0x34, +0x2e, 0x31, 0x13, 0x04, 0x00, 0xdb, 0x01, 0x54, 0x72, 0x6f, +0x6c, 0x73, 0x20, 0x0c, 0x04, 0x01, 0xe2, 0x00, 0x00, 0xb8, +0x00, 0x92, 0x62, 0x65, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x65, +0x64, 0xf0, 0x00, 0x21, 0x65, 0x69, 0x20, 0x04, 0x00, 0x05, +0x01, 0xa2, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, +0x00, 0x6f, 0x10, 0x00, 0x41, 0x6d, 0x6f, 0x75, 0x73, 0x7c, +0x01, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, +0x63, 0x6b, 0x13, 0x01, 0x72, 0x61, 0x6e, 0x79, 0x77, 0x68, +0x65, 0x72, 0xbe, 0x02, 0x10, 0x68, 0x37, 0x01, 0x92, 0x6e, +0x64, 0x6f, 0x77, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0xbf, 0x03, +0x05, 0x01, 0x02, 0x42, 0x28, 0x6f, 0x72, 0x00, 0x7f, 0x04, +0xe6, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x29, 0x00, 0x74, 0x6f, +0x77, 0x61, 0x72, 0x64, 0x73, 0x5e, 0x00, 0x91, 0x00, 0x70, +0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0xa7, 0x00, 0x09, +0xec, 0x03, 0x10, 0x63, 0xc4, 0x01, 0x21, 0x6c, 0x73, 0x08, +0x04, 0x1e, 0x64, 0xfa, 0x03, 0x68, 0x6f, 0x6e, 0x00, 0x69, +0x74, 0x73, 0x9b, 0x01, 0x22, 0x00, 0x69, 0x90, 0x00, 0x10, +0x66, 0x5f, 0x02, 0x41, 0x63, 0x61, 0x72, 0x64, 0x24, 0x02, +0x50, 0x64, 0x69, 0x72, 0x65, 0x63, 0x08, 0x02, 0x42, 0x73, +0x2e, 0x00, 0x4f, 0x21, 0x00, 0x0b, 0xae, 0x01, 0x22, 0x73, +0x2c, 0x90, 0x00, 0x31, 0x61, 0x70, 0x70, 0xf2, 0x01, 0x1b, +0x66, 0x72, 0x04, 0x06, 0x42, 0x00, 0x00, 0x11, 0x03, 0xf2, +0x0a, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x61, 0x70, 0x70, 0x72, +0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x00, 0x56, +0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0xfd, 0x00, 0x10, 0x6d, +0x63, 0x04, 0xb0, 0x69, 0x73, 0x00, 0x64, 0x69, 0x73, 0x61, +0x6c, 0x6c, 0x6f, 0x77, 0x67, 0x01, 0x01, 0x2d, 0x01, 0x10, +0x69, 0xc1, 0x03, 0xe0, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x00, +0x6d, 0x61, 0x6b, 0x65, 0x00, 0x73, 0x65, 0x6e, 0x5d, 0x01, +0x14, 0x54, 0xb1, 0x00, 0x01, 0x6e, 0x00, 0x80, 0x73, 0x75, +0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x88, 0x00, 0x0b, 0xfb, +0x04, 0x03, 0x6d, 0x01, 0x70, 0x6e, 0x75, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x14, 0x00, 0xc0, 0x70, 0x61, 0x64, 0x00, 0x28, +0x60, 0x37, 0x27, 0x2c, 0x00, 0x60, 0x39, 0x05, 0x00, 0x10, +0x31, 0x05, 0x00, 0x34, 0x33, 0x27, 0x29, 0xe6, 0x01, 0x01, +0x38, 0x01, 0xa7, 0x66, 0x6f, 0x72, 0x00, 0x64, 0x69, 0x61, +0x67, 0x6f, 0x6e, 0xa1, 0x00, 0x00, 0x6e, 0x01, 0x23, 0x28, +0x41, 0x4e, 0x01, 0x13, 0x61, 0xdc, 0x00, 0x81, 0x64, 0x65, +0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x48, 0x01, 0x12, 0x73, +0xf2, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, 0xbe, 0x05, 0x01, +0x89, 0x01, 0x60, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x90, +0x03, 0x11, 0x29, 0x6b, 0x02, 0x12, 0x32, 0x6b, 0x02, 0x93, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6d, +0x02, 0x10, 0x65, 0xd7, 0x01, 0x05, 0x14, 0x00, 0x02, 0x3f, +0x00, 0x04, 0x3a, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, +0x77, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6d, 0x00, 0x03, +0xe3, 0x00, 0xb1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x75, 0x17, 0x02, 0x71, 0x79, 0x70, 0x65, +0x20, 0x6f, 0x66, 0x20, 0x43, 0x02, 0x92, 0x00, 0x00, 0x00, +0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x44, 0x02, 0x02, 0x14, +0x00, 0x04, 0x1c, 0x02, 0x10, 0x28, 0x77, 0x03, 0x20, 0x68, +0x65, 0xe4, 0x03, 0x01, 0x1d, 0x00, 0x35, 0x68, 0x61, 0x70, +0x6f, 0x05, 0x00, 0xe9, 0x01, 0x2a, 0x29, 0x3a, 0x87, 0x03, +0x02, 0x22, 0x05, 0x06, 0x8a, 0x03, 0x10, 0x2c, 0xf9, 0x02, +0x0b, 0x88, 0x03, 0xf0, 0x0c, 0x57, 0x69, 0x64, 0x74, 0x68, +0x20, 0x2f, 0x20, 0x74, 0x6f, 0x70, 0x2c, 0x00, 0x48, 0x65, +0x69, 0x67, 0x68, 0x74, 0x20, 0x2f, 0x20, 0x62, 0x6f, 0x74, +0x74, 0x6f, 0x70, 0x03, 0x1d, 0x4f, 0x1f, 0x04, 0x50, 0x68, +0x6f, 0x72, 0x69, 0x7a, 0x58, 0x05, 0x11, 0x6c, 0x06, 0x04, +0x14, 0x76, 0x1d, 0x02, 0x65, 0x64, 0x69, 0x6d, 0x65, 0x6e, +0x73, 0x88, 0x02, 0x0d, 0x34, 0x04, 0x14, 0x2c, 0xdf, 0x01, +0x10, 0x62, 0xae, 0x07, 0x13, 0x66, 0x1f, 0x00, 0x25, 0x6c, +0x65, 0xfa, 0x01, 0x31, 0x74, 0x6f, 0x70, 0x52, 0x00, 0x03, +0x7c, 0x00, 0x40, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x07, 0xb0, +0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x2e, +0x00, }; -const unsigned short help_text_len = 2055; -const unsigned short help_text_words = 385; +const unsigned short help_text_len = 2071; +const unsigned short help_text_words = 386; const char quick_help_text[] = "Pick up all the blue squares by rolling the cube over them."; diff --git a/apps/plugins/puzzles/help/dominosa.c b/apps/plugins/puzzles/help/dominosa.c index 388abb16d4..34958feb22 100644 --- a/apps/plugins/puzzles/help/dominosa.c +++ b/apps/plugins/puzzles/help/dominosa.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,174 +6,174 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 88, TEXT_CENTER | C_RED }, - { 151, TEXT_UNDERLINE }, - { 267, TEXT_CENTER | C_RED }, - { 284, TEXT_UNDERLINE }, - { 336, TEXT_UNDERLINE }, - { 377, TEXT_UNDERLINE }, + { 89, TEXT_CENTER | C_RED }, + { 152, TEXT_UNDERLINE }, + { 268, TEXT_CENTER | C_RED }, + { 285, TEXT_UNDERLINE }, + { 337, TEXT_UNDERLINE }, + { 378, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2278 comp 1541 ratio 0.676471 level 10 saved 737 */ +/* orig 2299 comp 1550 ratio 0.674206 level 10 saved 749 */ const char help_text[] = { -0xf1, 0x1a, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x37, 0x3a, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x6f, -0x73, 0x61, 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x6e, 0x6f, -0x72, 0x6d, 0x61, 0x6c, 0x00, 0x73, 0x65, 0x74, 0x00, 0x6f, -0x66, 0x00, 0x64, 0x1c, 0x00, 0xf0, 0x0b, 0x65, 0x73, 0x00, -0x2d, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x69, 0x73, 0x2c, -0x00, 0x6f, 0x6e, 0x65, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x61, -0x6e, 0x63, 0x65, 0x24, 0x00, 0xf0, 0x07, 0x65, 0x76, 0x65, -0x72, 0x79, 0x00, 0x28, 0x75, 0x6e, 0x6f, 0x72, 0x64, 0x65, -0x72, 0x65, 0x64, 0x29, 0x00, 0x70, 0x61, 0x69, 0x72, 0x1a, -0x00, 0xf0, 0x3b, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, -0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x30, 0x00, 0x74, 0x6f, -0x00, 0x36, 0x00, 0x2d, 0x00, 0x68, 0x61, 0x73, 0x00, 0x62, -0x65, 0x65, 0x6e, 0x00, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x67, -0x65, 0x64, 0x00, 0x69, 0x72, 0x72, 0x65, 0x67, 0x75, 0x6c, -0x61, 0x72, 0x6c, 0x79, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, -0x61, 0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, -0x65, 0x3b, 0x00, 0x74, 0x68, 0x65, 0x6e, 0x05, 0x00, 0x03, -0x4f, 0x00, 0xf6, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x65, 0x61, -0x63, 0x68, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x4f, -0x00, 0xf1, 0x01, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, -0x00, 0x64, 0x6f, 0x77, 0x6e, 0x00, 0x61, 0x6e, 0x64, 0x34, -0x00, 0x05, 0xc1, 0x00, 0xf0, 0x11, 0x74, 0x68, 0x65, 0x6d, -0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x00, 0x72, 0x65, 0x6d, -0x6f, 0x76, 0x65, 0x64, 0x2e, 0x00, 0x59, 0x6f, 0x75, 0x72, -0x00, 0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, 0x73, 0x9e, 0x00, -0xb1, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, -0x63, 0x74, 0x3d, 0x00, 0xa3, 0x70, 0x61, 0x74, 0x74, 0x65, -0x72, 0x6e, 0x00, 0x62, 0x79, 0xac, 0x00, 0x31, 0x69, 0x6e, -0x67, 0x19, 0x00, 0x0c, 0x1e, 0x01, 0x82, 0x74, 0x6f, 0x00, -0x6d, 0x61, 0x74, 0x63, 0x68, 0x36, 0x00, 0x71, 0x72, 0x6f, -0x76, 0x69, 0x64, 0x65, 0x64, 0x34, 0x00, 0x17, 0x79, 0x08, -0x01, 0xf0, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, -0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x75, 0x00, -0xf0, 0x00, 0x77, 0x69, 0x64, 0x65, 0x6c, 0x79, 0x00, 0x63, -0x72, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64, 0x49, 0x00, 0xc2, -0x4f, 0x2e, 0x00, 0x53, 0x2e, 0x00, 0x41, 0x64, 0x6c, 0x65, -0x72, 0x2c, 0xc7, 0x00, 0x81, 0x61, 0x6b, 0x65, 0x73, 0x00, -0x70, 0x61, 0x72, 0x74, 0x00, 0x82, 0x69, 0x74, 0x73, 0x00, -0x6e, 0x61, 0x6d, 0x65, 0x55, 0x01, 0x40, 0x74, 0x68, 0x6f, -0x73, 0x8e, 0x01, 0x51, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x61, -0x00, 0x46, 0x31, 0x37, 0x2e, 0x31, 0xd3, 0x01, 0x80, 0x63, -0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0xdc, 0x01, 0xa0, -0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, -0xc7, 0x00, 0x41, 0x62, 0x65, 0x74, 0x77, 0x85, 0x01, 0xf5, -0x00, 0x6e, 0x79, 0x00, 0x74, 0x77, 0x6f, 0x00, 0x61, 0x64, -0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0xb5, 0x01, 0x83, 0x70, -0x6c, 0x61, 0x63, 0x65, 0x73, 0x00, 0x61, 0xe6, 0x00, 0x63, -0x00, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x01, 0x01, 0x53, 0x6d, -0x2c, 0x00, 0x6f, 0x72, 0x48, 0x01, 0x12, 0x73, 0x11, 0x02, -0x00, 0x9a, 0x00, 0x00, 0xd2, 0x00, 0xf1, 0x05, 0x61, 0x6c, -0x72, 0x65, 0x61, 0x64, 0x79, 0x00, 0x70, 0x72, 0x65, 0x73, -0x65, 0x6e, 0x74, 0x2e, 0x00, 0x54, 0x72, 0x79, 0x36, 0x00, -0x12, 0x6f, 0x52, 0x00, 0x06, 0x51, 0x00, 0x60, 0x77, 0x68, -0x69, 0x63, 0x68, 0x00, 0x56, 0x00, 0xa0, 0x6c, 0x61, 0x70, -0x73, 0x00, 0x65, 0x78, 0x69, 0x73, 0x74, 0x2a, 0x00, 0x05, -0x56, 0x01, 0x43, 0x77, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x01, -0x59, 0x01, 0x40, 0x6f, 0x6e, 0x65, 0x73, 0x66, 0x00, 0x04, -0x33, 0x00, 0x00, 0xef, 0x00, 0x4e, 0x52, 0x69, 0x67, 0x68, -0xd6, 0x00, 0x0f, 0xd2, 0x00, 0x03, 0x40, 0x64, 0x72, 0x61, -0x77, 0xd1, 0x00, 0x46, 0x6c, 0x69, 0x6e, 0x65, 0x2a, 0x00, -0x01, 0xce, 0x00, 0x02, 0x8c, 0x00, 0xb2, 0x79, 0x6f, 0x75, -0x00, 0x63, 0x61, 0x6e, 0x00, 0x75, 0x73, 0x65, 0x0f, 0x02, -0x40, 0x6d, 0x69, 0x6e, 0x64, 0x16, 0x00, 0x52, 0x72, 0x73, -0x65, 0x6c, 0x66, 0x02, 0x03, 0x00, 0x24, 0x00, 0x43, 0x6b, -0x6e, 0x6f, 0x77, 0x7b, 0x01, 0x00, 0x69, 0x00, 0x04, 0x60, -0x00, 0x00, 0x8e, 0x02, 0x32, 0x6e, 0x6f, 0x74, 0x2a, 0x01, -0x21, 0x65, 0x64, 0x37, 0x02, 0x30, 0x00, 0x73, 0x69, 0xc6, -0x02, 0x03, 0xd5, 0x00, 0x1c, 0x2e, 0xb0, 0x00, 0x55, 0x61, -0x67, 0x61, 0x69, 0x6e, 0x49, 0x01, 0x00, 0xe5, 0x00, 0x00, -0x9d, 0x00, 0x00, 0xd9, 0x00, 0x13, 0x59, 0x8c, 0x00, 0x42, -0x61, 0x6c, 0x73, 0x6f, 0x91, 0x00, 0xd2, 0x68, 0x65, 0x00, -0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, -0x74, 0x02, 0x00, 0x1a, 0x01, 0x14, 0x61, 0x16, 0x00, 0x43, -0x61, 0x72, 0x6f, 0x75, 0xf6, 0x02, 0x74, 0x67, 0x72, 0x69, -0x64, 0x2e, 0x00, 0x57, 0x39, 0x03, 0x03, 0x21, 0x00, 0xbf, -0x69, 0x73, 0x00, 0x68, 0x61, 0x6c, 0x66, 0x00, 0x77, 0x61, -0x79, 0x29, 0x01, 0x0a, 0x11, 0x2c, 0xbd, 0x01, 0x14, 0x73, -0xed, 0x02, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x75, -0x00, 0x02, 0x92, 0x01, 0x0b, 0xc7, 0x01, 0x07, 0x18, 0x02, -0x00, 0x11, 0x01, 0x05, 0x44, 0x00, 0x2a, 0x6f, 0x72, 0x47, -0x00, 0x20, 0x73, 0x70, 0x37, 0x00, 0x32, 0x62, 0x61, 0x72, -0x46, 0x00, 0x3e, 0x6c, 0x61, 0x79, 0x8b, 0x01, 0x02, 0x50, -0x01, 0x02, 0xd9, 0x03, 0x81, 0x73, 0x2e, 0x00, 0x52, 0x65, -0x70, 0x65, 0x61, 0x14, 0x02, 0xca, 0x65, 0x69, 0x74, 0x68, -0x65, 0x72, 0x00, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x30, 0x01, -0x03, 0x86, 0x00, 0x25, 0x6f, 0x72, 0x3a, 0x01, 0x14, 0x50, -0x76, 0x00, 0x14, 0x61, 0x32, 0x04, 0x05, 0xbb, 0x00, 0x50, -0x68, 0x69, 0x67, 0x68, 0x6c, 0x82, 0x01, 0xe0, 0x00, 0x61, -0x6c, 0x6c, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, -0x6e, 0x63, 0xc4, 0x02, 0x03, 0xdf, 0x01, 0x02, 0x32, 0x00, -0x16, 0x2e, 0x45, 0x00, 0x07, 0x16, 0x00, 0x03, 0xae, 0x01, -0x01, 0x4a, 0x00, 0x51, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x81, -0x00, 0x05, 0x54, 0x00, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x00, -0x55, 0x70, 0x99, 0x01, 0x00, 0xc6, 0x00, 0x68, 0x64, 0x69, -0x66, 0x66, 0x65, 0x72, 0x80, 0x02, 0x00, 0xcf, 0x01, 0x17, -0x62, 0x31, 0x00, 0x00, 0x23, 0x04, 0x11, 0x74, 0x81, 0x03, -0x30, 0x67, 0x69, 0x76, 0x00, 0x01, 0x21, 0x69, 0x6d, 0xc1, -0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x5b, 0x00, 0x02, 0xef, -0x00, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x65, 0x64, 0xfc, 0x04, 0x22, 0x73, 0x65, 0x05, 0x01, -0x31, 0x32, 0x2e, 0x31, 0x72, 0x02, 0x01, 0x21, 0x02, 0xb2, -0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, -0x29, 0x04, 0x04, 0x16, 0x32, 0x04, 0x04, 0xb1, 0x70, 0x61, -0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x81, -0x04, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x44, -0x00, 0x04, 0x3f, 0x00, 0x04, 0x56, 0x04, 0xf1, 0x01, 0x65, -0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x72, 0x00, 0x22, 0x6f, 0x6e, -0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, -0x65, 0x6e, 0x75, 0xae, 0x00, 0x82, 0x4d, 0x61, 0x78, 0x69, -0x6d, 0x75, 0x6d, 0x20, 0xe6, 0x00, 0x45, 0x20, 0x6f, 0x6e, -0x20, 0xc1, 0x03, 0x33, 0x00, 0x00, 0x43, 0x80, 0x04, 0x02, -0x02, 0x02, 0x32, 0x69, 0x7a, 0x65, 0x69, 0x01, 0x13, 0x65, -0x03, 0x05, 0x10, 0x2c, 0x24, 0x03, 0x03, 0xa4, 0x04, 0x15, -0x6c, 0x29, 0x02, 0x07, 0x27, 0x00, 0x0c, 0x69, 0x05, 0x42, -0x75, 0x73, 0x65, 0x64, 0x6e, 0x05, 0x86, 0x6b, 0x65, 0x00, -0x69, 0x74, 0x2e, 0x00, 0x44, 0x2d, 0x04, 0x25, 0x74, 0x68, -0x6a, 0x01, 0x20, 0x67, 0x6f, 0x4d, 0x00, 0x11, 0x75, 0x8c, -0x01, 0x12, 0x4e, 0xb1, 0x01, 0x00, 0x63, 0x01, 0x32, 0x00, -0x72, 0x69, 0xda, 0x03, 0xa0, 0x61, 0x6e, 0x00, 0x28, 0x4e, -0x2b, 0x32, 0x29, 0x00, 0x78, 0x08, 0x00, 0x28, 0x31, 0x29, -0x6f, 0x06, 0x30, 0x73, 0x6f, 0x2c, 0x67, 0x01, 0x00, 0x70, -0x05, 0x20, 0x69, 0x63, 0x95, 0x06, 0x12, 0x2c, 0x68, 0x02, -0xb1, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x76, 0x61, -0x6c, 0x75, 0x9f, 0x00, 0x11, 0x36, 0x53, 0x00, 0x10, 0x73, -0x4c, 0x00, 0x33, 0x38, 0x78, 0x37, 0x73, 0x03, 0xf1, 0x05, -0x00, 0x00, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x75, -0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, -0x3c, 0x01, 0x31, 0x00, 0x00, 0x4e, 0x59, 0x07, 0x44, 0x6c, -0x79, 0x2c, 0x00, 0x9a, 0x01, 0x02, 0x99, 0x00, 0x01, 0xcb, -0x00, 0x00, 0x34, 0x00, 0x02, 0x6b, 0x02, 0x06, 0x1d, 0x01, -0x01, 0xec, 0x04, 0x03, 0x47, 0x05, 0x00, 0xba, 0x03, 0x10, -0x76, 0x02, 0x05, 0x21, 0x6c, 0x79, 0x6f, 0x05, 0x04, 0x58, -0x00, 0x33, 0x2e, 0x00, 0x50, 0x2c, 0x00, 0x01, 0x00, 0x01, -0x94, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, -0x26, 0x02, 0x05, 0x75, 0x02, 0x41, 0x6d, 0x6f, 0x72, 0x65, -0x93, 0x02, 0x00, 0xd4, 0x00, 0x11, 0x74, 0x58, 0x06, 0x40, -0x73, 0x6f, 0x6d, 0x65, 0x73, 0x02, 0x12, 0x73, 0x1d, 0x00, -0x40, 0x73, 0x75, 0x62, 0x74, 0x92, 0x01, 0x20, 0x73, 0x6f, -0xcd, 0x05, 0x00, 0xe7, 0x04, 0x45, 0x6c, 0x69, 0x6b, 0x65, -0x14, 0x05, 0x01, 0x04, 0x04, 0x20, 0x6f, 0x66, 0x97, 0x01, -0xe0, 0x69, 0x73, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, -0x65, 0x2e, 0x00, 0x41, 0x6c, 0x30, 0x01, 0x41, 0x66, 0x69, -0x6e, 0x64, 0x72, 0x03, 0x03, 0xb9, 0x02, 0x76, 0x70, 0x6f, -0x73, 0x73, 0x69, 0x62, 0x6c, 0xa8, 0x00, 0x05, 0x88, 0x00, -0x00, 0xd2, 0x04, 0x30, 0x64, 0x64, 0x69, 0x14, 0x00, 0xf2, -0x01, 0x61, 0x6c, 0x00, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, -0x6e, 0x67, 0x65, 0x00, 0x66, 0x6f, 0x72, 0x1c, 0x00, 0x10, -0x76, 0x57, 0x08, 0x10, 0x64, 0x65, 0x04, 0x10, 0x79, 0x88, -0x03, 0x40, 0x54, 0x75, 0x72, 0x6e, 0x5a, 0x00, 0x05, 0x7a, -0x00, 0x03, 0x8c, 0x02, 0x05, 0x1b, 0x05, 0x50, 0x73, 0x70, -0x65, 0x65, 0x64, 0xeb, 0x01, 0x03, 0x55, 0x07, 0xc0, 0x67, -0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, -0x00, +0x73, 0x61, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf1, 0x05, +0x00, 0x00, 0x00, 0x41, 0x00, 0x6e, 0x6f, 0x72, 0x6d, 0x61, +0x6c, 0x00, 0x73, 0x65, 0x74, 0x00, 0x6f, 0x66, 0x00, 0x64, +0x31, 0x00, 0xf0, 0x0b, 0x65, 0x73, 0x00, 0x2d, 0x00, 0x74, +0x68, 0x61, 0x74, 0x00, 0x69, 0x73, 0x2c, 0x00, 0x6f, 0x6e, +0x65, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, +0x24, 0x00, 0xf0, 0x07, 0x65, 0x76, 0x65, 0x72, 0x79, 0x00, +0x28, 0x75, 0x6e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, +0x29, 0x00, 0x70, 0x61, 0x69, 0x72, 0x1a, 0x00, 0xf0, 0x3b, +0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x00, 0x66, 0x72, +0x6f, 0x6d, 0x00, 0x30, 0x00, 0x74, 0x6f, 0x00, 0x36, 0x00, +0x2d, 0x00, 0x68, 0x61, 0x73, 0x00, 0x62, 0x65, 0x65, 0x6e, +0x00, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x00, +0x69, 0x72, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x6c, +0x79, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, 0x61, 0x00, 0x72, +0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x3b, 0x00, +0x74, 0x68, 0x65, 0x6e, 0x05, 0x00, 0x03, 0x4f, 0x00, 0xf6, +0x00, 0x00, 0x69, 0x6e, 0x00, 0x65, 0x61, 0x63, 0x68, 0x00, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x4f, 0x00, 0xf1, 0x01, +0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x64, 0x6f, +0x77, 0x6e, 0x00, 0x61, 0x6e, 0x64, 0x34, 0x00, 0x05, 0xc1, +0x00, 0xf0, 0x11, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, +0x76, 0x65, 0x73, 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, +0x64, 0x2e, 0x00, 0x59, 0x6f, 0x75, 0x72, 0x00, 0x74, 0x61, +0x73, 0x6b, 0x00, 0x69, 0x73, 0x9e, 0x00, 0xb1, 0x72, 0x65, +0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3d, +0x00, 0xa3, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x00, +0x62, 0x79, 0xac, 0x00, 0x31, 0x69, 0x6e, 0x67, 0x19, 0x00, +0x0c, 0x1e, 0x01, 0x82, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74, +0x63, 0x68, 0x36, 0x00, 0x71, 0x72, 0x6f, 0x76, 0x69, 0x64, +0x65, 0x64, 0x34, 0x00, 0x17, 0x79, 0x08, 0x01, 0xf0, 0x00, +0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x75, 0x00, 0xf0, 0x00, 0x77, +0x69, 0x64, 0x65, 0x6c, 0x79, 0x00, 0x63, 0x72, 0x65, 0x64, +0x69, 0x74, 0x65, 0x64, 0x49, 0x00, 0xc2, 0x4f, 0x2e, 0x00, +0x53, 0x2e, 0x00, 0x41, 0x64, 0x6c, 0x65, 0x72, 0x2c, 0xc7, +0x00, 0x81, 0x61, 0x6b, 0x65, 0x73, 0x00, 0x70, 0x61, 0x72, +0x74, 0x00, 0x82, 0x69, 0x74, 0x73, 0x00, 0x6e, 0x61, 0x6d, +0x65, 0x55, 0x01, 0x40, 0x74, 0x68, 0x6f, 0x73, 0x8e, 0x01, +0x51, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x61, 0x00, 0x46, 0x31, +0x37, 0x2e, 0x31, 0xe8, 0x01, 0xf0, 0x07, 0x63, 0x6f, 0x6e, +0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c, +0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xc7, +0x00, 0x41, 0x62, 0x65, 0x74, 0x77, 0x85, 0x01, 0xf5, 0x00, +0x6e, 0x79, 0x00, 0x74, 0x77, 0x6f, 0x00, 0x61, 0x64, 0x6a, +0x61, 0x63, 0x65, 0x6e, 0x74, 0xb5, 0x01, 0x83, 0x70, 0x6c, +0x61, 0x63, 0x65, 0x73, 0x00, 0x61, 0xe6, 0x00, 0x63, 0x00, +0x63, 0x6f, 0x76, 0x65, 0x72, 0x01, 0x01, 0x53, 0x6d, 0x2c, +0x00, 0x6f, 0x72, 0x48, 0x01, 0x12, 0x73, 0x11, 0x02, 0x00, +0x9a, 0x00, 0x00, 0xd2, 0x00, 0xf1, 0x05, 0x61, 0x6c, 0x72, +0x65, 0x61, 0x64, 0x79, 0x00, 0x70, 0x72, 0x65, 0x73, 0x65, +0x6e, 0x74, 0x2e, 0x00, 0x54, 0x72, 0x79, 0x36, 0x00, 0x12, +0x6f, 0x52, 0x00, 0x06, 0x51, 0x00, 0x60, 0x77, 0x68, 0x69, +0x63, 0x68, 0x00, 0x56, 0x00, 0xa0, 0x6c, 0x61, 0x70, 0x73, +0x00, 0x65, 0x78, 0x69, 0x73, 0x74, 0x2a, 0x00, 0x05, 0x56, +0x01, 0x43, 0x77, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x01, 0x59, +0x01, 0x40, 0x6f, 0x6e, 0x65, 0x73, 0x66, 0x00, 0x04, 0x33, +0x00, 0x00, 0xef, 0x00, 0x4e, 0x52, 0x69, 0x67, 0x68, 0xd6, +0x00, 0x0f, 0xd2, 0x00, 0x03, 0x40, 0x64, 0x72, 0x61, 0x77, +0xd1, 0x00, 0x46, 0x6c, 0x69, 0x6e, 0x65, 0x2a, 0x00, 0x01, +0xce, 0x00, 0x02, 0x8c, 0x00, 0xb2, 0x79, 0x6f, 0x75, 0x00, +0x63, 0x61, 0x6e, 0x00, 0x75, 0x73, 0x65, 0x0f, 0x02, 0x40, +0x6d, 0x69, 0x6e, 0x64, 0x16, 0x00, 0x52, 0x72, 0x73, 0x65, +0x6c, 0x66, 0x02, 0x03, 0x00, 0x24, 0x00, 0x43, 0x6b, 0x6e, +0x6f, 0x77, 0x7b, 0x01, 0x00, 0x69, 0x00, 0x04, 0x60, 0x00, +0x00, 0x8e, 0x02, 0x32, 0x6e, 0x6f, 0x74, 0x2a, 0x01, 0x21, +0x65, 0x64, 0x37, 0x02, 0x30, 0x00, 0x73, 0x69, 0xc6, 0x02, +0x03, 0xd5, 0x00, 0x1c, 0x2e, 0xb0, 0x00, 0x55, 0x61, 0x67, +0x61, 0x69, 0x6e, 0x49, 0x01, 0x00, 0xe5, 0x00, 0x00, 0x9d, +0x00, 0x00, 0xd9, 0x00, 0x13, 0x59, 0x8c, 0x00, 0x42, 0x61, +0x6c, 0x73, 0x6f, 0x91, 0x00, 0xd2, 0x68, 0x65, 0x00, 0x63, +0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x74, +0x02, 0x00, 0x1a, 0x01, 0x14, 0x61, 0x16, 0x00, 0x43, 0x61, +0x72, 0x6f, 0x75, 0xf6, 0x02, 0x74, 0x67, 0x72, 0x69, 0x64, +0x2e, 0x00, 0x57, 0x39, 0x03, 0x03, 0x21, 0x00, 0xbf, 0x69, +0x73, 0x00, 0x68, 0x61, 0x6c, 0x66, 0x00, 0x77, 0x61, 0x79, +0x29, 0x01, 0x0a, 0x11, 0x2c, 0xbd, 0x01, 0x14, 0x73, 0xed, +0x02, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x75, 0x00, +0x02, 0x92, 0x01, 0x0b, 0xc7, 0x01, 0x07, 0x18, 0x02, 0x00, +0x11, 0x01, 0x05, 0x44, 0x00, 0x2a, 0x6f, 0x72, 0x47, 0x00, +0x20, 0x73, 0x70, 0x37, 0x00, 0x32, 0x62, 0x61, 0x72, 0x46, +0x00, 0x3e, 0x6c, 0x61, 0x79, 0x8b, 0x01, 0x02, 0x50, 0x01, +0x02, 0xd9, 0x03, 0x81, 0x73, 0x2e, 0x00, 0x52, 0x65, 0x70, +0x65, 0x61, 0x14, 0x02, 0xca, 0x65, 0x69, 0x74, 0x68, 0x65, +0x72, 0x00, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x30, 0x01, 0x03, +0x86, 0x00, 0x25, 0x6f, 0x72, 0x3a, 0x01, 0x14, 0x50, 0x76, +0x00, 0x14, 0x61, 0x32, 0x04, 0x05, 0xbb, 0x00, 0x50, 0x68, +0x69, 0x67, 0x68, 0x6c, 0x82, 0x01, 0xe0, 0x00, 0x61, 0x6c, +0x6c, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, +0x63, 0xc4, 0x02, 0x03, 0xdf, 0x01, 0x02, 0x32, 0x00, 0x16, +0x2e, 0x45, 0x00, 0x07, 0x16, 0x00, 0x03, 0xae, 0x01, 0x01, +0x4a, 0x00, 0x51, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x81, 0x00, +0x05, 0x54, 0x00, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x00, 0x55, +0x70, 0x99, 0x01, 0x00, 0xc6, 0x00, 0x68, 0x64, 0x69, 0x66, +0x66, 0x65, 0x72, 0x80, 0x02, 0x00, 0xcf, 0x01, 0x17, 0x62, +0x31, 0x00, 0x00, 0x23, 0x04, 0x11, 0x74, 0x81, 0x03, 0x30, +0x67, 0x69, 0x76, 0x00, 0x01, 0x21, 0x69, 0x6d, 0xc1, 0x00, +0x41, 0x28, 0x41, 0x6c, 0x6c, 0x5b, 0x00, 0x02, 0xef, 0x00, +0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, +0x65, 0x64, 0xfc, 0x04, 0x22, 0x73, 0x65, 0x05, 0x01, 0x31, +0x32, 0x2e, 0x31, 0x72, 0x02, 0x01, 0x21, 0x02, 0xb2, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, +0x04, 0x04, 0x16, 0x32, 0x04, 0x04, 0xb1, 0x70, 0x61, 0x72, +0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x81, 0x04, +0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x44, 0x00, +0x04, 0x3f, 0x00, 0x04, 0x56, 0x04, 0xf1, 0x01, 0x65, 0x00, +0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, +0x27, 0x00, 0x6f, 0x70, 0x72, 0x00, 0x22, 0x6f, 0x6e, 0x1a, +0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, +0x6e, 0x75, 0xae, 0x00, 0x82, 0x4d, 0x61, 0x78, 0x69, 0x6d, +0x75, 0x6d, 0x20, 0xe6, 0x00, 0x45, 0x20, 0x6f, 0x6e, 0x20, +0xc1, 0x03, 0x33, 0x00, 0x00, 0x43, 0x80, 0x04, 0x02, 0x02, +0x02, 0x32, 0x69, 0x7a, 0x65, 0x69, 0x01, 0x13, 0x65, 0x03, +0x05, 0x10, 0x2c, 0x24, 0x03, 0x03, 0xa4, 0x04, 0x15, 0x6c, +0x29, 0x02, 0x07, 0x27, 0x00, 0x0c, 0x69, 0x05, 0x42, 0x75, +0x73, 0x65, 0x64, 0x6e, 0x05, 0x86, 0x6b, 0x65, 0x00, 0x69, +0x74, 0x2e, 0x00, 0x44, 0x2d, 0x04, 0x25, 0x74, 0x68, 0x6a, +0x01, 0x20, 0x67, 0x6f, 0x4d, 0x00, 0x11, 0x75, 0x8c, 0x01, +0x12, 0x4e, 0xb1, 0x01, 0x00, 0x63, 0x01, 0x32, 0x00, 0x72, +0x69, 0xda, 0x03, 0xa0, 0x61, 0x6e, 0x00, 0x28, 0x4e, 0x2b, +0x32, 0x29, 0x00, 0x78, 0x08, 0x00, 0x28, 0x31, 0x29, 0x6f, +0x06, 0x30, 0x73, 0x6f, 0x2c, 0x67, 0x01, 0x00, 0x70, 0x05, +0x20, 0x69, 0x63, 0x95, 0x06, 0x12, 0x2c, 0x68, 0x02, 0xb1, +0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x76, 0x61, 0x6c, +0x75, 0x9f, 0x00, 0x11, 0x36, 0x53, 0x00, 0x10, 0x73, 0x4c, +0x00, 0x33, 0x38, 0x78, 0x37, 0x73, 0x03, 0xf1, 0x05, 0x00, +0x00, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x75, 0x6e, +0x69, 0x71, 0x75, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x3c, +0x01, 0x31, 0x00, 0x00, 0x4e, 0x59, 0x07, 0x44, 0x6c, 0x79, +0x2c, 0x00, 0x9a, 0x01, 0x02, 0x99, 0x00, 0x01, 0xcb, 0x00, +0x00, 0x34, 0x00, 0x02, 0x6b, 0x02, 0x06, 0x1d, 0x01, 0x01, +0xec, 0x04, 0x03, 0x47, 0x05, 0x00, 0xba, 0x03, 0x10, 0x76, +0x02, 0x05, 0x21, 0x6c, 0x79, 0x6f, 0x05, 0x04, 0x58, 0x00, +0x33, 0x2e, 0x00, 0x50, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x94, +0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x26, +0x02, 0x05, 0x75, 0x02, 0x41, 0x6d, 0x6f, 0x72, 0x65, 0x93, +0x02, 0x00, 0xd4, 0x00, 0x11, 0x74, 0x58, 0x06, 0x40, 0x73, +0x6f, 0x6d, 0x65, 0x73, 0x02, 0x12, 0x73, 0x1d, 0x00, 0x40, +0x73, 0x75, 0x62, 0x74, 0x92, 0x01, 0x20, 0x73, 0x6f, 0xcd, +0x05, 0x00, 0xe7, 0x04, 0x45, 0x6c, 0x69, 0x6b, 0x65, 0x14, +0x05, 0x01, 0x04, 0x04, 0x20, 0x6f, 0x66, 0x97, 0x01, 0xe0, +0x69, 0x73, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, +0x2e, 0x00, 0x41, 0x6c, 0x30, 0x01, 0x41, 0x66, 0x69, 0x6e, +0x64, 0x72, 0x03, 0x03, 0xb9, 0x02, 0x76, 0x70, 0x6f, 0x73, +0x73, 0x69, 0x62, 0x6c, 0xa8, 0x00, 0x05, 0x88, 0x00, 0x00, +0xd2, 0x04, 0x30, 0x64, 0x64, 0x69, 0x14, 0x00, 0xf2, 0x01, +0x61, 0x6c, 0x00, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, +0x67, 0x65, 0x00, 0x66, 0x6f, 0x72, 0x1c, 0x00, 0x10, 0x76, +0x57, 0x08, 0x10, 0x64, 0x65, 0x04, 0x10, 0x79, 0x88, 0x03, +0x40, 0x54, 0x75, 0x72, 0x6e, 0x5a, 0x00, 0x05, 0x7a, 0x00, +0x03, 0x8c, 0x02, 0x05, 0x1b, 0x05, 0x50, 0x73, 0x70, 0x65, +0x65, 0x64, 0xeb, 0x01, 0x03, 0x55, 0x07, 0xc0, 0x67, 0x65, +0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x00, }; -const unsigned short help_text_len = 2278; -const unsigned short help_text_words = 400; +const unsigned short help_text_len = 2299; +const unsigned short help_text_words = 401; const char quick_help_text[] = "Tile the rectangle with a full set of dominoes."; diff --git a/apps/plugins/puzzles/help/fifteen.c b/apps/plugins/puzzles/help/fifteen.c index 467118b7d5..7c0b4c8063 100644 --- a/apps/plugins/puzzles/help/fifteen.c +++ b/apps/plugins/puzzles/help/fifteen.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,112 +6,150 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 83, TEXT_UNDERLINE }, - { 86, TEXT_CENTER | C_RED }, - { 153, TEXT_UNDERLINE }, - { 195, TEXT_CENTER | C_RED }, - { 211, TEXT_UNDERLINE }, - { 213, TEXT_UNDERLINE }, + { 89, TEXT_UNDERLINE }, + { 92, TEXT_CENTER | C_RED }, + { 161, TEXT_UNDERLINE }, + { 203, TEXT_CENTER | C_RED }, + { 219, TEXT_UNDERLINE }, + { 221, TEXT_UNDERLINE }, + { 239, TEXT_CENTER | C_RED }, + { 343, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1245 comp 925 ratio 0.742972 level 5 saved 320 */ +/* orig 1927 comp 1285 ratio 0.66684 level 10 saved 642 */ const char help_text[] = { -0xf1, 0x29, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x35, 0x3a, 0x20, 0x46, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, -0x20, 0x00, 0x00, 0x00, 0x54, 0x68, 0x65, 0x00, 0x6f, 0x6c, -0x64, 0x00, 0x6f, 0x6e, 0x65, 0x73, 0x00, 0x61, 0x72, 0x65, -0x00, 0x74, 0x68, 0x65, 0x00, 0x62, 0x65, 0x73, 0x74, 0x3a, -0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x69, 0x73, 0x12, 0x00, -0x41, 0x67, 0x6f, 0x6f, 0x64, 0x28, 0x00, 0xf0, 0x23, 0x60, -0x31, 0x35, 0x2d, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x27, -0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x73, 0x6c, 0x69, 0x64, -0x69, 0x6e, 0x67, 0x00, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x2e, -0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, -0x61, 0x00, 0x34, 0x78, 0x34, 0x00, 0x73, 0x71, 0x75, 0x55, -0x00, 0x83, 0x67, 0x72, 0x69, 0x64, 0x3b, 0x00, 0x31, 0x35, -0x10, 0x00, 0xf2, 0x03, 0x73, 0x00, 0x63, 0x6f, 0x6e, 0x74, -0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, -0x65, 0x64, 0x3f, 0x00, 0x51, 0x2c, 0x00, 0x61, 0x6e, 0x64, -0x70, 0x00, 0x30, 0x73, 0x69, 0x78, 0xa2, 0x00, 0x20, 0x74, -0x68, 0x81, 0x00, 0x51, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5b, -0x00, 0x61, 0x72, 0x00, 0x6d, 0x6f, 0x76, 0x65, 0x95, 0x00, -0x70, 0x6f, 0x00, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x69, 0x00, -0x00, 0x3c, 0x00, 0x50, 0x00, 0x6e, 0x65, 0x78, 0x74, 0x16, -0x00, 0x00, 0x3e, 0x00, 0x01, 0x31, 0x00, 0x62, 0x00, 0x73, -0x70, 0x61, 0x63, 0x65, 0x53, 0x00, 0x00, 0xa5, 0x00, 0x73, -0x65, 0x00, 0x69, 0x74, 0x00, 0x69, 0x6e, 0x23, 0x00, 0x01, -0x1d, 0x00, 0x11, 0x2e, 0xff, 0x00, 0x33, 0x61, 0x69, 0x6d, -0x52, 0x00, 0x62, 0x65, 0x6e, 0x64, 0x00, 0x75, 0x70, 0xd8, -0x00, 0x00, 0x25, 0x00, 0x01, 0x95, 0x00, 0x12, 0x00, 0xa7, -0x00, 0xd6, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x6f, -0x72, 0x64, 0x65, 0x72, 0x2c, 0x23, 0x00, 0x01, 0x48, 0x00, -0x00, 0x23, 0x00, 0x01, 0x38, 0x01, 0xe0, 0x6f, 0x74, 0x74, -0x6f, 0x6d, 0x00, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0x28, -0x73, 0x6a, 0x00, 0x22, 0x61, 0x74, 0x4a, 0x00, 0xf5, 0x05, -0x6f, 0x70, 0x00, 0x72, 0x6f, 0x77, 0x00, 0x72, 0x65, 0x61, -0x64, 0x73, 0x00, 0x31, 0x2c, 0x32, 0x2c, 0x33, 0x2c, 0x34, -0xee, 0x00, 0x04, 0x38, 0x00, 0x06, 0x21, 0x00, 0x81, 0x33, -0x2c, 0x31, 0x34, 0x2c, 0x31, 0x35, 0x2c, 0x5f, 0x00, 0x85, -0x29, 0x2e, 0x00, 0x00, 0x00, 0x35, 0x2e, 0x31, 0xb8, 0x01, -0x00, 0x3e, 0x01, 0x42, 0x72, 0x6f, 0x6c, 0x73, 0xc1, 0x01, -0xf3, 0x00, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, -0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x1d, 0x00, 0x36, -0x6c, 0x65, 0x64, 0xa6, 0x00, 0x81, 0x6d, 0x6f, 0x75, 0x73, -0x65, 0x00, 0x6f, 0x72, 0x0d, 0x00, 0x80, 0x6b, 0x65, 0x79, -0x62, 0x6f, 0x61, 0x72, 0x64, 0x56, 0x00, 0xcc, 0x41, 0x00, -0x6c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, -0x2f, 0x00, 0x03, 0xd5, 0x00, 0x00, 0x96, 0x00, 0x94, 0x6f, -0x72, 0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0xb9, 0x01, -0x01, 0xf2, 0x01, 0x0a, 0x6a, 0x01, 0x52, 0x00, 0x77, 0x69, -0x6c, 0x6c, 0xa0, 0x01, 0x73, 0x61, 0x73, 0x00, 0x6d, 0x61, -0x6e, 0x79, 0x40, 0x01, 0xc0, 0x61, 0x73, 0x00, 0x6e, 0x65, -0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x66, 0x01, 0x01, -0x23, 0x00, 0x06, 0x3c, 0x01, 0x27, 0x74, 0x6f, 0x74, 0x00, -0x83, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x9a, -0x02, 0x20, 0x61, 0x72, 0x7e, 0x00, 0x48, 0x6b, 0x65, 0x79, -0x73, 0x5e, 0x00, 0x02, 0xf1, 0x01, 0x75, 0x61, 0x64, 0x6a, -0x61, 0x63, 0x65, 0x6e, 0xf5, 0x01, 0x09, 0x8a, 0x01, 0xf4, -0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, -0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, -0x00, 0x28, 0x6d, 0x6f, 0x76, 0xb8, 0x00, 0x09, 0x2d, 0x00, -0x77, 0x6f, 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x36, 0x00, -0x01, 0x72, 0x01, 0x50, 0x50, 0x72, 0x65, 0x73, 0x73, 0x31, -0x00, 0x33, 0x60, 0x68, 0x27, 0x7f, 0x00, 0x20, 0x61, 0x6b, -0x7f, 0x00, 0x60, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x53, -0x00, 0x00, 0x90, 0x00, 0x1a, 0x2e, 0x29, 0x00, 0xb3, 0x65, -0x6e, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x74, 0x69, 0x6d, 0x65, -0xb5, 0x00, 0x33, 0x73, 0x6f, 0x6c, 0xf1, 0x00, 0x00, 0xa7, -0x01, 0x50, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x8b, 0x02, 0xe0, -0x6d, 0x61, 0x79, 0x00, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, -0x6c, 0x65, 0x00, 0x79, 0xdc, 0x02, 0x40, 0x70, 0x72, 0x6f, -0x67, 0x4b, 0x00, 0x30, 0x00, 0x77, 0x68, 0xe1, 0x00, 0x20, -0x64, 0x6f, 0x54, 0x00, 0x20, 0x73, 0x6f, 0x8c, 0x00, 0x41, -0x28, 0x41, 0x6c, 0x6c, 0x43, 0x00, 0x11, 0x61, 0xa0, 0x00, -0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, -0x65, 0x64, 0xc5, 0x00, 0x13, 0x73, 0xec, 0x00, 0x31, 0x32, -0x2e, 0x31, 0xc4, 0x03, 0xf1, 0x01, 0x61, 0x6c, 0x73, 0x6f, -0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, -0x2e, 0x29, 0x3f, 0x02, 0x15, 0x32, 0x3f, 0x02, 0xa5, 0x70, -0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x02, -0x04, 0x62, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x70, 0x5b, 0x00, -0x05, 0x39, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x76, -0x00, 0xb3, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, -0x2e, 0x2e, 0x27, 0x27, 0x00, 0x22, 0x00, 0x6f, 0x3c, 0x01, -0xb1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf1, 0x16, 0x00, 0x00, 0x00, +0x54, 0x68, 0x65, 0x00, 0x6f, 0x6c, 0x64, 0x00, 0x6f, 0x6e, +0x65, 0x73, 0x00, 0x61, 0x72, 0x65, 0x00, 0x74, 0x68, 0x65, +0x00, 0x62, 0x65, 0x73, 0x74, 0x3a, 0x00, 0x74, 0x68, 0x69, +0x73, 0x00, 0x69, 0x73, 0x12, 0x00, 0x41, 0x67, 0x6f, 0x6f, +0x64, 0x28, 0x00, 0xf1, 0x21, 0x60, 0x31, 0x35, 0x2d, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x27, 0x00, 0x77, 0x69, 0x74, +0x68, 0x00, 0x73, 0x6c, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x00, +0x74, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, +0x63, 0x68, 0x00, 0x64, 0x61, 0x74, 0x65, 0x73, 0x00, 0x66, +0x72, 0x6f, 0x6d, 0x3e, 0x00, 0xf0, 0x0a, 0x31, 0x38, 0x37, +0x30, 0x73, 0x2e, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, +0x76, 0x65, 0x00, 0x61, 0x00, 0x34, 0x78, 0x34, 0x00, 0x73, +0x71, 0x75, 0x71, 0x00, 0x83, 0x67, 0x72, 0x69, 0x64, 0x3b, +0x00, 0x31, 0x35, 0x10, 0x00, 0xf4, 0x03, 0x73, 0x00, 0x63, +0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x65, 0x64, 0x5b, 0x00, 0x31, 0x61, 0x6e, +0x64, 0x4e, 0x00, 0x30, 0x73, 0x69, 0x78, 0xd1, 0x00, 0x20, +0x74, 0x68, 0x9d, 0x00, 0x51, 0x65, 0x6d, 0x70, 0x74, 0x79, +0x5b, 0x00, 0x61, 0x72, 0x00, 0x6d, 0x6f, 0x76, 0x65, 0xb1, +0x00, 0x70, 0x6f, 0x00, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x69, +0x00, 0x00, 0x3c, 0x00, 0x50, 0x00, 0x6e, 0x65, 0x78, 0x74, +0x16, 0x00, 0x00, 0x3e, 0x00, 0x01, 0x31, 0x00, 0x62, 0x00, +0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x00, 0x00, 0xc1, 0x00, +0x73, 0x65, 0x00, 0x69, 0x74, 0x00, 0x69, 0x6e, 0x23, 0x00, +0x01, 0x1d, 0x00, 0x11, 0x2e, 0x1b, 0x01, 0x33, 0x61, 0x69, +0x6d, 0x52, 0x00, 0x62, 0x65, 0x6e, 0x64, 0x00, 0x75, 0x70, +0xf4, 0x00, 0x00, 0x25, 0x00, 0x01, 0x95, 0x00, 0x12, 0x00, +0xa7, 0x00, 0xd6, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, +0x6f, 0x72, 0x64, 0x65, 0x72, 0x2c, 0x23, 0x00, 0x01, 0x48, +0x00, 0x00, 0x23, 0x00, 0x01, 0x54, 0x01, 0xe0, 0x6f, 0x74, +0x74, 0x6f, 0x6d, 0x00, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, +0x28, 0x73, 0x6a, 0x00, 0x22, 0x61, 0x74, 0x4a, 0x00, 0xf5, +0x05, 0x6f, 0x70, 0x00, 0x72, 0x6f, 0x77, 0x00, 0x72, 0x65, +0x61, 0x64, 0x73, 0x00, 0x31, 0x2c, 0x32, 0x2c, 0x33, 0x2c, +0x34, 0xee, 0x00, 0x04, 0x38, 0x00, 0x06, 0x21, 0x00, 0x81, +0x33, 0x2c, 0x31, 0x34, 0x2c, 0x31, 0x35, 0x2c, 0x5f, 0x00, +0x85, 0x29, 0x2e, 0x00, 0x00, 0x00, 0x35, 0x2e, 0x31, 0xe7, +0x01, 0x00, 0x3e, 0x01, 0x51, 0x72, 0x6f, 0x6c, 0x73, 0x20, +0xdd, 0x01, 0xf3, 0x00, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, +0x65, 0x00, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x1d, +0x00, 0x36, 0x6c, 0x65, 0x64, 0xa6, 0x00, 0x81, 0x6d, 0x6f, +0x75, 0x73, 0x65, 0x00, 0x6f, 0x72, 0x0d, 0x00, 0x80, 0x6b, +0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x56, 0x00, 0xcc, +0x41, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, +0x63, 0x6b, 0x2f, 0x00, 0x03, 0xd5, 0x00, 0x00, 0x96, 0x00, +0x94, 0x6f, 0x72, 0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, +0xb9, 0x01, 0x01, 0x0e, 0x02, 0x0a, 0x6a, 0x01, 0x52, 0x00, +0x77, 0x69, 0x6c, 0x6c, 0xa0, 0x01, 0x73, 0x61, 0x73, 0x00, +0x6d, 0x61, 0x6e, 0x79, 0x40, 0x01, 0xc0, 0x61, 0x73, 0x00, +0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x66, +0x01, 0x01, 0x23, 0x00, 0x06, 0x3c, 0x01, 0x27, 0x74, 0x6f, +0x74, 0x00, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, +0x9b, 0x00, 0xb1, 0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, +0x75, 0x6c, 0x74, 0x2c, 0x21, 0x00, 0x20, 0x61, 0x72, 0x8a, +0x00, 0x48, 0x6b, 0x65, 0x79, 0x73, 0x6a, 0x00, 0x02, 0xfd, +0x01, 0x75, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x01, +0x02, 0x09, 0x96, 0x01, 0xf4, 0x09, 0x64, 0x69, 0x72, 0x65, +0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x69, 0x6e, 0x64, 0x69, +0x63, 0x61, 0x74, 0x65, 0x64, 0x00, 0x28, 0x6d, 0x6f, 0x76, +0xc4, 0x00, 0x09, 0x2d, 0x00, 0x77, 0x6f, 0x70, 0x70, 0x6f, +0x73, 0x69, 0x74, 0x36, 0x00, 0x01, 0x7e, 0x01, 0x50, 0x50, +0x72, 0x65, 0x73, 0x73, 0x31, 0x00, 0x33, 0x60, 0x68, 0x27, +0x7f, 0x00, 0x20, 0x61, 0x6b, 0x7f, 0x00, 0x60, 0x73, 0x75, +0x67, 0x67, 0x65, 0x73, 0x53, 0x00, 0x00, 0x90, 0x00, 0x1a, +0x2e, 0x29, 0x00, 0xb3, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, +0x00, 0x74, 0x69, 0x6d, 0x65, 0xb5, 0x00, 0x33, 0x73, 0x6f, +0x6c, 0xfd, 0x00, 0x00, 0xb3, 0x01, 0x50, 0x2c, 0x00, 0x62, +0x75, 0x74, 0x97, 0x02, 0xe0, 0x6d, 0x61, 0x79, 0x00, 0x73, +0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, 0x65, 0x00, 0x79, 0xe8, +0x02, 0x40, 0x70, 0x72, 0x6f, 0x67, 0x4b, 0x00, 0x00, 0x6d, +0x03, 0x50, 0x6c, 0x65, 0x00, 0x64, 0x6f, 0x54, 0x00, 0x20, +0x73, 0x6f, 0x8c, 0x00, 0x42, 0x28, 0x41, 0x6c, 0x6c, 0x12, +0x01, 0x01, 0xa0, 0x00, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, +0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0xc5, 0x00, 0x13, 0x73, +0xec, 0x00, 0x31, 0x32, 0x2e, 0x31, 0xec, 0x03, 0xf1, 0x01, +0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x4b, 0x02, 0x15, 0x32, +0x4b, 0x02, 0xb4, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x73, 0x20, 0x2a, 0x04, 0x62, 0x6e, 0x6c, 0x79, +0x00, 0x6f, 0x70, 0x5b, 0x00, 0x05, 0x39, 0x00, 0x06, 0xe9, +0x03, 0xb3, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, +0x2e, 0x2e, 0x27, 0x27, 0x00, 0x32, 0x00, 0x6f, 0x6e, 0x1a, +0x00, 0xa1, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x7b, 0x00, 0x51, 0x57, 0x69, 0x64, 0x74, 0x68, -0xd9, 0x02, 0x20, 0x48, 0x65, 0x07, 0x03, 0x10, 0x2c, 0xcd, -0x00, 0x21, 0x63, 0x68, 0x1c, 0x00, 0xf1, 0x07, 0x73, 0x65, -0x6c, 0x66, 0x2d, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, -0x74, 0x6f, 0x72, 0x79, 0x2e, 0x00, 0x28, 0x4f, 0x6e, 0x63, -0xfd, 0x00, 0xa1, 0x27, 0x76, 0x65, 0x00, 0x63, 0x68, 0x61, -0x6e, 0x67, 0x65, 0x12, 0x03, 0xe9, 0x73, 0x65, 0x2c, 0x00, -0x69, 0x74, 0x27, 0x73, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x61, -0x75, 0x04, 0x00, 0x58, 0x02, 0xf0, 0x03, 0x6d, 0x6f, 0x72, -0x65, 0x2c, 0x00, 0x6f, 0x66, 0x00, 0x63, 0x6f, 0x75, 0x72, -0x73, 0x65, 0x21, 0x29, 0x00, +0xe5, 0x02, 0x20, 0x48, 0x65, 0x13, 0x03, 0x04, 0x3a, 0x04, +0x00, 0x1c, 0x00, 0xf1, 0x07, 0x73, 0x65, 0x6c, 0x66, 0x2d, +0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, 0x74, 0x6f, 0x72, +0x79, 0x2e, 0x00, 0x28, 0x4f, 0x6e, 0x63, 0xfd, 0x00, 0xa1, +0x27, 0x76, 0x65, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, +0x1e, 0x03, 0xe9, 0x73, 0x65, 0x2c, 0x00, 0x69, 0x74, 0x27, +0x73, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x61, 0x9d, 0x04, 0x00, +0x64, 0x02, 0xf2, 0x01, 0x6d, 0x6f, 0x72, 0x65, 0x2c, 0x00, +0x6f, 0x66, 0x00, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x21, +0xe1, 0x00, 0x15, 0x33, 0xe1, 0x00, 0xf1, 0x00, 0x75, 0x73, +0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, +0x6e, 0x63, 0x65, 0xe7, 0x00, 0xc2, 0x4f, 0x6e, 0x00, 0x70, +0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0xa4, 0x03, +0x80, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, +0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0xd9, 0x00, 0x16, +0x50, 0x12, 0x00, 0x0d, 0xf5, 0x00, 0x34, 0x47, 0x61, 0x6d, +0xf5, 0x00, 0x01, 0xe3, 0x01, 0x30, 0x6c, 0x65, 0x74, 0xc6, +0x00, 0x00, 0x2a, 0x03, 0x53, 0x66, 0x69, 0x67, 0x75, 0x72, +0xec, 0x02, 0x20, 0x65, 0x6e, 0x82, 0x03, 0x1b, 0x66, 0xcb, +0x02, 0x34, 0x2e, 0x00, 0x57, 0x75, 0x03, 0x03, 0xed, 0x02, +0xc4, 0x00, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2c, +0x00, 0x60, 0x4d, 0x29, 0x03, 0x00, 0xe4, 0x02, 0x1b, 0x27, +0x06, 0x03, 0x01, 0x64, 0x00, 0x11, 0x70, 0x23, 0x02, 0x04, +0xd7, 0x02, 0x1b, 0x73, 0xef, 0x02, 0x01, 0xda, 0x00, 0x00, +0x27, 0x00, 0x44, 0x77, 0x61, 0x6e, 0x74, 0x2b, 0x03, 0x03, +0x81, 0x03, 0x24, 0x2c, 0x00, 0x9f, 0x04, 0xf6, 0x01, 0x28, +0x66, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, +0x65, 0x29, 0x00, 0x69, 0x66, 0x32, 0x00, 0x08, 0xac, 0x03, +0x01, 0x3c, 0x00, 0x00, 0x2c, 0x04, 0x04, 0xc4, 0x00, 0x32, +0x67, 0x61, 0x70, 0xe9, 0x04, 0x56, 0x77, 0x61, 0x72, 0x64, +0x73, 0x59, 0x05, 0x41, 0x67, 0x61, 0x70, 0x2c, 0xc6, 0x01, +0x13, 0x64, 0x9e, 0x00, 0x10, 0x52, 0x25, 0x00, 0x07, 0xe8, +0x00, 0x05, 0x62, 0x03, 0x0e, 0xe9, 0x00, 0x00, 0x3d, 0x00, +0x23, 0x27, 0x2c, 0x9f, 0x06, 0x40, 0x68, 0x61, 0x76, 0x69, +0x0a, 0x03, 0x0d, 0x34, 0x01, 0x00, 0xad, 0x05, 0x82, 0x72, +0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0xdf, 0x05, 0x01, +0xb2, 0x00, 0x34, 0x6f, 0x75, 0x6c, 0x73, 0x00, 0x3f, 0x4c, +0x65, 0x66, 0xbe, 0x00, 0x10, 0x0a, 0xb3, 0x00, 0x08, 0xae, +0x05, 0x00, 0x1e, 0x00, 0x40, 0x65, 0x6e, 0x64, 0x73, 0x0d, +0x06, 0x34, 0x6f, 0x6e, 0x65, 0xc6, 0x06, 0x04, 0x41, 0x00, +0xe0, 0x77, 0x68, 0x65, 0x72, 0x65, 0x00, 0x69, 0x74, 0x00, +0x77, 0x61, 0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 1245; -const unsigned short help_text_words = 229; +const unsigned short help_text_len = 1927; +const unsigned short help_text_words = 353; const char quick_help_text[] = "Slide the tiles around to arrange them into order."; diff --git a/apps/plugins/puzzles/help/filling.c b/apps/plugins/puzzles/help/filling.c index 19ffb97dee..a5ccd6d1fb 100644 --- a/apps/plugins/puzzles/help/filling.c +++ b/apps/plugins/puzzles/help/filling.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,140 +6,140 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 141, TEXT_CENTER | C_RED }, - { 306, TEXT_CENTER | C_RED }, + { 142, TEXT_CENTER | C_RED }, + { 307, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 1804 comp 1242 ratio 0.68847 level 10 saved 562 */ +/* orig 1821 comp 1245 ratio 0.68369 level 10 saved 576 */ const char help_text[] = { -0xf0, 0x28, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x39, 0x3a, 0x20, 0x46, 0x69, 0x6c, 0x6c, 0x69, 0x6e, -0x67, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, -0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, -0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, -0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, 0x00, 0xf6, -0x13, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, -0x74, 0x61, 0x69, 0x6e, 0x00, 0x64, 0x69, 0x67, 0x69, 0x74, -0x73, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x74, 0x68, 0x65, -0x00, 0x72, 0x65, 0x73, 0x74, 0x26, 0x00, 0xa0, 0x61, 0x72, -0x65, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x5b, 0x00, -0xf5, 0x02, 0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, -0x00, 0x74, 0x6f, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x00, 0x40, -0x00, 0x00, 0x0a, 0x00, 0x23, 0x74, 0x68, 0x2c, 0x00, 0x06, -0x73, 0x00, 0x50, 0x69, 0x6e, 0x00, 0x73, 0x75, 0x47, 0x00, -0xc2, 0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, -0x00, 0x65, 0x61, 0x7d, 0x00, 0xd7, 0x6e, 0x65, 0x63, 0x74, -0x65, 0x64, 0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0xa8, -0x00, 0x44, 0x00, 0x61, 0x6c, 0x6c, 0x9d, 0x00, 0x31, 0x69, -0x6e, 0x67, 0x56, 0x00, 0x42, 0x73, 0x61, 0x6d, 0x65, 0x69, -0x00, 0x70, 0x00, 0x68, 0x61, 0x73, 0x00, 0x61, 0x6e, 0x98, -0x00, 0x70, 0x61, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x8c, -0x00, 0x01, 0x59, 0x00, 0x01, 0x20, 0x00, 0x7b, 0x2e, 0x00, -0x00, 0x00, 0x28, 0x60, 0x43, 0x5f, 0x00, 0x61, 0x27, 0x2c, -0x00, 0x66, 0x6f, 0x72, 0x4b, 0x00, 0x80, 0x70, 0x75, 0x72, -0x70, 0x6f, 0x73, 0x65, 0x73, 0x72, 0x00, 0xf0, 0x09, 0x74, -0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, -0x64, 0x6f, 0x65, 0x73, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x63, -0x6f, 0x75, 0x6e, 0x4c, 0x00, 0xf0, 0x00, 0x61, 0x67, 0x6f, -0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x65, 0x70, 0x61, -0x72, 0x61, 0x4c, 0x00, 0x05, 0xa1, 0x00, 0xf2, 0x17, 0x73, -0x00, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x2e, -0x29, 0x00, 0x00, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, -0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x00, 0x69, 0x74, 0x00, -0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x96, 0x00, 0x23, -0x6e, 0x6f, 0x38, 0x00, 0x45, 0x00, 0x63, 0x61, 0x6e, 0x75, -0x01, 0x64, 0x61, 0x00, 0x7a, 0x65, 0x72, 0x6f, 0x75, 0x01, -0x65, 0x61, 0x74, 0x00, 0x74, 0x77, 0x6f, 0x55, 0x00, 0x05, -0x69, 0x00, 0x00, 0x32, 0x00, 0x00, 0x94, 0x00, 0x47, 0x62, -0x6f, 0x74, 0x68, 0x3b, 0x00, 0x74, 0x6f, 0x6e, 0x65, 0x2e, -0x00, 0x4e, 0x6f, 0x3b, 0x01, 0x08, 0x12, 0x01, 0x70, 0x67, -0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x54, 0x00, 0xc0, 0x6e, -0x00, 0x39, 0x00, 0x28, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, -0x65, 0xfa, 0x00, 0x20, 0x6e, 0x00, 0xa7, 0x01, 0x01, 0x26, -0x00, 0x52, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x5a, 0x00, 0x00, -0x29, 0x02, 0x53, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x60, 0x01, -0x10, 0x29, 0x41, 0x01, 0x41, 0x43, 0x72, 0x65, 0x64, 0xc8, -0x00, 0x12, 0x72, 0x23, 0x01, 0xa1, 0x70, 0x75, 0x7a, 0x7a, -0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0xfa, 0x01, 0xb0, 0x4e, -0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x31, 0x34, 0x5d, -0x2e, 0x00, 0x03, 0x7e, 0x02, 0x41, 0x00, 0x77, 0x61, 0x73, -0xa5, 0x00, 0x40, 0x72, 0x69, 0x62, 0x75, 0x2f, 0x01, 0x01, -0x98, 0x01, 0x10, 0x69, 0x14, 0x00, 0x50, 0x6c, 0x6c, 0x65, -0x63, 0x74, 0xab, 0x00, 0xf0, 0x01, 0x62, 0x79, 0x00, 0x4a, -0x6f, 0x6e, 0x61, 0x73, 0x00, 0x4b, 0x6f, 0x65, 0x6c, 0x6b, -0x65, 0x72, 0x3f, 0x00, 0x00, 0x47, 0x00, 0xd1, 0x00, 0x68, -0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, -0x6e, 0x5e, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, -0x2f, 0x65, 0x6e, 0x2f, 0x7d, 0x00, 0x20, 0x73, 0x2f, 0x70, -0x02, 0xf5, 0x02, 0x6f, 0x6d, 0x69, 0x6e, 0x6f, 0x2e, 0x68, -0x74, 0x6d, 0x6c, 0x00, 0x00, 0x00, 0x32, 0x39, 0x2e, 0x31, -0xfb, 0x02, 0x01, 0x79, 0x00, 0x30, 0x6f, 0x6c, 0x73, 0x04, -0x03, 0x74, 0x54, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x99, -0x00, 0xe1, 0x2c, 0x00, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, -0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x05, 0x02, 0x20, 0x6d, -0x6f, 0x15, 0x01, 0x00, 0x4d, 0x01, 0x29, 0x6e, 0x79, 0xb3, -0x02, 0x04, 0x06, 0x03, 0x50, 0x6e, 0x00, 0x74, 0x79, 0x70, -0x1c, 0x01, 0x02, 0x75, 0x02, 0x12, 0x6f, 0xdd, 0x02, 0x85, -0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0xff, 0x02, -0x01, 0xbb, 0x01, 0x02, 0x3a, 0x00, 0xa4, 0x2e, 0x00, 0x42, -0x79, 0x00, 0x64, 0x72, 0x61, 0x67, 0x67, 0xb5, 0x02, 0x01, -0x65, 0x00, 0x51, 0x2c, 0x00, 0x79, 0x6f, 0x75, 0xc9, 0x01, -0x20, 0x73, 0x65, 0x06, 0x01, 0x95, 0x00, 0x6d, 0x75, 0x6c, -0x74, 0x69, 0x70, 0x6c, 0x65, 0xe5, 0x01, 0x04, 0x4c, 0x00, -0x46, 0x77, 0x69, 0x74, 0x68, 0x8d, 0x01, 0xc1, 0x6b, 0x65, -0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x00, 0x49, 0x66, -0x43, 0x00, 0x30, 0x6d, 0x61, 0x6b, 0x90, 0x00, 0x8e, 0x6d, -0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2c, 0xcd, 0x00, 0x02, -0xa3, 0x00, 0x60, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x69, -0x00, 0x07, 0xd1, 0x00, 0x01, 0x4a, 0x00, 0xf0, 0x01, 0x00, -0x30, 0x2c, 0x00, 0x53, 0x70, 0x61, 0x63, 0x65, 0x2c, 0x00, -0x42, 0x61, 0x63, 0x6b, 0x73, 0x0b, 0x00, 0x61, 0x00, 0x6f, -0x72, 0x00, 0x45, 0x6e, 0x31, 0x02, 0x70, 0x6f, 0x00, 0x63, -0x6c, 0x65, 0x61, 0x72, 0xc0, 0x02, 0x20, 0x61, 0x67, 0x68, -0x02, 0x43, 0x28, 0x6f, 0x72, 0x00, 0x3b, 0x02, 0xd1, 0x00, -0x55, 0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, -0x72, 0x65, 0x22, 0x02, 0x13, 0x59, 0xd5, 0x00, 0x70, 0x61, -0x6c, 0x73, 0x6f, 0x00, 0x6d, 0x6f, 0x70, 0x04, 0x33, 0x72, -0x6f, 0x75, 0x42, 0x04, 0x01, 0x79, 0x04, 0x01, 0xcf, 0x00, -0x00, 0x0e, 0x00, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, -0xd1, 0x00, 0x20, 0x73, 0x3b, 0x56, 0x01, 0x00, 0x1f, 0x01, -0x04, 0x58, 0x01, 0x10, 0x77, 0xf9, 0x00, 0x03, 0x4a, 0x01, -0x04, 0x12, 0x01, 0x0c, 0xfc, 0x03, 0x03, 0x40, 0x00, 0x03, -0x50, 0x00, 0x00, 0x52, 0x03, 0x55, 0x75, 0x6d, 0x62, 0x65, -0x72, 0x4c, 0x00, 0x12, 0x30, 0x46, 0x00, 0x04, 0xbe, 0x00, -0x1a, 0x2e, 0x9c, 0x00, 0x0f, 0x76, 0x01, 0x05, 0x00, 0xdc, -0x02, 0x02, 0x49, 0x00, 0x00, 0x44, 0x00, 0x22, 0x6f, 0x72, -0x40, 0x00, 0x01, 0xc7, 0x02, 0x04, 0xb9, 0x00, 0x61, 0x72, -0x65, 0x74, 0x75, 0x72, 0x6e, 0x41, 0x01, 0x51, 0x61, 0x72, -0x72, 0x6f, 0x77, 0xc3, 0x00, 0x8c, 0x2c, 0x00, 0x62, 0x65, -0x66, 0x6f, 0x72, 0x65, 0xca, 0x00, 0x04, 0xc6, 0x01, 0x04, -0x4a, 0x00, 0x01, 0x42, 0x00, 0x88, 0x68, 0x69, 0x67, 0x68, -0x6c, 0x69, 0x67, 0x68, 0x3d, 0x04, 0x10, 0x28, 0xae, 0x03, -0x30, 0x62, 0x6f, 0x76, 0x48, 0x01, 0x10, 0x54, 0xf5, 0x00, -0x01, 0x88, 0x01, 0x70, 0x62, 0x61, 0x72, 0x00, 0x61, 0x64, -0x64, 0xc9, 0x03, 0x00, 0xb4, 0x04, 0x00, 0x52, 0x01, 0x14, -0x73, 0x0b, 0x02, 0x07, 0x29, 0x02, 0x00, 0x1e, 0x00, 0x42, -0x66, 0x72, 0x6f, 0x6d, 0x2f, 0x01, 0x13, 0x65, 0x57, 0x03, -0x17, 0x2e, 0xd1, 0x01, 0x00, 0x22, 0x00, 0x63, 0x65, 0x73, -0x63, 0x61, 0x70, 0x65, 0x47, 0x00, 0x01, 0x4f, 0x05, 0x05, -0xf6, 0x00, 0x0e, 0x3c, 0x00, 0x00, 0x30, 0x05, 0x13, 0x41, -0x81, 0x01, 0x11, 0x61, 0x13, 0x00, 0xb1, 0x73, 0x00, 0x64, -0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0xc0, 0x05, -0x03, 0xbc, 0x03, 0x31, 0x32, 0x2e, 0x31, 0x0e, 0x06, 0x01, -0x57, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, -0x6c, 0x65, 0x2e, 0x29, 0x8a, 0x03, 0x15, 0x32, 0x8a, 0x03, -0x00, 0x2e, 0x05, 0x77, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, -0x20, 0x1d, 0x04, 0x12, 0x61, 0x13, 0x05, 0x00, 0xca, 0x02, -0x20, 0x74, 0x6f, 0xe3, 0x01, 0x52, 0x66, 0x69, 0x67, 0x75, -0x72, 0x5e, 0x02, 0x02, 0x88, 0x01, 0x00, 0x91, 0x05, 0x32, -0x72, 0x6f, 0x77, 0x03, 0x01, 0x63, 0x63, 0x6f, 0x6c, 0x75, -0x6d, 0x6e, 0xa5, 0x05, 0x02, 0x52, 0x02, 0x82, 0x2c, 0x00, -0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x9d, 0x01, 0xd0, 0x60, -0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, -0x2e, 0x00, +0x67, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x14, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, +0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, +0x6f, 0x6d, 0x65, 0x11, 0x00, 0xf6, 0x13, 0x77, 0x68, 0x69, +0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, +0x00, 0x64, 0x69, 0x67, 0x69, 0x74, 0x73, 0x2c, 0x00, 0x61, +0x6e, 0x64, 0x00, 0x74, 0x68, 0x65, 0x00, 0x72, 0x65, 0x73, +0x74, 0x26, 0x00, 0xa0, 0x61, 0x72, 0x65, 0x00, 0x65, 0x6d, +0x70, 0x74, 0x79, 0x2e, 0x5b, 0x00, 0xf5, 0x02, 0x72, 0x00, +0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, +0x66, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x00, 0x00, 0x0a, 0x00, +0x23, 0x74, 0x68, 0x2c, 0x00, 0x06, 0x73, 0x00, 0x50, 0x69, +0x6e, 0x00, 0x73, 0x75, 0x47, 0x00, 0xc2, 0x00, 0x77, 0x61, +0x79, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x65, 0x61, 0x7d, +0x00, 0xd7, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x72, +0x65, 0x67, 0x69, 0x6f, 0x6e, 0xa8, 0x00, 0x44, 0x00, 0x61, +0x6c, 0x6c, 0x9d, 0x00, 0x31, 0x69, 0x6e, 0x67, 0x56, 0x00, +0x42, 0x73, 0x61, 0x6d, 0x65, 0x69, 0x00, 0x70, 0x00, 0x68, +0x61, 0x73, 0x00, 0x61, 0x6e, 0x98, 0x00, 0x70, 0x61, 0x00, +0x65, 0x71, 0x75, 0x61, 0x6c, 0x8c, 0x00, 0x01, 0x59, 0x00, +0x01, 0x20, 0x00, 0x7b, 0x2e, 0x00, 0x00, 0x00, 0x28, 0x60, +0x43, 0x5f, 0x00, 0x61, 0x27, 0x2c, 0x00, 0x66, 0x6f, 0x72, +0x4b, 0x00, 0x80, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, +0x73, 0x72, 0x00, 0xf0, 0x09, 0x74, 0x68, 0x69, 0x73, 0x00, +0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, 0x64, 0x6f, 0x65, 0x73, +0x00, 0x6e, 0x6f, 0x74, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x4c, +0x00, 0xf0, 0x00, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, +0x79, 0x00, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x4c, 0x00, +0x05, 0xa1, 0x00, 0xf2, 0x17, 0x73, 0x00, 0x61, 0x64, 0x6a, +0x61, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x29, 0x00, 0x00, 0x00, +0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, +0x65, 0x2c, 0x00, 0x69, 0x74, 0x00, 0x66, 0x6f, 0x6c, 0x6c, +0x6f, 0x77, 0x73, 0x96, 0x00, 0x23, 0x6e, 0x6f, 0x38, 0x00, +0x45, 0x00, 0x63, 0x61, 0x6e, 0x75, 0x01, 0x64, 0x61, 0x00, +0x7a, 0x65, 0x72, 0x6f, 0x75, 0x01, 0x65, 0x61, 0x74, 0x00, +0x74, 0x77, 0x6f, 0x55, 0x00, 0x05, 0x69, 0x00, 0x00, 0x32, +0x00, 0x00, 0x94, 0x00, 0x47, 0x62, 0x6f, 0x74, 0x68, 0x3b, +0x00, 0x74, 0x6f, 0x6e, 0x65, 0x2e, 0x00, 0x4e, 0x6f, 0x3b, +0x01, 0x08, 0x12, 0x01, 0x70, 0x67, 0x72, 0x65, 0x61, 0x74, +0x65, 0x72, 0x54, 0x00, 0xc0, 0x6e, 0x00, 0x39, 0x00, 0x28, +0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0xfa, 0x00, 0x20, +0x6e, 0x00, 0xa7, 0x01, 0x01, 0x26, 0x00, 0x52, 0x77, 0x6f, +0x75, 0x6c, 0x64, 0x5a, 0x00, 0x00, 0x29, 0x02, 0x53, 0x73, +0x69, 0x6e, 0x67, 0x6c, 0x60, 0x01, 0x10, 0x29, 0x41, 0x01, +0x41, 0x43, 0x72, 0x65, 0x64, 0xc8, 0x00, 0x12, 0x72, 0x23, +0x01, 0xa1, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, +0x6f, 0x65, 0xfa, 0x01, 0xb0, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, +0x69, 0x00, 0x5b, 0x31, 0x34, 0x5d, 0x2e, 0x00, 0x03, 0x92, +0x02, 0x41, 0x00, 0x77, 0x61, 0x73, 0xa5, 0x00, 0x40, 0x72, +0x69, 0x62, 0x75, 0x2f, 0x01, 0x01, 0x98, 0x01, 0x10, 0x69, +0x14, 0x00, 0x50, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0xab, 0x00, +0xf0, 0x01, 0x62, 0x79, 0x00, 0x4a, 0x6f, 0x6e, 0x61, 0x73, +0x00, 0x4b, 0x6f, 0x65, 0x6c, 0x6b, 0x65, 0x72, 0x3f, 0x00, +0x00, 0x47, 0x00, 0xe1, 0x00, 0x68, 0x74, 0x74, 0x70, 0x73, +0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x5f, 0x00, +0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, +0x2f, 0x7e, 0x00, 0x20, 0x73, 0x2f, 0x71, 0x02, 0xd5, 0x6f, +0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x00, 0x00, 0x00, 0x32, 0x39, +0x2e, 0x31, 0x0c, 0x03, 0x01, 0x76, 0x00, 0xe4, 0x6f, 0x6c, +0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x00, 0x70, 0x6c, +0x61, 0x79, 0x96, 0x00, 0xe1, 0x2c, 0x00, 0x73, 0x69, 0x6d, +0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x02, +0x02, 0x20, 0x6d, 0x6f, 0x12, 0x01, 0x00, 0x4a, 0x01, 0x29, +0x6e, 0x79, 0xb0, 0x02, 0x04, 0x03, 0x03, 0x50, 0x6e, 0x00, +0x74, 0x79, 0x70, 0x19, 0x01, 0x02, 0x72, 0x02, 0x12, 0x6f, +0xda, 0x02, 0x85, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, +0x64, 0xfc, 0x02, 0x01, 0xb8, 0x01, 0x02, 0x3a, 0x00, 0xa4, +0x2e, 0x00, 0x42, 0x79, 0x00, 0x64, 0x72, 0x61, 0x67, 0x67, +0xb2, 0x02, 0x01, 0x65, 0x00, 0x51, 0x2c, 0x00, 0x79, 0x6f, +0x75, 0xc6, 0x01, 0x20, 0x73, 0x65, 0x03, 0x01, 0x95, 0x00, +0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0xe2, 0x01, +0x04, 0x4c, 0x00, 0x46, 0x77, 0x69, 0x74, 0x68, 0x8a, 0x01, +0xc1, 0x6b, 0x65, 0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2e, +0x00, 0x49, 0x66, 0x43, 0x00, 0x30, 0x6d, 0x61, 0x6b, 0x90, +0x00, 0x8e, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2c, +0xcd, 0x00, 0x02, 0xa3, 0x00, 0x60, 0x69, 0x6e, 0x63, 0x6f, +0x72, 0x72, 0x69, 0x00, 0x07, 0xd1, 0x00, 0x01, 0x4a, 0x00, +0xf0, 0x01, 0x00, 0x30, 0x2c, 0x00, 0x53, 0x70, 0x61, 0x63, +0x65, 0x2c, 0x00, 0x42, 0x61, 0x63, 0x6b, 0x73, 0x0b, 0x00, +0x61, 0x00, 0x6f, 0x72, 0x00, 0x45, 0x6e, 0x2e, 0x02, 0x70, +0x6f, 0x00, 0x63, 0x6c, 0x65, 0x61, 0x72, 0xbd, 0x02, 0x20, +0x61, 0x67, 0x65, 0x02, 0x43, 0x28, 0x6f, 0x72, 0x00, 0x38, +0x02, 0xd1, 0x00, 0x55, 0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, +0x61, 0x74, 0x75, 0x72, 0x65, 0x1f, 0x02, 0x13, 0x59, 0xd5, +0x00, 0x70, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x6d, 0x6f, 0x6d, +0x04, 0x33, 0x72, 0x6f, 0x75, 0x3f, 0x04, 0x01, 0x76, 0x04, +0x01, 0xcf, 0x00, 0x00, 0x0e, 0x00, 0x60, 0x63, 0x75, 0x72, +0x73, 0x6f, 0x72, 0xd1, 0x00, 0x20, 0x73, 0x3b, 0x56, 0x01, +0x00, 0x1f, 0x01, 0x04, 0x58, 0x01, 0x10, 0x77, 0xf9, 0x00, +0x03, 0x4a, 0x01, 0x04, 0x12, 0x01, 0x0c, 0xf9, 0x03, 0x03, +0x40, 0x00, 0x03, 0x50, 0x00, 0x00, 0x4f, 0x03, 0x55, 0x75, +0x6d, 0x62, 0x65, 0x72, 0x4c, 0x00, 0x12, 0x30, 0x46, 0x00, +0x04, 0xbe, 0x00, 0x1a, 0x2e, 0x9c, 0x00, 0x0f, 0x76, 0x01, +0x05, 0x00, 0xd9, 0x02, 0x02, 0x49, 0x00, 0x00, 0x44, 0x00, +0x22, 0x6f, 0x72, 0x40, 0x00, 0x01, 0xc4, 0x02, 0x04, 0xb9, +0x00, 0x61, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x41, 0x01, +0x51, 0x61, 0x72, 0x72, 0x6f, 0x77, 0xc3, 0x00, 0x8c, 0x2c, +0x00, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0xca, 0x00, 0x04, +0xc6, 0x01, 0x04, 0x4a, 0x00, 0x01, 0x42, 0x00, 0x88, 0x68, +0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x3a, 0x04, 0x10, +0x28, 0xab, 0x03, 0x30, 0x62, 0x6f, 0x76, 0x48, 0x01, 0x10, +0x54, 0xf5, 0x00, 0x01, 0x88, 0x01, 0x70, 0x62, 0x61, 0x72, +0x00, 0x61, 0x64, 0x64, 0xc6, 0x03, 0x00, 0xb1, 0x04, 0x00, +0x52, 0x01, 0x14, 0x73, 0x0b, 0x02, 0x07, 0x29, 0x02, 0x00, +0x1e, 0x00, 0x42, 0x66, 0x72, 0x6f, 0x6d, 0x2f, 0x01, 0x13, +0x65, 0x54, 0x03, 0x17, 0x2e, 0xd1, 0x01, 0x00, 0x22, 0x00, +0x63, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x47, 0x00, 0x01, +0x4c, 0x05, 0x05, 0xf6, 0x00, 0x0e, 0x3c, 0x00, 0x00, 0x2d, +0x05, 0x13, 0x41, 0x81, 0x01, 0x11, 0x61, 0x13, 0x00, 0xb1, +0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0xbd, 0x05, 0x03, 0xb9, 0x03, 0x31, 0x32, 0x2e, 0x31, +0x0b, 0x06, 0x01, 0x57, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, +0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x8a, 0x03, 0x15, +0x32, 0x8a, 0x03, 0x00, 0x2b, 0x05, 0x77, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x73, 0x20, 0x1a, 0x04, 0x12, 0x61, 0x10, 0x05, +0x00, 0xca, 0x02, 0x20, 0x74, 0x6f, 0xe3, 0x01, 0x52, 0x66, +0x69, 0x67, 0x75, 0x72, 0x5e, 0x02, 0x02, 0x88, 0x01, 0x00, +0x8e, 0x05, 0x32, 0x72, 0x6f, 0x77, 0x03, 0x01, 0x63, 0x63, +0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0xa2, 0x05, 0x02, 0x52, 0x02, +0x82, 0x2c, 0x00, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x9d, +0x01, 0xd0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, +0x65, 0x6e, 0x75, 0x2e, 0x00, }; -const unsigned short help_text_len = 1804; -const unsigned short help_text_words = 327; +const unsigned short help_text_len = 1821; +const unsigned short help_text_words = 328; const char quick_help_text[] = "Mark every square with the area of its containing region."; diff --git a/apps/plugins/puzzles/help/flip.c b/apps/plugins/puzzles/help/flip.c index e5ec994fdb..91a0886b66 100644 --- a/apps/plugins/puzzles/help/flip.c +++ b/apps/plugins/puzzles/help/flip.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,129 +6,129 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 76, TEXT_CENTER | C_RED }, - { 164, TEXT_UNDERLINE }, - { 203, TEXT_CENTER | C_RED }, - { 220, TEXT_UNDERLINE }, + { 77, TEXT_CENTER | C_RED }, + { 165, TEXT_UNDERLINE }, + { 204, TEXT_CENTER | C_RED }, { 221, TEXT_UNDERLINE }, - { 231, TEXT_UNDERLINE }, + { 222, TEXT_UNDERLINE }, + { 232, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1522 comp 1092 ratio 0.717477 level 10 saved 430 */ +/* orig 1539 comp 1099 ratio 0.7141 level 10 saved 440 */ const char help_text[] = { -0xf2, 0x2f, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfb, 0x04, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x34, 0x3a, 0x20, 0x46, 0x6c, 0x69, 0x70, 0x20, 0x00, -0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, -0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, -0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, -0x73, 0x6f, 0x6d, 0x65, 0x00, 0x6c, 0x69, 0x67, 0x68, 0x74, -0x00, 0x61, 0x6e, 0x64, 0x0f, 0x00, 0x50, 0x64, 0x61, 0x72, -0x6b, 0x2e, 0x36, 0x00, 0xb4, 0x72, 0x00, 0x61, 0x69, 0x6d, -0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x24, 0x00, 0x64, 0x6c, -0x6c, 0x00, 0x74, 0x68, 0x65, 0x40, 0x00, 0x62, 0x00, 0x75, -0x70, 0x00, 0x61, 0x74, 0x12, 0x00, 0x91, 0x61, 0x6d, 0x65, -0x00, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x70, 0x00, 0xe3, 0x63, -0x61, 0x6e, 0x00, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x00, -0x61, 0x6e, 0x79, 0x30, 0x00, 0x01, 0x63, 0x00, 0xf3, 0x04, -0x66, 0x6c, 0x69, 0x70, 0x00, 0x69, 0x74, 0x73, 0x00, 0x73, -0x74, 0x61, 0x74, 0x65, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x5d, -0x00, 0x21, 0x74, 0x6f, 0x7b, 0x00, 0x32, 0x00, 0x6f, 0x72, -0x08, 0x00, 0x04, 0x76, 0x00, 0xf5, 0x0c, 0x2c, 0x00, 0x62, -0x75, 0x74, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x00, 0x79, 0x6f, -0x75, 0x00, 0x64, 0x6f, 0x00, 0x73, 0x6f, 0x2c, 0x00, 0x6f, -0x74, 0x68, 0x65, 0x72, 0x89, 0x00, 0xf3, 0x01, 0x61, 0x72, -0x6f, 0x75, 0x6e, 0x64, 0x00, 0x69, 0x74, 0x00, 0x63, 0x68, -0x61, 0x6e, 0x67, 0x65, 0x5e, 0x00, 0xf4, 0x00, 0x61, 0x73, -0x00, 0x77, 0x65, 0x6c, 0x6c, 0x2e, 0x00, 0x00, 0x00, 0x45, -0x61, 0x63, 0x68, 0x88, 0x00, 0xd0, 0x63, 0x6f, 0x6e, 0x74, -0x61, 0x69, 0x6e, 0x73, 0x00, 0x61, 0x00, 0x73, 0x6d, 0xd4, -0x00, 0xfb, 0x06, 0x64, 0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, -0x00, 0x73, 0x68, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x00, 0x77, -0x68, 0x69, 0x63, 0x68, 0x63, 0x00, 0x03, 0x59, 0x00, 0x05, -0x88, 0x00, 0x03, 0xc9, 0x00, 0x00, 0x5c, 0x00, 0x42, 0x31, -0x34, 0x2e, 0x31, 0x6f, 0x01, 0x00, 0x5a, 0x00, 0x40, 0x72, -0x6f, 0x6c, 0x73, 0x78, 0x01, 0x60, 0x54, 0x68, 0x69, 0x73, -0x00, 0x67, 0x18, 0x01, 0x00, 0x0e, 0x01, 0xf1, 0x02, 0x62, -0x65, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x00, 0x77, -0x69, 0x74, 0x68, 0x00, 0x65, 0x69, 0x5d, 0x00, 0x00, 0x3b, -0x01, 0xa2, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, -0x00, 0x6f, 0x10, 0x00, 0x50, 0x6d, 0x6f, 0x75, 0x73, 0x65, -0x57, 0x00, 0xf4, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, -0x6c, 0x69, 0x63, 0x6b, 0x00, 0x69, 0x6e, 0x00, 0x61, 0xbe, -0x00, 0x24, 0x74, 0x6f, 0x7c, 0x00, 0x01, 0x51, 0x01, 0x00, -0x4c, 0x01, 0xa6, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, -0x74, 0x65, 0x64, 0xdb, 0x01, 0x61, 0x6f, 0x72, 0x00, 0x75, -0x73, 0x65, 0x52, 0x00, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, -0x72, 0x69, 0x00, 0x01, 0xcc, 0x01, 0x04, 0x99, 0x01, 0x08, -0x97, 0x01, 0x01, 0xc4, 0x01, 0x80, 0x70, 0x61, 0x63, 0x65, -0x00, 0x62, 0x61, 0x72, 0x3c, 0x00, 0x41, 0x45, 0x6e, 0x74, -0x65, 0x33, 0x00, 0x04, 0x70, 0x00, 0x00, 0x92, 0x00, 0x21, -0x49, 0x66, 0xfb, 0x00, 0x04, 0x58, 0x00, 0xf4, 0x06, 0x60, -0x53, 0x6f, 0x6c, 0x76, 0x65, 0x27, 0x00, 0x66, 0x75, 0x6e, -0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x6f, 0x6e, 0x00, 0x74, -0xf6, 0x00, 0x10, 0x2c, 0xa1, 0x00, 0x60, 0x77, 0x69, 0x6c, -0x6c, 0x00, 0x6d, 0xce, 0x01, 0x01, 0x5b, 0x02, 0x29, 0x6f, -0x66, 0x3f, 0x02, 0x74, 0x69, 0x6e, 0x00, 0x72, 0x65, 0x64, -0x2e, 0x57, 0x00, 0x02, 0xeb, 0x00, 0x40, 0x6f, 0x6e, 0x63, -0x65, 0x1a, 0x00, 0x45, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x02, -0x01, 0x34, 0x01, 0x10, 0x61, 0x2e, 0x00, 0x01, 0x4e, 0x00, -0x11, 0x2c, 0x47, 0x00, 0x01, 0x5c, 0x01, 0x60, 0x73, 0x68, -0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x01, 0x10, 0x73, 0x8d, 0x00, -0x49, 0x64, 0x2e, 0x00, 0x28, 0x4f, 0x00, 0x08, 0x3a, 0x01, -0x00, 0x46, 0x00, 0x39, 0x6f, 0x75, 0x74, 0x49, 0x00, 0x06, -0x0c, 0x00, 0x02, 0xad, 0x00, 0x60, 0x61, 0x70, 0x70, 0x65, -0x61, 0x72, 0x37, 0x00, 0x11, 0x69, 0x93, 0x02, 0x70, 0x69, -0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0xf1, 0x00, 0x21, 0x61, -0x74, 0x58, 0x00, 0x01, 0x27, 0x00, 0x40, 0x6e, 0x65, 0x65, -0x64, 0x1f, 0x00, 0x10, 0x72, 0xa7, 0x00, 0x13, 0x73, 0x1e, -0x00, 0x51, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x09, 0x01, 0x01, -0x1a, 0x00, 0x00, 0x72, 0x02, 0x21, 0x74, 0x68, 0x99, 0x00, -0x10, 0x75, 0x16, 0x00, 0x73, 0x2e, 0x29, 0x00, 0x00, 0x00, -0x28, 0x41, 0x44, 0x03, 0x11, 0x61, 0x33, 0x01, 0xb0, 0x73, -0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, -0x74, 0x00, 0x22, 0x73, 0x65, 0x49, 0x01, 0x41, 0x32, 0x2e, -0x31, 0x00, 0x9b, 0x01, 0xf2, 0x00, 0x6c, 0x73, 0x6f, 0x00, -0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, -0x29, 0x6d, 0x02, 0x12, 0x32, 0x6d, 0x02, 0x93, 0x70, 0x61, -0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6f, 0x02, 0x46, -0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x40, 0x00, 0x04, -0x3b, 0x00, 0x02, 0x69, 0x03, 0x01, 0xb5, 0x01, 0xd6, 0x43, -0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, -0x6f, 0x70, 0xb7, 0x01, 0xd0, 0x65, 0x00, 0x60, 0x54, 0x79, -0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xed, 0x01, -0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, -0x9e, 0x03, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xc2, 0x01, -0x01, 0x45, 0x04, 0x24, 0x69, 0x6e, 0xc6, 0x01, 0x10, 0x2e, -0x1b, 0x00, 0x94, 0x68, 0x61, 0x70, 0x65, 0x20, 0x74, 0x79, -0x70, 0x65, 0xf8, 0x02, 0x03, 0x09, 0x03, 0x20, 0x00, 0x64, -0x8c, 0x00, 0x52, 0x6d, 0x69, 0x6e, 0x65, 0x73, 0x0b, 0x01, -0x00, 0x29, 0x00, 0x04, 0x07, 0x02, 0x30, 0x72, 0x65, 0x67, -0x7e, 0x00, 0x02, 0x6d, 0x03, 0x21, 0x69, 0x73, 0x66, 0x02, -0x62, 0x70, 0x65, 0x64, 0x00, 0x62, 0x79, 0xbc, 0x01, 0x00, -0x8a, 0x03, 0x21, 0x69, 0x6e, 0x41, 0x04, 0x44, 0x67, 0x69, -0x76, 0x65, 0x72, 0x00, 0x10, 0x2e, 0xeb, 0x00, 0xfa, 0x14, -0x00, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x73, -0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x2c, 0x00, 0x60, 0x43, -0x72, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x27, 0x2c, 0x00, 0x63, -0x61, 0x75, 0x73, 0x65, 0x73, 0x42, 0x02, 0x06, 0x36, 0x03, -0x45, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x03, 0x10, 0x66, 0xe7, -0x04, 0x60, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0xe5, 0x01, -0x10, 0x6e, 0xed, 0x00, 0x71, 0x62, 0x6f, 0x75, 0x72, 0x73, -0x00, 0x28, 0x8f, 0x03, 0x31, 0x72, 0x65, 0x65, 0x98, 0x03, -0xc0, 0x77, 0x6f, 0x00, 0x69, 0x66, 0x00, 0x69, 0x74, 0x27, -0x73, 0x00, 0x61, 0x78, 0x03, 0x41, 0x00, 0x65, 0x64, 0x67, -0x1a, 0x00, 0x72, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0x29, -0x95, 0x00, 0x03, 0x32, 0x04, 0x05, 0x93, 0x00, 0x66, 0x52, -0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x92, 0x00, 0x31, 0x61, 0x00, -0x72, 0x12, 0x00, 0x03, 0x08, 0x01, 0x20, 0x74, 0x6f, 0xb8, -0x02, 0xa9, 0x63, 0x68, 0x6f, 0x73, 0x65, 0x6e, 0x00, 0x66, -0x6f, 0x72, 0xb2, 0x00, 0x00, 0x9d, 0x05, 0x06, 0xe7, 0x02, -0xc3, 0x69, 0x73, 0x00, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, -0x65, 0x6e, 0x74, 0x27, 0x00, 0x60, 0x74, 0x69, 0x6d, 0x65, -0x2e, 0x00, +0x2d, 0x01, 0x00, 0xf2, 0x1e, 0x00, 0x00, 0x00, 0x59, 0x6f, +0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, +0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, +0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, +0x00, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00, 0x61, 0x6e, 0x64, +0x0f, 0x00, 0x50, 0x64, 0x61, 0x72, 0x6b, 0x2e, 0x36, 0x00, +0xb4, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, +0x74, 0x6f, 0x24, 0x00, 0x64, 0x6c, 0x6c, 0x00, 0x74, 0x68, +0x65, 0x40, 0x00, 0x62, 0x00, 0x75, 0x70, 0x00, 0x61, 0x74, +0x12, 0x00, 0x91, 0x61, 0x6d, 0x65, 0x00, 0x74, 0x69, 0x6d, +0x65, 0x2e, 0x70, 0x00, 0xe3, 0x63, 0x61, 0x6e, 0x00, 0x63, +0x68, 0x6f, 0x6f, 0x73, 0x65, 0x00, 0x61, 0x6e, 0x79, 0x30, +0x00, 0x01, 0x63, 0x00, 0xf3, 0x04, 0x66, 0x6c, 0x69, 0x70, +0x00, 0x69, 0x74, 0x73, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, +0x00, 0x66, 0x72, 0x6f, 0x6d, 0x5d, 0x00, 0x21, 0x74, 0x6f, +0x7b, 0x00, 0x32, 0x00, 0x6f, 0x72, 0x08, 0x00, 0x04, 0x76, +0x00, 0xf5, 0x0c, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x77, +0x68, 0x65, 0x6e, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x64, 0x6f, +0x00, 0x73, 0x6f, 0x2c, 0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, +0x89, 0x00, 0xf3, 0x01, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, +0x00, 0x69, 0x74, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, +0x5e, 0x00, 0xf4, 0x00, 0x61, 0x73, 0x00, 0x77, 0x65, 0x6c, +0x6c, 0x2e, 0x00, 0x00, 0x00, 0x45, 0x61, 0x63, 0x68, 0x88, +0x00, 0xd0, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, +0x00, 0x61, 0x00, 0x73, 0x6d, 0xd4, 0x00, 0xfb, 0x06, 0x64, +0x69, 0x61, 0x67, 0x72, 0x61, 0x6d, 0x00, 0x73, 0x68, 0x6f, +0x77, 0x69, 0x6e, 0x67, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, +0x63, 0x00, 0x03, 0x59, 0x00, 0x05, 0x88, 0x00, 0x03, 0xc9, +0x00, 0x00, 0x5c, 0x00, 0x42, 0x31, 0x34, 0x2e, 0x31, 0x80, +0x01, 0x00, 0x5a, 0x00, 0xe0, 0x72, 0x6f, 0x6c, 0x73, 0x20, +0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x67, 0x18, +0x01, 0x00, 0x0e, 0x01, 0xf1, 0x02, 0x62, 0x65, 0x00, 0x70, +0x6c, 0x61, 0x79, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, +0x00, 0x65, 0x69, 0x5d, 0x00, 0x00, 0x3b, 0x01, 0xa2, 0x6b, +0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x6f, 0x10, +0x00, 0x50, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x57, 0x00, 0xf4, +0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0x00, 0x69, 0x6e, 0x00, 0x61, 0xbe, 0x00, 0x24, 0x74, +0x6f, 0x7c, 0x00, 0x01, 0x51, 0x01, 0x00, 0x4c, 0x01, 0xa6, +0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, +0xdb, 0x01, 0x61, 0x6f, 0x72, 0x00, 0x75, 0x73, 0x65, 0x52, +0x00, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x69, 0x00, +0x01, 0xcc, 0x01, 0x04, 0x99, 0x01, 0x08, 0x97, 0x01, 0x01, +0xc4, 0x01, 0x80, 0x70, 0x61, 0x63, 0x65, 0x00, 0x62, 0x61, +0x72, 0x3c, 0x00, 0x41, 0x45, 0x6e, 0x74, 0x65, 0x33, 0x00, +0x04, 0x70, 0x00, 0x00, 0x92, 0x00, 0x21, 0x49, 0x66, 0xfb, +0x00, 0x04, 0x58, 0x00, 0xf4, 0x06, 0x60, 0x53, 0x6f, 0x6c, +0x76, 0x65, 0x27, 0x00, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x00, 0x6f, 0x6e, 0x00, 0x74, 0xf6, 0x00, 0x10, +0x2c, 0xa1, 0x00, 0x60, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x6d, +0xce, 0x01, 0x01, 0x5b, 0x02, 0x29, 0x6f, 0x66, 0x3f, 0x02, +0x74, 0x69, 0x6e, 0x00, 0x72, 0x65, 0x64, 0x2e, 0x57, 0x00, +0x02, 0xeb, 0x00, 0x40, 0x6f, 0x6e, 0x63, 0x65, 0x1a, 0x00, +0x45, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x02, 0x01, 0x34, 0x01, +0x10, 0x61, 0x2e, 0x00, 0x01, 0x4e, 0x00, 0x11, 0x2c, 0x47, +0x00, 0x01, 0x5c, 0x01, 0x60, 0x73, 0x68, 0x6f, 0x75, 0x6c, +0x64, 0x5f, 0x01, 0x10, 0x73, 0x8d, 0x00, 0x49, 0x64, 0x2e, +0x00, 0x28, 0x4f, 0x00, 0x08, 0x3a, 0x01, 0x00, 0x46, 0x00, +0x39, 0x6f, 0x75, 0x74, 0x49, 0x00, 0x06, 0x0c, 0x00, 0x02, +0xad, 0x00, 0x60, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x37, +0x00, 0x11, 0x69, 0x93, 0x02, 0x70, 0x69, 0x6e, 0x64, 0x69, +0x63, 0x61, 0x74, 0xf1, 0x00, 0x21, 0x61, 0x74, 0x58, 0x00, +0x01, 0x27, 0x00, 0x40, 0x6e, 0x65, 0x65, 0x64, 0x1f, 0x00, +0x10, 0x72, 0xa7, 0x00, 0x13, 0x73, 0x1e, 0x00, 0x51, 0x6f, +0x70, 0x65, 0x72, 0x61, 0x09, 0x01, 0x01, 0x1a, 0x00, 0x00, +0x72, 0x02, 0x21, 0x74, 0x68, 0x99, 0x00, 0x10, 0x75, 0x16, +0x00, 0x73, 0x2e, 0x29, 0x00, 0x00, 0x00, 0x28, 0x41, 0x44, +0x03, 0x11, 0x61, 0x33, 0x01, 0xb0, 0x73, 0x00, 0x64, 0x65, +0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x74, 0x00, 0x22, +0x73, 0x65, 0x49, 0x01, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x9b, +0x01, 0xf2, 0x00, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, +0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x6d, 0x02, +0x12, 0x32, 0x6d, 0x02, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, +0x65, 0x74, 0x65, 0x72, 0x6f, 0x02, 0x46, 0x65, 0x73, 0x65, +0x00, 0x14, 0x00, 0x02, 0x40, 0x00, 0x04, 0x3b, 0x00, 0x02, +0x69, 0x03, 0x01, 0xb5, 0x01, 0xd6, 0x43, 0x75, 0x73, 0x74, +0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0xb7, +0x01, 0xd0, 0x65, 0x00, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0xed, 0x01, 0x91, 0x57, 0x69, +0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x9e, 0x03, 0x51, +0x00, 0x00, 0x53, 0x69, 0x7a, 0xc2, 0x01, 0x01, 0x45, 0x04, +0x24, 0x69, 0x6e, 0xc6, 0x01, 0x10, 0x2e, 0x1b, 0x00, 0x94, +0x68, 0x61, 0x70, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0xf8, +0x02, 0x03, 0x09, 0x03, 0x20, 0x00, 0x64, 0x8c, 0x00, 0x52, +0x6d, 0x69, 0x6e, 0x65, 0x73, 0x0b, 0x01, 0x00, 0x29, 0x00, +0x04, 0x07, 0x02, 0x30, 0x72, 0x65, 0x67, 0x7e, 0x00, 0x02, +0x6d, 0x03, 0x21, 0x69, 0x73, 0x66, 0x02, 0x62, 0x70, 0x65, +0x64, 0x00, 0x62, 0x79, 0xbc, 0x01, 0x00, 0x8a, 0x03, 0x21, +0x69, 0x6e, 0x41, 0x04, 0x44, 0x67, 0x69, 0x76, 0x65, 0x72, +0x00, 0x10, 0x2e, 0xeb, 0x00, 0xfa, 0x14, 0x00, 0x64, 0x65, +0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x73, 0x65, 0x74, 0x74, +0x69, 0x6e, 0x67, 0x2c, 0x00, 0x60, 0x43, 0x72, 0x6f, 0x73, +0x73, 0x65, 0x73, 0x27, 0x2c, 0x00, 0x63, 0x61, 0x75, 0x73, +0x65, 0x73, 0x42, 0x02, 0x06, 0x36, 0x03, 0x45, 0x73, 0x65, +0x6c, 0x66, 0x3a, 0x03, 0x10, 0x66, 0xe7, 0x04, 0x60, 0x69, +0x6d, 0x6d, 0x65, 0x64, 0x69, 0xe5, 0x01, 0x10, 0x6e, 0xed, +0x00, 0x71, 0x62, 0x6f, 0x75, 0x72, 0x73, 0x00, 0x28, 0x8f, +0x03, 0x31, 0x72, 0x65, 0x65, 0x98, 0x03, 0xc0, 0x77, 0x6f, +0x00, 0x69, 0x66, 0x00, 0x69, 0x74, 0x27, 0x73, 0x00, 0x61, +0x78, 0x03, 0x41, 0x00, 0x65, 0x64, 0x67, 0x1a, 0x00, 0x72, +0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0x29, 0x95, 0x00, 0x03, +0x32, 0x04, 0x05, 0x93, 0x00, 0x66, 0x52, 0x61, 0x6e, 0x64, +0x6f, 0x6d, 0x92, 0x00, 0x31, 0x61, 0x00, 0x72, 0x12, 0x00, +0x03, 0x08, 0x01, 0x20, 0x74, 0x6f, 0xb8, 0x02, 0xa9, 0x63, +0x68, 0x6f, 0x73, 0x65, 0x6e, 0x00, 0x66, 0x6f, 0x72, 0xb2, +0x00, 0x00, 0x9d, 0x05, 0x06, 0xe7, 0x02, 0xc3, 0x69, 0x73, +0x00, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, +0x27, 0x00, 0x60, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x00, }; -const unsigned short help_text_len = 1522; -const unsigned short help_text_words = 298; +const unsigned short help_text_len = 1539; +const unsigned short help_text_words = 299; const char quick_help_text[] = "Flip groups of squares to light them all up at once."; diff --git a/apps/plugins/puzzles/help/flood.c b/apps/plugins/puzzles/help/flood.c index 80e4383903..48905fd784 100644 --- a/apps/plugins/puzzles/help/flood.c +++ b/apps/plugins/puzzles/help/flood.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,180 +6,180 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 155, TEXT_CENTER | C_RED }, - { 261, TEXT_CENTER | C_RED }, - { 278, TEXT_UNDERLINE }, + { 156, TEXT_CENTER | C_RED }, + { 262, TEXT_CENTER | C_RED }, { 279, TEXT_UNDERLINE }, - { 290, TEXT_UNDERLINE }, - { 332, TEXT_UNDERLINE }, - { 444, TEXT_UNDERLINE }, + { 280, TEXT_UNDERLINE }, + { 291, TEXT_UNDERLINE }, + { 333, TEXT_UNDERLINE }, + { 445, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2377 comp 1592 ratio 0.669752 level 10 saved 785 */ +/* orig 2395 comp 1600 ratio 0.668058 level 10 saved 795 */ const char help_text[] = { -0xf3, 0x45, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x39, 0x3a, 0x20, 0x46, 0x6c, 0x6f, 0x6f, 0x64, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, -0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, -0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, -0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x63, 0x6f, 0x6c, 0x6f, -0x75, 0x72, 0x65, 0x64, 0x00, 0x61, 0x74, 0x00, 0x72, 0x61, -0x6e, 0x64, 0x6f, 0x6d, 0x00, 0x69, 0x6e, 0x00, 0x6d, 0x75, -0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x1f, 0x00, 0xf0, 0x0b, -0x73, 0x2e, 0x00, 0x49, 0x6e, 0x00, 0x65, 0x61, 0x63, 0x68, -0x00, 0x6d, 0x6f, 0x76, 0x65, 0x2c, 0x00, 0x79, 0x6f, 0x75, -0x00, 0x63, 0x61, 0x6e, 0x00, 0x66, 0x68, 0x00, 0xf3, 0x03, -0x2d, 0x66, 0x69, 0x6c, 0x6c, 0x00, 0x74, 0x68, 0x65, 0x00, -0x74, 0x6f, 0x70, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x00, -0x00, 0x4a, 0x00, 0x13, 0x61, 0x43, 0x00, 0x00, 0x75, 0x00, -0x10, 0x79, 0x08, 0x00, 0xf4, 0x03, 0x63, 0x68, 0x6f, 0x69, -0x63, 0x65, 0x00, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x00, 0x65, -0x76, 0x65, 0x72, 0x79, 0x2e, 0x00, 0x10, 0x72, 0x61, 0x00, -0x91, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x66, 0x72, 0x6f, 0x6d, -0x51, 0x00, 0x84, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, -0x67, 0x23, 0x00, 0xf7, 0x12, 0x62, 0x79, 0x00, 0x61, 0x6e, -0x00, 0x6f, 0x72, 0x74, 0x68, 0x6f, 0x67, 0x6f, 0x6e, 0x61, -0x6c, 0x6c, 0x79, 0x00, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, -0x74, 0x65, 0x64, 0x00, 0x70, 0x61, 0x74, 0x68, 0xdc, 0x00, -0x23, 0x00, 0x61, 0x96, 0x00, 0x44, 0x73, 0x61, 0x6d, 0x65, -0x86, 0x00, 0x10, 0x77, 0xab, 0x00, 0x30, 0x62, 0x65, 0x00, -0xb3, 0x00, 0x20, 0x65, 0x64, 0xa1, 0x00, 0x00, 0x22, 0x00, -0x33, 0x6e, 0x65, 0x77, 0x21, 0x00, 0x51, 0x29, 0x2e, 0x00, -0x41, 0x73, 0xdf, 0x00, 0xf2, 0x02, 0x64, 0x6f, 0x00, 0x74, -0x68, 0x69, 0x73, 0x2c, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, -0x61, 0x6e, 0x64, 0x09, 0x00, 0x21, 0x6f, 0x66, 0x32, 0x00, -0x01, 0x48, 0x01, 0x77, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, -0x73, 0x83, 0x00, 0x2f, 0x74, 0x6f, 0xb7, 0x00, 0x01, 0x12, -0x2e, 0x89, 0x01, 0x80, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, -0x69, 0x73, 0x26, 0x00, 0x41, 0x6d, 0x61, 0x6b, 0x65, 0x2b, -0x00, 0x43, 0x77, 0x68, 0x6f, 0x6c, 0x4f, 0x00, 0x0b, 0xac, -0x00, 0x11, 0x2c, 0x3f, 0x01, 0x51, 0x73, 0x00, 0x66, 0x65, -0x77, 0x76, 0x01, 0x10, 0x73, 0x0d, 0x00, 0xb0, 0x70, 0x6f, -0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x2e, 0x00, 0x54, 0x86, -0x00, 0x00, 0x2e, 0x00, 0x01, 0xd3, 0x00, 0xd3, 0x73, 0x65, -0x74, 0x00, 0x61, 0x00, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, -0x6f, 0xd5, 0x00, 0x41, 0x75, 0x6d, 0x62, 0x65, 0x78, 0x01, -0x01, 0x3e, 0x00, 0x70, 0x2c, 0x00, 0x62, 0x61, 0x73, 0x65, -0x64, 0x1e, 0x00, 0x40, 0x72, 0x75, 0x6e, 0x6e, 0x9e, 0x00, -0xf1, 0x09, 0x69, 0x74, 0x73, 0x00, 0x6f, 0x77, 0x6e, 0x00, -0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x00, 0x73, -0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x36, 0x02, 0x65, 0x77, -0x69, 0x6e, 0x00, 0x69, 0x66, 0xea, 0x01, 0x0f, 0xb1, 0x00, -0x10, 0x02, 0x4e, 0x01, 0x73, 0x61, 0x74, 0x00, 0x6d, 0x61, -0x6e, 0x79, 0xb3, 0x00, 0x20, 0x6f, 0x72, 0xc0, 0x00, 0x20, -0x65, 0x72, 0x03, 0x01, 0x51, 0x49, 0x00, 0x73, 0x61, 0x77, -0x55, 0x01, 0x02, 0xb9, 0x00, 0xd2, 0x28, 0x77, 0x69, 0x74, -0x68, 0x00, 0x61, 0x00, 0x66, 0x69, 0x78, 0x65, 0x64, 0x52, -0x00, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x11, 0x00, 0x06, -0xc0, 0x00, 0x03, 0x85, 0x02, 0x11, 0x2c, 0x86, 0x01, 0x02, -0x1d, 0x00, 0x00, 0x5e, 0x00, 0x02, 0xef, 0x00, 0x10, 0x29, -0xba, 0x02, 0x71, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, -0x8f, 0x02, 0xf2, 0x0f, 0x69, 0x74, 0x2e, 0x61, 0x70, 0x70, -0x73, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x28, -0x6e, 0x6f, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, -0x61, 0x63, 0x63, 0x65, 0x3f, 0x01, 0x10, 0x29, 0x90, 0x00, -0x43, 0x33, 0x39, 0x2e, 0x31, 0x2a, 0x03, 0x80, 0x63, 0x6f, -0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x33, 0x03, 0x81, 0x54, -0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x1a, 0x00, 0x71, -0x2c, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xeb, 0x00, 0x43, -0x6d, 0x6f, 0x75, 0x73, 0xd4, 0x02, 0x04, 0xd8, 0x01, 0x18, -0x54, 0xf5, 0x02, 0x61, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, -0xa5, 0x00, 0x01, 0xd8, 0x02, 0x20, 0x74, 0x68, 0x65, 0x01, -0x09, 0x1d, 0x02, 0x26, 0x69, 0x74, 0x82, 0x02, 0x05, 0x3b, -0x03, 0x31, 0x65, 0x64, 0x00, 0x0a, 0x01, 0x25, 0x74, 0x68, -0x4a, 0x01, 0x03, 0x66, 0x02, 0x03, 0xf6, 0x02, 0x01, 0x84, -0x01, 0x00, 0x87, 0x00, 0x50, 0x65, 0x64, 0x2e, 0x00, 0x43, -0x09, 0x00, 0x00, 0x59, 0x00, 0x04, 0x86, 0x00, 0x0d, 0x87, -0x01, 0x4f, 0x61, 0x73, 0x00, 0x74, 0x98, 0x00, 0x00, 0xd2, -0x68, 0x61, 0x73, 0x00, 0x6e, 0x6f, 0x00, 0x65, 0x66, 0x66, -0x65, 0x63, 0x74, 0x4c, 0x01, 0x60, 0x74, 0x68, 0x65, 0x72, -0x65, 0x66, 0xd7, 0x02, 0x30, 0x64, 0x6f, 0x65, 0x1e, 0x00, -0x00, 0x2d, 0x00, 0x30, 0x75, 0x6e, 0x74, 0x43, 0x00, 0x11, -0x61, 0x64, 0x01, 0x03, 0xbb, 0x02, 0x01, 0x03, 0x02, 0x50, -0x61, 0x6c, 0x73, 0x6f, 0x00, 0x03, 0x01, 0x01, 0xa9, 0x00, -0x92, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, -0xd0, 0x02, 0x00, 0x90, 0x01, 0x14, 0x61, 0x16, 0x00, 0xe3, -0x28, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0x62, -0x6c, 0x61, 0x63, 0x6b, 0xa8, 0x00, 0x85, 0x29, 0x00, 0x61, -0x72, 0x6f, 0x75, 0x6e, 0x64, 0x40, 0x03, 0x40, 0x2e, 0x00, -0x50, 0x72, 0x90, 0x01, 0x21, 0x6e, 0x67, 0x13, 0x00, 0x60, -0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x52, 0x00, 0x02, 0x24, -0x01, 0x0e, 0x56, 0x04, 0x03, 0xc9, 0x00, 0x2f, 0x69, 0x6e, -0x2b, 0x01, 0x07, 0x57, 0x75, 0x6e, 0x64, 0x65, 0x72, 0xa1, -0x00, 0x00, 0xc0, 0x00, 0x23, 0x28, 0x41, 0x49, 0x00, 0xf2, -0x00, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, -0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x00, 0x04, 0x21, 0x73, -0x65, 0x16, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, 0x2a, 0x05, -0x01, 0xe6, 0x00, 0x60, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, -0x68, 0x03, 0x12, 0x29, 0x29, 0x02, 0x13, 0x32, 0x29, 0x02, -0x92, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, -0x2b, 0x02, 0x56, 0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, -0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x06, 0xc7, 0x04, 0xe1, -0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, -0x27, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x03, 0xa5, 0x03, 0xb0, -0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, -0x75, 0xab, 0x00, 0xf9, 0x04, 0x57, 0x69, 0x64, 0x74, 0x68, -0x2c, 0x00, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, -0x00, 0x53, 0x69, 0x7a, 0x73, 0x04, 0x01, 0x14, 0x04, 0x03, -0xe0, 0x04, 0x00, 0x30, 0x00, 0x12, 0x43, 0x1a, 0x03, 0x4c, -0x00, 0x00, 0x00, 0x4e, 0x2e, 0x03, 0x00, 0xaa, 0x01, 0x01, -0x74, 0x02, 0x05, 0x48, 0x01, 0x02, 0x74, 0x01, 0x40, 0x4d, -0x75, 0x73, 0x74, 0x80, 0x02, 0xa3, 0x61, 0x74, 0x00, 0x6c, -0x65, 0x61, 0x73, 0x74, 0x00, 0x33, 0x89, 0x03, 0x35, 0x74, -0x77, 0x6f, 0x3c, 0x00, 0x01, 0x19, 0x02, 0x50, 0x00, 0x77, -0x6f, 0x75, 0x6c, 0x31, 0x04, 0x20, 0x6c, 0x79, 0x31, 0x00, -0x93, 0x6f, 0x6e, 0x65, 0x00, 0x6c, 0x65, 0x67, 0x61, 0x6c, -0xed, 0x01, 0x20, 0x74, 0x00, 0xe7, 0x03, 0xc0, 0x73, 0x74, -0x61, 0x67, 0x65, 0x2c, 0x00, 0x68, 0x65, 0x6e, 0x63, 0x65, -0x5f, 0x02, 0x03, 0xdf, 0x05, 0x04, 0xe3, 0x04, 0x20, 0x61, -0x74, 0x87, 0x05, 0x12, 0x29, 0x6f, 0x02, 0x00, 0x1b, 0x04, -0x60, 0x6f, 0x73, 0x74, 0x00, 0x31, 0x30, 0xbc, 0x00, 0x61, -0x45, 0x78, 0x74, 0x72, 0x61, 0x20, 0x27, 0x04, 0x70, 0x20, -0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x25, 0x03, 0x00, 0xd4, -0x00, 0x02, 0x8c, 0x03, 0x01, 0xb4, 0x00, 0xa4, 0x64, 0x69, -0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x07, 0x01, -0x70, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x0b, 0x06, -0x65, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x41, 0x02, 0x06, -0x14, 0x04, 0x06, 0xaf, 0x06, 0x00, 0xda, 0x05, 0x02, 0x39, -0x01, 0x01, 0xc0, 0x01, 0x02, 0x5a, 0x02, 0x5d, 0x72, 0x75, -0x6e, 0x00, 0x61, 0xf7, 0x04, 0x00, 0xb4, 0x00, 0x85, 0x67, -0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x1b, 0x05, 0x40, -0x73, 0x6f, 0x6c, 0x75, 0xb0, 0x01, 0x05, 0x30, 0x03, 0x02, -0xb7, 0x01, 0x41, 0x76, 0x61, 0x6c, 0x75, 0x0b, 0x04, 0x01, -0xce, 0x04, 0x55, 0x66, 0x69, 0x65, 0x6c, 0x64, 0xd9, 0x03, -0x36, 0x61, 0x64, 0x64, 0x0a, 0x06, 0x42, 0x6c, 0x65, 0x6e, -0x67, 0x96, 0x06, 0x01, 0x80, 0x00, 0x25, 0x27, 0x73, 0x52, -0x00, 0x09, 0x6f, 0x00, 0x13, 0x74, 0xcd, 0x05, 0x29, 0x27, -0x73, 0xc6, 0x00, 0x43, 0x53, 0x6f, 0x00, 0x61, 0x6c, 0x00, -0xc2, 0x6f, 0x66, 0x00, 0x30, 0x00, 0x72, 0x65, 0x71, 0x75, -0x69, 0x72, 0x65, 0xa1, 0x06, 0x20, 0x74, 0x6f, 0x6e, 0x00, -0x31, 0x6a, 0x75, 0x73, 0xaf, 0x03, 0x10, 0x65, 0x28, 0x01, -0x22, 0x69, 0x65, 0xbc, 0x03, 0x04, 0x6c, 0x00, 0x60, 0x61, -0x75, 0x74, 0x6f, 0x6d, 0x61, 0x57, 0x01, 0x02, 0xe3, 0x00, -0x03, 0x87, 0x01, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x10, 0x05, -0x02, 0x5a, 0x00, 0x00, 0xa8, 0x01, 0x10, 0x73, 0x9a, 0x04, -0x00, 0x4b, 0x01, 0x12, 0x65, 0x32, 0x03, 0x42, 0x4e, 0x6f, -0x74, 0x65, 0xcc, 0x05, 0x04, 0x4b, 0x00, 0x0c, 0x2d, 0x01, -0x01, 0xee, 0x00, 0x00, 0x31, 0x04, 0x20, 0x6e, 0x65, 0x55, -0x05, 0x93, 0x61, 0x72, 0x69, 0x6c, 0x79, 0x00, 0x66, 0x69, -0x6e, 0x16, 0x06, 0x75, 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, -0x74, 0xb0, 0x06, 0x07, 0x49, 0x01, 0xf0, 0x00, 0x74, 0x68, -0x6f, 0x75, 0x67, 0x68, 0x00, 0x49, 0x00, 0x62, 0x65, 0x6c, -0x69, 0x65, 0x76, 0x6c, 0x01, 0xf0, 0x07, 0x27, 0x73, 0x00, -0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x00, 0x63, 0x6c, 0x6f, -0x73, 0x65, 0x2e, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x61, 0x11, -0x08, 0x60, 0x6c, 0x00, 0x63, 0x68, 0x61, 0x6c, 0x46, 0x01, -0x21, 0x65, 0x2c, 0xe5, 0x06, 0x01, 0x71, 0x01, 0x02, 0xb9, -0x00, 0x47, 0x74, 0x6f, 0x00, 0x30, 0x97, 0x01, 0x20, 0x72, -0x79, 0x12, 0x00, 0x01, 0x9f, 0x00, 0x04, 0xe9, 0x08, 0x00, -0x2d, 0x03, 0x81, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6c, 0x79, -0x20, 0x87, 0x06, 0x03, 0x96, 0x06, 0x32, 0x74, 0x68, 0x61, -0xc8, 0x01, 0x02, 0x31, 0x07, 0xf0, 0x00, 0x79, 0x6f, 0x75, -0x27, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x21, -0x29, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf3, 0x33, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, +0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, +0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, +0x2c, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x65, 0x64, +0x00, 0x61, 0x74, 0x00, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, +0x00, 0x69, 0x6e, 0x00, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, +0x6c, 0x65, 0x1f, 0x00, 0xf0, 0x0b, 0x73, 0x2e, 0x00, 0x49, +0x6e, 0x00, 0x65, 0x61, 0x63, 0x68, 0x00, 0x6d, 0x6f, 0x76, +0x65, 0x2c, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x63, 0x61, 0x6e, +0x00, 0x66, 0x7a, 0x00, 0xf3, 0x03, 0x2d, 0x66, 0x69, 0x6c, +0x6c, 0x00, 0x74, 0x68, 0x65, 0x00, 0x74, 0x6f, 0x70, 0x00, +0x6c, 0x65, 0x66, 0x74, 0x5f, 0x00, 0x00, 0x4a, 0x00, 0x13, +0x61, 0x43, 0x00, 0x00, 0x75, 0x00, 0x10, 0x79, 0x08, 0x00, +0xf4, 0x03, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x00, 0x28, +0x69, 0x2e, 0x65, 0x2e, 0x00, 0x65, 0x76, 0x65, 0x72, 0x79, +0x2e, 0x00, 0x10, 0x72, 0x61, 0x00, 0x91, 0x61, 0x62, 0x6c, +0x65, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x51, 0x00, 0x84, 0x73, +0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x23, 0x00, 0xf7, +0x12, 0x62, 0x79, 0x00, 0x61, 0x6e, 0x00, 0x6f, 0x72, 0x74, +0x68, 0x6f, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x00, +0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, +0x70, 0x61, 0x74, 0x68, 0xdc, 0x00, 0x23, 0x00, 0x61, 0x96, +0x00, 0x44, 0x73, 0x61, 0x6d, 0x65, 0x86, 0x00, 0x10, 0x77, +0xab, 0x00, 0x30, 0x62, 0x65, 0x00, 0xb3, 0x00, 0x20, 0x65, +0x64, 0xa1, 0x00, 0x00, 0x22, 0x00, 0x33, 0x6e, 0x65, 0x77, +0x21, 0x00, 0x51, 0x29, 0x2e, 0x00, 0x41, 0x73, 0xdf, 0x00, +0xf2, 0x02, 0x64, 0x6f, 0x00, 0x74, 0x68, 0x69, 0x73, 0x2c, +0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x61, 0x6e, 0x64, 0x09, +0x00, 0x21, 0x6f, 0x66, 0x32, 0x00, 0x01, 0x48, 0x01, 0x77, +0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x83, 0x00, 0x2f, +0x74, 0x6f, 0xb7, 0x00, 0x01, 0x12, 0x2e, 0x89, 0x01, 0x80, +0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x26, 0x00, +0x41, 0x6d, 0x61, 0x6b, 0x65, 0x2b, 0x00, 0x43, 0x77, 0x68, +0x6f, 0x6c, 0x4f, 0x00, 0x0b, 0xac, 0x00, 0x11, 0x2c, 0x3f, +0x01, 0x51, 0x73, 0x00, 0x66, 0x65, 0x77, 0x76, 0x01, 0x10, +0x73, 0x0d, 0x00, 0xb0, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, +0x6c, 0x65, 0x2e, 0x00, 0x54, 0x86, 0x00, 0x00, 0x2e, 0x00, +0x01, 0xd3, 0x00, 0xd3, 0x73, 0x65, 0x74, 0x00, 0x61, 0x00, +0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, 0x6f, 0xd5, 0x00, 0x41, +0x75, 0x6d, 0x62, 0x65, 0x78, 0x01, 0x01, 0x3e, 0x00, 0x70, +0x2c, 0x00, 0x62, 0x61, 0x73, 0x65, 0x64, 0x1e, 0x00, 0x40, +0x72, 0x75, 0x6e, 0x6e, 0x9e, 0x00, 0xf1, 0x09, 0x69, 0x74, +0x73, 0x00, 0x6f, 0x77, 0x6e, 0x00, 0x69, 0x6e, 0x74, 0x65, +0x72, 0x6e, 0x61, 0x6c, 0x00, 0x73, 0x6f, 0x6c, 0x76, 0x65, +0x72, 0x2e, 0x36, 0x02, 0x65, 0x77, 0x69, 0x6e, 0x00, 0x69, +0x66, 0xea, 0x01, 0x0f, 0xb1, 0x00, 0x10, 0x02, 0x4e, 0x01, +0x73, 0x61, 0x74, 0x00, 0x6d, 0x61, 0x6e, 0x79, 0xb3, 0x00, +0x20, 0x6f, 0x72, 0xc0, 0x00, 0x20, 0x65, 0x72, 0x03, 0x01, +0x51, 0x49, 0x00, 0x73, 0x61, 0x77, 0x55, 0x01, 0x02, 0xb9, +0x00, 0xd2, 0x28, 0x77, 0x69, 0x74, 0x68, 0x00, 0x61, 0x00, +0x66, 0x69, 0x78, 0x65, 0x64, 0x52, 0x00, 0x53, 0x73, 0x69, +0x7a, 0x65, 0x2c, 0x11, 0x00, 0x06, 0xc0, 0x00, 0x03, 0x85, +0x02, 0x11, 0x2c, 0x86, 0x01, 0x02, 0x1d, 0x00, 0x00, 0x5e, +0x00, 0x02, 0xef, 0x00, 0x10, 0x29, 0xba, 0x02, 0x71, 0x68, +0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x8f, 0x02, 0xf2, 0x0f, +0x69, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x73, 0x70, 0x6f, 0x74, +0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x28, 0x6e, 0x6f, 0x00, 0x6c, +0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x61, 0x63, 0x63, 0x65, +0x3f, 0x01, 0x10, 0x29, 0x90, 0x00, 0x43, 0x33, 0x39, 0x2e, +0x31, 0x3c, 0x03, 0xf1, 0x05, 0x63, 0x6f, 0x6e, 0x74, 0x72, +0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x00, +0x70, 0x6c, 0x61, 0x79, 0x00, 0x1a, 0x00, 0x71, 0x2c, 0x00, +0x63, 0x6c, 0x69, 0x63, 0x6b, 0xeb, 0x00, 0x43, 0x6d, 0x6f, +0x75, 0x73, 0xd4, 0x02, 0x04, 0xd8, 0x01, 0x18, 0x54, 0xf5, +0x02, 0x61, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0xa5, 0x00, +0x01, 0xd8, 0x02, 0x20, 0x74, 0x68, 0x65, 0x01, 0x09, 0x1d, +0x02, 0x26, 0x69, 0x74, 0x82, 0x02, 0x05, 0x3b, 0x03, 0x31, +0x65, 0x64, 0x00, 0x0a, 0x01, 0x25, 0x74, 0x68, 0x4a, 0x01, +0x03, 0x66, 0x02, 0x03, 0xf6, 0x02, 0x01, 0x84, 0x01, 0x00, +0x87, 0x00, 0x50, 0x65, 0x64, 0x2e, 0x00, 0x43, 0x09, 0x00, +0x00, 0x59, 0x00, 0x04, 0x86, 0x00, 0x0d, 0x87, 0x01, 0x4f, +0x61, 0x73, 0x00, 0x74, 0x98, 0x00, 0x00, 0xd2, 0x68, 0x61, +0x73, 0x00, 0x6e, 0x6f, 0x00, 0x65, 0x66, 0x66, 0x65, 0x63, +0x74, 0x4c, 0x01, 0x60, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, +0xd7, 0x02, 0x30, 0x64, 0x6f, 0x65, 0x1e, 0x00, 0x00, 0x2d, +0x00, 0x30, 0x75, 0x6e, 0x74, 0x43, 0x00, 0x11, 0x61, 0x64, +0x01, 0x03, 0xbb, 0x02, 0x01, 0x03, 0x02, 0x50, 0x61, 0x6c, +0x73, 0x6f, 0x00, 0x03, 0x01, 0x01, 0xa9, 0x00, 0x92, 0x75, +0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xd0, 0x02, +0x00, 0x90, 0x01, 0x14, 0x61, 0x16, 0x00, 0xe3, 0x28, 0x6f, +0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0x62, 0x6c, 0x61, +0x63, 0x6b, 0xa8, 0x00, 0x85, 0x29, 0x00, 0x61, 0x72, 0x6f, +0x75, 0x6e, 0x64, 0x40, 0x03, 0x40, 0x2e, 0x00, 0x50, 0x72, +0x90, 0x01, 0x21, 0x6e, 0x67, 0x13, 0x00, 0x60, 0x72, 0x65, +0x74, 0x75, 0x72, 0x6e, 0x52, 0x00, 0x02, 0x24, 0x01, 0x0e, +0x56, 0x04, 0x03, 0xc9, 0x00, 0x2f, 0x69, 0x6e, 0x2b, 0x01, +0x07, 0x57, 0x75, 0x6e, 0x64, 0x65, 0x72, 0xa1, 0x00, 0x00, +0xc0, 0x00, 0x23, 0x28, 0x41, 0x49, 0x00, 0xf2, 0x00, 0x61, +0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x65, 0x73, +0x63, 0x72, 0x69, 0x62, 0x00, 0x04, 0x21, 0x73, 0x65, 0x16, +0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, 0x2a, 0x05, 0x01, 0xe6, +0x00, 0x60, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x68, 0x03, +0x12, 0x29, 0x29, 0x02, 0x13, 0x32, 0x29, 0x02, 0x92, 0x70, +0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2b, 0x02, +0x56, 0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x41, +0x00, 0x04, 0x3c, 0x00, 0x06, 0xc7, 0x04, 0xe1, 0x60, 0x43, +0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, +0x6f, 0x70, 0x6f, 0x00, 0x03, 0xa5, 0x03, 0xb0, 0x60, 0x54, +0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xab, +0x00, 0xf9, 0x04, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, +0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0x00, 0x53, +0x69, 0x7a, 0x73, 0x04, 0x01, 0x14, 0x04, 0x03, 0xe0, 0x04, +0x00, 0x30, 0x00, 0x12, 0x43, 0x1a, 0x03, 0x4c, 0x00, 0x00, +0x00, 0x4e, 0x2e, 0x03, 0x00, 0xaa, 0x01, 0x01, 0x74, 0x02, +0x05, 0x48, 0x01, 0x02, 0x74, 0x01, 0x40, 0x4d, 0x75, 0x73, +0x74, 0x80, 0x02, 0xa3, 0x61, 0x74, 0x00, 0x6c, 0x65, 0x61, +0x73, 0x74, 0x00, 0x33, 0x89, 0x03, 0x35, 0x74, 0x77, 0x6f, +0x3c, 0x00, 0x01, 0x19, 0x02, 0x50, 0x00, 0x77, 0x6f, 0x75, +0x6c, 0x31, 0x04, 0x20, 0x6c, 0x79, 0x31, 0x00, 0x93, 0x6f, +0x6e, 0x65, 0x00, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0xed, 0x01, +0x20, 0x74, 0x00, 0xe7, 0x03, 0xc0, 0x73, 0x74, 0x61, 0x67, +0x65, 0x2c, 0x00, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x02, +0x03, 0xdf, 0x05, 0x04, 0xe3, 0x04, 0x20, 0x61, 0x74, 0x87, +0x05, 0x12, 0x29, 0x6f, 0x02, 0x00, 0x1b, 0x04, 0x60, 0x6f, +0x73, 0x74, 0x00, 0x31, 0x30, 0xbc, 0x00, 0x61, 0x45, 0x78, +0x74, 0x72, 0x61, 0x20, 0x27, 0x04, 0x70, 0x20, 0x70, 0x65, +0x72, 0x6d, 0x69, 0x74, 0x25, 0x03, 0x00, 0xd4, 0x00, 0x02, +0x8c, 0x03, 0x01, 0xb4, 0x00, 0xa4, 0x64, 0x69, 0x66, 0x66, +0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x07, 0x01, 0x70, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x0b, 0x06, 0x65, 0x69, +0x6e, 0x63, 0x72, 0x65, 0x61, 0x41, 0x02, 0x06, 0x14, 0x04, +0x06, 0xaf, 0x06, 0x00, 0xda, 0x05, 0x02, 0x39, 0x01, 0x01, +0xc0, 0x01, 0x02, 0x5a, 0x02, 0x5d, 0x72, 0x75, 0x6e, 0x00, +0x61, 0xf7, 0x04, 0x00, 0xb4, 0x00, 0x85, 0x67, 0x65, 0x6e, +0x65, 0x72, 0x61, 0x74, 0x65, 0x1b, 0x05, 0x40, 0x73, 0x6f, +0x6c, 0x75, 0xb0, 0x01, 0x05, 0x30, 0x03, 0x02, 0xb7, 0x01, +0x41, 0x76, 0x61, 0x6c, 0x75, 0x0b, 0x04, 0x01, 0xce, 0x04, +0x55, 0x66, 0x69, 0x65, 0x6c, 0x64, 0xd9, 0x03, 0x36, 0x61, +0x64, 0x64, 0x0a, 0x06, 0x42, 0x6c, 0x65, 0x6e, 0x67, 0x96, +0x06, 0x01, 0x80, 0x00, 0x25, 0x27, 0x73, 0x52, 0x00, 0x09, +0x6f, 0x00, 0x13, 0x74, 0xcd, 0x05, 0x29, 0x27, 0x73, 0xc6, +0x00, 0x43, 0x53, 0x6f, 0x00, 0x61, 0x6c, 0x00, 0xc2, 0x6f, +0x66, 0x00, 0x30, 0x00, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, +0x65, 0xa1, 0x06, 0x20, 0x74, 0x6f, 0x6e, 0x00, 0x31, 0x6a, +0x75, 0x73, 0xaf, 0x03, 0x10, 0x65, 0x28, 0x01, 0x22, 0x69, +0x65, 0xbc, 0x03, 0x04, 0x6c, 0x00, 0x60, 0x61, 0x75, 0x74, +0x6f, 0x6d, 0x61, 0x57, 0x01, 0x02, 0xe3, 0x00, 0x03, 0x87, +0x01, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x10, 0x05, 0x02, 0x5a, +0x00, 0x00, 0xa8, 0x01, 0x10, 0x73, 0x9a, 0x04, 0x00, 0x4b, +0x01, 0x12, 0x65, 0x32, 0x03, 0x42, 0x4e, 0x6f, 0x74, 0x65, +0xcc, 0x05, 0x04, 0x4b, 0x00, 0x0c, 0x2d, 0x01, 0x01, 0xee, +0x00, 0x00, 0x31, 0x04, 0x20, 0x6e, 0x65, 0x55, 0x05, 0x93, +0x61, 0x72, 0x69, 0x6c, 0x79, 0x00, 0x66, 0x69, 0x6e, 0x16, +0x06, 0x75, 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0xb0, +0x06, 0x07, 0x49, 0x01, 0xf0, 0x00, 0x74, 0x68, 0x6f, 0x75, +0x67, 0x68, 0x00, 0x49, 0x00, 0x62, 0x65, 0x6c, 0x69, 0x65, +0x76, 0x6c, 0x01, 0xf0, 0x07, 0x27, 0x73, 0x00, 0x70, 0x72, +0x65, 0x74, 0x74, 0x79, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, +0x2e, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x61, 0x11, 0x08, 0x60, +0x6c, 0x00, 0x63, 0x68, 0x61, 0x6c, 0x46, 0x01, 0x21, 0x65, +0x2c, 0xe5, 0x06, 0x01, 0x71, 0x01, 0x02, 0xb9, 0x00, 0x47, +0x74, 0x6f, 0x00, 0x30, 0x97, 0x01, 0x20, 0x72, 0x79, 0x12, +0x00, 0x01, 0x9f, 0x00, 0x04, 0xe9, 0x08, 0x00, 0x2d, 0x03, +0x81, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6c, 0x79, 0x20, 0x87, +0x06, 0x03, 0x96, 0x06, 0x32, 0x74, 0x68, 0x61, 0xc8, 0x01, +0x02, 0x31, 0x07, 0xf0, 0x00, 0x79, 0x6f, 0x75, 0x27, 0x72, +0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x21, 0x29, 0x00, }; -const unsigned short help_text_len = 2377; -const unsigned short help_text_words = 451; +const unsigned short help_text_len = 2395; +const unsigned short help_text_words = 452; const char quick_help_text[] = "Turn the grid the same colour in as few flood fills as possible."; diff --git a/apps/plugins/puzzles/help/galaxies.c b/apps/plugins/puzzles/help/galaxies.c index 3942832c52..17b0d4a945 100644 --- a/apps/plugins/puzzles/help/galaxies.c +++ b/apps/plugins/puzzles/help/galaxies.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,206 +6,206 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 132, TEXT_CENTER | C_RED }, - { 444, TEXT_CENTER | C_RED }, - { 461, TEXT_UNDERLINE }, + { 133, TEXT_CENTER | C_RED }, + { 445, TEXT_CENTER | C_RED }, { 462, TEXT_UNDERLINE }, - { 472, TEXT_UNDERLINE }, + { 463, TEXT_UNDERLINE }, + { 473, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2754 comp 1877 ratio 0.681554 level 10 saved 877 */ +/* orig 2766 comp 1876 ratio 0.678236 level 10 saved 890 */ const char help_text[] = { -0xf0, 0x41, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x38, 0x3a, 0x20, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x69, -0x65, 0x73, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, -0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x72, 0x65, 0x63, -0x74, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x67, -0x72, 0x69, 0x64, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, -0x6e, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, -0x62, 0x65, 0x72, 0x00, 0x6f, 0x66, 0x00, 0x64, 0x6f, 0x74, -0x73, 0x2e, 0x39, 0x00, 0xf4, 0x0a, 0x72, 0x00, 0x61, 0x69, -0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x70, 0x61, -0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x74, 0x68, -0x65, 0x4b, 0x00, 0x70, 0x6c, 0x65, 0x00, 0x69, 0x6e, 0x74, -0x6f, 0x49, 0x00, 0xe0, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, -0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x47, 0x00, -0xf3, 0x12, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, -0x00, 0x69, 0x6e, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x61, -0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, -0x65, 0x76, 0x65, 0x72, 0x79, 0x2d, 0x00, 0x00, 0x61, 0x00, -0xf0, 0x00, 0x31, 0x38, 0x30, 0x2d, 0x64, 0x65, 0x67, 0x72, -0x65, 0x65, 0x00, 0x72, 0x6f, 0x74, 0x61, 0x68, 0x00, 0xf5, -0x03, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x79, 0x6d, 0x6d, -0x65, 0x74, 0x72, 0x69, 0x63, 0x2c, 0x00, 0x61, 0x6e, 0xb1, -0x00, 0xd0, 0x73, 0x00, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, -0x79, 0x00, 0x6f, 0x6e, 0x65, 0xaf, 0x00, 0x60, 0x00, 0x77, -0x68, 0x69, 0x63, 0x68, 0x49, 0x00, 0x40, 0x6c, 0x6f, 0x63, -0x61, 0x88, 0x00, 0xd1, 0x61, 0x74, 0x00, 0x69, 0x74, 0x73, -0x00, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x8e, 0x00, 0x02, -0x4a, 0x00, 0xf0, 0x00, 0x79, 0x2e, 0x00, 0x00, 0x00, 0x54, -0x6f, 0x00, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x00, 0x79, 0xe4, -0x00, 0x40, 0x73, 0x6f, 0x6c, 0x75, 0x71, 0x00, 0x10, 0x2c, -0x0f, 0x00, 0xf1, 0x02, 0x00, 0x64, 0x72, 0x61, 0x77, 0x00, -0x6c, 0x69, 0x6e, 0x65, 0x73, 0x00, 0x61, 0x6c, 0x6f, 0x6e, -0x67, 0xef, 0x00, 0x01, 0x2e, 0x01, 0x41, 0x65, 0x64, 0x67, -0x65, 0x0b, 0x01, 0x41, 0x6d, 0x61, 0x72, 0x6b, 0x17, 0x00, -0x91, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, 0x65, -0xf0, 0x00, 0x02, 0x18, 0x01, 0x01, 0xff, 0x00, 0xc0, 0x2e, -0x00, 0x54, 0x68, 0x65, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, -0x65, 0x96, 0x00, 0xc2, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, -0x74, 0x65, 0x00, 0x77, 0x68, 0x65, 0x41, 0x01, 0x00, 0x44, -0x00, 0x23, 0x65, 0x64, 0x69, 0x00, 0x26, 0x6f, 0x6e, 0x66, -0x00, 0xc0, 0x61, 0x72, 0x65, 0x00, 0x70, 0x72, 0x65, 0x63, -0x69, 0x73, 0x65, 0x6c, 0x2d, 0x01, 0x32, 0x6f, 0x73, 0x65, -0x33, 0x01, 0xc4, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, -0x65, 0x00, 0x74, 0x77, 0x6f, 0x5c, 0x01, 0x30, 0x00, 0x62, -0x65, 0xa4, 0x00, 0x10, 0x69, 0xa7, 0x00, 0xb6, 0x6f, 0x00, -0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x87, -0x00, 0x64, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x8a, 0x00, -0x90, 0x77, 0x61, 0x73, 0x00, 0x69, 0x6e, 0x76, 0x65, 0x6e, -0x22, 0x01, 0xf1, 0x06, 0x62, 0x79, 0x00, 0x4e, 0x69, 0x6b, -0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x31, 0x33, 0x5d, 0x2c, 0x00, -0x75, 0x6e, 0x64, 0x65, 0x72, 0x88, 0x00, 0x80, 0x6e, 0x61, -0x6d, 0x65, 0x00, 0x60, 0x54, 0x65, 0x6c, 0x01, 0x71, 0x00, -0x53, 0x68, 0x6f, 0x77, 0x27, 0x3b, 0x4d, 0x01, 0x01, 0x18, -0x00, 0x02, 0xce, 0x00, 0x30, 0x6d, 0x6f, 0x6e, 0x9e, 0x00, -0x51, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x70, 0x01, 0x01, 0x07, -0x02, 0xf4, 0x04, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, -0x00, 0x61, 0x73, 0x00, 0x60, 0x53, 0x70, 0x69, 0x72, 0x61, -0x6c, 0x00, 0x8b, 0x02, 0x10, 0x27, 0x8c, 0x00, 0x04, 0x0d, -0x00, 0x01, 0x89, 0x00, 0x00, 0xcc, 0x01, 0x40, 0x72, 0x69, -0x62, 0x75, 0x3e, 0x00, 0x51, 0x74, 0x6f, 0x00, 0x74, 0x68, -0x5a, 0x00, 0x41, 0x6c, 0x6c, 0x65, 0x63, 0x66, 0x02, 0xe1, -0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, -0x61, 0x72, 0x76, 0x65, 0xb7, 0x01, 0x00, 0xa8, 0x00, 0xd1, -0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, -0x77, 0x2e, 0x6e, 0xbf, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, -0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0xe6, 0x00, 0xf6, 0x10, -0x73, 0x2f, 0x61, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x6f, 0x6d, -0x69, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x2e, -0x68, 0x74, 0x6d, 0x6c, 0x00, 0x00, 0x00, 0x32, 0x38, 0x2e, -0x31, 0x1d, 0x03, 0x01, 0x81, 0x00, 0x21, 0x6f, 0x6c, 0x26, -0x03, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, -0x63, 0x6b, 0x8d, 0x01, 0x32, 0x61, 0x6e, 0x79, 0x8d, 0x01, -0x00, 0x9f, 0x01, 0x01, 0x5a, 0x01, 0x00, 0x15, 0x02, 0x21, -0x61, 0x6e, 0x03, 0x02, 0x21, 0x00, 0x69, 0xeb, 0x01, 0x10, -0x72, 0x0b, 0x01, 0x31, 0x6e, 0x27, 0x74, 0x83, 0x02, 0xb0, -0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2c, 0x00, 0x6f, -0x72, 0x2f, 0x00, 0x61, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, -0x1a, 0x00, 0x07, 0x2d, 0x00, 0x30, 0x2e, 0x00, 0x57, 0xfe, -0x01, 0x00, 0x65, 0x02, 0x50, 0x63, 0x72, 0x65, 0x61, 0x74, -0x93, 0x03, 0x54, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x08, 0x03, -0x10, 0x28, 0x31, 0x00, 0x05, 0xca, 0x02, 0x7f, 0x63, 0x6c, -0x6f, 0x73, 0x65, 0x64, 0x2c, 0xf4, 0x02, 0x06, 0x1b, 0x2c, -0x38, 0x03, 0x05, 0x2b, 0x03, 0x62, 0x00, 0x61, 0x62, 0x6f, -0x75, 0x74, 0x35, 0x02, 0x01, 0x28, 0x00, 0x09, 0x3a, 0x03, -0x50, 0x6e, 0x6f, 0x00, 0x65, 0x78, 0xb9, 0x01, 0x43, 0x65, -0x6f, 0x75, 0x73, 0xd4, 0x02, 0x71, 0x62, 0x65, 0x74, 0x77, -0x65, 0x65, 0x6e, 0x5a, 0x02, 0x21, 0x6f, 0x66, 0xec, 0x01, -0x34, 0x6f, 0x77, 0x6e, 0x65, 0x02, 0xf1, 0x07, 0x29, 0x2c, -0x00, 0x69, 0x74, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x62, -0x65, 0x00, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, -0x65, 0x03, 0x80, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, -0x63, 0xac, 0x03, 0x6a, 0x3b, 0x00, 0x73, 0x6f, 0x00, 0x79, -0x35, 0x04, 0x01, 0x79, 0x04, 0x20, 0x74, 0x68, 0xd6, 0x00, -0x23, 0x6f, 0x6c, 0xe1, 0x02, 0x08, 0x41, 0x00, 0x22, 0x69, -0x6e, 0xa7, 0x00, 0x21, 0x77, 0x61, 0xe1, 0x01, 0x30, 0x44, -0x75, 0x72, 0xcb, 0x02, 0x72, 0x73, 0x6f, 0x6c, 0x76, 0x69, -0x6e, 0x67, 0x90, 0x03, 0x10, 0x6d, 0x2b, 0x00, 0x52, 0x00, -0x6b, 0x6e, 0x6f, 0x77, 0x2b, 0x00, 0x12, 0x61, 0x8a, 0x04, -0x16, 0x63, 0xc6, 0x04, 0x02, 0xa7, 0x00, 0x03, 0x0b, 0x03, -0x01, 0x77, 0x00, 0xa2, 0x61, 0x00, 0x73, 0x70, 0x65, 0x63, -0x69, 0x66, 0x69, 0x63, 0x01, 0x01, 0x70, 0x62, 0x75, 0x74, -0x00, 0x6e, 0x6f, 0x74, 0xbf, 0x00, 0x22, 0x73, 0x75, 0x0f, -0x04, 0x11, 0x77, 0x95, 0x01, 0x00, 0x9b, 0x00, 0x02, 0x03, -0x01, 0x21, 0x67, 0x6f, 0x27, 0x01, 0x02, 0x7e, 0x01, 0x10, -0x6f, 0xb3, 0x01, 0x05, 0x64, 0x03, 0x00, 0x5d, 0x00, 0x06, -0xe1, 0x04, 0x01, 0xab, 0x02, 0x01, 0x81, 0x01, 0x71, 0x2e, -0x00, 0x49, 0x6e, 0x00, 0x6f, 0x72, 0x36, 0x03, 0x05, 0x15, -0x04, 0x23, 0x69, 0x73, 0x07, 0x01, 0x30, 0x00, 0x64, 0x6f, -0x1e, 0x02, 0x72, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x2c, -0xf6, 0x01, 0x40, 0x61, 0x6e, 0x00, 0x72, 0xcf, 0x00, 0x06, -0x6a, 0x02, 0x03, 0x4b, 0x00, 0x01, 0x7c, 0x00, 0x53, 0x64, -0x72, 0x61, 0x67, 0x2c, 0x82, 0x00, 0x01, 0x6e, 0x01, 0x04, -0x26, 0x02, 0x72, 0x6e, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, -0x34, 0x04, 0x71, 0x72, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, -0xb4, 0x05, 0x16, 0x74, 0x8b, 0x00, 0x42, 0x44, 0x72, 0x6f, -0x70, 0x21, 0x01, 0x44, 0x69, 0x6e, 0x00, 0x61, 0x14, 0x01, -0x22, 0x6f, 0x66, 0x92, 0x01, 0x61, 0x63, 0x68, 0x6f, 0x69, -0x63, 0x65, 0x66, 0x00, 0x04, 0xcb, 0x01, 0x61, 0x72, 0x65, -0x6d, 0x69, 0x6e, 0x64, 0x98, 0x00, 0x02, 0x73, 0x00, 0x20, -0x64, 0x6f, 0x33, 0x05, 0x91, 0x27, 0x73, 0x00, 0x61, 0x73, -0x73, 0x6f, 0x63, 0x69, 0xd6, 0x03, 0x41, 0x77, 0x69, 0x74, -0x68, 0x0a, 0x06, 0x01, 0xbc, 0x00, 0x4c, 0x61, 0x6c, 0x73, -0x6f, 0xc1, 0x00, 0x42, 0x65, 0x78, 0x69, 0x73, 0x8d, 0x00, -0x00, 0xa3, 0x00, 0x02, 0x2a, 0x06, 0x21, 0x69, 0x63, 0x1f, -0x05, 0x41, 0x6d, 0x00, 0x75, 0x70, 0x73, 0x00, 0x01, 0x0d, -0x03, 0x00, 0x11, 0x00, 0x01, 0x20, 0x03, 0x20, 0x64, 0x65, -0x9f, 0x03, 0x12, 0x79, 0x22, 0x00, 0x81, 0x62, 0x79, 0x00, -0x64, 0x72, 0x6f, 0x70, 0x70, 0xc2, 0x04, 0x00, 0x11, 0x00, -0x35, 0x6f, 0x66, 0x66, 0x96, 0x01, 0x04, 0x55, 0x05, 0x00, -0xe6, 0x01, 0xa1, 0x2e, 0x00, 0x28, 0x41, 0x6c, 0x73, 0x6f, -0x2c, 0x00, 0x69, 0xd3, 0x00, 0x31, 0x27, 0x72, 0x65, 0xd2, -0x01, 0x01, 0xcf, 0x01, 0x06, 0xc0, 0x00, 0x05, 0x2b, 0x01, -0x28, 0x69, 0x73, 0x27, 0x01, 0x06, 0x7f, 0x01, 0x01, 0x9c, -0x00, 0x29, 0x69, 0x74, 0x9a, 0x00, 0x50, 0x69, 0x74, 0x00, -0x61, 0x72, 0xca, 0x05, 0x02, 0xc7, 0x01, 0x11, 0x6b, 0x12, -0x00, 0xa3, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x65, 0x72, 0x2e, -0x00, 0x49, 0x30, 0x01, 0x60, 0x73, 0x77, 0x69, 0x76, 0x65, -0x6c, 0x09, 0x02, 0x40, 0x73, 0x74, 0x61, 0x6e, 0x88, 0x03, -0x24, 0x61, 0x73, 0x31, 0x06, 0x50, 0x67, 0x00, 0x69, 0x74, -0x2c, 0x3e, 0x00, 0x42, 0x73, 0x74, 0x61, 0x79, 0x79, 0x00, -0x06, 0x83, 0x06, 0x21, 0x70, 0x61, 0x93, 0x05, 0x00, 0xa6, -0x01, 0x3a, 0x29, 0x00, 0x00, 0x4d, 0x01, 0x22, 0x75, 0x73, -0x84, 0x02, 0xa2, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, -0x6b, 0x65, 0x79, 0x61, 0x06, 0x00, 0x97, 0x00, 0x04, 0x94, -0x00, 0x04, 0x19, 0x06, 0x05, 0x8f, 0x02, 0x13, 0x6e, 0x37, -0x06, 0x83, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x69, -0xa4, 0x06, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, -0x00, 0x02, 0x66, 0x06, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x00, -0x61, 0xc8, 0x04, 0x01, 0xc7, 0x00, 0x01, 0xca, 0x04, 0x22, -0x6f, 0x72, 0xe0, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x6a, 0x01, -0x10, 0x2c, 0xcd, 0x00, 0x5f, 0x61, 0x62, 0x6f, 0x76, 0x65, -0x55, 0x00, 0x13, 0x23, 0x64, 0x6f, 0x16, 0x01, 0x01, 0x50, -0x01, 0x25, 0x75, 0x70, 0x79, 0x01, 0x01, 0x06, 0x01, 0x22, -0x62, 0x65, 0xd5, 0x01, 0x22, 0x65, 0x64, 0x4f, 0x06, 0x8c, -0x65, 0x78, 0x74, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x00, -0x00, 0xa5, 0x01, 0x00, 0x6d, 0x00, 0x33, 0x65, 0x64, 0x3b, -0xff, 0x05, 0x04, 0x18, 0x01, 0x20, 0x62, 0x65, 0x1b, 0x01, -0x15, 0x64, 0x0c, 0x01, 0x0c, 0x66, 0x02, 0x02, 0x1c, 0x01, -0x12, 0x2c, 0x69, 0x05, 0x05, 0x3c, 0x02, 0x0e, 0x4d, 0x02, -0x13, 0x6e, 0xac, 0x00, 0x52, 0x6f, 0x72, 0x00, 0x61, 0x6e, -0xd6, 0x03, 0x01, 0x42, 0x00, 0x00, 0x6d, 0x04, 0x41, 0x28, -0x41, 0x6c, 0x6c, 0x92, 0x00, 0x11, 0x61, 0x71, 0x06, 0x10, -0x73, 0x99, 0x02, 0x42, 0x63, 0x72, 0x69, 0x62, 0x97, 0x04, -0x13, 0x73, 0x87, 0x06, 0x31, 0x32, 0x2e, 0x31, 0x01, 0x04, -0x01, 0x97, 0x00, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, -0x62, 0x6c, 0x65, 0x2e, 0x29, 0x4e, 0x06, 0x16, 0x32, 0x4e, -0x06, 0x00, 0x9d, 0x07, 0x71, 0x6d, 0x65, 0x74, 0x65, 0x72, -0x73, 0x20, 0x76, 0x07, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, -0x00, 0x02, 0x44, 0x00, 0x04, 0x3f, 0x00, 0x51, 0x00, 0x66, -0x72, 0x6f, 0x6d, 0x7c, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, -0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, -0x72, 0x00, 0x03, 0x16, 0x04, 0xb0, 0x60, 0x54, 0x79, 0x70, -0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xae, 0x00, 0x91, -0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x0f, -0x05, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x20, 0x03, 0x01, -0xdf, 0x01, 0x15, 0x69, 0xac, 0x05, 0x01, 0x46, 0x05, 0x30, -0x69, 0x66, 0x66, 0x20, 0x05, 0x63, 0x74, 0x79, 0x00, 0x00, -0x00, 0x43, 0xe5, 0x06, 0x02, 0x2a, 0x04, 0x06, 0x1a, 0x00, -0x04, 0x5b, 0x03, 0x41, 0x65, 0x6e, 0x65, 0x72, 0xeb, 0x03, -0x02, 0x3d, 0x07, 0x57, 0x2e, 0x00, 0x4d, 0x6f, 0x72, 0x29, -0x00, 0x13, 0x00, 0x54, 0x07, 0xa0, 0x00, 0x72, 0x65, 0x71, -0x75, 0x69, 0x72, 0x65, 0x00, 0x6d, 0x1f, 0x00, 0x02, 0xcf, -0x08, 0x62, 0x78, 0x00, 0x64, 0x65, 0x64, 0x75, 0x3d, 0x01, -0x02, 0x65, 0x06, 0x01, 0xb8, 0x00, 0x80, 0x55, 0x6e, 0x72, -0x65, 0x61, 0x73, 0x6f, 0x6e, 0xe9, 0x00, 0x18, 0x27, 0x73, -0x00, 0x20, 0x6c, 0x65, 0x41, 0x03, 0x35, 0x6d, 0x61, 0x79, -0x4d, 0x00, 0xe0, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, -0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x00, +0x65, 0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf0, 0x2c, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, +0x65, 0x00, 0x61, 0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, +0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x67, 0x72, 0x69, 0x64, +0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, +0x67, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, +0x00, 0x6f, 0x66, 0x00, 0x64, 0x6f, 0x74, 0x73, 0x2e, 0x39, +0x00, 0xf4, 0x0a, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, +0x73, 0x00, 0x74, 0x6f, 0x00, 0x70, 0x61, 0x72, 0x74, 0x69, +0x74, 0x69, 0x6f, 0x6e, 0x00, 0x74, 0x68, 0x65, 0x4b, 0x00, +0x70, 0x6c, 0x65, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x49, 0x00, +0xe0, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x72, 0x65, +0x67, 0x69, 0x6f, 0x6e, 0x73, 0x47, 0x00, 0xf3, 0x12, 0x73, +0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x69, 0x6e, +0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x61, 0x00, 0x77, 0x61, +0x79, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x65, 0x76, 0x65, +0x72, 0x79, 0x2d, 0x00, 0x00, 0x61, 0x00, 0xf0, 0x00, 0x31, +0x38, 0x30, 0x2d, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x00, +0x72, 0x6f, 0x74, 0x61, 0x68, 0x00, 0xf5, 0x03, 0x61, 0x6c, +0x6c, 0x79, 0x00, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, +0x69, 0x63, 0x2c, 0x00, 0x61, 0x6e, 0xb1, 0x00, 0xd0, 0x73, +0x00, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x00, 0x6f, +0x6e, 0x65, 0xaf, 0x00, 0x60, 0x00, 0x77, 0x68, 0x69, 0x63, +0x68, 0x49, 0x00, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x88, 0x00, +0xd1, 0x61, 0x74, 0x00, 0x69, 0x74, 0x73, 0x00, 0x63, 0x65, +0x6e, 0x74, 0x72, 0x65, 0x8e, 0x00, 0x02, 0x4a, 0x00, 0xf0, +0x00, 0x79, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x00, 0x65, +0x6e, 0x74, 0x65, 0x72, 0x00, 0x79, 0xe4, 0x00, 0x40, 0x73, +0x6f, 0x6c, 0x75, 0x71, 0x00, 0x10, 0x2c, 0x0f, 0x00, 0xf1, +0x02, 0x00, 0x64, 0x72, 0x61, 0x77, 0x00, 0x6c, 0x69, 0x6e, +0x65, 0x73, 0x00, 0x61, 0x6c, 0x6f, 0x6e, 0x67, 0xef, 0x00, +0x01, 0x2e, 0x01, 0x41, 0x65, 0x64, 0x67, 0x65, 0x0b, 0x01, +0x41, 0x6d, 0x61, 0x72, 0x6b, 0x17, 0x00, 0x91, 0x62, 0x6f, +0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, 0x65, 0xf0, 0x00, 0x02, +0x18, 0x01, 0x01, 0xff, 0x00, 0xc0, 0x2e, 0x00, 0x54, 0x68, +0x65, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x96, 0x00, +0xc2, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, +0x77, 0x68, 0x65, 0x41, 0x01, 0x00, 0x44, 0x00, 0x23, 0x65, +0x64, 0x69, 0x00, 0x26, 0x6f, 0x6e, 0x66, 0x00, 0xc0, 0x61, +0x72, 0x65, 0x00, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, +0x6c, 0x2d, 0x01, 0x32, 0x6f, 0x73, 0x65, 0x33, 0x01, 0xc4, +0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x00, 0x74, +0x77, 0x6f, 0x5c, 0x01, 0x30, 0x00, 0x62, 0x65, 0xa4, 0x00, +0x10, 0x69, 0xa7, 0x00, 0xb6, 0x6f, 0x00, 0x64, 0x69, 0x66, +0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x87, 0x00, 0x64, 0x00, +0x00, 0x54, 0x68, 0x69, 0x73, 0x8a, 0x00, 0x90, 0x77, 0x61, +0x73, 0x00, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x22, 0x01, 0xf1, +0x06, 0x62, 0x79, 0x00, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, +0x00, 0x5b, 0x31, 0x33, 0x5d, 0x2c, 0x00, 0x75, 0x6e, 0x64, +0x65, 0x72, 0x88, 0x00, 0x80, 0x6e, 0x61, 0x6d, 0x65, 0x00, +0x60, 0x54, 0x65, 0x6c, 0x01, 0x71, 0x00, 0x53, 0x68, 0x6f, +0x77, 0x27, 0x3b, 0x4d, 0x01, 0x01, 0x18, 0x00, 0x02, 0xce, +0x00, 0x30, 0x6d, 0x6f, 0x6e, 0x9e, 0x00, 0x51, 0x72, 0x61, +0x6e, 0x73, 0x6c, 0x70, 0x01, 0x01, 0x07, 0x02, 0xf4, 0x04, +0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x00, 0x61, 0x73, +0x00, 0x60, 0x53, 0x70, 0x69, 0x72, 0x61, 0x6c, 0x00, 0xa0, +0x02, 0x10, 0x27, 0x8c, 0x00, 0x04, 0x0d, 0x00, 0x01, 0x89, +0x00, 0x00, 0xcc, 0x01, 0x40, 0x72, 0x69, 0x62, 0x75, 0x3e, +0x00, 0x51, 0x74, 0x6f, 0x00, 0x74, 0x68, 0x5a, 0x00, 0x41, +0x6c, 0x6c, 0x65, 0x63, 0x66, 0x02, 0xe1, 0x62, 0x79, 0x00, +0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, +0x65, 0xb7, 0x01, 0x00, 0xa8, 0x00, 0xe1, 0x00, 0x68, 0x74, +0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, +0x6e, 0xc0, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, +0x2f, 0x65, 0x6e, 0x2f, 0xe7, 0x00, 0x31, 0x73, 0x2f, 0x74, +0xbb, 0x00, 0xd6, 0x5f, 0x73, 0x68, 0x6f, 0x77, 0x2f, 0x00, +0x00, 0x00, 0x32, 0x38, 0x2e, 0x31, 0x29, 0x03, 0x01, 0x78, +0x00, 0xf0, 0x02, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, +0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, +0x84, 0x01, 0x32, 0x61, 0x6e, 0x79, 0x84, 0x01, 0x00, 0x96, +0x01, 0x01, 0x51, 0x01, 0x00, 0x0c, 0x02, 0x21, 0x61, 0x6e, +0xfa, 0x01, 0x21, 0x00, 0x69, 0xe2, 0x01, 0x10, 0x72, 0x02, +0x01, 0x31, 0x6e, 0x27, 0x74, 0x7a, 0x02, 0xb0, 0x61, 0x6c, +0x72, 0x65, 0x61, 0x64, 0x79, 0x2c, 0x00, 0x6f, 0x72, 0x2f, +0x00, 0x61, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x00, +0x07, 0x2d, 0x00, 0x30, 0x2e, 0x00, 0x57, 0xf5, 0x01, 0x00, +0x5c, 0x02, 0x50, 0x63, 0x72, 0x65, 0x61, 0x74, 0x8a, 0x03, +0x54, 0x76, 0x61, 0x6c, 0x69, 0x64, 0xff, 0x02, 0x10, 0x28, +0x31, 0x00, 0x05, 0xc1, 0x02, 0x7f, 0x63, 0x6c, 0x6f, 0x73, +0x65, 0x64, 0x2c, 0xeb, 0x02, 0x06, 0x1b, 0x2c, 0x2f, 0x03, +0x05, 0x22, 0x03, 0x62, 0x00, 0x61, 0x62, 0x6f, 0x75, 0x74, +0x2c, 0x02, 0x01, 0x28, 0x00, 0x09, 0x31, 0x03, 0x50, 0x6e, +0x6f, 0x00, 0x65, 0x78, 0xb0, 0x01, 0x43, 0x65, 0x6f, 0x75, +0x73, 0xcb, 0x02, 0x71, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, +0x6e, 0x51, 0x02, 0x21, 0x6f, 0x66, 0xe3, 0x01, 0x34, 0x6f, +0x77, 0x6e, 0x5c, 0x02, 0xf1, 0x07, 0x29, 0x2c, 0x00, 0x69, +0x74, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x62, 0x65, 0x00, +0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x5c, 0x03, +0x80, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0xa3, +0x03, 0x6a, 0x3b, 0x00, 0x73, 0x6f, 0x00, 0x79, 0x2c, 0x04, +0x01, 0x70, 0x04, 0x20, 0x74, 0x68, 0xd6, 0x00, 0x23, 0x6f, +0x6c, 0xd8, 0x02, 0x08, 0x41, 0x00, 0x22, 0x69, 0x6e, 0xa7, +0x00, 0x21, 0x77, 0x61, 0xd8, 0x01, 0x30, 0x44, 0x75, 0x72, +0xc2, 0x02, 0x72, 0x73, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, +0x87, 0x03, 0x10, 0x6d, 0x2b, 0x00, 0x52, 0x00, 0x6b, 0x6e, +0x6f, 0x77, 0x2b, 0x00, 0x12, 0x61, 0x81, 0x04, 0x16, 0x63, +0xbd, 0x04, 0x02, 0xa7, 0x00, 0x03, 0x02, 0x03, 0x01, 0x77, +0x00, 0xa2, 0x61, 0x00, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, +0x69, 0x63, 0x01, 0x01, 0x70, 0x62, 0x75, 0x74, 0x00, 0x6e, +0x6f, 0x74, 0xbf, 0x00, 0x22, 0x73, 0x75, 0x06, 0x04, 0x11, +0x77, 0x95, 0x01, 0x00, 0x9b, 0x00, 0x02, 0x03, 0x01, 0x21, +0x67, 0x6f, 0x27, 0x01, 0x02, 0x7e, 0x01, 0x10, 0x6f, 0xb3, +0x01, 0x05, 0x5b, 0x03, 0x00, 0x5d, 0x00, 0x06, 0xd8, 0x04, +0x01, 0xa2, 0x02, 0x01, 0x81, 0x01, 0x71, 0x2e, 0x00, 0x49, +0x6e, 0x00, 0x6f, 0x72, 0x2d, 0x03, 0x05, 0x0c, 0x04, 0x23, +0x69, 0x73, 0x07, 0x01, 0x30, 0x00, 0x64, 0x6f, 0x1e, 0x02, +0x72, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x2c, 0xf6, 0x01, +0x40, 0x61, 0x6e, 0x00, 0x72, 0xcf, 0x00, 0x06, 0x6a, 0x02, +0x03, 0x4b, 0x00, 0x01, 0x7c, 0x00, 0x53, 0x64, 0x72, 0x61, +0x67, 0x2c, 0x82, 0x00, 0x01, 0x6e, 0x01, 0x04, 0x26, 0x02, +0x72, 0x6e, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2b, 0x04, +0x71, 0x72, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0xab, 0x05, +0x16, 0x74, 0x8b, 0x00, 0x42, 0x44, 0x72, 0x6f, 0x70, 0x21, +0x01, 0x44, 0x69, 0x6e, 0x00, 0x61, 0x14, 0x01, 0x22, 0x6f, +0x66, 0x92, 0x01, 0x61, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, +0x66, 0x00, 0x04, 0xcb, 0x01, 0x61, 0x72, 0x65, 0x6d, 0x69, +0x6e, 0x64, 0x98, 0x00, 0x02, 0x73, 0x00, 0x20, 0x64, 0x6f, +0x2a, 0x05, 0x91, 0x27, 0x73, 0x00, 0x61, 0x73, 0x73, 0x6f, +0x63, 0x69, 0xcd, 0x03, 0x41, 0x77, 0x69, 0x74, 0x68, 0x01, +0x06, 0x01, 0xbc, 0x00, 0x4c, 0x61, 0x6c, 0x73, 0x6f, 0xc1, +0x00, 0x42, 0x65, 0x78, 0x69, 0x73, 0x8d, 0x00, 0x00, 0xa3, +0x00, 0x02, 0x21, 0x06, 0x21, 0x69, 0x63, 0x16, 0x05, 0x41, +0x6d, 0x00, 0x75, 0x70, 0x73, 0x00, 0x01, 0x0d, 0x03, 0x00, +0x11, 0x00, 0x01, 0x20, 0x03, 0x72, 0x64, 0x65, 0x73, 0x74, +0x72, 0x6f, 0x79, 0x22, 0x00, 0x81, 0x62, 0x79, 0x00, 0x64, +0x72, 0x6f, 0x70, 0x70, 0xb9, 0x04, 0x00, 0x11, 0x00, 0x35, +0x6f, 0x66, 0x66, 0x96, 0x01, 0x04, 0x4c, 0x05, 0x00, 0xe6, +0x01, 0xa1, 0x2e, 0x00, 0x28, 0x41, 0x6c, 0x73, 0x6f, 0x2c, +0x00, 0x69, 0xd3, 0x00, 0x31, 0x27, 0x72, 0x65, 0xd2, 0x01, +0x01, 0xcf, 0x01, 0x06, 0xc0, 0x00, 0x05, 0x2b, 0x01, 0x28, +0x69, 0x73, 0x27, 0x01, 0x06, 0x7f, 0x01, 0x01, 0x9c, 0x00, +0x29, 0x69, 0x74, 0x9a, 0x00, 0x50, 0x69, 0x74, 0x00, 0x61, +0x72, 0xc1, 0x05, 0x02, 0xc7, 0x01, 0x11, 0x6b, 0x12, 0x00, +0xa3, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x65, 0x72, 0x2e, 0x00, +0x49, 0x30, 0x01, 0x60, 0x73, 0x77, 0x69, 0x76, 0x65, 0x6c, +0x09, 0x02, 0x40, 0x73, 0x74, 0x61, 0x6e, 0x88, 0x03, 0x24, +0x61, 0x73, 0x28, 0x06, 0x50, 0x67, 0x00, 0x69, 0x74, 0x2c, +0x3e, 0x00, 0x42, 0x73, 0x74, 0x61, 0x79, 0x79, 0x00, 0x06, +0x7a, 0x06, 0x21, 0x70, 0x61, 0x8a, 0x05, 0x00, 0xa6, 0x01, +0x3a, 0x29, 0x00, 0x00, 0x4d, 0x01, 0x22, 0x75, 0x73, 0x84, +0x02, 0xa2, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, +0x65, 0x79, 0x58, 0x06, 0x00, 0x97, 0x00, 0x04, 0x94, 0x00, +0x04, 0x10, 0x06, 0x05, 0x8f, 0x02, 0x13, 0x6e, 0x2e, 0x06, +0x83, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x69, 0x9b, +0x06, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x00, +0x02, 0x5d, 0x06, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x61, +0xc8, 0x04, 0x01, 0xc7, 0x00, 0x01, 0xca, 0x04, 0x22, 0x6f, +0x72, 0xe0, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x6a, 0x01, 0x10, +0x2c, 0xcd, 0x00, 0x5f, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x55, +0x00, 0x13, 0x23, 0x64, 0x6f, 0x16, 0x01, 0x01, 0x50, 0x01, +0x25, 0x75, 0x70, 0x79, 0x01, 0x01, 0x06, 0x01, 0x22, 0x62, +0x65, 0xd5, 0x01, 0x22, 0x65, 0x64, 0x46, 0x06, 0x8c, 0x65, +0x78, 0x74, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x00, 0x00, +0xa5, 0x01, 0x00, 0x6d, 0x00, 0x33, 0x65, 0x64, 0x3b, 0xf6, +0x05, 0x04, 0x18, 0x01, 0x20, 0x62, 0x65, 0x1b, 0x01, 0x15, +0x64, 0x0c, 0x01, 0x0c, 0x66, 0x02, 0x02, 0x1c, 0x01, 0x12, +0x2c, 0x69, 0x05, 0x05, 0x3c, 0x02, 0x0e, 0x4d, 0x02, 0x13, +0x6e, 0xac, 0x00, 0x52, 0x6f, 0x72, 0x00, 0x61, 0x6e, 0xd6, +0x03, 0x01, 0x42, 0x00, 0x00, 0x6d, 0x04, 0x41, 0x28, 0x41, +0x6c, 0x6c, 0x92, 0x00, 0x11, 0x61, 0x68, 0x06, 0x10, 0x73, +0x99, 0x02, 0x42, 0x63, 0x72, 0x69, 0x62, 0x97, 0x04, 0x13, +0x73, 0x7e, 0x06, 0x31, 0x32, 0x2e, 0x31, 0x01, 0x04, 0x01, +0x97, 0x00, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, +0x6c, 0x65, 0x2e, 0x29, 0x4e, 0x06, 0x16, 0x32, 0x4e, 0x06, +0x00, 0x94, 0x07, 0x71, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, +0x20, 0x6d, 0x07, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, +0x02, 0x44, 0x00, 0x04, 0x3f, 0x00, 0x51, 0x00, 0x66, 0x72, +0x6f, 0x6d, 0x7c, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, +0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x72, +0x00, 0x03, 0x16, 0x04, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, +0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xae, 0x00, 0x91, 0x57, +0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x0f, 0x05, +0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x20, 0x03, 0x01, 0xdf, +0x01, 0x15, 0x69, 0xac, 0x05, 0x01, 0x46, 0x05, 0x30, 0x69, +0x66, 0x66, 0x20, 0x05, 0x63, 0x74, 0x79, 0x00, 0x00, 0x00, +0x43, 0xe5, 0x06, 0x02, 0x2a, 0x04, 0x06, 0x1a, 0x00, 0x04, +0x5b, 0x03, 0x41, 0x65, 0x6e, 0x65, 0x72, 0xeb, 0x03, 0x02, +0x33, 0x07, 0x57, 0x2e, 0x00, 0x4d, 0x6f, 0x72, 0x29, 0x00, +0x13, 0x00, 0x4a, 0x07, 0xa0, 0x00, 0x72, 0x65, 0x71, 0x75, +0x69, 0x72, 0x65, 0x00, 0x6d, 0x1f, 0x00, 0x02, 0xc6, 0x08, +0x62, 0x78, 0x00, 0x64, 0x65, 0x64, 0x75, 0x3d, 0x01, 0x02, +0x65, 0x06, 0x01, 0xb8, 0x00, 0x80, 0x55, 0x6e, 0x72, 0x65, +0x61, 0x73, 0x6f, 0x6e, 0xe9, 0x00, 0x18, 0x27, 0x73, 0x00, +0x20, 0x6c, 0x65, 0x41, 0x03, 0x35, 0x6d, 0x61, 0x79, 0x4d, +0x00, 0xe0, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, +0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x00, }; -const unsigned short help_text_len = 2754; -const unsigned short help_text_words = 497; +const unsigned short help_text_len = 2766; +const unsigned short help_text_words = 498; const char quick_help_text[] = "Divide the grid into rotationally symmetric regions each centred on a dot."; diff --git a/apps/plugins/puzzles/help/guess.c b/apps/plugins/puzzles/help/guess.c index cdfc24e6b3..9749854e1e 100644 --- a/apps/plugins/puzzles/help/guess.c +++ b/apps/plugins/puzzles/help/guess.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,209 +6,236 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 123, TEXT_CENTER | C_RED }, - { 404, TEXT_CENTER | C_RED }, - { 432, TEXT_UNDERLINE }, - { 452, TEXT_UNDERLINE }, - { 465, TEXT_UNDERLINE }, - { 483, TEXT_UNDERLINE }, - { 543, TEXT_UNDERLINE }, + { 124, TEXT_CENTER | C_RED }, + { 444, TEXT_CENTER | C_RED }, + { 472, TEXT_UNDERLINE }, + { 492, TEXT_UNDERLINE }, + { 505, TEXT_UNDERLINE }, + { 523, TEXT_UNDERLINE }, + { 583, TEXT_UNDERLINE }, + { 614, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3042 comp 1883 ratio 0.619001 level 10 saved 1159 */ +/* orig 3506 comp 2143 ratio 0.611238 level 10 saved 1363 */ const char help_text[] = { -0xf2, 0x2a, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x35, 0x3a, 0x20, 0x47, 0x75, 0x65, 0x73, 0x73, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x73, 0x65, 0x74, 0x00, 0x6f, 0x66, -0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x65, 0x64, 0x00, -0x70, 0x65, 0x67, 0x73, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x21, -0x00, 0xb0, 0x74, 0x6f, 0x00, 0x72, 0x65, 0x70, 0x72, 0x6f, -0x64, 0x75, 0x63, 0x2e, 0x00, 0xf0, 0x07, 0x70, 0x72, 0x65, -0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, -0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x41, -0x00, 0xf0, 0x00, 0x74, 0x68, 0x65, 0x6d, 0x00, 0x28, 0x63, -0x68, 0x6f, 0x73, 0x65, 0x6e, 0x00, 0x62, 0x79, 0x10, 0x00, -0xf0, 0x13, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, -0x72, 0x29, 0x00, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x00, -0x61, 0x00, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x39, 0x00, 0x10, 0x67, -0x95, 0x00, 0xa2, 0x65, 0x73, 0x2e, 0x00, 0x00, 0x00, 0x45, -0x61, 0x63, 0x68, 0x10, 0x00, 0xc1, 0x00, 0x67, 0x65, 0x74, -0x73, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0x3d, 0x00, -0x01, 0x50, 0x00, 0x06, 0x35, 0x00, 0xa9, 0x63, 0x6f, 0x72, -0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2d, 0xb9, 0x00, 0x33, -0x00, 0x69, 0x6e, 0x79, 0x00, 0x01, 0x1f, 0x00, 0xf2, 0x03, -0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x00, 0x28, 0x69, -0x6e, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x29, 0xda, 0x00, -0x4f, 0x61, 0x6c, 0x73, 0x6f, 0x51, 0x00, 0x06, 0x1f, 0x00, -0x52, 0x00, 0x02, 0x58, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x50, -0x00, 0x60, 0x77, 0x68, 0x69, 0x74, 0x65, 0x29, 0xb6, 0x00, -0xc2, 0x54, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, -0x00, 0x69, 0x73, 0x5b, 0x00, 0x70, 0x6b, 0x6e, 0x6f, 0x77, -0x6e, 0x00, 0x28, 0x6b, 0x00, 0x01, 0xc3, 0x00, 0x40, 0x74, -0x65, 0x64, 0x2c, 0x14, 0x01, 0xf2, 0x0b, 0x48, 0x61, 0x73, -0x62, 0x72, 0x6f, 0x2c, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x6c, -0x79, 0x29, 0x00, 0x61, 0x73, 0x00, 0x61, 0x00, 0x62, 0x6f, -0x61, 0x72, 0x64, 0x40, 0x00, 0x42, 0x60, 0x4d, 0x61, 0x73, -0x5d, 0x01, 0x32, 0x64, 0x27, 0x2c, 0xf7, 0x00, 0x13, 0x36, -0x8f, 0x00, 0x42, 0x73, 0x2c, 0x00, 0x34, 0x91, 0x00, 0x72, -0x70, 0x65, 0x72, 0x00, 0x72, 0x6f, 0x77, 0xca, 0x00, 0x26, -0x31, 0x30, 0x40, 0x01, 0xa0, 0x48, 0x6f, 0x77, 0x65, 0x76, -0x65, 0x72, 0x2c, 0x00, 0x74, 0x91, 0x00, 0xf0, 0x06, 0x76, -0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x61, 0x6c, 0x6c, -0x6f, 0x77, 0x73, 0x00, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, -0xee, 0x01, 0x50, 0x74, 0x69, 0x6e, 0x67, 0x73, 0xf3, 0x00, -0x08, 0xfd, 0x00, 0x01, 0x63, 0x00, 0x40, 0x00, 0x28, 0x75, -0x70, 0xf1, 0x01, 0x47, 0x31, 0x30, 0x29, 0x2c, 0x1e, 0x00, -0x0e, 0x76, 0x00, 0x0f, 0xbd, 0x01, 0x02, 0x11, 0x47, 0xb8, -0x01, 0xf0, 0x00, 0x77, 0x61, 0x73, 0x00, 0x63, 0x6f, 0x6e, -0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x4f, 0x00, -0x01, 0x8f, 0x00, 0x91, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, -0x74, 0x69, 0x6f, 0x1d, 0x02, 0xc0, 0x4a, 0x61, 0x6d, 0x65, -0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x3c, 0x00, -0x43, 0x31, 0x35, 0x2e, 0x31, 0x9e, 0x02, 0x01, 0x3d, 0x00, -0x49, 0x6f, 0x6c, 0x73, 0x20, 0x5a, 0x01, 0x60, 0x63, 0x61, -0x6e, 0x00, 0x62, 0x65, 0x80, 0x01, 0x14, 0x79, 0x11, 0x02, -0x61, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x9d, 0x01, 0x32, -0x6b, 0x65, 0x79, 0x46, 0x01, 0x12, 0x6f, 0x10, 0x00, 0x50, -0x6d, 0x6f, 0x75, 0x73, 0x65, 0x58, 0x00, 0x14, 0x57, 0x3a, -0x02, 0x01, 0x12, 0x00, 0x89, 0x2c, 0x00, 0x64, 0x72, 0x61, -0x67, 0x00, 0x61, 0xe2, 0x01, 0x51, 0x00, 0x66, 0x72, 0x6f, -0x6d, 0x24, 0x00, 0x62, 0x74, 0x72, 0x61, 0x79, 0x00, 0x6f, -0xef, 0x01, 0x60, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x68, 0xec, -0x00, 0x31, 0x73, 0x69, 0x64, 0x06, 0x03, 0x91, 0x69, 0x74, -0x73, 0x00, 0x72, 0x65, 0x71, 0x75, 0x69, 0x38, 0x00, 0x31, -0x6f, 0x73, 0x69, 0xcc, 0x00, 0x04, 0x70, 0x02, 0x62, 0x75, -0x72, 0x72, 0x65, 0x6e, 0x74, 0x0f, 0x01, 0x12, 0x3b, 0x32, -0x01, 0x32, 0x6d, 0x61, 0x79, 0x0e, 0x02, 0x21, 0x62, 0x65, -0x78, 0x00, 0x32, 0x67, 0x65, 0x64, 0x6c, 0x00, 0x04, 0x2d, -0x00, 0x00, 0x5e, 0x00, 0x44, 0x70, 0x61, 0x73, 0x74, 0x45, -0x01, 0x00, 0x66, 0x00, 0x42, 0x63, 0x6f, 0x70, 0x79, 0x4b, -0x03, 0xc0, 0x65, 0x6c, 0x73, 0x65, 0x77, 0x68, 0x65, 0x72, -0x65, 0x2e, 0x00, 0x54, 0x84, 0x03, 0x31, 0x6d, 0x6f, 0x76, -0x81, 0x03, 0x23, 0x65, 0x67, 0xc7, 0x00, 0x10, 0x69, 0xb8, -0x03, 0x11, 0x66, 0x98, 0x00, 0x04, 0x52, 0x00, 0x05, 0x97, -0x00, 0x62, 0x74, 0x6f, 0x00, 0x73, 0x6f, 0x6d, 0x40, 0x00, -0x80, 0x00, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, -0x01, 0xef, 0x52, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0xbe, 0x00, 0x02, 0x40, -0x00, 0x61, 0x64, 0x64, 0x97, 0x02, 0x62, 0x60, 0x68, 0x6f, -0x6c, 0x64, 0x27, 0xc0, 0x02, 0x13, 0x72, 0xd3, 0x00, 0x42, -0x74, 0x68, 0x61, 0x74, 0x17, 0x04, 0x00, 0x1d, 0x00, 0x03, -0x1c, 0x00, 0x60, 0x73, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0xe6, -0x00, 0xd0, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, -0x63, 0x61, 0x6c, 0x6c, 0x79, 0x48, 0x00, 0x04, 0x00, 0x02, -0x55, 0x65, 0x00, 0x6e, 0x65, 0x78, 0x60, 0x00, 0x41, 0x66, -0x74, 0x65, 0x72, 0x3c, 0x00, 0x30, 0x69, 0x6e, 0x67, 0x95, -0x00, 0xd3, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, -0x69, 0x76, 0x65, 0x6c, 0x79, 0xf7, 0x02, 0x08, 0xd6, 0x01, -0x11, 0x2c, 0x0e, 0x00, 0x21, 0x75, 0x70, 0x31, 0x01, 0x10, -0x64, 0x5a, 0x03, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x21, 0x00, 0x14, 0x73, 0x1a, 0x02, 0x22, 0x75, 0x73, 0x6d, -0x00, 0x20, 0x73, 0x65, 0x67, 0x02, 0x02, 0x29, 0x01, 0x03, -0xe8, 0x01, 0x15, 0x2c, 0xd2, 0x01, 0x01, 0x42, 0x00, 0x10, -0x72, 0x04, 0x01, 0x02, 0x3c, 0x00, 0x0c, 0x30, 0x00, 0x04, -0x40, 0x01, 0x02, 0xe6, 0x02, 0x00, 0x36, 0x00, 0x90, 0x73, -0x70, 0x61, 0x63, 0x65, 0x00, 0x62, 0x61, 0x72, 0x5b, 0x02, -0x41, 0x45, 0x6e, 0x74, 0x65, 0x76, 0x00, 0x00, 0x39, 0x00, -0x01, 0x0b, 0x04, 0x03, 0x38, 0x00, 0x02, 0xff, 0x04, 0x03, -0x4c, 0x00, 0x23, 0x65, 0x64, 0x78, 0x00, 0x05, 0x5f, 0x01, -0x02, 0x14, 0x05, 0x04, 0x5d, 0x00, 0x50, 0x2e, 0x00, 0x60, -0x44, 0x27, 0x4f, 0x00, 0x42, 0x42, 0x61, 0x63, 0x6b, 0x60, -0x00, 0x02, 0xde, 0x01, 0x14, 0x73, 0xdf, 0x01, 0x00, 0x7d, -0x00, 0x11, 0x53, 0x19, 0x00, 0x03, 0x8c, 0x01, 0x07, 0x6e, -0x01, 0x00, 0x31, 0x01, 0x50, 0x50, 0x72, 0x65, 0x73, 0x73, -0xc0, 0x01, 0x21, 0x60, 0x68, 0x49, 0x00, 0x32, 0x60, 0x3f, -0x27, 0x84, 0x01, 0x10, 0x66, 0x05, 0x00, 0x0e, 0xd2, 0x01, -0x01, 0x52, 0x01, 0x80, 0x61, 0x00, 0x73, 0x75, 0x67, 0x67, -0x65, 0x73, 0xa0, 0x00, 0x01, 0x17, 0x00, 0x31, 0x2e, 0x00, -0x55, 0x45, 0x00, 0x01, 0x9f, 0x03, 0xf0, 0x01, 0x69, 0x73, +0x00, 0x2d, 0x01, 0x00, 0xf2, 0x18, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x73, 0x65, 0x74, 0x00, 0x6f, 0x66, 0x00, 0x63, 0x6f, 0x6c, +0x6f, 0x75, 0x72, 0x65, 0x64, 0x00, 0x70, 0x65, 0x67, 0x73, +0x2c, 0x00, 0x61, 0x6e, 0x64, 0x21, 0x00, 0xb0, 0x74, 0x6f, +0x00, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x2e, +0x00, 0xf0, 0x07, 0x70, 0x72, 0x65, 0x64, 0x65, 0x74, 0x65, +0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x00, 0x73, 0x65, 0x71, +0x75, 0x65, 0x6e, 0x63, 0x65, 0x41, 0x00, 0xf0, 0x00, 0x74, +0x68, 0x65, 0x6d, 0x00, 0x28, 0x63, 0x68, 0x6f, 0x73, 0x65, +0x6e, 0x00, 0x62, 0x79, 0x10, 0x00, 0xf0, 0x13, 0x00, 0x63, +0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x29, 0x00, 0x77, +0x69, 0x74, 0x68, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x63, 0x65, +0x72, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0x39, 0x00, 0x10, 0x67, 0xa7, 0x00, 0xa2, 0x65, +0x73, 0x2e, 0x00, 0x00, 0x00, 0x45, 0x61, 0x63, 0x68, 0x10, +0x00, 0xc1, 0x00, 0x67, 0x65, 0x74, 0x73, 0x00, 0x6d, 0x61, +0x72, 0x6b, 0x65, 0x64, 0x3d, 0x00, 0x01, 0x50, 0x00, 0x06, +0x35, 0x00, 0xa9, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, +0x6c, 0x79, 0x2d, 0xb9, 0x00, 0x33, 0x00, 0x69, 0x6e, 0x79, +0x00, 0x01, 0x1f, 0x00, 0xf2, 0x03, 0x00, 0x70, 0x6c, 0x61, +0x63, 0x65, 0x73, 0x00, 0x28, 0x69, 0x6e, 0x00, 0x62, 0x6c, +0x61, 0x63, 0x6b, 0x29, 0xda, 0x00, 0x4f, 0x61, 0x6c, 0x73, +0x6f, 0x51, 0x00, 0x06, 0x1f, 0x00, 0x52, 0x00, 0x02, 0x58, +0x77, 0x72, 0x6f, 0x6e, 0x67, 0x50, 0x00, 0x60, 0x77, 0x68, +0x69, 0x74, 0x65, 0x29, 0xb6, 0x00, 0xc2, 0x54, 0x68, 0x69, +0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x69, 0x73, 0x5b, +0x00, 0x70, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x28, 0x6b, +0x00, 0x01, 0xc3, 0x00, 0x40, 0x74, 0x65, 0x64, 0x2c, 0x14, +0x01, 0xf2, 0x0b, 0x48, 0x61, 0x73, 0x62, 0x72, 0x6f, 0x2c, +0x00, 0x6d, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x29, 0x00, 0x61, +0x73, 0x00, 0x61, 0x00, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x40, +0x00, 0x42, 0x60, 0x4d, 0x61, 0x73, 0x5d, 0x01, 0x32, 0x64, +0x27, 0x2c, 0xf7, 0x00, 0x13, 0x36, 0x8f, 0x00, 0x42, 0x73, +0x2c, 0x00, 0x34, 0x91, 0x00, 0x72, 0x70, 0x65, 0x72, 0x00, +0x72, 0x6f, 0x77, 0xca, 0x00, 0x26, 0x31, 0x30, 0x40, 0x01, +0xa0, 0x48, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, 0x00, +0x74, 0x91, 0x00, 0xf0, 0x06, 0x76, 0x65, 0x72, 0x73, 0x69, +0x6f, 0x6e, 0x00, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x00, +0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0xee, 0x01, 0x50, 0x74, +0x69, 0x6e, 0x67, 0x73, 0xf3, 0x00, 0x08, 0xfd, 0x00, 0x01, +0x63, 0x00, 0x40, 0x00, 0x28, 0x75, 0x70, 0xf1, 0x01, 0x47, +0x31, 0x30, 0x29, 0x2c, 0x1e, 0x00, 0x0e, 0x76, 0x00, 0x0f, +0xbd, 0x01, 0x02, 0x11, 0x47, 0xb8, 0x01, 0xf0, 0x00, 0x77, +0x61, 0x73, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, +0x75, 0x74, 0x65, 0x64, 0x4f, 0x00, 0x01, 0x8f, 0x00, 0x91, +0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x1d, +0x02, 0xc0, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, +0x72, 0x76, 0x65, 0x79, 0x3c, 0x00, 0x43, 0x31, 0x35, 0x2e, +0x31, 0xb0, 0x02, 0x01, 0x3d, 0x00, 0x49, 0x6f, 0x6c, 0x73, +0x20, 0x5a, 0x01, 0x60, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, +0x80, 0x01, 0x14, 0x79, 0x11, 0x02, 0x61, 0x65, 0x69, 0x74, +0x68, 0x65, 0x72, 0x9d, 0x01, 0x32, 0x6b, 0x65, 0x79, 0x46, +0x01, 0x12, 0x6f, 0x10, 0x00, 0x50, 0x6d, 0x6f, 0x75, 0x73, +0x65, 0x58, 0x00, 0x14, 0x57, 0x3a, 0x02, 0x01, 0x12, 0x00, +0x89, 0x2c, 0x00, 0x64, 0x72, 0x61, 0x67, 0x00, 0x61, 0xe2, +0x01, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x24, 0x00, 0x62, +0x74, 0x72, 0x61, 0x79, 0x00, 0x6f, 0xef, 0x01, 0x60, 0x6c, +0x65, 0x66, 0x74, 0x2d, 0x68, 0xec, 0x00, 0x31, 0x73, 0x69, +0x64, 0x06, 0x03, 0x91, 0x69, 0x74, 0x73, 0x00, 0x72, 0x65, +0x71, 0x75, 0x69, 0x38, 0x00, 0x31, 0x6f, 0x73, 0x69, 0xcc, +0x00, 0x04, 0x70, 0x02, 0x62, 0x75, 0x72, 0x72, 0x65, 0x6e, +0x74, 0x0f, 0x01, 0x12, 0x3b, 0x32, 0x01, 0x32, 0x6d, 0x61, +0x79, 0x0e, 0x02, 0x21, 0x62, 0x65, 0x78, 0x00, 0x32, 0x67, +0x65, 0x64, 0x6c, 0x00, 0x04, 0x2d, 0x00, 0x00, 0x5e, 0x00, +0x44, 0x70, 0x61, 0x73, 0x74, 0x45, 0x01, 0x00, 0x66, 0x00, +0x42, 0x63, 0x6f, 0x70, 0x79, 0x4b, 0x03, 0xc0, 0x65, 0x6c, +0x73, 0x65, 0x77, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x00, 0x54, +0x84, 0x03, 0x31, 0x6d, 0x6f, 0x76, 0x81, 0x03, 0x23, 0x65, +0x67, 0xc7, 0x00, 0x10, 0x69, 0xb8, 0x03, 0x11, 0x66, 0x98, +0x00, 0x04, 0x52, 0x00, 0x05, 0x97, 0x00, 0x62, 0x74, 0x6f, +0x00, 0x73, 0x6f, 0x6d, 0x40, 0x00, 0x80, 0x00, 0x69, 0x6e, +0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0x01, 0xef, 0x52, 0x69, +0x67, 0x68, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x69, +0x6e, 0x67, 0xbe, 0x00, 0x02, 0x40, 0x00, 0x61, 0x64, 0x64, +0x97, 0x02, 0x62, 0x60, 0x68, 0x6f, 0x6c, 0x64, 0x27, 0xc0, +0x02, 0x13, 0x72, 0xd3, 0x00, 0x42, 0x74, 0x68, 0x61, 0x74, +0x17, 0x04, 0x00, 0x1d, 0x00, 0x03, 0x1c, 0x00, 0x60, 0x73, +0x00, 0x77, 0x69, 0x6c, 0x6c, 0xe6, 0x00, 0xd0, 0x61, 0x75, +0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, +0x79, 0x48, 0x00, 0x04, 0x00, 0x02, 0x55, 0x65, 0x00, 0x6e, +0x65, 0x78, 0x60, 0x00, 0x41, 0x66, 0x74, 0x65, 0x72, 0x3c, +0x00, 0x30, 0x69, 0x6e, 0x67, 0x95, 0x00, 0xd3, 0x41, 0x6c, +0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, +0x79, 0xf7, 0x02, 0x08, 0xd6, 0x01, 0x11, 0x2c, 0x0e, 0x00, +0x21, 0x75, 0x70, 0x31, 0x01, 0x10, 0x64, 0x5a, 0x03, 0x60, +0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x21, 0x00, 0x14, 0x73, +0x1a, 0x02, 0x22, 0x75, 0x73, 0x6d, 0x00, 0x20, 0x73, 0x65, +0x67, 0x02, 0x02, 0x29, 0x01, 0x03, 0xe8, 0x01, 0x15, 0x2c, +0xd2, 0x01, 0x01, 0x42, 0x00, 0x10, 0x72, 0x04, 0x01, 0x02, +0x3c, 0x00, 0x0c, 0x30, 0x00, 0x04, 0x40, 0x01, 0x02, 0xe6, +0x02, 0x00, 0x36, 0x00, 0x41, 0x45, 0x6e, 0x74, 0x65, 0x69, +0x00, 0x00, 0x2c, 0x00, 0x01, 0xfe, 0x03, 0x03, 0x2b, 0x00, +0x02, 0xf2, 0x04, 0x03, 0x3f, 0x00, 0x23, 0x65, 0x64, 0x6b, +0x00, 0x05, 0x52, 0x01, 0x02, 0x07, 0x05, 0x04, 0x50, 0x00, +0x50, 0x2e, 0x00, 0x60, 0x44, 0x27, 0x9d, 0x02, 0x60, 0x42, +0x61, 0x63, 0x6b, 0x73, 0x70, 0x46, 0x00, 0x02, 0xd1, 0x01, +0x14, 0x73, 0xd2, 0x01, 0x00, 0x70, 0x00, 0x11, 0x53, 0x19, +0x00, 0x03, 0x7f, 0x01, 0x07, 0x61, 0x01, 0x02, 0x64, 0x04, +0x05, 0xad, 0x04, 0x05, 0xf6, 0x00, 0x04, 0x5d, 0x02, 0x04, +0xfb, 0x00, 0x61, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0xaa, +0x01, 0x53, 0x3a, 0x00, 0x60, 0x31, 0x27, 0x11, 0x00, 0x12, +0x73, 0xdd, 0x02, 0x75, 0x6f, 0x70, 0x2d, 0x6d, 0x6f, 0x73, +0x74, 0x14, 0x01, 0x33, 0x60, 0x32, 0x27, 0xc2, 0x00, 0x82, +0x63, 0x6f, 0x6e, 0x64, 0x00, 0x6f, 0x6e, 0x65, 0x86, 0x00, +0x90, 0x73, 0x6f, 0x00, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x2e, +0x74, 0x00, 0x22, 0x73, 0x65, 0x66, 0x00, 0x01, 0x7d, 0x02, +0x00, 0x2e, 0x00, 0x01, 0x56, 0x01, 0x02, 0x7e, 0x01, 0x03, +0xda, 0x01, 0x01, 0x4f, 0x01, 0x70, 0x2e, 0x00, 0x50, 0x72, +0x65, 0x73, 0x73, 0x54, 0x02, 0x32, 0x60, 0x4c, 0x27, 0x11, +0x02, 0x54, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x35, 0x00, 0x15, +0x73, 0xd7, 0x01, 0x23, 0x69, 0x72, 0xc9, 0x00, 0x01, 0x35, +0x04, 0x06, 0x37, 0x00, 0x11, 0x68, 0x21, 0x01, 0x23, 0x60, +0x3f, 0x3e, 0x00, 0x10, 0x66, 0x05, 0x00, 0x0e, 0x9d, 0x02, +0x01, 0x46, 0x00, 0x80, 0x61, 0x00, 0x73, 0x75, 0x67, 0x67, +0x65, 0x73, 0x78, 0x01, 0x01, 0x17, 0x00, 0x31, 0x2e, 0x00, +0x55, 0x45, 0x00, 0x01, 0x6a, 0x04, 0xf0, 0x01, 0x69, 0x73, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x72, 0x65, 0x63, 0x6f, 0x6d, -0x6d, 0x65, 0x6e, 0x64, 0xac, 0x02, 0x20, 0x6f, 0x72, 0x5f, -0x04, 0x72, 0x6f, 0x72, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x01, -0x02, 0x20, 0x61, 0x73, 0x77, 0x02, 0x71, 0x69, 0x73, 0x00, -0x73, 0x6c, 0x6f, 0x77, 0x61, 0x03, 0x22, 0x68, 0x65, 0xe5, -0x00, 0x02, 0x6a, 0x00, 0x21, 0x69, 0x73, 0xf4, 0x05, 0x52, -0x6c, 0x65, 0x74, 0x65, 0x2c, 0x13, 0x01, 0xf2, 0x00, 0x6d, -0x61, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x66, 0x65, 0x65, 0x64, -0x62, 0x61, 0x63, 0x6b, 0x47, 0x00, 0x04, 0x31, 0x02, 0x50, -0x68, 0x69, 0x67, 0x68, 0x6c, 0x8f, 0x01, 0x45, 0x65, 0x64, -0x3b, 0x00, 0x96, 0x02, 0x02, 0x83, 0x03, 0x41, 0x73, 0x65, -0x00, 0x28, 0x7c, 0x00, 0x12, 0x76, 0xa5, 0x00, 0x01, 0x82, -0x00, 0x04, 0xfa, 0x01, 0x02, 0x56, 0x02, 0x16, 0x6d, 0x2c, -0x02, 0x52, 0x61, 0x72, 0x72, 0x6f, 0x77, 0xd5, 0x01, 0x01, -0x57, 0x03, 0x04, 0x22, 0x01, 0x0f, 0xc4, 0x01, 0x07, 0x12, -0x29, 0x86, 0x00, 0x00, 0x56, 0x01, 0x0e, 0x33, 0x01, 0x12, -0x2c, 0x89, 0x03, 0x73, 0x61, 0x6e, 0x79, 0x00, 0x68, 0x65, -0x6c, 0x0a, 0x06, 0x0d, 0xcb, 0x02, 0x02, 0xaa, 0x01, 0x01, -0x99, 0x03, 0x00, 0x19, 0x00, 0x19, 0x60, 0x43, 0x00, 0x17, -0x27, 0xb1, 0x01, 0x66, 0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, -0x64, 0x06, 0x06, 0xa9, 0x03, 0x13, 0x61, 0xb1, 0x01, 0x03, -0x5f, 0x03, 0x61, 0x65, 0x00, 0x73, 0x6f, 0x6c, 0x75, 0x1a, -0x00, 0x04, 0x24, 0x01, 0x33, 0x64, 0x69, 0x73, 0xf6, 0x04, +0x6d, 0x65, 0x6e, 0x64, 0x77, 0x03, 0x20, 0x6f, 0x72, 0x2a, +0x05, 0x63, 0x6f, 0x72, 0x00, 0x6d, 0x6f, 0x72, 0x90, 0x00, +0x20, 0x61, 0x73, 0x42, 0x03, 0x71, 0x69, 0x73, 0x00, 0x73, +0x6c, 0x6f, 0x77, 0x2c, 0x04, 0x22, 0x68, 0x65, 0xbd, 0x01, +0x02, 0x6a, 0x00, 0x21, 0x69, 0x73, 0xbf, 0x06, 0x52, 0x6c, +0x65, 0x74, 0x65, 0x2c, 0x29, 0x01, 0xf4, 0x00, 0x6d, 0x61, +0x6c, 0x6c, 0x65, 0x72, 0x00, 0x66, 0x65, 0x65, 0x64, 0x62, +0x61, 0x63, 0x6b, 0xd7, 0x00, 0x02, 0xfc, 0x02, 0x50, 0x68, +0x69, 0x67, 0x68, 0x6c, 0x0b, 0x01, 0x45, 0x65, 0x64, 0x3b, +0x00, 0x61, 0x03, 0x02, 0x4e, 0x04, 0x41, 0x73, 0x65, 0x00, +0x28, 0x7c, 0x00, 0x12, 0x76, 0xa5, 0x00, 0x0f, 0x47, 0x01, +0x00, 0x16, 0x6d, 0xf7, 0x02, 0x52, 0x61, 0x72, 0x72, 0x6f, +0x77, 0xe6, 0x01, 0x01, 0x22, 0x04, 0x04, 0x22, 0x01, 0x01, +0x84, 0x00, 0x01, 0x23, 0x02, 0x30, 0x62, 0x61, 0x72, 0xcc, +0x00, 0x05, 0x9c, 0x02, 0x12, 0x29, 0x86, 0x00, 0x00, 0x2e, +0x02, 0x0e, 0x33, 0x01, 0x12, 0x2c, 0x54, 0x04, 0x73, 0x61, +0x6e, 0x79, 0x00, 0x68, 0x65, 0x6c, 0xd5, 0x06, 0x0d, 0x96, +0x03, 0x02, 0xfc, 0x01, 0x05, 0xe7, 0x01, 0x19, 0x60, 0x43, +0x00, 0x17, 0x27, 0x89, 0x02, 0x66, 0x49, 0x66, 0x00, 0x79, +0x6f, 0x75, 0x2f, 0x07, 0x06, 0x74, 0x04, 0x27, 0x61, 0x6c, +0xee, 0x01, 0x01, 0xad, 0x00, 0x31, 0x6f, 0x6c, 0x75, 0x1a, +0x00, 0x04, 0x24, 0x01, 0x33, 0x64, 0x69, 0x73, 0xc1, 0x05, 0x82, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x3b, 0x00, 0x69, 0x4d, -0x00, 0x77, 0x72, 0x75, 0x6e, 0x00, 0x6f, 0x75, 0x74, 0x85, -0x05, 0x01, 0x30, 0x01, 0x03, 0xd0, 0x02, 0xbe, 0x60, 0x53, +0x00, 0x77, 0x72, 0x75, 0x6e, 0x00, 0x6f, 0x75, 0x74, 0x50, +0x06, 0x01, 0x30, 0x01, 0x03, 0x9b, 0x03, 0xbe, 0x60, 0x53, 0x6f, 0x6c, 0x76, 0x65, 0x2e, 0x2e, 0x2e, 0x27, 0x29, 0x57, -0x00, 0x05, 0x97, 0x04, 0x71, 0x72, 0x65, 0x76, 0x65, 0x61, -0x6c, 0x65, 0x1b, 0x04, 0x23, 0x28, 0x41, 0x8b, 0x00, 0x11, -0x61, 0xa6, 0x05, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, -0x72, 0x69, 0x62, 0x65, 0x64, 0xc8, 0x02, 0x13, 0x73, 0xbc, -0x05, 0x72, 0x32, 0x2e, 0x31, 0x00, 0x61, 0x72, 0x65, 0x42, -0x00, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, -0x65, 0x2e, 0x29, 0xc4, 0x05, 0x13, 0x32, 0xc4, 0x05, 0x50, -0x70, 0x61, 0x72, 0x61, 0x6d, 0x27, 0x08, 0x03, 0xc6, 0x05, -0x00, 0xcd, 0x01, 0x06, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, -0x3c, 0x00, 0x06, 0x80, 0x05, 0x21, 0x60, 0x43, 0xa4, 0x06, -0x00, 0xb5, 0x00, 0x31, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x03, -0x8e, 0x05, 0xc0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0x2e, 0x4f, 0x00, 0x82, 0x00, 0x64, -0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x1c, 0x06, 0x62, 0x6d, -0x61, 0x74, 0x63, 0x68, 0x65, 0x3f, 0x01, 0x07, 0x66, 0x00, -0x13, 0x66, 0x0d, 0x06, 0x0f, 0x60, 0x07, 0x04, 0x00, 0xf4, -0x00, 0x13, 0x43, 0xf8, 0x06, 0x3d, 0x00, 0x00, 0x4e, 0x0c, -0x07, 0x09, 0x36, 0x01, 0x24, 0x69, 0x73, 0xc6, 0x03, 0x00, -0xae, 0x00, 0x12, 0x3b, 0xb4, 0x00, 0x12, 0x32, 0x2c, 0x07, -0x21, 0x00, 0x28, 0x20, 0x03, 0xa1, 0x69, 0x73, 0x00, 0x68, -0x61, 0x72, 0x64, 0x65, 0x72, 0x29, 0xa3, 0x03, 0x82, 0x65, -0x67, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x18, 0x03, 0x08, -0x61, 0x00, 0x05, 0x4f, 0x07, 0x02, 0x1b, 0x00, 0x0e, 0x3e, -0x00, 0x03, 0x4b, 0x07, 0x1a, 0x65, 0x37, 0x00, 0x04, 0xe5, -0x01, 0x00, 0xfc, 0x01, 0x04, 0x9a, 0x09, 0x4b, 0x66, 0x69, -0x6e, 0x64, 0xa9, 0x00, 0x8b, 0x6e, 0x00, 0x28, 0x66, 0x65, -0x77, 0x65, 0x72, 0x52, 0x00, 0x10, 0x41, 0x06, 0x08, 0x74, -0x20, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x0f, 0x00, 0x21, -0x73, 0x00, 0x10, 0x00, 0x05, 0xdd, 0x02, 0x80, 0x62, 0x65, -0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0xe6, 0x03, 0x31, 0x70, -0x61, 0x72, 0x5b, 0x02, 0x15, 0x61, 0xa6, 0x00, 0x31, 0x61, -0x6b, 0x65, 0xfd, 0x03, 0x40, 0x65, 0x61, 0x73, 0x69, 0x65, -0x08, 0x71, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x90, -0x00, 0x00, 0xf0, 0x08, 0x02, 0x1d, 0x06, 0x10, 0x74, 0x26, -0x01, 0x02, 0x65, 0x02, 0x10, 0x6e, 0x8d, 0x08, 0x20, 0x00, -0x62, 0x8d, 0x09, 0x20, 0x75, 0x6e, 0x76, 0x04, 0x07, 0x57, -0x00, 0x08, 0xb4, 0x00, 0x10, 0x29, 0xd3, 0x01, 0x02, 0x83, -0x04, 0x30, 0x74, 0x75, 0x72, 0x57, 0x0a, 0x00, 0xd7, 0x06, -0x24, 0x62, 0x79, 0xe5, 0x01, 0x10, 0x2e, 0x07, 0x01, 0x34, -0x6f, 0x74, 0x65, 0x61, 0x00, 0xa2, 0x69, 0x73, 0x00, 0x64, -0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0xdc, 0x08, 0x08, 0xc6, -0x00, 0x29, 0x69, 0x6e, 0x5b, 0x00, 0x06, 0x2d, 0x03, 0x11, -0x65, 0x93, 0x06, 0x21, 0x77, 0x61, 0x89, 0x00, 0x00, 0x49, -0x00, 0x20, 0x2c, 0x00, 0xbd, 0x00, 0x84, 0x6f, 0x6e, 0x65, -0x00, 0x65, 0x78, 0x74, 0x72, 0x13, 0x08, 0x06, 0x2b, 0x01, -0x97, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, -0x2f, 0x01, 0x09, 0x6a, 0x01, 0x14, 0x28, 0x23, 0x06, 0x03, -0x99, 0x01, 0x12, 0x29, 0xbf, 0x07, 0x11, 0x6e, 0xde, 0x0a, -0x04, 0x45, 0x02, 0x01, 0xdc, 0x01, 0x30, 0x74, 0x68, 0x61, -0xca, 0x02, 0x33, 0x63, 0x65, 0x3b, 0x6c, 0x05, 0x51, 0x6e, -0x63, 0x72, 0x65, 0x61, 0xf1, 0x07, 0x01, 0x35, 0x06, 0x43, -0x61, 0x72, 0x63, 0x68, 0xa5, 0x04, 0x00, 0x67, 0x01, 0x03, -0x94, 0x05, 0x25, 0x6e, 0x67, 0xc1, 0x01, 0x02, 0x68, 0x04, -0x07, 0x20, 0x01, 0x14, 0x6e, 0x1f, 0x01, 0x50, 0x75, 0x6c, -0x74, 0x2e, 0x00, +0x00, 0x05, 0x05, 0x03, 0x71, 0x72, 0x65, 0x76, 0x65, 0x61, +0x6c, 0x65, 0xe6, 0x04, 0x23, 0x28, 0x41, 0x8b, 0x00, 0x11, +0x61, 0x71, 0x06, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, +0x72, 0x69, 0x62, 0x65, 0x64, 0xa0, 0x03, 0x13, 0x73, 0x87, +0x06, 0x63, 0x32, 0x2e, 0x31, 0x00, 0x61, 0x72, 0xe1, 0x02, +0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, +0x2e, 0x29, 0x8f, 0x06, 0x13, 0x32, 0x8f, 0x06, 0x50, 0x70, +0x61, 0x72, 0x61, 0x6d, 0xf2, 0x08, 0x03, 0x91, 0x06, 0x00, +0xcd, 0x01, 0x06, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, +0x00, 0x06, 0x4b, 0x06, 0x21, 0x60, 0x43, 0x6f, 0x07, 0x00, +0xb5, 0x00, 0x31, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x03, 0x59, +0x06, 0xc1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, +0x65, 0x6e, 0x75, 0x2e, 0xd6, 0x03, 0x72, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6c, 0x74, 0xe7, 0x06, 0x62, 0x6d, 0x61, 0x74, +0x63, 0x68, 0x65, 0x3f, 0x01, 0x07, 0x66, 0x00, 0x13, 0x66, +0xd8, 0x06, 0x0f, 0x2b, 0x08, 0x04, 0x00, 0xf4, 0x00, 0x13, +0x43, 0xc3, 0x07, 0x3d, 0x00, 0x00, 0x4e, 0xd7, 0x07, 0x09, +0x36, 0x01, 0x24, 0x69, 0x73, 0x9e, 0x04, 0x00, 0xae, 0x00, +0x12, 0x3b, 0xb4, 0x00, 0x12, 0x32, 0xf7, 0x07, 0x21, 0x00, +0x28, 0x20, 0x03, 0xa1, 0x69, 0x73, 0x00, 0x68, 0x61, 0x72, +0x64, 0x65, 0x72, 0x29, 0xa3, 0x03, 0x82, 0x65, 0x67, 0x73, +0x20, 0x70, 0x65, 0x72, 0x20, 0x18, 0x03, 0x08, 0x61, 0x00, +0x05, 0x1a, 0x08, 0x02, 0x1b, 0x00, 0x0e, 0x3e, 0x00, 0x03, +0x16, 0x08, 0x1a, 0x65, 0x37, 0x00, 0x04, 0xe5, 0x01, 0x00, +0xfc, 0x01, 0x04, 0x65, 0x0a, 0x4b, 0x66, 0x69, 0x6e, 0x64, +0xa9, 0x00, 0x8b, 0x6e, 0x00, 0x28, 0x66, 0x65, 0x77, 0x65, +0x72, 0x52, 0x00, 0x10, 0x41, 0xd1, 0x08, 0x74, 0x20, 0x62, +0x6c, 0x61, 0x6e, 0x6b, 0x73, 0x0f, 0x00, 0x21, 0x73, 0x00, +0x10, 0x00, 0x05, 0xdd, 0x02, 0x80, 0x62, 0x65, 0x00, 0x67, +0x69, 0x76, 0x65, 0x6e, 0xe6, 0x03, 0x31, 0x70, 0x61, 0x72, +0x5b, 0x02, 0x15, 0x61, 0xa6, 0x00, 0x31, 0x61, 0x6b, 0x65, +0xfd, 0x03, 0x40, 0x65, 0x61, 0x73, 0x69, 0x30, 0x09, 0x71, +0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x90, 0x00, 0x00, +0xbb, 0x09, 0x02, 0xe8, 0x06, 0x10, 0x74, 0x26, 0x01, 0x02, +0x65, 0x02, 0x10, 0x6e, 0x58, 0x09, 0x20, 0x00, 0x62, 0x58, +0x0a, 0x20, 0x75, 0x6e, 0x76, 0x04, 0x07, 0x57, 0x00, 0x08, +0xb4, 0x00, 0x10, 0x29, 0xd3, 0x01, 0x02, 0x83, 0x04, 0x30, +0x74, 0x75, 0x72, 0x22, 0x0b, 0x00, 0xa2, 0x07, 0x24, 0x62, +0x79, 0xe5, 0x01, 0x10, 0x2e, 0x07, 0x01, 0x34, 0x6f, 0x74, +0x65, 0x61, 0x00, 0xa2, 0x69, 0x73, 0x00, 0x64, 0x6f, 0x65, +0x73, 0x6e, 0x27, 0x74, 0xa7, 0x09, 0x08, 0xc6, 0x00, 0x29, +0x69, 0x6e, 0x5b, 0x00, 0x06, 0x2d, 0x03, 0x11, 0x65, 0x5e, +0x07, 0x21, 0x77, 0x61, 0x89, 0x00, 0x00, 0x49, 0x00, 0x10, +0x2c, 0x02, 0x06, 0x00, 0xc1, 0x05, 0x54, 0x00, 0x65, 0x78, +0x74, 0x72, 0xde, 0x08, 0x06, 0x2b, 0x01, 0x97, 0x64, 0x75, +0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2f, 0x01, 0x09, +0x6a, 0x01, 0x14, 0x28, 0xee, 0x06, 0x03, 0x99, 0x01, 0x12, +0x29, 0x8a, 0x08, 0x11, 0x6e, 0xa9, 0x0b, 0x04, 0x45, 0x02, +0x01, 0xdc, 0x01, 0x30, 0x74, 0x68, 0x61, 0xca, 0x02, 0x33, +0x63, 0x65, 0x3b, 0x6c, 0x05, 0x51, 0x6e, 0x63, 0x72, 0x65, +0x61, 0xbc, 0x08, 0x01, 0x4b, 0x06, 0x43, 0x61, 0x72, 0x63, +0x68, 0xa5, 0x04, 0x00, 0x67, 0x01, 0x03, 0x94, 0x05, 0x25, +0x6e, 0x67, 0xc1, 0x01, 0x02, 0x68, 0x04, 0x07, 0x20, 0x01, +0x1b, 0x6e, 0x1f, 0x01, 0x43, 0x31, 0x35, 0x2e, 0x33, 0x7b, +0x03, 0xb0, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, +0x66, 0x65, 0x72, 0x65, 0x0c, 0x01, 0x81, 0x03, 0x20, 0x4f, +0x6e, 0x86, 0x07, 0x53, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x8f, +0x08, 0x80, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, +0x2e, 0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0x6f, 0x03, +0x16, 0x50, 0x12, 0x00, 0x0d, 0x8b, 0x03, 0x33, 0x47, 0x61, +0x6d, 0x8b, 0x03, 0x03, 0xb2, 0x06, 0x23, 0x65, 0x74, 0xdd, +0x04, 0xb1, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x00, +0x77, 0x68, 0x65, 0x65, 0x0a, 0x02, 0x32, 0x06, 0x22, 0x72, +0x65, 0xd5, 0x06, 0x3f, 0x6c, 0x65, 0x64, 0xcf, 0x06, 0x02, +0x53, 0x55, 0x6e, 0x6c, 0x69, 0x6b, 0x41, 0x05, 0x20, 0x4c, +0x27, 0x9a, 0x05, 0x03, 0x8c, 0x0b, 0x01, 0x5e, 0x00, 0x10, +0x70, 0x91, 0x0b, 0xf0, 0x03, 0x73, 0x74, 0x00, 0x62, 0x65, +0x74, 0x77, 0x65, 0x65, 0x6e, 0x00, 0x67, 0x61, 0x6d, 0x65, +0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 3042; -const unsigned short help_text_words = 572; +const unsigned short help_text_len = 3506; +const unsigned short help_text_words = 650; const char quick_help_text[] = "Guess the hidden combination of colours."; diff --git a/apps/plugins/puzzles/help/inertia.c b/apps/plugins/puzzles/help/inertia.c index 956d133d44..ba8d71d0a5 100644 --- a/apps/plugins/puzzles/help/inertia.c +++ b/apps/plugins/puzzles/help/inertia.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,176 +6,177 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 39, TEXT_UNDERLINE }, - { 110, TEXT_UNDERLINE }, - { 196, TEXT_CENTER | C_RED }, - { 404, TEXT_CENTER | C_RED }, - { 421, TEXT_UNDERLINE }, + { 40, TEXT_UNDERLINE }, + { 111, TEXT_UNDERLINE }, + { 197, TEXT_CENTER | C_RED }, + { 405, TEXT_CENTER | C_RED }, { 422, TEXT_UNDERLINE }, + { 423, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2266 comp 1565 ratio 0.690644 level 10 saved 701 */ +/* orig 2286 comp 1571 ratio 0.687227 level 10 saved 715 */ const char help_text[] = { -0xf0, 0x1f, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x34, 0x3a, 0x20, 0x49, 0x6e, 0x65, 0x72, 0x74, 0x69, -0x61, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, -0x72, 0x65, 0x00, 0x61, 0x00, 0x73, 0x6d, 0x61, 0x6c, 0x6c, -0x00, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x00, 0x62, 0x0b, 0x00, -0xf0, 0x15, 0x73, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x00, -0x69, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, -0x66, 0x75, 0x6c, 0x6c, 0x00, 0x6f, 0x66, 0x00, 0x6f, 0x62, -0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x73, 0x2e, 0x40, 0x00, -0xf0, 0x05, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, -0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, -0x74, 0x00, 0x40, 0x00, 0xf2, 0x06, 0x74, 0x68, 0x65, 0x00, -0x67, 0x65, 0x6d, 0x73, 0x00, 0x77, 0x69, 0x74, 0x68, 0x6f, -0x75, 0x74, 0x00, 0x72, 0x75, 0x6e, 0x6e, 0x51, 0x00, 0xa0, -0x74, 0x6f, 0x00, 0x61, 0x6e, 0x79, 0x00, 0x6d, 0x69, 0x6e, -0x44, 0x00, 0x02, 0x86, 0x00, 0x81, 0x63, 0x61, 0x6e, 0x00, -0x6d, 0x6f, 0x76, 0x65, 0x38, 0x00, 0x01, 0x81, 0x00, 0x21, -0x69, 0x6e, 0x26, 0x00, 0xf2, 0x02, 0x6f, 0x72, 0x74, 0x68, -0x6f, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x6f, 0x72, 0x20, -0x64, 0x69, 0x61, 0x0c, 0x00, 0xe7, 0x64, 0x69, 0x72, 0x65, -0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x00, 0x4f, 0x6e, 0x63, -0x37, 0x00, 0x60, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x4c, -0x00, 0xf0, 0x13, 0x69, 0x6e, 0x67, 0x2c, 0x00, 0x69, 0x74, -0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x63, 0x6f, 0x6e, 0x74, -0x69, 0x6e, 0x75, 0x65, 0x00, 0x75, 0x6e, 0x74, 0x69, 0x6c, -0x00, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x8f, 0x00, 0xf4, -0x00, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x00, 0x69, 0x74, 0x2e, -0x00, 0x41, 0x00, 0x77, 0x61, 0x6c, 0x5a, 0x00, 0x20, 0x6c, -0x79, 0x81, 0x00, 0x82, 0x69, 0x74, 0x73, 0x00, 0x70, 0x61, -0x74, 0x68, 0x44, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x51, 0x00, -0x70, 0x28, 0x62, 0x75, 0x74, 0x00, 0x69, 0x66, 0x0b, 0x00, -0x14, 0x69, 0x6a, 0x00, 0x14, 0x00, 0x9a, 0x00, 0x26, 0x6c, -0x79, 0x75, 0x00, 0x03, 0xd1, 0x00, 0x85, 0x72, 0x6f, 0x75, -0x67, 0x68, 0x00, 0x61, 0x00, 0xbd, 0x00, 0x80, 0x67, 0x61, -0x70, 0x00, 0x62, 0x65, 0x74, 0x77, 0x6d, 0x01, 0x91, 0x74, -0x77, 0x6f, 0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x7e, 0x00, -0x06, 0x2f, 0x01, 0x00, 0x6d, 0x00, 0xc1, 0x70, 0x69, 0x6e, -0x67, 0x29, 0x2e, 0x00, 0x41, 0x6c, 0x73, 0x6f, 0x2c, 0xb3, -0x00, 0x00, 0x7f, 0x01, 0x00, 0xea, 0x00, 0x71, 0x73, 0x71, -0x75, 0x61, 0x72, 0x65, 0x73, 0xbc, 0x01, 0x11, 0x60, 0xc2, -0x00, 0x76, 0x27, 0x3b, 0x00, 0x77, 0x68, 0x65, 0x6e, 0x08, -0x01, 0x00, 0x7c, 0x00, 0x50, 0x73, 0x00, 0x6f, 0x6e, 0x00, -0x6e, 0x01, 0x01, 0x4e, 0x00, 0x06, 0x98, 0x00, 0x01, 0xc9, -0x00, 0x03, 0xb8, 0x00, 0x70, 0x6e, 0x6f, 0x00, 0x6d, 0x61, -0x74, 0x74, 0x80, 0x00, 0x36, 0x68, 0x61, 0x74, 0x58, 0x01, -0x01, 0x2d, 0x00, 0x52, 0x61, 0x73, 0x00, 0x67, 0x6f, 0xb5, -0x01, 0x30, 0x2e, 0x00, 0x47, 0xce, 0x01, 0x52, 0x64, 0x6f, -0x00, 0x6e, 0x6f, 0x9e, 0x00, 0x05, 0x6c, 0x00, 0x10, 0x3b, -0x2c, 0x00, 0x50, 0x70, 0x69, 0x63, 0x6b, 0x73, 0x13, 0x00, -0xd1, 0x6d, 0x00, 0x75, 0x70, 0x00, 0x61, 0x6e, 0x64, 0x00, -0x6b, 0x65, 0x65, 0x70, 0x82, 0x00, 0x01, 0x43, 0x00, 0x00, -0xe9, 0x01, 0x19, 0x52, 0x03, 0x02, 0x01, 0x01, 0x02, 0x00, -0x42, 0x01, 0xb0, 0x66, 0x61, 0x74, 0x61, 0x6c, 0x2e, 0x00, -0x45, 0x76, 0x65, 0x6e, 0x57, 0x01, 0x31, 0x79, 0x6f, 0x75, -0x4e, 0x00, 0x42, 0x65, 0x64, 0x00, 0x75, 0x65, 0x00, 0x40, -0x6c, 0x61, 0x73, 0x74, 0x4d, 0x02, 0x00, 0x93, 0x01, 0x01, -0xff, 0x00, 0x32, 0x61, 0x6d, 0x65, 0x5d, 0x01, 0x70, 0x77, -0x68, 0x69, 0x63, 0x68, 0x00, 0x74, 0xfa, 0x00, 0x33, 0x68, -0x69, 0x74, 0x54, 0x00, 0x12, 0x2c, 0x7d, 0x02, 0x00, 0x25, -0x00, 0x03, 0xfc, 0x01, 0x31, 0x75, 0x6e, 0x74, 0x57, 0x00, -0xa1, 0x61, 0x73, 0x00, 0x64, 0x65, 0x61, 0x64, 0x00, 0x72, -0x61, 0x72, 0x01, 0xe1, 0x74, 0x68, 0x61, 0x6e, 0x00, 0x76, -0x69, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x6f, 0x75, 0x8c, 0x02, -0x43, 0x54, 0x68, 0x69, 0x73, 0x3b, 0x00, 0x81, 0x61, 0x73, -0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0xd5, 0x01, 0xf0, 0x16, -0x00, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, -0x65, 0x64, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x57, 0x69, 0x6e, -0x64, 0x6f, 0x77, 0x73, 0x00, 0x62, 0x79, 0x00, 0x42, 0x65, -0x6e, 0x00, 0x4f, 0x6c, 0x6d, 0x73, 0x74, 0x5b, 0x00, 0x91, -0x5b, 0x31, 0x31, 0x5d, 0x2c, 0x00, 0x77, 0x68, 0x6f, 0x41, -0x00, 0x71, 0x6b, 0x69, 0x6e, 0x64, 0x00, 0x65, 0x6e, 0x01, -0x02, 0xb0, 0x74, 0x6f, 0x00, 0x72, 0x65, 0x6c, 0x65, 0x61, -0x73, 0x65, 0x00, 0x65, 0x00, 0xb0, 0x73, 0x6f, 0x75, 0x72, -0x63, 0x65, 0x00, 0x63, 0x6f, 0x64, 0x65, 0x25, 0x01, 0xa0, -0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x73, 0x6f, -0x97, 0x00, 0x10, 0x74, 0x53, 0x01, 0xcc, 0x63, 0x6f, 0x75, -0x6c, 0x64, 0x00, 0x62, 0x65, 0x00, 0x72, 0x65, 0x2d, 0x7f, -0x00, 0x10, 0x74, 0x43, 0x00, 0x03, 0x70, 0x03, 0x01, 0x06, -0x03, 0x11, 0x00, 0x7a, 0x00, 0xf5, 0x09, 0x00, 0x68, 0x74, -0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x78, 0x6e, 0x31, 0x33, 0x2e, -0x63, 0x6f, 0x6d, 0x2f, 0x00, 0x00, 0x00, 0x32, 0x34, 0x2e, -0x31, 0xf5, 0x03, 0x00, 0x08, 0x03, 0x5f, 0x72, 0x6f, 0x6c, -0x73, 0x20, 0x78, 0x03, 0x0e, 0x02, 0x6a, 0x02, 0x47, 0x65, -0x69, 0x67, 0x68, 0x16, 0x02, 0x40, 0x73, 0x00, 0x75, 0x73, -0xc2, 0x01, 0x00, 0x1b, 0x00, 0xe0, 0x6e, 0x75, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x00, 0x6b, 0x65, 0x79, 0x70, 0x61, 0x64, -0xa7, 0x02, 0x91, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, -0x76, 0x65, 0x05, 0x03, 0x02, 0xca, 0x01, 0x52, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0xc6, 0x01, 0xf2, 0x03, 0x65, 0x66, 0x74, -0x00, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x62, 0x75, 0x74, -0x74, 0x6f, 0x6e, 0x00, 0x6f, 0xcf, 0x01, 0x00, 0x5e, 0x04, -0x16, 0x2c, 0x81, 0x00, 0x01, 0xb4, 0x01, 0x31, 0x62, 0x65, -0x67, 0x7a, 0x04, 0x01, 0x9c, 0x00, 0x23, 0x69, 0x6e, 0x4f, -0x04, 0x38, 0x6e, 0x65, 0x72, 0xfc, 0x03, 0x00, 0xa5, 0x00, -0x56, 0x77, 0x68, 0x65, 0x72, 0x65, 0x6a, 0x00, 0x20, 0x65, -0x64, 0x0b, 0x01, 0x12, 0x49, 0x7c, 0x00, 0x22, 0x75, 0x73, -0xd8, 0x00, 0xb3, 0x60, 0x53, 0x6f, 0x6c, 0x76, 0x65, 0x27, -0x00, 0x66, 0x75, 0x6e, 0x38, 0x00, 0x00, 0x51, 0x00, 0x03, -0xe9, 0x01, 0x02, 0x7a, 0x00, 0x74, 0x70, 0x72, 0x6f, 0x67, -0x72, 0x61, 0x6d, 0x31, 0x02, 0x40, 0x6d, 0x70, 0x75, 0x74, -0x17, 0x05, 0x01, 0xfd, 0x03, 0x04, 0xc2, 0x03, 0x04, 0xac, -0x00, 0x03, 0x76, 0x02, 0x03, 0x7e, 0x01, 0x15, 0x73, 0xef, -0x04, 0x51, 0x72, 0x65, 0x6d, 0x61, 0x69, 0xe1, 0x02, 0x01, -0xf9, 0x04, 0x00, 0x04, 0x03, 0x61, 0x72, 0x65, 0x74, 0x75, -0x72, 0x6e, 0x1d, 0x05, 0x00, 0x22, 0x00, 0xc2, 0x63, 0x75, -0x72, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x70, 0x6f, 0x73, 0x69, -0xb7, 0x01, 0xc2, 0x41, 0x00, 0x68, 0x69, 0x6e, 0x74, 0x00, -0x61, 0x72, 0x72, 0x6f, 0x77, 0x7d, 0x00, 0x64, 0x61, 0x70, -0x70, 0x65, 0x61, 0x72, 0x1c, 0x01, 0x03, 0x93, 0x01, 0x54, -0x64, 0x69, 0x63, 0x61, 0x74, 0x79, 0x01, 0x07, 0xa4, 0x03, -0x13, 0x6e, 0x8c, 0x00, 0x00, 0xee, 0x00, 0x21, 0x73, 0x68, -0x30, 0x02, 0x02, 0xce, 0x01, 0x13, 0x6f, 0x42, 0x01, 0x04, -0xea, 0x00, 0x00, 0xc9, 0x00, 0x14, 0x2e, 0x18, 0x01, 0x01, -0x30, 0x03, 0x06, 0x5a, 0x01, 0x08, 0xf7, 0x03, 0x02, 0x0e, -0x01, 0x07, 0x8f, 0x00, 0x51, 0x75, 0x70, 0x64, 0x61, 0x74, -0x51, 0x00, 0x03, 0x86, 0x00, 0x12, 0x65, 0xfd, 0x01, 0x28, -0x65, 0x78, 0x2d, 0x04, 0x03, 0xae, 0x00, 0x02, 0x66, 0x00, -0x04, 0x58, 0x02, 0xf1, 0x01, 0x61, 0x6c, 0x73, 0x6f, 0x00, -0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x61, 0x63, -0x65, 0x8b, 0x04, 0x81, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, -0x69, 0x63, 0x55, 0x03, 0x08, 0xde, 0x01, 0x09, 0xd6, 0x01, -0x00, 0x11, 0x00, 0x06, 0x19, 0x01, 0x05, 0xb9, 0x00, 0x04, -0x30, 0x00, 0x00, 0x4c, 0x05, 0x31, 0x66, 0x66, 0x65, 0x4c, -0x01, 0x06, 0x38, 0x00, 0x41, 0x66, 0x72, 0x6f, 0x6d, 0x3a, -0x00, 0x30, 0x6f, 0x6e, 0x65, 0x0e, 0x01, 0x20, 0x77, 0x6e, -0x9e, 0x03, 0x05, 0xd0, 0x00, 0x12, 0x2c, 0x07, 0x00, 0x14, -0x73, 0x61, 0x02, 0x03, 0x23, 0x00, 0x20, 0x6f, 0x6e, 0xde, -0x03, 0x12, 0x66, 0xc0, 0x00, 0x41, 0x75, 0x7a, 0x7a, 0x6c, -0x94, 0x04, 0x21, 0x73, 0x74, 0x29, 0x05, 0x70, 0x6f, 0x6c, -0x76, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x02, 0x13, 0x41, 0xe6, -0x01, 0x13, 0x61, 0x09, 0x03, 0x90, 0x64, 0x65, 0x73, 0x63, -0x72, 0x69, 0x62, 0x65, 0x64, 0x91, 0x00, 0x13, 0x73, 0x83, -0x00, 0x32, 0x32, 0x2e, 0x31, 0x51, 0x07, 0x00, 0xfb, 0x00, -0x52, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x3f, 0x00, 0xd5, 0x49, -0x6e, 0x00, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, -0x61, 0x72, 0x1c, 0x03, 0x20, 0x64, 0x6f, 0x16, 0x07, 0x09, -0x0f, 0x05, 0x00, 0x35, 0x02, 0x63, 0x64, 0x69, 0x65, 0x2c, -0x00, 0x79, 0x45, 0x01, 0x04, 0xc4, 0x02, 0x46, 0x55, 0x6e, -0x64, 0x6f, 0xc1, 0x02, 0x02, 0x5c, 0x02, 0x90, 0x73, 0x75, -0x6d, 0x65, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x1a, 0x02, 0x01, -0xfe, 0x00, 0x52, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x31, 0x00, -0x01, 0x56, 0x05, 0x01, 0x32, 0x01, 0x39, 0x2e, 0x00, 0x54, -0x10, 0x05, 0x00, 0x99, 0x05, 0x64, 0x00, 0x74, 0x72, 0x61, -0x63, 0x6b, 0x6b, 0x01, 0x61, 0x6e, 0x75, 0x6d, 0x62, 0x65, -0x72, 0x0e, 0x00, 0x41, 0x69, 0x6d, 0x65, 0x73, 0x7d, 0x00, -0x60, 0x68, 0x61, 0x76, 0x65, 0x00, 0x64, 0x4b, 0x01, 0x00, -0x41, 0x02, 0x12, 0x2e, 0x49, 0x04, 0x15, 0x32, 0x49, 0x04, -0xb1, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, -0x73, 0x20, 0x37, 0x05, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, -0x00, 0x02, 0x05, 0x01, 0x04, 0x00, 0x01, 0x06, 0x9a, 0x01, -0xe8, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x3b, 0x02, 0xb0, 0x60, 0x54, -0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x6c, -0x00, 0x82, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, -0x80, 0x04, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xfe, 0x06, -0x01, 0x80, 0x03, 0x00, 0x71, 0x01, 0x80, 0x71, 0x75, 0x61, -0x72, 0x65, 0x73, 0x2e, 0x00, +0x61, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x0b, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x61, +0x00, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x00, 0x67, 0x72, 0x65, +0x65, 0x6e, 0x00, 0x62, 0x0b, 0x00, 0xf0, 0x15, 0x73, 0x69, +0x74, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x69, 0x6e, 0x00, 0x61, +0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x66, 0x75, 0x6c, 0x6c, +0x00, 0x6f, 0x66, 0x00, 0x6f, 0x62, 0x73, 0x74, 0x61, 0x63, +0x6c, 0x65, 0x73, 0x2e, 0x40, 0x00, 0xf0, 0x05, 0x72, 0x00, +0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, +0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x00, 0x40, 0x00, +0xf2, 0x06, 0x74, 0x68, 0x65, 0x00, 0x67, 0x65, 0x6d, 0x73, +0x00, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x00, 0x72, +0x75, 0x6e, 0x6e, 0x51, 0x00, 0xa0, 0x74, 0x6f, 0x00, 0x61, +0x6e, 0x79, 0x00, 0x6d, 0x69, 0x6e, 0x44, 0x00, 0x02, 0x86, +0x00, 0x81, 0x63, 0x61, 0x6e, 0x00, 0x6d, 0x6f, 0x76, 0x65, +0x38, 0x00, 0x01, 0x81, 0x00, 0x21, 0x69, 0x6e, 0x26, 0x00, +0xf2, 0x02, 0x6f, 0x72, 0x74, 0x68, 0x6f, 0x67, 0x6f, 0x6e, +0x61, 0x6c, 0x00, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x61, 0x0c, +0x00, 0xe7, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, +0x6e, 0x2e, 0x00, 0x4f, 0x6e, 0x63, 0x37, 0x00, 0x60, 0x73, +0x74, 0x61, 0x72, 0x74, 0x73, 0x4c, 0x00, 0xf0, 0x13, 0x69, +0x6e, 0x67, 0x2c, 0x00, 0x69, 0x74, 0x00, 0x77, 0x69, 0x6c, +0x6c, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, +0x00, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x00, 0x73, 0x6f, 0x6d, +0x65, 0x74, 0x68, 0x8f, 0x00, 0xf4, 0x00, 0x73, 0x74, 0x6f, +0x70, 0x73, 0x00, 0x69, 0x74, 0x2e, 0x00, 0x41, 0x00, 0x77, +0x61, 0x6c, 0x5a, 0x00, 0x20, 0x6c, 0x79, 0x81, 0x00, 0x82, +0x69, 0x74, 0x73, 0x00, 0x70, 0x61, 0x74, 0x68, 0x44, 0x00, +0x00, 0x2b, 0x00, 0x00, 0x51, 0x00, 0x70, 0x28, 0x62, 0x75, +0x74, 0x00, 0x69, 0x66, 0x0b, 0x00, 0x14, 0x69, 0x6a, 0x00, +0x14, 0x00, 0x9a, 0x00, 0x26, 0x6c, 0x79, 0x75, 0x00, 0x03, +0xd1, 0x00, 0x85, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x61, +0x00, 0xbd, 0x00, 0x80, 0x67, 0x61, 0x70, 0x00, 0x62, 0x65, +0x74, 0x77, 0x6d, 0x01, 0x91, 0x74, 0x77, 0x6f, 0x00, 0x6f, +0x74, 0x68, 0x65, 0x72, 0x7e, 0x00, 0x06, 0x2f, 0x01, 0x00, +0x6d, 0x00, 0xc1, 0x70, 0x69, 0x6e, 0x67, 0x29, 0x2e, 0x00, +0x41, 0x6c, 0x73, 0x6f, 0x2c, 0xb3, 0x00, 0x00, 0x7f, 0x01, +0x00, 0xea, 0x00, 0x71, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x73, 0xbc, 0x01, 0x11, 0x60, 0xc2, 0x00, 0x76, 0x27, 0x3b, +0x00, 0x77, 0x68, 0x65, 0x6e, 0x08, 0x01, 0x00, 0x7c, 0x00, +0x50, 0x73, 0x00, 0x6f, 0x6e, 0x00, 0x6e, 0x01, 0x01, 0x4e, +0x00, 0x06, 0x98, 0x00, 0x01, 0xc9, 0x00, 0x03, 0xb8, 0x00, +0x70, 0x6e, 0x6f, 0x00, 0x6d, 0x61, 0x74, 0x74, 0x80, 0x00, +0x36, 0x68, 0x61, 0x74, 0x58, 0x01, 0x01, 0x2d, 0x00, 0x52, +0x61, 0x73, 0x00, 0x67, 0x6f, 0xb5, 0x01, 0x30, 0x2e, 0x00, +0x47, 0xce, 0x01, 0x52, 0x64, 0x6f, 0x00, 0x6e, 0x6f, 0x9e, +0x00, 0x05, 0x6c, 0x00, 0x10, 0x3b, 0x2c, 0x00, 0x50, 0x70, +0x69, 0x63, 0x6b, 0x73, 0x13, 0x00, 0xd1, 0x6d, 0x00, 0x75, +0x70, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x6b, 0x65, 0x65, 0x70, +0x82, 0x00, 0x01, 0x43, 0x00, 0x00, 0xe9, 0x01, 0x19, 0x52, +0x03, 0x02, 0x01, 0x01, 0x02, 0x00, 0x42, 0x01, 0xb0, 0x66, +0x61, 0x74, 0x61, 0x6c, 0x2e, 0x00, 0x45, 0x76, 0x65, 0x6e, +0x57, 0x01, 0x31, 0x79, 0x6f, 0x75, 0x4e, 0x00, 0x42, 0x65, +0x64, 0x00, 0x75, 0x65, 0x00, 0x40, 0x6c, 0x61, 0x73, 0x74, +0x4d, 0x02, 0x00, 0x93, 0x01, 0x01, 0xff, 0x00, 0x32, 0x61, +0x6d, 0x65, 0x5d, 0x01, 0x70, 0x77, 0x68, 0x69, 0x63, 0x68, +0x00, 0x74, 0xfa, 0x00, 0x33, 0x68, 0x69, 0x74, 0x54, 0x00, +0x12, 0x2c, 0x7d, 0x02, 0x00, 0x25, 0x00, 0x03, 0xfc, 0x01, +0x31, 0x75, 0x6e, 0x74, 0x57, 0x00, 0xa1, 0x61, 0x73, 0x00, +0x64, 0x65, 0x61, 0x64, 0x00, 0x72, 0x61, 0x72, 0x01, 0xe1, +0x74, 0x68, 0x61, 0x6e, 0x00, 0x76, 0x69, 0x63, 0x74, 0x6f, +0x72, 0x69, 0x6f, 0x75, 0x8c, 0x02, 0x43, 0x54, 0x68, 0x69, +0x73, 0x3b, 0x00, 0x81, 0x61, 0x73, 0x00, 0x6f, 0x72, 0x69, +0x67, 0x69, 0xd5, 0x01, 0xf0, 0x16, 0x00, 0x69, 0x6d, 0x70, +0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x00, 0x66, +0x6f, 0x72, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, +0x00, 0x62, 0x79, 0x00, 0x42, 0x65, 0x6e, 0x00, 0x4f, 0x6c, +0x6d, 0x73, 0x74, 0x5b, 0x00, 0x91, 0x5b, 0x31, 0x31, 0x5d, +0x2c, 0x00, 0x77, 0x68, 0x6f, 0x41, 0x00, 0x71, 0x6b, 0x69, +0x6e, 0x64, 0x00, 0x65, 0x6e, 0x01, 0x02, 0xb0, 0x74, 0x6f, +0x00, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x00, 0x65, +0x00, 0xb0, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x63, +0x6f, 0x64, 0x65, 0x25, 0x01, 0xa0, 0x72, 0x65, 0x71, 0x75, +0x65, 0x73, 0x74, 0x00, 0x73, 0x6f, 0x97, 0x00, 0x10, 0x74, +0x53, 0x01, 0xcc, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x62, +0x65, 0x00, 0x72, 0x65, 0x2d, 0x7f, 0x00, 0x10, 0x74, 0x43, +0x00, 0x03, 0x70, 0x03, 0x01, 0x06, 0x03, 0x11, 0x00, 0x7a, +0x00, 0xf5, 0x09, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +0x2f, 0x78, 0x6e, 0x31, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, +0x00, 0x00, 0x00, 0x32, 0x34, 0x2e, 0x31, 0x09, 0x04, 0x00, +0x08, 0x03, 0x5f, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x78, 0x03, +0x0e, 0x02, 0x6a, 0x02, 0x47, 0x65, 0x69, 0x67, 0x68, 0x16, +0x02, 0x40, 0x73, 0x00, 0x75, 0x73, 0xc2, 0x01, 0x00, 0x1b, +0x00, 0xe0, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x00, +0x6b, 0x65, 0x79, 0x70, 0x61, 0x64, 0xa7, 0x02, 0x91, 0x74, +0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x05, 0x03, +0x02, 0xca, 0x01, 0x52, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xc6, +0x01, 0xf2, 0x03, 0x65, 0x66, 0x74, 0x00, 0x6d, 0x6f, 0x75, +0x73, 0x65, 0x00, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x00, +0x6f, 0xcf, 0x01, 0x00, 0x5e, 0x04, 0x16, 0x2c, 0x81, 0x00, +0x01, 0xb4, 0x01, 0x31, 0x62, 0x65, 0x67, 0x7a, 0x04, 0x01, +0x9c, 0x00, 0x23, 0x69, 0x6e, 0x4f, 0x04, 0x38, 0x6e, 0x65, +0x72, 0xfc, 0x03, 0x00, 0xa5, 0x00, 0x56, 0x77, 0x68, 0x65, +0x72, 0x65, 0x6a, 0x00, 0x20, 0x65, 0x64, 0x0b, 0x01, 0x12, +0x49, 0x7c, 0x00, 0x22, 0x75, 0x73, 0xd8, 0x00, 0xb3, 0x60, +0x53, 0x6f, 0x6c, 0x76, 0x65, 0x27, 0x00, 0x66, 0x75, 0x6e, +0x38, 0x00, 0x00, 0x51, 0x00, 0x03, 0xe9, 0x01, 0x02, 0x7a, +0x00, 0x74, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x31, +0x02, 0x40, 0x6d, 0x70, 0x75, 0x74, 0x17, 0x05, 0x01, 0xfd, +0x03, 0x04, 0xc2, 0x03, 0x04, 0xac, 0x00, 0x03, 0x76, 0x02, +0x03, 0x7e, 0x01, 0x15, 0x73, 0xef, 0x04, 0x51, 0x72, 0x65, +0x6d, 0x61, 0x69, 0xe1, 0x02, 0x01, 0xf9, 0x04, 0x00, 0x04, +0x03, 0x61, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x1d, 0x05, +0x00, 0x22, 0x00, 0xc2, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, +0x74, 0x00, 0x70, 0x6f, 0x73, 0x69, 0xb7, 0x01, 0xc2, 0x41, +0x00, 0x68, 0x69, 0x6e, 0x74, 0x00, 0x61, 0x72, 0x72, 0x6f, +0x77, 0x7d, 0x00, 0x64, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, +0x1c, 0x01, 0x03, 0x93, 0x01, 0x54, 0x64, 0x69, 0x63, 0x61, +0x74, 0x79, 0x01, 0x07, 0xa4, 0x03, 0x13, 0x6e, 0x8c, 0x00, +0x00, 0xee, 0x00, 0x21, 0x73, 0x68, 0x30, 0x02, 0x02, 0xce, +0x01, 0x13, 0x6f, 0x42, 0x01, 0x04, 0xea, 0x00, 0x00, 0xc9, +0x00, 0x14, 0x2e, 0x18, 0x01, 0x01, 0x30, 0x03, 0x06, 0x5a, +0x01, 0x08, 0xf7, 0x03, 0x02, 0x0e, 0x01, 0x07, 0x8f, 0x00, +0x51, 0x75, 0x70, 0x64, 0x61, 0x74, 0x51, 0x00, 0x03, 0x86, +0x00, 0x12, 0x65, 0xfd, 0x01, 0x28, 0x65, 0x78, 0x2d, 0x04, +0x03, 0xae, 0x00, 0x02, 0x66, 0x00, 0x04, 0x58, 0x02, 0xf1, +0x01, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x70, 0x72, 0x65, 0x73, +0x73, 0x00, 0x53, 0x70, 0x61, 0x63, 0x65, 0x8b, 0x04, 0x81, +0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x03, +0x08, 0xde, 0x01, 0x09, 0xd6, 0x01, 0x00, 0x11, 0x00, 0x06, +0x19, 0x01, 0x05, 0xb9, 0x00, 0x04, 0x30, 0x00, 0x00, 0x4c, +0x05, 0x31, 0x66, 0x66, 0x65, 0x4c, 0x01, 0x06, 0x38, 0x00, +0x41, 0x66, 0x72, 0x6f, 0x6d, 0x3a, 0x00, 0x30, 0x6f, 0x6e, +0x65, 0x0e, 0x01, 0x20, 0x77, 0x6e, 0x9e, 0x03, 0x05, 0xd0, +0x00, 0x12, 0x2c, 0x07, 0x00, 0x14, 0x73, 0x61, 0x02, 0x03, +0x23, 0x00, 0x20, 0x6f, 0x6e, 0xde, 0x03, 0x12, 0x66, 0xc0, +0x00, 0x41, 0x75, 0x7a, 0x7a, 0x6c, 0x94, 0x04, 0x21, 0x73, +0x74, 0x29, 0x05, 0x70, 0x6f, 0x6c, 0x76, 0x61, 0x62, 0x6c, +0x65, 0x54, 0x02, 0x13, 0x41, 0xe6, 0x01, 0x13, 0x61, 0x09, +0x03, 0x90, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0x91, 0x00, 0x13, 0x73, 0x83, 0x00, 0x32, 0x32, 0x2e, +0x31, 0x51, 0x07, 0x00, 0xfb, 0x00, 0x52, 0x61, 0x76, 0x61, +0x69, 0x6c, 0x3f, 0x00, 0xd5, 0x49, 0x6e, 0x00, 0x70, 0x61, +0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x1c, 0x03, +0x20, 0x64, 0x6f, 0x16, 0x07, 0x09, 0x0f, 0x05, 0x00, 0x35, +0x02, 0x63, 0x64, 0x69, 0x65, 0x2c, 0x00, 0x79, 0x45, 0x01, +0x04, 0xc4, 0x02, 0x46, 0x55, 0x6e, 0x64, 0x6f, 0xc1, 0x02, +0x02, 0x5c, 0x02, 0x90, 0x73, 0x75, 0x6d, 0x65, 0x00, 0x70, +0x6c, 0x61, 0x79, 0x1a, 0x02, 0x01, 0xfe, 0x00, 0x52, 0x62, +0x65, 0x66, 0x6f, 0x72, 0x31, 0x00, 0x01, 0x56, 0x05, 0x01, +0x32, 0x01, 0x39, 0x2e, 0x00, 0x54, 0x10, 0x05, 0x00, 0x99, +0x05, 0x64, 0x00, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x6b, 0x01, +0x61, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x0e, 0x00, 0x41, +0x69, 0x6d, 0x65, 0x73, 0x7d, 0x00, 0x60, 0x68, 0x61, 0x76, +0x65, 0x00, 0x64, 0x4b, 0x01, 0x00, 0x41, 0x02, 0x12, 0x2e, +0x49, 0x04, 0x15, 0x32, 0x49, 0x04, 0xb1, 0x70, 0x61, 0x72, +0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x37, 0x05, +0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x05, 0x01, +0x04, 0x00, 0x01, 0x06, 0x9a, 0x01, 0xe8, 0x60, 0x43, 0x75, +0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, +0x70, 0x3b, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0x6c, 0x00, 0x82, 0x57, 0x69, +0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x80, 0x04, 0x51, 0x00, +0x00, 0x53, 0x69, 0x7a, 0xfe, 0x06, 0x01, 0x80, 0x03, 0x00, +0x71, 0x01, 0x80, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, +0x00, }; -const unsigned short help_text_len = 2266; -const unsigned short help_text_words = 430; +const unsigned short help_text_len = 2286; +const unsigned short help_text_words = 431; const char quick_help_text[] = "Collect all the gems without running into any of the mines."; diff --git a/apps/plugins/puzzles/help/keen.c b/apps/plugins/puzzles/help/keen.c index 58a5f0b2af..9152fed158 100644 --- a/apps/plugins/puzzles/help/keen.c +++ b/apps/plugins/puzzles/help/keen.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,257 +6,258 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 324, TEXT_CENTER | C_RED }, - { 391, TEXT_UNDERLINE }, - { 649, TEXT_CENTER | C_RED }, - { 666, TEXT_UNDERLINE }, - { 698, TEXT_UNDERLINE }, - { 737, TEXT_UNDERLINE }, + { 325, TEXT_CENTER | C_RED }, + { 392, TEXT_UNDERLINE }, + { 650, TEXT_CENTER | C_RED }, + { 667, TEXT_UNDERLINE }, + { 699, TEXT_UNDERLINE }, + { 738, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 3952 comp 2376 ratio 0.601215 level 10 saved 1576 */ +/* orig 3969 comp 2383 ratio 0.600403 level 10 saved 1586 */ const char help_text[] = { -0xf4, 0x21, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfb, 0x04, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x30, 0x3a, 0x20, 0x4b, 0x65, 0x65, 0x6e, 0x20, 0x00, -0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, -0x00, 0x61, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, -0x67, 0x72, 0x69, 0x64, 0x3b, 0x00, 0x65, 0x61, 0x63, 0x68, -0x12, 0x00, 0xf1, 0x1a, 0x6d, 0x61, 0x79, 0x00, 0x63, 0x6f, -0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x64, 0x69, -0x67, 0x69, 0x74, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x31, -0x00, 0x74, 0x6f, 0x00, 0x74, 0x68, 0x65, 0x00, 0x73, 0x69, -0x7a, 0x65, 0x00, 0x6f, 0x66, 0x0c, 0x00, 0x00, 0x40, 0x00, -0x33, 0x2e, 0x00, 0x54, 0x0a, 0x00, 0xf0, 0x08, 0x00, 0x69, -0x73, 0x00, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x00, -0x69, 0x6e, 0x74, 0x6f, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, -0x73, 0x2d, 0x00, 0xf1, 0x02, 0x76, 0x61, 0x72, 0x79, 0x69, -0x6e, 0x67, 0x00, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x61, -0x6e, 0x64, 0x47, 0x00, 0xf0, 0x13, 0x2c, 0x00, 0x77, 0x69, -0x74, 0x68, 0x00, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, -0x74, 0x69, 0x63, 0x00, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x00, -0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x69, 0x6e, -0x66, 0x00, 0x20, 0x6d, 0x2e, 0xba, 0x00, 0x50, 0x72, 0x00, -0x61, 0x69, 0x6d, 0x62, 0x00, 0xf5, 0x02, 0x74, 0x6f, 0x00, -0x66, 0x75, 0x6c, 0x6c, 0x79, 0x00, 0x70, 0x6f, 0x70, 0x75, -0x6c, 0x61, 0x74, 0x65, 0x8a, 0x00, 0x02, 0x4e, 0x00, 0x01, -0xb4, 0x00, 0xf0, 0x03, 0x73, 0x00, 0x73, 0x75, 0x63, 0x68, -0x00, 0x74, 0x68, 0x61, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, -0x00, 0x45, 0xe4, 0x00, 0x34, 0x72, 0x6f, 0x77, 0xdd, 0x00, -0xf1, 0x05, 0x73, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, -0x6e, 0x65, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, -0x6e, 0x63, 0xd7, 0x00, 0x01, 0x0d, 0x01, 0x02, 0xf8, 0x00, -0x05, 0x38, 0x00, 0x6f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, -0x3b, 0x00, 0x1d, 0x00, 0x17, 0x01, 0x03, 0x8d, 0x00, 0x22, -0x69, 0x6e, 0x1d, 0x00, 0x01, 0x11, 0x01, 0xf1, 0x01, 0x00, -0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x63, 0x6f, 0x6d, -0x62, 0x69, 0x6e, 0x65, 0x64, 0xd2, 0x00, 0x31, 0x6f, 0x72, -0x6d, 0xc8, 0x00, 0xd3, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, -0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x01, 0x01, 0x01, -0x16, 0x01, 0x40, 0x2c, 0x00, 0x75, 0x73, 0x42, 0x01, 0x00, -0x10, 0x00, 0x07, 0x31, 0x01, 0xf8, 0x00, 0x6f, 0x70, 0x65, -0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x67, 0x69, 0x76, -0x65, 0x6e, 0x32, 0x00, 0x00, 0x99, 0x01, 0x52, 0x61, 0x74, -0x00, 0x69, 0x73, 0x02, 0x01, 0x71, 0x41, 0x6e, 0x00, 0x61, -0x64, 0x64, 0x69, 0x2c, 0x00, 0x00, 0x1f, 0x00, 0x61, 0x00, -0x6d, 0x65, 0x61, 0x6e, 0x73, 0x23, 0x01, 0x02, 0xd8, 0x01, -0x24, 0x75, 0x6d, 0xd7, 0x01, 0x06, 0xb6, 0x00, 0x00, 0x0e, -0x00, 0x02, 0xb5, 0x00, 0x63, 0x6d, 0x75, 0x73, 0x74, 0x00, -0x62, 0x6d, 0x01, 0x01, 0x6b, 0x00, 0x02, 0xab, 0x00, 0xf5, -0x05, 0x2e, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, -0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x00, 0x60, 0x31, 0x35, 0x2b, -0x27, 0x5b, 0x00, 0x11, 0x65, 0x34, 0x01, 0x31, 0x65, 0x6e, -0x74, 0x05, 0x02, 0x06, 0x4d, 0x00, 0x71, 0x61, 0x64, 0x64, -0x73, 0x00, 0x75, 0x70, 0xfa, 0x00, 0x72, 0x69, 0x66, 0x74, -0x65, 0x65, 0x6e, 0x2e, 0xa4, 0x00, 0xb6, 0x00, 0x6d, 0x75, -0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x63, 0x61, 0xa9, 0x00, -0xfc, 0x09, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x00, 0x60, 0x36, -0x30, 0x2a, 0x27, 0x29, 0x2c, 0x00, 0x73, 0x69, 0x6d, 0x69, -0x6c, 0x61, 0x72, 0x6c, 0x79, 0x2c, 0xc2, 0x00, 0x7f, 0x70, -0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0xc6, 0x00, 0x23, 0x02, -0x7f, 0x00, 0x76, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, -0x7c, 0x00, 0xb0, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x61, 0x6c, -0x77, 0x61, 0x79, 0x73, 0x38, 0x00, 0x07, 0x9a, 0x02, 0x13, -0x61, 0x53, 0x00, 0x22, 0x6f, 0x66, 0x13, 0x03, 0x41, 0x74, -0x77, 0x6f, 0x2c, 0xda, 0x02, 0x28, 0x69, 0x74, 0x99, 0x00, -0x01, 0x27, 0x02, 0x0f, 0x91, 0x00, 0x07, 0xa0, 0x69, 0x73, -0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x2f, 0x00, -0x02, 0x1a, 0x00, 0x87, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, -0x62, 0x79, 0xa6, 0x00, 0x6c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, -0x74, 0x6c, 0x01, 0x3f, 0x32, 0x2d, 0x27, 0x6b, 0x00, 0x1b, -0x6b, 0x32, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x6a, 0x00, 0x20, -0x2c, 0x00, 0x55, 0x00, 0xb6, 0x71, 0x75, 0x69, 0x76, 0x61, -0x6c, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x4e, 0x00, 0x02, 0xcd, -0x02, 0x57, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x9a, 0x00, 0x00, -0x1a, 0x00, 0x00, 0x4d, 0x00, 0x02, 0xfa, 0x03, 0x34, 0x74, -0x77, 0x6f, 0x6f, 0x00, 0x50, 0x63, 0x6f, 0x75, 0x6c, 0x64, -0x27, 0x01, 0x21, 0x65, 0x69, 0x29, 0x00, 0xf4, 0x02, 0x77, -0x61, 0x79, 0x00, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x00, -0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x67, 0x01, 0x00, 0x26, -0x04, 0x1c, 0x73, 0xe0, 0x01, 0x2b, 0x33, 0x2f, 0xdf, 0x01, -0x24, 0x69, 0x73, 0x7a, 0x01, 0x0f, 0x6f, 0x01, 0x03, 0x01, -0x6e, 0x01, 0x0b, 0x00, 0x01, 0x02, 0xb2, 0x00, 0x04, 0x86, -0x04, 0x27, 0x62, 0x79, 0xb7, 0x00, 0x20, 0x69, 0x73, 0xe6, -0x00, 0x24, 0x61, 0x6c, 0xc9, 0x04, 0x0a, 0x5a, 0x01, 0x62, -0x00, 0x00, 0x4e, 0x6f, 0x74, 0x65, 0x49, 0x00, 0x04, 0x6c, -0x00, 0x08, 0x0d, 0x05, 0x01, 0x23, 0x03, 0x25, 0x61, 0x6d, -0x14, 0x01, 0x05, 0x48, 0x01, 0x10, 0x6f, 0xfe, 0x03, 0x42, -0x28, 0x70, 0x72, 0x6f, 0x73, 0x00, 0x00, 0x28, 0x00, 0x90, -0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x93, -0x00, 0x20, 0x73, 0x00, 0x58, 0x05, 0x48, 0x6e, 0x6f, 0x74, -0x00, 0x46, 0x00, 0x00, 0x8b, 0x04, 0x00, 0xbf, 0x00, 0x02, -0x5b, 0x04, 0x10, 0x29, 0x4b, 0x01, 0x61, 0x69, 0x73, 0x00, -0x72, 0x75, 0x6c, 0x5b, 0x01, 0x83, 0x70, 0x72, 0x65, 0x63, -0x69, 0x73, 0x65, 0x6c, 0xbf, 0x00, 0x65, 0x70, 0x70, 0x6f, -0x73, 0x69, 0x74, 0xdd, 0x01, 0x02, 0x26, 0x00, 0xf2, 0x0e, -0x6e, 0x00, 0x53, 0x6f, 0x6c, 0x6f, 0x27, 0x73, 0x00, 0x60, -0x4b, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x27, 0x00, 0x6d, 0x6f, -0x64, 0x65, 0x00, 0x28, 0x73, 0x65, 0x65, 0x00, 0x63, 0xfe, -0x05, 0x40, 0x00, 0x31, 0x31, 0x29, 0xda, 0x00, 0x01, 0x5c, -0x00, 0xd5, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x61, -0x70, 0x70, 0x65, 0x61, 0x72, 0x1b, 0x02, 0xb2, 0x54, 0x69, -0x6d, 0x65, 0x73, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x80, -0x04, 0x00, 0x9d, 0x00, 0x80, 0x60, 0x4b, 0x65, 0x6e, 0x4b, -0x65, 0x6e, 0x27, 0x3c, 0x00, 0x42, 0x33, 0x30, 0x2e, 0x31, -0x42, 0x06, 0x00, 0x0a, 0x01, 0x40, 0x72, 0x6f, 0x6c, 0x73, -0x4b, 0x06, 0x00, 0x11, 0x00, 0x00, 0xcd, 0x05, 0x50, 0x72, -0x65, 0x73, 0x00, 0x6d, 0x6a, 0x05, 0x32, 0x6f, 0x66, 0x00, -0x02, 0x02, 0x01, 0x24, 0x00, 0x72, 0x00, 0x73, 0x79, 0x73, -0x74, 0x65, 0x6d, 0x91, 0x05, 0x00, 0xa7, 0x00, 0x20, 0x00, -0x28, 0xed, 0x00, 0x21, 0x55, 0x6e, 0x81, 0x01, 0x02, 0x94, -0x00, 0x61, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x4a, 0x00, -0x01, 0xf6, 0x01, 0x91, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0x88, 0x00, 0x51, 0x6d, 0x6f, 0x75, 0x73, -0x65, 0xf8, 0x01, 0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, 0x70, -0x74, 0x79, 0xa2, 0x06, 0x21, 0x61, 0x6e, 0x65, 0x01, 0x65, -0x6e, 0x00, 0x74, 0x79, 0x70, 0x65, 0xa4, 0x06, 0x12, 0x6f, -0xcf, 0x00, 0x72, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, -0x54, 0x05, 0x00, 0xbb, 0x03, 0x01, 0xd0, 0x01, 0x02, 0x3a, -0x00, 0xc0, 0x2e, 0x00, 0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, -0x00, 0x6d, 0x61, 0x6b, 0x39, 0x00, 0x8f, 0x6d, 0x69, 0x73, -0x74, 0x61, 0x6b, 0x65, 0x2c, 0x76, 0x00, 0x01, 0x01, 0xc6, -0x01, 0x88, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, -0x7a, 0x00, 0xb0, 0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, -0x70, 0x61, 0x63, 0x65, 0x64, 0x00, 0x50, 0x63, 0x6c, 0x65, -0x61, 0x72, 0xf2, 0x03, 0x20, 0x61, 0x67, 0x25, 0x02, 0x62, -0x28, 0x6f, 0x72, 0x00, 0x75, 0x73, 0x5f, 0x04, 0xc1, 0x55, -0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, -0x65, 0xf2, 0x00, 0x03, 0x7e, 0x00, 0x62, 0x72, 0x69, 0x67, -0x68, 0x74, 0x2d, 0x74, 0x00, 0x01, 0xd8, 0x02, 0x0f, 0xd8, -0x00, 0x04, 0x02, 0x99, 0x04, 0x12, 0x2c, 0xc2, 0x00, 0x03, -0x17, 0x06, 0x01, 0x8e, 0x04, 0x00, 0x60, 0x03, 0x46, 0x6e, -0x74, 0x65, 0x72, 0x20, 0x06, 0x04, 0x42, 0x00, 0xf1, 0x02, -0x73, 0x00, 0x61, 0x00, 0x60, 0x70, 0x65, 0x6e, 0x63, 0x69, -0x6c, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x27, 0x3a, 0x07, 0x01, -0x70, 0x06, 0x01, 0xf8, 0x07, 0x07, 0x1b, 0x00, 0x10, 0x73, -0x73, 0x06, 0x04, 0x6e, 0x05, 0x04, 0x77, 0x06, 0x19, 0x73, -0xa3, 0x02, 0x04, 0x36, 0x01, 0x11, 0x53, 0x08, 0x00, 0x14, -0x73, 0x0a, 0x03, 0x00, 0x85, 0x06, 0x10, 0x66, 0x72, 0x02, -0x45, 0x64, 0x2d, 0x69, 0x6e, 0x39, 0x00, 0x30, 0x63, 0x61, -0x6e, 0xe3, 0x02, 0x45, 0x61, 0x6c, 0x73, 0x6f, 0x33, 0x03, -0x08, 0x6f, 0x00, 0x02, 0x87, 0x02, 0x30, 0x65, 0x00, 0x67, -0x5a, 0x00, 0x10, 0x70, 0xd4, 0x03, 0x40, 0x6e, 0x6f, 0x00, -0x61, 0x4c, 0x05, 0x01, 0x6c, 0x05, 0x29, 0x74, 0x6f, 0x2e, -0x00, 0x40, 0x2c, 0x00, 0x73, 0x6f, 0xe8, 0x04, 0x10, 0x63, -0x8e, 0x04, 0x10, 0x77, 0x01, 0x01, 0x00, 0x3a, 0x01, 0x03, -0x5a, 0x01, 0x11, 0x6d, 0xbb, 0x00, 0x14, 0x69, 0x41, 0x06, -0x63, 0x79, 0x6f, 0x75, 0x3a, 0x00, 0x79, 0xe7, 0x00, 0x05, -0x23, 0x00, 0x70, 0x61, 0x73, 0x00, 0x72, 0x65, 0x6d, 0x69, -0xd8, 0x02, 0x14, 0x73, 0xd5, 0x03, 0xa4, 0x70, 0x61, 0x72, -0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x32, 0x01, 0x41, -0x6e, 0x65, 0x65, 0x64, 0x52, 0x08, 0x60, 0x62, 0x65, 0x00, -0x72, 0x65, 0x2d, 0x5a, 0x05, 0x01, 0x92, 0x07, 0x01, 0xd4, -0x03, 0x00, 0x54, 0x00, 0x42, 0x6b, 0x6e, 0x6f, 0x77, 0xec, -0x03, 0x4b, 0x61, 0x62, 0x6f, 0x75, 0x45, 0x00, 0x04, 0xa2, -0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, 0x02, 0x36, 0x6c, 0x69, -0x73, 0xf8, 0x06, 0x6a, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, -0x6a, 0x01, 0x13, 0x61, 0x83, 0x04, 0x02, 0x8d, 0x00, 0x01, -0x48, 0x00, 0x50, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x62, 0x01, -0x32, 0x65, 0x6c, 0x73, 0x82, 0x00, 0x93, 0x66, 0x65, 0x65, -0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0x35, 0x03, 0x41, 0x65, -0x72, 0x61, 0x73, 0xc2, 0x09, 0x49, 0x69, 0x6e, 0x67, 0x6c, -0xd3, 0x01, 0x1c, 0x2c, 0x5b, 0x02, 0x08, 0x1b, 0x02, 0x22, -0x6e, 0x64, 0x58, 0x02, 0x05, 0xde, 0x01, 0x03, 0x52, 0x02, -0x01, 0xb8, 0x02, 0x00, 0x5b, 0x00, 0x3a, 0x41, 0x6c, 0x6c, -0x20, 0x02, 0x09, 0x9c, 0x02, 0x22, 0x72, 0x65, 0x79, 0x00, -0x30, 0x64, 0x00, 0x77, 0xa3, 0x02, 0x00, 0x99, 0x00, 0x34, -0x6c, 0x65, 0x66, 0x6c, 0x00, 0x05, 0x5e, 0x00, 0x18, 0x61, -0x14, 0x01, 0x0f, 0x2a, 0x00, 0x05, 0x02, 0x43, 0x03, 0x10, -0x73, 0x43, 0x03, 0x36, 0x2e, 0x00, 0x52, 0xb3, 0x00, 0x00, -0xf7, 0x00, 0x05, 0x20, 0x00, 0x01, 0x2d, 0x0a, 0x01, 0x66, -0x03, 0x03, 0x82, 0x07, 0x14, 0x73, 0xfb, 0x00, 0x0c, 0x56, -0x02, 0x12, 0x41, 0xcb, 0x02, 0x00, 0x66, 0x04, 0x12, 0x2c, -0x73, 0x08, 0x50, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x0b, 0x04, -0x14, 0x73, 0x6b, 0x09, 0x22, 0x75, 0x73, 0x2d, 0x03, 0x62, -0x63, 0x6f, 0x6e, 0x6a, 0x75, 0x6e, 0xdf, 0x07, 0x01, 0x9c, -0x04, 0x05, 0x2c, 0x07, 0x02, 0x2f, 0x00, 0x65, 0x74, 0x6f, -0x00, 0x73, 0x65, 0x74, 0xa4, 0x01, 0x2b, 0x6f, 0x72, 0x6e, -0x00, 0x3d, 0x55, 0x73, 0x65, 0x63, 0x00, 0x51, 0x74, 0x6f, -0x00, 0x6d, 0x6f, 0x55, 0x0b, 0x50, 0x68, 0x69, 0x67, 0x68, -0x6c, 0xd0, 0x00, 0x21, 0x00, 0x61, 0xf6, 0x06, 0x05, 0x99, -0x0a, 0x02, 0x18, 0x08, 0x09, 0xb0, 0x04, 0x22, 0x74, 0x6f, -0xc5, 0x03, 0x25, 0x00, 0x69, 0x18, 0x06, 0x05, 0x3f, 0x00, -0x25, 0x65, 0x64, 0x7c, 0x03, 0x14, 0x50, 0x0c, 0x01, 0x50, -0x72, 0x65, 0x74, 0x75, 0x72, 0x28, 0x03, 0x5a, 0x67, 0x67, -0x6c, 0x65, 0x73, 0x30, 0x00, 0x02, 0x6d, 0x0b, 0x12, 0x61, -0x00, 0x06, 0x85, 0x69, 0x6e, 0x00, 0x77, 0x68, 0x69, 0x63, -0x68, 0x93, 0x02, 0x02, 0x67, 0x00, 0x20, 0x6f, 0x72, 0x10, -0x03, 0x2e, 0x6f, 0x76, 0x40, 0x01, 0x05, 0x63, 0x00, 0x12, -0x4d, 0x6b, 0x01, 0x01, 0x37, 0x05, 0x01, 0xfd, 0x01, 0x00, -0x67, 0x0b, 0x01, 0x10, 0x01, 0x2d, 0x6f, 0x66, 0x1b, 0x02, -0x45, 0x65, 0x76, 0x65, 0x72, 0x93, 0x05, 0x01, 0x60, 0x03, -0x41, 0x64, 0x6f, 0x65, 0x73, 0xe7, 0x06, 0x03, 0x63, 0x0c, -0x10, 0x6d, 0x03, 0x04, 0x02, 0xed, 0x00, 0x41, 0x69, 0x6e, -0x00, 0x69, 0x63, 0x07, 0x10, 0x28, 0x66, 0x02, 0x01, 0xc2, -0x0a, 0x01, 0x84, 0x01, 0x92, 0x73, 0x00, 0x64, 0x65, 0x73, -0x63, 0x72, 0x69, 0x62, 0x9e, 0x01, 0x22, 0x73, 0x65, 0x9a, -0x01, 0x31, 0x32, 0x2e, 0x31, 0x72, 0x02, 0x01, 0xf5, 0x01, -0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, -0x2e, 0x29, 0x8e, 0x06, 0x12, 0x32, 0x8e, 0x06, 0xb2, 0x70, -0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, -0x5b, 0x04, 0x00, 0x1b, 0x02, 0x05, 0x14, 0x00, 0x02, 0x40, -0x00, 0x04, 0x3b, 0x00, 0x02, 0xc2, 0x0c, 0x00, 0x78, 0x00, -0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6e, 0x00, 0x03, 0x3a, 0x06, -0x50, 0x60, 0x54, 0x79, 0x70, 0x65, 0x4f, 0x09, 0x20, 0x6e, -0x75, 0xaa, 0x00, 0x51, 0x47, 0x72, 0x69, 0x64, 0x20, 0x69, -0x08, 0xbf, 0x00, 0x00, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, -0x69, 0x65, 0x73, 0x00, 0x0d, 0x04, 0xb0, 0x4c, 0x6f, 0x77, -0x65, 0x72, 0x00, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x97, 0x04, -0x68, 0x33, 0x3b, 0x00, 0x75, 0x70, 0x70, 0x12, 0x00, 0x74, -0x39, 0x00, 0x28, 0x62, 0x65, 0x63, 0x61, 0x1a, 0x06, 0x20, -0x75, 0x73, 0xf8, 0x01, 0x00, 0x97, 0x01, 0x11, 0x66, 0xe1, -0x02, 0x03, 0x36, 0x09, 0x42, 0x63, 0x6f, 0x6d, 0x65, 0x6c, -0x04, 0x40, 0x64, 0x69, 0x66, 0x66, 0x64, 0x04, 0x12, 0x74, -0xa5, 0x02, 0x12, 0x60, 0x5f, 0x09, 0x64, 0x27, 0x00, 0x62, -0x69, 0x67, 0x67, 0x29, 0x0a, 0x21, 0x39, 0x21, 0x55, 0x06, -0x14, 0x44, 0x2b, 0x00, 0x53, 0x79, 0x00, 0x00, 0x00, 0x43, -0xa2, 0x07, 0x03, 0xd7, 0x02, 0x05, 0x1a, 0x00, 0x04, 0xae, -0x00, 0x41, 0x65, 0x6e, 0x65, 0x72, 0x58, 0x0c, 0x02, 0x0c, -0x08, 0xd1, 0x2e, 0x00, 0x41, 0x74, 0x00, 0x55, 0x6e, 0x72, -0x65, 0x61, 0x73, 0x6f, 0x6e, 0x28, 0x01, 0x50, 0x6c, 0x65, -0x76, 0x65, 0x6c, 0x7d, 0x05, 0x70, 0x6d, 0x65, 0x00, 0x62, -0x61, 0x63, 0x6b, 0x0c, 0x0b, 0x01, 0x98, 0x03, 0x04, 0x79, -0x06, 0x10, 0x72, 0x28, 0x0a, 0x73, 0x72, 0x65, 0x64, 0x2c, -0x00, 0x62, 0x75, 0x37, 0x0c, 0x31, 0x6f, 0x6c, 0x75, 0x48, -0x01, 0x21, 0x73, 0x68, 0xc8, 0x00, 0x23, 0x73, 0x74, 0x2b, -0x00, 0x42, 0x75, 0x6e, 0x69, 0x71, 0x85, 0x0c, 0x10, 0x65, -0x7b, 0x02, 0x03, 0x3a, 0x06, 0x01, 0x62, 0x00, 0x14, 0x73, -0x48, 0x00, 0x00, 0x64, 0x07, 0x00, 0x7f, 0x00, 0x00, 0xcc, -0x04, 0x00, 0x6b, 0x09, 0x00, 0xd8, 0x0a, 0x22, 0x78, 0x00, -0x91, 0x00, 0x01, 0xed, 0x0c, 0x00, 0x00, 0x02, 0x30, 0x6f, -0x69, 0x64, 0x54, 0x02, 0x03, 0x10, 0x00, 0x05, 0x97, 0x00, -0x00, 0xfe, 0x00, 0x19, 0x4d, 0x2e, 0x0c, 0x11, 0x20, 0x98, -0x0d, 0x01, 0x69, 0x07, 0x10, 0x74, 0xf2, 0x08, 0x00, 0xf1, -0x09, 0x01, 0xd8, 0x00, 0x00, 0x81, 0x03, 0x00, 0x95, 0x00, -0x45, 0x6f, 0x78, 0x65, 0x73, 0xcb, 0x00, 0x0b, 0x6a, 0x0c, -0x01, 0x1d, 0x00, 0x32, 0x2e, 0x00, 0x57, 0x16, 0x04, 0x03, -0x8c, 0x09, 0x02, 0x51, 0x04, 0x03, 0x3a, 0x09, 0x21, 0x69, -0x73, 0x0f, 0x06, 0x10, 0x6e, 0xdc, 0x05, 0xf0, 0x02, 0x60, -0x49, 0x6e, 0x73, 0x68, 0x69, 0x00, 0x4e, 0x6f, 0x00, 0x48, -0x65, 0x79, 0x61, 0x27, 0x2e, 0x00, +0x2d, 0x01, 0x00, 0xf4, 0x10, 0x00, 0x00, 0x00, 0x59, 0x6f, +0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x73, +0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x67, 0x72, 0x69, 0x64, +0x3b, 0x00, 0x65, 0x61, 0x63, 0x68, 0x12, 0x00, 0xf1, 0x1a, +0x6d, 0x61, 0x79, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, +0x6e, 0x00, 0x61, 0x00, 0x64, 0x69, 0x67, 0x69, 0x74, 0x00, +0x66, 0x72, 0x6f, 0x6d, 0x00, 0x31, 0x00, 0x74, 0x6f, 0x00, +0x74, 0x68, 0x65, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6f, +0x66, 0x0c, 0x00, 0x00, 0x40, 0x00, 0x33, 0x2e, 0x00, 0x54, +0x0a, 0x00, 0xf0, 0x08, 0x00, 0x69, 0x73, 0x00, 0x64, 0x69, +0x76, 0x69, 0x64, 0x65, 0x64, 0x00, 0x69, 0x6e, 0x74, 0x6f, +0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2d, 0x00, 0xf1, +0x02, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x00, 0x73, +0x68, 0x61, 0x70, 0x65, 0x00, 0x61, 0x6e, 0x64, 0x47, 0x00, +0xf0, 0x13, 0x2c, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x61, +0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x00, +0x63, 0x6c, 0x75, 0x65, 0x73, 0x00, 0x77, 0x72, 0x69, 0x74, +0x74, 0x65, 0x6e, 0x00, 0x69, 0x6e, 0x66, 0x00, 0x20, 0x6d, +0x2e, 0xba, 0x00, 0x50, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x62, +0x00, 0xf5, 0x02, 0x74, 0x6f, 0x00, 0x66, 0x75, 0x6c, 0x6c, +0x79, 0x00, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, +0x8a, 0x00, 0x02, 0x4e, 0x00, 0x01, 0xb4, 0x00, 0xf0, 0x03, +0x73, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x74, 0x68, 0x61, +0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x45, 0xe4, 0x00, +0x34, 0x72, 0x6f, 0x77, 0xdd, 0x00, 0xf1, 0x05, 0x73, 0x00, +0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0x6f, +0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0xd7, 0x00, +0x01, 0x0d, 0x01, 0x02, 0xf8, 0x00, 0x05, 0x38, 0x00, 0x6f, +0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3b, 0x00, 0x1d, 0x00, +0x17, 0x01, 0x03, 0x8d, 0x00, 0x22, 0x69, 0x6e, 0x1d, 0x00, +0x01, 0x11, 0x01, 0xf1, 0x01, 0x00, 0x63, 0x61, 0x6e, 0x00, +0x62, 0x65, 0x00, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, +0x64, 0xd2, 0x00, 0x31, 0x6f, 0x72, 0x6d, 0xc8, 0x00, 0xd3, +0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x73, 0x74, 0x61, +0x74, 0x65, 0x64, 0x01, 0x01, 0x01, 0x16, 0x01, 0x40, 0x2c, +0x00, 0x75, 0x73, 0x42, 0x01, 0x00, 0x10, 0x00, 0x07, 0x31, +0x01, 0xf8, 0x00, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x32, 0x00, +0x00, 0x99, 0x01, 0x52, 0x61, 0x74, 0x00, 0x69, 0x73, 0x02, +0x01, 0x71, 0x41, 0x6e, 0x00, 0x61, 0x64, 0x64, 0x69, 0x2c, +0x00, 0x00, 0x1f, 0x00, 0x61, 0x00, 0x6d, 0x65, 0x61, 0x6e, +0x73, 0x23, 0x01, 0x02, 0xd8, 0x01, 0x24, 0x75, 0x6d, 0xd7, +0x01, 0x06, 0xb6, 0x00, 0x00, 0x0e, 0x00, 0x02, 0xb5, 0x00, +0x63, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x62, 0x6d, 0x01, 0x01, +0x6b, 0x00, 0x02, 0xab, 0x00, 0xf5, 0x05, 0x2e, 0x00, 0x46, +0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, +0x2c, 0x00, 0x60, 0x31, 0x35, 0x2b, 0x27, 0x5b, 0x00, 0x11, +0x65, 0x34, 0x01, 0x31, 0x65, 0x6e, 0x74, 0x05, 0x02, 0x06, +0x4d, 0x00, 0x71, 0x61, 0x64, 0x64, 0x73, 0x00, 0x75, 0x70, +0xfa, 0x00, 0x72, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x2e, +0xa4, 0x00, 0xb6, 0x00, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, +0x6c, 0x69, 0x63, 0x61, 0xa9, 0x00, 0xfc, 0x09, 0x28, 0x65, +0x2e, 0x67, 0x2e, 0x00, 0x60, 0x36, 0x30, 0x2a, 0x27, 0x29, +0x2c, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x6c, +0x79, 0x2c, 0xc2, 0x00, 0x7f, 0x70, 0x72, 0x6f, 0x64, 0x75, +0x63, 0x74, 0xc6, 0x00, 0x23, 0x02, 0x7f, 0x00, 0x76, 0x73, +0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x7c, 0x00, 0xb0, 0x77, +0x69, 0x6c, 0x6c, 0x00, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, +0x38, 0x00, 0x07, 0x9a, 0x02, 0x13, 0x61, 0x53, 0x00, 0x22, +0x6f, 0x66, 0x13, 0x03, 0x41, 0x74, 0x77, 0x6f, 0x2c, 0xda, +0x02, 0x28, 0x69, 0x74, 0x99, 0x00, 0x01, 0x27, 0x02, 0x0f, +0x91, 0x00, 0x07, 0xa0, 0x69, 0x73, 0x00, 0x67, 0x72, 0x65, +0x61, 0x74, 0x65, 0x72, 0x2f, 0x00, 0x02, 0x1a, 0x00, 0x87, +0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0x62, 0x79, 0xa6, 0x00, +0x6c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x6c, 0x01, 0x3f, +0x32, 0x2d, 0x27, 0x6b, 0x00, 0x1b, 0x6b, 0x32, 0x00, 0x6d, +0x6f, 0x72, 0x65, 0x6a, 0x00, 0x20, 0x2c, 0x00, 0x55, 0x00, +0xb6, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, +0x6c, 0x79, 0x4e, 0x00, 0x02, 0xcd, 0x02, 0x57, 0x6d, 0x69, +0x6e, 0x75, 0x73, 0x9a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x4d, +0x00, 0x02, 0xfa, 0x03, 0x34, 0x74, 0x77, 0x6f, 0x6f, 0x00, +0x50, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x27, 0x01, 0x21, 0x65, +0x69, 0x29, 0x00, 0xf4, 0x02, 0x77, 0x61, 0x79, 0x00, 0x72, +0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x00, 0x74, 0x68, 0x6f, 0x75, +0x67, 0x68, 0x67, 0x01, 0x00, 0x26, 0x04, 0x1c, 0x73, 0xe0, +0x01, 0x2b, 0x33, 0x2f, 0xdf, 0x01, 0x24, 0x69, 0x73, 0x7a, +0x01, 0x0f, 0x6f, 0x01, 0x03, 0x01, 0x6e, 0x01, 0x0b, 0x00, +0x01, 0x02, 0xb2, 0x00, 0x04, 0x86, 0x04, 0x27, 0x62, 0x79, +0xb7, 0x00, 0x20, 0x69, 0x73, 0xe6, 0x00, 0x24, 0x61, 0x6c, +0xc9, 0x04, 0x0a, 0x5a, 0x01, 0x62, 0x00, 0x00, 0x4e, 0x6f, +0x74, 0x65, 0x49, 0x00, 0x04, 0x6c, 0x00, 0x08, 0x0d, 0x05, +0x01, 0x23, 0x03, 0x25, 0x61, 0x6d, 0x14, 0x01, 0x05, 0x48, +0x01, 0x10, 0x6f, 0xfe, 0x03, 0x42, 0x28, 0x70, 0x72, 0x6f, +0x73, 0x00, 0x00, 0x28, 0x00, 0x90, 0x69, 0x64, 0x65, 0x6e, +0x74, 0x69, 0x63, 0x61, 0x6c, 0x93, 0x00, 0x20, 0x73, 0x00, +0x58, 0x05, 0x48, 0x6e, 0x6f, 0x74, 0x00, 0x46, 0x00, 0x00, +0x8b, 0x04, 0x00, 0xbf, 0x00, 0x02, 0x5b, 0x04, 0x10, 0x29, +0x4b, 0x01, 0x61, 0x69, 0x73, 0x00, 0x72, 0x75, 0x6c, 0x5b, +0x01, 0x83, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x6c, +0xbf, 0x00, 0x65, 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0xdd, +0x01, 0x02, 0x26, 0x00, 0xf2, 0x0e, 0x6e, 0x00, 0x53, 0x6f, +0x6c, 0x6f, 0x27, 0x73, 0x00, 0x60, 0x4b, 0x69, 0x6c, 0x6c, +0x65, 0x72, 0x27, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x28, +0x73, 0x65, 0x65, 0x00, 0x63, 0x0f, 0x06, 0x40, 0x00, 0x31, +0x31, 0x29, 0xda, 0x00, 0x01, 0x5c, 0x00, 0xd5, 0x70, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x61, 0x70, 0x70, 0x65, 0x61, +0x72, 0x1b, 0x02, 0xb2, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x00, +0x75, 0x6e, 0x64, 0x65, 0x72, 0x80, 0x04, 0x00, 0x9d, 0x00, +0x80, 0x60, 0x4b, 0x65, 0x6e, 0x4b, 0x65, 0x6e, 0x27, 0x3c, +0x00, 0x42, 0x33, 0x30, 0x2e, 0x31, 0x53, 0x06, 0x00, 0x0a, +0x01, 0x80, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, +0x11, 0x00, 0x00, 0xcd, 0x05, 0x50, 0x72, 0x65, 0x73, 0x00, +0x6d, 0x6a, 0x05, 0x32, 0x6f, 0x66, 0x00, 0x02, 0x02, 0x01, +0x24, 0x00, 0x72, 0x00, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, +0x91, 0x05, 0x00, 0xa7, 0x00, 0x20, 0x00, 0x28, 0xed, 0x00, +0x21, 0x55, 0x6e, 0x81, 0x01, 0x02, 0x94, 0x00, 0x61, 0x6f, +0x00, 0x70, 0x6c, 0x61, 0x79, 0x4a, 0x00, 0x01, 0xf6, 0x01, +0x91, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, +0x88, 0x00, 0x51, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0xf8, 0x01, +0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0xa2, +0x06, 0x21, 0x61, 0x6e, 0x65, 0x01, 0x65, 0x6e, 0x00, 0x74, +0x79, 0x70, 0x65, 0xa4, 0x06, 0x12, 0x6f, 0xcf, 0x00, 0x72, +0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x54, 0x05, 0x00, +0xbb, 0x03, 0x01, 0xd0, 0x01, 0x02, 0x3a, 0x00, 0xc0, 0x2e, +0x00, 0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6d, 0x61, +0x6b, 0x39, 0x00, 0x8f, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, +0x65, 0x2c, 0x76, 0x00, 0x01, 0x01, 0xc6, 0x01, 0x88, 0x6e, +0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x7a, 0x00, 0xb0, +0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x61, 0x63, +0x65, 0x64, 0x00, 0x50, 0x63, 0x6c, 0x65, 0x61, 0x72, 0xf2, +0x03, 0x20, 0x61, 0x67, 0x25, 0x02, 0x62, 0x28, 0x6f, 0x72, +0x00, 0x75, 0x73, 0x5f, 0x04, 0xc1, 0x55, 0x6e, 0x64, 0x6f, +0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0xf2, 0x00, +0x03, 0x7e, 0x00, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, +0x74, 0x00, 0x01, 0xd8, 0x02, 0x0f, 0xd8, 0x00, 0x04, 0x02, +0x99, 0x04, 0x12, 0x2c, 0xc2, 0x00, 0x03, 0x17, 0x06, 0x01, +0x8e, 0x04, 0x00, 0x60, 0x03, 0x46, 0x6e, 0x74, 0x65, 0x72, +0x20, 0x06, 0x04, 0x42, 0x00, 0xf1, 0x02, 0x73, 0x00, 0x61, +0x00, 0x60, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x00, 0x6d, +0x61, 0x72, 0x6b, 0x27, 0x3a, 0x07, 0x01, 0x70, 0x06, 0x01, +0xf8, 0x07, 0x07, 0x1b, 0x00, 0x10, 0x73, 0x73, 0x06, 0x04, +0x6e, 0x05, 0x04, 0x77, 0x06, 0x19, 0x73, 0xa3, 0x02, 0x04, +0x36, 0x01, 0x11, 0x53, 0x08, 0x00, 0x14, 0x73, 0x0a, 0x03, +0x00, 0x85, 0x06, 0x10, 0x66, 0x72, 0x02, 0x45, 0x64, 0x2d, +0x69, 0x6e, 0x39, 0x00, 0x30, 0x63, 0x61, 0x6e, 0xe3, 0x02, +0x45, 0x61, 0x6c, 0x73, 0x6f, 0x33, 0x03, 0x08, 0x6f, 0x00, +0x02, 0x87, 0x02, 0x30, 0x65, 0x00, 0x67, 0x5a, 0x00, 0x10, +0x70, 0xd4, 0x03, 0x40, 0x6e, 0x6f, 0x00, 0x61, 0x4c, 0x05, +0x01, 0x6c, 0x05, 0x29, 0x74, 0x6f, 0x2e, 0x00, 0x40, 0x2c, +0x00, 0x73, 0x6f, 0xe8, 0x04, 0x10, 0x63, 0x8e, 0x04, 0x10, +0x77, 0x01, 0x01, 0x00, 0x3a, 0x01, 0x03, 0x5a, 0x01, 0x11, +0x6d, 0xbb, 0x00, 0x14, 0x69, 0x41, 0x06, 0x63, 0x79, 0x6f, +0x75, 0x3a, 0x00, 0x79, 0xe7, 0x00, 0x05, 0x23, 0x00, 0x70, +0x61, 0x73, 0x00, 0x72, 0x65, 0x6d, 0x69, 0xd8, 0x02, 0x14, +0x73, 0xd5, 0x03, 0xa4, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, +0x75, 0x6c, 0x61, 0x72, 0x32, 0x01, 0x41, 0x6e, 0x65, 0x65, +0x64, 0x52, 0x08, 0x60, 0x62, 0x65, 0x00, 0x72, 0x65, 0x2d, +0x5a, 0x05, 0x01, 0x92, 0x07, 0x01, 0xd4, 0x03, 0x00, 0x54, +0x00, 0x42, 0x6b, 0x6e, 0x6f, 0x77, 0xec, 0x03, 0x4b, 0x61, +0x62, 0x6f, 0x75, 0x45, 0x00, 0x04, 0xa2, 0x01, 0x2f, 0x6f, +0x72, 0x80, 0x00, 0x02, 0x36, 0x6c, 0x69, 0x73, 0xf8, 0x06, +0x6a, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6a, 0x01, 0x13, +0x61, 0x83, 0x04, 0x02, 0x8d, 0x00, 0x01, 0x48, 0x00, 0x50, +0x61, 0x6e, 0x79, 0x74, 0x68, 0x62, 0x01, 0x32, 0x65, 0x6c, +0x73, 0x82, 0x00, 0x93, 0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, +0x69, 0x6b, 0x65, 0x35, 0x03, 0x41, 0x65, 0x72, 0x61, 0x73, +0xc2, 0x09, 0x49, 0x69, 0x6e, 0x67, 0x6c, 0xd3, 0x01, 0x1c, +0x2c, 0x5b, 0x02, 0x08, 0x1b, 0x02, 0x22, 0x6e, 0x64, 0x58, +0x02, 0x05, 0xde, 0x01, 0x03, 0x52, 0x02, 0x01, 0xb8, 0x02, +0x00, 0x5b, 0x00, 0x3a, 0x41, 0x6c, 0x6c, 0x20, 0x02, 0x09, +0x9c, 0x02, 0x22, 0x72, 0x65, 0x79, 0x00, 0x30, 0x64, 0x00, +0x77, 0xa3, 0x02, 0x00, 0x99, 0x00, 0x34, 0x6c, 0x65, 0x66, +0x6c, 0x00, 0x05, 0x5e, 0x00, 0x18, 0x61, 0x14, 0x01, 0x0f, +0x2a, 0x00, 0x05, 0x02, 0x43, 0x03, 0x10, 0x73, 0x43, 0x03, +0x36, 0x2e, 0x00, 0x52, 0xb3, 0x00, 0x00, 0xf7, 0x00, 0x05, +0x20, 0x00, 0x01, 0x2d, 0x0a, 0x01, 0x66, 0x03, 0x03, 0x82, +0x07, 0x14, 0x73, 0xfb, 0x00, 0x0c, 0x56, 0x02, 0x12, 0x41, +0xcb, 0x02, 0x00, 0x66, 0x04, 0x12, 0x2c, 0x73, 0x08, 0x50, +0x75, 0x72, 0x73, 0x6f, 0x72, 0x0b, 0x04, 0x14, 0x73, 0x6b, +0x09, 0x22, 0x75, 0x73, 0x2d, 0x03, 0x62, 0x63, 0x6f, 0x6e, +0x6a, 0x75, 0x6e, 0xdf, 0x07, 0x01, 0x9c, 0x04, 0x05, 0x2c, +0x07, 0x02, 0x2f, 0x00, 0x65, 0x74, 0x6f, 0x00, 0x73, 0x65, +0x74, 0xa4, 0x01, 0x2b, 0x6f, 0x72, 0x6e, 0x00, 0x3d, 0x55, +0x73, 0x65, 0x63, 0x00, 0x51, 0x74, 0x6f, 0x00, 0x6d, 0x6f, +0x55, 0x0b, 0x50, 0x68, 0x69, 0x67, 0x68, 0x6c, 0xd0, 0x00, +0x21, 0x00, 0x61, 0xf6, 0x06, 0x05, 0x99, 0x0a, 0x02, 0x18, +0x08, 0x09, 0xb0, 0x04, 0x22, 0x74, 0x6f, 0xc5, 0x03, 0x25, +0x00, 0x69, 0x18, 0x06, 0x05, 0x3f, 0x00, 0x25, 0x65, 0x64, +0x7c, 0x03, 0x14, 0x50, 0x0c, 0x01, 0x50, 0x72, 0x65, 0x74, +0x75, 0x72, 0x28, 0x03, 0x5a, 0x67, 0x67, 0x6c, 0x65, 0x73, +0x30, 0x00, 0x02, 0x6d, 0x0b, 0x12, 0x61, 0x00, 0x06, 0x85, +0x69, 0x6e, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x93, 0x02, +0x02, 0x67, 0x00, 0x20, 0x6f, 0x72, 0x10, 0x03, 0x2e, 0x6f, +0x76, 0x40, 0x01, 0x05, 0x63, 0x00, 0x12, 0x4d, 0x6b, 0x01, +0x01, 0x37, 0x05, 0x01, 0xfd, 0x01, 0x00, 0x67, 0x0b, 0x01, +0x10, 0x01, 0x2d, 0x6f, 0x66, 0x1b, 0x02, 0x45, 0x65, 0x76, +0x65, 0x72, 0x93, 0x05, 0x01, 0x60, 0x03, 0x41, 0x64, 0x6f, +0x65, 0x73, 0xe7, 0x06, 0x03, 0x63, 0x0c, 0x10, 0x6d, 0x03, +0x04, 0x02, 0xed, 0x00, 0x41, 0x69, 0x6e, 0x00, 0x69, 0x63, +0x07, 0x10, 0x28, 0x66, 0x02, 0x01, 0xc2, 0x0a, 0x01, 0x84, +0x01, 0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, +0x62, 0x9e, 0x01, 0x22, 0x73, 0x65, 0x9a, 0x01, 0x31, 0x32, +0x2e, 0x31, 0x72, 0x02, 0x01, 0xf5, 0x01, 0xb2, 0x61, 0x76, +0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x8e, +0x06, 0x12, 0x32, 0x8e, 0x06, 0xb2, 0x70, 0x61, 0x72, 0x61, +0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x5b, 0x04, 0x00, +0x1b, 0x02, 0x05, 0x14, 0x00, 0x02, 0x40, 0x00, 0x04, 0x3b, +0x00, 0x02, 0xc2, 0x0c, 0x00, 0x78, 0x00, 0xe1, 0x60, 0x43, +0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, +0x6f, 0x70, 0x6e, 0x00, 0x03, 0x3a, 0x06, 0x50, 0x60, 0x54, +0x79, 0x70, 0x65, 0x4f, 0x09, 0x20, 0x6e, 0x75, 0xaa, 0x00, +0x51, 0x47, 0x72, 0x69, 0x64, 0x20, 0x69, 0x08, 0xbf, 0x00, +0x00, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, +0x00, 0x0d, 0x04, 0xb0, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x00, +0x6c, 0x69, 0x6d, 0x69, 0x74, 0x97, 0x04, 0x68, 0x33, 0x3b, +0x00, 0x75, 0x70, 0x70, 0x12, 0x00, 0x74, 0x39, 0x00, 0x28, +0x62, 0x65, 0x63, 0x61, 0x1a, 0x06, 0x20, 0x75, 0x73, 0xf8, +0x01, 0x00, 0x97, 0x01, 0x11, 0x66, 0xe1, 0x02, 0x03, 0x36, +0x09, 0x42, 0x63, 0x6f, 0x6d, 0x65, 0x6c, 0x04, 0x40, 0x64, +0x69, 0x66, 0x66, 0x64, 0x04, 0x12, 0x74, 0xa5, 0x02, 0x12, +0x60, 0x5f, 0x09, 0x64, 0x27, 0x00, 0x62, 0x69, 0x67, 0x67, +0x29, 0x0a, 0x21, 0x39, 0x21, 0x55, 0x06, 0x14, 0x44, 0x2b, +0x00, 0x53, 0x79, 0x00, 0x00, 0x00, 0x43, 0xa2, 0x07, 0x03, +0xd7, 0x02, 0x05, 0x1a, 0x00, 0x04, 0xae, 0x00, 0x41, 0x65, +0x6e, 0x65, 0x72, 0x58, 0x0c, 0x02, 0x0c, 0x08, 0xd1, 0x2e, +0x00, 0x41, 0x74, 0x00, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x73, +0x6f, 0x6e, 0x28, 0x01, 0x50, 0x6c, 0x65, 0x76, 0x65, 0x6c, +0x7d, 0x05, 0x70, 0x6d, 0x65, 0x00, 0x62, 0x61, 0x63, 0x6b, +0x0c, 0x0b, 0x01, 0x98, 0x03, 0x04, 0x79, 0x06, 0x10, 0x72, +0x28, 0x0a, 0x73, 0x72, 0x65, 0x64, 0x2c, 0x00, 0x62, 0x75, +0x37, 0x0c, 0x31, 0x6f, 0x6c, 0x75, 0x48, 0x01, 0x21, 0x73, +0x68, 0xc8, 0x00, 0x23, 0x73, 0x74, 0x2b, 0x00, 0x42, 0x75, +0x6e, 0x69, 0x71, 0x85, 0x0c, 0x10, 0x65, 0x7b, 0x02, 0x03, +0x3a, 0x06, 0x01, 0x62, 0x00, 0x14, 0x73, 0x48, 0x00, 0x00, +0x64, 0x07, 0x00, 0x7f, 0x00, 0x00, 0xcc, 0x04, 0x00, 0x6b, +0x09, 0x00, 0xd8, 0x0a, 0x22, 0x78, 0x00, 0x91, 0x00, 0x01, +0xed, 0x0c, 0x00, 0x00, 0x02, 0x30, 0x6f, 0x69, 0x64, 0x54, +0x02, 0x03, 0x10, 0x00, 0x05, 0x97, 0x00, 0x00, 0xfe, 0x00, +0x19, 0x4d, 0x2e, 0x0c, 0x11, 0x20, 0x98, 0x0d, 0x01, 0x69, +0x07, 0x10, 0x74, 0xf2, 0x08, 0x00, 0xf1, 0x09, 0x01, 0xd8, +0x00, 0x00, 0x81, 0x03, 0x00, 0x95, 0x00, 0x45, 0x6f, 0x78, +0x65, 0x73, 0xcb, 0x00, 0x0b, 0x6a, 0x0c, 0x01, 0x1d, 0x00, +0x32, 0x2e, 0x00, 0x57, 0x16, 0x04, 0x03, 0x8c, 0x09, 0x02, +0x51, 0x04, 0x03, 0x3a, 0x09, 0x21, 0x69, 0x73, 0x0f, 0x06, +0x10, 0x6e, 0xdc, 0x05, 0xf0, 0x02, 0x60, 0x49, 0x6e, 0x73, +0x68, 0x69, 0x00, 0x4e, 0x6f, 0x00, 0x48, 0x65, 0x79, 0x61, +0x27, 0x2e, 0x00, }; -const unsigned short help_text_len = 3952; -const unsigned short help_text_words = 761; +const unsigned short help_text_len = 3969; +const unsigned short help_text_words = 762; const char quick_help_text[] = "Complete the latin square in accordance with the arithmetic clues."; diff --git a/apps/plugins/puzzles/help/lightup.c b/apps/plugins/puzzles/help/lightup.c index 5562b954b7..874a05c596 100644 --- a/apps/plugins/puzzles/help/lightup.c +++ b/apps/plugins/puzzles/help/lightup.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,176 +6,189 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 169, TEXT_CENTER | C_RED }, - { 304, TEXT_CENTER | C_RED }, - { 321, TEXT_UNDERLINE }, - { 322, TEXT_UNDERLINE }, - { 332, TEXT_UNDERLINE }, - { 380, TEXT_UNDERLINE }, - { 409, TEXT_UNDERLINE }, + { 167, TEXT_CENTER | C_RED }, + { 302, TEXT_CENTER | C_RED }, + { 319, TEXT_UNDERLINE }, + { 320, TEXT_UNDERLINE }, + { 330, TEXT_UNDERLINE }, + { 378, TEXT_UNDERLINE }, + { 407, TEXT_UNDERLINE }, + { 433, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 2327 comp 1558 ratio 0.669532 level 10 saved 769 */ +/* orig 2549 comp 1677 ratio 0.657905 level 10 saved 872 */ const char help_text[] = { -0xf0, 0x40, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x31, 0x3a, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x20, -0x55, 0x70, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, -0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, -0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, -0x65, 0x73, 0x2e, 0x00, 0x53, 0x6f, 0x6d, 0x65, 0x00, 0x61, -0x72, 0x65, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, -0x69, 0x6e, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0x00, -0x73, 0x1a, 0x00, 0x62, 0x6f, 0x66, 0x00, 0x74, 0x68, 0x65, -0x13, 0x00, 0x04, 0x35, 0x00, 0x01, 0x2f, 0x00, 0x90, 0x6e, -0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x5e, 0x00, -0xe0, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, -0x74, 0x6f, 0x00, 0x60, 0x6c, 0x7a, 0x00, 0x81, 0x00, 0x75, -0x70, 0x27, 0x00, 0x61, 0x6c, 0x6c, 0x3e, 0x00, 0x55, 0x65, -0x6d, 0x70, 0x74, 0x79, 0x3e, 0x00, 0xb2, 0x62, 0x79, 0x00, -0x70, 0x6c, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x00, 0x2b, 0x00, -0x50, 0x62, 0x75, 0x6c, 0x62, 0x73, 0x79, 0x00, 0x07, 0x72, -0x00, 0x97, 0x6d, 0x2e, 0x00, 0x00, 0x00, 0x45, 0x61, 0x63, -0x68, 0x24, 0x00, 0xc1, 0x00, 0x69, 0x6c, 0x6c, 0x75, 0x6d, -0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x58, 0x00, 0x02, 0x52, -0x00, 0x30, 0x00, 0x69, 0x74, 0x7b, 0x00, 0x81, 0x6f, 0x6e, -0x2c, 0x00, 0x70, 0x6c, 0x75, 0x73, 0x76, 0x00, 0x04, 0x6c, -0x00, 0xc0, 0x69, 0x6e, 0x00, 0x6c, 0x69, 0x6e, 0x65, 0x00, -0x77, 0x69, 0x74, 0x68, 0x28, 0x00, 0xf1, 0x07, 0x68, 0x6f, -0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x6c, 0x79, -0x00, 0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, -0x0e, 0x00, 0x89, 0x75, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x00, -0x61, 0xec, 0x00, 0x00, 0x59, 0x00, 0x50, 0x62, 0x6c, 0x6f, -0x63, 0x6b, 0xae, 0x00, 0x00, 0x73, 0x00, 0x30, 0x77, 0x61, -0x79, 0x9a, 0x00, 0x61, 0x54, 0x6f, 0x00, 0x77, 0x69, 0x6e, -0x12, 0x00, 0xf1, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, -0x79, 0x6f, 0x75, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x73, -0x61, 0x74, 0x69, 0x73, 0x66, 0x79, 0x1b, 0x00, 0x60, 0x66, -0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x3b, 0x00, 0xfe, 0x09, 0x63, -0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, -0x00, 0x00, 0x00, 0x2d, 0x00, 0x41, 0x6c, 0x6c, 0x00, 0x6e, -0x6f, 0x6e, 0x2d, 0x58, 0x01, 0x41, 0x6c, 0x69, 0x74, 0x2e, -0x23, 0x00, 0x23, 0x4e, 0x6f, 0xfb, 0x00, 0x20, 0x69, 0x73, -0x15, 0x00, 0x00, 0x37, 0x01, 0x72, 0x61, 0x6e, 0x6f, 0x74, -0x68, 0x65, 0x72, 0x18, 0x00, 0x16, 0x2e, 0x49, 0x00, 0x03, -0x8b, 0x01, 0x0b, 0xa6, 0x01, 0x01, 0xf2, 0x01, 0x60, 0x65, -0x78, 0x61, 0x63, 0x74, 0x6c, 0x8f, 0x00, 0x23, 0x61, 0x74, -0x29, 0x00, 0x00, 0x62, 0x01, 0x01, 0x42, 0x00, 0xa0, 0x73, -0x00, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0xb8, -0x01, 0x00, 0x75, 0x01, 0x23, 0x00, 0x28, 0xd5, 0x00, 0x10, -0x66, 0xd4, 0x01, 0x05, 0x97, 0x00, 0xf3, 0x01, 0x62, 0x6f, -0x76, 0x65, 0x2c, 0x00, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2c, -0x00, 0x61, 0x6e, 0x64, 0x2f, 0x00, 0x60, 0x00, 0x73, 0x69, -0x64, 0x65, 0x29, 0x88, 0x00, 0x4f, 0x4e, 0x6f, 0x6e, 0x2d, -0x86, 0x00, 0x04, 0x33, 0x6d, 0x61, 0x79, 0x7c, 0x02, 0x2f, -0x6e, 0x79, 0x81, 0x00, 0x0f, 0x00, 0x4d, 0x00, 0xf1, 0x0b, -0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, 0x72, -0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, -0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0x60, 0x02, 0xa0, 0x4e, -0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x39, 0x5d, 0x2d, -0x00, 0x11, 0x4c, 0x23, 0x01, 0x60, 0x55, 0x70, 0x00, 0x77, -0x61, 0x73, 0x66, 0x01, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, -0x74, 0x65, 0xa3, 0x00, 0x10, 0x69, 0x14, 0x00, 0x40, 0x6c, -0x6c, 0x65, 0x63, 0x7b, 0x01, 0x00, 0x42, 0x01, 0xb1, 0x4a, -0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, -0xc8, 0x01, 0xf1, 0x01, 0x5b, 0x39, 0x5d, 0x00, 0x68, 0x74, -0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, -0x5c, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, -0x65, 0x6e, 0x2f, 0x7b, 0x00, 0xf1, 0x04, 0x73, 0x2f, 0x61, -0x6b, 0x61, 0x72, 0x69, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, -0x28, 0x62, 0x65, 0x77, 0x61, 0x72, 0xa7, 0x02, 0xd6, 0x46, -0x6c, 0x61, 0x73, 0x68, 0x29, 0x00, 0x00, 0x00, 0x32, 0x31, -0x2e, 0x31, 0x71, 0x03, 0x01, 0x86, 0x00, 0x40, 0x6f, 0x6c, -0x73, 0x20, 0x9f, 0x00, 0x72, 0x65, 0x66, 0x74, 0x2d, 0x63, -0x6c, 0x69, 0x41, 0x02, 0x4d, 0x69, 0x6e, 0x00, 0x61, 0xf7, -0x01, 0x30, 0x00, 0x77, 0x69, 0x27, 0x03, 0x51, 0x6f, 0x67, -0x67, 0x6c, 0x65, 0x56, 0x01, 0x71, 0x70, 0x72, 0x65, 0x73, -0x65, 0x6e, 0x63, 0x63, 0x00, 0x14, 0x61, 0x04, 0x02, 0x12, -0x6e, 0xc2, 0x01, 0x02, 0x33, 0x00, 0x30, 0x2e, 0x00, 0x52, -0x16, 0x00, 0x0f, 0x59, 0x00, 0x0d, 0x02, 0x54, 0x00, 0x00, -0xd3, 0x02, 0x40, 0x6d, 0x61, 0x72, 0x6b, 0x5c, 0x00, 0x01, -0x15, 0x00, 0xd0, 0x00, 0x61, 0x69, 0x64, 0x00, 0x73, 0x6f, -0x6c, 0x76, 0x69, 0x6e, 0x67, 0x3b, 0x15, 0x03, 0x92, 0x63, -0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x75, 0x73, 0x37, 0x01, -0x42, 0x68, 0x69, 0x67, 0x68, 0x76, 0x00, 0x04, 0xc4, 0x01, -0x01, 0x7b, 0x00, 0x81, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, -0x00, 0x62, 0xa3, 0x02, 0x11, 0x2c, 0x9f, 0x01, 0x83, 0x65, -0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x04, 0x00, -0xeb, 0x01, 0x00, 0x23, 0x00, 0x00, 0xde, 0x03, 0x18, 0x65, -0xbb, 0x00, 0x02, 0x81, 0x00, 0x23, 0x65, 0x64, 0x51, 0x00, -0x55, 0x2c, 0x00, 0x6e, 0x6f, 0x72, 0x26, 0x00, 0x01, 0x9c, -0x00, 0x21, 0x69, 0x6e, 0x30, 0x00, 0x06, 0xe1, 0x00, 0x33, -0x00, 0x00, 0x54, 0x5c, 0x03, 0x02, 0x20, 0x01, 0x06, 0x95, -0x00, 0xd1, 0x6f, 0x62, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x00, -0x65, 0x72, 0x72, 0x6f, 0x72, 0xe2, 0x03, 0x01, 0x86, 0x04, -0x01, 0x7f, 0x01, 0x05, 0x2a, 0x03, 0x07, 0x28, 0x03, 0x02, -0x57, 0x03, 0x05, 0x40, 0x00, 0x02, 0xe3, 0x04, 0x01, 0x1b, -0x02, 0x6a, 0x77, 0x61, 0x79, 0x2c, 0x00, 0x61, 0xcf, 0x04, -0x05, 0xf4, 0x00, 0x81, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, -0x64, 0x6f, 0xd2, 0x00, 0x33, 0x28, 0x6f, 0x72, 0x00, 0x01, -0x12, 0x29, 0xcd, 0x02, 0x00, 0xa8, 0x01, 0x11, 0x72, 0x8f, -0x00, 0x0d, 0xd3, 0x02, 0x39, 0x6e, 0x65, 0x78, 0xcf, 0x02, -0x52, 0x54, 0x68, 0x75, 0x73, 0x2c, 0x2a, 0x04, 0x00, 0x7c, -0x05, 0x21, 0x69, 0x73, 0x7c, 0x01, 0x9e, 0x65, 0x64, 0x00, -0x77, 0x68, 0x65, 0x6e, 0x00, 0x61, 0x09, 0x04, 0x04, 0xbb, -0x03, 0x20, 0x79, 0x65, 0x3e, 0x04, 0x06, 0xba, 0x00, 0x12, -0x73, 0x7b, 0x03, 0x01, 0xc6, 0x01, 0x01, 0xb3, 0x00, 0x10, -0x6f, 0xfa, 0x00, 0x03, 0x77, 0x00, 0x00, 0x6a, 0x00, 0x23, -0x28, 0x41, 0x70, 0x05, 0x21, 0x61, 0x63, 0x6b, 0x04, 0x82, -0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0xf3, 0x00, -0x13, 0x73, 0x06, 0x03, 0x31, 0x32, 0x2e, 0x31, 0x3f, 0x00, -0xf3, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, -0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0xc8, 0x02, 0x16, -0x32, 0xc8, 0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, -0x74, 0x65, 0x72, 0x73, 0x20, 0x8f, 0x01, 0x36, 0x73, 0x65, -0x00, 0x14, 0x00, 0x02, 0x44, 0x00, 0x04, 0x3f, 0x00, 0x51, -0x00, 0x66, 0x72, 0x6f, 0x6d, 0x7c, 0x00, 0xe1, 0x60, 0x43, -0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, -0x6f, 0x70, 0x72, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, -0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, -0xae, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, -0x48, 0x65, 0x47, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, -0xf3, 0x02, 0x02, 0x26, 0x01, 0x16, 0x6e, 0xa2, 0x06, 0xa1, -0x00, 0x00, 0x25, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, -0x25, 0x01, 0x14, 0x20, 0x25, 0x01, 0xb0, 0x00, 0x00, 0x52, -0x6f, 0x75, 0x67, 0x68, 0x00, 0x70, 0x65, 0x72, 0x43, 0x04, -0x21, 0x61, 0x67, 0x3f, 0x00, 0x0a, 0x49, 0x01, 0x25, 0x69, -0x6e, 0x7a, 0x01, 0x02, 0x8c, 0x01, 0x40, 0x69, 0x73, 0x00, -0x69, 0x12, 0x03, 0x71, 0x68, 0x69, 0x6e, 0x74, 0x00, 0x72, -0x61, 0x27, 0x02, 0xe1, 0x74, 0x68, 0x61, 0x6e, 0x00, 0x61, -0x6e, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x26, 0x01, -0x46, 0x2e, 0x00, 0x49, 0x66, 0xb4, 0x01, 0x90, 0x67, 0x65, -0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3c, 0x00, 0x21, -0x75, 0x6e, 0xf1, 0x00, 0x24, 0x74, 0x6f, 0x17, 0x00, 0x00, -0xc5, 0x02, 0x03, 0xa4, 0x04, 0x04, 0x75, 0x04, 0xf0, 0x02, -0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x00, 0x73, 0x70, -0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x54, 0x00, 0x10, -0x2c, 0x6c, 0x03, 0x01, 0xcd, 0x02, 0x74, 0x69, 0x6e, 0x63, -0x72, 0x65, 0x61, 0x73, 0xef, 0x03, 0x42, 0x6f, 0x70, 0x6f, -0x72, 0x29, 0x01, 0x0c, 0xbf, 0x00, 0x53, 0x75, 0x6e, 0x74, -0x69, 0x6c, 0xa3, 0x03, 0x10, 0x2e, 0x24, 0x01, 0xb0, 0x79, -0x6d, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x00, 0x00, 0x00, 0x41, -0x1d, 0x02, 0x11, 0x73, 0x78, 0x06, 0x23, 0x74, 0x6f, 0x69, -0x00, 0x12, 0x79, 0x98, 0x02, 0x41, 0x65, 0x71, 0x75, 0x69, -0xcb, 0x02, 0x04, 0x2e, 0x00, 0x0e, 0xc5, 0x07, 0x0c, 0x1b, -0x01, 0x11, 0x28, 0x1a, 0x01, 0x10, 0x64, 0x63, 0x05, 0x00, -0xf0, 0x02, 0x61, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x20, -0x00, 0x95, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, -0x74, 0x47, 0x00, 0x03, 0x15, 0x05, 0x00, 0x29, 0x00, 0x71, -0x69, 0x63, 0x65, 0x61, 0x62, 0x6c, 0x79, 0x3d, 0x02, 0x16, -0x44, 0x29, 0x00, 0x70, 0x00, 0x00, 0x60, 0x45, 0x61, 0x73, -0x79, 0xec, 0x01, 0x23, 0x61, 0x6e, 0x3f, 0x04, 0x08, 0x3a, -0x00, 0x60, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x4b, 0x04, -0x62, 0x73, 0x6f, 0x6c, 0x75, 0x62, 0x6c, 0xa0, 0x07, 0xb2, -0x6f, 0x75, 0x74, 0x00, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, -0x61, 0xd6, 0x04, 0xf9, 0x03, 0x6f, 0x72, 0x00, 0x67, 0x75, -0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x2c, 0x00, 0x60, 0x48, -0x61, 0x72, 0x64, 0x52, 0x00, 0x01, 0x2e, 0x08, 0x01, 0x21, -0x00, 0x22, 0x65, 0x73, 0x58, 0x01, 0x40, 0x70, 0x72, 0x6f, -0x62, 0x90, 0x00, 0x00, 0x5a, 0x00, 0xb0, 0x6e, 0x65, 0x63, -0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x2e, 0x00, +0x55, 0x70, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf0, 0x2b, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, +0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, +0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, +0x00, 0x53, 0x6f, 0x6d, 0x65, 0x00, 0x61, 0x72, 0x65, 0x00, +0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x69, 0x6e, 0x00, +0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0x00, 0x73, 0x1a, 0x00, +0x62, 0x6f, 0x66, 0x00, 0x74, 0x68, 0x65, 0x13, 0x00, 0x04, +0x35, 0x00, 0x01, 0x2f, 0x00, 0x90, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0x65, 0x64, 0x2e, 0x5e, 0x00, 0xe0, 0x72, 0x00, +0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, +0x60, 0x6c, 0x8f, 0x00, 0x81, 0x00, 0x75, 0x70, 0x27, 0x00, +0x61, 0x6c, 0x6c, 0x3e, 0x00, 0x55, 0x65, 0x6d, 0x70, 0x74, +0x79, 0x3e, 0x00, 0xb2, 0x62, 0x79, 0x00, 0x70, 0x6c, 0x61, +0x63, 0x69, 0x6e, 0x67, 0x00, 0x2b, 0x00, 0x50, 0x62, 0x75, +0x6c, 0x62, 0x73, 0x79, 0x00, 0x07, 0x72, 0x00, 0x97, 0x6d, +0x2e, 0x00, 0x00, 0x00, 0x45, 0x61, 0x63, 0x68, 0x24, 0x00, +0xc1, 0x00, 0x69, 0x6c, 0x6c, 0x75, 0x6d, 0x69, 0x6e, 0x61, +0x74, 0x65, 0x73, 0x58, 0x00, 0x02, 0x52, 0x00, 0x30, 0x00, +0x69, 0x74, 0x7b, 0x00, 0x81, 0x6f, 0x6e, 0x2c, 0x00, 0x70, +0x6c, 0x75, 0x73, 0x76, 0x00, 0x04, 0x6c, 0x00, 0xc0, 0x69, +0x6e, 0x00, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0x77, 0x69, 0x74, +0x68, 0x28, 0x00, 0xf1, 0x07, 0x68, 0x6f, 0x72, 0x69, 0x7a, +0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, +0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, 0x89, +0x75, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x00, 0x61, 0xec, 0x00, +0x00, 0x59, 0x00, 0x50, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0xae, +0x00, 0x00, 0x73, 0x00, 0x30, 0x77, 0x61, 0x79, 0x9a, 0x00, +0x61, 0x54, 0x6f, 0x00, 0x77, 0x69, 0x6e, 0x12, 0x00, 0xf1, +0x07, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, 0x79, 0x6f, 0x75, +0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x73, 0x61, 0x74, 0x69, +0x73, 0x66, 0x79, 0x1b, 0x00, 0x60, 0x66, 0x6f, 0x6c, 0x6c, +0x6f, 0x77, 0x3b, 0x00, 0xfe, 0x09, 0x63, 0x6f, 0x6e, 0x64, +0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x00, 0x00, 0x00, +0x2d, 0x00, 0x41, 0x6c, 0x6c, 0x00, 0x6e, 0x6f, 0x6e, 0x2d, +0x58, 0x01, 0x41, 0x6c, 0x69, 0x74, 0x2e, 0x23, 0x00, 0x23, +0x4e, 0x6f, 0xfb, 0x00, 0x20, 0x69, 0x73, 0x15, 0x00, 0x00, +0x37, 0x01, 0x72, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, +0x18, 0x00, 0x16, 0x2e, 0x49, 0x00, 0x03, 0x8b, 0x01, 0x0b, +0xa6, 0x01, 0x01, 0xf2, 0x01, 0x60, 0x65, 0x78, 0x61, 0x63, +0x74, 0x6c, 0x8f, 0x00, 0x23, 0x61, 0x74, 0x29, 0x00, 0x00, +0x62, 0x01, 0x01, 0x42, 0x00, 0xa0, 0x73, 0x00, 0x61, 0x64, +0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0xb8, 0x01, 0x00, 0x75, +0x01, 0x23, 0x00, 0x28, 0xd5, 0x00, 0x10, 0x66, 0xd4, 0x01, +0x05, 0x97, 0x00, 0xf3, 0x01, 0x62, 0x6f, 0x76, 0x65, 0x2c, +0x00, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2c, 0x00, 0x61, 0x6e, +0x64, 0x2f, 0x00, 0x60, 0x00, 0x73, 0x69, 0x64, 0x65, 0x29, +0x88, 0x00, 0x4f, 0x4e, 0x6f, 0x6e, 0x2d, 0x86, 0x00, 0x04, +0x33, 0x6d, 0x61, 0x79, 0x7c, 0x02, 0x2f, 0x6e, 0x79, 0x81, +0x00, 0x0f, 0x00, 0x4d, 0x00, 0xf1, 0x0b, 0x43, 0x72, 0x65, +0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x74, 0x68, +0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, +0x67, 0x6f, 0x65, 0x60, 0x02, 0xa0, 0x4e, 0x69, 0x6b, 0x6f, +0x6c, 0x69, 0x00, 0x5b, 0x39, 0x5d, 0x2d, 0x00, 0x11, 0x4c, +0x23, 0x01, 0x60, 0x55, 0x70, 0x00, 0x77, 0x61, 0x73, 0x66, +0x01, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0xa3, +0x00, 0x10, 0x69, 0x14, 0x00, 0x40, 0x6c, 0x6c, 0x65, 0x63, +0x7b, 0x01, 0x00, 0x42, 0x01, 0xb1, 0x4a, 0x61, 0x6d, 0x65, +0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0xc8, 0x01, 0xf1, +0x02, 0x5b, 0x39, 0x5d, 0x00, 0x68, 0x74, 0x74, 0x70, 0x73, +0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x5d, 0x00, +0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, +0x2f, 0x7c, 0x00, 0xf6, 0x00, 0x73, 0x2f, 0x61, 0x6b, 0x61, +0x72, 0x69, 0x2f, 0x00, 0x00, 0x00, 0x32, 0x31, 0x2e, 0x31, +0x71, 0x03, 0x01, 0x71, 0x00, 0x40, 0x6f, 0x6c, 0x73, 0x20, +0x8a, 0x00, 0x72, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, +0x2c, 0x02, 0x4d, 0x69, 0x6e, 0x00, 0x61, 0xe2, 0x01, 0x30, +0x00, 0x77, 0x69, 0x12, 0x03, 0x51, 0x6f, 0x67, 0x67, 0x6c, +0x65, 0x41, 0x01, 0x71, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, +0x63, 0xf5, 0x02, 0x14, 0x61, 0xef, 0x01, 0x12, 0x6e, 0xad, +0x01, 0x02, 0x33, 0x00, 0x30, 0x2e, 0x00, 0x52, 0x16, 0x00, +0x0f, 0x59, 0x00, 0x0d, 0x02, 0x54, 0x00, 0x00, 0xbe, 0x02, +0x40, 0x6d, 0x61, 0x72, 0x6b, 0x5c, 0x00, 0x01, 0x15, 0x00, +0xd0, 0x00, 0x61, 0x69, 0x64, 0x00, 0x73, 0x6f, 0x6c, 0x76, +0x69, 0x6e, 0x67, 0x3b, 0x00, 0x03, 0x92, 0x63, 0x61, 0x6e, +0x00, 0x62, 0x65, 0x00, 0x75, 0x73, 0x22, 0x01, 0x42, 0x68, +0x69, 0x67, 0x68, 0x76, 0x00, 0x04, 0xaf, 0x01, 0x01, 0x7b, +0x00, 0x81, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x00, 0x62, +0x8e, 0x02, 0x11, 0x2c, 0x8a, 0x01, 0x83, 0x65, 0x78, 0x61, +0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x4e, 0x04, 0x00, 0xd6, 0x01, +0x00, 0x23, 0x00, 0x00, 0xc9, 0x03, 0x18, 0x65, 0xbb, 0x00, +0x02, 0x81, 0x00, 0x23, 0x65, 0x64, 0x51, 0x00, 0x55, 0x2c, +0x00, 0x6e, 0x6f, 0x72, 0x26, 0x00, 0x01, 0x9c, 0x00, 0x21, +0x69, 0x6e, 0x30, 0x00, 0x06, 0xe1, 0x00, 0x33, 0x00, 0x00, +0x54, 0x47, 0x03, 0x02, 0x20, 0x01, 0x06, 0x95, 0x00, 0xd1, +0x6f, 0x62, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x65, 0x72, +0x72, 0x6f, 0x72, 0xcd, 0x03, 0x01, 0x71, 0x04, 0x01, 0x7f, +0x01, 0x05, 0x15, 0x03, 0x07, 0x13, 0x03, 0x02, 0x42, 0x03, +0x05, 0x40, 0x00, 0x02, 0xce, 0x04, 0x01, 0x06, 0x02, 0x6a, +0x77, 0x61, 0x79, 0x2c, 0x00, 0x61, 0xba, 0x04, 0x05, 0xf4, +0x00, 0x81, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x64, 0x6f, +0xd2, 0x00, 0x33, 0x28, 0x6f, 0x72, 0x00, 0x01, 0x12, 0x29, +0xb8, 0x02, 0x00, 0xa8, 0x01, 0x11, 0x72, 0x8f, 0x00, 0x0d, +0xbe, 0x02, 0x39, 0x6e, 0x65, 0x78, 0xba, 0x02, 0x52, 0x54, +0x68, 0x75, 0x73, 0x2c, 0x15, 0x04, 0x00, 0x67, 0x05, 0x21, +0x69, 0x73, 0x7c, 0x01, 0x9e, 0x65, 0x64, 0x00, 0x77, 0x68, +0x65, 0x6e, 0x00, 0x61, 0xf4, 0x03, 0x04, 0xa6, 0x03, 0x20, +0x79, 0x65, 0x29, 0x04, 0x06, 0xba, 0x00, 0x12, 0x73, 0x66, +0x03, 0x01, 0xc6, 0x01, 0x01, 0xb3, 0x00, 0x10, 0x6f, 0xfa, +0x00, 0x03, 0x77, 0x00, 0x00, 0x6a, 0x00, 0x23, 0x28, 0x41, +0x5b, 0x05, 0x21, 0x61, 0x63, 0x56, 0x04, 0x82, 0x00, 0x64, +0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0xf3, 0x00, 0x13, 0x73, +0xf1, 0x02, 0x31, 0x32, 0x2e, 0x31, 0x3f, 0x00, 0xf2, 0x01, +0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xc8, 0x02, 0x16, 0x32, +0xc8, 0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x73, 0x20, 0x8f, 0x01, 0x36, 0x73, 0x65, 0x00, +0x14, 0x00, 0x02, 0x44, 0x00, 0x04, 0x3f, 0x00, 0x51, 0x00, +0x66, 0x72, 0x6f, 0x6d, 0x7c, 0x00, 0xe1, 0x60, 0x43, 0x75, +0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, +0x70, 0x72, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, 0x54, +0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xae, +0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, +0x65, 0x47, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xf3, +0x02, 0x02, 0x26, 0x01, 0x16, 0x6e, 0x8d, 0x06, 0xa1, 0x00, +0x00, 0x25, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x25, +0x01, 0x14, 0x20, 0x25, 0x01, 0xb0, 0x00, 0x00, 0x52, 0x6f, +0x75, 0x67, 0x68, 0x00, 0x70, 0x65, 0x72, 0x2e, 0x04, 0x21, +0x61, 0x67, 0x3f, 0x00, 0x0a, 0x49, 0x01, 0x25, 0x69, 0x6e, +0x7a, 0x01, 0x02, 0x8c, 0x01, 0x40, 0x69, 0x73, 0x00, 0x69, +0x12, 0x03, 0x71, 0x68, 0x69, 0x6e, 0x74, 0x00, 0x72, 0x61, +0x27, 0x02, 0xe1, 0x74, 0x68, 0x61, 0x6e, 0x00, 0x61, 0x6e, +0x00, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x26, 0x01, 0x46, +0x2e, 0x00, 0x49, 0x66, 0xb4, 0x01, 0x90, 0x67, 0x65, 0x6e, +0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3c, 0x00, 0x21, 0x75, +0x6e, 0xf1, 0x00, 0x24, 0x74, 0x6f, 0x17, 0x00, 0x00, 0xc5, +0x02, 0x03, 0x8f, 0x04, 0x04, 0x60, 0x04, 0xf0, 0x02, 0x70, +0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x00, 0x73, 0x70, 0x65, +0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x54, 0x00, 0x10, 0x2c, +0x6c, 0x03, 0x01, 0xcd, 0x02, 0x74, 0x69, 0x6e, 0x63, 0x72, +0x65, 0x61, 0x73, 0xef, 0x03, 0x42, 0x6f, 0x70, 0x6f, 0x72, +0x29, 0x01, 0x0c, 0xbf, 0x00, 0x53, 0x75, 0x6e, 0x74, 0x69, +0x6c, 0xa3, 0x03, 0x10, 0x2e, 0x24, 0x01, 0xb0, 0x79, 0x6d, +0x6d, 0x65, 0x74, 0x72, 0x79, 0x00, 0x00, 0x00, 0x41, 0x1d, +0x02, 0x11, 0x73, 0x63, 0x06, 0x23, 0x74, 0x6f, 0x69, 0x00, +0x12, 0x79, 0x98, 0x02, 0x41, 0x65, 0x71, 0x75, 0x69, 0xcb, +0x02, 0x04, 0x2e, 0x00, 0x0e, 0xb0, 0x07, 0x0c, 0x1b, 0x01, +0x11, 0x28, 0x1a, 0x01, 0x10, 0x64, 0x4e, 0x05, 0x00, 0xf0, +0x02, 0x61, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x20, 0x00, +0x95, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, +0x47, 0x00, 0x03, 0xff, 0x04, 0x00, 0x29, 0x00, 0x71, 0x69, +0x63, 0x65, 0x61, 0x62, 0x6c, 0x79, 0x3d, 0x02, 0x16, 0x44, +0x29, 0x00, 0x70, 0x00, 0x00, 0x60, 0x45, 0x61, 0x73, 0x79, +0xec, 0x01, 0x23, 0x61, 0x6e, 0x3f, 0x04, 0x08, 0x3a, 0x00, +0x60, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x4b, 0x04, 0x62, +0x73, 0x6f, 0x6c, 0x75, 0x62, 0x6c, 0x8b, 0x07, 0xb2, 0x6f, +0x75, 0x74, 0x00, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, +0xd6, 0x04, 0xf9, 0x03, 0x6f, 0x72, 0x00, 0x67, 0x75, 0x65, +0x73, 0x73, 0x69, 0x6e, 0x67, 0x2c, 0x00, 0x60, 0x48, 0x61, +0x72, 0x64, 0x52, 0x00, 0x01, 0x19, 0x08, 0x01, 0x21, 0x00, +0x22, 0x65, 0x73, 0x58, 0x01, 0x40, 0x70, 0x72, 0x6f, 0x62, +0x90, 0x00, 0x00, 0x5a, 0x00, 0xa2, 0x6e, 0x65, 0x63, 0x65, +0x73, 0x73, 0x61, 0x72, 0x79, 0x2e, 0xd9, 0x02, 0x16, 0x33, +0xd9, 0x02, 0xb0, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, 0x72, +0x65, 0x66, 0x65, 0x72, 0x68, 0x05, 0x01, 0xdf, 0x02, 0x20, +0x4f, 0x6e, 0x91, 0x04, 0x54, 0x74, 0x66, 0x6f, 0x72, 0x6d, +0x5f, 0x00, 0x20, 0x75, 0x70, 0x98, 0x01, 0x10, 0x00, 0x2e, +0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0xcd, 0x02, 0x16, +0x50, 0x12, 0x00, 0x0d, 0xe9, 0x02, 0x33, 0x47, 0x61, 0x6d, +0xe9, 0x02, 0x02, 0x98, 0x00, 0x31, 0x6c, 0x65, 0x74, 0xa9, +0x01, 0x90, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, +0x65, 0xfc, 0x03, 0x01, 0x7b, 0x02, 0x23, 0x60, 0x74, 0x92, +0x02, 0x01, 0x76, 0x01, 0x02, 0xcc, 0x03, 0x11, 0x27, 0x13, +0x05, 0x02, 0x61, 0x03, 0x52, 0x73, 0x68, 0x6f, 0x77, 0x6e, +0x2a, 0x04, 0x08, 0xdc, 0x08, 0x00, 0xd0, 0x08, 0x80, 0x73, +0x6f, 0x00, 0x6c, 0x69, 0x74, 0x2e, 0x00, }; -const unsigned short help_text_len = 2327; -const unsigned short help_text_words = 433; +const unsigned short help_text_len = 2549; +const unsigned short help_text_words = 468; const char quick_help_text[] = "Place bulbs to light up all the squares."; diff --git a/apps/plugins/puzzles/help/loopy.c b/apps/plugins/puzzles/help/loopy.c index 425b157107..62ec8cfa0e 100644 --- a/apps/plugins/puzzles/help/loopy.c +++ b/apps/plugins/puzzles/help/loopy.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,184 +6,262 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 169, TEXT_CENTER | C_RED }, - { 220, TEXT_UNDERLINE }, - { 262, TEXT_CENTER | C_RED }, - { 279, TEXT_UNDERLINE }, - { 280, TEXT_UNDERLINE }, - { 324, TEXT_UNDERLINE }, + { 167, TEXT_CENTER | C_RED }, + { 218, TEXT_UNDERLINE }, + { 260, TEXT_CENTER | C_RED }, + { 277, TEXT_UNDERLINE }, + { 278, TEXT_UNDERLINE }, + { 322, TEXT_UNDERLINE }, + { 353, TEXT_UNDERLINE }, { 355, TEXT_UNDERLINE }, - { 357, TEXT_UNDERLINE }, - { 375, TEXT_UNDERLINE }, - { 390, TEXT_UNDERLINE }, - { 404, TEXT_UNDERLINE }, + { 373, TEXT_UNDERLINE }, + { 388, TEXT_UNDERLINE }, + { 402, TEXT_UNDERLINE }, + { 414, TEXT_CENTER | C_RED }, + { 618, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2260 comp 1600 ratio 0.707965 level 10 saved 660 */ +/* orig 3584 comp 2352 ratio 0.65625 level 10 saved 1232 */ const char help_text[] = { -0xf1, 0x4e, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x33, 0x3a, 0x20, 0x4c, 0x6f, 0x6f, 0x70, 0x79, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, -0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, -0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x64, 0x6f, 0x74, -0x73, 0x2c, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0x00, -0x77, 0x69, 0x74, 0x68, 0x00, 0x79, 0x65, 0x6c, 0x6c, 0x6f, -0x77, 0x00, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x00, 0x74, 0x6f, -0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, -0x77, 0x68, 0x69, 0x63, 0x68, 0x31, 0x00, 0x23, 0x00, 0x79, -0x4e, 0x00, 0x10, 0x61, 0x2b, 0x00, 0x20, 0x65, 0x64, 0x27, -0x00, 0xf0, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, -0x00, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x00, -0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x7c, -0x00, 0x71, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x51, -0x00, 0xf0, 0x00, 0x75, 0x73, 0x65, 0x00, 0x73, 0x6f, 0x6d, -0x65, 0x00, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x86, 0x00, -0x5d, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x7a, 0x00, 0xf0, 0x11, -0x64, 0x72, 0x61, 0x77, 0x00, 0x61, 0x00, 0x73, 0x69, 0x6e, -0x67, 0x6c, 0x65, 0x00, 0x75, 0x6e, 0x62, 0x72, 0x6f, 0x6b, -0x65, 0x6e, 0x00, 0x6c, 0x6f, 0x6f, 0x70, 0x00, 0x66, 0x72, -0x6f, 0x6d, 0x8c, 0x00, 0x01, 0x28, 0x00, 0x21, 0x6f, 0x74, -0xbb, 0x00, 0x61, 0x69, 0x6e, 0x00, 0x74, 0x68, 0x65, 0xdb, -0x00, 0x50, 0x2e, 0x00, 0x00, 0x00, 0x53, 0x64, 0x00, 0x21, -0x6f, 0x66, 0x14, 0x00, 0xd2, 0x73, 0x70, 0x61, 0x63, 0x65, -0x73, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x27, 0x00, -0x02, 0x67, 0x00, 0xf4, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, -0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, -0x2e, 0x00, 0x54, 0x68, 0x65, 0x73, 0x65, 0x0f, 0x00, 0x06, -0xfd, 0x00, 0x84, 0x68, 0x6f, 0x77, 0x00, 0x6d, 0x61, 0x6e, -0x79, 0x51, 0x00, 0x02, 0x3e, 0x00, 0xb2, 0x61, 0x72, 0x6f, -0x75, 0x6e, 0x64, 0x00, 0x74, 0x68, 0x61, 0x74, 0x63, 0x00, -0xa5, 0x00, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x70, 0x61, 0x72, -0x74, 0x29, 0x00, 0x31, 0x6f, 0x6f, 0x70, 0x56, 0x00, 0x02, -0xb8, 0x00, 0x00, 0x3a, 0x01, 0x01, 0xd8, 0x00, 0x83, 0x6d, -0x75, 0x73, 0x74, 0x00, 0x63, 0x6f, 0x72, 0x2e, 0x01, 0x70, -0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x79, 0x52, 0x01, 0x03, -0x3a, 0x00, 0x62, 0x73, 0x65, 0x00, 0x63, 0x6c, 0x75, 0x0a, -0x01, 0x20, 0x62, 0x65, 0xa9, 0x00, 0x94, 0x73, 0x69, 0x64, -0x65, 0x72, 0x65, 0x64, 0x00, 0x61, 0x38, 0x00, 0x90, 0x00, -0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0xef, 0x00, -0x12, 0x49, 0xd7, 0x00, 0xd2, 0x64, 0x65, 0x66, 0x61, 0x75, -0x6c, 0x74, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x12, 0x00, -0x00, 0xb2, 0x01, 0x01, 0xae, 0x01, 0x98, 0x72, 0x72, 0x61, -0x6e, 0x67, 0x65, 0x64, 0x00, 0x69, 0x02, 0x02, 0x80, 0x73, -0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x3b, 0xe3, 0x00, 0x51, -0x65, 0x76, 0x65, 0x72, 0x2c, 0xa4, 0x00, 0xf1, 0x19, 0x63, -0x61, 0x6e, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x70, 0x6c, -0x61, 0x79, 0x00, 0x6f, 0x6e, 0x00, 0x74, 0x72, 0x69, 0x61, -0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x6f, 0x72, 0x00, -0x68, 0x65, 0x78, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x47, -0x00, 0x20, 0x73, 0x2c, 0x14, 0x00, 0x10, 0x65, 0x5a, 0x02, -0xf0, 0x01, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x65, 0x78, 0x6f, -0x74, 0x69, 0x63, 0x00, 0x6f, 0x6e, 0x65, 0x73, 0x9a, 0x00, -0x60, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x1b, 0x01, 0x01, -0x90, 0x00, 0xf2, 0x05, 0x62, 0x61, 0x73, 0x69, 0x63, 0x00, -0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x69, 0x64, 0x65, -0x61, 0x00, 0x67, 0x6f, 0xe7, 0x00, 0xb0, 0x4e, 0x69, 0x6b, -0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x31, 0x30, 0x5d, 0x38, 0x00, -0x01, 0xbd, 0x02, 0xf1, 0x00, 0x00, 0x77, 0x61, 0x73, 0x00, -0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, -0xb1, 0x01, 0x52, 0x72, 0x69, 0x62, 0x75, 0x74, 0x77, 0x02, -0x30, 0x74, 0x68, 0x69, 0xc5, 0x01, 0x40, 0x6c, 0x6c, 0x65, -0x63, 0x09, 0x01, 0xf2, 0x04, 0x00, 0x62, 0x79, 0x00, 0x4d, -0x69, 0x6b, 0x65, 0x00, 0x50, 0x69, 0x6e, 0x6e, 0x61, 0x2c, -0x00, 0x61, 0x6e, 0x64, 0x67, 0x02, 0x40, 0x71, 0x75, 0x65, -0x6e, 0x68, 0x01, 0x62, 0x65, 0x6e, 0x68, 0x61, 0x6e, 0x63, -0x3c, 0x00, 0xf0, 0x05, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, -0x00, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x74, -0x79, 0x70, 0x65, 0x73, 0x12, 0x01, 0x42, 0x6e, 0x6f, 0x6e, -0x2d, 0x16, 0x01, 0x02, 0x25, 0x01, 0xa3, 0x62, 0x79, 0x00, -0x4c, 0x61, 0x6d, 0x62, 0x72, 0x6f, 0x73, 0x08, 0x00, 0x10, -0x75, 0x9e, 0x00, 0x00, 0xa6, 0x00, 0xd1, 0x00, 0x68, 0x74, -0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, -0xbd, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, -0x65, 0x6e, 0x2f, 0xe1, 0x00, 0x50, 0x73, 0x2f, 0x73, 0x6c, -0x69, 0x07, 0x03, 0xf1, 0x01, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, -0x68, 0x74, 0x6d, 0x6c, 0x00, 0x28, 0x62, 0x65, 0x77, 0x61, -0x72, 0x9b, 0x02, 0xd3, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x29, -0x00, 0x00, 0x00, 0x32, 0x33, 0x2e, 0x31, 0xad, 0x03, 0x01, -0xe1, 0x00, 0x40, 0x6f, 0x6c, 0x73, 0x20, 0x3a, 0x01, 0x42, -0x6c, 0x69, 0x63, 0x6b, 0x47, 0x02, 0x20, 0x65, 0x66, 0xd4, -0x01, 0x00, 0x3c, 0x03, 0x60, 0x62, 0x75, 0x74, 0x74, 0x6f, -0x6e, 0x94, 0x01, 0x18, 0x61, 0x33, 0x03, 0x01, 0x0e, 0x01, -0xd4, 0x75, 0x72, 0x6e, 0x00, 0x69, 0x74, 0x00, 0x62, 0x6c, -0x61, 0x63, 0x6b, 0x2c, 0xbe, 0x02, 0x32, 0x69, 0x6e, 0x67, -0xa3, 0x02, 0x00, 0xd9, 0x01, 0x00, 0x27, 0x03, 0x10, 0x6b, -0x24, 0x00, 0x2e, 0x69, 0x73, 0xa8, 0x02, 0x03, 0x71, 0x00, -0x20, 0x61, 0x67, 0x13, 0x03, 0x04, 0x50, 0x00, 0x04, 0xef, -0x02, 0x04, 0x6d, 0x00, 0x02, 0x1e, 0x00, 0x50, 0x28, 0x6d, -0x65, 0x61, 0x6e, 0x5a, 0x00, 0x03, 0x0c, 0x04, 0x70, 0x6e, -0x27, 0x74, 0x00, 0x73, 0x75, 0x72, 0x26, 0x00, 0x21, 0x74, -0x29, 0x90, 0x02, 0x15, 0x66, 0x27, 0x04, 0x01, 0x18, 0x00, -0x01, 0x82, 0x00, 0x11, 0x61, 0x74, 0x00, 0x21, 0x69, 0x63, -0x48, 0x02, 0x01, 0x55, 0x00, 0x61, 0x73, 0x65, 0x67, 0x6d, -0x65, 0x6e, 0x8f, 0x00, 0x3d, 0x6e, 0x6f, 0x74, 0x93, 0x00, -0x06, 0x8e, 0x02, 0x15, 0x63, 0x0c, 0x01, 0x4b, 0x72, 0x69, -0x67, 0x68, 0x0d, 0x01, 0xb0, 0x74, 0x6f, 0x00, 0x72, 0x65, -0x6d, 0x6f, 0x76, 0x65, 0x00, 0x69, 0x56, 0x03, 0xb0, 0x6d, -0x70, 0x6c, 0x65, 0x74, 0x65, 0x6c, 0x79, 0x2e, 0x00, 0x41, -0xad, 0x00, 0x12, 0x2c, 0x3d, 0x00, 0x00, 0xae, 0x00, 0x60, -0x61, 0x00, 0x73, 0x65, 0x63, 0x6f, 0xb4, 0x03, 0x8b, 0x69, -0x6d, 0x65, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0xe5, 0x00, 0x20, -0x62, 0x61, 0x66, 0x00, 0x13, 0x6f, 0xed, 0x00, 0x00, 0xc9, -0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x20, 0x00, 0x11, 0x61, -0x63, 0x02, 0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, -0x69, 0x62, 0x49, 0x03, 0x13, 0x73, 0x79, 0x02, 0x33, 0x32, -0x2e, 0x31, 0x13, 0x05, 0xd3, 0x73, 0x6f, 0x00, 0x61, 0x76, -0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0xdd, 0x01, -0x13, 0x32, 0xdd, 0x01, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, -0x65, 0x74, 0x65, 0x72, 0xdf, 0x01, 0x02, 0x6c, 0x04, 0x06, -0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x02, 0xe4, -0x04, 0x00, 0x79, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, -0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6f, -0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0x91, 0x54, 0x79, 0x70, -0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x94, 0x02, 0x91, 0x57, -0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x22, 0x01, -0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x68, 0x02, 0x00, 0xc7, -0x02, 0x70, 0x2c, 0x00, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x41, -0x04, 0x05, 0xf0, 0x04, 0x00, 0x1c, 0x00, 0x31, 0x72, 0x65, -0x67, 0xd6, 0x00, 0x61, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x73, -0x32, 0x03, 0x93, 0x64, 0x6f, 0x77, 0x6e, 0x2e, 0x00, 0x46, -0x6f, 0x72, 0x1d, 0x04, 0x04, 0xe5, 0x03, 0xa1, 0x69, 0x74, -0x27, 0x73, 0x00, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x05, -0x01, 0x7c, 0x03, 0x01, 0x7f, 0x03, 0x61, 0x75, 0x6e, 0x74, -0x65, 0x64, 0x3b, 0xe2, 0x03, 0x10, 0x6f, 0xed, 0x02, 0x06, -0x4c, 0x03, 0x01, 0x41, 0x03, 0x00, 0xc3, 0x01, 0x72, 0x6d, -0x61, 0x79, 0x00, 0x68, 0x61, 0x76, 0xa7, 0x02, 0x01, 0x84, -0x02, 0x41, 0x61, 0x00, 0x62, 0x69, 0xc0, 0x05, 0x22, 0x73, -0x65, 0x60, 0x05, 0x01, 0xad, 0x04, 0x52, 0x69, 0x6d, 0x65, -0x6e, 0x73, 0x91, 0x00, 0x25, 0x72, 0x65, 0xb3, 0x00, 0x00, -0xdd, 0x00, 0x50, 0x47, 0x72, 0x69, 0x64, 0x20, 0x59, 0x00, -0x40, 0x00, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x02, 0x88, 0x06, -0x00, 0x7c, 0x06, 0x20, 0x68, 0x6f, 0x40, 0x06, 0x04, 0xde, -0x05, 0x00, 0xe4, 0x01, 0x04, 0x10, 0x04, 0x26, 0x6f, 0x66, -0x8c, 0x00, 0x72, 0x74, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x2e, -0x19, 0x06, 0x01, 0x8c, 0x00, 0x13, 0x61, 0xda, 0x01, 0x11, -0x66, 0x1e, 0x06, 0x01, 0x29, 0x06, 0x21, 0x61, 0x6d, 0x55, -0x02, 0x06, 0xb0, 0x00, 0x70, 0x6d, 0x75, 0x6c, 0x74, 0x69, -0x70, 0x6c, 0x9b, 0x00, 0x40, 0x66, 0x66, 0x65, 0x72, 0xac, -0x02, 0x05, 0x52, 0x00, 0xc1, 0x76, 0x65, 0x72, 0x74, 0x65, -0x78, 0x00, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x3f, 0x00, 0x50, -0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x05, 0x51, 0x4b, 0x69, -0x74, 0x65, 0x73, 0x85, 0x05, 0x22, 0x29, 0x3b, 0x14, 0x01, -0x1a, 0x73, 0x73, 0x00, 0x00, 0x3b, 0x00, 0x1f, 0x69, 0x76, -0x00, 0x07, 0x0e, 0x6d, 0x00, 0x01, 0xa5, 0x00, 0x07, 0x6b, -0x00, 0x74, 0x47, 0x72, 0x65, 0x61, 0x74, 0x20, 0x48, 0x89, -0x05, 0x12, 0x29, 0x65, 0x06, 0x02, 0xb1, 0x01, 0x18, 0x2c, -0xaf, 0x05, 0x00, 0xd2, 0x01, 0x92, 0x68, 0x6f, 0x6e, 0x65, -0x79, 0x63, 0x6f, 0x6d, 0x62, 0xcb, 0x01, 0x01, 0x5c, 0x01, -0x20, 0x66, 0x75, 0x50, 0x05, 0x21, 0x72, 0x65, 0x26, 0x00, -0x02, 0x2b, 0x05, 0x08, 0xa2, 0x00, 0x26, 0x69, 0x72, 0xa4, -0x00, 0x00, 0x1c, 0x00, 0x0a, 0x24, 0x01, 0x12, 0x3b, 0xfe, -0x01, 0x32, 0x6d, 0x61, 0x6b, 0x15, 0x00, 0x13, 0x6d, 0xa6, -0x04, 0x11, 0x61, 0xd6, 0x06, 0x41, 0x6e, 0x66, 0x75, 0x73, -0x76, 0x04, 0x02, 0x40, 0x06, 0x00, 0xbe, 0x01, 0x40, 0x44, -0x69, 0x66, 0x66, 0xf8, 0x03, 0x20, 0x74, 0x79, 0xd8, 0x04, -0x03, 0xe4, 0x04, 0x03, 0xf3, 0x01, 0x05, 0x1a, 0x00, 0x03, -0xf9, 0x03, 0x60, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0xe2, -0x05, 0x80, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2e, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf1, 0x3c, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, +0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, +0x6f, 0x66, 0x00, 0x64, 0x6f, 0x74, 0x73, 0x2c, 0x00, 0x6d, +0x61, 0x72, 0x6b, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, +0x00, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x6c, 0x69, +0x6e, 0x65, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x69, 0x6e, 0x64, +0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x77, 0x68, 0x69, 0x63, +0x68, 0x31, 0x00, 0x23, 0x00, 0x79, 0x4e, 0x00, 0x10, 0x61, +0x2b, 0x00, 0x20, 0x65, 0x64, 0x27, 0x00, 0xf0, 0x0b, 0x63, +0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x64, 0x69, 0x72, +0x65, 0x63, 0x74, 0x6c, 0x79, 0x00, 0x74, 0x6f, 0x67, 0x65, +0x74, 0x68, 0x65, 0x72, 0x2e, 0x7c, 0x00, 0x71, 0x72, 0x00, +0x61, 0x69, 0x6d, 0x00, 0x69, 0x51, 0x00, 0xf0, 0x00, 0x75, +0x73, 0x65, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x00, 0x73, 0x75, +0x62, 0x73, 0x65, 0x74, 0x86, 0x00, 0x5d, 0x74, 0x68, 0x6f, +0x73, 0x65, 0x7a, 0x00, 0xf0, 0x11, 0x64, 0x72, 0x61, 0x77, +0x00, 0x61, 0x00, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x00, +0x75, 0x6e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x00, 0x6c, +0x6f, 0x6f, 0x70, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x8c, 0x00, +0x01, 0x28, 0x00, 0x21, 0x6f, 0x74, 0xbb, 0x00, 0x61, 0x69, +0x6e, 0x00, 0x74, 0x68, 0x65, 0xdb, 0x00, 0x50, 0x2e, 0x00, +0x00, 0x00, 0x53, 0x64, 0x00, 0x21, 0x6f, 0x66, 0x14, 0x00, +0xd2, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x00, 0x62, 0x65, +0x74, 0x77, 0x65, 0x65, 0x27, 0x00, 0x02, 0x67, 0x00, 0xf4, +0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, +0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x00, 0x54, 0x68, +0x65, 0x73, 0x65, 0x0f, 0x00, 0x06, 0xfd, 0x00, 0x84, 0x68, +0x6f, 0x77, 0x00, 0x6d, 0x61, 0x6e, 0x79, 0x51, 0x00, 0x02, +0x3e, 0x00, 0xb2, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, +0x74, 0x68, 0x61, 0x74, 0x63, 0x00, 0xa5, 0x00, 0x66, 0x6f, +0x72, 0x6d, 0x00, 0x70, 0x61, 0x72, 0x74, 0x29, 0x00, 0x31, +0x6f, 0x6f, 0x70, 0x56, 0x00, 0x02, 0xb8, 0x00, 0x00, 0x3a, +0x01, 0x01, 0xd8, 0x00, 0x83, 0x6d, 0x75, 0x73, 0x74, 0x00, +0x63, 0x6f, 0x72, 0x2e, 0x01, 0x70, 0x73, 0x61, 0x74, 0x69, +0x73, 0x66, 0x79, 0x52, 0x01, 0x03, 0x3a, 0x00, 0x62, 0x73, +0x65, 0x00, 0x63, 0x6c, 0x75, 0x0a, 0x01, 0x20, 0x62, 0x65, +0xa9, 0x00, 0x94, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, +0x00, 0x61, 0x38, 0x00, 0x90, 0x00, 0x73, 0x6f, 0x6c, 0x75, +0x74, 0x69, 0x6f, 0x6e, 0xef, 0x00, 0x12, 0x49, 0xd7, 0x00, +0xd2, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x6d, +0x6f, 0x64, 0x65, 0x2c, 0x12, 0x00, 0x00, 0xb2, 0x01, 0x01, +0xae, 0x01, 0x98, 0x72, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x64, +0x00, 0x69, 0x02, 0x02, 0x80, 0x73, 0x71, 0x75, 0x61, 0x72, +0x65, 0x73, 0x3b, 0xe3, 0x00, 0x51, 0x65, 0x76, 0x65, 0x72, +0x2c, 0xa4, 0x00, 0xf1, 0x19, 0x63, 0x61, 0x6e, 0x00, 0x61, +0x6c, 0x73, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x6f, +0x6e, 0x00, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, +0x61, 0x72, 0x00, 0x6f, 0x72, 0x00, 0x68, 0x65, 0x78, 0x61, +0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x47, 0x00, 0x20, 0x73, 0x2c, +0x14, 0x00, 0x10, 0x65, 0x5a, 0x02, 0xf0, 0x01, 0x6d, 0x6f, +0x72, 0x65, 0x00, 0x65, 0x78, 0x6f, 0x74, 0x69, 0x63, 0x00, +0x6f, 0x6e, 0x65, 0x73, 0x9a, 0x00, 0x60, 0x43, 0x72, 0x65, +0x64, 0x69, 0x74, 0x1b, 0x01, 0x01, 0x90, 0x00, 0xf2, 0x05, +0x62, 0x61, 0x73, 0x69, 0x63, 0x00, 0x70, 0x75, 0x7a, 0x7a, +0x6c, 0x65, 0x00, 0x69, 0x64, 0x65, 0x61, 0x00, 0x67, 0x6f, +0xe7, 0x00, 0xb0, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, +0x5b, 0x31, 0x30, 0x5d, 0x38, 0x00, 0x01, 0xcf, 0x02, 0xf1, +0x00, 0x00, 0x77, 0x61, 0x73, 0x00, 0x6f, 0x72, 0x69, 0x67, +0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0xb1, 0x01, 0x52, 0x72, +0x69, 0x62, 0x75, 0x74, 0x77, 0x02, 0x30, 0x74, 0x68, 0x69, +0xc5, 0x01, 0x40, 0x6c, 0x6c, 0x65, 0x63, 0x09, 0x01, 0xf2, +0x04, 0x00, 0x62, 0x79, 0x00, 0x4d, 0x69, 0x6b, 0x65, 0x00, +0x50, 0x69, 0x6e, 0x6e, 0x61, 0x2c, 0x00, 0x61, 0x6e, 0x64, +0x67, 0x02, 0x40, 0x71, 0x75, 0x65, 0x6e, 0x68, 0x01, 0x62, +0x65, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x3c, 0x00, 0xf0, 0x05, +0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x76, 0x61, 0x72, +0x69, 0x6f, 0x75, 0x73, 0x00, 0x74, 0x79, 0x70, 0x65, 0x73, +0x12, 0x01, 0x42, 0x6e, 0x6f, 0x6e, 0x2d, 0x16, 0x01, 0x02, +0x25, 0x01, 0xa3, 0x62, 0x79, 0x00, 0x4c, 0x61, 0x6d, 0x62, +0x72, 0x6f, 0x73, 0x08, 0x00, 0x10, 0x75, 0x9e, 0x00, 0x00, +0xa6, 0x00, 0xe1, 0x00, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, +0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0xbe, 0x00, 0xa2, +0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, +0xe2, 0x00, 0x50, 0x73, 0x2f, 0x73, 0x6c, 0x69, 0x08, 0x03, +0xc3, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x00, 0x00, 0x00, 0x32, +0x33, 0x2e, 0x31, 0xaa, 0x03, 0x01, 0xcc, 0x00, 0x40, 0x6f, +0x6c, 0x73, 0x20, 0x25, 0x01, 0x42, 0x6c, 0x69, 0x63, 0x6b, +0x32, 0x02, 0x20, 0x65, 0x66, 0xbf, 0x01, 0x00, 0x27, 0x03, +0x60, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x7f, 0x01, 0x18, +0x61, 0x1e, 0x03, 0x01, 0xf9, 0x00, 0xd4, 0x75, 0x72, 0x6e, +0x00, 0x69, 0x74, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x2c, +0xa9, 0x02, 0x32, 0x69, 0x6e, 0x67, 0x8e, 0x02, 0x00, 0xc4, +0x01, 0x00, 0x12, 0x03, 0x10, 0x6b, 0x24, 0x00, 0x2e, 0x69, +0x73, 0x93, 0x02, 0x03, 0x71, 0x00, 0x20, 0x61, 0x67, 0xfe, +0x02, 0x04, 0x50, 0x00, 0x04, 0xda, 0x02, 0x04, 0x6d, 0x00, +0x02, 0x1e, 0x00, 0x50, 0x28, 0x6d, 0x65, 0x61, 0x6e, 0x5a, +0x00, 0x03, 0xf7, 0x03, 0x70, 0x6e, 0x27, 0x74, 0x00, 0x73, +0x75, 0x72, 0x26, 0x00, 0x21, 0x74, 0x29, 0x7b, 0x02, 0x15, +0x66, 0x12, 0x04, 0x01, 0x18, 0x00, 0x01, 0x82, 0x00, 0x11, +0x61, 0x74, 0x00, 0x21, 0x69, 0x63, 0x33, 0x02, 0x01, 0x55, +0x00, 0x61, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x8f, 0x00, +0x3d, 0x6e, 0x6f, 0x74, 0x93, 0x00, 0x06, 0x79, 0x02, 0x15, +0x63, 0x0c, 0x01, 0x4b, 0x72, 0x69, 0x67, 0x68, 0x0d, 0x01, +0xb0, 0x74, 0x6f, 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, +0x00, 0x69, 0x41, 0x03, 0xb0, 0x6d, 0x70, 0x6c, 0x65, 0x74, +0x65, 0x6c, 0x79, 0x2e, 0x00, 0x41, 0xad, 0x00, 0x12, 0x2c, +0x3d, 0x00, 0x00, 0xae, 0x00, 0x60, 0x61, 0x00, 0x73, 0x65, +0x63, 0x6f, 0x9f, 0x03, 0x8b, 0x69, 0x6d, 0x65, 0x00, 0x77, +0x69, 0x6c, 0x6c, 0xe5, 0x00, 0x20, 0x62, 0x61, 0x66, 0x00, +0x13, 0x6f, 0xed, 0x00, 0x00, 0xc9, 0x00, 0x41, 0x28, 0x41, +0x6c, 0x6c, 0x20, 0x00, 0x11, 0x61, 0x4e, 0x02, 0x92, 0x73, +0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x34, 0x03, +0x13, 0x73, 0x64, 0x02, 0x33, 0x32, 0x2e, 0x31, 0xfe, 0x04, +0xe2, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, +0x62, 0x6c, 0x65, 0x2e, 0x29, 0xdd, 0x01, 0x13, 0x32, 0xdd, +0x01, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, +0x72, 0xdf, 0x01, 0x02, 0x57, 0x04, 0x06, 0x14, 0x00, 0x02, +0x41, 0x00, 0x04, 0x3c, 0x00, 0x02, 0xcf, 0x04, 0x00, 0x79, +0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, +0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x22, 0x6f, +0x6e, 0x1a, 0x00, 0x91, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x7f, 0x02, 0x91, 0x57, 0x69, 0x64, 0x74, +0x68, 0x2c, 0x00, 0x48, 0x65, 0x22, 0x01, 0x51, 0x00, 0x00, +0x53, 0x69, 0x7a, 0xee, 0x04, 0x00, 0xb2, 0x02, 0x70, 0x2c, +0x00, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x2c, 0x04, 0x05, 0xdb, +0x04, 0x00, 0x1c, 0x00, 0x31, 0x72, 0x65, 0x67, 0xd6, 0x00, +0x61, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x1d, 0x03, 0x93, +0x64, 0x6f, 0x77, 0x6e, 0x2e, 0x00, 0x46, 0x6f, 0x72, 0x08, +0x04, 0x04, 0xd0, 0x03, 0xa1, 0x69, 0x74, 0x27, 0x73, 0x00, +0x63, 0x6c, 0x65, 0x61, 0x72, 0xfb, 0x04, 0x01, 0x67, 0x03, +0x01, 0x6a, 0x03, 0x61, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x3b, +0xcd, 0x03, 0x10, 0x6f, 0xd7, 0x02, 0x06, 0x37, 0x03, 0x01, +0x2c, 0x03, 0x00, 0xc3, 0x01, 0x72, 0x6d, 0x61, 0x79, 0x00, +0x68, 0x61, 0x76, 0xa7, 0x02, 0x01, 0x84, 0x02, 0x41, 0x61, +0x00, 0x62, 0x69, 0xab, 0x05, 0x22, 0x73, 0x65, 0x4b, 0x05, +0x01, 0x98, 0x04, 0x52, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x91, +0x00, 0x25, 0x72, 0x65, 0xb3, 0x00, 0x00, 0xdd, 0x00, 0x50, +0x47, 0x72, 0x69, 0x64, 0x20, 0x59, 0x00, 0x40, 0x00, 0x00, +0x00, 0x41, 0x9d, 0x01, 0x02, 0x73, 0x06, 0x00, 0x67, 0x06, +0x20, 0x68, 0x6f, 0x2b, 0x06, 0x04, 0xc9, 0x05, 0x00, 0xe4, +0x01, 0x04, 0xfb, 0x03, 0x26, 0x6f, 0x66, 0x8c, 0x00, 0x72, +0x74, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x04, 0x06, 0x01, +0x8c, 0x00, 0x13, 0x61, 0xda, 0x01, 0x11, 0x66, 0x09, 0x06, +0x01, 0x14, 0x06, 0x21, 0x61, 0x6d, 0x55, 0x02, 0x06, 0xb0, +0x00, 0x70, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x9b, +0x00, 0x40, 0x66, 0x66, 0x65, 0x72, 0xac, 0x02, 0x05, 0x52, +0x00, 0xc1, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x28, +0x65, 0x2e, 0x67, 0x2e, 0x3f, 0x00, 0x50, 0x43, 0x61, 0x69, +0x72, 0x6f, 0xf8, 0x04, 0x51, 0x4b, 0x69, 0x74, 0x65, 0x73, +0x70, 0x05, 0x22, 0x29, 0x3b, 0x14, 0x01, 0x1a, 0x73, 0x73, +0x00, 0x00, 0x3b, 0x00, 0x1f, 0x69, 0x76, 0x00, 0x07, 0x0e, +0x6d, 0x00, 0x01, 0xa5, 0x00, 0x07, 0x6b, 0x00, 0x74, 0x47, +0x72, 0x65, 0x61, 0x74, 0x20, 0x48, 0x74, 0x05, 0x12, 0x29, +0x50, 0x06, 0x02, 0xb1, 0x01, 0x18, 0x2c, 0x9a, 0x05, 0x00, +0xd2, 0x01, 0x92, 0x68, 0x6f, 0x6e, 0x65, 0x79, 0x63, 0x6f, +0x6d, 0x62, 0xcb, 0x01, 0x01, 0x5c, 0x01, 0x20, 0x66, 0x75, +0x3b, 0x05, 0x21, 0x72, 0x65, 0x26, 0x00, 0x02, 0x16, 0x05, +0x08, 0xa2, 0x00, 0x26, 0x69, 0x72, 0xa4, 0x00, 0x00, 0x1c, +0x00, 0x0a, 0x24, 0x01, 0x12, 0x3b, 0xfe, 0x01, 0x32, 0x6d, +0x61, 0x6b, 0x15, 0x00, 0x13, 0x6d, 0xa6, 0x04, 0x11, 0x61, +0xc1, 0x06, 0x41, 0x6e, 0x66, 0x75, 0x73, 0x76, 0x04, 0x02, +0x2b, 0x06, 0x00, 0xbe, 0x01, 0x40, 0x44, 0x69, 0x66, 0x66, +0xf8, 0x03, 0x20, 0x74, 0x79, 0xd8, 0x04, 0x03, 0xe4, 0x04, +0x03, 0xf3, 0x01, 0x05, 0x1a, 0x00, 0x03, 0xf9, 0x03, 0x60, +0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0xcd, 0x05, 0x02, 0x2f, +0x05, 0x12, 0x2e, 0x45, 0x03, 0x13, 0x33, 0x45, 0x03, 0x81, +0x75, 0x73, 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x21, 0x01, +0x21, 0x63, 0x65, 0x4b, 0x03, 0x20, 0x4f, 0x6e, 0x6a, 0x00, +0x10, 0x74, 0x6a, 0x07, 0x13, 0x73, 0x7b, 0x07, 0x70, 0x75, +0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, 0x00, 0x17, 0x00, +0x2e, 0x00, 0x12, 0x2c, 0x39, 0x03, 0x16, 0x50, 0x12, 0x00, +0x0d, 0x55, 0x03, 0x33, 0x47, 0x61, 0x6d, 0x55, 0x03, 0x02, +0x22, 0x04, 0x22, 0x6c, 0x65, 0x3c, 0x05, 0x00, 0xd9, 0x00, +0x22, 0x69, 0x67, 0xcd, 0x04, 0x00, 0xd6, 0x07, 0x00, 0x85, +0x02, 0x02, 0x5d, 0x05, 0xa0, 0x69, 0x6e, 0x67, 0x73, 0x3a, +0x00, 0x00, 0x00, 0x60, 0x44, 0xc7, 0x07, 0x82, 0x65, 0x78, +0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0xfe, 0x02, 0x02, 0x16, +0x08, 0x30, 0x66, 0x61, 0x69, 0x6c, 0x06, 0x10, 0x27, 0xa7, +0x01, 0x02, 0x37, 0x03, 0x02, 0x99, 0x06, 0x03, 0x9b, 0x07, +0x41, 0x3a, 0x00, 0x77, 0x68, 0xbb, 0x02, 0x01, 0x85, 0x04, +0x04, 0x08, 0x01, 0x00, 0x3f, 0x00, 0x20, 0x68, 0x61, 0xa3, +0x08, 0xa1, 0x65, 0x6e, 0x00, 0x65, 0x78, 0x70, 0x6c, 0x69, +0x63, 0x69, 0xb1, 0x06, 0x04, 0x61, 0x00, 0x05, 0x23, 0x04, +0x04, 0xf5, 0x07, 0x00, 0x53, 0x00, 0x01, 0x20, 0x05, 0x15, +0x2d, 0xf3, 0x04, 0x36, 0x69, 0x74, 0x2c, 0xdf, 0x04, 0x50, +0x69, 0x73, 0x00, 0x73, 0x74, 0xd4, 0x00, 0x00, 0x70, 0x08, +0x40, 0x6e, 0x2c, 0x00, 0x6a, 0x72, 0x08, 0x01, 0xfb, 0x07, +0x01, 0xa1, 0x00, 0x50, 0x00, 0x67, 0x72, 0x65, 0x79, 0x3b, +0x07, 0x44, 0x6f, 0x75, 0x72, 0x2e, 0xc3, 0x05, 0x03, 0x21, +0x05, 0x25, 0x69, 0x73, 0x28, 0x01, 0x36, 0x66, 0x66, 0x2c, +0x84, 0x00, 0x04, 0xf6, 0x08, 0x11, 0x65, 0xc1, 0x05, 0x01, +0x58, 0x00, 0x30, 0x00, 0x61, 0x74, 0x47, 0x02, 0x10, 0x2e, +0x12, 0x01, 0x52, 0x41, 0x75, 0x74, 0x6f, 0x2d, 0x2c, 0x01, +0x60, 0x00, 0x75, 0x6e, 0x69, 0x71, 0x75, 0xf2, 0x04, 0x21, +0x74, 0x68, 0xd3, 0x02, 0x58, 0x65, 0x64, 0x67, 0x65, 0x73, +0x13, 0x01, 0x27, 0x66, 0x66, 0x14, 0x01, 0x30, 0x2e, 0x00, +0x57, 0x14, 0x01, 0x01, 0x76, 0x04, 0x18, 0x6f, 0xc5, 0x05, +0x01, 0xf3, 0x03, 0x00, 0xb6, 0x08, 0x02, 0xfb, 0x00, 0x41, +0x74, 0x61, 0x74, 0x75, 0x4f, 0x00, 0x05, 0x17, 0x0a, 0x05, +0x78, 0x01, 0x02, 0xc0, 0x01, 0x71, 0x70, 0x6f, 0x74, 0x65, +0x6e, 0x74, 0x69, 0x2b, 0x08, 0x82, 0x70, 0x72, 0x6f, 0x70, +0x61, 0x67, 0x61, 0x74, 0x3c, 0x00, 0x03, 0x47, 0x00, 0x56, +0x61, 0x6c, 0x6f, 0x6e, 0x67, 0xea, 0x03, 0x01, 0xd2, 0x00, +0x40, 0x2c, 0x00, 0x69, 0x66, 0xae, 0x08, 0x00, 0xce, 0x03, +0x98, 0x62, 0x6f, 0x74, 0x68, 0x00, 0x65, 0x6e, 0x64, 0x73, +0xea, 0x09, 0x02, 0x13, 0x02, 0x00, 0x94, 0x00, 0x25, 0x65, +0x64, 0xea, 0x0a, 0x72, 0x74, 0x6f, 0x00, 0x6f, 0x6e, 0x6c, +0x79, 0x39, 0x00, 0x01, 0x0b, 0x05, 0x00, 0x2b, 0x00, 0x53, +0x2e, 0x00, 0x28, 0x54, 0x68, 0xd8, 0x08, 0x13, 0x69, 0xa0, +0x02, 0x63, 0x69, 0x66, 0x00, 0x74, 0x77, 0x6f, 0x3e, 0x01, +0x41, 0x6d, 0x65, 0x65, 0x74, 0x35, 0x01, 0x04, 0x53, 0x04, +0x00, 0x72, 0x03, 0x27, 0x6e, 0x6f, 0x43, 0x00, 0x43, 0x73, +0x00, 0x64, 0x6f, 0x57, 0x01, 0x01, 0xcf, 0x01, 0x13, 0x6e, +0x20, 0x0b, 0x06, 0x7e, 0x01, 0x11, 0x65, 0x52, 0x08, 0x02, +0xac, 0x00, 0x0c, 0x47, 0x07, 0x00, 0xc5, 0x00, 0x12, 0x6e, +0x21, 0x00, 0x50, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x09, 0x00, +0x30, 0x65, 0x27, 0x73, 0x63, 0x00, 0x61, 0x72, 0x65, 0x61, +0x73, 0x6f, 0x6e, 0xcd, 0x00, 0x65, 0x73, 0x68, 0x6f, 0x75, +0x6c, 0x64, 0xa7, 0x05, 0x02, 0x72, 0x07, 0x40, 0x73, 0x65, +0x70, 0x61, 0x8d, 0x03, 0x01, 0xbe, 0x0b, 0x00, 0xc1, 0x0b, +0x00, 0x61, 0x01, 0x40, 0x65, 0x61, 0x63, 0x68, 0xe4, 0x00, +0x26, 0x2e, 0x29, 0x65, 0x0a, 0x00, 0xed, 0x04, 0x70, 0x00, +0x60, 0x42, 0x61, 0x73, 0x65, 0x64, 0xdc, 0x02, 0x02, 0x4b, +0x0a, 0x42, 0x6e, 0x6c, 0x79, 0x27, 0x7f, 0x02, 0x63, 0x65, +0x66, 0x66, 0x65, 0x63, 0x74, 0xa8, 0x01, 0x02, 0x5b, 0x00, +0x01, 0x9d, 0x01, 0x29, 0x6f, 0x6e, 0x96, 0x01, 0x03, 0x87, +0x06, 0x07, 0x1f, 0x05, 0x23, 0x61, 0x74, 0x13, 0x05, 0x83, +0x65, 0x67, 0x72, 0x65, 0x65, 0x00, 0x32, 0x00, 0xd3, 0x0b, +0x70, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x11, 0x02, +0x02, 0xde, 0x0b, 0x10, 0x46, 0x70, 0x0a, 0x20, 0x78, 0x61, +0xfd, 0x07, 0x14, 0x2c, 0x25, 0x00, 0x07, 0xc1, 0x06, 0x08, +0x87, 0x00, 0x07, 0x7b, 0x00, 0x30, 0x6f, 0x63, 0x63, 0x8a, +0x0c, 0x13, 0x74, 0xd4, 0x03, 0x22, 0x75, 0x72, 0xba, 0x00, +0x41, 0x63, 0x6f, 0x72, 0x6e, 0xfc, 0x0b, 0x0f, 0xe0, 0x00, +0x0a, 0x00, 0xa7, 0x01, 0x32, 0x67, 0x61, 0x6d, 0x85, 0x02, +0x13, 0x65, 0xea, 0x00, 0x04, 0xcd, 0x00, 0x00, 0x2b, 0x03, +0x01, 0x68, 0x00, 0x01, 0x14, 0x08, 0x30, 0x74, 0x61, 0x6b, +0xde, 0x00, 0x01, 0x2d, 0x07, 0x05, 0xfc, 0x02, 0x00, 0x77, +0x01, 0x11, 0x27, 0x74, 0x05, 0x4f, 0x72, 0x65, 0x61, 0x64, +0xd9, 0x03, 0x09, 0x03, 0xb7, 0x01, 0x00, 0x39, 0x02, 0x03, +0xbe, 0x00, 0x27, 0x64, 0x6f, 0x5e, 0x0b, 0xe0, 0x77, 0x6f, +0x72, 0x6b, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x79, 0x6f, 0x75, +0x2e, 0x00, }; -const unsigned short help_text_len = 2260; -const unsigned short help_text_words = 414; +const unsigned short help_text_len = 3584; +const unsigned short help_text_words = 660; const char quick_help_text[] = "Draw a single closed loop, given clues about number of adjacent edges."; diff --git a/apps/plugins/puzzles/help/magnets.c b/apps/plugins/puzzles/help/magnets.c index 8c53b2f127..b89b23b097 100644 --- a/apps/plugins/puzzles/help/magnets.c +++ b/apps/plugins/puzzles/help/magnets.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,187 +6,188 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 143, TEXT_CENTER | C_RED }, - { 323, TEXT_CENTER | C_RED }, - { 340, TEXT_UNDERLINE }, + { 144, TEXT_CENTER | C_RED }, + { 324, TEXT_CENTER | C_RED }, { 341, TEXT_UNDERLINE }, - { 353, TEXT_UNDERLINE }, - { 355, TEXT_UNDERLINE }, - { 388, TEXT_UNDERLINE }, - { 416, TEXT_UNDERLINE }, + { 342, TEXT_UNDERLINE }, + { 354, TEXT_UNDERLINE }, + { 356, TEXT_UNDERLINE }, + { 389, TEXT_UNDERLINE }, + { 417, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2502 comp 1653 ratio 0.660671 level 10 saved 849 */ +/* orig 2522 comp 1662 ratio 0.659001 level 10 saved 860 */ const char help_text[] = { -0xf2, 0x3e, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x33, 0x3a, 0x20, 0x4d, 0x61, 0x67, 0x6e, 0x65, 0x74, -0x73, 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x72, 0x65, 0x63, -0x74, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x67, -0x72, 0x69, 0x64, 0x00, 0x68, 0x61, 0x73, 0x00, 0x62, 0x65, -0x65, 0x6e, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, -0x77, 0x69, 0x74, 0x68, 0x00, 0x61, 0x00, 0x6d, 0x69, 0x78, -0x74, 0x75, 0x72, 0x65, 0x00, 0x6f, 0x66, 0x00, 0x6d, 0x40, -0x00, 0xf2, 0x04, 0x00, 0x28, 0x74, 0x68, 0x61, 0x74, 0x00, -0x69, 0x73, 0x2c, 0x00, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x6f, -0x65, 0x73, 0x2d, 0x00, 0xf1, 0x05, 0x6f, 0x6e, 0x65, 0x00, -0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x65, -0x6e, 0x64, 0x00, 0x61, 0x6e, 0x64, 0x15, 0x00, 0x44, 0x6e, -0x65, 0x67, 0x61, 0x15, 0x00, 0x11, 0x29, 0x16, 0x00, 0x56, -0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x3f, 0x00, 0x0f, 0x52, 0x00, -0x05, 0xf6, 0x0a, 0x74, 0x77, 0x6f, 0x00, 0x6e, 0x65, 0x75, -0x74, 0x72, 0x61, 0x6c, 0x00, 0x70, 0x6f, 0x6c, 0x65, 0x73, -0x29, 0x2e, 0x00, 0x54, 0x68, 0x65, 0x73, 0x65, 0x28, 0x00, -0xf0, 0x05, 0x61, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74, -0x69, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x6e, 0x6c, 0x79, -0x00, 0x73, 0xc6, 0x00, 0xf2, 0x0a, 0x69, 0x6e, 0x00, 0x73, -0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x2e, -0x00, 0x41, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x74, 0x68, -0x65, 0xee, 0x00, 0x00, 0x37, 0x00, 0xf0, 0x00, 0x70, 0x6c, -0x61, 0x63, 0x65, 0x64, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, -0x62, 0x65, 0x72, 0xe3, 0x00, 0xf1, 0x01, 0x63, 0x6c, 0x75, -0x65, 0x73, 0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, -0x69, 0x6e, 0x67, 0x31, 0x00, 0x06, 0x1f, 0x00, 0x05, 0xde, -0x00, 0x00, 0xc4, 0x00, 0x05, 0xd6, 0x00, 0x01, 0x9a, 0x00, -0xa0, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, -0x64, 0x7b, 0x00, 0x50, 0x63, 0x65, 0x72, 0x74, 0x61, 0x08, -0x00, 0x61, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x30, 0x00, -0xf0, 0x0b, 0x72, 0x6f, 0x77, 0x73, 0x2e, 0x00, 0x00, 0x00, -0x59, 0x6f, 0x75, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, -0x73, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x72, 0x8c, 0x01, -0x22, 0x6c, 0x79, 0x90, 0x00, 0x01, 0x72, 0x00, 0x04, 0x6a, -0x01, 0x0f, 0x2b, 0x01, 0x00, 0x51, 0x73, 0x75, 0x63, 0x68, -0x00, 0x2f, 0x01, 0x31, 0x61, 0x6c, 0x6c, 0x2d, 0x00, 0x02, -0xb4, 0x00, 0x00, 0xd1, 0x00, 0xa3, 0x73, 0x61, 0x74, 0x69, -0x73, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x3f, 0x01, 0xd0, 0x68, -0x65, 0x00, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, -0x61, 0x6c, 0xa2, 0x00, 0x72, 0x73, 0x74, 0x72, 0x61, 0x69, -0x6e, 0x74, 0x41, 0x00, 0x21, 0x6e, 0x6f, 0x61, 0x01, 0x40, -0x73, 0x69, 0x6d, 0x69, 0x06, 0x02, 0x02, 0x75, 0x00, 0x23, -0x69, 0x63, 0xd0, 0x00, 0xf1, 0x00, 0x6d, 0x61, 0x79, 0x00, -0x62, 0x65, 0x00, 0x6f, 0x72, 0x74, 0x68, 0x6f, 0x67, 0x6f, -0x6e, 0x5f, 0x01, 0xd2, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, -0x6e, 0x74, 0x00, 0x28, 0x73, 0x69, 0x6e, 0xac, 0x00, 0xb8, -0x79, 0x00, 0x72, 0x65, 0x70, 0x65, 0x6c, 0x29, 0x2e, 0x00, -0x4e, 0xa9, 0x01, 0x72, 0x00, 0x64, 0x6f, 0x00, 0x6e, 0x6f, -0x74, 0x1d, 0x00, 0x11, 0x2c, 0xc9, 0x00, 0x30, 0x63, 0x61, -0x6e, 0x51, 0x00, 0x05, 0x44, 0x00, 0xc1, 0x74, 0x6f, 0x00, -0x61, 0x6e, 0x79, 0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x35, -0x00, 0x00, 0x1d, 0x01, 0xf1, 0x0b, 0x43, 0x72, 0x65, 0x64, -0x69, 0x74, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x74, 0x68, 0x69, -0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, -0x6f, 0x65, 0x2d, 0x01, 0xa0, 0x4a, 0x61, 0x6e, 0x6b, 0x6f, -0x00, 0x5b, 0x31, 0x36, 0x5d, 0x2d, 0x00, 0x13, 0x4d, 0x27, -0x01, 0x22, 0x77, 0x61, 0x7f, 0x01, 0x70, 0x72, 0x69, 0x62, -0x75, 0x74, 0x65, 0x64, 0x29, 0x00, 0x01, 0x3d, 0x00, 0x60, -0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0xfe, 0x00, 0xf0, 0x01, -0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, -0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x3e, 0x00, 0x00, 0x46, -0x00, 0xd0, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, -0x77, 0x77, 0x77, 0x2e, 0x6a, 0x5c, 0x00, 0xc2, 0x2e, 0x61, -0x74, 0x2f, 0x52, 0x61, 0x65, 0x74, 0x73, 0x65, 0x6c, 0x2f, -0x5f, 0x00, 0xf5, 0x03, 0x65, 0x2f, 0x69, 0x6e, 0x64, 0x65, -0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0x00, 0x00, 0x33, 0x33, -0x2e, 0x31, 0x49, 0x03, 0x01, 0x74, 0x00, 0x21, 0x6f, 0x6c, -0x52, 0x03, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0x37, 0x02, 0xf5, 0x00, 0x6f, 0x6e, 0x00, -0x61, 0x6e, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00, 0x73, -0x71, 0x75, 0x6e, 0x02, 0x33, 0x73, 0x00, 0x61, 0x68, 0x01, -0x23, 0x00, 0x61, 0x86, 0x01, 0x02, 0x54, 0x02, 0x26, 0x6f, -0x6e, 0xb3, 0x01, 0x05, 0x66, 0x02, 0x00, 0x15, 0x01, 0x00, -0x4b, 0x00, 0x00, 0x15, 0x00, 0x03, 0x46, 0x00, 0x13, 0x61, -0xc5, 0x02, 0x09, 0x7d, 0x02, 0x04, 0x24, 0x00, 0x02, 0x4b, -0x01, 0x40, 0x68, 0x61, 0x6c, 0x66, 0xad, 0x02, 0x06, 0x49, -0x02, 0x39, 0x3b, 0x00, 0x6c, 0x9e, 0x00, 0x20, 0x61, 0x67, -0x9c, 0x02, 0x83, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, -0x73, 0x74, 0x00, 0x62, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, -0xab, 0x01, 0x10, 0x61, 0x40, 0x01, 0x31, 0x72, 0x64, 0x00, -0x32, 0x00, 0x87, 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, -0x73, 0x51, 0x00, 0x00, 0x3f, 0x01, 0x4f, 0x52, 0x69, 0x67, -0x68, 0xf2, 0x00, 0x14, 0x08, 0xc3, 0x02, 0x10, 0x00, 0xa4, -0x00, 0x2c, 0x65, 0x2e, 0x3f, 0x00, 0x02, 0x93, 0x00, 0x03, -0x32, 0x00, 0x00, 0x96, 0x02, 0x41, 0x71, 0x75, 0x65, 0x73, -0x17, 0x01, 0x54, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0xe2, 0x00, -0x02, 0x44, 0x00, 0x90, 0x2c, 0x00, 0x73, 0x69, 0x67, 0x6e, -0x69, 0x66, 0x79, 0x3a, 0x00, 0x12, 0x60, 0xeb, 0x01, 0x20, -0x61, 0x6e, 0x6f, 0x02, 0x22, 0x62, 0x65, 0x6d, 0x00, 0x84, -0x27, 0x00, 0x28, 0x77, 0x68, 0x69, 0x63, 0x68, 0x75, 0x02, -0x81, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x74, 0x95, -0x02, 0x61, 0x65, 0x00, 0x64, 0x65, 0x64, 0x75, 0x18, 0x02, -0xf2, 0x02, 0x73, 0x00, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x00, -0x73, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x29, 0x2c, 0xaa, -0x03, 0x0e, 0x9c, 0x00, 0x02, 0xdb, 0x00, 0x37, 0x69, 0x65, -0x73, 0x87, 0x00, 0x1d, 0x2e, 0xf7, 0x01, 0x11, 0x61, 0x8d, -0x03, 0x51, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0xb8, 0x00, 0x50, -0x00, 0x69, 0x74, 0x00, 0x61, 0x0c, 0x03, 0x80, 0x6e, 0x65, -0x00, 0x28, 0x67, 0x72, 0x65, 0x79, 0x11, 0x00, 0xb4, 0x6f, -0x75, 0x74, 0x29, 0x2c, 0x00, 0x6f, 0x72, 0x00, 0x75, 0x6e, -0x24, 0x00, 0x21, 0x69, 0x66, 0x06, 0x00, 0x91, 0x73, 0x00, -0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x3d, 0x00, 0x23, -0x65, 0x64, 0x2e, 0x04, 0x01, 0xc5, 0x00, 0x40, 0x61, 0x6c, -0x73, 0x6f, 0xc7, 0x00, 0x02, 0xf3, 0x03, 0x91, 0x75, 0x72, -0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x16, 0x03, 0x20, -0x6d, 0x6f, 0x93, 0x04, 0x04, 0x16, 0x00, 0x1a, 0x61, 0xeb, -0x04, 0x74, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0xcd, -0x04, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x00, -0x02, 0xa7, 0x00, 0x54, 0x6c, 0x61, 0x79, 0x00, 0x61, 0x9c, -0x01, 0x03, 0xf4, 0x05, 0x0a, 0x81, 0x02, 0x0c, 0xa9, 0x02, -0x34, 0x3b, 0x00, 0x70, 0x51, 0x00, 0x0f, 0x49, 0x02, 0x08, -0x04, 0xaa, 0x02, 0x19, 0x6e, 0x3f, 0x02, 0x04, 0xc0, 0x01, -0x13, 0x61, 0xe1, 0x05, 0x09, 0x98, 0x02, 0x35, 0x2e, 0x00, -0x55, 0xa7, 0x00, 0x20, 0x73, 0x70, 0x0c, 0x05, 0x30, 0x62, -0x61, 0x72, 0xe7, 0x04, 0x32, 0x6f, 0x77, 0x73, 0x1b, 0x02, -0x10, 0x6d, 0x38, 0x04, 0x2c, 0x6f, 0x66, 0x14, 0x05, 0x03, -0x5e, 0x04, 0x72, 0x6e, 0x6f, 0x74, 0x2d, 0x62, 0x65, 0x2d, -0x1d, 0x00, 0x51, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x69, 0x00, -0x00, 0x4c, 0x04, 0x02, 0xd2, 0x01, 0x16, 0x00, 0x6a, 0x00, -0x43, 0x00, 0x00, 0x28, 0x41, 0x40, 0x05, 0x13, 0x61, 0x0a, -0x02, 0x72, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0xc1, -0x05, 0x13, 0x73, 0x38, 0x04, 0x31, 0x32, 0x2e, 0x31, 0x5b, -0x05, 0x01, 0x7f, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, -0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x0b, 0x04, 0x15, 0x32, -0x0b, 0x04, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, -0x65, 0x72, 0x0d, 0x04, 0x02, 0xa4, 0x06, 0x06, 0x14, 0x00, -0x02, 0x43, 0x00, 0x04, 0x3e, 0x00, 0x51, 0x00, 0x66, 0x72, -0x6f, 0x6d, 0x7b, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, -0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, -0x00, 0x03, 0xe9, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, -0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xad, 0x00, 0x90, 0x57, -0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xc8, 0x00, -0x61, 0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x93, 0x07, 0x01, -0xcc, 0x06, 0x23, 0x69, 0x6e, 0x72, 0x03, 0x11, 0x73, 0x1e, -0x07, 0x13, 0x72, 0x81, 0x02, 0x22, 0x62, 0x65, 0x0b, 0x04, -0x01, 0x3c, 0x00, 0x24, 0x00, 0x78, 0x3d, 0x00, 0x05, 0x36, -0x01, 0x25, 0x69, 0x6e, 0x24, 0x02, 0x10, 0x3a, 0x82, 0x02, -0x01, 0x48, 0x03, 0x03, 0xec, 0x06, 0x53, 0x69, 0x73, 0x00, -0x6f, 0x64, 0xc0, 0x01, 0x25, 0x6f, 0x6e, 0x7e, 0x04, 0x04, -0x58, 0x00, 0x01, 0x63, 0x01, 0x01, 0x45, 0x01, 0x53, 0x47, -0x72, 0x69, 0x64, 0x73, 0x38, 0x02, 0x71, 0x74, 0x00, 0x6c, -0x65, 0x61, 0x73, 0x74, 0x31, 0x00, 0x00, 0x3e, 0x00, 0x70, -0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0xd2, 0x00, 0x21, -0x65, 0x6e, 0x96, 0x05, 0x90, 0x62, 0x65, 0x00, 0x65, 0x61, -0x73, 0x69, 0x65, 0x72, 0x0d, 0x00, 0x00, 0x74, 0x03, 0x02, -0x4a, 0x01, 0xa0, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, -0x6c, 0x74, 0x79, 0x02, 0x06, 0x03, 0x55, 0x05, 0x02, 0x30, -0x02, 0x06, 0x1a, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x67, 0x65, -0x6e, 0x65, 0x72, 0x61, 0xe6, 0x05, 0x02, 0x1b, 0x06, 0xf0, -0x00, 0x2e, 0x00, 0x41, 0x74, 0x00, 0x54, 0x72, 0x69, 0x63, -0x6b, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x6d, 0x06, 0x31, 0x79, -0x6f, 0x75, 0x71, 0x01, 0x62, 0x72, 0x65, 0x71, 0x75, 0x69, -0x72, 0x10, 0x06, 0x89, 0x6d, 0x61, 0x6b, 0x65, 0x00, 0x6d, -0x6f, 0x72, 0xfc, 0x03, 0x53, 0x61, 0x62, 0x6f, 0x75, 0x74, -0xb4, 0x04, 0x09, 0x4d, 0x02, 0x42, 0x72, 0x6f, 0x77, 0x2f, -0xbb, 0x07, 0x61, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xb8, -0x07, 0x62, 0x53, 0x74, 0x72, 0x69, 0x70, 0x20, 0x6e, 0x07, -0xe1, 0x00, 0x00, 0x49, 0x66, 0x00, 0x74, 0x72, 0x75, 0x65, -0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x8b, 0x01, 0x08, 0x8b, 0x07, -0x0e, 0x6c, 0x08, 0x02, 0x05, 0x03, 0x10, 0x64, 0x25, 0x01, -0x03, 0xc2, 0x00, 0x01, 0x18, 0x01, 0x40, 0x69, 0x6d, 0x65, -0x2c, 0x9c, 0x00, 0x04, 0xf7, 0x02, 0x03, 0xef, 0x06, 0x02, -0xa9, 0x00, 0xa0, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, -0x74, 0x2e, 0x00, +0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf2, 0x2a, 0x00, 0x00, +0x00, 0x41, 0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, +0x75, 0x6c, 0x61, 0x72, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, +0x68, 0x61, 0x73, 0x00, 0x62, 0x65, 0x65, 0x6e, 0x00, 0x66, +0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, +0x00, 0x61, 0x00, 0x6d, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, +0x00, 0x6f, 0x66, 0x00, 0x6d, 0x54, 0x00, 0xf2, 0x04, 0x00, +0x28, 0x74, 0x68, 0x61, 0x74, 0x00, 0x69, 0x73, 0x2c, 0x00, +0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x6f, 0x65, 0x73, 0x2d, 0x00, +0xf1, 0x05, 0x6f, 0x6e, 0x65, 0x00, 0x70, 0x6f, 0x73, 0x69, +0x74, 0x69, 0x76, 0x65, 0x00, 0x65, 0x6e, 0x64, 0x00, 0x61, +0x6e, 0x64, 0x15, 0x00, 0x44, 0x6e, 0x65, 0x67, 0x61, 0x15, +0x00, 0x11, 0x29, 0x16, 0x00, 0x56, 0x62, 0x6c, 0x61, 0x6e, +0x6b, 0x3f, 0x00, 0x0f, 0x52, 0x00, 0x05, 0xf6, 0x0a, 0x74, +0x77, 0x6f, 0x00, 0x6e, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6c, +0x00, 0x70, 0x6f, 0x6c, 0x65, 0x73, 0x29, 0x2e, 0x00, 0x54, +0x68, 0x65, 0x73, 0x65, 0x28, 0x00, 0xf0, 0x05, 0x61, 0x72, +0x65, 0x00, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x6c, +0x79, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x73, 0xc6, 0x00, +0xf2, 0x0a, 0x69, 0x6e, 0x00, 0x73, 0x69, 0x6c, 0x68, 0x6f, +0x75, 0x65, 0x74, 0x74, 0x65, 0x2e, 0x00, 0x41, 0x72, 0x6f, +0x75, 0x6e, 0x64, 0x00, 0x74, 0x68, 0x65, 0xee, 0x00, 0x00, +0x37, 0x00, 0xf0, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64, +0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xe3, +0x00, 0xf1, 0x01, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x00, 0x69, +0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x31, +0x00, 0x06, 0x1f, 0x00, 0x05, 0xde, 0x00, 0x00, 0xc4, 0x00, +0x05, 0xd6, 0x00, 0x01, 0x9a, 0x00, 0xa0, 0x00, 0x63, 0x6f, +0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x7b, 0x00, 0x50, +0x63, 0x65, 0x72, 0x74, 0x61, 0x08, 0x00, 0x61, 0x6f, 0x6c, +0x75, 0x6d, 0x6e, 0x73, 0x30, 0x00, 0xf0, 0x0b, 0x72, 0x6f, +0x77, 0x73, 0x2e, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x72, +0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, +0x00, 0x63, 0x6f, 0x72, 0x8c, 0x01, 0x22, 0x6c, 0x79, 0x90, +0x00, 0x01, 0x72, 0x00, 0x04, 0x6a, 0x01, 0x0f, 0x2b, 0x01, +0x00, 0x51, 0x73, 0x75, 0x63, 0x68, 0x00, 0x2f, 0x01, 0x31, +0x61, 0x6c, 0x6c, 0x2d, 0x00, 0x02, 0xb4, 0x00, 0x00, 0xd1, +0x00, 0xa3, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, 0x65, +0x64, 0x2c, 0x3f, 0x01, 0xd0, 0x68, 0x65, 0x00, 0x61, 0x64, +0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0xa2, 0x00, +0x72, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x41, 0x00, +0x21, 0x6e, 0x6f, 0x61, 0x01, 0x40, 0x73, 0x69, 0x6d, 0x69, +0x06, 0x02, 0x02, 0x75, 0x00, 0x23, 0x69, 0x63, 0xd0, 0x00, +0xf1, 0x00, 0x6d, 0x61, 0x79, 0x00, 0x62, 0x65, 0x00, 0x6f, +0x72, 0x74, 0x68, 0x6f, 0x67, 0x6f, 0x6e, 0x5f, 0x01, 0xd2, +0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x00, 0x28, +0x73, 0x69, 0x6e, 0xac, 0x00, 0xb8, 0x79, 0x00, 0x72, 0x65, +0x70, 0x65, 0x6c, 0x29, 0x2e, 0x00, 0x4e, 0xa9, 0x01, 0x72, +0x00, 0x64, 0x6f, 0x00, 0x6e, 0x6f, 0x74, 0x1d, 0x00, 0x11, +0x2c, 0xc9, 0x00, 0x30, 0x63, 0x61, 0x6e, 0x51, 0x00, 0x05, +0x44, 0x00, 0xc1, 0x74, 0x6f, 0x00, 0x61, 0x6e, 0x79, 0x00, +0x6f, 0x74, 0x68, 0x65, 0x72, 0x35, 0x00, 0x00, 0x1d, 0x01, +0xf1, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x66, +0x6f, 0x72, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0x2d, 0x01, +0xa0, 0x4a, 0x61, 0x6e, 0x6b, 0x6f, 0x00, 0x5b, 0x31, 0x36, +0x5d, 0x2d, 0x00, 0x13, 0x4d, 0x27, 0x01, 0x22, 0x77, 0x61, +0x7f, 0x01, 0x70, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, +0x29, 0x00, 0x01, 0x3d, 0x00, 0x60, 0x63, 0x6f, 0x6c, 0x6c, +0x65, 0x63, 0xfe, 0x00, 0xf0, 0x01, 0x00, 0x62, 0x79, 0x00, +0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, +0x65, 0x79, 0x3e, 0x00, 0x00, 0x46, 0x00, 0xd0, 0x00, 0x68, +0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, +0x6a, 0x5c, 0x00, 0xc2, 0x2e, 0x61, 0x74, 0x2f, 0x52, 0x61, +0x65, 0x74, 0x73, 0x65, 0x6c, 0x2f, 0x5f, 0x00, 0xf5, 0x03, +0x65, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, +0x6d, 0x00, 0x00, 0x00, 0x33, 0x33, 0x2e, 0x31, 0x5d, 0x03, +0x01, 0x74, 0x00, 0xf0, 0x02, 0x6f, 0x6c, 0x73, 0x20, 0x00, +0x00, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, +0x63, 0x6b, 0x37, 0x02, 0xf5, 0x00, 0x6f, 0x6e, 0x00, 0x61, +0x6e, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00, 0x73, 0x71, +0x75, 0x6e, 0x02, 0x33, 0x73, 0x00, 0x61, 0x68, 0x01, 0x23, +0x00, 0x61, 0x86, 0x01, 0x02, 0x54, 0x02, 0x26, 0x6f, 0x6e, +0xb3, 0x01, 0x05, 0x66, 0x02, 0x00, 0x15, 0x01, 0x00, 0x4b, +0x00, 0x00, 0x15, 0x00, 0x03, 0x46, 0x00, 0x13, 0x61, 0xc5, +0x02, 0x09, 0x7d, 0x02, 0x04, 0x24, 0x00, 0x02, 0x4b, 0x01, +0x40, 0x68, 0x61, 0x6c, 0x66, 0xad, 0x02, 0x06, 0x49, 0x02, +0x39, 0x3b, 0x00, 0x6c, 0x9e, 0x00, 0x20, 0x61, 0x67, 0x9c, +0x02, 0x83, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x73, +0x74, 0x00, 0x62, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, 0xab, +0x01, 0x10, 0x61, 0x40, 0x01, 0x31, 0x72, 0x64, 0x00, 0x32, +0x00, 0x87, 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, +0x51, 0x00, 0x00, 0x3f, 0x01, 0x4f, 0x52, 0x69, 0x67, 0x68, +0xf2, 0x00, 0x14, 0x08, 0xc3, 0x02, 0x10, 0x00, 0xa4, 0x00, +0x2c, 0x65, 0x2e, 0x3f, 0x00, 0x02, 0x93, 0x00, 0x03, 0x32, +0x00, 0x00, 0x96, 0x02, 0x41, 0x71, 0x75, 0x65, 0x73, 0x17, +0x01, 0x54, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0xe2, 0x00, 0x02, +0x44, 0x00, 0x90, 0x2c, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x69, +0x66, 0x79, 0x3a, 0x00, 0x12, 0x60, 0xeb, 0x01, 0x20, 0x61, +0x6e, 0x6f, 0x02, 0x22, 0x62, 0x65, 0x6d, 0x00, 0x84, 0x27, +0x00, 0x28, 0x77, 0x68, 0x69, 0x63, 0x68, 0x75, 0x02, 0x81, +0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x74, 0x95, 0x02, +0x61, 0x65, 0x00, 0x64, 0x65, 0x64, 0x75, 0x18, 0x02, 0xf2, +0x02, 0x73, 0x00, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x00, 0x73, +0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x29, 0x2c, 0xaa, 0x03, +0x0e, 0x9c, 0x00, 0x02, 0xdb, 0x00, 0x37, 0x69, 0x65, 0x73, +0x87, 0x00, 0x1d, 0x2e, 0xf7, 0x01, 0x11, 0x61, 0x8d, 0x03, +0x51, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0xb8, 0x00, 0x50, 0x00, +0x69, 0x74, 0x00, 0x61, 0x0c, 0x03, 0x80, 0x6e, 0x65, 0x00, +0x28, 0x67, 0x72, 0x65, 0x79, 0x11, 0x00, 0xb4, 0x6f, 0x75, +0x74, 0x29, 0x2c, 0x00, 0x6f, 0x72, 0x00, 0x75, 0x6e, 0x24, +0x00, 0x21, 0x69, 0x66, 0x06, 0x00, 0x91, 0x73, 0x00, 0x61, +0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x3d, 0x00, 0x23, 0x65, +0x64, 0x2e, 0x04, 0x01, 0xc5, 0x00, 0x40, 0x61, 0x6c, 0x73, +0x6f, 0xc7, 0x00, 0x02, 0xf3, 0x03, 0x91, 0x75, 0x72, 0x73, +0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x16, 0x03, 0x20, 0x6d, +0x6f, 0x93, 0x04, 0x04, 0x16, 0x00, 0x1a, 0x61, 0xeb, 0x04, +0x74, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0xcd, 0x04, +0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x00, 0x02, +0xa7, 0x00, 0x54, 0x6c, 0x61, 0x79, 0x00, 0x61, 0x9c, 0x01, +0x03, 0xf4, 0x05, 0x0a, 0x81, 0x02, 0x0c, 0xa9, 0x02, 0x34, +0x3b, 0x00, 0x70, 0x51, 0x00, 0x0f, 0x49, 0x02, 0x08, 0x04, +0xaa, 0x02, 0x19, 0x6e, 0x3f, 0x02, 0x04, 0xc0, 0x01, 0x13, +0x61, 0xe1, 0x05, 0x09, 0x98, 0x02, 0x35, 0x2e, 0x00, 0x55, +0xa7, 0x00, 0x20, 0x73, 0x70, 0x0c, 0x05, 0x30, 0x62, 0x61, +0x72, 0xe7, 0x04, 0x32, 0x6f, 0x77, 0x73, 0x1b, 0x02, 0x10, +0x6d, 0x38, 0x04, 0x2c, 0x6f, 0x66, 0x14, 0x05, 0x03, 0x5e, +0x04, 0x72, 0x6e, 0x6f, 0x74, 0x2d, 0x62, 0x65, 0x2d, 0x1d, +0x00, 0x51, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x69, 0x00, 0x00, +0x4c, 0x04, 0x02, 0xd2, 0x01, 0x16, 0x00, 0x6a, 0x00, 0x43, +0x00, 0x00, 0x28, 0x41, 0x40, 0x05, 0x13, 0x61, 0x0a, 0x02, +0x72, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0xc1, 0x05, +0x13, 0x73, 0x38, 0x04, 0x31, 0x32, 0x2e, 0x31, 0x5b, 0x05, +0x01, 0x7f, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, +0x62, 0x6c, 0x65, 0x2e, 0x29, 0x0b, 0x04, 0x15, 0x32, 0x0b, +0x04, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, +0x72, 0x0d, 0x04, 0x02, 0xa4, 0x06, 0x06, 0x14, 0x00, 0x02, +0x43, 0x00, 0x04, 0x3e, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, +0x6d, 0x7b, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, +0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, 0x00, +0x03, 0xe9, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0xad, 0x00, 0x90, 0x57, 0x69, +0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xc8, 0x00, 0x61, +0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x93, 0x07, 0x01, 0xcc, +0x06, 0x23, 0x69, 0x6e, 0x72, 0x03, 0x11, 0x73, 0x1e, 0x07, +0x13, 0x72, 0x81, 0x02, 0x22, 0x62, 0x65, 0x0b, 0x04, 0x01, +0x3c, 0x00, 0x24, 0x00, 0x78, 0x3d, 0x00, 0x05, 0x36, 0x01, +0x25, 0x69, 0x6e, 0x24, 0x02, 0x10, 0x3a, 0x82, 0x02, 0x01, +0x48, 0x03, 0x03, 0xec, 0x06, 0x53, 0x69, 0x73, 0x00, 0x6f, +0x64, 0xc0, 0x01, 0x25, 0x6f, 0x6e, 0x7e, 0x04, 0x04, 0x58, +0x00, 0x01, 0x63, 0x01, 0x01, 0x45, 0x01, 0x53, 0x47, 0x72, +0x69, 0x64, 0x73, 0x38, 0x02, 0x71, 0x74, 0x00, 0x6c, 0x65, +0x61, 0x73, 0x74, 0x31, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x64, +0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0xd2, 0x00, 0x21, 0x65, +0x6e, 0x96, 0x05, 0x90, 0x62, 0x65, 0x00, 0x65, 0x61, 0x73, +0x69, 0x65, 0x72, 0x0d, 0x00, 0x00, 0x74, 0x03, 0x02, 0x4a, +0x01, 0xa0, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, +0x74, 0x79, 0x02, 0x06, 0x03, 0x55, 0x05, 0x02, 0x30, 0x02, +0x06, 0x1a, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x67, 0x65, 0x6e, +0x65, 0x72, 0x61, 0xe6, 0x05, 0x02, 0x1b, 0x06, 0xf0, 0x00, +0x2e, 0x00, 0x41, 0x74, 0x00, 0x54, 0x72, 0x69, 0x63, 0x6b, +0x79, 0x00, 0x6c, 0x65, 0x76, 0x6d, 0x06, 0x31, 0x79, 0x6f, +0x75, 0x71, 0x01, 0x62, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, +0x10, 0x06, 0x89, 0x6d, 0x61, 0x6b, 0x65, 0x00, 0x6d, 0x6f, +0x72, 0xfc, 0x03, 0x53, 0x61, 0x62, 0x6f, 0x75, 0x74, 0xb4, +0x04, 0x09, 0x4d, 0x02, 0x42, 0x72, 0x6f, 0x77, 0x2f, 0xbb, +0x07, 0x61, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xb8, 0x07, +0x62, 0x53, 0x74, 0x72, 0x69, 0x70, 0x20, 0x6e, 0x07, 0xe1, +0x00, 0x00, 0x49, 0x66, 0x00, 0x74, 0x72, 0x75, 0x65, 0x2c, +0x00, 0x73, 0x6f, 0x6d, 0x8b, 0x01, 0x08, 0x8b, 0x07, 0x0e, +0x6c, 0x08, 0x02, 0x05, 0x03, 0x10, 0x64, 0x25, 0x01, 0x03, +0xc2, 0x00, 0x01, 0x18, 0x01, 0x40, 0x69, 0x6d, 0x65, 0x2c, +0x9c, 0x00, 0x04, 0xf7, 0x02, 0x03, 0xef, 0x06, 0x02, 0xa9, +0x00, 0xa0, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, +0x2e, 0x00, }; -const unsigned short help_text_len = 2502; -const unsigned short help_text_words = 438; +const unsigned short help_text_len = 2522; +const unsigned short help_text_words = 439; const char quick_help_text[] = "Place magnets to satisfy the clues and avoid like poles touching."; diff --git a/apps/plugins/puzzles/help/map.c b/apps/plugins/puzzles/help/map.c index 2f577ae6b2..18b3fb5ace 100644 --- a/apps/plugins/puzzles/help/map.c +++ b/apps/plugins/puzzles/help/map.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,251 +6,269 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 81, TEXT_UNDERLINE }, - { 157, TEXT_CENTER | C_RED }, - { 244, TEXT_UNDERLINE }, - { 268, TEXT_UNDERLINE }, - { 507, TEXT_CENTER | C_RED }, - { 524, TEXT_UNDERLINE }, - { 525, TEXT_UNDERLINE }, - { 535, TEXT_UNDERLINE }, - { 547, TEXT_UNDERLINE }, + { 87, TEXT_UNDERLINE }, + { 163, TEXT_CENTER | C_RED }, + { 250, TEXT_UNDERLINE }, + { 274, TEXT_UNDERLINE }, + { 513, TEXT_CENTER | C_RED }, + { 530, TEXT_UNDERLINE }, + { 531, TEXT_UNDERLINE }, + { 541, TEXT_UNDERLINE }, + { 553, TEXT_UNDERLINE }, + { 650, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3466 comp 2283 ratio 0.658684 level 10 saved 1183 */ +/* orig 3752 comp 2460 ratio 0.65565 level 10 saved 1292 */ const char help_text[] = { -0xf0, 0x2e, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, -0x32, 0x32, 0x3a, 0x20, 0x4d, 0x61, 0x70, 0x20, 0x00, 0x00, -0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, -0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x61, 0x70, -0x00, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x69, 0x6e, -0x67, 0x00, 0x6f, 0x66, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, -0x62, 0x65, 0x72, 0x0c, 0x00, 0x80, 0x72, 0x65, 0x67, 0x69, -0x6f, 0x6e, 0x73, 0x2e, 0x37, 0x00, 0xf0, 0x01, 0x72, 0x00, -0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, -0x00, 0x63, 0x6f, 0x6c, 0x12, 0x00, 0x43, 0x65, 0x61, 0x63, -0x68, 0x25, 0x00, 0x90, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, -0x6f, 0x6e, 0x65, 0x38, 0x00, 0x10, 0x66, 0x1d, 0x00, 0x02, -0x24, 0x00, 0xf4, 0x0d, 0x73, 0x2c, 0x00, 0x69, 0x6e, 0x00, -0x73, 0x75, 0x63, 0x68, 0x00, 0x61, 0x00, 0x77, 0x61, 0x79, -0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x6e, 0x6f, 0x00, 0x74, -0x77, 0x6f, 0x60, 0x00, 0x50, 0x00, 0x73, 0x68, 0x61, 0x72, -0x7f, 0x00, 0xf3, 0x09, 0x61, 0x00, 0x62, 0x6f, 0x75, 0x6e, -0x64, 0x61, 0x72, 0x79, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, -0x74, 0x68, 0x65, 0x00, 0x73, 0x61, 0x6d, 0x65, 0x4c, 0x00, -0x15, 0x2e, 0xbf, 0x00, 0x82, 0x70, 0x72, 0x6f, 0x76, 0x69, -0x64, 0x65, 0x64, 0x76, 0x00, 0x45, 0x73, 0x6f, 0x6d, 0x65, -0x4c, 0x00, 0x73, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, -0x33, 0x00, 0xe0, 0x65, 0x64, 0x2c, 0x00, 0x73, 0x75, 0x66, -0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0xbb, 0x00, 0x32, -0x6d, 0x61, 0x6b, 0x59, 0x00, 0x72, 0x72, 0x65, 0x6d, 0x61, -0x69, 0x6e, 0x64, 0xea, 0x00, 0x01, 0x6a, 0x00, 0x40, 0x6f, -0x6c, 0x75, 0x74, 0xcb, 0x00, 0xe5, 0x75, 0x6e, 0x69, 0x71, -0x75, 0x65, 0x2e, 0x00, 0x00, 0x00, 0x4f, 0x6e, 0x6c, 0x79, -0x5a, 0x00, 0x51, 0x77, 0x68, 0x69, 0x63, 0x68, 0xac, 0x00, -0xa0, 0x65, 0x00, 0x61, 0x00, 0x6c, 0x65, 0x6e, 0x67, 0x74, -0x68, 0x3c, 0x00, 0x30, 0x62, 0x6f, 0x72, 0x46, 0x00, 0x20, -0x61, 0x72, 0x54, 0x00, 0x60, 0x71, 0x75, 0x69, 0x72, 0x65, -0x64, 0x69, 0x00, 0x90, 0x62, 0x65, 0x00, 0x64, 0x69, 0x66, -0x66, 0x65, 0x72, 0x79, 0x00, 0x03, 0x0d, 0x01, 0x5b, 0x2e, -0x00, 0x54, 0x77, 0x6f, 0x51, 0x00, 0x90, 0x6d, 0x65, 0x65, -0x74, 0x00, 0x61, 0x74, 0x00, 0x6f, 0x6c, 0x00, 0x00, 0x41, -0x01, 0xb1, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x28, 0x69, -0x2e, 0x65, 0x2e, 0x55, 0x00, 0xff, 0x0c, 0x64, 0x69, 0x61, -0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x65, -0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x29, 0x00, 0x6d, -0x61, 0x79, 0x00, 0x62, 0x23, 0x01, 0x00, 0x91, 0x00, 0x00, -0x49, 0x00, 0x62, 0x65, 0x6c, 0x69, 0x65, 0x40, 0x01, 0x90, -0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0xb9, -0x01, 0xf0, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, -0x6c, 0x3b, 0x00, 0x49, 0x27, 0x76, 0x65, 0x00, 0x6e, 0x65, -0x76, 0x65, 0x72, 0x00, 0x73, 0x65, 0x09, 0x02, 0xc1, 0x6e, -0x00, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, -0x61, 0x04, 0x01, 0xf0, 0x09, 0x6f, 0x66, 0x00, 0x69, 0x74, -0x00, 0x61, 0x6e, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x00, -0x65, 0x6c, 0x73, 0x65, 0x2e, 0x00, 0x54, 0x68, 0x65, 0x2e, -0x02, 0x42, 0x63, 0x65, 0x70, 0x74, 0x2b, 0x02, 0x00, 0xe9, -0x01, 0x12, 0x2d, 0x7a, 0x00, 0x00, 0xc0, 0x01, 0x03, 0x6b, -0x00, 0xf0, 0x20, 0x77, 0x61, 0x73, 0x00, 0x73, 0x75, 0x67, -0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x00, 0x62, 0x79, 0x00, -0x4f, 0x77, 0x65, 0x6e, 0x00, 0x44, 0x75, 0x6e, 0x6e, 0x3b, -0x00, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x6d, 0x75, -0x73, 0x74, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x67, 0x6f, -0x2d, 0x01, 0x91, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, -0x61, 0x6e, 0x3b, 0x01, 0xf1, 0x07, 0x56, 0x65, 0x72, 0x69, -0x74, 0x79, 0x00, 0x41, 0x6c, 0x6c, 0x61, 0x6e, 0x00, 0x66, -0x6f, 0x72, 0x00, 0x69, 0x6e, 0x73, 0x70, 0x69, 0x63, 0x00, -0x00, 0xf0, 0x00, 0x52, 0x74, 0x72, 0x61, 0x69, 0x6e, 0xb6, -0x01, 0x52, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x54, 0x02, 0x12, -0x6c, 0x77, 0x01, 0x01, 0x0b, 0x02, 0x40, 0x61, 0x6c, 0x69, -0x73, 0x2e, 0x00, 0x00, 0x79, 0x00, 0x15, 0x27, 0x8d, 0x00, -0x01, 0xa7, 0x02, 0xb3, 0x61, 0x73, 0x00, 0x61, 0x00, 0x76, -0x69, 0x61, 0x62, 0x6c, 0x65, 0xb0, 0x00, 0x00, 0xd8, 0x00, -0x42, 0x61, 0x6e, 0x6b, 0x73, 0x90, 0x00, 0xf1, 0x01, 0x74, -0x6f, 0x00, 0x47, 0x61, 0x72, 0x65, 0x74, 0x68, 0x00, 0x54, -0x61, 0x79, 0x6c, 0x6f, 0x72, 0x80, 0x00, 0xa0, 0x6d, 0x61, -0x6e, 0x79, 0x00, 0x64, 0x65, 0x74, 0x61, 0x69, 0x66, 0x00, -0x06, 0x4f, 0x00, 0x10, 0x73, 0x70, 0x01, 0x41, 0x32, 0x32, -0x2e, 0x31, 0x60, 0x03, 0x80, 0x63, 0x6f, 0x6e, 0x74, 0x72, -0x6f, 0x6c, 0x73, 0x69, 0x03, 0x15, 0x54, 0x25, 0x03, 0x13, -0x61, 0xf0, 0x01, 0x71, 0x2c, 0x00, 0x63, 0x6c, 0x69, 0x63, -0x6b, 0xc2, 0x00, 0xf0, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x00, -0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x62, 0x75, 0x74, 0x74, -0x70, 0x01, 0x01, 0x85, 0x01, 0x23, 0x65, 0x78, 0x89, 0x03, -0x03, 0x55, 0x03, 0x03, 0x9a, 0x02, 0x31, 0x64, 0x65, 0x73, -0x56, 0x02, 0x04, 0x52, 0x00, 0x72, 0x6e, 0x64, 0x00, 0x64, -0x72, 0x61, 0x67, 0xf8, 0x00, 0x03, 0x15, 0x00, 0x41, 0x69, -0x6e, 0x74, 0x6f, 0x2d, 0x00, 0x33, 0x6e, 0x65, 0x77, 0x3f, -0x00, 0x00, 0x9d, 0x00, 0x31, 0x28, 0x54, 0x68, 0x2f, 0x03, -0xf3, 0x07, 0x67, 0x72, 0x61, 0x6d, 0x00, 0x77, 0x69, 0x6c, -0x6c, 0x00, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x00, 0x65, -0x6e, 0x73, 0x75, 0x72, 0x40, 0x02, 0x47, 0x74, 0x61, 0x72, -0x74, 0xc0, 0x01, 0x10, 0x68, 0x24, 0x01, 0x00, 0x51, 0x01, -0x31, 0x61, 0x73, 0x74, 0x92, 0x02, 0x06, 0x8e, 0x00, 0x01, -0xf2, 0x03, 0x02, 0x72, 0x00, 0x42, 0x2c, 0x00, 0x73, 0x6f, -0x82, 0x00, 0x01, 0x67, 0x02, 0x24, 0x69, 0x73, 0x5a, 0x00, -0xa0, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x21, -0x29, 0x8d, 0x02, 0x82, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x00, -0x6e, 0x65, 0x9e, 0x01, 0x48, 0x63, 0x6c, 0x65, 0x61, 0x13, -0x01, 0x00, 0x1c, 0x00, 0x32, 0x63, 0x61, 0x6e, 0xcf, 0x00, -0x41, 0x66, 0x72, 0x6f, 0x6d, 0x06, 0x01, 0x45, 0x6d, 0x70, -0x74, 0x79, 0x23, 0x00, 0x22, 0x6f, 0x72, 0x19, 0x00, 0x24, -0x74, 0x68, 0xb1, 0x01, 0x06, 0x26, 0x04, 0x11, 0x69, 0x20, -0x01, 0x21, 0x72, 0x65, 0x28, 0x03, 0x29, 0x6e, 0x6f, 0x3a, -0x00, 0x11, 0x73, 0x66, 0x01, 0x00, 0x04, 0x01, 0x52, 0x44, -0x72, 0x61, 0x67, 0x67, 0x60, 0x04, 0x03, 0x2d, 0x01, 0x24, -0x75, 0x73, 0x4c, 0x02, 0x4b, 0x72, 0x69, 0x67, 0x68, 0x8b, -0x01, 0x01, 0x26, 0x01, 0x64, 0x73, 0x74, 0x69, 0x70, 0x70, -0x6c, 0x2a, 0x04, 0x01, 0xff, 0x00, 0x28, 0x69, 0x6e, 0x71, -0x01, 0x13, 0x2c, 0xbf, 0x03, 0x04, 0xc2, 0x00, 0x00, 0x41, -0x00, 0x01, 0x5c, 0x02, 0x40, 0x6e, 0x6f, 0x74, 0x65, 0xeb, -0x00, 0x10, 0x79, 0xf1, 0x03, 0x32, 0x65, 0x6c, 0x66, 0x35, -0x00, 0x00, 0x27, 0x00, 0x58, 0x74, 0x68, 0x69, 0x6e, 0x6b, -0x52, 0x00, 0x11, 0x6d, 0x7d, 0x00, 0x28, 0x62, 0x65, 0x58, -0x00, 0x34, 0x2e, 0x00, 0x41, 0x1f, 0x00, 0x00, 0x57, 0x00, -0x00, 0x54, 0x02, 0x00, 0xee, 0x02, 0x03, 0x90, 0x00, 0x10, -0x73, 0x86, 0x00, 0x74, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, -0x6c, 0xf4, 0x03, 0x01, 0xad, 0x01, 0x00, 0x96, 0x03, 0x10, -0x2e, 0xee, 0x01, 0x02, 0x8b, 0x01, 0x41, 0x6f, 0x66, 0x74, -0x65, 0x94, 0x00, 0x41, 0x66, 0x75, 0x6c, 0x00, 0xa3, 0x01, -0x00, 0xd7, 0x01, 0x01, 0xa8, 0x04, 0x20, 0x64, 0x69, 0x0f, -0x05, 0xd3, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x6c, 0x65, 0x76, -0x65, 0x6c, 0x73, 0x2e, 0x29, 0x19, 0x06, 0x00, 0x70, 0x00, -0x01, 0x04, 0x03, 0x22, 0x75, 0x73, 0xf9, 0x00, 0xb1, 0x63, -0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, -0x5b, 0x03, 0x20, 0x6f, 0x76, 0x6a, 0x01, 0x00, 0x7d, 0x01, -0x01, 0x1f, 0x00, 0x42, 0x6d, 0x61, 0x70, 0x3a, 0x28, 0x00, -0x02, 0x56, 0x01, 0x28, 0x6f, 0x66, 0x36, 0x00, 0x92, 0x69, -0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0xba, 0x01, -0x34, 0x6f, 0x73, 0x69, 0x59, 0x04, 0x07, 0x33, 0x00, 0x00, -0x17, 0x01, 0x43, 0x77, 0x6f, 0x75, 0x6c, 0xd1, 0x02, 0x12, -0x28, 0x54, 0x01, 0x20, 0x69, 0x73, 0x46, 0x01, 0xa1, 0x00, -0x6f, 0x62, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x69, 0x44, -0x02, 0x31, 0x27, 0x72, 0x65, 0x26, 0x03, 0x03, 0x1e, 0x01, -0x25, 0x27, 0x73, 0x07, 0x02, 0x70, 0x2c, 0x00, 0x73, 0x69, -0x6e, 0x63, 0x65, 0xb1, 0x04, 0x70, 0x64, 0x65, 0x70, 0x65, -0x6e, 0x64, 0x73, 0x29, 0x00, 0x01, 0x39, 0x03, 0x41, 0x69, -0x72, 0x65, 0x63, 0x77, 0x00, 0x01, 0x43, 0x02, 0x06, 0xb2, -0x01, 0x92, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x61, 0x63, 0x68, -0x65, 0xca, 0x00, 0x04, 0x4a, 0x00, 0x76, 0x29, 0x2e, 0x00, -0x50, 0x72, 0x65, 0x73, 0x1e, 0x02, 0x50, 0x65, 0x74, 0x75, -0x72, 0x6e, 0x01, 0x01, 0x02, 0x25, 0x03, 0x00, 0xe0, 0x01, -0x01, 0xa9, 0x00, 0x2a, 0x6f, 0x66, 0x0c, 0x02, 0x00, 0xfa, -0x01, 0x49, 0x62, 0x6f, 0x76, 0x65, 0x16, 0x02, 0x02, 0x0f, -0x04, 0x02, 0xa4, 0x06, 0x0b, 0x4f, 0x01, 0x3f, 0x3b, 0x00, -0x70, 0x68, 0x00, 0x04, 0x20, 0x61, 0x67, 0xef, 0x01, 0x63, -0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x3c, 0x01, 0x00, 0x72, -0x00, 0x02, 0x7d, 0x05, 0x91, 0x73, 0x70, 0x61, 0x63, 0x65, -0x00, 0x62, 0x61, 0x72, 0xac, 0x01, 0x20, 0x62, 0x65, 0xaa, -0x01, 0xb1, 0x64, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, -0x72, 0x6c, 0x79, 0x62, 0x03, 0x40, 0x72, 0x65, 0x61, 0x74, -0xa1, 0x06, 0x03, 0x32, 0x02, 0x15, 0x64, 0x0d, 0x04, 0x7f, -0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2d, 0x79, 0x00, 0x05, -0x30, 0x28, 0x77, 0x69, 0x50, 0x05, 0x10, 0x74, 0xe7, 0x01, -0x04, 0x1f, 0x00, 0x02, 0xb2, 0x00, 0x12, 0x29, 0x13, 0x03, -0x02, 0xbc, 0x03, 0x06, 0xbf, 0x02, 0x02, 0xf6, 0x00, 0x0f, -0xbb, 0x03, 0x07, 0x65, 0x00, 0x64, 0x6f, 0x65, 0x73, 0x3a, -0x1e, 0x04, 0x03, 0x8d, 0x02, 0x0c, 0x0e, 0x01, 0x43, 0x6d, -0x6f, 0x64, 0x65, 0xe2, 0x01, 0x02, 0xf5, 0x07, 0x43, 0x66, -0x69, 0x6c, 0x6c, 0x97, 0x01, 0x51, 0x65, 0x6e, 0x74, 0x69, -0x72, 0x68, 0x02, 0x00, 0xf7, 0x02, 0x36, 0x62, 0x75, 0x74, -0x48, 0x04, 0x20, 0x6f, 0x72, 0xda, 0x01, 0x02, 0x4d, 0x05, -0x66, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x04, 0x01, -0xe2, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x64, 0x96, 0x06, 0x41, -0x6c, 0x61, 0x79, 0x2c, 0x2a, 0x00, 0x10, 0x67, 0x29, 0x07, -0x01, 0xcc, 0x00, 0x50, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x20, -0x02, 0x10, 0x73, 0x1e, 0x00, 0x09, 0xf8, 0x08, 0x29, 0x69, -0x6e, 0xd8, 0x08, 0x24, 0x6f, 0x66, 0xec, 0x02, 0x00, 0x83, -0x01, 0x09, 0xcb, 0x00, 0x03, 0xb6, 0x00, 0x22, 0x77, 0x61, -0x5a, 0x08, 0x60, 0x64, 0x69, 0x73, 0x63, 0x75, 0x73, 0x13, -0x01, 0x10, 0x70, 0x50, 0x05, 0x55, 0x63, 0x75, 0x6c, 0x61, -0x72, 0x7e, 0x07, 0x40, 0x6e, 0x73, 0x74, 0x61, 0xa4, 0x02, -0x01, 0xff, 0x00, 0xa0, 0x61, 0x00, 0x66, 0x72, 0x69, 0x65, -0x6e, 0x64, 0x00, 0x2d, 0xf3, 0x00, 0x01, 0x9a, 0x04, 0x00, -0x76, 0x08, 0x60, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0xf2, -0x02, 0x10, 0x6e, 0xa9, 0x00, 0x2a, 0x66, 0x6f, 0x62, 0x09, -0x40, 0x69, 0x73, 0x00, 0x6d, 0x48, 0x09, 0x60, 0x65, 0x61, -0x73, 0x69, 0x65, 0x72, 0x80, 0x02, 0x51, 0x6e, 0x00, 0x74, -0x72, 0x79, 0xac, 0x01, 0x00, 0x55, 0x08, 0x10, 0x66, 0x15, -0x00, 0x01, 0x04, 0x06, 0x50, 0x6d, 0x00, 0x61, 0x6c, 0x6c, -0x79, 0x07, 0x00, 0x48, 0x00, 0x13, 0x73, 0x7e, 0x09, 0x30, -0x73, 0x00, 0x60, 0xc9, 0x00, 0x00, 0xd0, 0x05, 0x41, 0x64, -0x6f, 0x77, 0x6e, 0x46, 0x06, 0x02, 0xfe, 0x04, 0x03, 0xe3, -0x00, 0x20, 0x62, 0x72, 0x17, 0x00, 0x01, 0xc3, 0x09, 0x12, -0x6e, 0x68, 0x07, 0x23, 0x6f, 0x70, 0xdd, 0x08, 0x11, 0x27, -0x4b, 0x06, 0x31, 0x41, 0x6c, 0x6c, 0x18, 0x00, 0x21, 0x61, -0x63, 0xfc, 0x06, 0x00, 0x97, 0x06, 0x61, 0x63, 0x72, 0x69, -0x62, 0x65, 0x64, 0xe3, 0x09, 0x03, 0x69, 0x03, 0x31, 0x32, -0x2e, 0x31, 0x8e, 0x05, 0x01, 0x49, 0x04, 0x50, 0x61, 0x76, -0x61, 0x69, 0x6c, 0x6b, 0x07, 0x22, 0x2e, 0x29, 0x29, 0x07, -0x11, 0x32, 0x29, 0x07, 0x00, 0xc5, 0x08, 0x52, 0x6d, 0x65, -0x74, 0x65, 0x72, 0x2b, 0x07, 0x56, 0x68, 0x65, 0x73, 0x65, -0x00, 0x14, 0x00, 0x02, 0x3f, 0x00, 0x04, 0x3a, 0x00, 0x06, -0xfd, 0x05, 0xe2, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, -0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x4d, 0x04, 0x12, -0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0xa9, 0x00, 0x91, 0x57, 0x69, 0x64, -0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xde, 0x00, 0x51, 0x00, -0x00, 0x53, 0x69, 0x7a, 0x97, 0x0a, 0x32, 0x67, 0x72, 0x69, -0xab, 0x00, 0x51, 0x71, 0x75, 0x61, 0x72, 0x65, 0xbc, 0x07, -0x13, 0x52, 0x2b, 0x06, 0x3c, 0x00, 0x00, 0x4e, 0xf6, 0x0a, -0x22, 0x00, 0x69, 0x5d, 0x00, 0x41, 0x67, 0x65, 0x6e, 0x65, -0x74, 0x09, 0x02, 0x04, 0x02, 0x36, 0x00, 0x00, 0x44, 0x41, -0x05, 0xb1, 0x00, 0x00, 0x49, 0x6e, 0x00, 0x60, 0x45, 0x61, -0x73, 0x79, 0x27, 0xc9, 0x02, 0x13, 0x2c, 0x8f, 0x06, 0x21, -0x73, 0x68, 0xd4, 0x04, 0x03, 0x11, 0x07, 0x2f, 0x62, 0x65, -0x4f, 0x07, 0x02, 0x45, 0x77, 0x68, 0x6f, 0x73, 0x09, 0x05, -0x03, 0xd0, 0x03, 0x10, 0x64, 0x02, 0x01, 0x30, 0x6d, 0x69, -0x6e, 0xe6, 0x02, 0x40, 0x72, 0x69, 0x76, 0x69, 0xf6, 0x09, -0x11, 0x2e, 0x65, 0x00, 0x71, 0x4e, 0x6f, 0x72, 0x6d, 0x61, -0x6c, 0x27, 0xb7, 0x01, 0x52, 0x60, 0x48, 0x61, 0x72, 0x64, -0x72, 0x00, 0x12, 0x73, 0x44, 0x07, 0x01, 0xd5, 0x02, 0x02, -0x34, 0x0b, 0x02, 0xbf, 0x05, 0x20, 0x69, 0x6e, 0x09, 0x04, -0x00, 0xe8, 0x03, 0x10, 0x6c, 0x0c, 0x0b, 0x00, 0xdd, 0x09, -0x71, 0x78, 0x00, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0xab, 0x02, -0x5b, 0x65, 0x64, 0x75, 0x63, 0x65, 0xbc, 0x05, 0x08, 0x47, -0x0b, 0x50, 0x2e, 0x00, 0x48, 0x6f, 0x77, 0x20, 0x0a, 0x10, -0x2c, 0x56, 0x05, 0x08, 0x38, 0x08, 0x25, 0x62, 0x65, 0xe1, -0x07, 0x14, 0x00, 0x32, 0x04, 0x03, 0xc5, 0x02, 0x70, 0x74, -0x6f, 0x00, 0x67, 0x75, 0x65, 0x73, 0x69, 0x0a, 0xb3, 0x00, -0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x2e, -0x25, 0x01, 0x20, 0x55, 0x6e, 0x90, 0x00, 0x20, 0x6f, 0x6e, -0xd4, 0x01, 0x07, 0x2d, 0x01, 0x0a, 0x9c, 0x08, 0x81, 0x66, -0x65, 0x65, 0x6c, 0x00, 0x66, 0x72, 0x65, 0xc7, 0x00, 0x04, -0x79, 0x01, 0x03, 0x44, 0x03, 0x04, 0x30, 0x0b, 0x01, 0x1e, -0x02, 0x11, 0x73, 0xce, 0x06, 0x00, 0x08, 0x00, 0x21, 0x69, -0x74, 0x3c, 0x01, 0x03, 0x94, 0x00, 0x15, 0x79, 0xe0, 0x0b, -0x12, 0x6d, 0x9b, 0x06, 0x01, 0x56, 0x0b, 0x00, 0xe2, 0x0c, -0x01, 0x35, 0x0a, 0x11, 0x74, 0xc0, 0x0c, 0x12, 0x68, 0x11, -0x07, 0x14, 0x79, 0xa7, 0x01, 0x25, 0x73, 0x74, 0x3e, 0x01, -0x13, 0x61, 0xfd, 0x0b, 0x05, 0x0d, 0x0c, 0x51, 0x2e, 0x00, -0x53, 0x6f, 0x6c, 0xde, 0x00, 0x08, 0xc1, 0x00, 0x05, 0x93, -0x00, 0x00, 0x86, 0x0b, 0x03, 0xf5, 0x0b, 0x02, 0xfc, 0x00, -0x02, 0xcd, 0x03, 0x16, 0x64, 0x00, 0x01, 0x50, 0x69, 0x6e, -0x67, 0x2e, 0x00, +0xfa, 0x03, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0x32, 0x32, 0x3a, 0x20, 0x4d, 0x61, 0x70, 0x20, 0x00, 0x2d, +0x01, 0x00, 0xf0, 0x1e, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, +0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, +0x00, 0x61, 0x00, 0x6d, 0x61, 0x70, 0x00, 0x63, 0x6f, 0x6e, +0x73, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x6f, 0x66, +0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x0c, +0x00, 0x80, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x2e, +0x37, 0x00, 0xf0, 0x01, 0x72, 0x00, 0x74, 0x61, 0x73, 0x6b, +0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6c, +0x12, 0x00, 0x43, 0x65, 0x61, 0x63, 0x68, 0x25, 0x00, 0x90, +0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x6f, 0x6e, 0x65, 0x38, +0x00, 0x10, 0x66, 0x1d, 0x00, 0x02, 0x24, 0x00, 0xf4, 0x0d, +0x73, 0x2c, 0x00, 0x69, 0x6e, 0x00, 0x73, 0x75, 0x63, 0x68, +0x00, 0x61, 0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, +0x74, 0x00, 0x6e, 0x6f, 0x00, 0x74, 0x77, 0x6f, 0x60, 0x00, +0x50, 0x00, 0x73, 0x68, 0x61, 0x72, 0x7f, 0x00, 0xf3, 0x09, +0x61, 0x00, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, +0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x74, 0x68, 0x65, 0x00, +0x73, 0x61, 0x6d, 0x65, 0x4c, 0x00, 0x15, 0x2e, 0xbf, 0x00, +0x82, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x76, +0x00, 0x45, 0x73, 0x6f, 0x6d, 0x65, 0x4c, 0x00, 0x73, 0x61, +0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x33, 0x00, 0xe0, 0x65, +0x64, 0x2c, 0x00, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, +0x65, 0x6e, 0x74, 0xbb, 0x00, 0x32, 0x6d, 0x61, 0x6b, 0x59, +0x00, 0x72, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x64, 0xea, +0x00, 0x01, 0x6a, 0x00, 0x40, 0x6f, 0x6c, 0x75, 0x74, 0xcb, +0x00, 0xb0, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2c, 0x00, +0x61, 0x6e, 0x64, 0x19, 0x00, 0xf5, 0x0d, 0x73, 0x65, 0x00, +0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x00, 0x62, 0x65, 0x00, +0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x2e, 0x00, 0x00, +0x00, 0x4f, 0x6e, 0x6c, 0x79, 0x77, 0x00, 0x51, 0x77, 0x68, +0x69, 0x63, 0x68, 0xc9, 0x00, 0xa0, 0x65, 0x00, 0x61, 0x00, +0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x59, 0x00, 0x30, 0x62, +0x6f, 0x72, 0x63, 0x00, 0x20, 0x61, 0x72, 0x71, 0x00, 0x60, +0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x86, 0x00, 0x90, 0x62, +0x65, 0x00, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x96, 0x00, +0x03, 0x2a, 0x01, 0x5b, 0x2e, 0x00, 0x54, 0x77, 0x6f, 0x51, +0x00, 0x90, 0x6d, 0x65, 0x65, 0x74, 0x00, 0x61, 0x74, 0x00, +0x6f, 0x6c, 0x00, 0x00, 0x5e, 0x01, 0xb1, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x00, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x55, 0x00, +0xff, 0x0c, 0x64, 0x69, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, +0x6c, 0x79, 0x00, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, +0x65, 0x64, 0x29, 0x00, 0x6d, 0x61, 0x79, 0x00, 0x62, 0x40, +0x01, 0x00, 0x91, 0x00, 0x00, 0x49, 0x00, 0x62, 0x65, 0x6c, +0x69, 0x65, 0x5d, 0x01, 0x90, 0x69, 0x73, 0x00, 0x70, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0xd6, 0x01, 0xf0, 0x08, 0x6f, 0x72, +0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x3b, 0x00, 0x49, 0x27, +0x76, 0x65, 0x00, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x00, 0x73, +0x65, 0x26, 0x02, 0xc1, 0x6e, 0x00, 0x69, 0x6d, 0x70, 0x6c, +0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x21, 0x01, 0xf0, 0x09, +0x6f, 0x66, 0x00, 0x69, 0x74, 0x00, 0x61, 0x6e, 0x79, 0x77, +0x68, 0x65, 0x72, 0x65, 0x00, 0x65, 0x6c, 0x73, 0x65, 0x2e, +0x00, 0x54, 0x68, 0x65, 0x4b, 0x02, 0x42, 0x63, 0x65, 0x70, +0x74, 0x48, 0x02, 0x00, 0x06, 0x02, 0x12, 0x2d, 0x7a, 0x00, +0x00, 0xdd, 0x01, 0x03, 0x6b, 0x00, 0xf0, 0x26, 0x77, 0x61, +0x73, 0x00, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, +0x64, 0x00, 0x62, 0x79, 0x00, 0x41, 0x6c, 0x65, 0x78, 0x61, +0x6e, 0x64, 0x72, 0x61, 0x00, 0x4c, 0x61, 0x6e, 0x65, 0x73, +0x3b, 0x00, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x6d, +0x75, 0x73, 0x74, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x67, +0x6f, 0x33, 0x01, 0x62, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, +0x95, 0x01, 0x70, 0x6f, 0x00, 0x56, 0x65, 0x72, 0x69, 0x74, +0x3d, 0x00, 0xd1, 0x6c, 0x61, 0x6e, 0x00, 0x66, 0x6f, 0x72, +0x00, 0x69, 0x6e, 0x73, 0x70, 0x69, 0x69, 0x00, 0x00, 0xf6, +0x00, 0x52, 0x74, 0x72, 0x61, 0x69, 0x6e, 0xd9, 0x01, 0x52, +0x6f, 0x75, 0x67, 0x68, 0x74, 0x77, 0x02, 0x12, 0x6c, 0x7d, +0x01, 0x01, 0x2e, 0x02, 0x40, 0x61, 0x6c, 0x69, 0x73, 0x2e, +0x00, 0x00, 0x7f, 0x00, 0x15, 0x27, 0x93, 0x00, 0x01, 0xca, +0x02, 0xb3, 0x61, 0x73, 0x00, 0x61, 0x00, 0x76, 0x69, 0x61, +0x62, 0x6c, 0x65, 0xb6, 0x00, 0x00, 0xde, 0x00, 0x42, 0x61, +0x6e, 0x6b, 0x73, 0x90, 0x00, 0xf1, 0x01, 0x74, 0x6f, 0x00, +0x47, 0x61, 0x72, 0x65, 0x74, 0x68, 0x00, 0x54, 0x61, 0x79, +0x6c, 0x6f, 0x72, 0x80, 0x00, 0xa0, 0x6d, 0x61, 0x6e, 0x79, +0x00, 0x64, 0x65, 0x74, 0x61, 0x69, 0x66, 0x00, 0x06, 0x4f, +0x00, 0x10, 0x73, 0x76, 0x01, 0x41, 0x32, 0x32, 0x2e, 0x31, +0x93, 0x03, 0xd5, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, +0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x48, 0x03, 0x13, 0x61, +0xf6, 0x01, 0x71, 0x2c, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, +0xc2, 0x00, 0xf0, 0x00, 0x6c, 0x65, 0x66, 0x74, 0x00, 0x6d, +0x6f, 0x75, 0x73, 0x65, 0x00, 0x62, 0x75, 0x74, 0x74, 0x76, +0x01, 0x01, 0x8b, 0x01, 0x23, 0x65, 0x78, 0xac, 0x03, 0x03, +0x78, 0x03, 0x03, 0xbd, 0x02, 0x31, 0x64, 0x65, 0x73, 0x5c, +0x02, 0x04, 0x52, 0x00, 0x72, 0x6e, 0x64, 0x00, 0x64, 0x72, +0x61, 0x67, 0xf8, 0x00, 0x03, 0x15, 0x00, 0x41, 0x69, 0x6e, +0x74, 0x6f, 0x2d, 0x00, 0x33, 0x6e, 0x65, 0x77, 0x3f, 0x00, +0x00, 0x9d, 0x00, 0x31, 0x28, 0x54, 0x68, 0x52, 0x03, 0xf3, +0x07, 0x67, 0x72, 0x61, 0x6d, 0x00, 0x77, 0x69, 0x6c, 0x6c, +0x00, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x00, 0x65, 0x6e, +0x73, 0x75, 0x72, 0x46, 0x02, 0x47, 0x74, 0x61, 0x72, 0x74, +0xc6, 0x01, 0x10, 0x68, 0x24, 0x01, 0x00, 0x51, 0x01, 0x31, +0x61, 0x73, 0x74, 0x98, 0x02, 0x06, 0x8e, 0x00, 0x01, 0x15, +0x04, 0x02, 0x72, 0x00, 0x42, 0x2c, 0x00, 0x73, 0x6f, 0x82, +0x00, 0x01, 0x6d, 0x02, 0x24, 0x69, 0x73, 0x5a, 0x00, 0xa0, +0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x21, 0x29, +0x93, 0x02, 0x82, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6e, +0x65, 0x9e, 0x01, 0x48, 0x63, 0x6c, 0x65, 0x61, 0x13, 0x01, +0x00, 0x1c, 0x00, 0x32, 0x63, 0x61, 0x6e, 0xcf, 0x00, 0x41, +0x66, 0x72, 0x6f, 0x6d, 0x06, 0x01, 0x45, 0x6d, 0x70, 0x74, +0x79, 0x23, 0x00, 0x22, 0x6f, 0x72, 0x19, 0x00, 0x24, 0x74, +0x68, 0xb1, 0x01, 0x06, 0x49, 0x04, 0x11, 0x69, 0x20, 0x01, +0x21, 0x72, 0x65, 0x2e, 0x03, 0x29, 0x6e, 0x6f, 0x3a, 0x00, +0x11, 0x73, 0x66, 0x01, 0x00, 0x04, 0x01, 0x52, 0x44, 0x72, +0x61, 0x67, 0x67, 0x83, 0x04, 0x03, 0x2d, 0x01, 0x24, 0x75, +0x73, 0x4c, 0x02, 0x4b, 0x72, 0x69, 0x67, 0x68, 0x8b, 0x01, +0x01, 0x26, 0x01, 0x64, 0x73, 0x74, 0x69, 0x70, 0x70, 0x6c, +0x4d, 0x04, 0x01, 0xff, 0x00, 0x28, 0x69, 0x6e, 0x71, 0x01, +0x13, 0x2c, 0xc5, 0x03, 0x04, 0xc2, 0x00, 0x00, 0x41, 0x00, +0x01, 0x5c, 0x02, 0x40, 0x6e, 0x6f, 0x74, 0x65, 0xeb, 0x00, +0x10, 0x79, 0xf7, 0x03, 0x32, 0x65, 0x6c, 0x66, 0x35, 0x00, +0x00, 0x27, 0x00, 0x58, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x52, +0x00, 0x11, 0x6d, 0x7d, 0x00, 0x28, 0x62, 0x65, 0x58, 0x00, +0x34, 0x2e, 0x00, 0x41, 0x1f, 0x00, 0x00, 0x57, 0x00, 0x00, +0x54, 0x02, 0x00, 0xee, 0x02, 0x03, 0x90, 0x00, 0x10, 0x73, +0x86, 0x00, 0x74, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, +0xfa, 0x03, 0x01, 0xad, 0x01, 0x00, 0x9c, 0x03, 0x10, 0x2e, +0xee, 0x01, 0x02, 0x8b, 0x01, 0x41, 0x6f, 0x66, 0x74, 0x65, +0x94, 0x00, 0x41, 0x66, 0x75, 0x6c, 0x00, 0xa3, 0x01, 0x00, +0xd7, 0x01, 0x01, 0xae, 0x04, 0x20, 0x64, 0x69, 0x32, 0x05, +0xd3, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x65, +0x6c, 0x73, 0x2e, 0x29, 0x3c, 0x06, 0x00, 0x70, 0x00, 0x01, +0x04, 0x03, 0x22, 0x75, 0x73, 0xf9, 0x00, 0xb1, 0x63, 0x75, +0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x5b, +0x03, 0x20, 0x6f, 0x76, 0x6a, 0x01, 0x22, 0x6f, 0x75, 0x3b, +0x05, 0x00, 0x60, 0x06, 0x12, 0x3a, 0x28, 0x00, 0x02, 0x56, +0x01, 0x28, 0x6f, 0x66, 0x36, 0x00, 0x92, 0x69, 0x6e, 0x64, +0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0xba, 0x01, 0x34, 0x6f, +0x73, 0x69, 0x5f, 0x04, 0x07, 0x33, 0x00, 0x00, 0x17, 0x01, +0x43, 0x77, 0x6f, 0x75, 0x6c, 0xd1, 0x02, 0x12, 0x28, 0x54, +0x01, 0x30, 0x69, 0x73, 0x00, 0x92, 0x05, 0x91, 0x6f, 0x62, +0x76, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x69, 0x44, 0x02, 0x31, +0x27, 0x72, 0x65, 0x26, 0x03, 0x03, 0x1e, 0x01, 0x25, 0x27, +0x73, 0x07, 0x02, 0x70, 0x2c, 0x00, 0x73, 0x69, 0x6e, 0x63, +0x65, 0xb7, 0x04, 0x70, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, +0x73, 0x29, 0x00, 0x01, 0x39, 0x03, 0x41, 0x69, 0x72, 0x65, +0x63, 0x77, 0x00, 0x01, 0x43, 0x02, 0x06, 0xb2, 0x01, 0x92, +0x61, 0x70, 0x70, 0x72, 0x6f, 0x61, 0x63, 0x68, 0x65, 0xca, +0x00, 0x04, 0x4a, 0x00, 0x76, 0x29, 0x2e, 0x00, 0x50, 0x72, +0x65, 0x73, 0x1e, 0x02, 0x50, 0x65, 0x74, 0x75, 0x72, 0x6e, +0x01, 0x01, 0x02, 0x25, 0x03, 0x00, 0xe0, 0x01, 0x01, 0xa9, +0x00, 0x2a, 0x6f, 0x66, 0x0c, 0x02, 0x00, 0xfa, 0x01, 0x49, +0x62, 0x6f, 0x76, 0x65, 0x16, 0x02, 0x02, 0x0f, 0x04, 0x02, +0xc7, 0x06, 0x0b, 0x4f, 0x01, 0x3f, 0x3b, 0x00, 0x70, 0x68, +0x00, 0x04, 0x20, 0x61, 0x67, 0xef, 0x01, 0x63, 0x66, 0x69, +0x6e, 0x69, 0x73, 0x68, 0x3c, 0x01, 0x00, 0x72, 0x00, 0x02, +0x83, 0x05, 0x91, 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, 0x62, +0x61, 0x72, 0xac, 0x01, 0x20, 0x62, 0x65, 0xaa, 0x01, 0xb1, +0x64, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x6c, +0x79, 0x62, 0x03, 0x40, 0x72, 0x65, 0x61, 0x74, 0xa7, 0x06, +0x03, 0x32, 0x02, 0x15, 0x64, 0x0d, 0x04, 0x7f, 0x44, 0x6f, +0x75, 0x62, 0x6c, 0x65, 0x2d, 0x79, 0x00, 0x05, 0x30, 0x28, +0x77, 0x69, 0x50, 0x05, 0x10, 0x74, 0xe7, 0x01, 0x04, 0x1f, +0x00, 0x02, 0xb2, 0x00, 0x12, 0x29, 0x13, 0x03, 0x02, 0xbc, +0x03, 0x06, 0xbf, 0x02, 0x02, 0xf6, 0x00, 0x0f, 0xbb, 0x03, +0x07, 0x65, 0x00, 0x64, 0x6f, 0x65, 0x73, 0x3a, 0x1e, 0x04, +0x03, 0x8d, 0x02, 0x0c, 0x0e, 0x01, 0x43, 0x6d, 0x6f, 0x64, +0x65, 0xe2, 0x01, 0x02, 0x18, 0x08, 0x43, 0x66, 0x69, 0x6c, +0x6c, 0x97, 0x01, 0x51, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x68, +0x02, 0x00, 0xf7, 0x02, 0x36, 0x62, 0x75, 0x74, 0x48, 0x04, +0x20, 0x6f, 0x72, 0xda, 0x01, 0x02, 0x4d, 0x05, 0x66, 0x61, +0x79, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x04, 0x01, 0xe2, 0x00, +0x43, 0x00, 0x4c, 0x00, 0x64, 0x9c, 0x06, 0x41, 0x6c, 0x61, +0x79, 0x2c, 0x2a, 0x00, 0x10, 0x67, 0x2f, 0x07, 0x01, 0xcc, +0x00, 0x50, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x20, 0x02, 0x10, +0x73, 0x1e, 0x00, 0x09, 0x1b, 0x09, 0x29, 0x69, 0x6e, 0xfb, +0x08, 0x24, 0x6f, 0x66, 0xec, 0x02, 0x00, 0x83, 0x01, 0x09, +0xcb, 0x00, 0x03, 0xb6, 0x00, 0x22, 0x77, 0x61, 0x7d, 0x08, +0x60, 0x64, 0x69, 0x73, 0x63, 0x75, 0x73, 0x13, 0x01, 0x10, +0x70, 0x50, 0x05, 0x55, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x84, +0x07, 0x40, 0x6e, 0x73, 0x74, 0x61, 0xa4, 0x02, 0x01, 0xff, +0x00, 0xa0, 0x61, 0x00, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, +0x00, 0x2d, 0xf3, 0x00, 0x01, 0x9a, 0x04, 0x00, 0x99, 0x08, +0x60, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0xf2, 0x02, 0x10, +0x6e, 0xa9, 0x00, 0x2a, 0x66, 0x6f, 0x85, 0x09, 0x40, 0x69, +0x73, 0x00, 0x6d, 0x6b, 0x09, 0x60, 0x65, 0x61, 0x73, 0x69, +0x65, 0x72, 0x80, 0x02, 0x51, 0x6e, 0x00, 0x74, 0x72, 0x79, +0xac, 0x01, 0x00, 0x5b, 0x08, 0x10, 0x66, 0x15, 0x00, 0x01, +0x04, 0x06, 0x50, 0x6d, 0x00, 0x61, 0x6c, 0x6c, 0x7f, 0x07, +0x00, 0x48, 0x00, 0x13, 0x73, 0xa1, 0x09, 0x30, 0x73, 0x00, +0x60, 0xc9, 0x00, 0x00, 0xd0, 0x05, 0x41, 0x64, 0x6f, 0x77, +0x6e, 0x46, 0x06, 0x02, 0xfe, 0x04, 0x03, 0xe3, 0x00, 0x20, +0x62, 0x72, 0x17, 0x00, 0x01, 0xe6, 0x09, 0x12, 0x6e, 0x68, +0x07, 0x23, 0x6f, 0x70, 0xe3, 0x08, 0x11, 0x27, 0x4b, 0x06, +0x31, 0x41, 0x6c, 0x6c, 0x18, 0x00, 0x21, 0x61, 0x63, 0xfc, +0x06, 0x00, 0x97, 0x06, 0x61, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0x06, 0x0a, 0x03, 0x69, 0x03, 0x31, 0x32, 0x2e, 0x31, +0x8e, 0x05, 0x01, 0x49, 0x04, 0x50, 0x61, 0x76, 0x61, 0x69, +0x6c, 0x6b, 0x07, 0x22, 0x2e, 0x29, 0x29, 0x07, 0x11, 0x32, +0x29, 0x07, 0x00, 0xcb, 0x08, 0x52, 0x6d, 0x65, 0x74, 0x65, +0x72, 0x2b, 0x07, 0x01, 0x86, 0x09, 0x06, 0x14, 0x00, 0x02, +0x3f, 0x00, 0x04, 0x3a, 0x00, 0x06, 0xfd, 0x05, 0xe2, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x4d, 0x04, 0x12, 0x6e, 0x1a, 0x00, 0xa0, +0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, +0xa9, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, +0x48, 0x65, 0xde, 0x00, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, +0xba, 0x0a, 0x32, 0x67, 0x72, 0x69, 0xab, 0x00, 0x51, 0x71, +0x75, 0x61, 0x72, 0x65, 0xbc, 0x07, 0x13, 0x52, 0x2b, 0x06, +0x3c, 0x00, 0x00, 0x4e, 0x19, 0x0b, 0x22, 0x00, 0x69, 0x5d, +0x00, 0x41, 0x67, 0x65, 0x6e, 0x65, 0x7a, 0x09, 0x02, 0x04, +0x02, 0x36, 0x00, 0x00, 0x44, 0x41, 0x05, 0xb1, 0x00, 0x00, +0x49, 0x6e, 0x00, 0x60, 0x45, 0x61, 0x73, 0x79, 0x27, 0xc9, +0x02, 0x13, 0x2c, 0x8f, 0x06, 0x21, 0x73, 0x68, 0xd4, 0x04, +0x03, 0x11, 0x07, 0x2f, 0x62, 0x65, 0x4f, 0x07, 0x02, 0x45, +0x77, 0x68, 0x6f, 0x73, 0x09, 0x05, 0x03, 0xd0, 0x03, 0x10, +0x64, 0x02, 0x01, 0x30, 0x6d, 0x69, 0x6e, 0xe6, 0x02, 0x40, +0x72, 0x69, 0x76, 0x69, 0xfc, 0x09, 0x11, 0x2e, 0x65, 0x00, +0x71, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x27, 0xb7, 0x01, +0x52, 0x60, 0x48, 0x61, 0x72, 0x64, 0x72, 0x00, 0x12, 0x73, +0x44, 0x07, 0x01, 0xd5, 0x02, 0x02, 0x57, 0x0b, 0x02, 0xbf, +0x05, 0x20, 0x69, 0x6e, 0x09, 0x04, 0x00, 0xe8, 0x03, 0x10, +0x6c, 0x2f, 0x0b, 0x00, 0xe3, 0x09, 0x71, 0x78, 0x00, 0x6c, +0x6f, 0x67, 0x69, 0x63, 0xab, 0x02, 0x5b, 0x65, 0x64, 0x75, +0x63, 0x65, 0xbc, 0x05, 0x08, 0x6a, 0x0b, 0x50, 0x2e, 0x00, +0x48, 0x6f, 0x77, 0x26, 0x0a, 0x10, 0x2c, 0x56, 0x05, 0x08, +0x38, 0x08, 0x25, 0x62, 0x65, 0xe1, 0x07, 0x14, 0x00, 0x32, +0x04, 0x03, 0xc5, 0x02, 0x70, 0x74, 0x6f, 0x00, 0x67, 0x75, +0x65, 0x73, 0x6f, 0x0a, 0xb3, 0x00, 0x62, 0x61, 0x63, 0x6b, +0x74, 0x72, 0x61, 0x63, 0x6b, 0x2e, 0x25, 0x01, 0x20, 0x55, +0x6e, 0x90, 0x00, 0x20, 0x6f, 0x6e, 0xd4, 0x01, 0x07, 0x2d, +0x01, 0x0a, 0x9c, 0x08, 0x81, 0x66, 0x65, 0x65, 0x6c, 0x00, +0x66, 0x72, 0x65, 0xc7, 0x00, 0x04, 0x79, 0x01, 0x03, 0x44, +0x03, 0x04, 0x36, 0x0b, 0x01, 0x1e, 0x02, 0x11, 0x73, 0xce, +0x06, 0x00, 0x08, 0x00, 0x21, 0x69, 0x74, 0x3c, 0x01, 0x03, +0x94, 0x00, 0x15, 0x79, 0x03, 0x0c, 0x12, 0x6d, 0x9b, 0x06, +0x01, 0x5c, 0x0b, 0x00, 0x05, 0x0d, 0x01, 0x35, 0x0a, 0x11, +0x74, 0xe3, 0x0c, 0x12, 0x68, 0x11, 0x07, 0x14, 0x79, 0xa7, +0x01, 0x25, 0x73, 0x74, 0x3e, 0x01, 0x13, 0x61, 0x20, 0x0c, +0x05, 0x30, 0x0c, 0x51, 0x2e, 0x00, 0x53, 0x6f, 0x6c, 0xde, +0x00, 0x08, 0xc1, 0x00, 0x05, 0x93, 0x00, 0x00, 0x8c, 0x0b, +0x03, 0xfb, 0x0b, 0x02, 0xfc, 0x00, 0x02, 0xcd, 0x03, 0x16, +0x64, 0x00, 0x01, 0x33, 0x69, 0x6e, 0x67, 0x25, 0x0a, 0x11, +0x33, 0xfc, 0x02, 0x81, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, +0x72, 0x65, 0x1f, 0x0c, 0x41, 0x63, 0x65, 0x73, 0x20, 0x6d, +0x0c, 0x00, 0xa5, 0x04, 0x53, 0x74, 0x66, 0x6f, 0x72, 0x6d, +0x9f, 0x00, 0x80, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, +0x00, 0x2e, 0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0xf0, +0x02, 0x16, 0x50, 0x12, 0x00, 0x0d, 0x0c, 0x03, 0x33, 0x47, +0x61, 0x6d, 0x0c, 0x03, 0x02, 0x54, 0x01, 0x34, 0x6c, 0x65, +0x74, 0x8f, 0x06, 0x36, 0x66, 0x69, 0x67, 0xf4, 0x09, 0x34, +0x79, 0x6c, 0x65, 0xfa, 0x03, 0xd1, 0x76, 0x69, 0x63, 0x74, +0x6f, 0x72, 0x79, 0x00, 0x66, 0x6c, 0x61, 0x73, 0x68, 0xbf, +0x00, 0x01, 0xbe, 0x03, 0x30, 0x77, 0x68, 0x65, 0xcf, 0x02, +0x07, 0xf3, 0x05, 0x12, 0x73, 0x07, 0x07, 0x10, 0x00, 0xf5, +0x01, 0x64, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x6c, 0xa7, 0x0d, +0x90, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 3466; -const unsigned short help_text_words = 642; +const unsigned short help_text_len = 3752; +const unsigned short help_text_words = 686; const char quick_help_text[] = "Colour the map so that adjacent regions are never the same colour."; diff --git a/apps/plugins/puzzles/help/mines.c b/apps/plugins/puzzles/help/mines.c index c2f73d4b54..8a4f4038c0 100644 --- a/apps/plugins/puzzles/help/mines.c +++ b/apps/plugins/puzzles/help/mines.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,258 +6,258 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 29, TEXT_UNDERLINE }, - { 119, TEXT_UNDERLINE }, - { 171, TEXT_CENTER | C_RED }, - { 248, TEXT_UNDERLINE }, - { 283, TEXT_UNDERLINE }, - { 334, TEXT_UNDERLINE }, - { 583, TEXT_CENTER | C_RED }, - { 600, TEXT_UNDERLINE }, + { 30, TEXT_UNDERLINE }, + { 120, TEXT_UNDERLINE }, + { 172, TEXT_CENTER | C_RED }, + { 249, TEXT_UNDERLINE }, + { 284, TEXT_UNDERLINE }, + { 335, TEXT_UNDERLINE }, + { 584, TEXT_CENTER | C_RED }, { 601, TEXT_UNDERLINE }, - { 611, TEXT_UNDERLINE }, - { 685, TEXT_UNDERLINE }, + { 602, TEXT_UNDERLINE }, + { 612, TEXT_UNDERLINE }, + { 686, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 3796 comp 2333 ratio 0.614594 level 10 saved 1463 */ +/* orig 3814 comp 2339 ratio 0.613267 level 10 saved 1475 */ const char help_text[] = { -0xf0, 0x2e, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x32, 0x3a, 0x20, 0x4d, 0x69, 0x6e, 0x65, 0x73, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, -0x66, 0x00, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x00, -0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, -0x6f, 0x6d, 0x65, 0x19, 0x00, 0xf0, 0x02, 0x77, 0x68, 0x69, -0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, -0x00, 0x6d, 0x69, 0x6e, 0x1d, 0x00, 0xf2, 0x03, 0x62, 0x75, -0x74, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x64, 0x6f, 0x6e, 0x27, -0x74, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x28, 0x00, 0x10, 0x2e, -0x5b, 0x00, 0xe1, 0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, -0x73, 0x00, 0x74, 0x6f, 0x00, 0x75, 0x6e, 0x59, 0x00, 0x63, -0x00, 0x65, 0x76, 0x65, 0x72, 0x79, 0x5d, 0x00, 0x03, 0x53, -0x00, 0x85, 0x64, 0x6f, 0x65, 0x73, 0x00, 0x6e, 0x6f, 0x74, -0x5c, 0x00, 0x11, 0x61, 0x5e, 0x00, 0x41, 0x2e, 0x00, 0x49, -0x66, 0x5c, 0x00, 0x04, 0x3b, 0x00, 0x14, 0x61, 0x37, 0x00, -0x03, 0x28, 0x00, 0x33, 0x69, 0x6e, 0x67, 0x2b, 0x00, 0x11, -0x2c, 0x28, 0x00, 0x3f, 0x6c, 0x6f, 0x73, 0x35, 0x00, 0x08, -0x0f, 0x6c, 0x00, 0x0a, 0x02, 0x41, 0x00, 0x00, 0x27, 0x00, -0xd2, 0x74, 0x6f, 0x6c, 0x64, 0x00, 0x68, 0x6f, 0x77, 0x00, -0x6d, 0x61, 0x6e, 0x79, 0xe6, 0x00, 0x17, 0x00, 0x74, 0x00, -0xf0, 0x0d, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, 0x69, -0x6e, 0x00, 0x74, 0x68, 0x65, 0x00, 0x65, 0x69, 0x67, 0x68, -0x74, 0x00, 0x73, 0x75, 0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, -0x90, 0x00, 0x03, 0x36, 0x01, 0xf0, 0x03, 0x2e, 0x00, 0x00, -0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, -0x00, 0x6e, 0x65, 0x65, 0x64, 0x76, 0x00, 0xf0, 0x1a, 0x00, -0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, -0x6f, 0x6e, 0x3b, 0x00, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, -0x72, 0x69, 0x73, 0x65, 0x64, 0x00, 0x62, 0x79, 0x00, 0x57, -0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2c, 0x00, 0x69, 0x74, -0x34, 0x01, 0x71, 0x70, 0x65, 0x72, 0x68, 0x61, 0x70, 0x73, -0x68, 0x00, 0xa2, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x00, -0x62, 0x65, 0x73, 0x64, 0x01, 0xf2, 0x01, 0x6e, 0x00, 0x64, -0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x00, 0x70, 0x75, 0x7a, -0x7a, 0x6c, 0x65, 0x67, 0x00, 0xc5, 0x69, 0x6e, 0x00, 0x65, -0x78, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x81, 0x00, -0x70, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xc1, 0x01, -0xf1, 0x17, 0x69, 0x74, 0x00, 0x68, 0x61, 0x73, 0x00, 0x61, -0x6e, 0x00, 0x75, 0x6e, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x00, -0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x00, -0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, -0x80, 0x00, 0xf1, 0x02, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x67, -0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x00, 0x69, 0x74, -0x73, 0x0a, 0x01, 0x50, 0x00, 0x70, 0x6f, 0x73, 0x69, 0xbc, -0x00, 0x10, 0x73, 0x6c, 0x00, 0xc1, 0x73, 0x75, 0x63, 0x68, -0x00, 0x61, 0x00, 0x77, 0x61, 0x79, 0x00, 0x61, 0xe3, 0x01, -0x40, 0x65, 0x6e, 0x73, 0x75, 0x42, 0x01, 0x22, 0x68, 0x61, -0x14, 0x02, 0x10, 0x6e, 0xec, 0x01, 0x01, 0xfd, 0x00, 0x00, -0x1e, 0x00, 0xb3, 0x67, 0x75, 0x65, 0x73, 0x73, 0x00, 0x77, -0x68, 0x65, 0x72, 0x65, 0x75, 0x01, 0x41, 0x00, 0x69, 0x73, -0x3a, 0x29, 0x00, 0x01, 0x6e, 0x00, 0xe0, 0x61, 0x6c, 0x77, -0x61, 0x79, 0x73, 0x00, 0x62, 0x65, 0x00, 0x61, 0x62, 0x6c, -0x65, 0x32, 0x00, 0x50, 0x64, 0x65, 0x64, 0x75, 0x63, 0x7e, -0x00, 0x01, 0x83, 0x02, 0x76, 0x68, 0x6f, 0x77, 0x2e, 0x00, -0x53, 0x6f, 0x31, 0x00, 0x01, 0x5f, 0x00, 0x10, 0x2c, 0x7c, -0x00, 0xa0, 0x63, 0x61, 0x6e, 0x00, 0x68, 0x61, 0x70, 0x70, -0x65, 0x6e, 0x98, 0x00, 0x54, 0x6f, 0x74, 0x68, 0x65, 0x72, -0xf8, 0x00, 0x60, 0x73, 0x2c, 0x00, 0x67, 0x65, 0x74, 0x4e, -0x00, 0x00, 0x48, 0x01, 0x60, 0x6c, 0x61, 0x73, 0x74, 0x00, -0x66, 0x99, 0x02, 0x03, 0xa8, 0x01, 0x82, 0x00, 0x61, 0x6e, -0x64, 0x00, 0x64, 0x69, 0x73, 0x2c, 0x02, 0x01, 0xba, 0x00, -0x12, 0x74, 0xa2, 0x00, 0x00, 0xc9, 0x00, 0x23, 0x77, 0x6f, -0x01, 0x02, 0x45, 0x6c, 0x65, 0x66, 0x74, 0xeb, 0x02, 0x01, -0x30, 0x03, 0x21, 0x6e, 0x6f, 0xf9, 0x00, 0x21, 0x6f, 0x66, -0x90, 0x01, 0x00, 0xfa, 0x01, 0x41, 0x66, 0x6f, 0x72, 0x00, -0x00, 0x01, 0x02, 0xe3, 0x00, 0x40, 0x74, 0x68, 0x65, 0x79, -0x46, 0x00, 0x00, 0x89, 0x01, 0x43, 0x31, 0x32, 0x2e, 0x31, -0x74, 0x03, 0x20, 0x63, 0x6f, 0x03, 0x02, 0x39, 0x6c, 0x73, -0x20, 0x21, 0x02, 0x00, 0xef, 0x01, 0x33, 0x6c, 0x61, 0x79, -0x5d, 0x02, 0x01, 0xab, 0x00, 0x41, 0x6d, 0x6f, 0x75, 0x73, -0x3d, 0x00, 0x03, 0xd0, 0x02, 0x00, 0x83, 0x00, 0x71, 0x2d, -0x63, 0x6c, 0x69, 0x63, 0x6b, 0x00, 0xb6, 0x02, 0x0a, 0xa7, -0x03, 0x06, 0xb5, 0x01, 0x24, 0x62, 0x65, 0xfb, 0x02, 0x27, -0x65, 0x64, 0x3f, 0x00, 0x10, 0x72, 0xaa, 0x02, 0x0f, 0x40, -0x00, 0x11, 0x40, 0x70, 0x6c, 0x61, 0x63, 0xa1, 0x01, 0x43, -0x66, 0x6c, 0x61, 0x67, 0x34, 0x03, 0x95, 0x69, 0x6e, 0x64, -0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x21, 0x01, 0x04, 0x54, -0x03, 0x10, 0x69, 0xb0, 0x01, 0x42, 0x6c, 0x69, 0x65, 0x76, -0xe3, 0x01, 0x25, 0x62, 0x65, 0xbb, 0x03, 0x15, 0x4c, 0xaf, -0x00, 0x00, 0x1c, 0x01, 0x02, 0x68, 0x03, 0x35, 0x61, 0x72, -0x6b, 0x71, 0x00, 0x03, 0xc3, 0x01, 0x25, 0x6f, 0x74, 0xa9, -0x03, 0x32, 0x69, 0x74, 0x2c, 0x44, 0x01, 0x51, 0x61, 0x66, -0x65, 0x74, 0x79, 0x40, 0x04, 0x01, 0xd9, 0x01, 0x08, 0xba, -0x00, 0x30, 0x61, 0x67, 0x61, 0x7a, 0x03, 0x83, 0x6f, 0x00, -0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x00, 0x02, 0xb4, -0x00, 0x11, 0x64, 0x00, 0x03, 0x4f, 0x72, 0x72, 0x6f, 0x72, -0x36, 0x01, 0x07, 0x00, 0xfa, 0x02, 0x0f, 0xf9, 0x00, 0x05, -0x81, 0x60, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x61, 0xcb, -0x03, 0x17, 0x27, 0xe6, 0x00, 0x12, 0x2e, 0xa9, 0x01, 0x98, -0x6d, 0x65, 0x61, 0x6e, 0x73, 0x3a, 0x00, 0x69, 0x66, 0x01, -0x01, 0x00, 0x50, 0x03, 0x61, 0x65, 0x78, 0x61, 0x63, 0x74, -0x6c, 0x05, 0x03, 0x01, 0x34, 0x04, 0x00, 0x3a, 0x01, 0x19, -0x73, 0x15, 0x04, 0x20, 0x69, 0x74, 0x1d, 0x00, 0x00, 0xc8, -0x02, 0x52, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x42, 0x02, 0x03, -0x41, 0x05, 0x81, 0x74, 0x68, 0x65, 0x6e, 0x00, 0x61, 0x6c, -0x6c, 0x56, 0x00, 0x0b, 0x7c, 0x05, 0x41, 0x00, 0x6e, 0x65, -0x78, 0xbc, 0x02, 0x23, 0x69, 0x74, 0x8b, 0x01, 0x00, 0x74, -0x00, 0x00, 0x35, 0x01, 0x00, 0x64, 0x00, 0x3e, 0x67, 0x65, -0x64, 0xf3, 0x01, 0x01, 0x23, 0x03, 0x41, 0x6f, 0x6e, 0x63, -0x65, 0xff, 0x00, 0x00, 0xa9, 0x04, 0x11, 0x6b, 0x0a, 0x00, -0x01, 0x9a, 0x05, 0x01, 0x03, 0x03, 0x43, 0x6f, 0x63, 0x61, -0x74, 0x11, 0x04, 0x04, 0x77, 0x00, 0x04, 0xe6, 0x04, 0x00, -0xb0, 0x00, 0x05, 0x31, 0x05, 0x02, 0x13, 0x05, 0x10, 0x63, -0x34, 0x01, 0x20, 0x73, 0x65, 0x4a, 0x00, 0x61, 0x73, 0x00, -0x66, 0x75, 0x6e, 0x63, 0x3c, 0x00, 0x00, 0x46, 0x04, 0x00, -0xcd, 0x00, 0x41, 0x72, 0x74, 0x63, 0x75, 0xa1, 0x00, 0x41, -0x61, 0x76, 0x6f, 0x69, 0xd8, 0x00, 0x00, 0xef, 0x00, 0x32, -0x74, 0x6f, 0x00, 0x73, 0x01, 0x92, 0x6f, 0x6e, 0x00, 0x65, -0x61, 0x63, 0x68, 0x00, 0x6f, 0x34, 0x01, 0x33, 0x72, 0x65, -0x6d, 0xb6, 0x05, 0x04, 0xe0, 0x00, 0x30, 0x6f, 0x6e, 0x65, -0xfa, 0x04, 0x28, 0x6f, 0x6e, 0xea, 0x02, 0x0f, 0xba, 0x05, -0x04, 0x00, 0x6b, 0x01, 0x14, 0x6e, 0x91, 0x03, 0x03, 0x80, -0x05, 0x08, 0x65, 0x01, 0x03, 0x8c, 0x05, 0x04, 0xb6, 0x06, -0x01, 0x58, 0x01, 0x02, 0x4a, 0x05, 0x91, 0x6f, 0x62, 0x76, -0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x5c, 0x02, 0x08, 0x8d, -0x06, 0x44, 0x74, 0x68, 0x6f, 0x73, 0xcc, 0x01, 0x02, 0x55, -0x00, 0x41, 0x75, 0x72, 0x6e, 0x2c, 0x15, 0x04, 0x10, 0x73, -0x47, 0x01, 0x00, 0xee, 0x01, 0x00, 0xd3, 0x01, 0x02, 0xc1, -0x00, 0x64, 0x6d, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x89, 0x00, -0x08, 0x7c, 0x00, 0x01, 0x95, 0x00, 0x03, 0x28, 0x02, 0x04, -0x93, 0x01, 0x10, 0x64, 0xdd, 0x00, 0x00, 0xd1, 0x02, 0x01, -0x5a, 0x06, 0xd0, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, -0x63, 0x61, 0x6c, 0x6c, 0x79, 0x3b, 0x5d, 0x00, 0x00, 0xd3, -0x04, 0x41, 0x74, 0x69, 0x6d, 0x65, 0x13, 0x05, 0x1f, 0x6e, -0xf9, 0x00, 0x02, 0x10, 0x2c, 0x5e, 0x05, 0x30, 0x68, 0x6f, -0x6c, 0x41, 0x06, 0x10, 0x77, 0xfb, 0x01, 0x12, 0x61, 0x5d, -0x00, 0x10, 0x6f, 0xe9, 0x04, 0x23, 0x75, 0x70, 0x72, 0x03, -0x53, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0xed, 0x03, 0x04, 0x34, -0x03, 0x01, 0xa8, 0x00, 0x02, 0xb7, 0x01, 0xc1, 0x65, 0x00, -0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, -0xa6, 0x05, 0x02, 0x39, 0x03, 0x02, 0xec, 0x01, 0x04, 0xfd, -0x01, 0xb0, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x00, 0x50, -0x72, 0x65, 0x73, 0x6b, 0x06, 0x03, 0xae, 0x01, 0x00, 0x0d, -0x01, 0x00, 0x37, 0x00, 0x0f, 0x31, 0x04, 0x01, 0x04, 0xad, -0x00, 0x00, 0xd7, 0x02, 0x02, 0x31, 0x01, 0x0e, 0x60, 0x03, -0x06, 0xe8, 0x03, 0x08, 0x5b, 0x03, 0x00, 0x95, 0x01, 0x31, -0x28, 0x73, 0x6f, 0x15, 0x03, 0x52, 0x63, 0x74, 0x73, 0x00, -0x61, 0xe3, 0x06, 0x04, 0x63, 0x05, 0x78, 0x74, 0x6f, 0x6e, -0x29, 0x2c, 0x00, 0x70, 0x8a, 0x00, 0x20, 0x73, 0x70, 0x93, -0x04, 0x3f, 0x62, 0x61, 0x72, 0x89, 0x00, 0x02, 0x0e, 0xb6, -0x04, 0xbc, 0x28, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, -0x6c, 0x79, 0x2c, 0x66, 0x00, 0x01, 0x4d, 0x04, 0x04, 0x67, -0x00, 0x00, 0x32, 0x01, 0x13, 0x41, 0x03, 0x03, 0x22, 0x61, -0x63, 0xd8, 0x06, 0x72, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x4e, 0x04, 0x22, 0x73, 0x65, 0xef, 0x02, 0x31, 0x32, -0x2e, 0x31, 0x7a, 0x03, 0x01, 0x57, 0x01, 0x50, 0x61, 0x76, -0x61, 0x69, 0x6c, 0xa3, 0x06, 0x00, 0x3f, 0x00, 0x90, 0x45, -0x76, 0x65, 0x6e, 0x00, 0x55, 0x6e, 0x64, 0x6f, 0x68, 0x02, -0x05, 0x1a, 0x00, 0xa1, 0x2c, 0x00, 0x61, 0x6c, 0x74, 0x68, -0x6f, 0x75, 0x67, 0x68, 0xd8, 0x01, 0x11, 0x6d, 0x75, 0x00, -0x61, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0xe9, 0x04, 0x63, -0x00, 0x63, 0x68, 0x65, 0x61, 0x74, 0x2b, 0x03, 0x20, 0x75, -0x73, 0xe3, 0x06, 0x05, 0xb8, 0x08, 0x66, 0x73, 0x74, 0x65, -0x70, 0x00, 0x6f, 0x98, 0x08, 0x00, 0x9d, 0x00, 0x73, 0x70, -0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0xfe, 0x01, 0x96, 0x6e, -0x6c, 0x79, 0x00, 0x72, 0x65, 0x76, 0x65, 0x61, 0xbd, 0x03, -0x00, 0xad, 0x00, 0x41, 0x71, 0x75, 0x65, 0x73, 0xae, 0x00, -0x60, 0x28, 0x75, 0x6e, 0x6c, 0x69, 0x6b, 0x42, 0x06, 0x23, -0x73, 0x74, 0x0d, 0x07, 0xb2, 0x69, 0x6d, 0x70, 0x6c, 0x65, -0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x14, 0x07, 0x02, 0x53, -0x03, 0x03, 0x46, 0x00, 0x00, 0x07, 0x04, 0x03, 0xe2, 0x02, -0x16, 0x29, 0x78, 0x05, 0x24, 0x74, 0x68, 0xdb, 0x00, 0x10, -0x79, 0x31, 0x07, 0x53, 0x66, 0x61, 0x74, 0x61, 0x6c, 0x3d, -0x02, 0x21, 0x6e, 0x64, 0x0f, 0x09, 0x41, 0x69, 0x6e, 0x75, -0x65, 0xb8, 0x06, 0x01, 0xe4, 0x04, 0x03, 0x71, 0x05, 0x21, -0x69, 0x6b, 0x31, 0x05, 0x0b, 0xb5, 0x00, 0x51, 0x74, 0x72, -0x61, 0x63, 0x6b, 0xaf, 0x00, 0x61, 0x6e, 0x75, 0x6d, 0x62, -0x65, 0x72, 0x70, 0x00, 0x01, 0xfe, 0x02, 0x01, 0x3d, 0x0a, -0x50, 0x69, 0x65, 0x64, 0x00, 0x28, 0x57, 0x00, 0x01, 0x70, -0x00, 0x05, 0x1b, 0x06, 0x12, 0x72, 0x01, 0x08, 0x01, 0x76, -0x06, 0x80, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x29, -0x90, 0x0a, 0x06, 0x33, 0x03, 0x07, 0xdc, 0x07, 0x34, 0x65, -0x6e, 0x64, 0x69, 0x04, 0x01, 0x54, 0x07, 0x05, 0xf6, 0x04, -0x31, 0x77, 0x68, 0x65, 0x05, 0x01, 0x21, 0x6f, 0x72, 0x55, -0x00, 0x02, 0x71, 0x00, 0x12, 0x64, 0xf8, 0x05, 0x00, 0xa6, -0x01, 0x41, 0x74, 0x00, 0x6d, 0x61, 0xa6, 0x06, 0x00, 0xea, -0x03, 0x01, 0x41, 0x06, 0x01, 0xbf, 0x09, 0x14, 0x28, 0x3a, -0x07, 0x10, 0x65, 0xb4, 0x03, 0x41, 0x00, 0x77, 0x61, 0x6e, -0x6b, 0x00, 0x05, 0x49, 0x05, 0x80, 0x66, 0x75, 0x6c, 0x6c, -0x00, 0x6c, 0x61, 0x79, 0x41, 0x00, 0x04, 0x78, 0x00, 0x34, -0x72, 0x69, 0x64, 0x5c, 0x01, 0x0f, 0x79, 0x01, 0x02, 0x02, -0xdb, 0x00, 0x10, 0x73, 0x5f, 0x0a, 0x01, 0x16, 0x04, 0x44, -0x66, 0x74, 0x65, 0x72, 0x02, 0x01, 0x06, 0x70, 0x05, 0x03, -0x0a, 0x09, 0x04, 0xc0, 0x03, 0x30, 0x53, 0x6f, 0x6c, 0x2f, -0x06, 0x60, 0x65, 0x6e, 0x75, 0x00, 0x6f, 0x70, 0x47, 0x00, -0x22, 0x2e, 0x29, 0x54, 0x08, 0x13, 0x32, 0x54, 0x08, 0x93, -0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, -0x08, 0x13, 0x65, 0x28, 0x00, 0x07, 0x92, 0x02, 0x51, 0x00, -0x66, 0x72, 0x6f, 0x6d, 0x4e, 0x00, 0xb3, 0x60, 0x43, 0x75, -0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x27, 0x00, -0x00, 0x6e, 0x02, 0x01, 0x1a, 0x00, 0x52, 0x54, 0x79, 0x70, -0x65, 0x27, 0x69, 0x00, 0xf2, 0x00, 0x61, 0x72, 0x65, 0x3a, -0x00, 0x00, 0x00, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, -0x48, 0x5c, 0x05, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x0b, -0x0c, 0x01, 0x2c, 0x0c, 0x28, 0x69, 0x6e, 0xee, 0x0a, 0x11, -0x4d, 0x98, 0x05, 0x35, 0x00, 0x00, 0x4e, 0xe0, 0x01, 0x09, -0xaa, 0x05, 0x00, 0x32, 0x00, 0x06, 0x5c, 0x02, 0x10, 0x65, -0xcb, 0x01, 0x02, 0x54, 0x06, 0x02, 0x91, 0x0a, 0x73, 0x61, -0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0xce, 0x02, 0x01, 0xec, -0x01, 0x10, 0x2c, 0xb1, 0x01, 0xd5, 0x61, 0x6c, 0x74, 0x65, -0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x21, -0x01, 0xb5, 0x70, 0x75, 0x74, 0x00, 0x61, 0x00, 0x25, 0x00, -0x73, 0x69, 0x67, 0xbe, 0x00, 0x12, 0x65, 0x83, 0x04, 0x03, -0xa5, 0x0c, 0x36, 0x61, 0x73, 0x65, 0x0a, 0x02, 0x02, 0x5f, -0x0a, 0x52, 0x72, 0x72, 0x61, 0x6e, 0x67, 0x92, 0x05, 0x01, -0x51, 0x02, 0x00, 0xfc, 0x0a, 0x24, 0x6f, 0x72, 0x0b, 0x07, -0x06, 0xd4, 0x07, 0x09, 0xb3, 0x00, 0x03, 0x64, 0x05, 0x03, -0xe0, 0x05, 0x71, 0x00, 0x00, 0x42, 0x65, 0x77, 0x61, 0x72, -0x03, 0x01, 0x44, 0x73, 0x65, 0x74, 0x74, 0xa1, 0x04, 0x06, -0xb5, 0x00, 0xe1, 0x00, 0x74, 0x6f, 0x6f, 0x00, 0x68, 0x69, -0x67, 0x68, 0x2e, 0x00, 0x41, 0x74, 0x00, 0xeb, 0x0c, 0x00, -0x0e, 0x00, 0x40, 0x00, 0x64, 0x65, 0x6e, 0x3a, 0x0b, 0x2a, -0x65, 0x73, 0xd1, 0x03, 0x60, 0x6d, 0x61, 0x79, 0x00, 0x73, -0x70, 0xbb, 0x00, 0x31, 0x66, 0x6f, 0x72, 0x2e, 0x0b, 0x64, -0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x0a, 0x61, 0x61, -0x00, 0x73, 0x6f, 0x6c, 0x76, 0xc1, 0x01, 0x02, 0x41, 0x01, -0x31, 0x00, 0x00, 0x45, 0x65, 0x0b, 0x10, 0x20, 0x2f, 0x01, -0x60, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0xa7, 0x01, 0x00, -0x0f, 0x03, 0x01, 0x4e, 0x01, 0x03, 0xd2, 0x01, 0x50, 0x69, -0x73, 0x00, 0x65, 0x6e, 0x37, 0x00, 0x00, 0x57, 0x03, 0x13, -0x73, 0x07, 0x07, 0x15, 0x62, 0xe3, 0x0b, 0x23, 0x29, 0x2c, -0xaf, 0x01, 0x01, 0x1a, 0x01, 0x08, 0xb7, 0x0b, 0x02, 0x4a, -0x01, 0x33, 0x74, 0x69, 0x72, 0xff, 0x00, 0x00, 0x6e, 0x01, -0x12, 0x62, 0xec, 0x02, 0x13, 0x79, 0x90, 0x0b, 0x61, 0x64, -0x00, 0x73, 0x74, 0x61, 0x72, 0xfc, 0x00, 0x05, 0x55, 0x02, -0x63, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x9a, 0x06, 0x01, -0xaf, 0x05, 0x05, 0xd0, 0x04, 0x63, 0x70, 0x72, 0x65, 0x66, -0x65, 0x72, 0x7d, 0x05, 0x51, 0x73, 0x6b, 0x69, 0x65, 0x72, -0x5a, 0x00, 0x15, 0x73, 0x5e, 0x0c, 0x01, 0xfc, 0x0c, 0x0f, -0xa7, 0x04, 0x04, 0x04, 0xf1, 0x01, 0x41, 0x73, 0x77, 0x69, -0x74, 0x48, 0x08, 0x15, 0x66, 0xe7, 0x00, 0x50, 0x69, 0x6f, -0x6e, 0x2e, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf0, 0x1c, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x63, 0x6f, +0x76, 0x65, 0x72, 0x65, 0x64, 0x00, 0x73, 0x71, 0x75, 0x61, +0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x19, +0x00, 0xf0, 0x02, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x63, +0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6d, 0x69, 0x6e, +0x1d, 0x00, 0xf2, 0x03, 0x62, 0x75, 0x74, 0x00, 0x79, 0x6f, +0x75, 0x00, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x00, 0x6b, 0x6e, +0x6f, 0x77, 0x28, 0x00, 0x10, 0x2e, 0x5b, 0x00, 0xe1, 0x72, +0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, +0x00, 0x75, 0x6e, 0x59, 0x00, 0x63, 0x00, 0x65, 0x76, 0x65, +0x72, 0x79, 0x5d, 0x00, 0x03, 0x53, 0x00, 0x85, 0x64, 0x6f, +0x65, 0x73, 0x00, 0x6e, 0x6f, 0x74, 0x5c, 0x00, 0x11, 0x61, +0x5e, 0x00, 0x41, 0x2e, 0x00, 0x49, 0x66, 0x5c, 0x00, 0x04, +0x3b, 0x00, 0x14, 0x61, 0x37, 0x00, 0x03, 0x28, 0x00, 0x33, +0x69, 0x6e, 0x67, 0x2b, 0x00, 0x11, 0x2c, 0x28, 0x00, 0x3f, +0x6c, 0x6f, 0x73, 0x35, 0x00, 0x08, 0x0f, 0x6c, 0x00, 0x0a, +0x02, 0x41, 0x00, 0x00, 0x27, 0x00, 0xd2, 0x74, 0x6f, 0x6c, +0x64, 0x00, 0x68, 0x6f, 0x77, 0x00, 0x6d, 0x61, 0x6e, 0x79, +0xe6, 0x00, 0x17, 0x00, 0x74, 0x00, 0xf0, 0x0d, 0x65, 0x64, +0x00, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x00, 0x74, 0x68, +0x65, 0x00, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x73, 0x75, +0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x90, 0x00, 0x03, 0x36, +0x01, 0xf0, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, +0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x6e, 0x65, 0x65, +0x64, 0x76, 0x00, 0xf0, 0x1a, 0x00, 0x69, 0x6e, 0x74, 0x72, +0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x00, +0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x73, 0x65, +0x64, 0x00, 0x62, 0x79, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, +0x77, 0x73, 0x2c, 0x00, 0x69, 0x74, 0x34, 0x01, 0x71, 0x70, +0x65, 0x72, 0x68, 0x61, 0x70, 0x73, 0x68, 0x00, 0xa2, 0x73, +0x69, 0x6e, 0x67, 0x6c, 0x65, 0x00, 0x62, 0x65, 0x73, 0x64, +0x01, 0xf2, 0x01, 0x6e, 0x00, 0x64, 0x65, 0x73, 0x6b, 0x74, +0x6f, 0x70, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x67, +0x00, 0xc5, 0x69, 0x6e, 0x00, 0x65, 0x78, 0x69, 0x73, 0x74, +0x65, 0x6e, 0x63, 0x65, 0x81, 0x00, 0x70, 0x76, 0x65, 0x72, +0x73, 0x69, 0x6f, 0x6e, 0xc1, 0x01, 0xf1, 0x17, 0x69, 0x74, +0x00, 0x68, 0x61, 0x73, 0x00, 0x61, 0x6e, 0x00, 0x75, 0x6e, +0x75, 0x73, 0x75, 0x61, 0x6c, 0x00, 0x70, 0x72, 0x6f, 0x70, +0x65, 0x72, 0x74, 0x79, 0x2e, 0x00, 0x42, 0x79, 0x00, 0x64, +0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x80, 0x00, 0xf1, 0x02, +0x77, 0x69, 0x6c, 0x6c, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, +0x61, 0x74, 0x65, 0x00, 0x69, 0x74, 0x73, 0x0a, 0x01, 0x50, +0x00, 0x70, 0x6f, 0x73, 0x69, 0xbc, 0x00, 0x10, 0x73, 0x6c, +0x00, 0xc1, 0x73, 0x75, 0x63, 0x68, 0x00, 0x61, 0x00, 0x77, +0x61, 0x79, 0x00, 0x61, 0xe3, 0x01, 0x40, 0x65, 0x6e, 0x73, +0x75, 0x42, 0x01, 0x22, 0x68, 0x61, 0x14, 0x02, 0x10, 0x6e, +0xec, 0x01, 0x01, 0xfd, 0x00, 0x00, 0x1e, 0x00, 0xb3, 0x67, +0x75, 0x65, 0x73, 0x73, 0x00, 0x77, 0x68, 0x65, 0x72, 0x65, +0x75, 0x01, 0x41, 0x00, 0x69, 0x73, 0x3a, 0x29, 0x00, 0x01, +0x6e, 0x00, 0xe0, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x00, +0x62, 0x65, 0x00, 0x61, 0x62, 0x6c, 0x65, 0x32, 0x00, 0x50, +0x64, 0x65, 0x64, 0x75, 0x63, 0x7e, 0x00, 0x01, 0x83, 0x02, +0x76, 0x68, 0x6f, 0x77, 0x2e, 0x00, 0x53, 0x6f, 0x31, 0x00, +0x01, 0x5f, 0x00, 0x10, 0x2c, 0x7c, 0x00, 0xa0, 0x63, 0x61, +0x6e, 0x00, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x98, 0x00, +0x54, 0x6f, 0x74, 0x68, 0x65, 0x72, 0xf8, 0x00, 0x60, 0x73, +0x2c, 0x00, 0x67, 0x65, 0x74, 0x4e, 0x00, 0x00, 0x48, 0x01, +0x60, 0x6c, 0x61, 0x73, 0x74, 0x00, 0x66, 0x99, 0x02, 0x03, +0xa8, 0x01, 0x82, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x64, 0x69, +0x73, 0x2c, 0x02, 0x01, 0xba, 0x00, 0x12, 0x74, 0xa2, 0x00, +0x00, 0xc9, 0x00, 0x23, 0x77, 0x6f, 0x01, 0x02, 0x45, 0x6c, +0x65, 0x66, 0x74, 0xeb, 0x02, 0x01, 0x30, 0x03, 0x21, 0x6e, +0x6f, 0xf9, 0x00, 0x21, 0x6f, 0x66, 0x90, 0x01, 0x00, 0xfa, +0x01, 0x41, 0x66, 0x6f, 0x72, 0x00, 0x00, 0x01, 0x02, 0xe3, +0x00, 0x40, 0x74, 0x68, 0x65, 0x79, 0x46, 0x00, 0x00, 0x89, +0x01, 0x43, 0x31, 0x32, 0x2e, 0x31, 0x86, 0x03, 0x20, 0x63, +0x6f, 0x03, 0x02, 0x39, 0x6c, 0x73, 0x20, 0x21, 0x02, 0x00, +0xef, 0x01, 0x33, 0x6c, 0x61, 0x79, 0x5d, 0x02, 0x01, 0xab, +0x00, 0x41, 0x6d, 0x6f, 0x75, 0x73, 0x3d, 0x00, 0x03, 0xd0, +0x02, 0x00, 0x83, 0x00, 0x71, 0x2d, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0x00, 0xb6, 0x02, 0x0a, 0xa7, 0x03, 0x06, 0xb5, 0x01, +0x24, 0x62, 0x65, 0xfb, 0x02, 0x27, 0x65, 0x64, 0x3f, 0x00, +0x10, 0x72, 0xaa, 0x02, 0x0f, 0x40, 0x00, 0x11, 0x40, 0x70, +0x6c, 0x61, 0x63, 0xa1, 0x01, 0x43, 0x66, 0x6c, 0x61, 0x67, +0x34, 0x03, 0x95, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, +0x65, 0x73, 0x21, 0x01, 0x04, 0x54, 0x03, 0x10, 0x69, 0xb0, +0x01, 0x42, 0x6c, 0x69, 0x65, 0x76, 0xe3, 0x01, 0x25, 0x62, +0x65, 0xbb, 0x03, 0x15, 0x4c, 0xaf, 0x00, 0x00, 0x1c, 0x01, +0x02, 0x68, 0x03, 0x35, 0x61, 0x72, 0x6b, 0x71, 0x00, 0x03, +0xc3, 0x01, 0x25, 0x6f, 0x74, 0xa9, 0x03, 0x32, 0x69, 0x74, +0x2c, 0x44, 0x01, 0x51, 0x61, 0x66, 0x65, 0x74, 0x79, 0x40, +0x04, 0x01, 0xd9, 0x01, 0x08, 0xba, 0x00, 0x30, 0x61, 0x67, +0x61, 0x7a, 0x03, 0x83, 0x6f, 0x00, 0x72, 0x65, 0x6d, 0x6f, +0x76, 0x65, 0x55, 0x00, 0x02, 0xb4, 0x00, 0x11, 0x64, 0x00, +0x03, 0x4f, 0x72, 0x72, 0x6f, 0x72, 0x36, 0x01, 0x07, 0x00, +0xfa, 0x02, 0x0f, 0xf9, 0x00, 0x05, 0x81, 0x60, 0x63, 0x6c, +0x65, 0x61, 0x72, 0x00, 0x61, 0xcb, 0x03, 0x17, 0x27, 0xe6, +0x00, 0x12, 0x2e, 0xa9, 0x01, 0x98, 0x6d, 0x65, 0x61, 0x6e, +0x73, 0x3a, 0x00, 0x69, 0x66, 0x01, 0x01, 0x00, 0x50, 0x03, +0x61, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x05, 0x03, 0x01, +0x34, 0x04, 0x00, 0x3a, 0x01, 0x19, 0x73, 0x15, 0x04, 0x20, +0x69, 0x74, 0x1d, 0x00, 0x00, 0xc8, 0x02, 0x52, 0x68, 0x6f, +0x75, 0x6c, 0x64, 0x42, 0x02, 0x03, 0x41, 0x05, 0x81, 0x74, +0x68, 0x65, 0x6e, 0x00, 0x61, 0x6c, 0x6c, 0x56, 0x00, 0x0b, +0x7c, 0x05, 0x41, 0x00, 0x6e, 0x65, 0x78, 0xbc, 0x02, 0x23, +0x69, 0x74, 0x8b, 0x01, 0x00, 0x74, 0x00, 0x00, 0x35, 0x01, +0x00, 0x64, 0x00, 0x3e, 0x67, 0x65, 0x64, 0xf3, 0x01, 0x01, +0x23, 0x03, 0x41, 0x6f, 0x6e, 0x63, 0x65, 0xff, 0x00, 0x00, +0xa9, 0x04, 0x11, 0x6b, 0x0a, 0x00, 0x01, 0x9a, 0x05, 0x01, +0x03, 0x03, 0x43, 0x6f, 0x63, 0x61, 0x74, 0x11, 0x04, 0x04, +0x77, 0x00, 0x04, 0xe6, 0x04, 0x00, 0xb0, 0x00, 0x05, 0x31, +0x05, 0x02, 0x13, 0x05, 0x10, 0x63, 0x34, 0x01, 0x20, 0x73, +0x65, 0x4a, 0x00, 0x61, 0x73, 0x00, 0x66, 0x75, 0x6e, 0x63, +0x3c, 0x00, 0x00, 0x46, 0x04, 0x00, 0xcd, 0x00, 0x41, 0x72, +0x74, 0x63, 0x75, 0xa1, 0x00, 0x41, 0x61, 0x76, 0x6f, 0x69, +0xd8, 0x00, 0x00, 0xef, 0x00, 0x32, 0x74, 0x6f, 0x00, 0x73, +0x01, 0x92, 0x6f, 0x6e, 0x00, 0x65, 0x61, 0x63, 0x68, 0x00, +0x6f, 0x34, 0x01, 0x33, 0x72, 0x65, 0x6d, 0xb6, 0x05, 0x04, +0xe0, 0x00, 0x30, 0x6f, 0x6e, 0x65, 0xfa, 0x04, 0x28, 0x6f, +0x6e, 0xea, 0x02, 0x0f, 0xba, 0x05, 0x04, 0x00, 0x6b, 0x01, +0x14, 0x6e, 0x91, 0x03, 0x03, 0x80, 0x05, 0x08, 0x65, 0x01, +0x03, 0x8c, 0x05, 0x04, 0xb6, 0x06, 0x01, 0x58, 0x01, 0x02, +0x4a, 0x05, 0x91, 0x6f, 0x62, 0x76, 0x69, 0x6f, 0x75, 0x73, +0x6c, 0x79, 0x5c, 0x02, 0x08, 0x8d, 0x06, 0x44, 0x74, 0x68, +0x6f, 0x73, 0xcc, 0x01, 0x02, 0x55, 0x00, 0x41, 0x75, 0x72, +0x6e, 0x2c, 0x15, 0x04, 0x10, 0x73, 0x47, 0x01, 0x00, 0xee, +0x01, 0x00, 0xd3, 0x01, 0x02, 0xc1, 0x00, 0x64, 0x6d, 0x00, +0x61, 0x6c, 0x73, 0x6f, 0x89, 0x00, 0x08, 0x7c, 0x00, 0x01, +0x95, 0x00, 0x03, 0x28, 0x02, 0x04, 0x93, 0x01, 0x10, 0x64, +0xdd, 0x00, 0x00, 0xd1, 0x02, 0x01, 0x5a, 0x06, 0xd0, 0x75, +0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, +0x79, 0x3b, 0x5d, 0x00, 0x00, 0xd3, 0x04, 0x41, 0x74, 0x69, +0x6d, 0x65, 0x13, 0x05, 0x1f, 0x6e, 0xf9, 0x00, 0x02, 0x10, +0x2c, 0x5e, 0x05, 0x30, 0x68, 0x6f, 0x6c, 0x41, 0x06, 0x10, +0x77, 0xfb, 0x01, 0x12, 0x61, 0x5d, 0x00, 0x10, 0x6f, 0xe9, +0x04, 0x23, 0x75, 0x70, 0x72, 0x03, 0x53, 0x65, 0x78, 0x70, +0x6c, 0x6f, 0xed, 0x03, 0x04, 0x34, 0x03, 0x01, 0xa8, 0x00, +0x02, 0xb7, 0x01, 0xc1, 0x65, 0x00, 0x63, 0x75, 0x72, 0x73, +0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xa6, 0x05, 0x02, 0x39, +0x03, 0x02, 0xec, 0x01, 0x04, 0xfd, 0x01, 0xb0, 0x66, 0x69, +0x65, 0x6c, 0x64, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x6b, +0x06, 0x03, 0xae, 0x01, 0x00, 0x0d, 0x01, 0x00, 0x37, 0x00, +0x0f, 0x31, 0x04, 0x01, 0x04, 0xad, 0x00, 0x00, 0xd7, 0x02, +0x02, 0x31, 0x01, 0x0e, 0x60, 0x03, 0x06, 0xe8, 0x03, 0x08, +0x5b, 0x03, 0x00, 0x95, 0x01, 0x31, 0x28, 0x73, 0x6f, 0x15, +0x03, 0x52, 0x63, 0x74, 0x73, 0x00, 0x61, 0xe3, 0x06, 0x04, +0x63, 0x05, 0x78, 0x74, 0x6f, 0x6e, 0x29, 0x2c, 0x00, 0x70, +0x8a, 0x00, 0x20, 0x73, 0x70, 0x93, 0x04, 0x3f, 0x62, 0x61, +0x72, 0x89, 0x00, 0x02, 0x0e, 0xb6, 0x04, 0xbc, 0x28, 0x73, +0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x6c, 0x79, 0x2c, 0x66, +0x00, 0x01, 0x4d, 0x04, 0x04, 0x67, 0x00, 0x00, 0x32, 0x01, +0x13, 0x41, 0x03, 0x03, 0x22, 0x61, 0x63, 0xd8, 0x06, 0x72, +0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x4e, 0x04, 0x22, +0x73, 0x65, 0xef, 0x02, 0x31, 0x32, 0x2e, 0x31, 0x7a, 0x03, +0x01, 0x57, 0x01, 0x50, 0x61, 0x76, 0x61, 0x69, 0x6c, 0xa3, +0x06, 0x00, 0x3f, 0x00, 0x90, 0x45, 0x76, 0x65, 0x6e, 0x00, +0x55, 0x6e, 0x64, 0x6f, 0x68, 0x02, 0x05, 0x1a, 0x00, 0xa1, +0x2c, 0x00, 0x61, 0x6c, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, +0xd8, 0x01, 0x11, 0x6d, 0x75, 0x00, 0x61, 0x63, 0x6f, 0x6e, +0x73, 0x69, 0x64, 0xe9, 0x04, 0x63, 0x00, 0x63, 0x68, 0x65, +0x61, 0x74, 0x2b, 0x03, 0x20, 0x75, 0x73, 0xe3, 0x06, 0x05, +0xb8, 0x08, 0x66, 0x73, 0x74, 0x65, 0x70, 0x00, 0x6f, 0x98, +0x08, 0x00, 0x9d, 0x00, 0x73, 0x70, 0x72, 0x6f, 0x67, 0x72, +0x61, 0x6d, 0xfe, 0x01, 0x96, 0x6e, 0x6c, 0x79, 0x00, 0x72, +0x65, 0x76, 0x65, 0x61, 0xbd, 0x03, 0x00, 0xad, 0x00, 0x41, +0x71, 0x75, 0x65, 0x73, 0xae, 0x00, 0x60, 0x28, 0x75, 0x6e, +0x6c, 0x69, 0x6b, 0x42, 0x06, 0x23, 0x73, 0x74, 0x0d, 0x07, +0xb2, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, +0x61, 0x74, 0x14, 0x07, 0x02, 0x53, 0x03, 0x03, 0x46, 0x00, +0x00, 0x07, 0x04, 0x03, 0xe2, 0x02, 0x16, 0x29, 0x78, 0x05, +0x24, 0x74, 0x68, 0xdb, 0x00, 0x10, 0x79, 0x31, 0x07, 0x53, +0x66, 0x61, 0x74, 0x61, 0x6c, 0x3d, 0x02, 0x21, 0x6e, 0x64, +0x0f, 0x09, 0x41, 0x69, 0x6e, 0x75, 0x65, 0xb8, 0x06, 0x01, +0xe4, 0x04, 0x03, 0x71, 0x05, 0x21, 0x69, 0x6b, 0x31, 0x05, +0x0b, 0xb5, 0x00, 0x51, 0x74, 0x72, 0x61, 0x63, 0x6b, 0xaf, +0x00, 0x61, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x70, 0x00, +0x01, 0xfe, 0x02, 0x01, 0x3d, 0x0a, 0x50, 0x69, 0x65, 0x64, +0x00, 0x28, 0x57, 0x00, 0x01, 0x70, 0x00, 0x05, 0x1b, 0x06, +0x12, 0x72, 0x01, 0x08, 0x01, 0x76, 0x06, 0x80, 0x63, 0x6f, +0x75, 0x6e, 0x74, 0x65, 0x72, 0x29, 0x90, 0x0a, 0x06, 0x33, +0x03, 0x07, 0xdc, 0x07, 0x34, 0x65, 0x6e, 0x64, 0x69, 0x04, +0x01, 0x54, 0x07, 0x05, 0xf6, 0x04, 0x31, 0x77, 0x68, 0x65, +0x05, 0x01, 0x21, 0x6f, 0x72, 0x55, 0x00, 0x02, 0x71, 0x00, +0x12, 0x64, 0xf8, 0x05, 0x00, 0xa6, 0x01, 0x41, 0x74, 0x00, +0x6d, 0x61, 0xa6, 0x06, 0x00, 0xea, 0x03, 0x01, 0x41, 0x06, +0x01, 0xbf, 0x09, 0x14, 0x28, 0x3a, 0x07, 0x10, 0x65, 0xb4, +0x03, 0x41, 0x00, 0x77, 0x61, 0x6e, 0x6b, 0x00, 0x05, 0x49, +0x05, 0x80, 0x66, 0x75, 0x6c, 0x6c, 0x00, 0x6c, 0x61, 0x79, +0x41, 0x00, 0x04, 0x78, 0x00, 0x34, 0x72, 0x69, 0x64, 0x5c, +0x01, 0x0f, 0x79, 0x01, 0x02, 0x02, 0xdb, 0x00, 0x10, 0x73, +0x5f, 0x0a, 0x01, 0x16, 0x04, 0x44, 0x66, 0x74, 0x65, 0x72, +0x02, 0x01, 0x06, 0x70, 0x05, 0x03, 0x0a, 0x09, 0x04, 0xc0, +0x03, 0x30, 0x53, 0x6f, 0x6c, 0x2f, 0x06, 0x60, 0x65, 0x6e, +0x75, 0x00, 0x6f, 0x70, 0x47, 0x00, 0x22, 0x2e, 0x29, 0x54, +0x08, 0x13, 0x32, 0x54, 0x08, 0x93, 0x70, 0x61, 0x72, 0x61, +0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x08, 0x13, 0x65, 0x28, +0x00, 0x07, 0x92, 0x02, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, +0x4e, 0x00, 0xb3, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0x27, 0x00, 0x00, 0x6e, 0x02, 0x01, +0x1a, 0x00, 0x52, 0x54, 0x79, 0x70, 0x65, 0x27, 0x69, 0x00, +0xf2, 0x00, 0x61, 0x72, 0x65, 0x3a, 0x00, 0x00, 0x00, 0x57, +0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x5c, 0x05, 0x51, +0x00, 0x00, 0x53, 0x69, 0x7a, 0x0b, 0x0c, 0x01, 0x2c, 0x0c, +0x28, 0x69, 0x6e, 0xee, 0x0a, 0x11, 0x4d, 0x98, 0x05, 0x35, +0x00, 0x00, 0x4e, 0xe0, 0x01, 0x09, 0xaa, 0x05, 0x00, 0x32, +0x00, 0x06, 0x5c, 0x02, 0x10, 0x65, 0xcb, 0x01, 0x02, 0x54, +0x06, 0x02, 0x91, 0x0a, 0x73, 0x61, 0x62, 0x73, 0x6f, 0x6c, +0x75, 0x74, 0xce, 0x02, 0x01, 0xec, 0x01, 0x10, 0x2c, 0xb1, +0x01, 0xd5, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, +0x69, 0x76, 0x65, 0x6c, 0x79, 0x21, 0x01, 0xb5, 0x70, 0x75, +0x74, 0x00, 0x61, 0x00, 0x25, 0x00, 0x73, 0x69, 0x67, 0xbe, +0x00, 0x12, 0x65, 0x83, 0x04, 0x03, 0xa5, 0x0c, 0x36, 0x61, +0x73, 0x65, 0x0a, 0x02, 0x02, 0x5f, 0x0a, 0x52, 0x72, 0x72, +0x61, 0x6e, 0x67, 0x92, 0x05, 0x01, 0x51, 0x02, 0x00, 0xfc, +0x0a, 0x24, 0x6f, 0x72, 0x0b, 0x07, 0x06, 0xd4, 0x07, 0x09, +0xb3, 0x00, 0x03, 0x64, 0x05, 0x03, 0xe0, 0x05, 0x71, 0x00, +0x00, 0x42, 0x65, 0x77, 0x61, 0x72, 0x03, 0x01, 0x44, 0x73, +0x65, 0x74, 0x74, 0xa1, 0x04, 0x06, 0xb5, 0x00, 0xe1, 0x00, +0x74, 0x6f, 0x6f, 0x00, 0x68, 0x69, 0x67, 0x68, 0x2e, 0x00, +0x41, 0x74, 0x00, 0xeb, 0x0c, 0x00, 0x0e, 0x00, 0x40, 0x00, +0x64, 0x65, 0x6e, 0x3a, 0x0b, 0x2a, 0x65, 0x73, 0xd1, 0x03, +0x60, 0x6d, 0x61, 0x79, 0x00, 0x73, 0x70, 0xbb, 0x00, 0x31, +0x66, 0x6f, 0x72, 0x2e, 0x0b, 0x64, 0x73, 0x65, 0x61, 0x72, +0x63, 0x68, 0x50, 0x0a, 0x61, 0x61, 0x00, 0x73, 0x6f, 0x6c, +0x76, 0xc1, 0x01, 0x02, 0x41, 0x01, 0x31, 0x00, 0x00, 0x45, +0x65, 0x0b, 0x10, 0x20, 0x2f, 0x01, 0x60, 0x62, 0x69, 0x6c, +0x69, 0x74, 0x79, 0xa7, 0x01, 0x00, 0x0f, 0x03, 0x01, 0x4e, +0x01, 0x03, 0xd2, 0x01, 0x50, 0x69, 0x73, 0x00, 0x65, 0x6e, +0x37, 0x00, 0x00, 0x57, 0x03, 0x13, 0x73, 0x07, 0x07, 0x15, +0x62, 0xe3, 0x0b, 0x23, 0x29, 0x2c, 0xaf, 0x01, 0x01, 0x1a, +0x01, 0x08, 0xb7, 0x0b, 0x02, 0x4a, 0x01, 0x33, 0x74, 0x69, +0x72, 0xff, 0x00, 0x00, 0x6e, 0x01, 0x12, 0x62, 0xec, 0x02, +0x13, 0x79, 0x90, 0x0b, 0x61, 0x64, 0x00, 0x73, 0x74, 0x61, +0x72, 0xfc, 0x00, 0x05, 0x55, 0x02, 0x63, 0x69, 0x6e, 0x69, +0x74, 0x69, 0x61, 0x9a, 0x06, 0x01, 0xaf, 0x05, 0x05, 0xd0, +0x04, 0x63, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x7d, 0x05, +0x51, 0x73, 0x6b, 0x69, 0x65, 0x72, 0x5a, 0x00, 0x15, 0x73, +0x5e, 0x0c, 0x01, 0xfc, 0x0c, 0x0f, 0xa7, 0x04, 0x04, 0x04, +0xf1, 0x01, 0x41, 0x73, 0x77, 0x69, 0x74, 0x48, 0x08, 0x15, +0x66, 0xe7, 0x00, 0x50, 0x69, 0x6f, 0x6e, 0x2e, 0x00, }; -const unsigned short help_text_len = 3796; -const unsigned short help_text_words = 731; +const unsigned short help_text_len = 3814; +const unsigned short help_text_words = 732; const char quick_help_text[] = "Find all the mines without treading on any of them."; diff --git a/apps/plugins/puzzles/help/mosaic.c b/apps/plugins/puzzles/help/mosaic.c new file mode 100644 index 0000000000..835de1898d --- /dev/null +++ b/apps/plugins/puzzles/help/mosaic.c @@ -0,0 +1,150 @@ +/* auto-generated on Jul 22 2024 by genhelp.sh */ +/* help text is compressed using LZ4; see compress.c for details */ +/* DO NOT EDIT! */ + +#include "lib/display_text.h" + +struct style_text help_text_style[] = { + { 0, TEXT_CENTER | C_RED }, + { 43, TEXT_UNDERLINE }, + { 105, TEXT_CENTER | C_RED }, + { 223, TEXT_CENTER | C_RED }, + { 240, TEXT_UNDERLINE }, + { 241, TEXT_UNDERLINE }, + { 251, TEXT_UNDERLINE }, + LAST_STYLE_ITEM +}; + +/* orig 1673 comp 1259 ratio 0.75254 level 10 saved 414 */ +const char help_text[] = { +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0x34, 0x32, 0x3a, 0x20, 0x4d, 0x6f, 0x73, 0x61, 0x69, 0x63, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x3a, 0x00, 0x00, 0x00, +0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, +0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, +0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x79, +0x6f, 0x75, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x63, 0x6f, +0x6c, 0x6f, 0x75, 0x72, 0x00, 0x65, 0x69, 0x74, 0x68, 0x65, +0x72, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x00, 0x6f, 0x72, +0x26, 0x00, 0xa4, 0x74, 0x65, 0x2e, 0x00, 0x00, 0x00, 0x53, +0x6f, 0x6d, 0x65, 0x3d, 0x00, 0xf2, 0x0c, 0x00, 0x63, 0x6f, +0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x63, 0x6c, 0x75, 0x65, +0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x00, +0x45, 0x61, 0x63, 0x68, 0x13, 0x00, 0x51, 0x74, 0x65, 0x6c, +0x6c, 0x73, 0x5c, 0x00, 0x24, 0x74, 0x68, 0x21, 0x00, 0x00, +0x7d, 0x00, 0x02, 0x57, 0x00, 0x04, 0x46, 0x00, 0x21, 0x69, +0x6e, 0x1f, 0x00, 0xf1, 0x07, 0x33, 0x2a, 0x33, 0x00, 0x72, +0x65, 0x67, 0x69, 0x6f, 0x6e, 0x00, 0x73, 0x75, 0x72, 0x72, +0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x1b, 0x00, 0x01, +0x4d, 0x00, 0x7a, 0x2d, 0x00, 0x69, 0x6e, 0x63, 0x6c, 0x75, +0x15, 0x00, 0x02, 0x44, 0x00, 0x70, 0x00, 0x69, 0x74, 0x73, +0x65, 0x6c, 0x66, 0xa0, 0x00, 0xf0, 0x0d, 0x54, 0x68, 0x69, +0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x69, 0x73, 0x00, +0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x00, +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x6a, 0x00, 0x11, 0x6f, 0xd8, +0x00, 0xf2, 0x02, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x73, 0x00, 0x61, 0x73, 0x3a, 0x00, 0x41, 0x72, 0x74, +0x44, 0x01, 0xf0, 0x0e, 0x6f, 0x2c, 0x00, 0x43, 0x6f, 0x75, +0x6e, 0x74, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x44, 0x61, 0x72, +0x6b, 0x65, 0x6e, 0x2c, 0x00, 0x43, 0x75, 0x65, 0x6e, 0x74, +0x61, 0x00, 0x59, 0xfb, 0x00, 0xf3, 0x01, 0x62, 0x72, 0x65, +0x61, 0x2c, 0x00, 0x46, 0x69, 0x6c, 0x6c, 0x2d, 0x61, 0x2d, +0x50, 0x69, 0x78, 0x0c, 0x00, 0xf0, 0x0a, 0x49, 0x6e, 0x2c, +0x00, 0x4b, 0x6f, 0x6d, 0x73, 0x75, 0x00, 0x4b, 0x61, 0x72, +0x61, 0x6c, 0x61, 0x2c, 0x00, 0x4d, 0x61, 0x67, 0x69, 0x70, +0x69, 0x63, 0x09, 0x00, 0x85, 0x6a, 0x69, 0x70, 0x69, 0x6b, +0x75, 0x2c, 0x00, 0x63, 0x00, 0x01, 0x09, 0x00, 0x10, 0x6b, +0x08, 0x00, 0xf4, 0x0d, 0x7a, 0x61, 0x69, 0x65, 0x6b, 0x2c, +0x00, 0x4e, 0x61, 0x6d, 0x70, 0x72, 0x65, 0x00, 0x50, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x00, 0x4e, 0x75, 0x72, 0x69, +0x65, 0x2d, 0x0e, 0x00, 0x62, 0x4f, 0x65, 0x6b, 0x61, 0x6b, +0x69, 0x6d, 0x00, 0x81, 0x56, 0x6f, 0x69, 0x73, 0x69, 0x6d, +0x61, 0x67, 0x8a, 0x01, 0x02, 0x50, 0x00, 0x32, 0x00, 0x77, +0x61, 0x88, 0x01, 0xe0, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, +0x64, 0x00, 0x74, 0x6f, 0x00, 0x74, 0x68, 0x69, 0x14, 0x00, +0x50, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x4f, 0x01, 0xf2, 0x01, +0x62, 0x79, 0x00, 0x44, 0x69, 0x64, 0x69, 0x00, 0x4b, 0x6f, +0x68, 0x65, 0x6e, 0x2e, 0x00, 0x43, 0xe3, 0x01, 0x51, 0x64, +0x65, 0x73, 0x69, 0x67, 0x1d, 0x00, 0xf0, 0x0a, 0x4d, 0x69, +0x63, 0x68, 0x61, 0x6c, 0x00, 0x53, 0x68, 0x6f, 0x6d, 0x65, +0x72, 0x2e, 0x00, 0x54, 0x68, 0x65, 0x00, 0x69, 0x6d, 0x70, +0x6c, 0x65, 0x6d, 0xf9, 0x00, 0x01, 0x42, 0x00, 0xf2, 0x1b, +0x69, 0x73, 0x00, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x6c, 0x79, +0x00, 0x62, 0x61, 0x73, 0x65, 0x64, 0x00, 0x6f, 0x6e, 0x00, +0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, +0x2f, 0x6d, 0x6f, 0x72, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, +0x6d, 0x2f, 0x96, 0x00, 0x00, 0xa0, 0x00, 0x44, 0x34, 0x32, +0x2e, 0x31, 0x9c, 0x02, 0x01, 0xa1, 0x00, 0x40, 0x6f, 0x6c, +0x73, 0x20, 0xa2, 0x01, 0x63, 0x6f, 0x00, 0x70, 0x6c, 0x61, +0x79, 0xc0, 0x00, 0x71, 0x2c, 0x00, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0xd2, 0x01, 0x50, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0xa5, +0x01, 0x14, 0x61, 0xd8, 0x01, 0x81, 0x74, 0x6f, 0x00, 0x63, +0x68, 0x61, 0x6e, 0x67, 0xe2, 0x01, 0x03, 0x9c, 0x02, 0x71, +0x2e, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x37, 0x00, 0x00, +0x0c, 0x02, 0x84, 0x61, 0x6e, 0x00, 0x65, 0x6d, 0x70, 0x74, +0x79, 0x34, 0x00, 0xc2, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x74, +0x75, 0x72, 0x6e, 0x00, 0x69, 0x74, 0x6a, 0x02, 0x11, 0x2c, +0xd0, 0x01, 0x47, 0x72, 0x69, 0x67, 0x68, 0x37, 0x00, 0x09, +0x27, 0x00, 0x03, 0xdf, 0x02, 0x42, 0x4b, 0x65, 0x65, 0x70, +0x90, 0x00, 0x04, 0x65, 0x02, 0x10, 0x73, 0x4a, 0x02, 0x61, +0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x8d, 0x00, 0xc1, 0x79, +0x63, 0x6c, 0x65, 0x00, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, +0x68, 0x21, 0x00, 0xf2, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x65, +0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x00, +0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x00, 0x66, 0x6f, 0x72, +0x3f, 0x00, 0x01, 0x93, 0x00, 0x00, 0x0e, 0x01, 0x21, 0x49, +0x66, 0x08, 0x03, 0x60, 0x68, 0x6f, 0x6c, 0x64, 0x00, 0x64, +0x8c, 0x02, 0x06, 0xf1, 0x00, 0x03, 0x5f, 0x00, 0x00, 0xa4, +0x00, 0x51, 0x64, 0x72, 0x61, 0x67, 0x2c, 0x29, 0x00, 0x34, +0x63, 0x61, 0x6e, 0x8c, 0x03, 0xa1, 0x6d, 0x75, 0x6c, 0x74, +0x69, 0x70, 0x6c, 0x65, 0x00, 0x63, 0x4f, 0x03, 0x02, 0x20, +0x01, 0x71, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x00, 0x61, 0xe1, +0x01, 0x13, 0x2e, 0xe8, 0x03, 0x00, 0x34, 0x00, 0x50, 0x61, +0x6c, 0x73, 0x6f, 0x00, 0x56, 0x00, 0x01, 0x23, 0x03, 0xa0, +0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, +0xbe, 0x00, 0x61, 0x6d, 0x6f, 0x76, 0x65, 0x00, 0x61, 0x5a, +0x03, 0x01, 0x1f, 0x00, 0x00, 0x0c, 0x04, 0x74, 0x2e, 0x00, +0x50, 0x72, 0x65, 0x73, 0x73, 0xf0, 0x00, 0x21, 0x72, 0x65, +0x13, 0x01, 0x82, 0x6f, 0x72, 0x00, 0x73, 0x70, 0x61, 0x63, +0x65, 0x3b, 0x00, 0x06, 0x2b, 0x01, 0x0c, 0x6c, 0x01, 0x0a, +0x20, 0x04, 0x50, 0x00, 0x72, 0x65, 0x73, 0x70, 0x74, 0x02, +0x10, 0x76, 0x29, 0x02, 0x22, 0x28, 0x61, 0x67, 0x00, 0x15, +0x6e, 0x36, 0x01, 0x13, 0x65, 0xd2, 0x00, 0x05, 0xf3, 0x03, +0x01, 0x5e, 0x01, 0x6d, 0x77, 0x61, 0x79, 0x00, 0x61, 0x73, +0x10, 0x01, 0x22, 0x73, 0x29, 0xb7, 0x01, 0x14, 0x70, 0x9f, +0x00, 0x42, 0x42, 0x61, 0x63, 0x6b, 0x95, 0x00, 0x01, 0x90, +0x00, 0x59, 0x72, 0x65, 0x73, 0x65, 0x74, 0x2a, 0x02, 0x01, +0x9a, 0x00, 0x03, 0x7a, 0x02, 0x14, 0x32, 0x7a, 0x02, 0x92, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x7c, +0x02, 0x56, 0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x01, +0x1b, 0x05, 0x60, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0xbe, +0x01, 0x41, 0x66, 0x72, 0x6f, 0x6d, 0x89, 0x00, 0xe1, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x03, 0x03, 0x22, 0x6f, 0x6e, 0x1a, 0x00, +0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, +0x75, 0x6b, 0x00, 0x90, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, +0x00, 0x48, 0x65, 0x5d, 0x02, 0x00, 0x1f, 0x05, 0x30, 0x69, +0x7a, 0x65, 0xe2, 0x04, 0x01, 0x67, 0x05, 0x24, 0x69, 0x6e, +0xe4, 0x04, 0x00, 0x2b, 0x00, 0x31, 0x41, 0x67, 0x67, 0xcb, +0x00, 0x82, 0x76, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, +0x5a, 0x03, 0x00, 0x43, 0x00, 0x22, 0x74, 0x68, 0xb3, 0x03, +0x03, 0x6a, 0x00, 0x42, 0x73, 0x65, 0x74, 0x2c, 0xa0, 0x01, +0x00, 0x1f, 0x01, 0x03, 0x2c, 0x00, 0x23, 0x6f, 0x72, 0x87, +0x01, 0x91, 0x72, 0x79, 0x00, 0x68, 0x61, 0x72, 0x64, 0x65, +0x72, 0xf3, 0x00, 0xf1, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x6e, +0x61, 0x74, 0x65, 0x00, 0x75, 0x6e, 0x6e, 0x65, 0x63, 0x65, +0x73, 0x73, 0x61, 0x72, 0x79, 0x1a, 0x05, 0x14, 0x73, 0xb1, +0x00, 0x62, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x18, 0x05, +0x52, 0x73, 0x6c, 0x6f, 0x77, 0x73, 0x7f, 0x02, 0x06, 0x83, +0x00, 0xf1, 0x0a, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x69, 0x74, +0x27, 0x73, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x72, 0x65, 0x63, +0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0xc6, 0x02, +0x01, 0x3f, 0x00, 0x70, 0x73, 0x00, 0x6c, 0x61, 0x72, 0x67, +0x65, 0xd4, 0x02, 0x10, 0x61, 0x30, 0x00, 0xb0, 0x61, 0x79, +0x2c, 0x00, 0x33, 0x30, 0x2a, 0x33, 0x30, 0x2e, 0x00, +}; + +const unsigned short help_text_len = 1673; +const unsigned short help_text_words = 285; +const char quick_help_text[] = "Fill in the grid given clues about number of nearby black squares."; diff --git a/apps/plugins/puzzles/help/net.c b/apps/plugins/puzzles/help/net.c index b0224838cf..9b42b5eca3 100644 --- a/apps/plugins/puzzles/help/net.c +++ b/apps/plugins/puzzles/help/net.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,268 +6,295 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 3, TEXT_UNDERLINE }, - { 120, TEXT_CENTER | C_RED }, - { 140, TEXT_UNDERLINE }, - { 147, TEXT_UNDERLINE }, - { 155, TEXT_UNDERLINE }, - { 163, TEXT_UNDERLINE }, - { 168, TEXT_UNDERLINE }, - { 221, TEXT_UNDERLINE }, - { 257, TEXT_UNDERLINE }, - { 313, TEXT_UNDERLINE }, - { 344, TEXT_CENTER | C_RED }, - { 361, TEXT_UNDERLINE }, + { 4, TEXT_UNDERLINE }, + { 121, TEXT_CENTER | C_RED }, + { 141, TEXT_UNDERLINE }, + { 148, TEXT_UNDERLINE }, + { 156, TEXT_UNDERLINE }, + { 164, TEXT_UNDERLINE }, + { 169, TEXT_UNDERLINE }, + { 222, TEXT_UNDERLINE }, + { 258, TEXT_UNDERLINE }, + { 314, TEXT_UNDERLINE }, + { 345, TEXT_CENTER | C_RED }, { 362, TEXT_UNDERLINE }, - { 372, TEXT_UNDERLINE }, - { 398, TEXT_UNDERLINE }, - { 485, TEXT_UNDERLINE }, - { 553, TEXT_UNDERLINE }, - { 598, TEXT_UNDERLINE }, + { 363, TEXT_UNDERLINE }, + { 373, TEXT_UNDERLINE }, + { 399, TEXT_UNDERLINE }, + { 486, TEXT_UNDERLINE }, + { 554, TEXT_UNDERLINE }, + { 599, TEXT_UNDERLINE }, + { 614, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3439 comp 2361 ratio 0.686537 level 10 saved 1078 */ +/* orig 3919 comp 2622 ratio 0.669048 level 10 saved 1297 */ const char help_text[] = { -0xf4, 0x57, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, -0x33, 0x3a, 0x20, 0x4e, 0x65, 0x74, 0x20, 0x00, 0x00, 0x00, -0x28, 0x4e, 0x6f, 0x74, 0x65, 0x3a, 0x00, 0x74, 0x68, 0x65, -0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x00, 0x76, -0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x6f, 0x66, 0x00, -0x74, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, -0x69, 0x73, 0x00, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x00, -0x4e, 0x45, 0x54, 0x47, 0x41, 0x4d, 0x45, 0x2e, 0x45, 0x58, -0x45, 0x00, 0x74, 0x6f, 0x00, 0x61, 0x76, 0x6f, 0x69, 0x64, -0x00, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x00, -0x77, 0x69, 0x74, 0x68, 0x4a, 0x00, 0x60, 0x27, 0x73, 0x00, -0x6f, 0x77, 0x6e, 0x31, 0x00, 0x00, 0x2d, 0x00, 0xf2, 0x06, -0x2e, 0x29, 0x00, 0x00, 0x00, 0x49, 0x00, 0x6f, 0x72, 0x69, -0x67, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x61, -0x77, 0x62, 0x00, 0x21, 0x69, 0x6e, 0x81, 0x00, 0x40, 0x66, -0x6f, 0x72, 0x6d, 0x76, 0x00, 0x30, 0x61, 0x00, 0x46, 0x4f, -0x00, 0x02, 0x79, 0x00, 0x03, 0x76, 0x00, 0xf0, 0x18, 0x46, -0x72, 0x65, 0x65, 0x4e, 0x65, 0x74, 0x00, 0x5b, 0x31, 0x5d, -0x2c, 0x00, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, -0x62, 0x79, 0x00, 0x50, 0x61, 0x76, 0x69, 0x6c, 0x73, 0x00, -0x4a, 0x75, 0x72, 0x6a, 0x61, 0x6e, 0x73, 0x3b, 0x48, 0x00, -0xf0, 0x01, 0x72, 0x65, 0x00, 0x61, 0x72, 0x65, 0x00, 0x73, -0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x00, 0x6f, 0x13, 0x00, -0xf1, 0x07, 0x00, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, -0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x75, -0x6e, 0x64, 0x65, 0x72, 0x76, 0x00, 0x10, 0x6e, 0x66, 0x00, -0xf0, 0x19, 0x4e, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6b, 0x2e, -0x00, 0x54, 0x68, 0x65, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x75, -0x74, 0x65, 0x72, 0x00, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, -0x65, 0x73, 0x00, 0x61, 0x00, 0x6e, 0x65, 0x74, 0x77, 0x6f, -0x72, 0x6b, 0x73, 0x00, 0x70, 0x63, 0x6f, 0x6e, 0x6e, 0x65, -0x63, 0x74, 0xee, 0x00, 0x21, 0x75, 0x70, 0x43, 0x00, 0x40, -0x63, 0x65, 0x6e, 0x74, 0x27, 0x00, 0x61, 0x6f, 0x66, 0x00, -0x73, 0x71, 0x75, 0x32, 0x00, 0xe0, 0x69, 0x6e, 0x00, 0x61, -0x00, 0x67, 0x72, 0x69, 0x64, 0x2c, 0x00, 0x61, 0x6e, 0x64, -0x26, 0x00, 0xa2, 0x6e, 0x00, 0x73, 0x68, 0x75, 0x66, 0x66, -0x6c, 0x65, 0x73, 0x77, 0x00, 0x06, 0x51, 0x00, 0x41, 0x72, -0x6f, 0x74, 0x61, 0x4f, 0x00, 0x00, 0xb2, 0x00, 0xf0, 0x0a, -0x79, 0x00, 0x74, 0x69, 0x6c, 0x65, 0x00, 0x72, 0x61, 0x6e, -0x64, 0x6f, 0x6d, 0x6c, 0x79, 0x2e, 0x00, 0x59, 0x6f, 0x75, -0x72, 0x00, 0x6a, 0x6f, 0x62, 0x83, 0x01, 0x22, 0x74, 0x6f, -0x2d, 0x00, 0xf2, 0x09, 0x65, 0x00, 0x69, 0x74, 0x00, 0x61, -0x6c, 0x6c, 0x00, 0x62, 0x61, 0x63, 0x6b, 0x00, 0x69, 0x6e, -0x74, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0xc0, 0x00, -0xf0, 0x01, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, -0x75, 0x6c, 0x00, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0xcd, 0x01, -0x20, 0x77, 0x69, 0x2e, 0x00, 0xc5, 0x65, 0x00, 0x61, 0x6e, -0x00, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x65, 0x6c, 0xc9, 0x00, -0x24, 0x65, 0x64, 0x8d, 0x00, 0x12, 0x2c, 0xbf, 0x01, 0xf0, -0x03, 0x6e, 0x6f, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, -0x00, 0x6c, 0x6f, 0x6f, 0x70, 0x73, 0x2e, 0x00, 0x41, 0x02, -0x01, 0x81, 0x76, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x00, 0x61, -0xd3, 0x00, 0x21, 0x6c, 0x6c, 0xa7, 0x00, 0x71, 0x73, 0x00, -0x77, 0x68, 0x69, 0x63, 0x68, 0x70, 0x01, 0x06, 0x4e, 0x00, -0x21, 0x74, 0x6f, 0xe2, 0x00, 0x34, 0x6f, 0x6e, 0x65, 0xda, -0x01, 0x52, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x97, 0x01, 0xe0, -0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, -0x64, 0x2e, 0x00, 0x00, 0xd0, 0x01, 0xd2, 0x00, 0x68, 0x74, -0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6a, -0xc8, 0x01, 0xe3, 0x2e, 0x6c, 0x76, 0x2f, 0x73, 0x74, 0x75, -0x66, 0x66, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0xfc, 0x01, 0xa1, -0x2e, 0x68, 0x74, 0x6d, 0x00, 0x00, 0x00, 0x33, 0x2e, 0x31, -0xbd, 0x02, 0x80, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, -0x73, 0xc6, 0x02, 0x15, 0x54, 0xa8, 0x02, 0x30, 0x63, 0x61, -0x6e, 0xe7, 0x00, 0x62, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, -0xcf, 0x00, 0x43, 0x65, 0x69, 0x74, 0x68, 0xec, 0x01, 0xb2, -0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x6f, -0x72, 0x98, 0x00, 0x33, 0x6f, 0x75, 0x73, 0x35, 0x01, 0x04, -0x4f, 0x00, 0x00, 0xa5, 0x00, 0xb0, 0x3a, 0x00, 0x00, 0x00, -0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0xe6, 0x00, 0x12, -0x3a, 0x28, 0x00, 0xf0, 0x00, 0x00, 0x70, 0x6f, 0x69, 0x6e, -0x74, 0x65, 0x72, 0x2c, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, -0x4d, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0x52, 0x91, 0x01, -0x01, 0x29, 0x00, 0xf3, 0x05, 0x20, 0x61, 0x6e, 0x74, 0x69, -0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x3a, -0x00, 0x6c, 0x65, 0x66, 0x74, 0x3c, 0x00, 0xb0, 0x62, 0x75, -0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x00, 0x60, 0x41, 0x27, 0x39, -0x00, 0x0b, 0x38, 0x00, 0x07, 0x34, 0x00, 0x10, 0x72, 0x1c, -0x01, 0x0c, 0x35, 0x00, 0x1f, 0x44, 0x35, 0x00, 0x01, 0xf4, -0x03, 0x62, 0x79, 0x20, 0x31, 0x38, 0x30, 0x20, 0x64, 0x65, -0x67, 0x72, 0x65, 0x65, 0x73, 0x3a, 0x00, 0x60, 0x46, 0x26, -0x00, 0xb0, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x28, 0x6f, 0x72, -0x20, 0x75, 0x6e, 0x59, 0x00, 0x14, 0x29, 0xc6, 0x00, 0x02, -0x86, 0x01, 0x0a, 0x5c, 0x00, 0xf4, 0x00, 0x73, 0x68, 0x69, -0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x2c, 0x00, -0x60, 0x53, 0x43, 0x00, 0x31, 0x59, 0x6f, 0x75, 0x4c, 0x01, -0x00, 0x40, 0x00, 0x22, 0x00, 0x61, 0x94, 0x02, 0xa0, 0x6f, -0x6e, 0x63, 0x65, 0x00, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x64, -0x02, 0x20, 0x72, 0x65, 0xf0, 0x02, 0x30, 0x69, 0x74, 0x73, -0xd3, 0x03, 0x04, 0x59, 0x03, 0x15, 0x2e, 0x39, 0x00, 0x52, -0x61, 0x6c, 0x73, 0x6f, 0x00, 0x80, 0x00, 0x01, 0xad, 0x02, -0x50, 0x67, 0x61, 0x69, 0x6e, 0x2c, 0x76, 0x00, 0x00, 0x33, -0x02, 0x10, 0x6c, 0xc1, 0x02, 0x21, 0x27, 0x73, 0x5e, 0x00, -0x42, 0x65, 0x64, 0x00, 0x79, 0x34, 0x00, 0x80, 0x27, 0x74, -0x00, 0x61, 0x63, 0x63, 0x69, 0x64, 0x4d, 0x00, 0x00, 0x20, -0x04, 0x81, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x69, 0x74, 0x2e, -0xe1, 0x01, 0x00, 0x1f, 0x04, 0x40, 0x6c, 0x6c, 0x6f, 0x77, -0x28, 0x03, 0x08, 0xac, 0x01, 0x70, 0x00, 0x6e, 0x6f, 0x74, -0x00, 0x6e, 0x65, 0xf1, 0x02, 0x10, 0x61, 0x3d, 0x03, 0x11, -0x6f, 0xbf, 0x03, 0x41, 0x6c, 0x65, 0x74, 0x65, 0xe2, 0x01, -0x00, 0x15, 0x02, 0x02, 0x77, 0x00, 0x30, 0x6d, 0x61, 0x79, -0x1a, 0x02, 0x61, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0xe2, -0x01, 0x00, 0xfa, 0x00, 0x10, 0x20, 0xa4, 0x03, 0x12, 0x3a, -0x0c, 0x00, 0x2a, 0x00, 0x2b, 0xda, 0x01, 0x21, 0x4f, 0x6e, -0xc2, 0x03, 0x00, 0xb0, 0x03, 0x84, 0x61, 0x74, 0x00, 0x77, -0x72, 0x61, 0x70, 0x2c, 0xab, 0x00, 0x42, 0x00, 0x6d, 0x6f, -0x76, 0x61, 0x00, 0x02, 0xd0, 0x04, 0x02, 0x2d, 0x05, 0x13, -0x65, 0xf2, 0x03, 0x22, 0x73, 0x6f, 0x33, 0x00, 0x02, 0x23, -0x03, 0x02, 0x3e, 0x00, 0x00, 0x97, 0x04, 0x00, 0x55, 0x05, -0xd8, 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x00, 0x73, -0x69, 0x64, 0x65, 0x73, 0x37, 0x00, 0x04, 0xbb, 0x02, 0x90, -0x73, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x6f, 0x67, 0x65, 0xb6, -0x02, 0x00, 0xfc, 0x00, 0x52, 0x4d, 0x6f, 0x76, 0x65, 0x20, -0x63, 0x04, 0x6c, 0x3a, 0x00, 0x43, 0x74, 0x72, 0x6c, 0xa8, -0x00, 0x04, 0x73, 0x01, 0x63, 0x63, 0x68, 0x61, 0x6e, 0x67, -0x65, 0x93, 0x03, 0x11, 0x74, 0x65, 0x01, 0x30, 0x73, 0x00, -0x75, 0xc8, 0x03, 0x12, 0x61, 0x74, 0x04, 0x51, 0x73, 0x6f, -0x75, 0x72, 0x63, 0xb7, 0x01, 0x05, 0x86, 0x03, 0xd0, 0x69, -0x6e, 0x67, 0x2e, 0x00, 0x28, 0x49, 0x74, 0x00, 0x64, 0x6f, -0x65, 0x73, 0x82, 0x01, 0x70, 0x75, 0x6c, 0x74, 0x69, 0x6d, -0x61, 0x74, 0x20, 0x04, 0x30, 0x6d, 0x61, 0x74, 0x06, 0x05, -0x07, 0x50, 0x00, 0x02, 0xae, 0x05, 0x20, 0x73, 0x2c, 0x51, -0x00, 0x07, 0xad, 0x04, 0x04, 0x5d, 0x04, 0x09, 0x03, 0x04, -0x02, 0x20, 0x00, 0x02, 0x7e, 0x05, 0x02, 0x8d, 0x00, 0x00, -0x13, 0x05, 0x75, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, -0x99, 0x04, 0x02, 0x9c, 0x01, 0x15, 0x69, 0x9f, 0x01, 0x40, -0x68, 0x65, 0x6c, 0x70, 0xb9, 0x04, 0x03, 0x39, 0x04, 0x01, -0x71, 0x03, 0x50, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x33, 0x01, -0x33, 0x74, 0x61, 0x67, 0x66, 0x05, 0x30, 0x6f, 0x6c, 0x76, -0x09, 0x02, 0x00, 0x23, 0x00, 0x61, 0x70, 0x75, 0x7a, 0x7a, -0x6c, 0x65, 0x5e, 0x06, 0x52, 0x4a, 0x75, 0x6d, 0x62, 0x6c, -0x1e, 0x03, 0x00, 0x10, 0x03, 0x14, 0x4a, 0xcd, 0x02, 0x01, -0x1f, 0x04, 0x22, 0x6b, 0x65, 0x52, 0x02, 0x17, 0x73, 0xbe, -0x04, 0x01, 0x9b, 0x01, 0x04, 0x45, 0x02, 0x03, 0x8d, 0x02, -0x23, 0x74, 0x6f, 0x7d, 0x05, 0x08, 0xd8, 0x02, 0x20, 0x73, -0x2e, 0x2c, 0x07, 0x31, 0x41, 0x6c, 0x6c, 0x73, 0x00, 0x22, -0x61, 0x63, 0x45, 0x06, 0x90, 0x64, 0x65, 0x73, 0x63, 0x72, -0x69, 0x62, 0x65, 0x64, 0xaf, 0x00, 0x31, 0x73, 0x65, 0x63, -0x6a, 0x05, 0x31, 0x32, 0x2e, 0x31, 0x53, 0x00, 0x01, 0x01, -0x03, 0x73, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0xa0, -0x00, 0x31, 0x33, 0x2e, 0x32, 0xbb, 0x04, 0x93, 0x70, 0x61, -0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0xbd, 0x04, 0x10, -0x65, 0x5d, 0x04, 0x05, 0x14, 0x00, 0x02, 0x3e, 0x00, 0x04, -0x39, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x76, 0x00, -0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6c, 0x00, 0x22, 0x6f, 0x6e, -0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, -0x65, 0x6e, 0x75, 0xa8, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, -0x68, 0x2c, 0x00, 0x48, 0x65, 0x4b, 0x04, 0x51, 0x00, 0x00, -0x53, 0x69, 0x7a, 0xf5, 0x01, 0x01, 0x66, 0x02, 0x22, 0x69, -0x6e, 0xfc, 0x00, 0x01, 0x29, 0x00, 0x50, 0x61, 0x6c, 0x6c, -0x73, 0x20, 0xd9, 0x02, 0x70, 0x20, 0x61, 0x72, 0x6f, 0x75, -0x6e, 0x64, 0xa2, 0x07, 0x50, 0x66, 0x00, 0x63, 0x68, 0x65, -0x0a, 0x01, 0x61, 0x2c, 0x00, 0x66, 0x6c, 0x6f, 0x77, 0x5a, -0x02, 0x46, 0x70, 0x61, 0x73, 0x73, 0x89, 0x00, 0x01, 0xd7, -0x04, 0x44, 0x65, 0x64, 0x67, 0x65, 0xea, 0x05, 0x02, 0xb4, -0x04, 0x00, 0x12, 0x00, 0x02, 0xee, 0x06, 0x02, 0x2a, 0x00, -0x20, 0x6f, 0x70, 0x20, 0x00, 0x62, 0x62, 0x6f, 0x74, 0x74, -0x6f, 0x6d, 0x18, 0x00, 0x41, 0x76, 0x69, 0x63, 0x65, 0x5f, -0x08, 0x10, 0x61, 0x7e, 0x00, 0xf0, 0x03, 0x42, 0x61, 0x72, -0x72, 0x69, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, -0x62, 0x69, 0x6c, 0x69, 0x74, 0xac, 0x01, 0xd0, 0x41, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x62, 0x65, 0x74, -0x77, 0x0b, 0x03, 0x31, 0x30, 0x2e, 0x30, 0x3d, 0x00, 0x34, -0x31, 0x2e, 0x30, 0xf9, 0x03, 0x11, 0x6c, 0x6a, 0x08, 0x11, -0x68, 0x22, 0x03, 0x00, 0xd2, 0x06, 0x51, 0x69, 0x6d, 0x6d, -0x6f, 0x76, 0x2d, 0x01, 0x12, 0x62, 0x54, 0x00, 0x00, 0xf9, -0x02, 0x01, 0x11, 0x07, 0x15, 0x64, 0x47, 0x00, 0x34, 0x74, -0x77, 0x6f, 0xf5, 0x01, 0x10, 0x6f, 0xd9, 0x07, 0x42, 0x76, -0x65, 0x6e, 0x74, 0xe1, 0x00, 0x05, 0x22, 0x00, 0x61, 0x68, -0x65, 0x6d, 0x00, 0x28, 0x61, 0x1c, 0x03, 0x24, 0x65, 0x72, -0x87, 0x00, 0x95, 0x67, 0x69, 0x76, 0x65, 0x73, 0x00, 0x6d, -0x6f, 0x72, 0x5d, 0x00, 0x86, 0x73, 0x29, 0x2e, 0x00, 0x53, -0x69, 0x6e, 0x63, 0x11, 0x00, 0x01, 0xb2, 0x01, 0x05, 0x85, -0x00, 0x10, 0x2c, 0x4a, 0x00, 0x10, 0x79, 0x25, 0x02, 0x00, -0x27, 0x03, 0xb4, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, -0x69, 0x6e, 0x74, 0x73, 0xaf, 0x01, 0x05, 0x95, 0x07, 0x80, -0x28, 0x69, 0x2e, 0x65, 0x2e, 0x2c, 0x00, 0x68, 0x1d, 0x00, -0x14, 0x29, 0xe7, 0x04, 0x01, 0xa6, 0x01, 0x51, 0x67, 0x65, -0x6e, 0x65, 0x72, 0x7a, 0x02, 0x00, 0xb1, 0x01, 0x00, 0xf9, -0x08, 0x50, 0x68, 0x61, 0x73, 0x00, 0x62, 0xa7, 0x00, 0x30, -0x63, 0x61, 0x72, 0xc2, 0x04, 0x20, 0x6c, 0x79, 0x05, 0x04, -0x00, 0xf1, 0x03, 0x16, 0x64, 0x70, 0x04, 0x1c, 0x68, 0x94, -0x00, 0x60, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x52, 0x05, -0x04, 0x6b, 0x04, 0x48, 0x72, 0x65, 0x73, 0x74, 0x77, 0x04, -0x12, 0x2e, 0x1e, 0x03, 0x43, 0x6d, 0x65, 0x61, 0x6e, 0x10, -0x03, 0x21, 0x69, 0x66, 0xe6, 0x04, 0x82, 0x6e, 0x6f, 0x74, -0x65, 0x00, 0x64, 0x6f, 0x77, 0xb4, 0x00, 0x03, 0x13, 0x03, -0x42, 0x73, 0x65, 0x65, 0x64, 0x53, 0x04, 0x24, 0x74, 0x6f, -0xa5, 0x00, 0x12, 0x65, 0x04, 0x09, 0x30, 0x75, 0x72, 0x72, -0x67, 0x00, 0x02, 0x8f, 0x03, 0x57, 0x00, 0x28, 0x73, 0x65, -0x65, 0x13, 0x03, 0x34, 0x32, 0x29, 0x2c, 0x9f, 0x04, 0x00, -0x2d, 0x00, 0x0f, 0xfb, 0x01, 0x01, 0x05, 0x01, 0x03, 0x07, -0x32, 0x09, 0x40, 0x72, 0x65, 0x2d, 0x65, 0x02, 0x04, 0x02, -0x37, 0x01, 0x29, 0x61, 0x6d, 0x88, 0x00, 0x02, 0x8d, 0x05, -0x70, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6f, 0x00, -0x76, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x2d, 0x00, -0x41, 0x73, 0x74, 0x61, 0x72, 0x59, 0x09, 0x02, 0x97, 0x05, -0x01, 0x0e, 0x08, 0x02, 0x9a, 0x08, 0x24, 0x6c, 0x79, 0x8f, -0x00, 0x24, 0x62, 0x65, 0x49, 0x04, 0x03, 0xf1, 0x01, 0x25, -0x6f, 0x66, 0x44, 0x01, 0x43, 0x2e, 0x00, 0x53, 0x6f, 0x0f, -0x01, 0x01, 0xf4, 0x06, 0x60, 0x74, 0x75, 0x63, 0x6b, 0x00, -0x6f, 0xc7, 0x04, 0x10, 0x70, 0x59, 0x00, 0x52, 0x63, 0x75, -0x6c, 0x61, 0x72, 0xb0, 0x01, 0x20, 0x61, 0x6e, 0x45, 0x09, -0x00, 0x6a, 0x05, 0x01, 0xce, 0x01, 0x03, 0x28, 0x06, 0x02, -0x9a, 0x00, 0x00, 0x85, 0x00, 0x00, 0x2a, 0x0a, 0x23, 0x61, -0x6e, 0x8b, 0x0a, 0x52, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x88, -0x05, 0x71, 0x4e, 0x65, 0x74, 0x2c, 0x00, 0x73, 0x65, 0x20, -0x00, 0x05, 0xb7, 0x00, 0x07, 0x0b, 0x04, 0x00, 0x1d, 0x05, -0x05, 0x92, 0x02, 0x04, 0xdd, 0x02, 0x07, 0x36, 0x01, 0x02, -0x2c, 0x01, 0x06, 0x24, 0x01, 0x01, 0x04, 0x09, 0x01, 0xa5, -0x01, 0x05, 0xae, 0x03, 0x04, 0x71, 0x0b, 0x01, 0x46, 0x02, -0x11, 0x77, 0x9a, 0x0b, 0x00, 0x6b, 0x02, 0x20, 0x45, 0x6e, -0xc3, 0x07, 0x85, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, -0x20, 0x93, 0x02, 0x60, 0x00, 0x00, 0x4e, 0x6f, 0x72, 0x6d, -0x7f, 0x07, 0x13, 0x2c, 0x31, 0x00, 0x63, 0x6c, 0x6c, 0x00, -0x6d, 0x61, 0x6b, 0xf2, 0x07, 0x05, 0x67, 0x02, 0x02, 0xe7, -0x01, 0x10, 0x73, 0xba, 0x05, 0x50, 0x70, 0x72, 0x65, 0x73, -0x65, 0xdf, 0x02, 0x33, 0x68, 0x61, 0x76, 0x5c, 0x01, 0x26, -0x6f, 0x6e, 0xe6, 0x02, 0x33, 0x2e, 0x00, 0x50, 0x2c, 0x00, -0x01, 0x80, 0x01, 0x94, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, -0x6f, 0x75, 0x73, 0x1e, 0x02, 0x14, 0x73, 0xf9, 0x06, 0x01, -0x64, 0x03, 0x40, 0x64, 0x69, 0x66, 0x66, 0x59, 0x01, 0x11, -0x74, 0xd9, 0x00, 0x21, 0x6d, 0x6f, 0x6b, 0x08, 0x41, 0x62, -0x74, 0x6c, 0x65, 0x56, 0x07, 0x03, 0x9b, 0x02, 0x45, 0x6c, -0x69, 0x6b, 0x65, 0x8a, 0x07, 0x01, 0x26, 0x08, 0x23, 0x6f, -0x66, 0xad, 0x0c, 0x40, 0x66, 0x65, 0x61, 0x74, 0xa9, 0x00, -0x00, 0x3e, 0x00, 0x40, 0x72, 0x69, 0x73, 0x6b, 0x95, 0x00, -0x00, 0xe1, 0x01, 0x06, 0x77, 0x00, 0x03, 0xba, 0x00, 0x10, -0x2e, 0xcf, 0x05, 0x81, 0x73, 0x6f, 0x2c, 0x00, 0x66, 0x69, -0x6e, 0x64, 0x22, 0x00, 0x03, 0xdd, 0x05, 0x76, 0x70, 0x6f, -0x73, 0x73, 0x69, 0x62, 0x6c, 0xc1, 0x00, 0x05, 0xa1, 0x00, -0x00, 0xd6, 0x08, 0x30, 0x64, 0x64, 0x69, 0x14, 0x00, 0x20, -0x61, 0x6c, 0x40, 0x02, 0x51, 0x6c, 0x6c, 0x65, 0x6e, 0x67, -0xb8, 0x0c, 0x02, 0x1c, 0x00, 0x30, 0x76, 0x61, 0x6e, 0x73, -0x04, 0x90, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2e, 0x29, -0x00, +0xf9, 0x02, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0x33, 0x3a, 0x20, 0x4e, 0x65, 0x74, 0x20, 0x00, 0x2d, 0x01, +0x00, 0xf4, 0x48, 0x00, 0x00, 0x00, 0x28, 0x4e, 0x6f, 0x74, +0x65, 0x3a, 0x00, 0x74, 0x68, 0x65, 0x00, 0x57, 0x69, 0x6e, +0x64, 0x6f, 0x77, 0x73, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, +0x6f, 0x6e, 0x00, 0x6f, 0x66, 0x00, 0x74, 0x68, 0x69, 0x73, +0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x69, 0x73, 0x00, 0x63, +0x61, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x4e, 0x45, 0x54, 0x47, +0x41, 0x4d, 0x45, 0x2e, 0x45, 0x58, 0x45, 0x00, 0x74, 0x6f, +0x00, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x00, 0x63, 0x6c, 0x61, +0x73, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x77, 0x69, 0x74, 0x68, +0x4a, 0x00, 0x60, 0x27, 0x73, 0x00, 0x6f, 0x77, 0x6e, 0x31, +0x00, 0x00, 0x2d, 0x00, 0xf2, 0x06, 0x2e, 0x29, 0x00, 0x00, +0x00, 0x49, 0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, +0x6c, 0x6c, 0x79, 0x00, 0x73, 0x61, 0x77, 0x62, 0x00, 0x21, +0x69, 0x6e, 0x81, 0x00, 0x40, 0x66, 0x6f, 0x72, 0x6d, 0x76, +0x00, 0x30, 0x61, 0x00, 0x46, 0x4f, 0x00, 0x02, 0x79, 0x00, +0x03, 0x76, 0x00, 0xf0, 0x18, 0x46, 0x72, 0x65, 0x65, 0x4e, +0x65, 0x74, 0x00, 0x5b, 0x31, 0x5d, 0x2c, 0x00, 0x77, 0x72, +0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x50, +0x61, 0x76, 0x69, 0x6c, 0x73, 0x00, 0x4a, 0x75, 0x72, 0x6a, +0x61, 0x6e, 0x73, 0x3b, 0x48, 0x00, 0xf0, 0x01, 0x72, 0x65, +0x00, 0x61, 0x72, 0x65, 0x00, 0x73, 0x65, 0x76, 0x65, 0x72, +0x61, 0x6c, 0x00, 0x6f, 0x13, 0x00, 0xf1, 0x07, 0x00, 0x69, +0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x73, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, +0x76, 0x00, 0x10, 0x6e, 0x66, 0x00, 0xf0, 0x19, 0x4e, 0x65, +0x74, 0x57, 0x61, 0x6c, 0x6b, 0x2e, 0x00, 0x54, 0x68, 0x65, +0x00, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x00, +0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x73, 0x00, 0x61, +0x00, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x00, +0x70, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xee, 0x00, +0x21, 0x75, 0x70, 0x43, 0x00, 0x40, 0x63, 0x65, 0x6e, 0x74, +0x27, 0x00, 0x61, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x32, +0x00, 0xe0, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, +0x64, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x26, 0x00, 0xa2, 0x6e, +0x00, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x77, +0x00, 0x06, 0x51, 0x00, 0x41, 0x72, 0x6f, 0x74, 0x61, 0x4f, +0x00, 0x00, 0xb2, 0x00, 0xf0, 0x0a, 0x79, 0x00, 0x74, 0x69, +0x6c, 0x65, 0x00, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, +0x79, 0x2e, 0x00, 0x59, 0x6f, 0x75, 0x72, 0x00, 0x6a, 0x6f, +0x62, 0x83, 0x01, 0x22, 0x74, 0x6f, 0x2d, 0x00, 0xf2, 0x09, +0x65, 0x00, 0x69, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x00, 0x62, +0x61, 0x63, 0x6b, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, 0x70, +0x6c, 0x61, 0x63, 0x65, 0xc0, 0x00, 0xf0, 0x01, 0x73, 0x75, +0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x00, 0x73, +0x6f, 0x6c, 0x75, 0x74, 0xcd, 0x01, 0x20, 0x77, 0x69, 0x2e, +0x00, 0xc5, 0x65, 0x00, 0x61, 0x6e, 0x00, 0x65, 0x6e, 0x74, +0x69, 0x72, 0x65, 0x6c, 0xc9, 0x00, 0x24, 0x65, 0x64, 0x8d, +0x00, 0x12, 0x2c, 0xbf, 0x01, 0xf0, 0x03, 0x6e, 0x6f, 0x00, +0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x00, 0x6c, 0x6f, 0x6f, +0x70, 0x73, 0x2e, 0x00, 0x41, 0x02, 0x01, 0x81, 0x76, 0x69, +0x73, 0x75, 0x61, 0x6c, 0x00, 0x61, 0xd3, 0x00, 0x21, 0x6c, +0x6c, 0xa7, 0x00, 0x71, 0x73, 0x00, 0x77, 0x68, 0x69, 0x63, +0x68, 0x70, 0x01, 0x06, 0x4e, 0x00, 0x21, 0x74, 0x6f, 0xe2, +0x00, 0x34, 0x6f, 0x6e, 0x65, 0xda, 0x01, 0x52, 0x6d, 0x69, +0x64, 0x64, 0x6c, 0x97, 0x01, 0xe0, 0x68, 0x69, 0x67, 0x68, +0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x00, +0xd0, 0x01, 0xd2, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6a, 0xc8, 0x01, 0xe3, 0x2e, +0x6c, 0x76, 0x2f, 0x73, 0x74, 0x75, 0x66, 0x66, 0x2f, 0x6e, +0x65, 0x74, 0x2f, 0xfc, 0x01, 0xa1, 0x2e, 0x68, 0x74, 0x6d, +0x00, 0x00, 0x00, 0x33, 0x2e, 0x31, 0xcc, 0x02, 0xd5, 0x63, +0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, +0x00, 0x54, 0xa8, 0x02, 0x30, 0x63, 0x61, 0x6e, 0xe7, 0x00, +0x62, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0xcf, 0x00, 0x43, +0x65, 0x69, 0x74, 0x68, 0xec, 0x01, 0xb2, 0x6b, 0x65, 0x79, +0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x6f, 0x72, 0x98, 0x00, +0x33, 0x6f, 0x75, 0x73, 0x35, 0x01, 0x04, 0x4f, 0x00, 0x00, +0xa5, 0x00, 0xb0, 0x3a, 0x00, 0x00, 0x00, 0x53, 0x65, 0x6c, +0x65, 0x63, 0x74, 0x20, 0xe6, 0x00, 0x12, 0x3a, 0x28, 0x00, +0xf0, 0x00, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, +0x2c, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x4d, 0x00, 0x51, +0x73, 0x00, 0x00, 0x00, 0x52, 0x91, 0x01, 0x01, 0x29, 0x00, +0xf3, 0x05, 0x20, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x3a, 0x00, 0x6c, 0x65, +0x66, 0x74, 0x3c, 0x00, 0xb0, 0x62, 0x75, 0x74, 0x74, 0x6f, +0x6e, 0x2c, 0x00, 0x60, 0x41, 0x27, 0x39, 0x00, 0x0b, 0x38, +0x00, 0x07, 0x34, 0x00, 0x10, 0x72, 0x1c, 0x01, 0x0c, 0x35, +0x00, 0x1f, 0x44, 0x35, 0x00, 0x01, 0xf4, 0x03, 0x62, 0x79, +0x20, 0x31, 0x38, 0x30, 0x20, 0x64, 0x65, 0x67, 0x72, 0x65, +0x65, 0x73, 0x3a, 0x00, 0x60, 0x46, 0x26, 0x00, 0xb0, 0x4c, +0x6f, 0x63, 0x6b, 0x20, 0x28, 0x6f, 0x72, 0x20, 0x75, 0x6e, +0x59, 0x00, 0x14, 0x29, 0xc6, 0x00, 0x02, 0x86, 0x01, 0x0a, +0x5c, 0x00, 0xf4, 0x00, 0x73, 0x68, 0x69, 0x66, 0x74, 0x2d, +0x63, 0x6c, 0x69, 0x63, 0x6b, 0x2c, 0x00, 0x60, 0x53, 0x43, +0x00, 0x31, 0x59, 0x6f, 0x75, 0x4c, 0x01, 0x00, 0x40, 0x00, +0x22, 0x00, 0x61, 0x94, 0x02, 0xa0, 0x6f, 0x6e, 0x63, 0x65, +0x00, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x64, 0x02, 0x20, 0x72, +0x65, 0xf0, 0x02, 0x30, 0x69, 0x74, 0x73, 0xd3, 0x03, 0x04, +0x59, 0x03, 0x15, 0x2e, 0x39, 0x00, 0x52, 0x61, 0x6c, 0x73, +0x6f, 0x00, 0x80, 0x00, 0x01, 0xad, 0x02, 0x50, 0x67, 0x61, +0x69, 0x6e, 0x2c, 0x76, 0x00, 0x00, 0x33, 0x02, 0x10, 0x6c, +0xc1, 0x02, 0x21, 0x27, 0x73, 0x5e, 0x00, 0x42, 0x65, 0x64, +0x00, 0x79, 0x34, 0x00, 0x80, 0x27, 0x74, 0x00, 0x61, 0x63, +0x63, 0x69, 0x64, 0x4d, 0x00, 0x00, 0x20, 0x04, 0x81, 0x74, +0x75, 0x72, 0x6e, 0x00, 0x69, 0x74, 0x2e, 0xe1, 0x01, 0x00, +0x1f, 0x04, 0x40, 0x6c, 0x6c, 0x6f, 0x77, 0x28, 0x03, 0x08, +0xac, 0x01, 0x70, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x6e, 0x65, +0xf1, 0x02, 0x10, 0x61, 0x3d, 0x03, 0x11, 0x6f, 0xbf, 0x03, +0x41, 0x6c, 0x65, 0x74, 0x65, 0xe2, 0x01, 0x00, 0x15, 0x02, +0x02, 0x77, 0x00, 0x30, 0x6d, 0x61, 0x79, 0x1a, 0x02, 0x61, +0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0xe2, 0x01, 0x00, 0xfa, +0x00, 0x10, 0x20, 0xa4, 0x03, 0x12, 0x3a, 0x0c, 0x00, 0x2a, +0x00, 0x2b, 0xda, 0x01, 0x21, 0x4f, 0x6e, 0xc2, 0x03, 0x00, +0xb0, 0x03, 0x84, 0x61, 0x74, 0x00, 0x77, 0x72, 0x61, 0x70, +0x2c, 0xab, 0x00, 0x42, 0x00, 0x6d, 0x6f, 0x76, 0x61, 0x00, +0x02, 0xd0, 0x04, 0x02, 0x2d, 0x05, 0x13, 0x65, 0xf2, 0x03, +0x22, 0x73, 0x6f, 0x33, 0x00, 0x02, 0x23, 0x03, 0x02, 0x3e, +0x00, 0x00, 0x97, 0x04, 0x00, 0x55, 0x05, 0xd8, 0x70, 0x70, +0x6f, 0x73, 0x69, 0x74, 0x65, 0x00, 0x73, 0x69, 0x64, 0x65, +0x73, 0x37, 0x00, 0x04, 0xbb, 0x02, 0x90, 0x73, 0x65, 0x65, +0x6e, 0x00, 0x74, 0x6f, 0x67, 0x65, 0xb6, 0x02, 0x00, 0xfc, +0x00, 0x52, 0x4d, 0x6f, 0x76, 0x65, 0x20, 0x63, 0x04, 0x6c, +0x3a, 0x00, 0x43, 0x74, 0x72, 0x6c, 0xa8, 0x00, 0x04, 0x73, +0x01, 0x63, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x93, 0x03, +0x11, 0x74, 0x65, 0x01, 0x30, 0x73, 0x00, 0x75, 0xc8, 0x03, +0x12, 0x61, 0x74, 0x04, 0x51, 0x73, 0x6f, 0x75, 0x72, 0x63, +0xb7, 0x01, 0x05, 0x86, 0x03, 0xd0, 0x69, 0x6e, 0x67, 0x2e, +0x00, 0x28, 0x49, 0x74, 0x00, 0x64, 0x6f, 0x65, 0x73, 0x82, +0x01, 0x70, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x20, +0x04, 0x30, 0x6d, 0x61, 0x74, 0x06, 0x05, 0x07, 0x50, 0x00, +0x02, 0xae, 0x05, 0x20, 0x73, 0x2c, 0x51, 0x00, 0x07, 0xad, +0x04, 0x04, 0x5d, 0x04, 0x09, 0x03, 0x04, 0x02, 0x20, 0x00, +0x02, 0x7e, 0x05, 0x02, 0x8d, 0x00, 0x00, 0x13, 0x05, 0x75, +0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x99, 0x04, 0x02, +0x9c, 0x01, 0x15, 0x69, 0x9f, 0x01, 0x40, 0x68, 0x65, 0x6c, +0x70, 0xb9, 0x04, 0x03, 0x39, 0x04, 0x01, 0x71, 0x03, 0x50, +0x6d, 0x65, 0x64, 0x69, 0x61, 0x33, 0x01, 0x33, 0x74, 0x61, +0x67, 0x66, 0x05, 0x30, 0x6f, 0x6c, 0x76, 0x09, 0x02, 0x00, +0x23, 0x00, 0x61, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x5e, +0x06, 0x52, 0x4a, 0x75, 0x6d, 0x62, 0x6c, 0x1e, 0x03, 0x00, +0x10, 0x03, 0x14, 0x4a, 0xcd, 0x02, 0x01, 0x1f, 0x04, 0x22, +0x6b, 0x65, 0x52, 0x02, 0x17, 0x73, 0xbe, 0x04, 0x01, 0x9b, +0x01, 0x04, 0x45, 0x02, 0x03, 0x8d, 0x02, 0x23, 0x74, 0x6f, +0x7d, 0x05, 0x08, 0xd8, 0x02, 0x20, 0x73, 0x2e, 0x2c, 0x07, +0x31, 0x41, 0x6c, 0x6c, 0x73, 0x00, 0x22, 0x61, 0x63, 0x45, +0x06, 0x90, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0xaf, 0x00, 0x31, 0x73, 0x65, 0x63, 0x6a, 0x05, 0x31, +0x32, 0x2e, 0x31, 0x53, 0x00, 0x01, 0x01, 0x03, 0x73, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0xa0, 0x00, 0x31, 0x33, +0x2e, 0x32, 0xbb, 0x04, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, +0x65, 0x74, 0x65, 0x72, 0xbd, 0x04, 0x10, 0x65, 0x5d, 0x04, +0x05, 0x14, 0x00, 0x02, 0x3e, 0x00, 0x04, 0x39, 0x00, 0x51, +0x00, 0x66, 0x72, 0x6f, 0x6d, 0x76, 0x00, 0xe1, 0x60, 0x43, +0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, +0x6f, 0x70, 0x6c, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, +0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, +0xa8, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, +0x48, 0x65, 0x4b, 0x04, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, +0xf5, 0x01, 0x01, 0x66, 0x02, 0x22, 0x69, 0x6e, 0xfc, 0x00, +0x01, 0x29, 0x00, 0x50, 0x61, 0x6c, 0x6c, 0x73, 0x20, 0xd9, +0x02, 0x70, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0xa2, +0x07, 0x50, 0x66, 0x00, 0x63, 0x68, 0x65, 0x0a, 0x01, 0x61, +0x2c, 0x00, 0x66, 0x6c, 0x6f, 0x77, 0x5a, 0x02, 0x46, 0x70, +0x61, 0x73, 0x73, 0x89, 0x00, 0x01, 0xd7, 0x04, 0x44, 0x65, +0x64, 0x67, 0x65, 0xea, 0x05, 0x02, 0xb4, 0x04, 0x00, 0x12, +0x00, 0x02, 0xee, 0x06, 0x02, 0x2a, 0x00, 0x20, 0x6f, 0x70, +0x20, 0x00, 0x62, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x18, +0x00, 0x41, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x08, 0x10, 0x61, +0x7e, 0x00, 0xf0, 0x03, 0x42, 0x61, 0x72, 0x72, 0x69, 0x65, +0x72, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, +0x69, 0x74, 0xac, 0x01, 0xd0, 0x41, 0x00, 0x6e, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x00, 0x62, 0x65, 0x74, 0x77, 0x0b, 0x03, +0x31, 0x30, 0x2e, 0x30, 0x3d, 0x00, 0x34, 0x31, 0x2e, 0x30, +0xf9, 0x03, 0x11, 0x6c, 0x6a, 0x08, 0x11, 0x68, 0x22, 0x03, +0x00, 0xd2, 0x06, 0x51, 0x69, 0x6d, 0x6d, 0x6f, 0x76, 0x2d, +0x01, 0x12, 0x62, 0x54, 0x00, 0x00, 0xf9, 0x02, 0x01, 0x11, +0x07, 0x15, 0x64, 0x47, 0x00, 0x34, 0x74, 0x77, 0x6f, 0xf5, +0x01, 0x10, 0x6f, 0xd9, 0x07, 0x42, 0x76, 0x65, 0x6e, 0x74, +0xe1, 0x00, 0x05, 0x22, 0x00, 0x61, 0x68, 0x65, 0x6d, 0x00, +0x28, 0x61, 0x1c, 0x03, 0x24, 0x65, 0x72, 0x87, 0x00, 0x95, +0x67, 0x69, 0x76, 0x65, 0x73, 0x00, 0x6d, 0x6f, 0x72, 0x5d, +0x00, 0x86, 0x73, 0x29, 0x2e, 0x00, 0x53, 0x69, 0x6e, 0x63, +0x11, 0x00, 0x01, 0xb2, 0x01, 0x05, 0x85, 0x00, 0x10, 0x2c, +0x4a, 0x00, 0x10, 0x79, 0x25, 0x02, 0x00, 0x27, 0x03, 0xb4, +0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, +0x73, 0xaf, 0x01, 0x05, 0x95, 0x07, 0x80, 0x28, 0x69, 0x2e, +0x65, 0x2e, 0x2c, 0x00, 0x68, 0x1d, 0x00, 0x14, 0x29, 0xe7, +0x04, 0x01, 0xa6, 0x01, 0x51, 0x67, 0x65, 0x6e, 0x65, 0x72, +0x7a, 0x02, 0x00, 0xb1, 0x01, 0x00, 0xf9, 0x08, 0x50, 0x68, +0x61, 0x73, 0x00, 0x62, 0xa7, 0x00, 0x30, 0x63, 0x61, 0x72, +0xc2, 0x04, 0x20, 0x6c, 0x79, 0x05, 0x04, 0x00, 0xf1, 0x03, +0x16, 0x64, 0x70, 0x04, 0x1c, 0x68, 0x94, 0x00, 0x60, 0x6e, +0x64, 0x65, 0x70, 0x65, 0x6e, 0x52, 0x05, 0x04, 0x6b, 0x04, +0x48, 0x72, 0x65, 0x73, 0x74, 0x77, 0x04, 0x12, 0x2e, 0x1e, +0x03, 0x43, 0x6d, 0x65, 0x61, 0x6e, 0x10, 0x03, 0x21, 0x69, +0x66, 0xe6, 0x04, 0x82, 0x6e, 0x6f, 0x74, 0x65, 0x00, 0x64, +0x6f, 0x77, 0xb4, 0x00, 0x03, 0x13, 0x03, 0x42, 0x73, 0x65, +0x65, 0x64, 0x53, 0x04, 0x24, 0x74, 0x6f, 0xa5, 0x00, 0x12, +0x65, 0x04, 0x09, 0x30, 0x75, 0x72, 0x72, 0x67, 0x00, 0x02, +0x8f, 0x03, 0x57, 0x00, 0x28, 0x73, 0x65, 0x65, 0x13, 0x03, +0x34, 0x32, 0x29, 0x2c, 0x9f, 0x04, 0x00, 0x2d, 0x00, 0x0f, +0xfb, 0x01, 0x01, 0x05, 0x01, 0x03, 0x07, 0x32, 0x09, 0x40, +0x72, 0x65, 0x2d, 0x65, 0x02, 0x04, 0x02, 0x37, 0x01, 0x29, +0x61, 0x6d, 0x88, 0x00, 0x02, 0x8d, 0x05, 0x70, 0x73, 0x68, +0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6f, 0x00, 0x76, 0x65, 0x78, +0x61, 0x63, 0x74, 0x6c, 0x79, 0x2d, 0x00, 0x41, 0x73, 0x74, +0x61, 0x72, 0x59, 0x09, 0x02, 0x97, 0x05, 0x01, 0x0e, 0x08, +0x02, 0x9a, 0x08, 0x24, 0x6c, 0x79, 0x8f, 0x00, 0x24, 0x62, +0x65, 0x49, 0x04, 0x03, 0xf1, 0x01, 0x25, 0x6f, 0x66, 0x44, +0x01, 0x43, 0x2e, 0x00, 0x53, 0x6f, 0x0f, 0x01, 0x01, 0xf4, +0x06, 0x60, 0x74, 0x75, 0x63, 0x6b, 0x00, 0x6f, 0xc7, 0x04, +0x10, 0x70, 0x59, 0x00, 0x52, 0x63, 0x75, 0x6c, 0x61, 0x72, +0xb0, 0x01, 0x20, 0x61, 0x6e, 0x45, 0x09, 0x00, 0x6a, 0x05, +0x01, 0xce, 0x01, 0x03, 0x28, 0x06, 0x02, 0x9a, 0x00, 0x00, +0x85, 0x00, 0x00, 0x2a, 0x0a, 0x23, 0x61, 0x6e, 0x8b, 0x0a, +0x52, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x88, 0x05, 0x71, 0x4e, +0x65, 0x74, 0x2c, 0x00, 0x73, 0x65, 0x20, 0x00, 0x05, 0xb7, +0x00, 0x07, 0x0b, 0x04, 0x00, 0x1d, 0x05, 0x05, 0x92, 0x02, +0x04, 0xdd, 0x02, 0x07, 0x36, 0x01, 0x02, 0x2c, 0x01, 0x06, +0x24, 0x01, 0x01, 0x04, 0x09, 0x01, 0xa5, 0x01, 0x05, 0xae, +0x03, 0x04, 0x71, 0x0b, 0x01, 0x46, 0x02, 0x11, 0x77, 0x9a, +0x0b, 0x00, 0x6b, 0x02, 0x20, 0x45, 0x6e, 0xc3, 0x07, 0x85, +0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x93, 0x02, +0x60, 0x00, 0x00, 0x4e, 0x6f, 0x72, 0x6d, 0x7f, 0x07, 0x13, +0x2c, 0x31, 0x00, 0x63, 0x6c, 0x6c, 0x00, 0x6d, 0x61, 0x6b, +0xf2, 0x07, 0x05, 0x67, 0x02, 0x02, 0xe7, 0x01, 0x10, 0x73, +0xba, 0x05, 0x50, 0x70, 0x72, 0x65, 0x73, 0x65, 0xdf, 0x02, +0x33, 0x68, 0x61, 0x76, 0x5c, 0x01, 0x26, 0x6f, 0x6e, 0xe6, +0x02, 0x33, 0x2e, 0x00, 0x50, 0x2c, 0x00, 0x01, 0x80, 0x01, +0x94, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, +0x1e, 0x02, 0x14, 0x73, 0xf9, 0x06, 0x01, 0x64, 0x03, 0x40, +0x64, 0x69, 0x66, 0x66, 0x59, 0x01, 0x11, 0x74, 0xd9, 0x00, +0x21, 0x6d, 0x6f, 0x6b, 0x08, 0x41, 0x62, 0x74, 0x6c, 0x65, +0x56, 0x07, 0x03, 0x9b, 0x02, 0x45, 0x6c, 0x69, 0x6b, 0x65, +0x8a, 0x07, 0x01, 0x26, 0x08, 0x23, 0x6f, 0x66, 0xad, 0x0c, +0x40, 0x66, 0x65, 0x61, 0x74, 0xa9, 0x00, 0x00, 0x3e, 0x00, +0x40, 0x72, 0x69, 0x73, 0x6b, 0x95, 0x00, 0x00, 0xe1, 0x01, +0x06, 0x77, 0x00, 0x03, 0xba, 0x00, 0x10, 0x2e, 0xcf, 0x05, +0x81, 0x73, 0x6f, 0x2c, 0x00, 0x66, 0x69, 0x6e, 0x64, 0x22, +0x00, 0x03, 0xdd, 0x05, 0x76, 0x70, 0x6f, 0x73, 0x73, 0x69, +0x62, 0x6c, 0xc1, 0x00, 0x05, 0xa1, 0x00, 0x00, 0xd6, 0x08, +0x30, 0x64, 0x64, 0x69, 0x14, 0x00, 0x20, 0x61, 0x6c, 0x40, +0x02, 0x51, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0xb8, 0x0c, 0x02, +0x1c, 0x00, 0x10, 0x76, 0xd7, 0x01, 0x12, 0x64, 0x7d, 0x0a, +0x13, 0x72, 0xf2, 0x05, 0x11, 0x33, 0xf2, 0x05, 0x21, 0x75, +0x73, 0xee, 0x02, 0xa2, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, +0x63, 0x65, 0x73, 0x20, 0x5f, 0x08, 0x40, 0x70, 0x6c, 0x61, +0x74, 0xf6, 0x0c, 0x03, 0x7a, 0x03, 0x50, 0x73, 0x75, 0x70, +0x70, 0x6f, 0x2d, 0x02, 0x12, 0x73, 0x7d, 0x0c, 0x04, 0x2e, +0x00, 0x12, 0x2c, 0xe6, 0x05, 0x16, 0x50, 0x12, 0x00, 0x0d, +0x02, 0x06, 0x33, 0x47, 0x61, 0x6d, 0x02, 0x06, 0x02, 0xb3, +0x01, 0x33, 0x6c, 0x65, 0x74, 0x84, 0x02, 0x40, 0x6e, 0x66, +0x69, 0x67, 0x12, 0x01, 0x10, 0x77, 0x51, 0x03, 0x01, 0xd1, +0x0b, 0x0c, 0x88, 0x0b, 0x01, 0xce, 0x07, 0x30, 0x72, 0x72, +0x6f, 0xf1, 0x02, 0xa2, 0x42, 0x79, 0x00, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6c, 0x74, 0xc7, 0x04, 0x11, 0x27, 0xca, 0x06, +0x48, 0x77, 0x61, 0x79, 0x73, 0x32, 0x00, 0x33, 0x3b, 0x00, +0x62, 0x41, 0x03, 0x02, 0x3d, 0x03, 0x23, 0x69, 0x73, 0x90, +0x00, 0x06, 0x21, 0x09, 0x32, 0x61, 0x73, 0x6b, 0x19, 0x01, +0x01, 0x74, 0x00, 0x01, 0x0a, 0x06, 0x0a, 0x75, 0x00, 0x01, +0x29, 0x02, 0x28, 0x69, 0x66, 0x48, 0x08, 0x00, 0x0b, 0x01, +0x00, 0x51, 0x00, 0x00, 0x5e, 0x03, 0x04, 0xa4, 0x04, 0x01, +0x3e, 0x00, 0x14, 0x69, 0x2b, 0x0a, 0x03, 0xae, 0x04, 0x01, +0x75, 0x0e, 0x16, 0x73, 0x20, 0x00, 0x08, 0xcf, 0x08, 0x01, +0x9e, 0x07, 0x00, 0x07, 0x00, 0x00, 0xb5, 0x0c, 0x72, 0x73, +0x70, 0x6f, 0x69, 0x6c, 0x65, 0x72, 0x8a, 0x00, 0x05, 0x53, +0x07, 0x43, 0x64, 0x65, 0x64, 0x75, 0x7c, 0x02, 0x55, 0x61, +0x62, 0x6f, 0x75, 0x74, 0xb6, 0x0d, 0x00, 0xbd, 0x00, 0x00, +0xc6, 0x02, 0x00, 0x09, 0x09, 0x22, 0x65, 0x76, 0x30, 0x01, +0x00, 0x14, 0x08, 0x80, 0x61, 0x74, 0x00, 0x79, 0x65, 0x74, +0x2e, 0x00, }; -const unsigned short help_text_len = 3439; -const unsigned short help_text_words = 611; +const unsigned short help_text_len = 3919; +const unsigned short help_text_words = 689; const char quick_help_text[] = "Rotate each tile to reassemble the network."; diff --git a/apps/plugins/puzzles/help/netslide.c b/apps/plugins/puzzles/help/netslide.c index 0035c6e3e1..e8d066e1fc 100644 --- a/apps/plugins/puzzles/help/netslide.c +++ b/apps/plugins/puzzles/help/netslide.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -9,52 +9,53 @@ struct style_text help_text_style[] = { LAST_STYLE_ITEM }; -/* orig 526 comp 419 ratio 0.796578 level 3 saved 107 */ +/* orig 546 comp 425 ratio 0.778388 level 3 saved 121 */ const char help_text[] = { -0xf2, 0x3c, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x39, 0x3a, 0x20, 0x4e, 0x65, 0x74, 0x73, 0x6c, 0x69, 0x64, -0x65, 0x20, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, -0x67, 0x61, 0x6d, 0x65, 0x00, 0x63, 0x6f, 0x6d, 0x62, 0x69, -0x6e, 0x65, 0x73, 0x00, 0x74, 0x68, 0x65, 0x00, 0x67, 0x72, -0x69, 0x64, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, -0x69, 0x6f, 0x6e, 0x00, 0x6f, 0x66, 0x00, 0x4e, 0x65, 0x74, -0x00, 0x28, 0x73, 0x65, 0x65, 0x00, 0x63, 0x4a, 0x00, 0x81, -0x00, 0x33, 0x29, 0x00, 0x77, 0x69, 0x74, 0x68, 0x30, 0x00, -0x80, 0x6d, 0x6f, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x29, -0x00, 0x7a, 0x53, 0x69, 0x78, 0x74, 0x65, 0x65, 0x6e, 0x2d, -0x00, 0xe1, 0x36, 0x29, 0x3a, 0x00, 0x79, 0x6f, 0x75, 0x00, -0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x4d, 0x00, 0x00, 0x64, -0x00, 0xd0, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x69, 0x6e, -0x73, 0x74, 0x65, 0x61, 0x64, 0x3d, 0x00, 0xf6, 0x0f, 0x72, -0x6f, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x74, 0x69, -0x6c, 0x65, 0x73, 0x00, 0x62, 0x61, 0x63, 0x6b, 0x00, 0x69, -0x6e, 0x74, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x43, -0x00, 0x31, 0x74, 0x6f, 0x00, 0xc4, 0x00, 0x00, 0x7e, 0x00, -0x18, 0x6d, 0x22, 0x00, 0x20, 0x62, 0x79, 0x8d, 0x00, 0x00, -0x42, 0x00, 0xf4, 0x0f, 0x61, 0x00, 0x77, 0x68, 0x6f, 0x6c, -0x65, 0x00, 0x72, 0x6f, 0x77, 0x00, 0x61, 0x74, 0x00, 0x61, -0x00, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x00, 0x00, 0x00, 0x41, -0x73, 0x00, 0x69, 0x6e, 0xa7, 0x00, 0xc8, 0x2c, 0x00, 0x63, -0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x00, 0x69, 0x73, 0xd0, -0x00, 0xf1, 0x0c, 0x75, 0x73, 0x65, 0x00, 0x6f, 0x72, 0x00, -0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, -0x73, 0x2e, 0x00, 0x53, 0x65, 0x65, 0x00, 0x73, 0x65, 0x63, -0x12, 0x01, 0x41, 0x36, 0x2e, 0x31, 0x2e, 0x40, 0x01, 0xb2, -0x65, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, -0x65, 0x49, 0x01, 0xa2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, -0x74, 0x65, 0x72, 0x73, 0xab, 0x00, 0xf0, 0x01, 0x73, 0x69, -0x6d, 0x69, 0x6c, 0x61, 0x72, 0x00, 0x6d, 0x65, 0x61, 0x6e, -0x69, 0x6e, 0x67, 0x73, 0xbc, 0x00, 0x50, 0x74, 0x68, 0x6f, -0x73, 0x65, 0x86, 0x00, 0x05, 0x56, 0x01, 0x04, 0x58, 0x00, -0x8a, 0x33, 0x2e, 0x32, 0x29, 0x00, 0x61, 0x6e, 0x64, 0x47, -0x01, 0x06, 0x76, 0x00, 0x20, 0x32, 0x29, 0x77, 0x00, 0x04, -0xc3, 0x01, 0x42, 0x00, 0x77, 0x61, 0x73, 0xc1, 0x00, 0x62, -0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x5c, 0x00, 0x10, 0x69, -0x14, 0x00, 0x23, 0x6c, 0x6c, 0x34, 0x00, 0xf0, 0x05, 0x62, -0x79, 0x00, 0x52, 0x69, 0x63, 0x68, 0x61, 0x72, 0x64, 0x00, -0x42, 0x6f, 0x75, 0x6c, 0x74, 0x6f, 0x6e, 0x2e, 0x00, +0x65, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf2, 0x28, 0x00, 0x00, +0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, +0x00, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x73, 0x00, +0x74, 0x68, 0x65, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x67, +0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, +0x6f, 0x66, 0x00, 0x4e, 0x65, 0x74, 0x00, 0x28, 0x73, 0x65, +0x65, 0x00, 0x63, 0x5e, 0x00, 0x81, 0x00, 0x33, 0x29, 0x00, +0x77, 0x69, 0x74, 0x68, 0x30, 0x00, 0x80, 0x6d, 0x6f, 0x76, +0x65, 0x6d, 0x65, 0x6e, 0x74, 0x29, 0x00, 0x7a, 0x53, 0x69, +0x78, 0x74, 0x65, 0x65, 0x6e, 0x2d, 0x00, 0xe1, 0x36, 0x29, +0x3a, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, +0x00, 0x61, 0x4d, 0x00, 0x00, 0x64, 0x00, 0xd0, 0x2c, 0x00, +0x62, 0x75, 0x74, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, +0x64, 0x3d, 0x00, 0xf6, 0x0f, 0x72, 0x6f, 0x74, 0x61, 0x74, +0x69, 0x6e, 0x67, 0x00, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x00, +0x62, 0x61, 0x63, 0x6b, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, +0x70, 0x6c, 0x61, 0x63, 0x65, 0x43, 0x00, 0x31, 0x74, 0x6f, +0x00, 0xd8, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x6d, 0x22, 0x00, +0x20, 0x62, 0x79, 0x8d, 0x00, 0x00, 0x42, 0x00, 0xf4, 0x0f, +0x61, 0x00, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x00, 0x72, 0x6f, +0x77, 0x00, 0x61, 0x74, 0x00, 0x61, 0x00, 0x74, 0x69, 0x6d, +0x65, 0x2e, 0x00, 0x00, 0x00, 0x41, 0x73, 0x00, 0x69, 0x6e, +0xa7, 0x00, 0xc8, 0x2c, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x72, +0x6f, 0x6c, 0x00, 0x69, 0x73, 0xd0, 0x00, 0xf1, 0x0c, 0x75, +0x73, 0x65, 0x00, 0x6f, 0x72, 0x00, 0x63, 0x75, 0x72, 0x73, +0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x00, 0x53, +0x65, 0x65, 0x00, 0x73, 0x65, 0x63, 0x12, 0x01, 0x41, 0x36, +0x2e, 0x31, 0x2e, 0x40, 0x01, 0xb2, 0x65, 0x00, 0x61, 0x76, +0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x01, 0xa2, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, +0xab, 0x00, 0xf0, 0x01, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, +0x72, 0x00, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x73, +0xbc, 0x00, 0x50, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x86, 0x00, +0x05, 0x56, 0x01, 0x04, 0x58, 0x00, 0x8a, 0x33, 0x2e, 0x32, +0x29, 0x00, 0x61, 0x6e, 0x64, 0x47, 0x01, 0x06, 0x76, 0x00, +0x20, 0x32, 0x29, 0x77, 0x00, 0x04, 0xd7, 0x01, 0x42, 0x00, +0x77, 0x61, 0x73, 0xc1, 0x00, 0x62, 0x69, 0x62, 0x75, 0x74, +0x65, 0x64, 0x5c, 0x00, 0x10, 0x69, 0x14, 0x00, 0x23, 0x6c, +0x6c, 0x34, 0x00, 0xf0, 0x05, 0x62, 0x79, 0x00, 0x52, 0x69, +0x63, 0x68, 0x61, 0x72, 0x64, 0x00, 0x42, 0x6f, 0x75, 0x6c, +0x74, 0x6f, 0x6e, 0x2e, 0x00, }; -const unsigned short help_text_len = 526; -const unsigned short help_text_words = 98; +const unsigned short help_text_len = 546; +const unsigned short help_text_words = 99; const char quick_help_text[] = "Slide a row at a time to reassemble the network."; diff --git a/apps/plugins/puzzles/help/nullgame.c b/apps/plugins/puzzles/help/nullgame.c new file mode 100644 index 0000000000..219a68c7e8 --- /dev/null +++ b/apps/plugins/puzzles/help/nullgame.c @@ -0,0 +1 @@ +const char quick_help_text[] = ""; diff --git a/apps/plugins/puzzles/help/palisade.c b/apps/plugins/puzzles/help/palisade.c index 1094502ea7..9b95b07eae 100644 --- a/apps/plugins/puzzles/help/palisade.c +++ b/apps/plugins/puzzles/help/palisade.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,89 +6,90 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 87, TEXT_CENTER | C_RED }, - { 149, TEXT_CENTER | C_RED }, - { 166, TEXT_UNDERLINE }, + { 88, TEXT_CENTER | C_RED }, + { 150, TEXT_CENTER | C_RED }, { 167, TEXT_UNDERLINE }, - { 177, TEXT_UNDERLINE }, + { 168, TEXT_UNDERLINE }, + { 178, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1113 comp 892 ratio 0.801438 level 3 saved 221 */ +/* orig 1135 comp 902 ratio 0.794714 level 3 saved 233 */ const char help_text[] = { -0xf0, 0x2d, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x34, 0x31, 0x3a, 0x20, 0x50, 0x61, 0x6c, 0x69, 0x73, 0x61, -0x64, 0x65, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x27, -0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, -0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, -0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, -0x6d, 0x65, 0x11, 0x00, 0xf0, 0x07, 0x77, 0x68, 0x69, 0x63, -0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x3f, 0x00, -0xf2, 0x0b, 0x72, 0x00, 0x67, 0x6f, 0x61, 0x6c, 0x00, 0x69, -0x73, 0x00, 0x74, 0x6f, 0x00, 0x73, 0x75, 0x62, 0x64, 0x69, -0x76, 0x69, 0x64, 0x65, 0x00, 0x74, 0x68, 0x65, 0x4e, 0x00, -0x41, 0x69, 0x6e, 0x74, 0x6f, 0x39, 0x00, 0xf0, 0x04, 0x69, -0x67, 0x75, 0x6f, 0x75, 0x73, 0x00, 0x72, 0x65, 0x67, 0x69, -0x6f, 0x6e, 0x73, 0x2c, 0x00, 0x61, 0x6c, 0x6c, 0x5a, 0x00, -0x00, 0x29, 0x00, 0x61, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x28, -0x85, 0x00, 0xf3, 0x07, 0x29, 0x00, 0x73, 0x69, 0x7a, 0x65, -0x2c, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x74, 0x68, 0x61, -0x74, 0x00, 0x65, 0x61, 0x63, 0x68, 0x91, 0x00, 0x04, 0x81, -0x00, 0x53, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x86, 0x00, 0x00, -0x7a, 0x00, 0x80, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, -0x74, 0x83, 0x00, 0x72, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, -0x79, 0x3c, 0x00, 0xf0, 0x03, 0x6d, 0x61, 0x6e, 0x79, 0x00, -0x65, 0x64, 0x67, 0x65, 0x73, 0x00, 0x28, 0x69, 0x6e, 0x63, -0x6c, 0x75, 0x64, 0x3b, 0x00, 0xd1, 0x74, 0x68, 0x6f, 0x73, -0x65, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x81, -0x00, 0x30, 0x69, 0x6e, 0x73, 0xb5, 0x00, 0x31, 0x61, 0x6e, -0x64, 0x0f, 0x00, 0x31, 0x6f, 0x75, 0x74, 0x10, 0x00, 0x25, -0x6f, 0x66, 0xc8, 0x00, 0xf1, 0x10, 0x29, 0x2e, 0x00, 0x00, -0x00, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, -0x72, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, -0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0xfe, 0x00, 0xd0, -0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x2c, 0x00, 0x77, 0x68, -0x6f, 0x00, 0x63, 0xdf, 0x00, 0xf0, 0x06, 0x69, 0x74, 0x00, -0x60, 0x46, 0x69, 0x76, 0x65, 0x00, 0x43, 0x65, 0x6c, 0x6c, -0x73, 0x27, 0x2e, 0x00, 0x5b, 0x32, 0x32, 0x5d, 0x49, 0x00, -0x04, 0x83, 0x01, 0x41, 0x00, 0x77, 0x61, 0x73, 0xd5, 0x00, -0x70, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x46, 0x00, -0x01, 0x5a, 0x00, 0xf0, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, -0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, -0x6f, 0x6e, 0x61, 0x73, 0x00, 0x4b, 0x6f, 0x65, 0x6c, 0x6b, -0x65, 0x72, 0x40, 0x00, 0x00, 0x48, 0x00, 0x91, 0x00, 0x68, -0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x76, 0x00, 0xa2, -0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, -0x95, 0x00, 0x80, 0x73, 0x2f, 0x66, 0x69, 0x76, 0x65, 0x5f, -0x63, 0x79, 0x00, 0xc6, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, -0x00, 0x00, 0x34, 0x31, 0x2e, 0x31, 0xfe, 0x01, 0x01, 0x77, -0x00, 0x30, 0x6f, 0x6c, 0x73, 0x07, 0x02, 0xa0, 0x4c, 0x65, -0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x82, 0x00, -0x40, 0x70, 0x6c, 0x61, 0x63, 0x0d, 0x01, 0x01, 0x3a, 0x01, +0x64, 0x65, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf0, 0x18, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x00, +0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, +0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, +0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, +0x00, 0xf0, 0x07, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x63, +0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x73, 0x2e, 0x3f, 0x00, 0xf2, 0x0b, 0x72, +0x00, 0x67, 0x6f, 0x61, 0x6c, 0x00, 0x69, 0x73, 0x00, 0x74, +0x6f, 0x00, 0x73, 0x75, 0x62, 0x64, 0x69, 0x76, 0x69, 0x64, +0x65, 0x00, 0x74, 0x68, 0x65, 0x4e, 0x00, 0x41, 0x69, 0x6e, +0x74, 0x6f, 0x39, 0x00, 0xf0, 0x04, 0x69, 0x67, 0x75, 0x6f, +0x75, 0x73, 0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, +0x2c, 0x00, 0x61, 0x6c, 0x6c, 0x5a, 0x00, 0x00, 0x29, 0x00, +0x61, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x28, 0x85, 0x00, 0xf3, +0x07, 0x29, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x00, 0x73, +0x75, 0x63, 0x68, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x65, +0x61, 0x63, 0x68, 0x91, 0x00, 0x04, 0x81, 0x00, 0x53, 0x69, +0x6e, 0x67, 0x00, 0x61, 0x86, 0x00, 0x00, 0x7a, 0x00, 0x80, +0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x83, 0x00, +0x72, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x3c, 0x00, +0xf0, 0x03, 0x6d, 0x61, 0x6e, 0x79, 0x00, 0x65, 0x64, 0x67, +0x65, 0x73, 0x00, 0x28, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, +0x3b, 0x00, 0xd1, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x00, 0x62, +0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x81, 0x00, 0x30, 0x69, +0x6e, 0x73, 0xb5, 0x00, 0x31, 0x61, 0x6e, 0x64, 0x0f, 0x00, +0x31, 0x6f, 0x75, 0x74, 0x10, 0x00, 0x25, 0x6f, 0x66, 0xc8, +0x00, 0xf1, 0x10, 0x29, 0x2e, 0x00, 0x00, 0x00, 0x43, 0x72, +0x65, 0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x74, +0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, +0x00, 0x67, 0x6f, 0x65, 0xfe, 0x00, 0xd0, 0x4e, 0x69, 0x6b, +0x6f, 0x6c, 0x69, 0x2c, 0x00, 0x77, 0x68, 0x6f, 0x00, 0x63, +0xdf, 0x00, 0xf0, 0x06, 0x69, 0x74, 0x00, 0x60, 0x46, 0x69, +0x76, 0x65, 0x00, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x27, 0x2e, +0x00, 0x5b, 0x32, 0x32, 0x5d, 0x49, 0x00, 0x04, 0x98, 0x01, +0x41, 0x00, 0x77, 0x61, 0x73, 0xd5, 0x00, 0x70, 0x72, 0x69, +0x62, 0x75, 0x74, 0x65, 0x64, 0x46, 0x00, 0x01, 0x5a, 0x00, +0xf0, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x6f, 0x6e, 0x61, +0x73, 0x00, 0x4b, 0x6f, 0x65, 0x6c, 0x6b, 0x65, 0x72, 0x40, +0x00, 0x00, 0x48, 0x00, 0xe1, 0x00, 0x68, 0x74, 0x74, 0x70, +0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x7b, +0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, +0x6e, 0x2f, 0x9a, 0x00, 0x80, 0x73, 0x2f, 0x66, 0x69, 0x76, +0x65, 0x5f, 0x63, 0x7e, 0x00, 0x86, 0x2f, 0x00, 0x00, 0x00, +0x34, 0x31, 0x2e, 0x31, 0x14, 0x02, 0x01, 0x78, 0x00, 0xf0, +0x02, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c, 0x65, +0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x83, 0x00, +0x40, 0x70, 0x6c, 0x61, 0x63, 0x0e, 0x01, 0x01, 0x3b, 0x01, 0x67, 0x2e, 0x00, 0x52, 0x69, 0x67, 0x68, 0x1e, 0x00, 0xc1, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x60, 0x6e, 0x6f, 0x22, 0x00, 0xf1, 0x02, 0x27, 0x2e, 0x00, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, -0x6c, 0x79, 0x2c, 0x35, 0x01, 0xf0, 0x07, 0x61, 0x72, 0x72, +0x6c, 0x79, 0x2c, 0x36, 0x01, 0xf0, 0x07, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x6d, 0x6f, 0x76, 0x65, 0x00, 0x61, 0x11, 0x00, 0xf1, 0x02, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x2e, 0x00, 0x48, 0x6f, 0x6c, -0x95, 0x01, 0x12, 0x43, 0x8f, 0x00, 0x00, 0x6a, 0x02, 0x81, -0x6c, 0x65, 0x00, 0x70, 0x72, 0x65, 0x73, 0x73, 0xe7, 0x01, +0x96, 0x01, 0x12, 0x43, 0x8f, 0x00, 0x00, 0x6b, 0x02, 0x81, +0x6c, 0x65, 0x00, 0x70, 0x72, 0x65, 0x73, 0x73, 0xe8, 0x01, 0x16, 0x6e, 0x4a, 0x00, 0x02, 0x49, 0x00, 0x0b, 0x9e, 0x00, 0x10, 0x50, 0x2a, 0x00, 0x72, 0x00, 0x53, 0x68, 0x69, 0x66, -0x74, 0x2d, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x8c, 0x02, +0x74, 0x2d, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x8d, 0x02, 0x97, 0x77, 0x69, 0x74, 0x63, 0x68, 0x00, 0x6f, 0x66, 0x66, 0xcb, 0x00, 0x51, 0x65, 0x70, 0x65, 0x61, 0x74, 0x55, 0x00, -0x02, 0x5d, 0x01, 0x00, 0xee, 0x00, 0xf0, 0x03, 0x65, 0x72, +0x02, 0x5e, 0x01, 0x00, 0xee, 0x00, 0xf0, 0x03, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x69, 0x74, 0x73, 0x00, 0x69, -0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x63, 0x01, 0x42, 0x28, +0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x01, 0x42, 0x28, 0x41, 0x6c, 0x6c, 0xc9, 0x00, 0x01, 0x2a, 0x00, 0xa0, 0x73, -0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xd3, -0x02, 0x23, 0x00, 0x73, 0x9d, 0x01, 0x40, 0x32, 0x2e, 0x31, -0x00, 0x99, 0x02, 0xf2, 0x01, 0x61, 0x6c, 0x73, 0x6f, 0x00, +0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xd4, +0x02, 0x23, 0x00, 0x73, 0x9e, 0x01, 0x40, 0x32, 0x2e, 0x31, +0x00, 0x9a, 0x02, 0xf2, 0x01, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x6e, 0x01, 0x16, 0x32, 0x6e, 0x01, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x70, 0x01, 0x66, @@ -99,15 +100,15 @@ const char help_text[] = { 0x6f, 0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xae, 0x00, 0x90, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xac, 0x01, 0x61, -0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xbf, 0x02, 0x03, 0x83, -0x03, 0x04, 0xd1, 0x03, 0x00, 0x2b, 0x00, 0x11, 0x52, 0x81, -0x03, 0x10, 0x20, 0x67, 0x03, 0x02, 0x8a, 0x00, 0x01, 0x72, -0x03, 0x04, 0xec, 0x02, 0x03, 0x9f, 0x03, 0x02, 0xb7, 0x03, -0x02, 0xf6, 0x03, 0x05, 0xcb, 0x03, 0x74, 0x6d, 0x75, 0x73, -0x74, 0x00, 0x62, 0x65, 0xe6, 0x03, 0x50, 0x64, 0x65, 0x64, +0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xc0, 0x02, 0x03, 0x84, +0x03, 0x04, 0xd2, 0x03, 0x00, 0x2b, 0x00, 0x11, 0x52, 0x82, +0x03, 0x10, 0x20, 0x68, 0x03, 0x02, 0x8a, 0x00, 0x01, 0x73, +0x03, 0x04, 0xed, 0x02, 0x03, 0xa0, 0x03, 0x02, 0xb8, 0x03, +0x02, 0xf7, 0x03, 0x05, 0xcc, 0x03, 0x74, 0x6d, 0x75, 0x73, +0x74, 0x00, 0x62, 0x65, 0xe7, 0x03, 0x50, 0x64, 0x65, 0x64, 0x2e, 0x00, }; -const unsigned short help_text_len = 1113; -const unsigned short help_text_words = 192; +const unsigned short help_text_len = 1135; +const unsigned short help_text_words = 193; const char quick_help_text[] = "Divide the grid into equal-sized areas in accordance with the clues."; diff --git a/apps/plugins/puzzles/help/pattern.c b/apps/plugins/puzzles/help/pattern.c index 2b43a878bd..b5775f32ed 100644 --- a/apps/plugins/puzzles/help/pattern.c +++ b/apps/plugins/puzzles/help/pattern.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,92 +6,94 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 137, TEXT_UNDERLINE }, - { 173, TEXT_CENTER | C_RED }, - { 362, TEXT_CENTER | C_RED }, - { 378, TEXT_UNDERLINE }, - { 380, TEXT_UNDERLINE }, + { 142, TEXT_UNDERLINE }, + { 178, TEXT_CENTER | C_RED }, + { 367, TEXT_CENTER | C_RED }, + { 383, TEXT_UNDERLINE }, + { 385, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2125 comp 1459 ratio 0.686588 level 4 saved 666 */ +/* orig 2167 comp 1479 ratio 0.68251 level 4 saved 688 */ const char help_text[] = { -0xf0, 0x4f, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x30, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, -0x6e, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, -0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, -0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, -0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x6d, -0x75, 0x73, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x00, 0x62, 0x65, -0x00, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x69, 0x6e, -0x00, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x00, 0x62, 0x6c, -0x61, 0x63, 0x6b, 0x00, 0x6f, 0x72, 0x2c, 0x00, 0xf0, 0x04, -0x74, 0x65, 0x2e, 0x00, 0x42, 0x65, 0x73, 0x69, 0x64, 0x65, -0x00, 0x65, 0x61, 0x63, 0x68, 0x00, 0x72, 0x6f, 0x77, 0x4f, -0x00, 0x32, 0x74, 0x68, 0x65, 0x5b, 0x00, 0xa1, 0x61, 0x72, -0x65, 0x00, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x14, 0x00, -0x74, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, 0x23, 0x00, -0x31, 0x72, 0x75, 0x6e, 0x0c, 0x00, 0x02, 0x52, 0x00, 0x03, -0x84, 0x00, 0x80, 0x00, 0x6f, 0x6e, 0x00, 0x74, 0x68, 0x61, -0x74, 0x4c, 0x00, 0x63, 0x3b, 0x00, 0x61, 0x62, 0x6f, 0x76, -0x5c, 0x00, 0x6f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x53, -0x00, 0x22, 0x13, 0x69, 0x53, 0x00, 0x02, 0x43, 0x00, 0x10, -0x2e, 0x02, 0x01, 0xb1, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, -0x69, 0x73, 0x00, 0x74, 0x6f, 0xe3, 0x00, 0x02, 0x24, 0x00, -0x73, 0x65, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x72, 0xbe, 0x00, -0x0c, 0xea, 0x00, 0xf1, 0x22, 0x00, 0x00, 0x49, 0x00, 0x66, -0x69, 0x72, 0x73, 0x74, 0x00, 0x73, 0x61, 0x77, 0x00, 0x74, -0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, -0x00, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x61, 0x72, 0x6f, 0x75, -0x6e, 0x64, 0x00, 0x31, 0x39, 0x39, 0x35, 0x2c, 0x00, 0x75, -0x6e, 0x64, 0x65, 0x72, 0x52, 0x00, 0xf0, 0x0f, 0x6e, 0x61, -0x6d, 0x65, 0x00, 0x60, 0x6e, 0x6f, 0x6e, 0x6f, 0x67, 0x72, -0x61, 0x6d, 0x73, 0x27, 0x2e, 0x00, 0x49, 0x27, 0x76, 0x65, -0x00, 0x73, 0x65, 0x65, 0x6e, 0x00, 0x69, 0x74, 0x78, 0x00, -0xf0, 0x05, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, -0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x00, 0x73, 0x69, 0x6e, -0x63, 0x65, 0x3b, 0x00, 0x14, 0x6e, 0x47, 0x00, 0x91, 0x64, -0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4d, 0x00, -0x10, 0x73, 0x8a, 0x00, 0x93, 0x4e, 0x6f, 0x72, 0x6d, 0x61, -0x6c, 0x6c, 0x79, 0x2c, 0x83, 0x00, 0x03, 0x02, 0x01, 0x00, -0xd1, 0x00, 0xc0, 0x79, 0x70, 0x65, 0x00, 0x74, 0x75, 0x72, -0x6e, 0x00, 0x6f, 0x75, 0x74, 0xdf, 0x00, 0x10, 0x62, 0xea, -0x01, 0xf1, 0x03, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, -0x66, 0x75, 0x6c, 0x00, 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, -0x65, 0xf8, 0x01, 0xa0, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, -0x6e, 0x67, 0x00, 0x6f, 0x74, 0x00, 0x31, 0x79, 0x6f, 0x75, -0x9b, 0x00, 0x32, 0x6f, 0x6c, 0x76, 0x5f, 0x01, 0xb5, 0x6d, -0x2e, 0x00, 0x48, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, -0x97, 0x00, 0xf1, 0x05, 0x69, 0x73, 0x00, 0x76, 0x65, 0x72, -0x73, 0x69, 0x6f, 0x6e, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, -0x61, 0x74, 0x65, 0x73, 0xe9, 0x00, 0x04, 0x89, 0x00, 0x92, -0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0xa0, -0x00, 0x60, 0x74, 0x68, 0x65, 0x79, 0x00, 0x77, 0x63, 0x01, -0x10, 0x6a, 0x57, 0x02, 0xf7, 0x0b, 0x6c, 0x6f, 0x6f, 0x6b, -0x00, 0x6c, 0x69, 0x6b, 0x65, 0x00, 0x72, 0x61, 0x6e, 0x64, -0x6f, 0x6d, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, -0x67, 0x73, 0x89, 0x02, 0xf3, 0x06, 0x2e, 0x00, 0x28, 0x4f, -0x6e, 0x65, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x68, 0x61, -0x73, 0x00, 0x73, 0x75, 0x67, 0x67, 0x65, 0xf4, 0x01, 0x22, -0x61, 0x74, 0x85, 0x00, 0x70, 0x69, 0x73, 0x00, 0x61, 0x63, -0x74, 0x75, 0x65, 0x00, 0x00, 0xca, 0x02, 0x41, 0x6f, 0x6f, -0x64, 0x00, 0xcb, 0x00, 0x04, 0xaa, 0x00, 0xb0, 0x69, 0x74, -0x00, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0xd9, -0x00, 0x30, 0x00, 0x66, 0x72, 0x6d, 0x00, 0x40, 0x75, 0x65, -0x73, 0x73, 0xf0, 0x00, 0x00, 0xb1, 0x00, 0x30, 0x63, 0x6f, -0x6c, 0x09, 0x02, 0x06, 0x77, 0x00, 0x62, 0x00, 0x62, 0x61, -0x73, 0x65, 0x64, 0x82, 0x02, 0x14, 0x65, 0x28, 0x01, 0x50, -0x2c, 0x00, 0x61, 0x6e, 0x64, 0xe2, 0x01, 0x22, 0x63, 0x65, -0x49, 0x00, 0x20, 0x74, 0x6f, 0x99, 0x00, 0xf0, 0x0f, 0x00, -0x6c, 0x6f, 0x67, 0x69, 0x63, 0x00, 0x69, 0x6e, 0x73, 0x74, -0x65, 0x61, 0x64, 0x2e, 0x29, 0x00, 0x54, 0x68, 0x65, 0x00, -0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, 0x67, 0x65, 0xf7, -0x00, 0x51, 0x6f, 0x75, 0x67, 0x68, 0x2c, 0x63, 0x02, 0x00, -0xb4, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x6e, 0x4a, 0x01, 0x00, -0xa4, 0x02, 0x01, 0x9b, 0x01, 0x23, 0x6f, 0x66, 0x63, 0x01, -0x65, 0x00, 0x00, 0x31, 0x30, 0x2e, 0x31, 0xa3, 0x03, 0x80, -0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0xac, 0x03, -0x10, 0x54, 0xea, 0x00, 0x10, 0x67, 0x42, 0x02, 0x11, 0x69, +0x6e, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x3b, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, +0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x77, +0x68, 0x69, 0x63, 0x68, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, +0x61, 0x6c, 0x6c, 0x00, 0x62, 0x65, 0x00, 0x66, 0x69, 0x6c, +0x6c, 0x65, 0x64, 0x00, 0x69, 0x6e, 0x00, 0x65, 0x69, 0x74, +0x68, 0x65, 0x72, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x00, +0x6f, 0x72, 0x2c, 0x00, 0xf0, 0x04, 0x74, 0x65, 0x2e, 0x00, +0x42, 0x65, 0x73, 0x69, 0x64, 0x65, 0x00, 0x65, 0x61, 0x63, +0x68, 0x00, 0x72, 0x6f, 0x77, 0x4f, 0x00, 0x32, 0x74, 0x68, +0x65, 0x5b, 0x00, 0xb0, 0x61, 0x72, 0x65, 0x00, 0x6c, 0x69, +0x73, 0x74, 0x65, 0x64, 0x2c, 0x42, 0x00, 0x61, 0x6f, 0x72, +0x64, 0x65, 0x72, 0x2c, 0x1f, 0x00, 0x74, 0x6c, 0x65, 0x6e, +0x67, 0x74, 0x68, 0x73, 0x2e, 0x00, 0x31, 0x72, 0x75, 0x6e, +0x0c, 0x00, 0x02, 0x5d, 0x00, 0x03, 0x8f, 0x00, 0x80, 0x00, +0x6f, 0x6e, 0x00, 0x74, 0x68, 0x61, 0x74, 0x57, 0x00, 0x63, +0x3b, 0x00, 0x61, 0x62, 0x6f, 0x76, 0x67, 0x00, 0x6f, 0x63, +0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5e, 0x00, 0x2d, 0x13, 0x69, +0x5e, 0x00, 0x02, 0x4e, 0x00, 0x10, 0x2e, 0x18, 0x01, 0xb1, +0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, +0x6f, 0xf9, 0x00, 0x02, 0x24, 0x00, 0x73, 0x65, 0x00, 0x65, +0x6e, 0x74, 0x69, 0x72, 0xd4, 0x00, 0x0c, 0x00, 0x01, 0xf1, +0x22, 0x00, 0x00, 0x49, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, +0x00, 0x73, 0x61, 0x77, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, +0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x66, 0x6f, 0x72, +0x6d, 0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x31, +0x39, 0x39, 0x35, 0x2c, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, +0x52, 0x00, 0xf0, 0x0f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x60, +0x6e, 0x6f, 0x6e, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x27, +0x2e, 0x00, 0x49, 0x27, 0x76, 0x65, 0x00, 0x73, 0x65, 0x65, +0x6e, 0x00, 0x69, 0x74, 0x78, 0x00, 0xf0, 0x05, 0x76, 0x61, +0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x70, 0x6c, 0x61, 0x63, +0x65, 0x73, 0x00, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x00, +0x14, 0x6e, 0x47, 0x00, 0x91, 0x64, 0x69, 0x66, 0x66, 0x65, +0x72, 0x65, 0x6e, 0x74, 0x4d, 0x00, 0x10, 0x73, 0x8a, 0x00, +0x93, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x6c, 0x79, 0x2c, +0x83, 0x00, 0x03, 0x02, 0x01, 0x00, 0xd1, 0x00, 0xc0, 0x79, +0x70, 0x65, 0x00, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x6f, 0x75, +0x74, 0xdf, 0x00, 0x10, 0x62, 0x00, 0x02, 0xf1, 0x03, 0x6d, +0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x00, +0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x0e, 0x02, 0xa0, +0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x6f, +0x74, 0x00, 0x31, 0x79, 0x6f, 0x75, 0x9b, 0x00, 0x50, 0x6f, +0x6c, 0x76, 0x65, 0x64, 0x82, 0x00, 0x80, 0x6d, 0x2e, 0x00, +0x48, 0x6f, 0x77, 0x65, 0x76, 0x6e, 0x01, 0x04, 0x97, 0x00, +0xf1, 0x05, 0x69, 0x73, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, +0x6f, 0x6e, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, +0x65, 0x73, 0xe9, 0x00, 0x04, 0x89, 0x00, 0x92, 0x61, 0x75, +0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0xa0, 0x00, 0x60, +0x74, 0x68, 0x65, 0x79, 0x00, 0x77, 0x63, 0x01, 0x10, 0x6a, +0x6d, 0x02, 0xf7, 0x0b, 0x6c, 0x6f, 0x6f, 0x6b, 0x00, 0x6c, +0x69, 0x6b, 0x65, 0x00, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, +0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x67, 0x73, +0x9f, 0x02, 0xf0, 0x06, 0x2e, 0x00, 0x28, 0x4f, 0x6e, 0x65, +0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x68, 0x61, 0x73, 0x00, +0x73, 0x75, 0x67, 0x67, 0x65, 0xff, 0x01, 0x02, 0xc8, 0x01, +0x01, 0x85, 0x00, 0x70, 0x69, 0x73, 0x00, 0x61, 0x63, 0x74, +0x75, 0x65, 0x00, 0x00, 0xe0, 0x02, 0x41, 0x6f, 0x6f, 0x64, +0x00, 0xcb, 0x00, 0x04, 0xaa, 0x00, 0xb0, 0x69, 0x74, 0x00, +0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0xd9, 0x00, +0x30, 0x00, 0x66, 0x72, 0x6d, 0x00, 0x40, 0x75, 0x65, 0x73, +0x73, 0xf0, 0x00, 0x00, 0xb1, 0x00, 0x30, 0x63, 0x6f, 0x6c, +0x09, 0x02, 0x06, 0x77, 0x00, 0x62, 0x00, 0x62, 0x61, 0x73, +0x65, 0x64, 0x8d, 0x02, 0x14, 0x65, 0x28, 0x01, 0x50, 0x2c, +0x00, 0x61, 0x6e, 0x64, 0xe2, 0x01, 0x22, 0x63, 0x65, 0x49, +0x00, 0x20, 0x74, 0x6f, 0x99, 0x00, 0xf0, 0x0f, 0x00, 0x6c, +0x6f, 0x67, 0x69, 0x63, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x65, +0x61, 0x64, 0x2e, 0x29, 0x00, 0x54, 0x68, 0x65, 0x00, 0x61, +0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, 0x67, 0x65, 0xf7, 0x00, +0x51, 0x6f, 0x75, 0x67, 0x68, 0x2c, 0x63, 0x02, 0x00, 0xb4, +0x00, 0x00, 0x3a, 0x00, 0x10, 0x6e, 0x4a, 0x01, 0x00, 0xa4, +0x02, 0x01, 0x9b, 0x01, 0x23, 0x6f, 0x66, 0x63, 0x01, 0x65, +0x00, 0x00, 0x31, 0x30, 0x2e, 0x31, 0xcd, 0x03, 0xd0, 0x63, +0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, +0x00, 0x54, 0xea, 0x00, 0x10, 0x67, 0x42, 0x02, 0x11, 0x69, 0x20, 0x02, 0x81, 0x79, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, 0xa1, 0x00, 0x41, 0x6d, 0x6f, 0x75, 0x73, 0x97, 0x02, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, @@ -111,7 +113,7 @@ const char help_text[] = { 0x74, 0x00, 0x67, 0x72, 0x65, 0x79, 0x00, 0x28, 0xb2, 0x02, 0x20, 0x00, 0x60, 0x04, 0x03, 0xe3, 0x63, 0x69, 0x64, 0x65, 0x64, 0x27, 0x29, 0x00, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2e, -0xc5, 0x04, 0x00, 0x91, 0x00, 0x02, 0xca, 0x00, 0x00, 0xa2, +0xdb, 0x04, 0x00, 0x91, 0x00, 0x02, 0xca, 0x00, 0x00, 0xa2, 0x01, 0x46, 0x64, 0x72, 0x61, 0x67, 0x1c, 0x01, 0x40, 0x6c, 0x65, 0x66, 0x74, 0xa0, 0x00, 0x10, 0x72, 0xf0, 0x00, 0x02, 0x2a, 0x01, 0x03, 0x84, 0x00, 0x07, 0x83, 0x00, 0x10, 0x61, @@ -126,8 +128,8 @@ const char help_text[] = { 0x6f, 0x01, 0x05, 0xa8, 0x00, 0xe9, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x9c, 0x00, 0x00, 0x2e, 0x01, 0x08, 0x12, 0x01, 0x60, 0x61, -0x6c, 0x73, 0x6f, 0x00, 0x6d, 0x37, 0x05, 0x03, 0x91, 0x04, -0x05, 0x8e, 0x05, 0x05, 0x39, 0x02, 0xf7, 0x00, 0x63, 0x75, +0x6c, 0x73, 0x6f, 0x00, 0x6d, 0x42, 0x05, 0x03, 0x91, 0x04, +0x05, 0xa4, 0x05, 0x05, 0x39, 0x02, 0xf7, 0x00, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x00, 0x50, 0x72, 0x13, 0x03, 0x21, 0x72, 0x65, 0x3a, 0x04, 0x14, 0x6b, 0xb3, 0x03, 0x54, 0x63, 0x79, 0x63, 0x6c, 0x65, @@ -148,8 +150,8 @@ const char help_text[] = { 0x6f, 0x74, 0x68, 0x3b, 0x00, 0x15, 0x6d, 0x87, 0x01, 0x21, 0x28, 0x41, 0x20, 0x01, 0x10, 0x65, 0x9d, 0x04, 0xc2, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x44, 0x07, 0x21, 0x73, 0x65, 0x16, 0x00, 0x41, 0x00, -0x32, 0x2e, 0x31, 0xca, 0x06, 0x01, 0xad, 0x01, 0xb2, 0x61, +0x62, 0x5a, 0x07, 0x21, 0x73, 0x65, 0x16, 0x00, 0x41, 0x00, +0x32, 0x2e, 0x31, 0xd5, 0x06, 0x01, 0xad, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x0c, 0x04, 0x15, 0x32, 0x0c, 0x04, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0e, 0x04, 0x92, 0x65, @@ -159,11 +161,11 @@ const char help_text[] = { 0x27, 0x27, 0x00, 0x04, 0xd0, 0x04, 0xb1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x7c, 0x00, 0x31, 0x57, 0x69, 0x64, 0x9d, 0x03, 0x40, 0x64, 0x00, 0x48, -0x65, 0x26, 0x03, 0x04, 0xfe, 0x07, 0x00, 0x1c, 0x00, 0xf0, +0x65, 0x26, 0x03, 0x04, 0x14, 0x08, 0x00, 0x1c, 0x00, 0xf0, 0x03, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x00, }; -const unsigned short help_text_len = 2125; -const unsigned short help_text_words = 384; +const unsigned short help_text_len = 2167; +const unsigned short help_text_words = 389; const char quick_help_text[] = "Fill in the pattern in the grid, given only the lengths of runs of black squares."; diff --git a/apps/plugins/puzzles/help/pearl.c b/apps/plugins/puzzles/help/pearl.c index 353c541d47..b8f32ce3b8 100644 --- a/apps/plugins/puzzles/help/pearl.c +++ b/apps/plugins/puzzles/help/pearl.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,180 +6,247 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 138, TEXT_UNDERLINE }, - { 164, TEXT_UNDERLINE }, - { 185, TEXT_UNDERLINE }, - { 223, TEXT_CENTER | C_RED }, - { 369, TEXT_UNDERLINE }, - { 460, TEXT_CENTER | C_RED }, + { 139, TEXT_UNDERLINE }, + { 165, TEXT_UNDERLINE }, + { 186, TEXT_UNDERLINE }, + { 221, TEXT_CENTER | C_RED }, + { 367, TEXT_UNDERLINE }, + { 458, TEXT_CENTER | C_RED }, + { 475, TEXT_UNDERLINE }, + { 476, TEXT_UNDERLINE }, + { 486, TEXT_UNDERLINE }, + { 498, TEXT_UNDERLINE }, + { 586, TEXT_CENTER | C_RED }, + { 652, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2570 comp 1610 ratio 0.626459 level 10 saved 960 */ +/* orig 3598 comp 2217 ratio 0.616176 level 10 saved 1381 */ const char help_text[] = { -0xf0, 0x21, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x36, 0x3a, 0x20, 0x50, 0x65, 0x61, 0x72, 0x6c, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, -0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, -0x1c, 0x00, 0xf0, 0x1b, 0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, -0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x64, 0x72, 0x61, 0x77, -0x00, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x00, 0x62, 0x65, 0x74, -0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x68, 0x65, 0x00, 0x63, -0x65, 0x6e, 0x74, 0x72, 0x65, 0x73, 0x3a, 0x00, 0xf1, 0x07, -0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, -0x6c, 0x79, 0x00, 0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, 0x74, -0x69, 0x63, 0x0e, 0x00, 0x40, 0x61, 0x64, 0x6a, 0x61, 0x2a, -0x00, 0x04, 0x5e, 0x00, 0x91, 0x2c, 0x00, 0x73, 0x6f, 0x00, -0x74, 0x68, 0x61, 0x74, 0x44, 0x00, 0x02, 0x56, 0x00, 0xf2, -0x0d, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x61, 0x00, 0x73, 0x69, -0x6e, 0x67, 0x6c, 0x65, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, -0x64, 0x00, 0x6c, 0x6f, 0x6f, 0x70, 0x2e, 0x00, 0x49, 0x6c, -0x00, 0x91, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, -0x67, 0xad, 0x00, 0x00, 0x44, 0x00, 0x20, 0x6d, 0x65, 0x79, -0x00, 0x00, 0x1c, 0x00, 0x03, 0x59, 0x00, 0x07, 0x55, 0x00, -0x81, 0x6f, 0x6f, 0x70, 0x00, 0x70, 0x61, 0x73, 0x73, 0x15, -0x00, 0xc0, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x77, 0x69, -0x6c, 0x6c, 0x00, 0x63, 0xa3, 0x00, 0xf2, 0x00, 0x69, 0x6e, -0x00, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0x73, 0x2c, 0x00, -0x61, 0x6e, 0x64, 0x4b, 0x00, 0x01, 0x1f, 0x00, 0xb7, 0x62, -0x65, 0x00, 0x73, 0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, -0xd2, 0x00, 0x08, 0xd0, 0x00, 0x02, 0xb0, 0x00, 0x44, 0x2e, -0x00, 0x28, 0x41, 0x39, 0x00, 0x04, 0x7d, 0x00, 0x30, 0x63, -0x61, 0x6e, 0x40, 0x00, 0xf6, 0x03, 0x63, 0x6f, 0x6d, 0x70, -0x6c, 0x65, 0x74, 0x65, 0x6c, 0x79, 0x00, 0x65, 0x6d, 0x70, -0x74, 0x79, 0x00, 0x2d, 0x92, 0x00, 0x72, 0x64, 0x6f, 0x65, -0x73, 0x6e, 0x27, 0x74, 0x76, 0x01, 0x21, 0x74, 0x6f, 0xa2, -0x00, 0x05, 0xa0, 0x00, 0x53, 0x65, 0x76, 0x65, 0x72, 0x79, -0x4e, 0x00, 0x6e, 0x2e, 0x29, 0x00, 0x00, 0x00, 0x53, 0xe2, -0x00, 0x05, 0xc0, 0x00, 0x51, 0x62, 0x6c, 0x61, 0x63, 0x6b, -0xbd, 0x00, 0xb0, 0x77, 0x68, 0x69, 0x74, 0x65, 0x00, 0x63, -0x69, 0x72, 0x63, 0x6c, 0x5b, 0x01, 0x80, 0x77, 0x68, 0x69, -0x63, 0x68, 0x00, 0x61, 0x72, 0x45, 0x01, 0x1d, 0x75, 0x13, -0x01, 0xf3, 0x02, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x73, 0x61, -0x74, 0x69, 0x73, 0x66, 0x79, 0x2e, 0x00, 0x00, 0x00, 0x41, -0x49, 0x00, 0x02, 0x3f, 0x00, 0x53, 0x00, 0x69, 0x6e, 0x00, -0x61, 0x6b, 0x00, 0x86, 0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, -0x61, 0x74, 0x43, 0x00, 0x14, 0x61, 0xc1, 0x01, 0x00, 0x14, -0x02, 0x13, 0x61, 0x42, 0x01, 0xdc, 0x2c, 0x00, 0x62, 0x75, -0x74, 0x00, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0xad, -0x00, 0x05, 0xf9, 0x01, 0x50, 0x74, 0x6f, 0x00, 0x69, 0x74, -0x5e, 0x00, 0x05, 0x89, 0x00, 0x00, 0x43, 0x00, 0x35, 0x6c, -0x73, 0x6f, 0x48, 0x00, 0x02, 0x8d, 0x00, 0x08, 0xcc, 0x00, -0x0e, 0x81, 0x00, 0x19, 0x65, 0x80, 0x00, 0x05, 0xa8, 0x01, -0x42, 0x65, 0x64, 0x67, 0x65, 0x87, 0x00, 0xcf, 0x61, 0x74, -0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, -0x8c, 0x00, 0x1c, 0x07, 0x87, 0x00, 0xc0, 0x28, 0x49, 0x6e, -0x00, 0x62, 0x6f, 0x74, 0x68, 0x00, 0x63, 0x61, 0x73, 0x52, -0x01, 0x22, 0x74, 0x68, 0x4c, 0x01, 0x50, 0x00, 0x6f, 0x6e, -0x6c, 0x79, 0x81, 0x01, 0x01, 0x7a, 0x00, 0x21, 0x6e, 0x73, -0x19, 0x00, 0x3e, 0x74, 0x77, 0x6f, 0x63, 0x00, 0x70, 0x69, -0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5d, 0x00, 0x12, 0x2c, -0xbd, 0x00, 0x3f, 0x69, 0x73, 0x2c, 0xa9, 0x02, 0x0f, 0xf0, -0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, 0x61, 0x66, 0x74, 0x65, -0x72, 0x00, 0x6c, 0x65, 0x61, 0x76, 0xeb, 0x02, 0x05, 0x7c, -0x00, 0x03, 0x17, 0x02, 0x2c, 0x00, 0x54, 0x45, 0x00, 0x23, -0x61, 0x72, 0x99, 0x00, 0x0c, 0x7e, 0x00, 0x01, 0xd3, 0x03, -0x00, 0x1e, 0x00, 0x36, 0x6e, 0x6f, 0x74, 0xb6, 0x00, 0x21, -0x65, 0x64, 0x5b, 0x02, 0x60, 0x43, 0x72, 0x65, 0x64, 0x69, -0x74, 0x76, 0x03, 0xf1, 0x01, 0x00, 0x74, 0x68, 0x69, 0x73, -0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, -0x65, 0xef, 0x03, 0x60, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, -0x4d, 0x02, 0x20, 0x6f, 0x00, 0xc4, 0x03, 0x00, 0x32, 0x01, -0xf1, 0x06, 0x60, 0x4d, 0x61, 0x73, 0x79, 0x75, 0x27, 0x2e, -0x00, 0x5b, 0x31, 0x39, 0x5d, 0x00, 0x00, 0x00, 0x54, 0x68, -0x61, 0x6e, 0x6b, 0x2e, 0x00, 0xc1, 0x4a, 0x61, 0x6d, 0x65, -0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x53, 0x00, -0x90, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, -0x56, 0x03, 0x21, 0x74, 0x68, 0xc6, 0x00, 0x10, 0x69, 0x16, -0x03, 0x90, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, -0x6e, 0x68, 0x01, 0x01, 0x48, 0x00, 0xc1, 0x68, 0x74, 0x74, -0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x75, -0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, -0x6e, 0x2f, 0x94, 0x00, 0x30, 0x73, 0x2f, 0x6d, 0x78, 0x00, -0xc1, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, 0x28, 0x62, 0x65, -0x77, 0x61, 0x72, 0xdc, 0x01, 0x50, 0x46, 0x6c, 0x61, 0x73, -0x68, 0xcb, 0x00, 0x43, 0x33, 0x36, 0x2e, 0x31, 0xd4, 0x04, -0x00, 0x1d, 0x03, 0x50, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0xe2, -0x00, 0x46, 0x6c, 0x69, 0x63, 0x6b, 0x7f, 0x00, 0x40, 0x6c, -0x65, 0x66, 0x74, 0x24, 0x02, 0x64, 0x74, 0x6f, 0x6e, 0x00, -0x6f, 0x6e, 0xf2, 0x04, 0x00, 0x3b, 0x02, 0x05, 0xdf, 0x04, -0x50, 0x61, 0x00, 0x73, 0x65, 0x67, 0xa2, 0x00, 0x04, 0x3b, -0x02, 0x01, 0x9c, 0x01, 0x04, 0x9e, 0x03, 0x01, 0x6d, 0x01, -0x02, 0x6b, 0x02, 0x20, 0x6f, 0x72, 0x34, 0x00, 0x68, 0x72, -0x65, 0x6d, 0x6f, 0x76, 0x65, 0x36, 0x00, 0x00, 0xf0, 0x00, -0x10, 0x69, 0xec, 0x01, 0x01, 0x50, 0x00, 0x01, 0xe4, 0x00, -0x4f, 0x44, 0x72, 0x61, 0x67, 0x85, 0x00, 0x03, 0x04, 0x58, -0x00, 0x00, 0x40, 0x00, 0x47, 0x72, 0x69, 0x65, 0x73, 0x7e, -0x05, 0x05, 0x92, 0x00, 0x40, 0x6d, 0x6f, 0x72, 0x65, 0x79, -0x00, 0x00, 0xb3, 0x00, 0x1f, 0x65, 0x9e, 0x00, 0x02, 0x12, -0x69, 0x1b, 0x00, 0xf0, 0x05, 0x67, 0x6f, 0x2e, 0x00, 0x41, -0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, -0x6c, 0x79, 0x2c, 0x00, 0x64, 0x7a, 0x00, 0xc1, 0x6f, 0x76, -0x65, 0x72, 0x00, 0x61, 0x6e, 0x00, 0x65, 0x78, 0x69, 0x73, -0x3b, 0x05, 0x3b, 0x70, 0x61, 0x72, 0xdf, 0x00, 0x41, 0x6f, -0x00, 0x75, 0x6e, 0x6d, 0x00, 0x24, 0x69, 0x74, 0xda, 0x00, -0x03, 0x11, 0x00, 0x04, 0x2c, 0x00, 0x21, 0x69, 0x74, 0x68, -0x04, 0x72, 0x74, 0x68, 0x65, 0x6e, 0x00, 0x67, 0x6f, 0x24, -0x04, 0x60, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x8e, 0x00, -0x54, 0x64, 0x69, 0x72, 0x65, 0x63, 0xd3, 0x01, 0x0b, 0x75, -0x01, 0x11, 0x72, 0xa0, 0x03, 0x0f, 0x76, 0x01, 0x06, 0x40, -0x6d, 0x61, 0x72, 0x6b, 0x5e, 0x00, 0x01, 0x30, 0x00, 0x84, -0x61, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x2c, 0xf7, 0x03, -0x02, 0xfe, 0x02, 0x61, 0x61, 0x74, 0x00, 0x79, 0x6f, 0x75, -0xc7, 0x02, 0x4a, 0x73, 0x75, 0x72, 0x65, 0x4a, 0x05, 0x01, -0xda, 0x02, 0x2e, 0x67, 0x6f, 0xa3, 0x01, 0x92, 0x2e, 0x00, -0x28, 0x46, 0x6f, 0x72, 0x00, 0x69, 0x6e, 0x85, 0x02, 0x64, -0x2c, 0x00, 0x69, 0x66, 0x00, 0x79, 0xed, 0x06, 0x73, 0x64, -0x65, 0x63, 0x69, 0x64, 0x65, 0x64, 0x29, 0x05, 0x0f, 0x26, -0x04, 0x08, 0x14, 0x61, 0x8f, 0x04, 0x00, 0x80, 0x03, 0x21, -0x68, 0x61, 0x97, 0x01, 0x2b, 0x62, 0x65, 0xfa, 0x04, 0x20, -0x64, 0x6f, 0xd0, 0x05, 0x83, 0x79, 0x65, 0x74, 0x00, 0x6b, -0x6e, 0x6f, 0x77, 0x55, 0x00, 0x32, 0x77, 0x61, 0x79, 0xba, -0x03, 0x01, 0x29, 0x00, 0x71, 0x00, 0x74, 0x75, 0x72, 0x6e, -0x73, 0x2c, 0x82, 0x00, 0x11, 0x6d, 0x12, 0x01, 0x01, 0xf9, -0x00, 0x00, 0x21, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x2d, 0x00, -0x20, 0x69, 0x74, 0x3e, 0x06, 0x11, 0x27, 0xce, 0x00, 0x08, -0x0e, 0x01, 0x01, 0xac, 0x03, 0x0b, 0xd9, 0x01, 0x32, 0x75, -0x73, 0x65, 0x5d, 0x00, 0x91, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x00, 0x6b, 0x65, 0x79, 0x9a, 0x00, 0x01, 0x8d, 0x02, 0x06, -0x18, 0x00, 0x33, 0x2e, 0x00, 0x55, 0x28, 0x00, 0x41, 0x45, -0x6e, 0x74, 0x65, 0x27, 0x00, 0x02, 0xc0, 0x00, 0x31, 0x67, -0x69, 0x6e, 0xcf, 0x01, 0x30, 0x65, 0x6e, 0x64, 0x15, 0x00, -0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x60, 0x2e, 0x02, -0x61, 0x27, 0x00, 0x6f, 0x70, 0x65, 0x72, 0x9f, 0x03, 0x16, -0x73, 0x3f, 0x00, 0x30, 0x53, 0x70, 0x61, 0x42, 0x01, 0x60, -0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x21, 0x02, 0x50, 0x42, -0x61, 0x63, 0x6b, 0x73, 0x15, 0x00, 0x05, 0x7b, 0x00, 0x10, -0x63, 0x65, 0x01, 0x11, 0x6c, 0x2e, 0x00, 0x00, 0x48, 0x00, -0xc2, 0x2e, 0x00, 0x4f, 0x72, 0x2c, 0x00, 0x68, 0x6f, 0x6c, -0x64, 0x00, 0x43, 0x91, 0x03, 0x00, 0x17, 0x01, 0x12, 0x6c, -0x1d, 0x00, 0x37, 0x67, 0x69, 0x6e, 0x11, 0x03, 0x0b, 0xc4, -0x00, 0x55, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0xe9, 0x02, 0x42, -0x73, 0x00, 0x61, 0x73, 0x35, 0x01, 0x00, 0xdb, 0x00, 0x04, -0x77, 0x08, 0x05, 0xa2, 0x08, 0x60, 0x00, 0x00, 0x50, 0x72, -0x65, 0x73, 0x31, 0x08, 0x04, 0x67, 0x00, 0xe1, 0x2d, 0x53, -0x68, 0x69, 0x66, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x6f, 0x77, -0x6b, 0x65, 0x86, 0x08, 0x0b, 0x12, 0x00, 0x51, 0x73, 0x69, -0x6d, 0x75, 0x6c, 0x53, 0x06, 0x12, 0x61, 0x8d, 0x03, 0x23, -0x6f, 0x72, 0xa5, 0x02, 0x10, 0x63, 0xba, 0x02, 0x10, 0x2c, -0x65, 0x08, 0x34, 0x70, 0x65, 0x63, 0x6b, 0x01, 0x12, 0x6f, -0x25, 0x06, 0x01, 0xb0, 0x02, 0x03, 0x31, 0x06, 0x05, 0xef, -0x02, 0x04, 0x3a, 0x02, 0x31, 0x6b, 0x65, 0x79, 0x35, 0x06, -0x22, 0x41, 0x6c, 0x02, 0x01, 0x21, 0x61, 0x63, 0x41, 0x01, -0xa0, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, -0x64, 0x3a, 0x00, 0x13, 0x73, 0x34, 0x00, 0x31, 0x32, 0x2e, -0x31, 0xcc, 0x02, 0x02, 0xfb, 0x06, 0x93, 0x76, 0x61, 0x69, -0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0xc7, 0x04, 0x13, 0x32, -0xc7, 0x04, 0xb1, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, -0x65, 0x72, 0x73, 0x20, 0x68, 0x05, 0x46, 0x65, 0x73, 0x65, -0x00, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x51, -0x00, 0x66, 0x72, 0x6f, 0x6d, 0x79, 0x00, 0xa0, 0x60, 0x43, -0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0xc9, 0x01, -0x02, 0xa3, 0x00, 0x12, 0x6e, 0x1a, 0x00, 0xc0, 0x54, 0x79, -0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x2e, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, 0x1c, 0x00, 0xf0, 0x1b, +0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, 0x00, 0x74, +0x6f, 0x00, 0x64, 0x72, 0x61, 0x77, 0x00, 0x6c, 0x69, 0x6e, +0x65, 0x73, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, +0x00, 0x74, 0x68, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x74, 0x72, +0x65, 0x73, 0x3a, 0x00, 0xf1, 0x07, 0x68, 0x6f, 0x72, 0x69, +0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x6f, +0x72, 0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, +0x40, 0x61, 0x64, 0x6a, 0x61, 0x2a, 0x00, 0x04, 0x5e, 0x00, +0x91, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x74, 0x68, 0x61, 0x74, +0x44, 0x00, 0x02, 0x56, 0x00, 0xf2, 0x0d, 0x66, 0x6f, 0x72, +0x6d, 0x00, 0x61, 0x00, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, +0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x00, 0x6c, 0x6f, +0x6f, 0x70, 0x2e, 0x00, 0x49, 0x6c, 0x00, 0x91, 0x72, 0x65, +0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0xad, 0x00, 0x00, +0x44, 0x00, 0x20, 0x6d, 0x65, 0x79, 0x00, 0x00, 0x1c, 0x00, +0x03, 0x59, 0x00, 0x07, 0x55, 0x00, 0x81, 0x6f, 0x6f, 0x70, +0x00, 0x70, 0x61, 0x73, 0x73, 0x15, 0x00, 0xc0, 0x72, 0x6f, +0x75, 0x67, 0x68, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x63, +0xa3, 0x00, 0xf2, 0x00, 0x69, 0x6e, 0x00, 0x63, 0x6f, 0x72, +0x6e, 0x65, 0x72, 0x73, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x4b, +0x00, 0x01, 0x1f, 0x00, 0xb7, 0x62, 0x65, 0x00, 0x73, 0x74, +0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0xd2, 0x00, 0x08, 0xd0, +0x00, 0x02, 0xb0, 0x00, 0x44, 0x2e, 0x00, 0x28, 0x41, 0x39, +0x00, 0x04, 0x7d, 0x00, 0x30, 0x63, 0x61, 0x6e, 0x40, 0x00, +0xf6, 0x03, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, +0x6c, 0x79, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00, 0x2d, +0x92, 0x00, 0x72, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, +0x76, 0x01, 0x21, 0x74, 0x6f, 0xa2, 0x00, 0x05, 0xa0, 0x00, +0x53, 0x65, 0x76, 0x65, 0x72, 0x79, 0x4e, 0x00, 0x6e, 0x2e, +0x29, 0x00, 0x00, 0x00, 0x53, 0xe2, 0x00, 0x05, 0xc0, 0x00, +0x51, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0xbd, 0x00, 0xb0, 0x77, +0x68, 0x69, 0x74, 0x65, 0x00, 0x63, 0x69, 0x72, 0x63, 0x6c, +0x5b, 0x01, 0x80, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x61, +0x72, 0x45, 0x01, 0x1d, 0x75, 0x13, 0x01, 0xf3, 0x02, 0x6d, +0x75, 0x73, 0x74, 0x00, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, +0x79, 0x2e, 0x00, 0x00, 0x00, 0x41, 0x49, 0x00, 0x02, 0x3f, +0x00, 0x53, 0x00, 0x69, 0x6e, 0x00, 0x61, 0x6b, 0x00, 0x86, +0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x43, 0x00, +0x14, 0x61, 0xc1, 0x01, 0x00, 0x14, 0x02, 0x13, 0x61, 0x42, +0x01, 0xdc, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x6e, 0x65, +0x69, 0x74, 0x68, 0x65, 0x72, 0xad, 0x00, 0x05, 0xf9, 0x01, +0x50, 0x74, 0x6f, 0x00, 0x69, 0x74, 0x5e, 0x00, 0x05, 0x89, +0x00, 0x00, 0x43, 0x00, 0x35, 0x6c, 0x73, 0x6f, 0x48, 0x00, +0x02, 0x8d, 0x00, 0x08, 0xcc, 0x00, 0x0e, 0x81, 0x00, 0x19, +0x65, 0x80, 0x00, 0x05, 0xa8, 0x01, 0x42, 0x65, 0x64, 0x67, +0x65, 0x87, 0x00, 0xcf, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, +0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x8c, 0x00, 0x1c, 0x07, +0x87, 0x00, 0xc0, 0x28, 0x49, 0x6e, 0x00, 0x62, 0x6f, 0x74, +0x68, 0x00, 0x63, 0x61, 0x73, 0x52, 0x01, 0x22, 0x74, 0x68, +0x4c, 0x01, 0x50, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x81, 0x01, +0x01, 0x7a, 0x00, 0x21, 0x6e, 0x73, 0x19, 0x00, 0x3e, 0x74, +0x77, 0x6f, 0x63, 0x00, 0x70, 0x69, 0x6e, 0x20, 0x74, 0x68, +0x65, 0x20, 0x5d, 0x00, 0x12, 0x2c, 0xbd, 0x00, 0x3f, 0x69, +0x73, 0x2c, 0xa9, 0x02, 0x0f, 0xf0, 0x00, 0x69, 0x6e, 0x74, +0x6f, 0x00, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x6c, 0x65, +0x61, 0x76, 0xeb, 0x02, 0x05, 0x7c, 0x00, 0x03, 0x17, 0x02, +0x2c, 0x00, 0x54, 0x45, 0x00, 0x23, 0x61, 0x72, 0x99, 0x00, +0x0c, 0x7e, 0x00, 0x01, 0xd3, 0x03, 0x00, 0x1e, 0x00, 0x36, +0x6e, 0x6f, 0x74, 0xb6, 0x00, 0x21, 0x65, 0x64, 0x5b, 0x02, +0x60, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x76, 0x03, 0xf1, +0x01, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, +0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0xef, 0x03, 0x60, +0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x4d, 0x02, 0x20, 0x6f, +0x00, 0xc4, 0x03, 0x00, 0x32, 0x01, 0xf1, 0x06, 0x60, 0x4d, +0x61, 0x73, 0x79, 0x75, 0x27, 0x2e, 0x00, 0x5b, 0x31, 0x39, +0x5d, 0x00, 0x00, 0x00, 0x54, 0x68, 0x61, 0x6e, 0x6b, 0x2e, +0x00, 0xc1, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, +0x72, 0x76, 0x65, 0x79, 0x53, 0x00, 0x90, 0x61, 0x73, 0x73, +0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x56, 0x03, 0x21, 0x74, +0x68, 0xc6, 0x00, 0x10, 0x69, 0x16, 0x03, 0x90, 0x6d, 0x65, +0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x68, 0x01, 0x01, +0x48, 0x00, 0xd1, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, +0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x76, 0x00, 0xa2, 0x2e, +0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0x95, +0x00, 0x30, 0x73, 0x2f, 0x6d, 0x79, 0x00, 0x83, 0x2f, 0x00, +0x00, 0x00, 0x33, 0x36, 0x2e, 0x31, 0xd1, 0x04, 0x00, 0x08, +0x03, 0x50, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0xcd, 0x00, 0x46, +0x6c, 0x69, 0x63, 0x6b, 0x6a, 0x00, 0x40, 0x6c, 0x65, 0x66, +0x74, 0x0f, 0x02, 0x64, 0x74, 0x6f, 0x6e, 0x00, 0x6f, 0x6e, +0xdd, 0x04, 0x00, 0x26, 0x02, 0x05, 0xca, 0x04, 0x50, 0x61, +0x00, 0x73, 0x65, 0x67, 0x8d, 0x00, 0x04, 0x26, 0x02, 0x01, +0x87, 0x01, 0x04, 0x89, 0x03, 0x01, 0x58, 0x01, 0x02, 0x56, +0x02, 0x20, 0x6f, 0x72, 0x34, 0x00, 0x68, 0x72, 0x65, 0x6d, +0x6f, 0x76, 0x65, 0x36, 0x00, 0x00, 0xdb, 0x00, 0x10, 0x69, +0xd7, 0x01, 0x01, 0x50, 0x00, 0x01, 0xcf, 0x00, 0x4f, 0x44, +0x72, 0x61, 0x67, 0x85, 0x00, 0x03, 0x04, 0x58, 0x00, 0x00, +0x40, 0x00, 0x47, 0x72, 0x69, 0x65, 0x73, 0x69, 0x05, 0x05, +0x92, 0x00, 0x40, 0x6d, 0x6f, 0x72, 0x65, 0x79, 0x00, 0x00, +0xb3, 0x00, 0x1f, 0x65, 0x9e, 0x00, 0x02, 0x12, 0x69, 0x1b, +0x00, 0xf0, 0x05, 0x67, 0x6f, 0x2e, 0x00, 0x41, 0x6c, 0x74, +0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, +0x2c, 0x00, 0x64, 0x7a, 0x00, 0xc1, 0x6f, 0x76, 0x65, 0x72, +0x00, 0x61, 0x6e, 0x00, 0x65, 0x78, 0x69, 0x73, 0x26, 0x05, +0x3b, 0x70, 0x61, 0x72, 0xdf, 0x00, 0x41, 0x6f, 0x00, 0x75, +0x6e, 0x6d, 0x00, 0x24, 0x69, 0x74, 0xda, 0x00, 0x03, 0x11, +0x00, 0x04, 0x2c, 0x00, 0x21, 0x69, 0x74, 0x53, 0x04, 0x72, +0x74, 0x68, 0x65, 0x6e, 0x00, 0x67, 0x6f, 0x0f, 0x04, 0x60, +0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x8e, 0x00, 0x54, 0x64, +0x69, 0x72, 0x65, 0x63, 0xbe, 0x01, 0x0b, 0x75, 0x01, 0x11, +0x72, 0x8b, 0x03, 0x0f, 0x76, 0x01, 0x06, 0x40, 0x6d, 0x61, +0x72, 0x6b, 0x5e, 0x00, 0x01, 0x30, 0x00, 0x84, 0x61, 0x00, +0x63, 0x72, 0x6f, 0x73, 0x73, 0x2c, 0xe2, 0x03, 0x02, 0xe9, +0x02, 0x61, 0x61, 0x74, 0x00, 0x79, 0x6f, 0x75, 0xb2, 0x02, +0x4a, 0x73, 0x75, 0x72, 0x65, 0x35, 0x05, 0x01, 0xc5, 0x02, +0x2e, 0x67, 0x6f, 0xa3, 0x01, 0x92, 0x2e, 0x00, 0x28, 0x46, +0x6f, 0x72, 0x00, 0x69, 0x6e, 0x70, 0x02, 0x64, 0x2c, 0x00, +0x69, 0x66, 0x00, 0x79, 0xd8, 0x06, 0x73, 0x64, 0x65, 0x63, +0x69, 0x64, 0x65, 0x64, 0x14, 0x05, 0x0f, 0x11, 0x04, 0x08, +0x14, 0x61, 0x7a, 0x04, 0x00, 0x6b, 0x03, 0x21, 0x68, 0x61, +0x97, 0x01, 0x2b, 0x62, 0x65, 0xe5, 0x04, 0x20, 0x64, 0x6f, +0xbb, 0x05, 0x83, 0x79, 0x65, 0x74, 0x00, 0x6b, 0x6e, 0x6f, +0x77, 0x55, 0x00, 0x32, 0x77, 0x61, 0x79, 0xa5, 0x03, 0x01, +0x29, 0x00, 0x71, 0x00, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x2c, +0x82, 0x00, 0x11, 0x6d, 0x12, 0x01, 0x01, 0xf9, 0x00, 0x00, +0x21, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x69, +0x74, 0x29, 0x06, 0x11, 0x27, 0xce, 0x00, 0x08, 0x0e, 0x01, +0x01, 0x97, 0x03, 0x0b, 0xd9, 0x01, 0x32, 0x75, 0x73, 0x65, +0x5d, 0x00, 0x91, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, +0x65, 0x79, 0x9a, 0x00, 0x01, 0x8d, 0x02, 0x06, 0x18, 0x00, +0x33, 0x2e, 0x00, 0x55, 0x28, 0x00, 0x41, 0x45, 0x6e, 0x74, +0x65, 0x27, 0x00, 0x02, 0xc0, 0x00, 0x31, 0x67, 0x69, 0x6e, +0xcf, 0x01, 0x30, 0x65, 0x6e, 0x64, 0x15, 0x00, 0x70, 0x62, +0x6f, 0x61, 0x72, 0x64, 0x00, 0x60, 0x2e, 0x02, 0x61, 0x27, +0x00, 0x6f, 0x70, 0x65, 0x72, 0x8a, 0x03, 0x16, 0x73, 0x3f, +0x00, 0x30, 0x53, 0x70, 0x61, 0x42, 0x01, 0x60, 0x45, 0x73, +0x63, 0x61, 0x70, 0x65, 0x21, 0x02, 0x50, 0x42, 0x61, 0x63, +0x6b, 0x73, 0x15, 0x00, 0x05, 0x7b, 0x00, 0x10, 0x63, 0x65, +0x01, 0x11, 0x6c, 0x2e, 0x00, 0x00, 0x48, 0x00, 0xc2, 0x2e, +0x00, 0x4f, 0x72, 0x2c, 0x00, 0x68, 0x6f, 0x6c, 0x64, 0x00, +0x43, 0x91, 0x03, 0x00, 0x17, 0x01, 0x12, 0x6c, 0x1d, 0x00, +0x37, 0x67, 0x69, 0x6e, 0x11, 0x03, 0x0b, 0xc4, 0x00, 0x55, +0x74, 0x6f, 0x67, 0x67, 0x6c, 0xe9, 0x02, 0x42, 0x73, 0x00, +0x61, 0x73, 0x35, 0x01, 0x00, 0xdb, 0x00, 0x04, 0x62, 0x08, +0x05, 0x8d, 0x08, 0x60, 0x00, 0x00, 0x50, 0x72, 0x65, 0x73, +0x1c, 0x08, 0x04, 0x67, 0x00, 0xe1, 0x2d, 0x53, 0x68, 0x69, +0x66, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6b, 0x65, +0x71, 0x08, 0x0b, 0x12, 0x00, 0x51, 0x73, 0x69, 0x6d, 0x75, +0x6c, 0x3e, 0x06, 0x12, 0x61, 0x8d, 0x03, 0x23, 0x6f, 0x72, +0xa5, 0x02, 0x10, 0x63, 0xba, 0x02, 0x10, 0x2c, 0x50, 0x08, +0x34, 0x70, 0x65, 0x63, 0x6b, 0x01, 0x12, 0x6f, 0x10, 0x06, +0x01, 0xb0, 0x02, 0x03, 0x1c, 0x06, 0x05, 0xef, 0x02, 0x04, +0x3a, 0x02, 0x31, 0x6b, 0x65, 0x79, 0x20, 0x06, 0x22, 0x41, +0x6c, 0x02, 0x01, 0x21, 0x61, 0x63, 0x41, 0x01, 0xa0, 0x00, +0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x3a, +0x00, 0x13, 0x73, 0x34, 0x00, 0x31, 0x32, 0x2e, 0x31, 0xcc, +0x02, 0x02, 0xe6, 0x06, 0x72, 0x76, 0x61, 0x69, 0x6c, 0x61, +0x62, 0x6c, 0xd8, 0x07, 0x43, 0x33, 0x36, 0x2e, 0x32, 0xc7, +0x04, 0xb1, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, +0x72, 0x73, 0x20, 0x53, 0x05, 0x46, 0x65, 0x73, 0x65, 0x00, +0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x51, 0x00, +0x66, 0x72, 0x6f, 0x6d, 0x79, 0x00, 0xa0, 0x60, 0x43, 0x75, +0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0xc9, 0x01, 0x02, +0xa3, 0x00, 0x12, 0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, +0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xab, 0x00, 0x91, +0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xf9, +0x00, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x19, 0x07, 0x01, +0x9c, 0x03, 0x19, 0x69, 0x62, 0x01, 0xa0, 0x44, 0x69, 0x66, +0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0xdd, 0x03, 0x03, +0x5e, 0x05, 0x03, 0x08, 0x01, 0x05, 0x1a, 0x00, 0x03, 0x09, +0x01, 0x30, 0x67, 0x65, 0x6e, 0x3e, 0x02, 0x23, 0x65, 0x64, +0x38, 0x06, 0x11, 0x2e, 0xbb, 0x02, 0xa0, 0x6c, 0x6f, 0x77, +0x20, 0x75, 0x6e, 0x73, 0x6f, 0x6c, 0x75, 0xad, 0x00, 0x42, +0x00, 0x00, 0x49, 0x66, 0x5c, 0x06, 0x72, 0x69, 0x73, 0x00, +0x73, 0x65, 0x74, 0x2c, 0x56, 0x04, 0x01, 0x3f, 0x00, 0x17, +0x61, 0x6f, 0x09, 0x06, 0x4c, 0x00, 0x03, 0x77, 0x01, 0x11, +0x73, 0x2a, 0x06, 0x20, 0x73, 0x74, 0x2e, 0x03, 0x13, 0x3a, +0x15, 0x09, 0x07, 0x03, 0x07, 0x02, 0xfb, 0x03, 0x00, 0x6c, +0x09, 0x80, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x79, +0x46, 0x00, 0x42, 0x70, 0x72, 0x6f, 0x76, 0xeb, 0x03, 0x04, +0xc6, 0x09, 0x42, 0x68, 0x6f, 0x77, 0x6e, 0xde, 0x09, 0x07, +0xb2, 0x00, 0x22, 0x6f, 0x72, 0x21, 0x00, 0x01, 0x13, 0x07, +0x20, 0x68, 0x65, 0xc1, 0x04, 0x21, 0x68, 0x65, 0xba, 0x08, +0x00, 0x25, 0x00, 0x03, 0x05, 0x07, 0x03, 0xc8, 0x09, 0x50, +0x75, 0x6e, 0x69, 0x71, 0x75, 0xc6, 0x09, 0x71, 0x73, 0x6f, +0x6c, 0x76, 0x65, 0x64, 0x2e, 0xa0, 0x01, 0x00, 0xcc, 0x00, +0x82, 0x70, 0x65, 0x65, 0x64, 0x73, 0x00, 0x75, 0x70, 0xc8, +0x00, 0x03, 0x5a, 0x00, 0x23, 0x69, 0x6f, 0x6e, 0x00, 0x10, +0x61, 0x08, 0x01, 0xd1, 0x73, 0x00, 0x6d, 0x75, 0x63, 0x68, +0x00, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x6e, 0x01, 0x04, +0x53, 0x04, 0x40, 0x70, 0x6c, 0x61, 0x79, 0x4d, 0x00, 0x31, +0x41, 0x74, 0x00, 0xab, 0x08, 0x01, 0x18, 0x04, 0x03, 0xca, +0x00, 0x20, 0x65, 0x00, 0x3d, 0x01, 0x01, 0xcf, 0x01, 0x01, +0xa6, 0x00, 0x20, 0x73, 0x74, 0x06, 0x00, 0x62, 0x61, 0x6c, +0x77, 0x61, 0x79, 0x73, 0xd8, 0x05, 0x02, 0x89, 0x04, 0x00, +0xb1, 0x00, 0x20, 0x65, 0x27, 0x14, 0x05, 0xa3, 0x00, 0x67, +0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x67, 0x08, +0x15, 0x74, 0x01, 0x01, 0x02, 0xbf, 0x00, 0x02, 0xe8, 0x05, +0x0b, 0x1b, 0x00, 0x05, 0x6f, 0x00, 0x00, 0x7d, 0x06, 0x32, +0x65, 0x64, 0x75, 0xcc, 0x06, 0x71, 0x73, 0x74, 0x65, 0x70, +0x00, 0x62, 0x79, 0x08, 0x00, 0x12, 0x2e, 0xa6, 0x02, 0x13, +0x33, 0xa6, 0x02, 0x81, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, +0x72, 0x65, 0x08, 0x06, 0x21, 0x63, 0x65, 0xac, 0x02, 0x20, +0x4f, 0x6e, 0xcc, 0x00, 0x10, 0x74, 0xb8, 0x0b, 0x13, 0x73, +0x1d, 0x0a, 0x70, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, +0x2e, 0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0x9a, 0x02, +0x16, 0x50, 0x12, 0x00, 0x0d, 0xb6, 0x02, 0x33, 0x47, 0x61, +0x6d, 0xb6, 0x02, 0x02, 0xa5, 0x00, 0x22, 0x6c, 0x65, 0x0d, +0x06, 0x64, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0e, 0x06, +0x45, 0x73, 0x74, 0x79, 0x6c, 0xd8, 0x09, 0x01, 0x7d, 0x01, +0x30, 0x64, 0x69, 0x73, 0x51, 0x01, 0x80, 0x2e, 0x00, 0x60, +0x54, 0x72, 0x61, 0x64, 0x69, 0x54, 0x00, 0x53, 0x61, 0x6c, +0x27, 0x00, 0x69, 0xb9, 0x02, 0xb0, 0x65, 0x66, 0x61, 0x75, +0x6c, 0x74, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x06, 0x03, +0xb3, 0x05, 0x05, 0x59, 0x06, 0x36, 0x72, 0x75, 0x6e, 0xcf, +0x0c, 0x07, 0xcb, 0x0c, 0x01, 0x1e, 0x03, 0x05, 0xac, 0x0c, +0x01, 0x42, 0x05, 0x33, 0x61, 0x63, 0x68, 0x04, 0x0a, 0x51, +0x63, 0x63, 0x75, 0x70, 0x69, 0x56, 0x04, 0x04, 0x93, 0x09, +0x71, 0x60, 0x4c, 0x6f, 0x6f, 0x70, 0x79, 0x2d, 0x9e, 0x00, +0x11, 0x27, 0x4d, 0x0a, 0x36, 0x6e, 0x00, 0x61, 0xc9, 0x05, +0x01, 0x7f, 0x00, 0x02, 0x22, 0x01, 0x52, 0x6c, 0x6f, 0x6f, +0x6b, 0x73, 0xeb, 0x07, 0x51, 0x6c, 0x69, 0x6b, 0x65, 0x00, +0x39, 0x00, 0x32, 0x00, 0x28, 0x63, 0xaf, 0x0d, 0x4f, 0x00, +0x32, 0x33, 0x29, 0xa7, 0x00, 0x0e, 0x01, 0x9c, 0x00, 0x02, +0x8c, 0x0c, 0x04, 0x9d, 0x00, 0x04, 0x24, 0x0a, 0x03, 0x52, +0x0b, 0x01, 0xa2, 0x00, 0xc0, 0x79, 0x00, 0x76, 0x65, 0x72, +0x74, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 2570; -const unsigned short help_text_words = 475; +const unsigned short help_text_len = 3598; +const unsigned short help_text_words = 659; const char quick_help_text[] = "Draw a single closed loop, given clues about corner and straight squares."; diff --git a/apps/plugins/puzzles/help/pegs.c b/apps/plugins/puzzles/help/pegs.c index 14cbbf7f94..b7159ffc5c 100644 --- a/apps/plugins/puzzles/help/pegs.c +++ b/apps/plugins/puzzles/help/pegs.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,143 +6,146 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 72, TEXT_CENTER | C_RED }, - { 228, TEXT_CENTER | C_RED }, - { 245, TEXT_UNDERLINE }, + { 73, TEXT_CENTER | C_RED }, + { 229, TEXT_CENTER | C_RED }, { 246, TEXT_UNDERLINE }, - { 256, TEXT_UNDERLINE }, + { 247, TEXT_UNDERLINE }, + { 257, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1689 comp 1250 ratio 0.740083 level 3 saved 439 */ +/* orig 1734 comp 1272 ratio 0.733564 level 4 saved 462 */ const char help_text[] = { -0xf0, 0x46, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfb, 0x04, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x36, 0x3a, 0x20, 0x50, 0x65, 0x67, 0x73, 0x20, 0x00, -0x00, 0x00, 0x41, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, -0x00, 0x6f, 0x66, 0x00, 0x70, 0x65, 0x67, 0x73, 0x00, 0x61, -0x72, 0x65, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x00, -0x69, 0x6e, 0x00, 0x68, 0x6f, 0x6c, 0x65, 0x73, 0x00, 0x6f, -0x6e, 0x00, 0x61, 0x00, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, -0x00, 0x59, 0x6f, 0x75, 0x00, 0x63, 0x61, 0x6e, 0x00, 0x72, -0x65, 0x6d, 0x6f, 0x76, 0x65, 0x00, 0x61, 0x36, 0x00, 0xf1, -0x08, 0x00, 0x62, 0x79, 0x00, 0x6a, 0x75, 0x6d, 0x70, 0x69, -0x6e, 0x67, 0x00, 0x61, 0x6e, 0x00, 0x61, 0x64, 0x6a, 0x61, -0x63, 0x65, 0x6e, 0x74, 0x1b, 0x00, 0xf0, 0x10, 0x6f, 0x76, -0x65, 0x72, 0x00, 0x69, 0x74, 0x00, 0x28, 0x68, 0x6f, 0x72, -0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x00, -0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, -0x00, 0xd1, 0x29, 0x00, 0x74, 0x6f, 0x00, 0x61, 0x00, 0x76, -0x61, 0x63, 0x61, 0x6e, 0x74, 0x73, 0x00, 0x00, 0x72, 0x00, -0xe1, 0x74, 0x68, 0x65, 0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, -0x00, 0x73, 0x69, 0x64, 0x65, 0x79, 0x00, 0x80, 0x72, 0x00, -0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x30, 0x00, 0x04, 0x80, -0x00, 0xa0, 0x6c, 0x6c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x6f, -0x6e, 0x65, 0xc3, 0x00, 0x00, 0x35, 0x00, 0x01, 0xc7, 0x00, -0x51, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6b, 0x00, 0xf0, 0x25, -0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x2e, 0x00, 0x00, -0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, -0x2c, 0x00, 0x62, 0x65, 0x73, 0x74, 0x00, 0x6b, 0x6e, 0x6f, -0x77, 0x6e, 0x00, 0x61, 0x73, 0x00, 0x60, 0x50, 0x65, 0x67, -0x00, 0x53, 0x6f, 0x6c, 0x69, 0x74, 0x61, 0x69, 0x72, 0x65, -0x27, 0x2c, 0x64, 0x00, 0x88, 0x70, 0x6f, 0x73, 0x73, 0x69, -0x62, 0x6c, 0x79, 0x5b, 0x00, 0x30, 0x6f, 0x6c, 0x64, 0x38, -0x00, 0x61, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x4a, 0x00, -0xf2, 0x01, 0x73, 0x00, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x00, -0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6c, 0x79, 0x54, 0x00, -0x00, 0x6d, 0x00, 0x42, 0x31, 0x36, 0x2e, 0x31, 0x67, 0x01, -0x71, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x01, -0x36, 0x54, 0x6f, 0x00, 0x38, 0x01, 0x60, 0x2c, 0x00, 0x64, -0x72, 0x61, 0x67, 0x1e, 0x01, 0x41, 0x77, 0x69, 0x74, 0x68, -0x62, 0x00, 0xf1, 0x04, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, -0x66, 0x72, 0x6f, 0x6d, 0x00, 0x69, 0x74, 0x73, 0x00, 0x63, -0x75, 0x72, 0x72, 0x4a, 0x01, 0x50, 0x6f, 0x73, 0x69, 0x74, -0x69, 0x16, 0x01, 0x11, 0x6f, 0x18, 0x00, 0x55, 0x66, 0x69, -0x6e, 0x61, 0x6c, 0x16, 0x00, 0x32, 0x2e, 0x00, 0x49, 0xa0, -0x00, 0x0a, 0x17, 0x00, 0x00, 0xc6, 0x00, 0xb3, 0x65, 0x78, -0x61, 0x63, 0x74, 0x6c, 0x79, 0x00, 0x74, 0x77, 0x6f, 0xcd, -0x01, 0x42, 0x61, 0x77, 0x61, 0x79, 0x61, 0x00, 0x00, 0x32, -0x00, 0x03, 0x28, 0x01, 0x05, 0x34, 0x00, 0x01, 0xfb, 0x00, -0x03, 0x76, 0x00, 0xd0, 0x6c, 0x79, 0x00, 0x75, 0x6e, 0x6f, -0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0xe4, 0x01, 0x03, -0xb5, 0x00, 0x30, 0x61, 0x6e, 0x64, 0x3c, 0x00, 0x20, 0x72, -0x65, 0x2c, 0x00, 0x02, 0x01, 0x02, 0x23, 0x69, 0x6e, 0x4e, -0x00, 0x60, 0x74, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x09, 0x02, -0x73, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x2c, 0xd6, 0x00, -0x40, 0x76, 0x65, 0x00, 0x77, 0x28, 0x01, 0x10, 0x62, 0xa0, -0x01, 0x74, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x49, -0x00, 0x09, 0x37, 0x00, 0x00, 0x4e, 0x00, 0x04, 0x2a, 0x00, -0x02, 0xe4, 0x01, 0x10, 0x64, 0x4e, 0x01, 0x12, 0x56, 0x1d, -0x02, 0xe3, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x00, 0x77, -0x68, 0x69, 0x63, 0x68, 0x00, 0x79, 0x8b, 0x02, 0x06, 0x51, -0x01, 0x00, 0x4a, 0x00, 0x11, 0x6f, 0xc3, 0x02, 0x62, 0x6d, -0x61, 0x72, 0x6b, 0x65, 0x64, 0x58, 0x01, 0x01, 0xf8, 0x00, -0x32, 0x2e, 0x00, 0x41, 0x3e, 0x00, 0x02, 0x14, 0x00, 0x21, -0x6e, 0x6f, 0x30, 0x00, 0x00, 0x82, 0x00, 0x12, 0x6e, 0x1a, -0x01, 0x00, 0xcd, 0x00, 0xf0, 0x02, 0x6e, 0x6f, 0x74, 0x00, -0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, -0x66, 0x6f, 0x72, 0x5c, 0x00, 0x01, 0xd6, 0x02, 0x10, 0x74, -0x6a, 0x02, 0x10, 0x3a, 0xab, 0x01, 0x00, 0xf4, 0x00, 0xa7, -0x6e, 0x00, 0x6f, 0x62, 0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, -0x8b, 0x00, 0xf1, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x77, -0x6f, 0x72, 0x6b, 0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0xb7, -0x00, 0x04, 0x2e, 0x03, 0x50, 0x61, 0x6c, 0x73, 0x6f, 0x00, -0xda, 0x01, 0x00, 0xef, 0x00, 0xa1, 0x63, 0x75, 0x72, 0x73, -0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xca, 0x02, 0x04, 0x10, -0x02, 0x05, 0xb6, 0x01, 0x83, 0x6e, 0x64, 0x69, 0x63, 0x61, -0x74, 0x6f, 0x72, 0x48, 0x00, 0x01, 0x34, 0x00, 0x03, 0x7e, -0x03, 0x50, 0x50, 0x72, 0x65, 0x73, 0x73, 0x91, 0x00, 0x00, -0x14, 0x00, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x48, -0x00, 0x00, 0x86, 0x00, 0x22, 0x6c, 0x65, 0x6c, 0x03, 0x03, -0xa5, 0x01, 0x64, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0xb8, -0x01, 0x06, 0x73, 0x00, 0x12, 0x2c, 0x5e, 0x01, 0x00, 0xaf, -0x03, 0x04, 0x2e, 0x03, 0x02, 0xbe, 0x01, 0x81, 0x61, 0x74, -0x00, 0x64, 0x69, 0x72, 0x65, 0x63, 0x84, 0x00, 0x32, 0x28, -0x69, 0x66, 0x13, 0x00, 0x01, 0xe2, 0x01, 0x51, 0x6c, 0x65, -0x67, 0x61, 0x6c, 0xa8, 0x00, 0x10, 0x29, 0xd5, 0x00, 0x41, -0x28, 0x41, 0x6c, 0x6c, 0x3c, 0x00, 0x11, 0x61, 0x2d, 0x00, -0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, -0x33, 0x04, 0x13, 0x73, 0x43, 0x00, 0x31, 0x32, 0x2e, 0x31, -0x8a, 0x01, 0x01, 0xfb, 0x00, 0x05, 0x55, 0x01, 0x22, 0x2e, -0x29, 0x1b, 0x03, 0x12, 0x32, 0x1b, 0x03, 0x92, 0x70, 0x61, -0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1d, 0x03, 0x56, -0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x40, 0x00, -0x06, 0x90, 0x01, 0x04, 0xb5, 0x02, 0xe1, 0x60, 0x43, 0x75, -0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, -0x70, 0x6e, 0x00, 0x03, 0x31, 0x04, 0xb0, 0x60, 0x54, 0x79, -0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xaa, 0x00, -0xf1, 0x04, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, -0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0x00, 0x53, 0x69, -0x7a, 0xcc, 0x03, 0x36, 0x67, 0x72, 0x69, 0xdf, 0x04, 0x00, -0x29, 0x00, 0x10, 0x42, 0x5f, 0x01, 0x93, 0x20, 0x74, 0x79, -0x70, 0x65, 0x00, 0x00, 0x00, 0x43, 0xb0, 0x03, 0x41, 0x00, -0x77, 0x68, 0x65, 0x81, 0x04, 0x00, 0xde, 0x01, 0x00, 0x8b, -0x00, 0x45, 0x67, 0x69, 0x76, 0x65, 0x0b, 0x05, 0x00, 0x48, -0x00, 0x70, 0x61, 0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x0e, -0x00, 0x50, 0x73, 0x68, 0x61, 0x70, 0x65, 0xd8, 0x04, 0xf3, -0x04, 0x61, 0x00, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, -0x79, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, -0x1e, 0x00, 0x10, 0x2e, 0xe1, 0x00, 0x01, 0x8a, 0x03, 0x0a, -0x36, 0x00, 0x08, 0x71, 0x03, 0x61, 0x73, 0x75, 0x70, 0x70, -0x6f, 0x72, 0x1d, 0x03, 0x10, 0x72, 0xe9, 0x00, 0x51, 0x72, -0x6f, 0x73, 0x73, 0x27, 0xa7, 0x02, 0xb1, 0x60, 0x4f, 0x63, -0x74, 0x61, 0x67, 0x6f, 0x6e, 0x27, 0x00, 0x28, 0x53, 0x01, -0x0a, 0x72, 0x04, 0x00, 0xc6, 0x04, 0x00, 0x01, 0x01, 0x71, -0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x32, 0x00, 0xd1, -0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x00, 0x74, -0x72, 0x61, 0x64, 0x5c, 0x02, 0x23, 0x61, 0x6c, 0xbc, 0x00, -0xc0, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x00, 0x72, -0x65, 0x73, 0x70, 0xb0, 0x01, 0xa0, 0x76, 0x65, 0x6c, 0x79, -0x29, 0x2e, 0x00, 0x53, 0x65, 0x6c, 0x0e, 0x00, 0x51, 0x6e, -0x67, 0x00, 0x60, 0x52, 0xc5, 0x00, 0x12, 0x27, 0x2e, 0x02, -0x00, 0xf9, 0x00, 0x02, 0x06, 0x01, 0x61, 0x00, 0x64, 0x69, -0x66, 0x66, 0x65, 0x94, 0x04, 0x26, 0x62, 0x6f, 0xf8, 0x00, -0xc0, 0x65, 0x76, 0x65, 0x72, 0x79, 0x00, 0x74, 0x69, 0x6d, -0x65, 0x00, 0x28, 0x8f, 0x05, 0x61, 0x61, 0x6c, 0x77, 0x61, -0x79, 0x73, 0x3b, 0x05, 0x04, 0x47, 0x02, 0x02, 0xa7, 0x00, -0x51, 0x74, 0x6f, 0x00, 0x68, 0x61, 0xf0, 0x02, 0xb0, 0x73, -0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2e, 0x00, +0x2d, 0x01, 0x00, 0xf0, 0x35, 0x00, 0x00, 0x00, 0x41, 0x00, +0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x6f, 0x66, 0x00, +0x70, 0x65, 0x67, 0x73, 0x00, 0x61, 0x72, 0x65, 0x00, 0x70, +0x6c, 0x61, 0x63, 0x65, 0x64, 0x00, 0x69, 0x6e, 0x00, 0x68, +0x6f, 0x6c, 0x65, 0x73, 0x00, 0x6f, 0x6e, 0x00, 0x61, 0x00, +0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x00, 0x59, 0x6f, 0x75, +0x00, 0x63, 0x61, 0x6e, 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x76, +0x65, 0x00, 0x61, 0x36, 0x00, 0xf1, 0x08, 0x00, 0x62, 0x79, +0x00, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x00, 0x61, +0x6e, 0x00, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, +0x1b, 0x00, 0xf0, 0x10, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x69, +0x74, 0x00, 0x28, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, +0x74, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, 0x00, 0x76, +0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, 0xd1, 0x29, 0x00, +0x74, 0x6f, 0x00, 0x61, 0x00, 0x76, 0x61, 0x63, 0x61, 0x6e, +0x74, 0x73, 0x00, 0x00, 0x72, 0x00, 0xe1, 0x74, 0x68, 0x65, +0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0x73, 0x69, 0x64, +0x65, 0x79, 0x00, 0x80, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, +0x69, 0x73, 0x30, 0x00, 0x04, 0x80, 0x00, 0xa0, 0x6c, 0x6c, +0x00, 0x62, 0x75, 0x74, 0x00, 0x6f, 0x6e, 0x65, 0xc3, 0x00, +0x00, 0x35, 0x00, 0x01, 0xc7, 0x00, 0x51, 0x69, 0x6e, 0x69, +0x74, 0x69, 0x6b, 0x00, 0xf0, 0x25, 0x70, 0x72, 0x65, 0x73, +0x65, 0x6e, 0x74, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, +0x73, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, 0x62, 0x65, +0x73, 0x74, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x61, +0x73, 0x00, 0x60, 0x50, 0x65, 0x67, 0x00, 0x53, 0x6f, 0x6c, +0x69, 0x74, 0x61, 0x69, 0x72, 0x65, 0x27, 0x2c, 0x64, 0x00, +0x88, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x79, 0x5b, +0x00, 0x30, 0x6f, 0x6c, 0x64, 0x38, 0x00, 0x61, 0x70, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0x4a, 0x00, 0xf2, 0x01, 0x73, 0x00, +0x73, 0x74, 0x69, 0x6c, 0x6c, 0x00, 0x63, 0x6f, 0x6d, 0x6d, +0x6f, 0x6e, 0x6c, 0x79, 0x54, 0x00, 0x00, 0x6d, 0x00, 0x42, +0x31, 0x36, 0x2e, 0x31, 0x78, 0x01, 0x90, 0x63, 0x6f, 0x6e, +0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x83, 0x00, 0x26, 0x6f, +0x00, 0x38, 0x01, 0x60, 0x2c, 0x00, 0x64, 0x72, 0x61, 0x67, +0x1e, 0x01, 0x41, 0x77, 0x69, 0x74, 0x68, 0x62, 0x00, 0xf1, +0x04, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x66, 0x72, 0x6f, +0x6d, 0x00, 0x69, 0x74, 0x73, 0x00, 0x63, 0x75, 0x72, 0x72, +0x4a, 0x01, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x16, 0x01, +0x11, 0x6f, 0x18, 0x00, 0x55, 0x66, 0x69, 0x6e, 0x61, 0x6c, +0x16, 0x00, 0x32, 0x2e, 0x00, 0x49, 0xa0, 0x00, 0x0a, 0x17, +0x00, 0x00, 0xc6, 0x00, 0xb3, 0x65, 0x78, 0x61, 0x63, 0x74, +0x6c, 0x79, 0x00, 0x74, 0x77, 0x6f, 0xcd, 0x01, 0x42, 0x61, +0x77, 0x61, 0x79, 0x61, 0x00, 0x00, 0x32, 0x00, 0x03, 0x28, +0x01, 0x05, 0x34, 0x00, 0x01, 0xfb, 0x00, 0x03, 0x76, 0x00, +0xd0, 0x6c, 0x79, 0x00, 0x75, 0x6e, 0x6f, 0x63, 0x63, 0x75, +0x70, 0x69, 0x65, 0x64, 0xe4, 0x01, 0x03, 0xb5, 0x00, 0x30, +0x61, 0x6e, 0x64, 0x3c, 0x00, 0x20, 0x72, 0x65, 0x2c, 0x00, +0x02, 0x01, 0x02, 0x23, 0x69, 0x6e, 0x4e, 0x00, 0x60, 0x74, +0x65, 0x72, 0x76, 0x65, 0x6e, 0x09, 0x02, 0x73, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x2c, 0xd6, 0x00, 0x40, 0x76, 0x65, +0x00, 0x77, 0x28, 0x01, 0x10, 0x62, 0xa0, 0x01, 0x74, 0x72, +0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x49, 0x00, 0x09, 0x37, +0x00, 0x00, 0x4e, 0x00, 0x04, 0x2a, 0x00, 0x02, 0xe4, 0x01, +0x10, 0x64, 0x4e, 0x01, 0x12, 0x56, 0x1d, 0x02, 0xe3, 0x73, +0x70, 0x61, 0x63, 0x65, 0x73, 0x00, 0x77, 0x68, 0x69, 0x63, +0x68, 0x00, 0x79, 0x8b, 0x02, 0x07, 0x89, 0x02, 0x41, 0x69, +0x6e, 0x74, 0x6f, 0xc3, 0x02, 0x62, 0x6d, 0x61, 0x72, 0x6b, +0x65, 0x64, 0x58, 0x01, 0x01, 0xf8, 0x00, 0x32, 0x2e, 0x00, +0x41, 0x3e, 0x00, 0x02, 0x14, 0x00, 0x21, 0x6e, 0x6f, 0x30, +0x00, 0x00, 0x82, 0x00, 0x12, 0x6e, 0x1a, 0x01, 0x00, 0xcd, +0x00, 0xf0, 0x02, 0x6e, 0x6f, 0x74, 0x00, 0x61, 0x76, 0x61, +0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x66, 0x6f, 0x72, +0x5c, 0x00, 0x01, 0xd6, 0x02, 0x10, 0x74, 0x6a, 0x02, 0x10, +0x3a, 0xab, 0x01, 0x00, 0xf4, 0x00, 0xa7, 0x6e, 0x00, 0x6f, +0x62, 0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x8b, 0x00, 0xf1, +0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x77, 0x6f, 0x72, 0x6b, +0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0xb7, 0x00, 0x04, 0x2e, +0x03, 0x50, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0xda, 0x01, 0x00, +0xef, 0x00, 0xa1, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, +0x6b, 0x65, 0x79, 0xca, 0x02, 0x04, 0x10, 0x02, 0x05, 0xb6, +0x01, 0x83, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, +0x48, 0x00, 0x01, 0x34, 0x00, 0x03, 0x7e, 0x03, 0x50, 0x50, +0x72, 0x65, 0x73, 0x73, 0x91, 0x00, 0x00, 0x14, 0x00, 0x60, +0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x48, 0x00, 0x00, 0x86, +0x00, 0x22, 0x6c, 0x65, 0x6c, 0x03, 0x03, 0xa5, 0x01, 0x64, +0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0xb8, 0x01, 0x06, 0x73, +0x00, 0x12, 0x2c, 0x5e, 0x01, 0x00, 0xaf, 0x03, 0x04, 0x2e, +0x03, 0x02, 0xbe, 0x01, 0x81, 0x61, 0x74, 0x00, 0x64, 0x69, +0x72, 0x65, 0x63, 0x84, 0x00, 0x32, 0x28, 0x69, 0x66, 0x13, +0x00, 0x01, 0xe2, 0x01, 0x51, 0x6c, 0x65, 0x67, 0x61, 0x6c, +0xa8, 0x00, 0x10, 0x29, 0xd5, 0x00, 0x41, 0x28, 0x41, 0x6c, +0x6c, 0x3c, 0x00, 0x11, 0x61, 0x2d, 0x00, 0x92, 0x73, 0x00, +0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x33, 0x04, 0x13, +0x73, 0x43, 0x00, 0x31, 0x32, 0x2e, 0x31, 0x8a, 0x01, 0x01, +0xfb, 0x00, 0x05, 0x55, 0x01, 0x22, 0x2e, 0x29, 0x1b, 0x03, +0x12, 0x32, 0x1b, 0x03, 0x92, 0x70, 0x61, 0x72, 0x61, 0x6d, +0x65, 0x74, 0x65, 0x72, 0x1d, 0x03, 0x56, 0x68, 0x65, 0x73, +0x65, 0x00, 0x14, 0x00, 0x02, 0x40, 0x00, 0x06, 0x90, 0x01, +0x04, 0xb5, 0x02, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, +0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6e, 0x00, +0x03, 0x31, 0x04, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0xaa, 0x00, 0xf1, 0x04, 0x57, +0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x69, 0x67, +0x68, 0x74, 0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, 0xcc, 0x03, +0x36, 0x67, 0x72, 0x69, 0xdf, 0x04, 0x00, 0x29, 0x00, 0x10, +0x42, 0x5f, 0x01, 0x93, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, +0x00, 0x00, 0x43, 0xb0, 0x03, 0x41, 0x00, 0x77, 0x68, 0x65, +0x81, 0x04, 0x00, 0xde, 0x01, 0x00, 0x8b, 0x00, 0x45, 0x67, +0x69, 0x76, 0x65, 0x0b, 0x05, 0x00, 0x48, 0x00, 0x70, 0x61, +0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x0e, 0x00, 0x50, 0x73, +0x68, 0x61, 0x70, 0x65, 0xd8, 0x04, 0xf3, 0x04, 0x61, 0x00, +0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, 0x79, 0x00, 0x67, +0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x1e, 0x00, 0x10, +0x2e, 0xe1, 0x00, 0x01, 0x8a, 0x03, 0x0a, 0x36, 0x00, 0x08, +0x71, 0x03, 0x61, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x1d, +0x03, 0x10, 0x72, 0xe9, 0x00, 0xf1, 0x09, 0x72, 0x6f, 0x73, +0x73, 0x27, 0x00, 0x28, 0x69, 0x6e, 0x00, 0x76, 0x61, 0x72, +0x69, 0x6f, 0x75, 0x73, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x73, +0x29, 0xba, 0x02, 0x92, 0x60, 0x4f, 0x63, 0x74, 0x61, 0x67, +0x6f, 0x6e, 0x27, 0x5a, 0x00, 0x41, 0x37, 0x78, 0x37, 0x00, +0x31, 0x00, 0x01, 0x23, 0x05, 0x00, 0x6b, 0x00, 0x31, 0x72, +0x61, 0x64, 0x54, 0x02, 0xa3, 0x61, 0x6c, 0x00, 0x45, 0x6e, +0x67, 0x6c, 0x69, 0x73, 0x68, 0xbc, 0x00, 0x62, 0x6c, 0x61, +0x79, 0x6f, 0x75, 0x74, 0x37, 0x00, 0x03, 0x45, 0x00, 0x0f, +0x35, 0x00, 0x01, 0x60, 0x46, 0x72, 0x65, 0x6e, 0x63, 0x68, +0x02, 0x05, 0x50, 0x2e, 0x00, 0x53, 0x65, 0x6c, 0xda, 0x01, +0x51, 0x6e, 0x67, 0x00, 0x60, 0x52, 0xe1, 0x00, 0x12, 0x27, +0x4a, 0x02, 0x00, 0x15, 0x01, 0x02, 0x22, 0x01, 0x61, 0x00, +0x64, 0x69, 0x66, 0x66, 0x65, 0xb0, 0x04, 0x26, 0x62, 0x6f, +0x14, 0x01, 0xc0, 0x65, 0x76, 0x65, 0x72, 0x79, 0x00, 0x74, +0x69, 0x6d, 0x65, 0x00, 0x28, 0xab, 0x05, 0x61, 0x61, 0x6c, +0x77, 0x61, 0x79, 0x73, 0x57, 0x05, 0x04, 0x63, 0x02, 0x02, +0x89, 0x05, 0x51, 0x74, 0x6f, 0x00, 0x68, 0x61, 0x0c, 0x03, +0xb0, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, +0x2e, 0x00, }; -const unsigned short help_text_len = 1689; -const unsigned short help_text_words = 318; +const unsigned short help_text_len = 1734; +const unsigned short help_text_words = 326; const char quick_help_text[] = "Jump pegs over each other to remove all but one."; diff --git a/apps/plugins/puzzles/help/range.c b/apps/plugins/puzzles/help/range.c index 1ce92c05d1..5a9e3ab71d 100644 --- a/apps/plugins/puzzles/help/range.c +++ b/apps/plugins/puzzles/help/range.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,157 +6,168 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 212, TEXT_CENTER | C_RED }, - { 245, TEXT_UNDERLINE }, - { 339, TEXT_CENTER | C_RED }, - { 356, TEXT_UNDERLINE }, + { 213, TEXT_CENTER | C_RED }, + { 246, TEXT_UNDERLINE }, + { 340, TEXT_CENTER | C_RED }, { 357, TEXT_UNDERLINE }, + { 358, TEXT_UNDERLINE }, + { 368, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 2036 comp 1387 ratio 0.681238 level 4 saved 649 */ +/* orig 2223 comp 1486 ratio 0.668466 level 10 saved 737 */ const char help_text[] = { -0xf4, 0x26, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x35, 0x3a, 0x20, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, -0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x3b, -0x00, 0x73, 0x6f, 0x6d, 0x65, 0x0e, 0x00, 0xf0, 0x02, 0x00, -0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, -0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x3a, 0x00, 0xf0, 0x00, -0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, 0x00, 0x74, -0x6f, 0x00, 0x63, 0x6f, 0x6c, 0x11, 0x00, 0x01, 0x34, 0x00, -0x56, 0x6f, 0x66, 0x00, 0x74, 0x68, 0x3b, 0x00, 0xf3, 0x28, -0x62, 0x6c, 0x61, 0x63, 0x6b, 0x2c, 0x00, 0x73, 0x75, 0x63, -0x68, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x73, 0x65, 0x76, -0x65, 0x72, 0x61, 0x6c, 0x00, 0x63, 0x72, 0x69, 0x74, 0x65, -0x72, 0x69, 0x61, 0x00, 0x61, 0x72, 0x65, 0x00, 0x73, 0x61, -0x74, 0x69, 0x73, 0x66, 0x69, 0x65, 0x64, 0x3a, 0x00, 0x00, -0x00, 0x2d, 0x00, 0x6e, 0x6f, 0x40, 0x00, 0x73, 0x00, 0x77, -0x69, 0x74, 0x68, 0x00, 0x61, 0x79, 0x00, 0x00, 0x6e, 0x00, -0x02, 0x6b, 0x00, 0x22, 0x65, 0x64, 0x59, 0x00, 0x14, 0x2e, -0x2f, 0x00, 0x32, 0x74, 0x77, 0x6f, 0x12, 0x00, 0x05, 0x79, -0x00, 0x00, 0x3e, 0x00, 0xf0, 0x00, 0x61, 0x64, 0x6a, 0x61, -0x63, 0x65, 0x6e, 0x74, 0x00, 0x28, 0x68, 0x6f, 0x72, 0x69, -0x7a, 0xc6, 0x00, 0xd0, 0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, -0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, 0x12, -0x29, 0x44, 0x00, 0x71, 0x66, 0x6f, 0x72, 0x00, 0x61, 0x6e, -0x79, 0x49, 0x00, 0x45, 0x77, 0x68, 0x69, 0x74, 0xc2, 0x00, -0x10, 0x2c, 0xcf, 0x00, 0x20, 0x72, 0x65, 0x7c, 0x00, 0xe0, -0x61, 0x00, 0x70, 0x61, 0x74, 0x68, 0x00, 0x62, 0x65, 0x74, -0x77, 0x65, 0x65, 0x6e, 0x18, 0x00, 0xca, 0x6d, 0x00, 0x75, -0x73, 0x69, 0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x37, -0x00, 0x06, 0x56, 0x00, 0x4f, 0x65, 0x61, 0x63, 0x68, 0xcf, -0x00, 0x02, 0x12, 0x2c, 0x11, 0x01, 0x03, 0xdc, 0x00, 0x71, -0x64, 0x65, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x3d, 0x01, 0x54, -0x74, 0x6f, 0x74, 0x61, 0x6c, 0x19, 0x00, 0x2a, 0x6f, 0x66, -0x5a, 0x00, 0x20, 0x00, 0x72, 0x52, 0x00, 0x93, 0x61, 0x62, -0x6c, 0x65, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x56, 0x01, 0x02, -0x60, 0x00, 0x20, 0x67, 0x6f, 0x8e, 0x00, 0xf1, 0x03, 0x69, -0x6e, 0x00, 0x61, 0x00, 0x73, 0x74, 0x72, 0x61, 0x69, 0x67, -0x68, 0x74, 0x00, 0x6c, 0x69, 0x6e, 0x65, 0x13, 0x00, 0x36, -0x6e, 0x79, 0x00, 0x07, 0x01, 0x08, 0x05, 0x01, 0xf0, 0x06, -0x00, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, -0x00, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x00, 0x68, 0x69, 0x74, -0x74, 0x49, 0x00, 0x51, 0x61, 0x00, 0x77, 0x61, 0x6c, 0x2b, -0x00, 0x19, 0x61, 0x5e, 0x01, 0x17, 0x3b, 0xe3, 0x01, 0x02, -0xd4, 0x00, 0x00, 0x10, 0x00, 0x06, 0xa5, 0x01, 0x80, 0x69, -0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x77, 0x00, 0x06, -0xd0, 0x00, 0x51, 0x28, 0x6f, 0x6e, 0x63, 0x65, 0x6f, 0x01, -0xf4, 0x00, 0x46, 0x6f, 0x72, 0x00, 0x69, 0x6e, 0x73, 0x74, -0x61, 0x6e, 0x63, 0x65, 0x2c, 0x00, 0x61, 0x4a, 0x00, 0x03, -0x67, 0x02, 0x00, 0x7a, 0x00, 0x07, 0x50, 0x00, 0x82, 0x6f, -0x6e, 0x65, 0x00, 0x6d, 0x75, 0x73, 0x74, 0xab, 0x02, 0x10, -0x66, 0x69, 0x02, 0x0b, 0xea, 0x01, 0xf1, 0x04, 0x73, 0x00, -0x69, 0x74, 0x73, 0x00, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, -0x6f, 0x75, 0x72, 0x73, 0x00, 0x62, 0x79, 0x41, 0x00, 0x44, -0x6c, 0x61, 0x73, 0x74, 0x68, 0x02, 0x70, 0x6f, 0x6e, 0x3b, -0x00, 0x62, 0x75, 0x74, 0x18, 0x00, 0xe1, 0x6e, 0x00, 0x69, -0x74, 0x27, 0x73, 0x00, 0x69, 0x6d, 0x70, 0x6f, 0x73, 0x73, -0x69, 0x48, 0x01, 0x00, 0x90, 0x00, 0x10, 0x74, 0xca, 0x02, -0x11, 0x62, 0x86, 0x00, 0x60, 0x6e, 0x65, 0x63, 0x74, 0x65, -0x64, 0x10, 0x00, 0x00, 0x35, 0x01, 0x79, 0x6f, 0x75, 0x74, -0x73, 0x69, 0x64, 0x65, 0x86, 0x01, 0x10, 0x2c, 0x0e, 0x00, -0x84, 0x63, 0x68, 0x00, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0xb7, -0x01, 0x51, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x37, 0x00, 0x0a, -0x7a, 0x00, 0x49, 0x2e, 0x00, 0x53, 0x6f, 0xd4, 0x02, 0x25, -0x6c, 0x6c, 0x53, 0x03, 0x0a, 0xe9, 0x00, 0x00, 0x1d, 0x01, -0x61, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x94, 0x00, 0xa0, -0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, -0xdb, 0x01, 0x11, 0x65, 0x6c, 0x03, 0x60, 0x4e, 0x69, 0x6b, -0x6f, 0x6c, 0x69, 0x80, 0x00, 0x12, 0x6f, 0x12, 0x01, 0xa0, -0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x00, -0xd0, 0x02, 0x00, 0x75, 0x01, 0xd2, 0x74, 0x00, 0x60, 0x4b, -0x75, 0x72, 0x6f, 0x64, 0x6f, 0x6b, 0x6f, 0x27, 0x2c, 0x0c, -0x00, 0x50, 0x6d, 0x61, 0x73, 0x75, 0x27, 0xc9, 0x01, 0x24, -0x60, 0x57, 0xce, 0x02, 0x11, 0x42, 0x45, 0x01, 0xc0, 0x43, -0x65, 0x6c, 0x6c, 0x73, 0x27, 0x2e, 0x00, 0x5b, 0x31, 0x38, -0x5d, 0x7e, 0x00, 0x01, 0x1d, 0x04, 0x32, 0x00, 0x77, 0x61, -0xf5, 0x03, 0x43, 0x72, 0x69, 0x62, 0x75, 0x0a, 0x01, 0x22, -0x74, 0x68, 0x7e, 0x03, 0x13, 0x6c, 0x2a, 0x02, 0xf0, 0x01, -0x62, 0x79, 0x00, 0x4a, 0x6f, 0x6e, 0x61, 0x73, 0x00, 0x4b, -0x6f, 0x65, 0x6c, 0x6b, 0x65, 0x72, 0x3d, 0x00, 0x00, 0x45, -0x00, 0xd1, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, -0x77, 0x77, 0x77, 0x2e, 0x6e, 0xac, 0x00, 0xa2, 0x2e, 0x63, -0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0xcb, 0x00, -0x30, 0x73, 0x2f, 0x77, 0x84, 0x00, 0x41, 0x5f, 0x69, 0x73, -0x5f, 0xc9, 0x01, 0x20, 0x5f, 0x63, 0x84, 0x00, 0xc3, 0x2e, -0x68, 0x74, 0x6d, 0x6c, 0x00, 0x00, 0x00, 0x33, 0x35, 0x2e, -0x31, 0xa3, 0x04, 0x01, 0x82, 0x00, 0x30, 0x6f, 0x6c, 0x73, -0xac, 0x04, 0x56, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x6c, 0x02, -0x40, 0x6c, 0x65, 0x66, 0x74, 0xd0, 0x01, 0x30, 0x74, 0x6f, -0x6e, 0x9d, 0x00, 0x56, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x49, -0x02, 0x03, 0x75, 0x04, 0x26, 0x6f, 0x72, 0x31, 0x00, 0x11, -0x72, 0x0c, 0x03, 0x06, 0x32, 0x00, 0x6b, 0x6d, 0x61, 0x72, -0x6b, 0x00, 0x61, 0x98, 0x03, 0x21, 0x64, 0x6f, 0x05, 0x02, -0x82, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5b, -0x03, 0x32, 0x79, 0x6f, 0x75, 0xa4, 0x04, 0x10, 0x75, 0x38, -0x01, 0xc0, 0x74, 0x00, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, -0x00, 0x6e, 0x6f, 0x74, 0x2e, 0x02, 0x01, 0x7a, 0x00, 0x06, -0x8f, 0x04, 0x50, 0x52, 0x65, 0x70, 0x65, 0x61, 0x10, 0x00, -0x10, 0x63, 0xb0, 0x00, 0x00, 0xca, 0x02, 0x01, 0x5b, 0x00, -0x20, 0x65, 0x69, 0x45, 0x04, 0x04, 0x7f, 0x00, 0x02, 0x01, -0x02, 0x48, 0x79, 0x63, 0x6c, 0x65, 0x48, 0x03, 0x62, 0x74, -0x68, 0x72, 0x6f, 0x75, 0x67, 0xae, 0x00, 0x65, 0x74, 0x68, -0x72, 0x65, 0x65, 0x00, 0xa0, 0x02, 0x21, 0x73, 0x74, 0x64, -0x02, 0x30, 0x28, 0x66, 0x69, 0xe1, 0x01, 0x10, 0x2c, 0xa8, -0x00, 0x00, 0x64, 0x00, 0x00, 0x5d, 0x04, 0x50, 0x6d, 0x70, -0x74, 0x79, 0x29, 0x68, 0x03, 0x50, 0x6f, 0x70, 0x70, 0x6f, -0x73, 0xa1, 0x02, 0x05, 0xcd, 0x03, 0x23, 0x73, 0x2e, 0xe4, -0x05, 0xb2, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, 0x73, 0x6f, -0x00, 0x75, 0x73, 0x72, 0x00, 0xa1, 0x63, 0x75, 0x72, 0x73, -0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x53, 0x02, 0x20, 0x6d, -0x6f, 0x04, 0x06, 0x51, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x1f, -0x00, 0x01, 0x0d, 0x06, 0x05, 0xc8, 0x04, 0x41, 0x50, 0x72, -0x65, 0x73, 0xe5, 0x04, 0x94, 0x52, 0x65, 0x74, 0x75, 0x72, -0x6e, 0x00, 0x64, 0x6f, 0xef, 0x02, 0x30, 0x61, 0x6d, 0x65, -0x7d, 0x03, 0x0a, 0xeb, 0x00, 0x0b, 0x9e, 0x01, 0x01, 0x29, -0x03, 0x44, 0x6c, 0x65, 0x00, 0x70, 0x46, 0x00, 0x5e, 0x53, -0x70, 0x61, 0x63, 0x65, 0x45, 0x00, 0x1a, 0x61, 0xa2, 0x01, -0x01, 0x54, 0x00, 0x59, 0x2e, 0x00, 0x4d, 0x6f, 0x76, 0x59, -0x00, 0x08, 0xb9, 0x00, 0x02, 0x58, 0x00, 0x41, 0x68, 0x6f, -0x6c, 0x64, 0x57, 0x00, 0x42, 0x68, 0x69, 0x66, 0x74, 0x5a, -0x01, 0x22, 0x70, 0x6c, 0x62, 0x00, 0x21, 0x74, 0x73, 0xf7, -0x04, 0x25, 0x6c, 0x6c, 0x2a, 0x04, 0x01, 0xd0, 0x01, 0x00, -0x6c, 0x01, 0x00, 0xf2, 0x00, 0x14, 0x64, 0x72, 0x01, 0x00, -0x27, 0x01, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x62, 0x00, 0x12, -0x61, 0x3b, 0x01, 0x82, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, -0x69, 0x62, 0xc4, 0x04, 0x13, 0x73, 0xf4, 0x02, 0x32, 0x32, -0x2e, 0x31, 0x58, 0x06, 0x00, 0x4d, 0x01, 0x50, 0x61, 0x76, -0x61, 0x69, 0x6c, 0x87, 0x05, 0x22, 0x2e, 0x29, 0xb7, 0x02, -0x13, 0x32, 0xb7, 0x02, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, -0x65, 0x74, 0x65, 0x72, 0xb9, 0x02, 0x66, 0x54, 0x68, 0x65, -0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, -0x00, 0x04, 0xc3, 0x05, 0xf1, 0x01, 0x65, 0x00, 0x60, 0x43, -0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, -0x6f, 0x70, 0x6f, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, -0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, -0xab, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, -0x48, 0x65, 0x30, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, -0x76, 0x07, 0x01, 0xb6, 0x01, 0x00, 0xad, 0x00, 0x80, 0x71, -0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf4, 0x14, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x00, 0x73, 0x6f, 0x6d, +0x65, 0x0e, 0x00, 0xf0, 0x02, 0x00, 0x63, 0x6f, 0x6e, 0x74, +0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, +0x73, 0x2e, 0x3a, 0x00, 0xf0, 0x00, 0x72, 0x00, 0x6a, 0x6f, +0x62, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, +0x6c, 0x11, 0x00, 0x01, 0x34, 0x00, 0x56, 0x6f, 0x66, 0x00, +0x74, 0x68, 0x3b, 0x00, 0xf3, 0x28, 0x62, 0x6c, 0x61, 0x63, +0x6b, 0x2c, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, 0x74, 0x68, +0x61, 0x74, 0x00, 0x73, 0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, +0x00, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x00, +0x61, 0x72, 0x65, 0x00, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, +0x69, 0x65, 0x64, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x6e, +0x6f, 0x40, 0x00, 0x73, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, +0x61, 0x79, 0x00, 0x00, 0x6e, 0x00, 0x02, 0x6b, 0x00, 0x22, +0x65, 0x64, 0x59, 0x00, 0x14, 0x2e, 0x2f, 0x00, 0x32, 0x74, +0x77, 0x6f, 0x12, 0x00, 0x05, 0x79, 0x00, 0x00, 0x3e, 0x00, +0xf0, 0x00, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, +0x00, 0x28, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0xc6, 0x00, 0xd0, +0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, +0x74, 0x69, 0x63, 0x0e, 0x00, 0x12, 0x29, 0x44, 0x00, 0x71, +0x66, 0x6f, 0x72, 0x00, 0x61, 0x6e, 0x79, 0x49, 0x00, 0x45, +0x77, 0x68, 0x69, 0x74, 0xc2, 0x00, 0x10, 0x2c, 0xcf, 0x00, +0x20, 0x72, 0x65, 0x7c, 0x00, 0xe0, 0x61, 0x00, 0x70, 0x61, +0x74, 0x68, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, +0x18, 0x00, 0xca, 0x6d, 0x00, 0x75, 0x73, 0x69, 0x6e, 0x67, +0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x37, 0x00, 0x06, 0x56, 0x00, +0x4f, 0x65, 0x61, 0x63, 0x68, 0xcf, 0x00, 0x02, 0x12, 0x2c, +0x11, 0x01, 0x03, 0xdc, 0x00, 0x71, 0x64, 0x65, 0x6e, 0x6f, +0x74, 0x65, 0x73, 0x3d, 0x01, 0x54, 0x74, 0x6f, 0x74, 0x61, +0x6c, 0x19, 0x00, 0x2a, 0x6f, 0x66, 0x5a, 0x00, 0x20, 0x00, +0x72, 0x52, 0x00, 0x93, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x66, +0x72, 0x6f, 0x6d, 0x56, 0x01, 0x02, 0x60, 0x00, 0x20, 0x67, +0x6f, 0x8e, 0x00, 0xf1, 0x03, 0x69, 0x6e, 0x00, 0x61, 0x00, +0x73, 0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0x00, 0x6c, +0x69, 0x6e, 0x65, 0x13, 0x00, 0x36, 0x6e, 0x79, 0x00, 0x07, +0x01, 0x08, 0x05, 0x01, 0xf0, 0x06, 0x00, 0x64, 0x69, 0x72, +0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x75, 0x6e, 0x74, +0x69, 0x6c, 0x00, 0x68, 0x69, 0x74, 0x74, 0x49, 0x00, 0x51, +0x61, 0x00, 0x77, 0x61, 0x6c, 0x2b, 0x00, 0x19, 0x61, 0x5e, +0x01, 0x17, 0x3b, 0xe3, 0x01, 0x02, 0xd4, 0x00, 0x00, 0x10, +0x00, 0x06, 0xa5, 0x01, 0x80, 0x69, 0x6e, 0x63, 0x6c, 0x75, +0x64, 0x65, 0x64, 0x77, 0x00, 0x06, 0xd0, 0x00, 0x51, 0x28, +0x6f, 0x6e, 0x63, 0x65, 0x6f, 0x01, 0xf4, 0x00, 0x46, 0x6f, +0x72, 0x00, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, +0x2c, 0x00, 0x61, 0x4a, 0x00, 0x03, 0x67, 0x02, 0x00, 0x7a, +0x00, 0x07, 0x50, 0x00, 0x82, 0x6f, 0x6e, 0x65, 0x00, 0x6d, +0x75, 0x73, 0x74, 0xab, 0x02, 0x10, 0x66, 0x69, 0x02, 0x0b, +0xea, 0x01, 0xf1, 0x04, 0x73, 0x00, 0x69, 0x74, 0x73, 0x00, +0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x75, 0x72, 0x73, +0x00, 0x62, 0x79, 0x41, 0x00, 0x44, 0x6c, 0x61, 0x73, 0x74, +0x68, 0x02, 0x70, 0x6f, 0x6e, 0x3b, 0x00, 0x62, 0x75, 0x74, +0x18, 0x00, 0xe1, 0x6e, 0x00, 0x69, 0x74, 0x27, 0x73, 0x00, +0x69, 0x6d, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x48, 0x01, 0x00, +0x90, 0x00, 0x10, 0x74, 0xca, 0x02, 0x11, 0x62, 0x86, 0x00, +0x60, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x00, 0x00, +0x35, 0x01, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, +0x86, 0x01, 0x10, 0x2c, 0x0e, 0x00, 0x84, 0x63, 0x68, 0x00, +0x76, 0x69, 0x6f, 0x6c, 0x61, 0xb7, 0x01, 0x51, 0x73, 0x65, +0x63, 0x6f, 0x6e, 0x37, 0x00, 0x0a, 0x7a, 0x00, 0x49, 0x2e, +0x00, 0x53, 0x6f, 0xd4, 0x02, 0x25, 0x6c, 0x6c, 0x53, 0x03, +0x0a, 0xe9, 0x00, 0x00, 0x1d, 0x01, 0x61, 0x43, 0x72, 0x65, +0x64, 0x69, 0x74, 0x94, 0x00, 0xa0, 0x74, 0x68, 0x69, 0x73, +0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0xdb, 0x01, 0x11, 0x65, +0x6c, 0x03, 0x60, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x80, +0x00, 0x12, 0x6f, 0x12, 0x01, 0xa0, 0x76, 0x61, 0x72, 0x69, +0x6f, 0x75, 0x73, 0x6c, 0x79, 0x00, 0xd0, 0x02, 0x20, 0x65, +0x64, 0xca, 0x00, 0xb2, 0x60, 0x4b, 0x75, 0x72, 0x6f, 0x64, +0x6f, 0x6b, 0x6f, 0x27, 0x2c, 0x0c, 0x00, 0x50, 0x6d, 0x61, +0x73, 0x75, 0x27, 0xc9, 0x01, 0x24, 0x60, 0x57, 0xce, 0x02, +0x11, 0x42, 0x45, 0x01, 0xc0, 0x43, 0x65, 0x6c, 0x6c, 0x73, +0x27, 0x2e, 0x00, 0x5b, 0x31, 0x38, 0x5d, 0x7e, 0x00, 0x01, +0x2f, 0x04, 0x32, 0x00, 0x77, 0x61, 0xf5, 0x03, 0x43, 0x72, +0x69, 0x62, 0x75, 0x0a, 0x01, 0x22, 0x74, 0x68, 0x7e, 0x03, +0x13, 0x6c, 0x2a, 0x02, 0xf0, 0x01, 0x62, 0x79, 0x00, 0x4a, +0x6f, 0x6e, 0x61, 0x73, 0x00, 0x4b, 0x6f, 0x65, 0x6c, 0x6b, +0x65, 0x72, 0x3d, 0x00, 0x00, 0x45, 0x00, 0xe1, 0x00, 0x68, +0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, +0x2e, 0x6e, 0xad, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, +0x70, 0x2f, 0x65, 0x6e, 0x2f, 0xcc, 0x00, 0x33, 0x73, 0x2f, +0x6b, 0x9f, 0x00, 0x83, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x35, +0x2e, 0x31, 0xa6, 0x04, 0x01, 0x73, 0x00, 0x40, 0x6f, 0x6c, +0x73, 0x20, 0x07, 0x01, 0x46, 0x6c, 0x69, 0x63, 0x6b, 0x5d, +0x02, 0x40, 0x6c, 0x65, 0x66, 0x74, 0xc1, 0x01, 0x30, 0x74, +0x6f, 0x6e, 0x8e, 0x00, 0x56, 0x70, 0x61, 0x69, 0x6e, 0x74, +0x3a, 0x02, 0x03, 0x66, 0x04, 0x26, 0x6f, 0x72, 0x31, 0x00, +0x11, 0x72, 0xfd, 0x02, 0x06, 0x32, 0x00, 0x6b, 0x6d, 0x61, +0x72, 0x6b, 0x00, 0x61, 0x89, 0x03, 0x21, 0x64, 0x6f, 0xf6, +0x01, 0x82, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, +0x4c, 0x03, 0x32, 0x79, 0x6f, 0x75, 0x95, 0x04, 0x30, 0x75, +0x72, 0x65, 0x4d, 0x01, 0xa0, 0x73, 0x68, 0x6f, 0x75, 0x6c, +0x64, 0x00, 0x6e, 0x6f, 0x74, 0x1f, 0x02, 0x01, 0x7a, 0x00, +0x06, 0x80, 0x04, 0x50, 0x52, 0x65, 0x70, 0x65, 0x61, 0x10, +0x00, 0x10, 0x63, 0xb0, 0x00, 0x00, 0xbb, 0x02, 0x01, 0x5b, +0x00, 0x20, 0x65, 0x69, 0x36, 0x04, 0x04, 0x7f, 0x00, 0x02, +0xf2, 0x01, 0x48, 0x79, 0x63, 0x6c, 0x65, 0x39, 0x03, 0x72, +0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x22, 0x03, 0x55, +0x68, 0x72, 0x65, 0x65, 0x00, 0x91, 0x02, 0x21, 0x73, 0x74, +0x55, 0x02, 0x30, 0x28, 0x66, 0x69, 0xd2, 0x01, 0x10, 0x2c, +0xa8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x4e, 0x04, 0x50, 0x6d, +0x70, 0x74, 0x79, 0x29, 0x59, 0x03, 0x50, 0x6f, 0x70, 0x70, +0x6f, 0x73, 0x92, 0x02, 0x05, 0xbe, 0x03, 0x23, 0x73, 0x2e, +0xd5, 0x05, 0xb2, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, 0x73, +0x6f, 0x00, 0x75, 0x73, 0x72, 0x00, 0xb1, 0x63, 0x75, 0x72, +0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x0c, 0x01, +0x10, 0x6f, 0xf5, 0x05, 0x51, 0x72, 0x6f, 0x75, 0x6e, 0x64, +0x1f, 0x00, 0x01, 0xfe, 0x05, 0x05, 0xb9, 0x04, 0x41, 0x50, +0x72, 0x65, 0x73, 0xd6, 0x04, 0x94, 0x52, 0x65, 0x74, 0x75, +0x72, 0x6e, 0x00, 0x64, 0x6f, 0xe0, 0x02, 0x30, 0x61, 0x6d, +0x65, 0x6e, 0x03, 0x0a, 0xeb, 0x00, 0x0b, 0x9e, 0x01, 0x01, +0x1a, 0x03, 0x44, 0x6c, 0x65, 0x00, 0x70, 0x46, 0x00, 0x5e, +0x53, 0x70, 0x61, 0x63, 0x65, 0x45, 0x00, 0x1a, 0x61, 0xa2, +0x01, 0x01, 0x54, 0x00, 0x59, 0x2e, 0x00, 0x4d, 0x6f, 0x76, +0x59, 0x00, 0x08, 0xb9, 0x00, 0x02, 0x58, 0x00, 0x41, 0x68, +0x6f, 0x6c, 0x64, 0x57, 0x00, 0x42, 0x68, 0x69, 0x66, 0x74, +0x5a, 0x01, 0x22, 0x70, 0x6c, 0x62, 0x00, 0x21, 0x74, 0x73, +0xe8, 0x04, 0x25, 0x6c, 0x6c, 0x1b, 0x04, 0x01, 0xd0, 0x01, +0x00, 0x6c, 0x01, 0x00, 0xf2, 0x00, 0x14, 0x64, 0x72, 0x01, +0x00, 0x27, 0x01, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x62, 0x00, +0x12, 0x61, 0x3b, 0x01, 0x82, 0x00, 0x64, 0x65, 0x73, 0x63, +0x72, 0x69, 0x62, 0xb5, 0x04, 0x13, 0x73, 0xe5, 0x02, 0x32, +0x32, 0x2e, 0x31, 0x49, 0x06, 0x00, 0x4d, 0x01, 0x50, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x78, 0x05, 0x22, 0x2e, 0x29, 0xb7, +0x02, 0x13, 0x32, 0xb7, 0x02, 0x91, 0x70, 0x61, 0x72, 0x61, +0x6d, 0x65, 0x74, 0x65, 0x72, 0xb9, 0x02, 0x66, 0x54, 0x68, +0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, +0x3c, 0x00, 0x04, 0xb4, 0x05, 0xf1, 0x01, 0x65, 0x00, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x6f, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, +0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, +0x75, 0xab, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, +0x00, 0x48, 0x65, 0x30, 0x01, 0x51, 0x00, 0x00, 0x53, 0x69, +0x7a, 0x67, 0x07, 0x01, 0xb6, 0x01, 0x28, 0x69, 0x6e, 0x72, +0x06, 0x43, 0x33, 0x35, 0x2e, 0x33, 0x95, 0x00, 0xf1, 0x00, +0x75, 0x73, 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, +0x72, 0x65, 0x6e, 0x63, 0x65, 0x9b, 0x00, 0x20, 0x4f, 0x6e, +0x2c, 0x01, 0x63, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x38, +0x06, 0x70, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, +0x00, 0x17, 0x00, 0x2e, 0x00, 0x12, 0x2c, 0x89, 0x00, 0x16, +0x50, 0x12, 0x00, 0x0d, 0xa5, 0x00, 0x33, 0x47, 0x61, 0x6d, +0xa5, 0x00, 0x02, 0x86, 0x01, 0x22, 0x6c, 0x65, 0x3b, 0x03, +0x60, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3c, 0x03, 0x02, +0x23, 0x05, 0x46, 0x77, 0x61, 0x79, 0x00, 0x6b, 0x02, 0x20, +0x6d, 0x6f, 0x94, 0x02, 0x02, 0xf5, 0x01, 0x80, 0x73, 0x00, +0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x00, }; -const unsigned short help_text_len = 2036; -const unsigned short help_text_words = 365; +const unsigned short help_text_len = 2223; +const unsigned short help_text_words = 395; const char quick_help_text[] = "Place black squares to limit the visible distance from each numbered cell."; diff --git a/apps/plugins/puzzles/help/rect.c b/apps/plugins/puzzles/help/rect.c index e86a77091b..c608c4fc98 100644 --- a/apps/plugins/puzzles/help/rect.c +++ b/apps/plugins/puzzles/help/rect.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,257 +6,256 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 144, TEXT_CENTER | C_RED }, - { 311, TEXT_CENTER | C_RED }, - { 328, TEXT_UNDERLINE }, - { 329, TEXT_UNDERLINE }, - { 339, TEXT_UNDERLINE }, - { 381, TEXT_UNDERLINE }, - { 512, TEXT_UNDERLINE }, - { 537, TEXT_UNDERLINE }, - { 582, TEXT_UNDERLINE }, + { 142, TEXT_CENTER | C_RED }, + { 309, TEXT_CENTER | C_RED }, + { 326, TEXT_UNDERLINE }, + { 327, TEXT_UNDERLINE }, + { 337, TEXT_UNDERLINE }, + { 379, TEXT_UNDERLINE }, + { 510, TEXT_UNDERLINE }, + { 535, TEXT_UNDERLINE }, + { 580, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 3535 comp 2341 ratio 0.662235 level 10 saved 1194 */ +/* orig 3536 comp 2332 ratio 0.659502 level 10 saved 1204 */ const char help_text[] = { -0xf0, 0x50, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x09, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x38, 0x3a, 0x20, 0x52, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, -0x6c, 0x65, 0x73, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, -0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, -0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, -0x72, 0x65, 0x73, 0x2c, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x00, 0x77, 0x72, -0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x69, 0x6e, 0x00, 0x73, -0x6f, 0x6d, 0x65, 0x00, 0x28, 0x62, 0x75, 0x74, 0x00, 0x6e, -0x6f, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x29, 0x37, 0x00, 0x34, -0x74, 0x68, 0x65, 0x3b, 0x00, 0x10, 0x2e, 0x57, 0x00, 0xf1, -0x07, 0x72, 0x00, 0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, 0x73, -0x00, 0x74, 0x6f, 0x00, 0x73, 0x75, 0x62, 0x64, 0x69, 0x76, -0x69, 0x64, 0x65, 0x27, 0x00, 0x01, 0x6a, 0x00, 0x65, 0x69, -0x6e, 0x74, 0x6f, 0x00, 0x72, 0x8d, 0x00, 0x00, 0x43, 0x00, -0xb0, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x73, -0x69, 0x7a, 0x80, 0x00, 0xf6, 0x04, 0x73, 0x75, 0x63, 0x68, -0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x28, 0x61, 0x29, 0x00, -0x65, 0x76, 0x65, 0x72, 0x79, 0x31, 0x00, 0xf3, 0x06, 0x00, -0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x00, 0x65, -0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x00, 0x6f, 0x6e, 0x65, -0xae, 0x00, 0x23, 0x65, 0x64, 0x8a, 0x00, 0x91, 0x2c, 0x00, -0x61, 0x6e, 0x64, 0x00, 0x28, 0x62, 0x29, 0x77, 0x00, 0x40, -0x61, 0x72, 0x65, 0x61, 0x67, 0x00, 0x47, 0x65, 0x61, 0x63, -0x68, 0x49, 0x00, 0x80, 0x69, 0x73, 0x00, 0x65, 0x71, 0x75, -0x61, 0x6c, 0xa8, 0x00, 0x24, 0x74, 0x68, 0x44, 0x00, 0x08, -0xf1, 0x00, 0x3c, 0x69, 0x74, 0x73, 0x5a, 0x00, 0xf4, 0x0e, -0x2e, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, -0x00, 0x66, 0x6f, 0x72, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, -0x67, 0x61, 0x6d, 0x65, 0x00, 0x67, 0x6f, 0x65, 0x73, 0x4a, -0x00, 0xf0, 0x18, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, -0x65, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x6d, -0x61, 0x67, 0x61, 0x7a, 0x69, 0x6e, 0x65, 0x00, 0x4e, 0x69, -0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x33, 0x5d, 0x3b, 0x00, -0x49, 0x27, 0x7e, 0x01, 0xf2, 0x14, 0x6c, 0x73, 0x6f, 0x00, -0x73, 0x65, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x50, 0x61, 0x6c, -0x6d, 0x00, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, -0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x61, 0x74, 0x00, -0x50, 0x44, 0x00, 0xfa, 0x03, 0x50, 0x61, 0x6c, 0x61, 0x63, -0x65, 0x00, 0x5b, 0x34, 0x5d, 0x2e, 0x00, 0x55, 0x6e, 0x6c, -0x69, 0x6b, 0x65, 0x1a, 0x00, 0x2b, 0x27, 0x73, 0x3c, 0x00, -0x91, 0x2c, 0x00, 0x6d, 0x79, 0x00, 0x76, 0x65, 0x72, 0x73, -0x48, 0x00, 0xf1, 0x0e, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, -0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x67, 0x65, 0x6e, -0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x00, 0x72, 0x61, 0x6e, -0x64, 0x6f, 0x6d, 0x99, 0x01, 0x01, 0x8a, 0x01, 0x31, 0x61, -0x6e, 0x79, 0x86, 0x01, 0x50, 0x00, 0x79, 0x6f, 0x75, 0x00, -0x65, 0x00, 0x60, 0x2e, 0x00, 0x54, 0x68, 0x65, 0x00, 0x27, -0x01, 0x30, 0x69, 0x74, 0x79, 0x22, 0x00, 0x03, 0xd3, 0x00, -0x61, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0xe6, 0x01, 0x81, -0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x16, 0x02, -0xd0, 0x71, 0x75, 0x69, 0x74, 0x65, 0x00, 0x61, 0x73, 0x00, -0x67, 0x6f, 0x6f, 0x64, 0x08, 0x00, 0xc3, 0x68, 0x61, 0x6e, -0x64, 0x2d, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x64, 0x3d, -0x00, 0xc0, 0x73, 0x00, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, -0x62, 0x65, 0x2c, 0x00, 0x4e, 0x02, 0x21, 0x6f, 0x6e, 0x36, -0x01, 0x21, 0x70, 0x6c, 0x03, 0x02, 0x12, 0x64, 0x7d, 0x00, -0x50, 0x67, 0x65, 0x74, 0x00, 0x61, 0x86, 0x01, 0xf7, 0x02, -0x65, 0x78, 0x68, 0x61, 0x75, 0x73, 0x74, 0x69, 0x62, 0x6c, -0x65, 0x00, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x87, 0x00, 0x70, -0x73, 0x00, 0x74, 0x61, 0x69, 0x6c, 0x6f, 0x9f, 0x01, 0x40, -0x74, 0x6f, 0x00, 0x79, 0x7d, 0x02, 0xc1, 0x6f, 0x77, 0x6e, -0x00, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x08, -0x01, 0x00, 0xb2, 0x01, 0xf1, 0x01, 0x5b, 0x33, 0x5d, 0x00, -0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, -0x2e, 0x6e, 0x87, 0x01, 0xa3, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, -0x70, 0x2f, 0x65, 0x6e, 0x2f, 0x4d, 0x00, 0xf0, 0x06, 0x2f, -0x73, 0x68, 0x69, 0x6b, 0x61, 0x6b, 0x75, 0x2e, 0x68, 0x74, -0x6d, 0x6c, 0x00, 0x28, 0x62, 0x65, 0x77, 0x61, 0x72, 0x65, -0x6d, 0x00, 0x60, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x29, 0x48, -0x00, 0x12, 0x34, 0x48, 0x00, 0x10, 0x73, 0x49, 0x00, 0xe0, -0x65, 0x62, 0x2e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, -0x2e, 0x6f, 0x72, 0x67, 0x10, 0x00, 0xf7, 0x01, 0x2f, 0x32, -0x30, 0x30, 0x34, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30, 0x31, -0x34, 0x35, 0x39, 0x2f, 0x73, 0x00, 0x02, 0x63, 0x00, 0x30, -0x2e, 0x67, 0x72, 0x73, 0x00, 0x02, 0x0d, 0x00, 0x21, 0x2f, -0x73, 0x6e, 0x00, 0xb1, 0x2f, 0x70, 0x61, 0x6c, 0x6d, 0x2f, -0x69, 0x6e, 0x64, 0x65, 0x78, 0x79, 0x00, 0x98, 0x2e, 0x65, -0x6e, 0x00, 0x00, 0x00, 0x38, 0x2e, 0x31, 0xb2, 0x03, 0x00, -0xf5, 0x02, 0x31, 0x72, 0x6f, 0x6c, 0xbb, 0x03, 0x15, 0x54, -0x74, 0x02, 0x92, 0x69, 0x73, 0x00, 0x70, 0x6c, 0x61, 0x79, -0x65, 0x64, 0xb3, 0x03, 0x00, 0x45, 0x01, 0xf0, 0x05, 0x6d, -0x6f, 0x75, 0x73, 0x65, 0x00, 0x6f, 0x72, 0x00, 0x63, 0x75, -0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x02, -0x01, 0xa1, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, -0x63, 0x6b, 0xe4, 0x01, 0x41, 0x65, 0x64, 0x67, 0x65, 0xae, -0x02, 0x21, 0x6f, 0x67, 0x0b, 0x03, 0x01, 0x85, 0x01, 0x70, -0x6f, 0x72, 0x00, 0x6f, 0x66, 0x66, 0x2c, 0x08, 0x00, 0x18, -0x6c, 0x2f, 0x00, 0x60, 0x64, 0x00, 0x64, 0x72, 0x61, 0x67, -0x2f, 0x00, 0x40, 0x64, 0x72, 0x61, 0x77, 0x96, 0x01, 0x67, -0x65, 0x6e, 0x74, 0x69, 0x72, 0x65, 0x4c, 0x03, 0x10, 0x28, -0x34, 0x00, 0x44, 0x69, 0x6e, 0x65, 0x29, 0xcd, 0x01, 0x03, -0xeb, 0x03, 0x01, 0x9d, 0x03, 0xc2, 0x67, 0x6f, 0x00, 0x28, -0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x7e, 0x00, -0x40, 0x78, 0x69, 0x73, 0x74, 0x0d, 0x00, 0x00, 0x87, 0x00, -0x11, 0x73, 0xbd, 0x00, 0x22, 0x69, 0x6e, 0xf2, 0x03, 0x05, -0x53, 0x00, 0x73, 0x29, 0x2e, 0x00, 0x52, 0x69, 0x67, 0x68, -0x86, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x89, 0x00, 0x10, 0x67, -0x0d, 0x00, 0x40, 0x77, 0x69, 0x6c, 0x6c, 0x83, 0x04, 0x21, -0x6f, 0x77, 0x2e, 0x02, 0x72, 0x74, 0x6f, 0x00, 0x65, 0x72, -0x61, 0x73, 0x67, 0x04, 0x00, 0x2d, 0x01, 0x32, 0x65, 0x6e, -0x74, 0xd1, 0x02, 0x07, 0xa5, 0x00, 0x00, 0x68, 0x00, 0x91, -0x6f, 0x75, 0x74, 0x00, 0x61, 0x66, 0x66, 0x65, 0x63, 0x80, -0x00, 0x00, 0xe1, 0x03, 0x01, 0x84, 0x00, 0x00, 0x23, 0x01, -0xf4, 0x01, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, -0x69, 0x76, 0x65, 0x6c, 0x79, 0x2c, 0x00, 0x75, 0x4e, 0x00, -0x06, 0x49, 0x01, 0x00, 0x67, 0x00, 0x42, 0x6d, 0x6f, 0x76, -0x65, 0xaf, 0x02, 0x31, 0x6f, 0x73, 0x69, 0xa4, 0x03, 0x30, -0x69, 0x6e, 0x64, 0x6b, 0x02, 0x91, 0x6f, 0x72, 0x00, 0x61, -0x72, 0x6f, 0x75, 0x6e, 0x64, 0x1e, 0x00, 0xc0, 0x62, 0x6f, -0x61, 0x72, 0x64, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, -0x6a, 0x00, 0x20, 0x74, 0x68, 0x2f, 0x01, 0x40, 0x74, 0x75, -0x72, 0x6e, 0x4a, 0x00, 0x00, 0x0f, 0x00, 0x12, 0x6e, 0xbf, -0x00, 0x14, 0x73, 0xc0, 0x00, 0x0f, 0x70, 0x00, 0x04, 0x01, -0x7b, 0x01, 0x08, 0xc6, 0x00, 0x00, 0xc2, 0x00, 0x42, 0x66, -0x72, 0x6f, 0x6d, 0x30, 0x01, 0x04, 0x86, 0x00, 0x02, 0xf2, -0x04, 0x1f, 0x70, 0x6f, 0x00, 0x04, 0x80, 0x61, 0x67, 0x61, -0x69, 0x6e, 0x00, 0x63, 0x6f, 0x21, 0x04, 0x21, 0x74, 0x65, -0xb4, 0x03, 0x06, 0x52, 0x00, 0x35, 0x2e, 0x00, 0x55, 0x34, -0x00, 0x20, 0x73, 0x70, 0x65, 0x04, 0xa1, 0x62, 0x61, 0x72, -0x00, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x19, 0x06, 0x0c, -0x4d, 0x00, 0x09, 0xb7, 0x00, 0x0f, 0x77, 0x01, 0x2a, 0x10, -0x2c, 0x22, 0x04, 0x57, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x2b, -0x01, 0xf1, 0x01, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x00, -0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x73, 0x00, 0x61, 0x03, -0x01, 0x00, 0xa1, 0x01, 0x11, 0x57, 0x35, 0x01, 0x08, 0x0b, -0x01, 0x13, 0x66, 0x79, 0x00, 0x10, 0x72, 0x14, 0x00, 0x02, -0xb9, 0x04, 0x25, 0x69, 0x73, 0xe8, 0x00, 0x20, 0x64, 0x2c, -0xd9, 0x02, 0x01, 0x2a, 0x02, 0x90, 0x62, 0x65, 0x00, 0x73, -0x68, 0x61, 0x64, 0x65, 0x64, 0x48, 0x00, 0x42, 0x28, 0x41, -0x6c, 0x6c, 0x19, 0x06, 0x10, 0x63, 0x3b, 0x01, 0x10, 0x73, -0xcd, 0x04, 0x61, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0xe6, -0x06, 0x21, 0x65, 0x63, 0xd7, 0x01, 0x30, 0x32, 0x2e, 0x31, -0x3a, 0x06, 0x02, 0xa3, 0x05, 0xb1, 0x61, 0x76, 0x61, 0x69, -0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x9d, 0x03, 0x18, -0x32, 0x9d, 0x03, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, -0x74, 0x65, 0x72, 0x9f, 0x03, 0x01, 0xfa, 0x05, 0x05, 0x14, -0x00, 0x02, 0x45, 0x00, 0x04, 0x40, 0x00, 0x04, 0xbb, 0x01, -0xf1, 0x01, 0x65, 0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, -0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x73, 0x00, -0x03, 0x3c, 0x03, 0xb1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, -0x00, 0x6d, 0x65, 0x6e, 0x75, 0xf7, 0x00, 0x80, 0x69, 0x64, -0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x0f, 0x03, 0x61, 0x00, -0x00, 0x00, 0x53, 0x69, 0x7a, 0xfb, 0x00, 0x00, 0x63, 0x03, -0x11, 0x2c, 0xb2, 0x00, 0x04, 0x7e, 0x07, 0x70, 0x00, 0x00, -0x45, 0x78, 0x70, 0x61, 0x6e, 0xf2, 0x05, 0x40, 0x20, 0x66, -0x61, 0x63, 0x93, 0x02, 0x03, 0x2f, 0x04, 0x10, 0x69, 0x48, -0x01, 0x91, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, -0x6d, 0xbb, 0x06, 0x00, 0x0c, 0x00, 0x14, 0x67, 0xf8, 0x01, -0x35, 0x74, 0x79, 0x70, 0x54, 0x00, 0x15, 0x73, 0x20, 0x06, -0x42, 0x64, 0x00, 0x62, 0x79, 0xec, 0x02, 0x90, 0x72, 0x6f, -0x67, 0x72, 0x61, 0x6d, 0x2e, 0x00, 0x53, 0x03, 0x08, 0x60, -0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x6d, 0x02, 0x34, 0x66, -0x65, 0x72, 0x41, 0x08, 0x03, 0x97, 0x07, 0x01, 0xa9, 0x03, -0x97, 0x00, 0x66, 0x65, 0x77, 0x00, 0x6c, 0x61, 0x72, 0x67, -0x66, 0x02, 0x01, 0xcd, 0x02, 0x00, 0x0e, 0x04, 0x07, 0x29, -0x00, 0x11, 0x6d, 0x6f, 0x06, 0x40, 0x6d, 0x61, 0x6c, 0x6c, -0x1a, 0x00, 0x10, 0x73, 0x5f, 0x00, 0x01, 0x57, 0x02, 0x40, -0x63, 0x61, 0x6e, 0x00, 0x44, 0x08, 0x19, 0x52, 0x3d, 0x00, -0x30, 0x65, 0x73, 0x73, 0x78, 0x04, 0x09, 0xc2, 0x06, 0x22, -0x00, 0x61, 0x40, 0x00, 0x22, 0x65, 0x72, 0x86, 0x00, 0x32, -0x74, 0x68, 0x61, 0x44, 0x01, 0x05, 0xc5, 0x06, 0x03, 0x0c, -0x06, 0x22, 0x65, 0x64, 0x22, 0x03, 0x01, 0x79, 0x03, 0x00, -0x4d, 0x00, 0x00, 0x29, 0x01, 0x10, 0x64, 0x20, 0x02, 0x60, -0x62, 0x79, 0x00, 0x61, 0x64, 0x64, 0x8f, 0x00, 0x10, 0x72, -0xd7, 0x02, 0x20, 0x61, 0x6e, 0xcc, 0x00, 0x41, 0x6c, 0x75, -0x6d, 0x6e, 0x51, 0x01, 0x00, 0xfe, 0x06, 0x72, 0x64, 0x65, -0x66, 0x61, 0x75, 0x6c, 0x74, 0x34, 0x00, 0x01, 0x4f, 0x07, -0x03, 0x5d, 0x01, 0xd2, 0x6f, 0x66, 0x00, 0x7a, 0x65, 0x72, -0x6f, 0x00, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x90, 0x03, 0x07, -0xb3, 0x00, 0x01, 0x79, 0x02, 0x10, 0x73, 0x95, 0x07, 0x09, -0xb0, 0x00, 0x04, 0x6f, 0x09, 0x09, 0xa6, 0x00, 0x00, 0xee, -0x00, 0x42, 0x66, 0x6f, 0x72, 0x2c, 0xe5, 0x04, 0x10, 0x6f, -0x4b, 0x07, 0x10, 0x68, 0x93, 0x00, 0x30, 0x66, 0x75, 0x72, -0x60, 0x07, 0x42, 0x2e, 0x00, 0x49, 0x66, 0xce, 0x00, 0x02, -0x16, 0x07, 0x0f, 0x8a, 0x00, 0x01, 0x91, 0x28, 0x73, 0x61, -0x79, 0x29, 0x00, 0x30, 0x2e, 0x35, 0xf6, 0x02, 0x07, 0x93, -0x00, 0x01, 0xf7, 0x08, 0x42, 0x64, 0x69, 0x6d, 0x65, 0x32, -0x00, 0x26, 0x6f, 0x66, 0xa1, 0x05, 0x04, 0x1c, 0x03, 0x02, -0x0e, 0x01, 0x02, 0x46, 0x07, 0x43, 0x68, 0x61, 0x6c, 0x66, -0x31, 0x04, 0x70, 0x61, 0x73, 0x00, 0x62, 0x69, 0x67, 0x00, -0xbc, 0x07, 0x14, 0x72, 0xc3, 0x00, 0x01, 0x52, 0x07, 0x60, -0x49, 0x6e, 0x00, 0x6f, 0x74, 0x68, 0x2d, 0x09, 0x51, 0x6f, -0x72, 0x64, 0x73, 0x2c, 0x51, 0x00, 0x30, 0x69, 0x6e, 0x69, -0x9d, 0x01, 0x0a, 0x59, 0x00, 0x36, 0x32, 0x2f, 0x33, 0xe9, -0x00, 0x2b, 0x69, 0x6e, 0x8c, 0x00, 0x02, 0xef, 0x00, 0x0f, -0x85, 0x00, 0x01, 0x00, 0x22, 0x04, 0x21, 0x66, 0x75, 0x40, -0x01, 0x17, 0x7a, 0x42, 0x04, 0x24, 0x64, 0x64, 0x43, 0x06, -0x28, 0x6d, 0x6f, 0x80, 0x06, 0x01, 0xab, 0x01, 0x31, 0x53, -0x65, 0x74, 0x5e, 0x04, 0x0f, 0x20, 0x01, 0x04, 0x03, 0x9d, -0x05, 0x82, 0x30, 0x2e, 0x35, 0x00, 0x74, 0x65, 0x6e, 0x64, -0xcd, 0x05, 0x23, 0x61, 0x6b, 0x9a, 0x0a, 0x00, 0x4f, 0x07, -0x01, 0x54, 0x00, 0x92, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, -0x75, 0x6c, 0x74, 0x9d, 0x00, 0x01, 0xfe, 0x03, 0x50, 0x28, -0x69, 0x6e, 0x00, 0x6d, 0xb7, 0x06, 0xb0, 0x70, 0x65, 0x72, -0x69, 0x65, 0x6e, 0x63, 0x65, 0x29, 0x00, 0x72, 0x1d, 0x08, -0x10, 0x64, 0x56, 0x03, 0x30, 0x6c, 0x65, 0x73, 0x42, 0x04, -0x30, 0x64, 0x75, 0x63, 0x3a, 0x06, 0x01, 0x35, 0x00, 0x01, -0x49, 0x00, 0x51, 0x69, 0x6e, 0x74, 0x75, 0x69, 0x13, 0x00, -0x00, 0xa4, 0x07, 0x00, 0x99, 0x00, 0x59, 0x73, 0x74, 0x79, -0x6c, 0x65, 0xcb, 0x01, 0xd0, 0x69, 0x74, 0x00, 0x74, 0x6f, -0x6f, 0x00, 0x68, 0x69, 0x67, 0x68, 0x2c, 0x00, 0xe4, 0x00, -0x02, 0x08, 0x00, 0x03, 0x90, 0x00, 0x03, 0x3c, 0x02, 0x30, -0x63, 0x61, 0x6e, 0x5a, 0x09, 0x05, 0x43, 0x02, 0x01, 0x5e, -0x00, 0x01, 0xe9, 0x02, 0x02, 0x69, 0x03, 0x0a, 0x63, 0x03, -0x51, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x00, 0x03, 0xa5, -0x07, 0x02, 0x27, 0x04, 0x03, 0xfc, 0x02, 0x02, 0x59, 0x00, -0x50, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x2f, 0x00, 0x61, 0x72, -0x69, 0x76, 0x69, 0x61, 0x6c, 0x39, 0x04, 0xf1, 0x02, 0x6e, -0x73, 0x75, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, -0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x92, 0x04, 0x60, 0x00, -0x00, 0x4e, 0x6f, 0x72, 0x6d, 0x73, 0x03, 0x1d, 0x2c, 0xdb, -0x02, 0x01, 0x3d, 0x01, 0x00, 0x36, 0x00, 0x02, 0x67, 0x02, -0x01, 0x28, 0x04, 0x03, 0x96, 0x09, 0x21, 0x69, 0x74, 0x8b, -0x06, 0x01, 0x0e, 0x06, 0x01, 0x66, 0x0c, 0x23, 0x6f, 0x6e, -0xa9, 0x0b, 0x04, 0x5a, 0x00, 0x13, 0x2e, 0xbe, 0x0a, 0x12, -0x73, 0xbb, 0x08, 0x61, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, -0x04, 0x0c, 0x13, 0x65, 0x95, 0x05, 0x00, 0x05, 0x04, 0x1c, -0x62, 0x95, 0x01, 0x06, 0x5f, 0x01, 0xd5, 0x73, 0x75, 0x62, -0x74, 0x6c, 0x65, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x69, 0x66, -0xaf, 0x0a, 0x05, 0x3f, 0x04, 0x01, 0xae, 0x06, 0x32, 0x6f, -0x66, 0x66, 0xa2, 0x0b, 0x62, 0x66, 0x65, 0x61, 0x74, 0x75, -0x72, 0x9d, 0x01, 0x40, 0x72, 0x69, 0x73, 0x6b, 0x95, 0x00, -0x01, 0x2b, 0x02, 0x05, 0x77, 0x00, 0x03, 0xba, 0x00, 0xb2, -0x2e, 0x00, 0x41, 0x6c, 0x73, 0x6f, 0x2c, 0x00, 0x66, 0x69, -0x6e, 0x6b, 0x02, 0x24, 0x6c, 0x6c, 0xed, 0x07, 0x12, 0x73, -0x82, 0x0a, 0x03, 0xc0, 0x00, 0x05, 0xa0, 0x00, 0x21, 0x61, -0x6e, 0x97, 0x02, 0x00, 0x14, 0x00, 0x20, 0x61, 0x6c, 0x55, -0x05, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x63, 0x05, -0x01, 0x1c, 0x00, 0x10, 0x76, 0xc8, 0x06, 0x12, 0x64, 0xa9, -0x09, 0x61, 0x72, 0x2e, 0x00, 0x54, 0x75, 0x72, 0xfc, 0x04, -0x05, 0x9c, 0x00, 0x03, 0xfc, 0x05, 0x01, 0xf4, 0x04, 0x01, -0x0e, 0x0c, 0x74, 0x70, 0x65, 0x65, 0x64, 0x00, 0x75, 0x70, -0x6a, 0x0b, 0x03, 0xf8, 0x01, 0x50, 0x69, 0x6f, 0x6e, 0x2e, -0x00, +0x6c, 0x65, 0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x01, 0xf0, +0x3a, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, +0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, +0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, +0x2c, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x6e, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x73, 0x00, 0x77, 0x72, 0x69, 0x74, 0x74, +0x65, 0x6e, 0x00, 0x69, 0x6e, 0x00, 0x73, 0x6f, 0x6d, 0x65, +0x00, 0x28, 0x62, 0x75, 0x74, 0x00, 0x6e, 0x6f, 0x74, 0x00, +0x61, 0x6c, 0x6c, 0x29, 0x37, 0x00, 0x34, 0x74, 0x68, 0x65, +0x3b, 0x00, 0x10, 0x2e, 0x57, 0x00, 0xf1, 0x07, 0x72, 0x00, +0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, +0x00, 0x73, 0x75, 0x62, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, +0x27, 0x00, 0x01, 0x6a, 0x00, 0x65, 0x69, 0x6e, 0x74, 0x6f, +0x00, 0x72, 0xa3, 0x00, 0x00, 0x43, 0x00, 0xb0, 0x76, 0x61, +0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x73, 0x69, 0x7a, 0x80, +0x00, 0xf6, 0x04, 0x73, 0x75, 0x63, 0x68, 0x00, 0x74, 0x68, +0x61, 0x74, 0x00, 0x28, 0x61, 0x29, 0x00, 0x65, 0x76, 0x65, +0x72, 0x79, 0x31, 0x00, 0xf3, 0x06, 0x00, 0x63, 0x6f, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0x73, 0x00, 0x65, 0x78, 0x61, 0x63, +0x74, 0x6c, 0x79, 0x00, 0x6f, 0x6e, 0x65, 0xae, 0x00, 0x23, +0x65, 0x64, 0x8a, 0x00, 0x91, 0x2c, 0x00, 0x61, 0x6e, 0x64, +0x00, 0x28, 0x62, 0x29, 0x77, 0x00, 0x40, 0x61, 0x72, 0x65, +0x61, 0x67, 0x00, 0x47, 0x65, 0x61, 0x63, 0x68, 0x49, 0x00, +0x80, 0x69, 0x73, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6c, 0xa8, +0x00, 0x24, 0x74, 0x68, 0x44, 0x00, 0x08, 0xf1, 0x00, 0x3c, +0x69, 0x74, 0x73, 0x5a, 0x00, 0xf4, 0x0e, 0x2e, 0x00, 0x00, +0x00, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, +0x72, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, +0x65, 0x00, 0x67, 0x6f, 0x65, 0x73, 0x4a, 0x00, 0xf0, 0x18, +0x4a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x00, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x6d, 0x61, 0x67, 0x61, +0x7a, 0x69, 0x6e, 0x65, 0x00, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, +0x69, 0x00, 0x5b, 0x33, 0x5d, 0x3b, 0x00, 0x49, 0x27, 0x7e, +0x01, 0xf2, 0x14, 0x6c, 0x73, 0x6f, 0x00, 0x73, 0x65, 0x65, +0x6e, 0x00, 0x61, 0x00, 0x50, 0x61, 0x6c, 0x6d, 0x00, 0x69, +0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x00, 0x61, 0x74, 0x00, 0x50, 0x44, 0x00, +0xfa, 0x03, 0x50, 0x61, 0x6c, 0x61, 0x63, 0x65, 0x00, 0x5b, +0x34, 0x5d, 0x2e, 0x00, 0x55, 0x6e, 0x6c, 0x69, 0x6b, 0x65, +0x1a, 0x00, 0x2b, 0x27, 0x73, 0x3c, 0x00, 0x91, 0x2c, 0x00, +0x6d, 0x79, 0x00, 0x76, 0x65, 0x72, 0x73, 0x48, 0x00, 0xf1, +0x0e, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, +0x6c, 0x6c, 0x79, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, +0x74, 0x65, 0x73, 0x00, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, +0x99, 0x01, 0x01, 0x8a, 0x01, 0x31, 0x61, 0x6e, 0x79, 0x86, +0x01, 0x50, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x65, 0x00, 0x60, +0x2e, 0x00, 0x54, 0x68, 0x65, 0x00, 0x27, 0x01, 0x30, 0x69, +0x74, 0x79, 0x22, 0x00, 0x03, 0xd3, 0x00, 0x61, 0x64, 0x65, +0x73, 0x69, 0x67, 0x6e, 0xe6, 0x01, 0x81, 0x68, 0x65, 0x72, +0x65, 0x66, 0x6f, 0x72, 0x65, 0x16, 0x02, 0xd0, 0x71, 0x75, +0x69, 0x74, 0x65, 0x00, 0x61, 0x73, 0x00, 0x67, 0x6f, 0x6f, +0x64, 0x08, 0x00, 0xc3, 0x68, 0x61, 0x6e, 0x64, 0x2d, 0x63, +0x72, 0x61, 0x66, 0x74, 0x65, 0x64, 0x3d, 0x00, 0xc0, 0x73, +0x00, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x62, 0x65, 0x2c, +0x00, 0x4e, 0x02, 0x21, 0x6f, 0x6e, 0x36, 0x01, 0x21, 0x70, +0x6c, 0x03, 0x02, 0x12, 0x64, 0x7d, 0x00, 0x50, 0x67, 0x65, +0x74, 0x00, 0x61, 0x86, 0x01, 0xf7, 0x02, 0x65, 0x78, 0x68, +0x61, 0x75, 0x73, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x00, 0x73, +0x75, 0x70, 0x70, 0x6c, 0x87, 0x00, 0x70, 0x73, 0x00, 0x74, +0x61, 0x69, 0x6c, 0x6f, 0x9f, 0x01, 0x40, 0x74, 0x6f, 0x00, +0x79, 0x7d, 0x02, 0xc1, 0x6f, 0x77, 0x6e, 0x00, 0x73, 0x70, +0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x08, 0x01, 0x00, 0xb2, +0x01, 0xf1, 0x02, 0x5b, 0x33, 0x5d, 0x00, 0x68, 0x74, 0x74, +0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, +0x88, 0x01, 0xa3, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, +0x65, 0x6e, 0x2f, 0x4e, 0x00, 0x90, 0x2f, 0x73, 0x68, 0x69, +0x6b, 0x61, 0x6b, 0x75, 0x2f, 0x33, 0x00, 0x17, 0x34, 0x33, +0x00, 0xe0, 0x65, 0x62, 0x2e, 0x61, 0x72, 0x63, 0x68, 0x69, +0x76, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x10, 0x00, 0xf0, 0x01, +0x2f, 0x32, 0x30, 0x30, 0x34, 0x31, 0x30, 0x32, 0x34, 0x30, +0x30, 0x31, 0x34, 0x35, 0x39, 0x2f, 0x2b, 0x00, 0x03, 0x5d, +0x00, 0x02, 0x4d, 0x00, 0x30, 0x2e, 0x67, 0x72, 0x5d, 0x00, +0x02, 0x0d, 0x00, 0x22, 0x2f, 0x73, 0x58, 0x00, 0xf8, 0x09, +0x70, 0x61, 0x6c, 0x6d, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, +0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x2e, 0x65, 0x6e, 0x00, 0x00, +0x00, 0x38, 0x2e, 0x31, 0xb3, 0x03, 0x00, 0xe0, 0x02, 0x95, +0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x5f, +0x02, 0x92, 0x69, 0x73, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x65, +0x64, 0x9e, 0x03, 0x00, 0x30, 0x01, 0xf0, 0x05, 0x6d, 0x6f, +0x75, 0x73, 0x65, 0x00, 0x6f, 0x72, 0x00, 0x63, 0x75, 0x72, +0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0xed, 0x00, +0xa1, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0xcf, 0x01, 0x41, 0x65, 0x64, 0x67, 0x65, 0x99, 0x02, +0x21, 0x6f, 0x67, 0xf6, 0x02, 0x01, 0x70, 0x01, 0x70, 0x6f, +0x72, 0x00, 0x6f, 0x66, 0x66, 0x2c, 0x08, 0x00, 0x18, 0x6c, +0x2f, 0x00, 0x60, 0x64, 0x00, 0x64, 0x72, 0x61, 0x67, 0x2f, +0x00, 0x40, 0x64, 0x72, 0x61, 0x77, 0x81, 0x01, 0x67, 0x65, +0x6e, 0x74, 0x69, 0x72, 0x65, 0x37, 0x03, 0x10, 0x28, 0x34, +0x00, 0x44, 0x69, 0x6e, 0x65, 0x29, 0xb8, 0x01, 0x03, 0xd6, +0x03, 0x01, 0x88, 0x03, 0xc2, 0x67, 0x6f, 0x00, 0x28, 0x72, +0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x7e, 0x00, 0x40, +0x78, 0x69, 0x73, 0x74, 0x0d, 0x00, 0x00, 0x87, 0x00, 0x11, +0x73, 0xbd, 0x00, 0x22, 0x69, 0x6e, 0xdd, 0x03, 0x05, 0x53, +0x00, 0x73, 0x29, 0x2e, 0x00, 0x52, 0x69, 0x67, 0x68, 0x86, +0x00, 0x02, 0x3a, 0x00, 0x02, 0x89, 0x00, 0x10, 0x67, 0x0d, +0x00, 0x40, 0x77, 0x69, 0x6c, 0x6c, 0x6e, 0x04, 0x21, 0x6f, +0x77, 0x19, 0x02, 0x72, 0x74, 0x6f, 0x00, 0x65, 0x72, 0x61, +0x73, 0x52, 0x04, 0x00, 0x2d, 0x01, 0x32, 0x65, 0x6e, 0x74, +0xbc, 0x02, 0x07, 0xa5, 0x00, 0x00, 0x68, 0x00, 0x91, 0x6f, +0x75, 0x74, 0x00, 0x61, 0x66, 0x66, 0x65, 0x63, 0x80, 0x00, +0x00, 0xcc, 0x03, 0x01, 0x84, 0x00, 0x00, 0x23, 0x01, 0xf4, +0x01, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, +0x76, 0x65, 0x6c, 0x79, 0x2c, 0x00, 0x75, 0x4e, 0x00, 0x06, +0x49, 0x01, 0x00, 0x67, 0x00, 0x42, 0x6d, 0x6f, 0x76, 0x65, +0x9a, 0x02, 0x31, 0x6f, 0x73, 0x69, 0x8f, 0x03, 0x30, 0x69, +0x6e, 0x64, 0x56, 0x02, 0x91, 0x6f, 0x72, 0x00, 0x61, 0x72, +0x6f, 0x75, 0x6e, 0x64, 0x1e, 0x00, 0xc0, 0x62, 0x6f, 0x61, +0x72, 0x64, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x6a, +0x00, 0x20, 0x74, 0x68, 0x2f, 0x01, 0x40, 0x74, 0x75, 0x72, +0x6e, 0x4a, 0x00, 0x00, 0x0f, 0x00, 0x12, 0x6e, 0xbf, 0x00, +0x14, 0x73, 0xc0, 0x00, 0x0f, 0x70, 0x00, 0x04, 0x01, 0x7b, +0x01, 0x08, 0xc6, 0x00, 0x00, 0xc2, 0x00, 0x42, 0x66, 0x72, +0x6f, 0x6d, 0x30, 0x01, 0x04, 0x86, 0x00, 0x02, 0xdd, 0x04, +0x1f, 0x70, 0x6f, 0x00, 0x04, 0x80, 0x61, 0x67, 0x61, 0x69, +0x6e, 0x00, 0x63, 0x6f, 0x0c, 0x04, 0x21, 0x74, 0x65, 0x9f, +0x03, 0x06, 0x52, 0x00, 0x35, 0x2e, 0x00, 0x55, 0x34, 0x00, +0x20, 0x73, 0x70, 0x50, 0x04, 0xa1, 0x62, 0x61, 0x72, 0x00, +0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x04, 0x06, 0x0c, 0x4d, +0x00, 0x09, 0xb7, 0x00, 0x0f, 0x77, 0x01, 0x2a, 0x10, 0x2c, +0x0d, 0x04, 0x57, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x2b, 0x01, +0xf1, 0x01, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x00, 0x63, +0x61, 0x6e, 0x63, 0x65, 0x6c, 0x73, 0x00, 0x61, 0x03, 0x01, +0x00, 0xa1, 0x01, 0x11, 0x57, 0x35, 0x01, 0x08, 0x0b, 0x01, +0x13, 0x66, 0x79, 0x00, 0x10, 0x72, 0x14, 0x00, 0x02, 0xa4, +0x04, 0x25, 0x69, 0x73, 0xe8, 0x00, 0x20, 0x64, 0x2c, 0xd9, +0x02, 0x01, 0x2a, 0x02, 0x90, 0x62, 0x65, 0x00, 0x73, 0x68, +0x61, 0x64, 0x65, 0x64, 0x48, 0x00, 0x42, 0x28, 0x41, 0x6c, +0x6c, 0x04, 0x06, 0x10, 0x63, 0x3b, 0x01, 0x10, 0x73, 0xb8, +0x04, 0x61, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0xd1, 0x06, +0x21, 0x65, 0x63, 0xd7, 0x01, 0x30, 0x32, 0x2e, 0x31, 0x25, +0x06, 0x02, 0x8e, 0x05, 0xb1, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x9d, 0x03, 0x18, 0x32, +0x9d, 0x03, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x9f, 0x03, 0x01, 0xe5, 0x05, 0x05, 0x14, 0x00, +0x02, 0x45, 0x00, 0x04, 0x40, 0x00, 0x04, 0xbb, 0x01, 0xf1, +0x01, 0x65, 0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x73, 0x00, 0x03, +0x3c, 0x03, 0xb1, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x75, 0xf7, 0x00, 0x80, 0x69, 0x64, 0x74, +0x68, 0x2c, 0x00, 0x48, 0x65, 0x0f, 0x03, 0x61, 0x00, 0x00, +0x00, 0x53, 0x69, 0x7a, 0xfb, 0x00, 0x00, 0x63, 0x03, 0x11, +0x2c, 0xb2, 0x00, 0x04, 0x69, 0x07, 0x70, 0x00, 0x00, 0x45, +0x78, 0x70, 0x61, 0x6e, 0xdd, 0x05, 0x40, 0x20, 0x66, 0x61, +0x63, 0x93, 0x02, 0x03, 0x2f, 0x04, 0x10, 0x69, 0x48, 0x01, +0x91, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, +0xa6, 0x06, 0x00, 0x0c, 0x00, 0x14, 0x67, 0xf8, 0x01, 0x35, +0x74, 0x79, 0x70, 0x54, 0x00, 0x15, 0x73, 0x0b, 0x06, 0x42, +0x64, 0x00, 0x62, 0x79, 0xec, 0x02, 0x90, 0x72, 0x6f, 0x67, +0x72, 0x61, 0x6d, 0x2e, 0x00, 0x53, 0xee, 0x07, 0x60, 0x70, +0x65, 0x6f, 0x70, 0x6c, 0x65, 0x6d, 0x02, 0x34, 0x66, 0x65, +0x72, 0x2c, 0x08, 0x03, 0x82, 0x07, 0x01, 0xa9, 0x03, 0x97, +0x00, 0x66, 0x65, 0x77, 0x00, 0x6c, 0x61, 0x72, 0x67, 0x66, +0x02, 0x01, 0xcd, 0x02, 0x00, 0x0e, 0x04, 0x07, 0x29, 0x00, +0x11, 0x6d, 0x5a, 0x06, 0x40, 0x6d, 0x61, 0x6c, 0x6c, 0x1a, +0x00, 0x10, 0x73, 0x5f, 0x00, 0x01, 0x57, 0x02, 0x40, 0x63, +0x61, 0x6e, 0x00, 0x2f, 0x08, 0x19, 0x52, 0x3d, 0x00, 0x30, +0x65, 0x73, 0x73, 0x78, 0x04, 0x09, 0xad, 0x06, 0x22, 0x00, +0x61, 0x40, 0x00, 0x22, 0x65, 0x72, 0x86, 0x00, 0x32, 0x74, +0x68, 0x61, 0x44, 0x01, 0x05, 0xb0, 0x06, 0x03, 0xf7, 0x05, +0x22, 0x65, 0x64, 0x22, 0x03, 0x01, 0x79, 0x03, 0x00, 0x4d, +0x00, 0x00, 0x29, 0x01, 0x10, 0x64, 0x20, 0x02, 0x60, 0x62, +0x79, 0x00, 0x61, 0x64, 0x64, 0x8f, 0x00, 0x10, 0x72, 0xd7, +0x02, 0x20, 0x61, 0x6e, 0xcc, 0x00, 0x41, 0x6c, 0x75, 0x6d, +0x6e, 0x51, 0x01, 0x00, 0xe9, 0x06, 0x72, 0x64, 0x65, 0x66, +0x61, 0x75, 0x6c, 0x74, 0x34, 0x00, 0x01, 0x3a, 0x07, 0x03, +0x5d, 0x01, 0xd2, 0x6f, 0x66, 0x00, 0x7a, 0x65, 0x72, 0x6f, +0x00, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x90, 0x03, 0x07, 0xb3, +0x00, 0x01, 0x79, 0x02, 0x10, 0x73, 0x80, 0x07, 0x09, 0xb0, +0x00, 0x04, 0x5a, 0x09, 0x09, 0xa6, 0x00, 0x00, 0xee, 0x00, +0x42, 0x66, 0x6f, 0x72, 0x2c, 0xe5, 0x04, 0x10, 0x6f, 0x36, +0x07, 0x10, 0x68, 0x93, 0x00, 0x30, 0x66, 0x75, 0x72, 0x4b, +0x07, 0x42, 0x2e, 0x00, 0x49, 0x66, 0xce, 0x00, 0x02, 0x01, +0x07, 0x0f, 0x8a, 0x00, 0x01, 0x91, 0x28, 0x73, 0x61, 0x79, +0x29, 0x00, 0x30, 0x2e, 0x35, 0xf6, 0x02, 0x07, 0x93, 0x00, +0x01, 0xe2, 0x08, 0x42, 0x64, 0x69, 0x6d, 0x65, 0x32, 0x00, +0x26, 0x6f, 0x66, 0xa1, 0x05, 0x04, 0x1c, 0x03, 0x02, 0x0e, +0x01, 0x02, 0x31, 0x07, 0x43, 0x68, 0x61, 0x6c, 0x66, 0x31, +0x04, 0x70, 0x61, 0x73, 0x00, 0x62, 0x69, 0x67, 0x00, 0xa7, +0x07, 0x14, 0x72, 0xc3, 0x00, 0x01, 0x3d, 0x07, 0x60, 0x49, +0x6e, 0x00, 0x6f, 0x74, 0x68, 0x18, 0x09, 0x51, 0x6f, 0x72, +0x64, 0x73, 0x2c, 0x51, 0x00, 0x30, 0x69, 0x6e, 0x69, 0x9d, +0x01, 0x0a, 0x59, 0x00, 0x36, 0x32, 0x2f, 0x33, 0xe9, 0x00, +0x2b, 0x69, 0x6e, 0x8c, 0x00, 0x02, 0xef, 0x00, 0x0f, 0x85, +0x00, 0x01, 0x00, 0x22, 0x04, 0x21, 0x66, 0x75, 0x40, 0x01, +0x17, 0x7a, 0x42, 0x04, 0x24, 0x64, 0x64, 0x43, 0x06, 0x28, +0x6d, 0x6f, 0x80, 0x06, 0x01, 0xab, 0x01, 0x31, 0x53, 0x65, +0x74, 0x5e, 0x04, 0x0f, 0x20, 0x01, 0x04, 0x03, 0x9d, 0x05, +0x82, 0x30, 0x2e, 0x35, 0x00, 0x74, 0x65, 0x6e, 0x64, 0xcd, +0x05, 0x23, 0x61, 0x6b, 0x85, 0x0a, 0x00, 0x4f, 0x07, 0x01, +0x54, 0x00, 0x92, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, +0x6c, 0x74, 0x9d, 0x00, 0x01, 0xfe, 0x03, 0x50, 0x28, 0x69, +0x6e, 0x00, 0x6d, 0xb7, 0x06, 0xf0, 0x01, 0x70, 0x65, 0x72, +0x69, 0x65, 0x6e, 0x63, 0x65, 0x29, 0x00, 0x72, 0x65, 0x77, +0x61, 0x72, 0x64, 0x56, 0x03, 0x30, 0x6c, 0x65, 0x73, 0x42, +0x04, 0x30, 0x64, 0x75, 0x63, 0x3a, 0x06, 0x01, 0x35, 0x00, +0x01, 0x49, 0x00, 0x51, 0x69, 0x6e, 0x74, 0x75, 0x69, 0x13, +0x00, 0x00, 0xa4, 0x07, 0x00, 0x99, 0x00, 0x59, 0x73, 0x74, +0x79, 0x6c, 0x65, 0xcb, 0x01, 0xd0, 0x69, 0x74, 0x00, 0x74, +0x6f, 0x6f, 0x00, 0x68, 0x69, 0x67, 0x68, 0x2c, 0x00, 0xe4, +0x00, 0x02, 0x08, 0x00, 0x03, 0x90, 0x00, 0x03, 0x3c, 0x02, +0x30, 0x63, 0x61, 0x6e, 0x45, 0x09, 0x05, 0x43, 0x02, 0x01, +0x5e, 0x00, 0x01, 0xe9, 0x02, 0x02, 0x69, 0x03, 0x0a, 0x63, +0x03, 0x51, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x00, 0x03, +0xa5, 0x07, 0x02, 0x27, 0x04, 0x03, 0xfc, 0x02, 0x02, 0x59, +0x00, 0x50, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x2f, 0x00, 0x61, +0x72, 0x69, 0x76, 0x69, 0x61, 0x6c, 0x39, 0x04, 0xf1, 0x02, +0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, +0x75, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x92, 0x04, 0x60, +0x00, 0x00, 0x4e, 0x6f, 0x72, 0x6d, 0x73, 0x03, 0x1d, 0x2c, +0xdb, 0x02, 0x01, 0x3d, 0x01, 0x00, 0x36, 0x00, 0x02, 0x67, +0x02, 0x01, 0x28, 0x04, 0x03, 0x81, 0x09, 0x21, 0x69, 0x74, +0x8b, 0x06, 0x01, 0x0e, 0x06, 0x01, 0x51, 0x0c, 0x23, 0x6f, +0x6e, 0x94, 0x0b, 0x04, 0x5a, 0x00, 0x13, 0x2e, 0xa9, 0x0a, +0x12, 0x73, 0xbb, 0x08, 0x61, 0x61, 0x6d, 0x62, 0x69, 0x67, +0x75, 0xef, 0x0b, 0x13, 0x65, 0x95, 0x05, 0x00, 0x05, 0x04, +0x1c, 0x62, 0x95, 0x01, 0x06, 0x5f, 0x01, 0xd5, 0x73, 0x75, +0x62, 0x74, 0x6c, 0x65, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x69, +0x66, 0x9a, 0x0a, 0x05, 0x3f, 0x04, 0x01, 0xae, 0x06, 0x32, +0x6f, 0x66, 0x66, 0x8d, 0x0b, 0x62, 0x66, 0x65, 0x61, 0x74, +0x75, 0x72, 0x9d, 0x01, 0x40, 0x72, 0x69, 0x73, 0x6b, 0x95, +0x00, 0x01, 0x2b, 0x02, 0x05, 0x77, 0x00, 0x03, 0xba, 0x00, +0xb2, 0x2e, 0x00, 0x41, 0x6c, 0x73, 0x6f, 0x2c, 0x00, 0x66, +0x69, 0x6e, 0x6b, 0x02, 0x24, 0x6c, 0x6c, 0xed, 0x07, 0x12, +0x73, 0x6d, 0x0a, 0x03, 0xc0, 0x00, 0x05, 0xa0, 0x00, 0x21, +0x61, 0x6e, 0x97, 0x02, 0x00, 0x14, 0x00, 0x20, 0x61, 0x6c, +0x55, 0x05, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x63, +0x05, 0x01, 0x1c, 0x00, 0x10, 0x76, 0xc8, 0x06, 0x12, 0x64, +0xa9, 0x09, 0x61, 0x72, 0x2e, 0x00, 0x54, 0x75, 0x72, 0xfc, +0x04, 0x05, 0x9c, 0x00, 0x03, 0xfc, 0x05, 0x01, 0xf4, 0x04, +0x01, 0xf9, 0x0b, 0x74, 0x70, 0x65, 0x65, 0x64, 0x00, 0x75, +0x70, 0x55, 0x0b, 0x03, 0xf8, 0x01, 0x50, 0x69, 0x6f, 0x6e, +0x2e, 0x00, }; -const unsigned short help_text_len = 3535; -const unsigned short help_text_words = 605; +const unsigned short help_text_len = 3536; +const unsigned short help_text_words = 603; const char quick_help_text[] = "Divide the grid into rectangles with areas equal to the numbers."; diff --git a/apps/plugins/puzzles/help/samegame.c b/apps/plugins/puzzles/help/samegame.c index 5efe0ff4c3..87f7b2b3b9 100644 --- a/apps/plugins/puzzles/help/samegame.c +++ b/apps/plugins/puzzles/help/samegame.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,185 +6,186 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 116, TEXT_CENTER | C_RED }, - { 229, TEXT_CENTER | C_RED }, - { 246, TEXT_UNDERLINE }, + { 117, TEXT_CENTER | C_RED }, + { 230, TEXT_CENTER | C_RED }, { 247, TEXT_UNDERLINE }, - { 257, TEXT_UNDERLINE }, - { 292, TEXT_UNDERLINE }, - { 342, TEXT_UNDERLINE }, - { 414, TEXT_UNDERLINE }, + { 248, TEXT_UNDERLINE }, + { 258, TEXT_UNDERLINE }, + { 293, TEXT_UNDERLINE }, + { 343, TEXT_UNDERLINE }, + { 415, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2470 comp 1634 ratio 0.661538 level 10 saved 836 */ +/* orig 2492 comp 1641 ratio 0.658507 level 10 saved 851 */ const char help_text[] = { 0xf0, 0x03, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x33, 0x3a, 0x20, 0x53, 0x61, 0x6d, 0x65, 0x20, 0x47, -0x05, 0x00, 0xf4, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, -0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, -0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x63, 0x6f, 0x6c, 0x6f, -0x75, 0x72, 0x65, 0x64, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, -0x65, 0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, -0x79, 0x2b, 0x00, 0xf0, 0x1c, 0x74, 0x6f, 0x00, 0x63, 0x6c, -0x65, 0x61, 0x72, 0x00, 0x62, 0x79, 0x00, 0x68, 0x69, 0x67, -0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x00, -0x63, 0x6f, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, -0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x00, -0xdc, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x74, 0x68, 0x61, 0x6e, -0x00, 0x6f, 0x6e, 0x65, 0x5e, 0x00, 0xc1, 0x3b, 0x00, 0x74, -0x68, 0x65, 0x00, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x0b, -0x00, 0x02, 0x39, 0x00, 0x02, 0x6d, 0x00, 0x04, 0x5c, 0x00, -0x11, 0x2c, 0x1a, 0x00, 0x01, 0x48, 0x00, 0x61, 0x70, 0x6f, -0x69, 0x6e, 0x74, 0x73, 0x1f, 0x00, 0x81, 0x67, 0x65, 0x74, -0x00, 0x28, 0x61, 0x6e, 0x64, 0x1d, 0x00, 0x61, 0x66, 0x61, -0x73, 0x74, 0x65, 0x72, 0x18, 0x00, 0x02, 0x9c, 0x00, 0x00, -0x15, 0x00, 0xcb, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x29, 0x2e, -0x00, 0x00, 0x00, 0x49, 0x66, 0x1b, 0x00, 0x01, 0xed, 0x00, -0x00, 0x13, 0x00, 0x44, 0x77, 0x69, 0x6e, 0x2e, 0x1f, 0x00, -0xf0, 0x01, 0x65, 0x6e, 0x64, 0x00, 0x75, 0x70, 0x00, 0x77, -0x69, 0x74, 0x68, 0x00, 0x6e, 0x6f, 0x74, 0x68, 0xd4, 0x00, -0xa4, 0x62, 0x75, 0x74, 0x00, 0x73, 0x69, 0x6e, 0x67, 0x6c, -0x65, 0x10, 0x01, 0x61, 0x00, 0x28, 0x69, 0x2e, 0x65, 0x2e, -0x94, 0x00, 0x11, 0x72, 0x64, 0x00, 0x32, 0x00, 0x6e, 0x6f, -0x9d, 0x00, 0x95, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x61, 0x62, -0x6c, 0x65, 0xff, 0x00, 0x51, 0x6c, 0x65, 0x66, 0x74, 0x29, -0x5c, 0x00, 0x40, 0x6c, 0x6f, 0x73, 0x65, 0x8a, 0x00, 0x50, -0x52, 0x65, 0x6d, 0x6f, 0x76, 0x59, 0x00, 0x14, 0x61, 0xeb, -0x00, 0x63, 0x63, 0x61, 0x75, 0x73, 0x65, 0x73, 0xfd, 0x00, -0x20, 0x73, 0x74, 0x33, 0x01, 0x05, 0xa2, 0x00, 0xf0, 0x06, -0x74, 0x6f, 0x00, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, -0x00, 0x75, 0x70, 0x3a, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, -0x73, 0x4d, 0x01, 0x11, 0x74, 0x79, 0x00, 0xf3, 0x13, 0x73, -0x75, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x00, 0x77, -0x69, 0x6c, 0x6c, 0x00, 0x66, 0x61, 0x6c, 0x6c, 0x00, 0x64, -0x6f, 0x77, 0x6e, 0x00, 0x28, 0x66, 0x69, 0x72, 0x73, 0x74, -0x29, 0x2c, 0x00, 0x20, 0x01, 0x70, 0x6e, 0x00, 0x65, 0x6d, -0x70, 0x74, 0x79, 0x7e, 0x01, 0x41, 0x75, 0x6d, 0x6e, 0x73, -0x3d, 0x00, 0xb2, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, -0x66, 0x72, 0x6f, 0x6d, 0x7d, 0x00, 0x00, 0x6b, 0x01, 0x00, -0xa3, 0x00, 0x00, 0x21, 0x02, 0x20, 0x00, 0x47, 0x05, 0x00, -0x31, 0x77, 0x61, 0x73, 0xd5, 0x01, 0x61, 0x72, 0x69, 0x62, -0x75, 0x74, 0x65, 0x8f, 0x00, 0x40, 0x74, 0x68, 0x69, 0x73, -0x47, 0x00, 0x40, 0x6c, 0x65, 0x63, 0x74, 0xbe, 0x00, 0xf0, -0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, -0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x40, 0x00, 0x47, 0x31, -0x33, 0x2e, 0x31, 0x66, 0x02, 0x01, 0x41, 0x00, 0x30, 0x6f, -0x6c, 0x73, 0x6f, 0x02, 0x10, 0x54, 0x3e, 0x00, 0x10, 0x67, -0x5b, 0x00, 0xd2, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, -0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x73, 0x01, 0x43, 0x65, -0x69, 0x74, 0x68, 0x06, 0x02, 0xb3, 0x6b, 0x65, 0x79, 0x62, -0x6f, 0x61, 0x72, 0x64, 0x00, 0x6f, 0x72, 0xfc, 0x01, 0x37, -0x75, 0x73, 0x65, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x11, 0x2d, -0x6f, 0x01, 0x80, 0x00, 0x61, 0x6e, 0x00, 0x75, 0x6e, 0x73, -0x65, 0x90, 0x00, 0x23, 0x65, 0x64, 0x54, 0x01, 0x90, 0x2c, -0x00, 0x69, 0x74, 0x00, 0x62, 0x65, 0x63, 0x6f, 0x99, 0x00, -0x05, 0x1c, 0x00, 0x92, 0x28, 0x70, 0x6f, 0x73, 0x73, 0x69, -0x62, 0x6c, 0x79, 0x08, 0x02, 0x00, 0x85, 0x01, 0x00, 0x5c, -0x00, 0x73, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x28, -0x00, 0x4f, 0x69, 0x6f, 0x6e, 0x29, 0x69, 0x00, 0x03, 0x00, -0x2c, 0x00, 0x0f, 0x68, 0x00, 0x01, 0x01, 0x7b, 0x01, 0x10, -0x62, 0xbd, 0x01, 0x56, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x94, -0x02, 0x0d, 0xce, 0x01, 0x03, 0xcb, 0x01, 0xd8, 0x64, 0x00, -0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, -0x79, 0x6d, 0x00, 0x01, 0x82, 0x01, 0x0f, 0x6e, 0x00, 0x14, -0x06, 0xf4, 0x00, 0x11, 0x2e, 0x58, 0x01, 0x01, 0xc8, 0x00, -0x30, 0x73, 0x6f, 0x72, 0x3b, 0x01, 0x41, 0x73, 0x00, 0x6d, -0x6f, 0xd3, 0x03, 0x03, 0x13, 0x00, 0x65, 0x61, 0x72, 0x6f, -0x75, 0x6e, 0x64, 0x88, 0x00, 0x74, 0x2e, 0x00, 0x50, 0x72, -0x65, 0x73, 0x73, 0x00, 0x01, 0x50, 0x53, 0x70, 0x61, 0x63, -0x65, 0x69, 0x01, 0x43, 0x45, 0x6e, 0x74, 0x65, 0x40, 0x00, -0x40, 0x77, 0x68, 0x69, 0x6c, 0xb5, 0x03, 0x05, 0x56, 0x00, -0x5f, 0x69, 0x73, 0x00, 0x69, 0x6e, 0x6c, 0x01, 0x02, 0x03, -0xa6, 0x00, 0x74, 0x73, 0x00, 0x69, 0x74, 0x3b, 0x00, 0x70, -0x59, 0x00, 0x0b, 0x55, 0x00, 0x53, 0x61, 0x67, 0x61, 0x69, -0x6e, 0x22, 0x01, 0x10, 0x73, 0xc7, 0x00, 0x71, 0x61, 0x73, -0x00, 0x61, 0x62, 0x6f, 0x76, 0xd4, 0x01, 0x42, 0x28, 0x41, -0x6c, 0x6c, 0xb0, 0x03, 0x21, 0x63, 0x74, 0x36, 0x03, 0x70, -0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x29, 0x01, 0x00, -0x5f, 0x00, 0x02, 0x69, 0x02, 0x31, 0x32, 0x2e, 0x31, 0xb7, -0x02, 0xa0, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, -0x69, 0x6c, 0x6a, 0x03, 0x22, 0x2e, 0x29, 0x71, 0x02, 0x17, -0x32, 0x71, 0x02, 0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, -0x74, 0x65, 0x72, 0x73, 0x02, 0x46, 0x65, 0x73, 0x65, 0x00, -0x14, 0x00, 0x02, 0x45, 0x00, 0x04, 0x40, 0x00, 0x06, 0xff, -0x02, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, -0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x73, 0x00, 0x22, 0x6f, -0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0xaf, 0x00, 0x90, 0x57, 0x69, 0x64, -0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xae, 0x01, 0x00, 0x2f, -0x03, 0x30, 0x69, 0x7a, 0x65, 0xe7, 0x01, 0x01, 0xe3, 0x01, -0x24, 0x69, 0x6e, 0x27, 0x04, 0x00, 0x2b, 0x00, 0x72, 0x4e, -0x6f, 0x2e, 0x20, 0x6f, 0x66, 0x20, 0xf4, 0x04, 0x10, 0x73, -0x11, 0x00, 0x50, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x00, -0x51, 0x64, 0x69, 0x66, 0x66, 0x65, 0x78, 0x02, 0x04, 0x1e, -0x00, 0x22, 0x75, 0x73, 0x62, 0x03, 0x00, 0x98, 0x03, 0x05, -0xac, 0x01, 0x16, 0x3b, 0xfb, 0x04, 0x03, 0x28, 0x00, 0x12, -0x2c, 0xf0, 0x04, 0x42, 0x65, 0x77, 0x65, 0x72, 0x38, 0x05, -0x08, 0x6c, 0x05, 0x02, 0x24, 0x00, 0x03, 0xf6, 0x03, 0x26, -0x75, 0x73, 0x3d, 0x00, 0x00, 0x6f, 0x00, 0x50, 0x69, 0x63, -0x75, 0x6c, 0x74, 0x7d, 0x01, 0x21, 0x69, 0x73, 0x59, 0x04, -0xbb, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, -0x6c, 0x79, 0x1a, 0x05, 0x01, 0x06, 0x04, 0x20, 0x63, 0x6f, -0x23, 0x03, 0xb3, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, -0x00, 0x00, 0x00, 0x43, 0xc8, 0x03, 0x01, 0x26, 0x00, 0xf2, -0x02, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x00, 0x6d, -0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0xbf, 0x00, -0x52, 0x66, 0x6f, 0x72, 0x00, 0x73, 0x39, 0x00, 0x30, 0x2e, -0x00, 0x57, 0xd5, 0x03, 0x00, 0x2d, 0x00, 0x40, 0x64, 0x65, -0x66, 0x61, 0x7b, 0x00, 0x02, 0x4b, 0x00, 0xf8, 0x02, 0x2c, -0x00, 0x60, 0x28, 0x6e, 0x2d, 0x32, 0x29, 0x5e, 0x32, 0x27, -0x2c, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0xc1, 0x00, 0x46, 0x74, -0x68, 0x72, 0x65, 0x6a, 0x05, 0x22, 0x6f, 0x72, 0xbe, 0x00, -0x01, 0xf5, 0x02, 0x20, 0x73, 0x63, 0x0b, 0x00, 0x34, 0x61, -0x6e, 0x79, 0x05, 0x06, 0x00, 0x05, 0x05, 0x27, 0x6c, 0x6c, -0x68, 0x00, 0xb1, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, -0x74, 0x69, 0x76, 0x65, 0x64, 0x00, 0x10, 0x31, 0x64, 0x00, -0x05, 0x76, 0x00, 0x08, 0x66, 0x00, 0x25, 0x77, 0x6f, 0x64, -0x00, 0x03, 0x57, 0x00, 0x02, 0x55, 0x00, 0x52, 0x00, 0x65, -0x61, 0x63, 0x68, 0x36, 0x05, 0x03, 0x94, 0x06, 0x04, 0x36, -0x00, 0x02, 0x27, 0x00, 0x31, 0x72, 0x65, 0x6c, 0x5f, 0x00, -0x28, 0x6c, 0x79, 0x8f, 0x06, 0x00, 0x2f, 0x01, 0xf2, 0x02, -0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6c, -0x75, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0xd7, 0x03, 0x01, -0x2f, 0x05, 0x03, 0x4f, 0x02, 0x00, 0x77, 0x01, 0x30, 0x69, -0x63, 0x6b, 0x23, 0x04, 0x09, 0x16, 0x01, 0xd0, 0x74, 0x61, -0x74, 0x65, 0x29, 0x2c, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, -0x61, 0x59, 0x03, 0x00, 0x83, 0x01, 0x15, 0x73, 0xea, 0x03, -0x82, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x1e, -0x02, 0x02, 0xad, 0x07, 0x71, 0x74, 0x00, 0x6c, 0x65, 0x61, -0x73, 0x74, 0x52, 0x07, 0x00, 0x73, 0x00, 0x00, 0x60, 0x00, -0x07, 0x49, 0x04, 0x60, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x69, -0x7d, 0x04, 0x12, 0x66, 0x2f, 0x02, 0x01, 0x73, 0x05, 0x03, -0x61, 0x00, 0x22, 0x6f, 0x72, 0x5b, 0x00, 0x70, 0x6e, 0x6f, -0x74, 0x00, 0x74, 0x72, 0x79, 0x55, 0x00, 0x05, 0x63, 0x00, -0x01, 0x4d, 0x00, 0x00, 0x17, 0x03, 0x01, 0x83, 0x00, 0x14, -0x3b, 0x71, 0x04, 0xd0, 0x2c, 0x00, 0x68, 0x6f, 0x77, 0x65, -0x76, 0x65, 0x72, 0x2c, 0x00, 0x73, 0x74, 0x3c, 0x00, 0x11, -0x65, 0xee, 0x00, 0x02, 0x89, 0x06, 0x06, 0x08, 0x07, 0x05, -0x97, 0x00, 0x16, 0x32, 0xc2, 0x01, 0x11, 0x66, 0x53, 0x01, -0x04, 0x99, 0x02, 0x26, 0x6f, 0x6e, 0x0e, 0x05, 0x02, 0x3b, -0x00, 0x00, 0xff, 0x00, 0x85, 0x72, 0x74, 0x00, 0x28, 0x73, -0x69, 0x6e, 0x63, 0x86, 0x08, 0x02, 0x0f, 0x06, 0x62, 0x78, -0x61, 0x63, 0x74, 0x6c, 0x79, 0xe4, 0x00, 0x01, 0x4f, 0x00, -0x00, 0x4e, 0x00, 0x74, 0x61, 0x00, 0x67, 0x69, 0x76, 0x65, -0x6e, 0x51, 0x00, 0x20, 0x69, 0x73, 0x48, 0x01, 0x40, 0x69, -0x6e, 0x69, 0x74, 0x94, 0x01, 0x23, 0x69, 0x6e, 0xc0, 0x00, -0x41, 0x29, 0x2e, 0x00, 0x47, 0x45, 0x01, 0x06, 0x55, 0x01, -0x01, 0x54, 0x00, 0x08, 0x8f, 0x01, 0x50, 0x64, 0x69, 0x73, -0x61, 0x62, 0x8e, 0x05, 0x31, 0x6d, 0x61, 0x79, 0xe6, 0x06, -0x00, 0xa3, 0x04, 0x01, 0xd6, 0x01, 0x02, 0x57, 0x03, 0x43, -0x61, 0x72, 0x65, 0x61, 0x55, 0x03, 0x05, 0xd7, 0x08, 0x02, -0x76, 0x00, 0x10, 0x2c, 0xe7, 0x00, 0x11, 0x64, 0x40, 0x05, -0xf1, 0x00, 0x6f, 0x00, 0x6f, 0x70, 0x70, 0x6f, 0x72, 0x74, -0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x01, 0x03, 0x00, -0xb8, 0x08, 0x22, 0x65, 0x72, 0x32, 0x02, 0x11, 0x73, 0xc1, -0x03, 0x11, 0x79, 0xef, 0x06, 0x01, 0xba, 0x04, 0x80, 0x74, -0x61, 0x6b, 0x65, 0x00, 0x6c, 0x65, 0x73, 0x0c, 0x02, 0x21, -0x6d, 0x65, 0x7d, 0x01, 0x90, 0x65, 0x6e, 0x65, 0x72, 0x61, -0x74, 0x65, 0x2e, 0x00, +0x05, 0x00, 0x2f, 0x00, 0x2d, 0x01, 0x00, 0x01, 0xf4, 0x20, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, +0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, +0x66, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x65, 0x64, +0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, +0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x79, 0x2b, 0x00, 0xf0, +0x1c, 0x74, 0x6f, 0x00, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x00, +0x62, 0x79, 0x00, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, +0x68, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x63, 0x6f, 0x6e, 0x74, +0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x00, 0x72, 0x65, 0x67, +0x69, 0x6f, 0x6e, 0x73, 0x50, 0x00, 0xdc, 0x6d, 0x6f, 0x72, +0x65, 0x00, 0x74, 0x68, 0x61, 0x6e, 0x00, 0x6f, 0x6e, 0x65, +0x5e, 0x00, 0xc1, 0x3b, 0x00, 0x74, 0x68, 0x65, 0x00, 0x6c, +0x61, 0x72, 0x67, 0x65, 0x72, 0x0b, 0x00, 0x02, 0x39, 0x00, +0x02, 0x6d, 0x00, 0x04, 0x5c, 0x00, 0x11, 0x2c, 0x1a, 0x00, +0x01, 0x48, 0x00, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, +0x1f, 0x00, 0x81, 0x67, 0x65, 0x74, 0x00, 0x28, 0x61, 0x6e, +0x64, 0x1d, 0x00, 0x61, 0x66, 0x61, 0x73, 0x74, 0x65, 0x72, +0x18, 0x00, 0x02, 0x9c, 0x00, 0x00, 0x15, 0x00, 0xcb, 0x61, +0x72, 0x65, 0x6e, 0x61, 0x29, 0x2e, 0x00, 0x00, 0x00, 0x49, +0x66, 0x1b, 0x00, 0x01, 0xed, 0x00, 0x00, 0x13, 0x00, 0x44, +0x77, 0x69, 0x6e, 0x2e, 0x1f, 0x00, 0xf0, 0x01, 0x65, 0x6e, +0x64, 0x00, 0x75, 0x70, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, +0x6e, 0x6f, 0x74, 0x68, 0xd4, 0x00, 0xa4, 0x62, 0x75, 0x74, +0x00, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x10, 0x01, 0x61, +0x00, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x94, 0x00, 0x11, 0x72, +0x64, 0x00, 0x32, 0x00, 0x6e, 0x6f, 0x9d, 0x00, 0x95, 0x63, +0x6c, 0x69, 0x63, 0x6b, 0x61, 0x62, 0x6c, 0x65, 0xff, 0x00, +0x51, 0x6c, 0x65, 0x66, 0x74, 0x29, 0x5c, 0x00, 0x40, 0x6c, +0x6f, 0x73, 0x65, 0x8a, 0x00, 0x50, 0x52, 0x65, 0x6d, 0x6f, +0x76, 0x59, 0x00, 0x14, 0x61, 0xeb, 0x00, 0x63, 0x63, 0x61, +0x75, 0x73, 0x65, 0x73, 0xfd, 0x00, 0x20, 0x73, 0x74, 0x33, +0x01, 0x05, 0xa2, 0x00, 0xf0, 0x06, 0x74, 0x6f, 0x00, 0x73, +0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x00, 0x75, 0x70, 0x3a, +0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4d, 0x01, 0x11, +0x74, 0x79, 0x00, 0xf3, 0x13, 0x73, 0x75, 0x73, 0x70, 0x65, +0x6e, 0x64, 0x65, 0x64, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, +0x66, 0x61, 0x6c, 0x6c, 0x00, 0x64, 0x6f, 0x77, 0x6e, 0x00, +0x28, 0x66, 0x69, 0x72, 0x73, 0x74, 0x29, 0x2c, 0x00, 0x20, +0x01, 0x70, 0x6e, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x7e, +0x01, 0x41, 0x75, 0x6d, 0x6e, 0x73, 0x3d, 0x00, 0xb2, 0x66, +0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x66, 0x72, 0x6f, 0x6d, +0x7d, 0x00, 0x00, 0x6b, 0x01, 0x00, 0xa3, 0x00, 0x00, 0x37, +0x02, 0x20, 0x00, 0x47, 0x05, 0x00, 0x31, 0x77, 0x61, 0x73, +0xd5, 0x01, 0x61, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x8f, +0x00, 0x40, 0x74, 0x68, 0x69, 0x73, 0x47, 0x00, 0x40, 0x6c, +0x65, 0x63, 0x74, 0xbe, 0x00, 0xf0, 0x00, 0x62, 0x79, 0x00, +0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, +0x65, 0x79, 0x40, 0x00, 0x47, 0x31, 0x33, 0x2e, 0x31, 0x7c, +0x02, 0x01, 0x41, 0x00, 0x80, 0x6f, 0x6c, 0x73, 0x20, 0x00, +0x00, 0x00, 0x54, 0x3e, 0x00, 0x10, 0x67, 0x5b, 0x00, 0xd2, +0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x70, 0x6c, 0x61, +0x79, 0x65, 0x64, 0x73, 0x01, 0x43, 0x65, 0x69, 0x74, 0x68, +0x06, 0x02, 0xb3, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, +0x64, 0x00, 0x6f, 0x72, 0xfc, 0x01, 0x37, 0x75, 0x73, 0x65, +0xc9, 0x01, 0x00, 0x58, 0x01, 0x11, 0x2d, 0x6f, 0x01, 0x80, +0x00, 0x61, 0x6e, 0x00, 0x75, 0x6e, 0x73, 0x65, 0x90, 0x00, +0x23, 0x65, 0x64, 0x54, 0x01, 0x90, 0x2c, 0x00, 0x69, 0x74, +0x00, 0x62, 0x65, 0x63, 0x6f, 0x99, 0x00, 0x05, 0x1c, 0x00, +0x92, 0x28, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x79, +0x08, 0x02, 0x00, 0x85, 0x01, 0x00, 0x5c, 0x00, 0x73, 0x63, +0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x28, 0x00, 0x4f, 0x69, +0x6f, 0x6e, 0x29, 0x69, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x0f, +0x68, 0x00, 0x01, 0x01, 0x7b, 0x01, 0x10, 0x62, 0xbd, 0x01, +0x56, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x94, 0x02, 0x0d, 0xce, +0x01, 0x03, 0xcb, 0x01, 0xd8, 0x64, 0x00, 0x69, 0x6d, 0x6d, +0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x6d, 0x00, +0x01, 0x82, 0x01, 0x0f, 0x6e, 0x00, 0x14, 0x06, 0xf4, 0x00, +0x11, 0x2e, 0x58, 0x01, 0x01, 0xc8, 0x00, 0x30, 0x73, 0x6f, +0x72, 0x3b, 0x01, 0x41, 0x73, 0x00, 0x6d, 0x6f, 0xd3, 0x03, +0x03, 0x13, 0x00, 0x65, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, +0x88, 0x00, 0x74, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, +0x00, 0x01, 0x50, 0x53, 0x70, 0x61, 0x63, 0x65, 0x69, 0x01, +0x43, 0x45, 0x6e, 0x74, 0x65, 0x40, 0x00, 0x40, 0x77, 0x68, +0x69, 0x6c, 0xb5, 0x03, 0x05, 0x56, 0x00, 0x5f, 0x69, 0x73, +0x00, 0x69, 0x6e, 0x6c, 0x01, 0x02, 0x03, 0xa6, 0x00, 0x74, +0x73, 0x00, 0x69, 0x74, 0x3b, 0x00, 0x70, 0x59, 0x00, 0x0b, +0x55, 0x00, 0x53, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x22, 0x01, +0x10, 0x73, 0xc7, 0x00, 0x71, 0x61, 0x73, 0x00, 0x61, 0x62, +0x6f, 0x76, 0xd4, 0x01, 0x42, 0x28, 0x41, 0x6c, 0x6c, 0xb0, +0x03, 0x21, 0x63, 0x74, 0x36, 0x03, 0x70, 0x64, 0x65, 0x73, +0x63, 0x72, 0x69, 0x62, 0x29, 0x01, 0x00, 0x5f, 0x00, 0x02, +0x69, 0x02, 0x31, 0x32, 0x2e, 0x31, 0xb7, 0x02, 0xa0, 0x61, +0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x6a, +0x03, 0x22, 0x2e, 0x29, 0x71, 0x02, 0x17, 0x32, 0x71, 0x02, +0x93, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, +0x73, 0x02, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, +0x45, 0x00, 0x04, 0x40, 0x00, 0x06, 0xff, 0x02, 0xe1, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x73, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, +0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, +0x75, 0xaf, 0x00, 0x90, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, +0x00, 0x48, 0x65, 0xae, 0x01, 0x00, 0x2f, 0x03, 0x30, 0x69, +0x7a, 0x65, 0xe7, 0x01, 0x01, 0xe3, 0x01, 0x24, 0x69, 0x6e, +0x27, 0x04, 0x00, 0x2b, 0x00, 0x72, 0x4e, 0x6f, 0x2e, 0x20, +0x6f, 0x66, 0x20, 0xf4, 0x04, 0x10, 0x73, 0x11, 0x00, 0x50, +0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x00, 0x51, 0x64, 0x69, +0x66, 0x66, 0x65, 0x78, 0x02, 0x04, 0x1e, 0x00, 0x22, 0x75, +0x73, 0x62, 0x03, 0x00, 0x98, 0x03, 0x05, 0xac, 0x01, 0x16, +0x3b, 0xfb, 0x04, 0x03, 0x28, 0x00, 0x12, 0x2c, 0xf0, 0x04, +0x42, 0x65, 0x77, 0x65, 0x72, 0x38, 0x05, 0x08, 0x6c, 0x05, +0x02, 0x24, 0x00, 0x03, 0xf6, 0x03, 0x26, 0x75, 0x73, 0x3d, +0x00, 0x00, 0x6f, 0x00, 0x50, 0x69, 0x63, 0x75, 0x6c, 0x74, +0x7d, 0x01, 0x21, 0x69, 0x73, 0x59, 0x04, 0xbb, 0x75, 0x63, +0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x1a, +0x05, 0x01, 0x06, 0x04, 0x20, 0x63, 0x6f, 0x23, 0x03, 0xb3, +0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, +0x43, 0xc8, 0x03, 0x01, 0x26, 0x00, 0xf2, 0x02, 0x70, 0x72, +0x65, 0x63, 0x69, 0x73, 0x65, 0x00, 0x6d, 0x65, 0x63, 0x68, +0x61, 0x6e, 0x69, 0x73, 0x6d, 0xbf, 0x00, 0x52, 0x66, 0x6f, +0x72, 0x00, 0x73, 0x39, 0x00, 0x30, 0x2e, 0x00, 0x57, 0xd5, +0x03, 0x00, 0x2d, 0x00, 0x40, 0x64, 0x65, 0x66, 0x61, 0x7b, +0x00, 0x02, 0x4b, 0x00, 0xf8, 0x02, 0x2c, 0x00, 0x60, 0x28, +0x6e, 0x2d, 0x32, 0x29, 0x5e, 0x32, 0x27, 0x2c, 0x00, 0x6f, +0x6e, 0x6c, 0x79, 0xc1, 0x00, 0x46, 0x74, 0x68, 0x72, 0x65, +0x6a, 0x05, 0x22, 0x6f, 0x72, 0xbe, 0x00, 0x01, 0xf5, 0x02, +0x20, 0x73, 0x63, 0x0b, 0x00, 0x34, 0x61, 0x6e, 0x79, 0x05, +0x06, 0x00, 0x05, 0x05, 0x27, 0x6c, 0x6c, 0x68, 0x00, 0xb1, +0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, +0x65, 0x64, 0x00, 0x10, 0x31, 0x64, 0x00, 0x05, 0x76, 0x00, +0x08, 0x66, 0x00, 0x25, 0x77, 0x6f, 0x64, 0x00, 0x03, 0x57, +0x00, 0x02, 0x55, 0x00, 0x52, 0x00, 0x65, 0x61, 0x63, 0x68, +0x36, 0x05, 0x03, 0x94, 0x06, 0x04, 0x36, 0x00, 0x02, 0x27, +0x00, 0x31, 0x72, 0x65, 0x6c, 0x5f, 0x00, 0x28, 0x6c, 0x79, +0x8f, 0x06, 0x00, 0x2f, 0x01, 0xf2, 0x02, 0x45, 0x6e, 0x73, +0x75, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x62, 0x69, +0x6c, 0x69, 0x74, 0x79, 0xd7, 0x03, 0x01, 0x2f, 0x05, 0x03, +0x4f, 0x02, 0x00, 0x77, 0x01, 0x30, 0x69, 0x63, 0x6b, 0x23, +0x04, 0x09, 0x16, 0x01, 0xd0, 0x74, 0x61, 0x74, 0x65, 0x29, +0x2c, 0x00, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x59, 0x03, +0x00, 0x83, 0x01, 0x15, 0x73, 0xea, 0x03, 0x82, 0x67, 0x75, +0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x1e, 0x02, 0x02, 0xad, +0x07, 0x71, 0x74, 0x00, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x52, +0x07, 0x00, 0x73, 0x00, 0x00, 0x60, 0x00, 0x07, 0x49, 0x04, +0x60, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x69, 0x7d, 0x04, 0x12, +0x66, 0x2f, 0x02, 0x01, 0x73, 0x05, 0x03, 0x61, 0x00, 0x22, +0x6f, 0x72, 0x5b, 0x00, 0x70, 0x6e, 0x6f, 0x74, 0x00, 0x74, +0x72, 0x79, 0x55, 0x00, 0x05, 0x63, 0x00, 0x01, 0x4d, 0x00, +0x00, 0x17, 0x03, 0x01, 0x83, 0x00, 0x14, 0x3b, 0x71, 0x04, +0xd0, 0x2c, 0x00, 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, +0x2c, 0x00, 0x73, 0x74, 0x3c, 0x00, 0x11, 0x65, 0xee, 0x00, +0x02, 0x89, 0x06, 0x06, 0x08, 0x07, 0x05, 0x97, 0x00, 0x16, +0x32, 0xc2, 0x01, 0x11, 0x66, 0x53, 0x01, 0x04, 0x99, 0x02, +0x26, 0x6f, 0x6e, 0x0e, 0x05, 0x02, 0x3b, 0x00, 0x00, 0xff, +0x00, 0x85, 0x72, 0x74, 0x00, 0x28, 0x73, 0x69, 0x6e, 0x63, +0x86, 0x08, 0x02, 0x0f, 0x06, 0x62, 0x78, 0x61, 0x63, 0x74, +0x6c, 0x79, 0xe4, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x4e, 0x00, +0x74, 0x61, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x51, 0x00, +0x20, 0x69, 0x73, 0x48, 0x01, 0x40, 0x69, 0x6e, 0x69, 0x74, +0x94, 0x01, 0x23, 0x69, 0x6e, 0xc0, 0x00, 0x41, 0x29, 0x2e, +0x00, 0x47, 0x45, 0x01, 0x06, 0x55, 0x01, 0x01, 0x54, 0x00, +0x08, 0x8f, 0x01, 0x50, 0x64, 0x69, 0x73, 0x61, 0x62, 0x8e, +0x05, 0x31, 0x6d, 0x61, 0x79, 0xe6, 0x06, 0x00, 0xa3, 0x04, +0x01, 0xd6, 0x01, 0x02, 0x57, 0x03, 0x43, 0x61, 0x72, 0x65, +0x61, 0x55, 0x03, 0x05, 0xd7, 0x08, 0x02, 0x76, 0x00, 0x10, +0x2c, 0xe7, 0x00, 0x11, 0x64, 0x40, 0x05, 0xf1, 0x00, 0x6f, +0x00, 0x6f, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x6e, 0x69, +0x74, 0x69, 0x65, 0x73, 0x01, 0x03, 0x00, 0xb8, 0x08, 0x22, +0x65, 0x72, 0x32, 0x02, 0x11, 0x73, 0xc1, 0x03, 0x11, 0x79, +0xef, 0x06, 0x01, 0xba, 0x04, 0x80, 0x74, 0x61, 0x6b, 0x65, +0x00, 0x6c, 0x65, 0x73, 0x0c, 0x02, 0x21, 0x6d, 0x65, 0x7d, +0x01, 0x90, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2e, +0x00, }; -const unsigned short help_text_len = 2470; -const unsigned short help_text_words = 444; +const unsigned short help_text_len = 2492; +const unsigned short help_text_words = 445; const char quick_help_text[] = "Clear the grid by removing touching groups of the same colour squares."; diff --git a/apps/plugins/puzzles/help/signpost.c b/apps/plugins/puzzles/help/signpost.c index 6f89cbdd62..e38e42870c 100644 --- a/apps/plugins/puzzles/help/signpost.c +++ b/apps/plugins/puzzles/help/signpost.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,208 +6,220 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 158, TEXT_CENTER | C_RED }, - { 495, TEXT_CENTER | C_RED }, - { 512, TEXT_UNDERLINE }, + { 159, TEXT_CENTER | C_RED }, + { 496, TEXT_CENTER | C_RED }, { 513, TEXT_UNDERLINE }, - { 523, TEXT_UNDERLINE }, + { 514, TEXT_UNDERLINE }, + { 524, TEXT_UNDERLINE }, + { 569, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3054 comp 1895 ratio 0.620498 level 10 saved 1159 */ +/* orig 3255 comp 2009 ratio 0.617204 level 10 saved 1246 */ const char help_text[] = { -0xf3, 0x29, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x34, 0x3a, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x70, 0x6f, -0x73, 0x74, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, -0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, -0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, -0x65, 0x73, 0x3b, 0x00, 0x65, 0x61, 0x63, 0x68, 0x0e, 0x00, -0xf4, 0x23, 0x00, 0x28, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, -0x00, 0x74, 0x68, 0x65, 0x00, 0x6c, 0x61, 0x73, 0x74, 0x00, -0x6f, 0x6e, 0x65, 0x29, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, -0x69, 0x6e, 0x73, 0x00, 0x61, 0x6e, 0x00, 0x61, 0x72, 0x72, -0x6f, 0x77, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x73, 0x6f, -0x6d, 0x65, 0x47, 0x00, 0x54, 0x00, 0x61, 0x6c, 0x73, 0x6f, -0x29, 0x00, 0x90, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, -0x73, 0x2e, 0x78, 0x00, 0xa1, 0x72, 0x00, 0x6a, 0x6f, 0x62, -0x00, 0x69, 0x73, 0x00, 0x74, 0x20, 0x00, 0x32, 0x6e, 0x65, -0x63, 0x5f, 0x00, 0x04, 0x39, 0x00, 0x91, 0x74, 0x6f, 0x00, -0x66, 0x6f, 0x72, 0x6d, 0x00, 0x61, 0x3e, 0x00, 0x90, 0x69, -0x6e, 0x75, 0x6f, 0x75, 0x73, 0x00, 0x6c, 0x69, 0x7c, 0x00, -0x14, 0x66, 0x49, 0x00, 0xe1, 0x00, 0x73, 0x74, 0x61, 0x72, -0x74, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x74, 0x00, 0x31, 0x7d, -0x00, 0x91, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x00, 0x69, -0x6e, 0x4d, 0x00, 0x90, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, -0x69, 0x6f, 0x6e, 0x35, 0x00, 0x00, 0x11, 0x00, 0x01, 0xa7, -0x00, 0x66, 0x73, 0x00, 0x2d, 0x00, 0x73, 0x6f, 0x10, 0x00, -0x77, 0x00, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x7f, 0x00, -0x51, 0x00, 0x77, 0x69, 0x74, 0x68, 0x10, 0x00, 0x02, 0x6a, -0x00, 0xd0, 0x00, 0x31, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, -0x70, 0x6f, 0x69, 0x6e, 0x74, 0x9b, 0x00, 0x07, 0x2b, 0x00, -0x03, 0xdd, 0x00, 0x00, 0x86, 0x00, 0x07, 0x31, 0x00, 0x8f, -0x32, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x38, 0x00, -0x1d, 0x97, 0x33, 0x2c, 0x00, 0x65, 0x74, 0x63, 0x2e, 0x00, -0x45, 0x7e, 0x01, 0xf1, 0x0e, 0x63, 0x61, 0x6e, 0x00, 0x62, -0x65, 0x00, 0x61, 0x6e, 0x79, 0x00, 0x64, 0x69, 0x73, 0x74, -0x61, 0x6e, 0x63, 0x65, 0x00, 0x61, 0x77, 0x61, 0x79, 0x00, -0x66, 0x72, 0x6f, 0x6d, 0x3d, 0x00, 0x50, 0x70, 0x72, 0x65, -0x76, 0x69, 0x21, 0x01, 0xc0, 0x6f, 0x6e, 0x65, 0x2c, 0x00, -0x61, 0x73, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x08, 0x00, 0x20, -0x69, 0x74, 0x63, 0x01, 0x00, 0x92, 0x01, 0x5f, 0x77, 0x68, -0x65, 0x72, 0x65, 0x18, 0x01, 0x0b, 0x60, 0x2e, 0x00, 0x00, -0x00, 0x42, 0x79, 0x99, 0x00, 0x31, 0x76, 0x65, 0x6e, 0x1e, -0x00, 0x00, 0x1b, 0x00, 0x52, 0x66, 0x69, 0x72, 0x73, 0x74, -0x5c, 0x01, 0x00, 0xfa, 0x01, 0x04, 0x7b, 0x01, 0x00, 0x99, -0x00, 0x60, 0x73, 0x68, 0x6f, 0x77, 0x6e, 0x3b, 0x75, 0x00, -0x61, 0x00, 0x6f, 0x72, 0x00, 0x6d, 0x6f, 0x61, 0x00, 0x55, -0x74, 0x65, 0x72, 0x69, 0x6d, 0x27, 0x00, 0x32, 0x6d, 0x61, -0x79, 0x04, 0x02, 0x82, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, -0x00, 0x61, 0xe6, 0x01, 0x50, 0x62, 0x65, 0x67, 0x69, 0x6e, -0xfc, 0x00, 0x00, 0x74, 0x00, 0x60, 0x43, 0x72, 0x65, 0x64, -0x69, 0x74, 0xef, 0x01, 0xf2, 0x00, 0x00, 0x74, 0x68, 0x69, -0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, -0x6f, 0x07, 0x02, 0xa0, 0x4a, 0x61, 0x6e, 0x6b, 0x6f, 0x00, -0x5b, 0x31, 0x37, 0x5d, 0x54, 0x01, 0x60, 0x6f, 0x00, 0x63, -0x61, 0x6c, 0x6c, 0xd9, 0x00, 0xe2, 0x60, 0x50, 0x66, 0x65, -0x69, 0x6c, 0x70, 0x66, 0x61, 0x64, 0x27, 0x00, 0x28, 0x60, -0xca, 0x01, 0x60, 0x70, 0x61, 0x74, 0x68, 0x27, 0x29, 0x55, -0x00, 0x04, 0xe7, 0x02, 0x41, 0x00, 0x77, 0x61, 0x73, 0x6c, -0x01, 0x72, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x86, -0x01, 0x10, 0x69, 0x14, 0x00, 0x23, 0x6c, 0x6c, 0x05, 0x01, -0xf0, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, -0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x3f, 0x00, 0x00, -0x6f, 0x00, 0x90, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -0x2f, 0x6a, 0x81, 0x00, 0xc5, 0x2e, 0x61, 0x74, 0x2f, 0x52, -0x61, 0x65, 0x74, 0x73, 0x65, 0x6c, 0x2f, 0x79, 0x00, 0xf6, -0x02, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, -0x6d, 0x00, 0x00, 0x00, 0x33, 0x34, 0x2e, 0x31, 0x5e, 0x03, -0x01, 0x73, 0x00, 0x30, 0x6f, 0x6c, 0x73, 0x67, 0x03, 0x75, -0x54, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x94, 0x00, 0x55, -0x2c, 0x00, 0x79, 0x6f, 0x75, 0xf6, 0x02, 0x06, 0xf2, 0x02, -0x60, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x8f, 0x00, 0x50, -0x64, 0x72, 0x61, 0x67, 0x67, 0x1b, 0x02, 0x01, 0xe3, 0x01, -0x25, 0x6f, 0x6e, 0x36, 0x02, 0x60, 0x74, 0x6f, 0x00, 0x61, -0x6e, 0x6f, 0x27, 0x00, 0x92, 0x2c, 0x00, 0x69, 0x6e, 0x64, -0x69, 0x63, 0x61, 0x74, 0x42, 0x02, 0x02, 0x59, 0x01, 0x11, -0x79, 0x98, 0x01, 0x84, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, -0x6e, 0x74, 0xef, 0x01, 0xe6, 0x73, 0x65, 0x71, 0x75, 0x65, -0x6e, 0x63, 0x65, 0x2e, 0x00, 0x44, 0x72, 0x61, 0x67, 0xdd, -0x02, 0xb2, 0x6c, 0x65, 0x66, 0x74, 0x00, 0x62, 0x75, 0x74, -0x74, 0x6f, 0x6e, 0x69, 0x00, 0x17, 0x61, 0x67, 0x00, 0xe0, -0x69, 0x74, 0x73, 0x00, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, -0x73, 0x6f, 0x72, 0x2c, 0xe1, 0x01, 0x05, 0x38, 0x00, 0x4f, -0x72, 0x69, 0x67, 0x68, 0x39, 0x00, 0x0b, 0x52, 0x70, 0x72, -0x65, 0x64, 0x65, 0x3b, 0x00, 0x00, 0x4e, 0x01, 0x29, 0x49, -0x66, 0xf2, 0x00, 0x05, 0xea, 0x00, 0x35, 0x74, 0x77, 0x6f, -0xff, 0x00, 0x22, 0x69, 0x6e, 0x98, 0x01, 0x00, 0xd9, 0x02, -0x00, 0x6e, 0x02, 0x01, 0x56, 0x02, 0x01, 0x9e, 0x02, 0x74, -0x6d, 0x00, 0x68, 0x61, 0x73, 0x00, 0x61, 0x23, 0x03, 0x62, -0x69, 0x6e, 0x00, 0x69, 0x74, 0x2c, 0xb7, 0x02, 0x95, 0x70, -0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x41, 0x03, -0x01, 0x70, 0x03, 0x03, 0x6d, 0x02, 0x03, 0xff, 0x00, 0x01, -0x2f, 0x01, 0x03, 0x68, 0x00, 0x1d, 0x2e, 0x8c, 0x00, 0x72, -0x77, 0x6f, 0x00, 0x6e, 0x6f, 0x6e, 0x2d, 0x3f, 0x00, 0x24, -0x65, 0x64, 0x90, 0x00, 0x12, 0x2c, 0x4f, 0x01, 0x01, 0x4f, -0x00, 0x00, 0x7d, 0x03, 0x50, 0x73, 0x73, 0x69, 0x67, 0x6e, -0x3f, 0x02, 0x70, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, -0xd7, 0x02, 0xf9, 0x01, 0x67, 0x65, 0x62, 0x72, 0x61, 0x69, -0x63, 0x00, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x3a, 0x00, -0x32, 0x03, 0x8b, 0x6f, 0x63, 0x63, 0x61, 0x73, 0x69, 0x6f, -0x6e, 0x49, 0x00, 0x01, 0x2c, 0x00, 0x71, 0x6c, 0x65, 0x64, -0x00, 0x60, 0x61, 0x27, 0xe8, 0x00, 0x52, 0x60, 0x61, 0x2b, -0x31, 0x27, 0x3a, 0x05, 0x73, 0x74, 0x68, 0x65, 0x6e, 0x00, -0x60, 0x62, 0x18, 0x00, 0x15, 0x62, 0x18, 0x00, 0x82, 0x73, -0x6f, 0x00, 0x6f, 0x6e, 0x2e, 0x00, 0x43, 0xb3, 0x00, 0x00, -0xf0, 0x01, 0x01, 0x6c, 0x03, 0x04, 0x3a, 0x01, 0x24, 0x6f, -0x6e, 0x5b, 0x04, 0x41, 0x65, 0x6e, 0x64, 0x73, 0xc5, 0x05, -0x30, 0x75, 0x63, 0x68, 0x3a, 0x05, 0x10, 0x68, 0x76, 0x05, -0x01, 0x7a, 0x00, 0x52, 0x63, 0x61, 0x75, 0x73, 0x65, 0x4d, -0x01, 0x00, 0x3f, 0x03, 0x29, 0x74, 0x6f, 0x8c, 0x00, 0x05, -0xda, 0x01, 0x30, 0x73, 0x61, 0x6d, 0x17, 0x02, 0x31, 0x74, -0x74, 0x65, 0xb8, 0x01, 0x10, 0x57, 0x91, 0x00, 0x00, 0x2e, -0x01, 0x00, 0x2a, 0x02, 0x60, 0x2d, 0x63, 0x6c, 0x69, 0x63, -0x6b, 0x09, 0x02, 0x01, 0x00, 0x02, 0x03, 0x0f, 0x00, 0x25, -0x69, 0x6e, 0xfd, 0x01, 0x13, 0x2c, 0x55, 0x02, 0x38, 0x67, -0x61, 0x6c, 0xc7, 0x05, 0x04, 0x6a, 0x01, 0x11, 0x69, 0x02, -0x05, 0x04, 0x08, 0x01, 0x01, 0x3c, 0x04, 0x10, 0x2e, 0x1d, -0x03, 0x07, 0x87, 0x05, 0x09, 0x75, 0x06, 0x01, 0xdd, 0x05, -0x00, 0xcf, 0x00, 0x72, 0x66, 0x00, 0x62, 0x6c, 0x61, 0x63, -0x6b, 0x0c, 0x01, 0x01, 0x16, 0x04, 0x60, 0x67, 0x72, 0x65, -0x79, 0x00, 0x6f, 0x08, 0x05, 0x09, 0xcb, 0x01, 0x2e, 0x68, -0x65, 0xc0, 0x02, 0x04, 0x85, 0x02, 0x59, 0x41, 0x6c, 0x73, -0x6f, 0x2c, 0x60, 0x00, 0x02, 0xa0, 0x05, 0x40, 0x6e, 0x65, -0x65, 0x64, 0x5d, 0x02, 0x07, 0xb2, 0x02, 0x03, 0x6f, 0x02, -0x20, 0x73, 0x6d, 0x2a, 0x01, 0x25, 0x64, 0x6f, 0x47, 0x03, -0x62, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x36, 0x03, 0x64, -0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0xe5, 0x05, 0x86, 0x76, -0x61, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x73, 0x94, 0x00, 0x00, -0x88, 0x06, 0x0b, 0x16, 0x03, 0x60, 0x2e, 0x00, 0x53, 0x6f, -0x00, 0x79, 0xfa, 0x06, 0x50, 0x61, 0x69, 0x6d, 0x00, 0x69, -0x1c, 0x07, 0x39, 0x77, 0x61, 0x79, 0x23, 0x01, 0x19, 0x61, -0x80, 0x06, 0x12, 0x61, 0xf8, 0x00, 0x03, 0x1e, 0x01, 0x2d, -0x74, 0x6f, 0x1f, 0x00, 0x42, 0x64, 0x6f, 0x74, 0x2e, 0x5f, -0x04, 0x52, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x23, 0x06, 0x00, -0x7a, 0x00, 0x11, 0x73, 0x4d, 0x05, 0x30, 0x61, 0x00, 0x70, -0x1f, 0x07, 0x55, 0x63, 0x75, 0x6c, 0x61, 0x72, 0xca, 0x07, -0xa1, 0x62, 0x6f, 0x74, 0x68, 0x00, 0x69, 0x6e, 0x63, 0x6f, -0x6d, 0x38, 0x07, 0x00, 0x69, 0x03, 0x92, 0x75, 0x74, 0x67, -0x6f, 0x69, 0x6e, 0x67, 0x29, 0x2c, 0xe7, 0x01, 0x10, 0x64, -0x24, 0x04, 0x10, 0x69, 0x68, 0x07, 0x02, 0x1c, 0x06, 0x00, -0x1a, 0x08, 0x18, 0x2e, 0x65, 0x00, 0x00, 0x86, 0x05, 0x22, -0x6c, 0x65, 0x5e, 0x02, 0x13, 0x2c, 0x0d, 0x02, 0x01, 0x35, -0x00, 0x00, 0x7f, 0x00, 0x03, 0x68, 0x00, 0x03, 0x33, 0x01, -0x02, 0x82, 0x02, 0x0a, 0x4a, 0x00, 0x02, 0x77, 0x08, 0x00, -0xd5, 0x06, 0x01, 0x19, 0x06, 0x03, 0x98, 0x02, 0x40, 0x00, -0x63, 0x75, 0x72, 0x7c, 0x01, 0x22, 0x6b, 0x65, 0x13, 0x01, -0x02, 0x6b, 0x00, 0x55, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3c, -0x00, 0x06, 0x56, 0x08, 0x02, 0xea, 0x07, 0x94, 0x65, 0x73, -0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x45, 0x07, 0x80, -0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x6b, 0x70, 0x03, -0x00, 0xbb, 0x02, 0x30, 0x6f, 0x76, 0x65, 0x07, 0x01, 0x0a, -0x51, 0x02, 0x12, 0x61, 0x9d, 0x01, 0x50, 0x6f, 0x70, 0x65, -0x72, 0x61, 0xff, 0x05, 0x02, 0x58, 0x02, 0x1f, 0x70, 0x48, -0x00, 0x04, 0x4c, 0x61, 0x67, 0x61, 0x69, 0x49, 0x00, 0x01, -0xc4, 0x02, 0x20, 0x66, 0x69, 0xf4, 0x01, 0x02, 0xf3, 0x02, -0x70, 0x69, 0x6e, 0x6b, 0x2c, 0x00, 0x69, 0x66, 0x5b, 0x03, -0x6b, 0x6f, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x98, 0x00, 0x9f, -0x73, 0x70, 0x61, 0x63, 0x65, 0x00, 0x62, 0x61, 0x72, 0x49, -0x00, 0x01, 0x00, 0x0a, 0x03, 0x0d, 0xa8, 0x04, 0x12, 0x73, -0x34, 0x08, 0x01, 0x41, 0x00, 0x00, 0x3d, 0x02, 0x02, 0xa5, -0x00, 0x01, 0x60, 0x00, 0x01, 0x60, 0x02, 0x06, 0x1f, 0x09, -0x72, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0xfb, 0x08, -0x0e, 0xcc, 0x00, 0x07, 0x7c, 0x00, 0x02, 0xcb, 0x00, 0x10, -0x63, 0x40, 0x08, 0x21, 0x6c, 0x73, 0x6d, 0x05, 0x00, 0x8d, -0x01, 0x42, 0x28, 0x41, 0x6c, 0x6c, 0x4d, 0x05, 0x01, 0x0d, -0x07, 0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x46, 0x09, 0x13, 0x73, 0x23, 0x07, 0x32, 0x32, 0x2e, -0x31, 0x5b, 0x06, 0x01, 0xcc, 0x07, 0x41, 0x76, 0x61, 0x69, -0x6c, 0xe7, 0x00, 0x12, 0x29, 0xf8, 0x06, 0x16, 0x32, 0xf8, -0x06, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, -0x72, 0x73, 0x20, 0xdd, 0x03, 0x36, 0x73, 0x65, 0x00, 0x14, -0x00, 0x02, 0x44, 0x00, 0x04, 0x3f, 0x00, 0x06, 0xc1, 0x08, -0xe2, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x9a, 0x08, 0x12, 0x6e, 0x1a, -0x00, 0xa1, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, -0x6e, 0x75, 0x92, 0x04, 0x81, 0x69, 0x64, 0x74, 0x68, 0x2c, -0x00, 0x48, 0x65, 0x83, 0x06, 0x00, 0xe7, 0x07, 0x11, 0x7a, -0x27, 0x06, 0x01, 0x1f, 0x02, 0x24, 0x69, 0x6e, 0x3e, 0x01, -0x00, 0x2b, 0x00, 0x61, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x20, -0xf5, 0x01, 0x82, 0x2f, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, -0x20, 0xb6, 0x03, 0x12, 0x73, 0x92, 0x06, 0x33, 0x74, 0x72, -0x75, 0xb3, 0x04, 0x01, 0x24, 0x00, 0x01, 0x3a, 0x01, 0x27, -0x65, 0x6e, 0x65, 0x02, 0x24, 0x72, 0x65, 0xa3, 0x03, 0x42, -0x70, 0x6c, 0x61, 0x63, 0x10, 0x01, 0x94, 0x6f, 0x70, 0x70, -0x6f, 0x73, 0x69, 0x74, 0x65, 0x00, 0x4b, 0x00, 0x17, 0x28, -0x41, 0x00, 0x02, 0x83, 0x04, 0x31, 0x74, 0x6f, 0x70, 0x49, -0x03, 0x05, 0xd4, 0x05, 0x01, 0x56, 0x00, 0x28, 0x61, 0x74, -0x44, 0x04, 0x01, 0x35, 0x03, 0x11, 0x29, 0x8d, 0x06, 0x5f, -0x66, 0x61, 0x6c, 0x73, 0x65, 0x87, 0x00, 0x0c, 0x03, 0x80, -0x00, 0xf4, 0x03, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, -0x79, 0x00, 0x28, 0x61, 0x6c, 0x74, 0x68, 0x6f, 0x75, 0x67, -0x68, 0xa1, 0x00, 0x01, 0xd6, 0x03, 0x80, 0x73, 0x68, 0x6f, -0x77, 0x6e, 0x29, 0x2e, 0x00, +0x73, 0x74, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf3, 0x14, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, +0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, +0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x3b, +0x00, 0x65, 0x61, 0x63, 0x68, 0x0e, 0x00, 0xf4, 0x23, 0x00, +0x28, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x00, 0x74, 0x68, +0x65, 0x00, 0x6c, 0x61, 0x73, 0x74, 0x00, 0x6f, 0x6e, 0x65, +0x29, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, +0x00, 0x61, 0x6e, 0x00, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2c, +0x00, 0x61, 0x6e, 0x64, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x47, +0x00, 0x54, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x29, 0x00, 0x90, +0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x78, +0x00, 0xa1, 0x72, 0x00, 0x6a, 0x6f, 0x62, 0x00, 0x69, 0x73, +0x00, 0x74, 0x20, 0x00, 0x32, 0x6e, 0x65, 0x63, 0x5f, 0x00, +0x04, 0x39, 0x00, 0x91, 0x74, 0x6f, 0x00, 0x66, 0x6f, 0x72, +0x6d, 0x00, 0x61, 0x3e, 0x00, 0x90, 0x69, 0x6e, 0x75, 0x6f, +0x75, 0x73, 0x00, 0x6c, 0x69, 0x7c, 0x00, 0x14, 0x66, 0x49, +0x00, 0xe1, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, +0x67, 0x00, 0x61, 0x74, 0x00, 0x31, 0x7d, 0x00, 0x91, 0x6c, +0x69, 0x6e, 0x6b, 0x65, 0x64, 0x00, 0x69, 0x6e, 0x4d, 0x00, +0x90, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, +0x35, 0x00, 0x00, 0x11, 0x00, 0x01, 0xa7, 0x00, 0x66, 0x73, +0x00, 0x2d, 0x00, 0x73, 0x6f, 0x10, 0x00, 0x77, 0x00, 0x69, +0x6e, 0x73, 0x69, 0x64, 0x65, 0x7f, 0x00, 0x51, 0x00, 0x77, +0x69, 0x74, 0x68, 0x10, 0x00, 0x02, 0x6a, 0x00, 0xd0, 0x00, +0x31, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x9b, 0x00, 0x07, 0x2b, 0x00, 0x03, 0xdd, 0x00, +0x00, 0x86, 0x00, 0x07, 0x31, 0x00, 0x8f, 0x32, 0x2c, 0x00, +0x77, 0x68, 0x69, 0x63, 0x68, 0x38, 0x00, 0x1d, 0x97, 0x33, +0x2c, 0x00, 0x65, 0x74, 0x63, 0x2e, 0x00, 0x45, 0x7e, 0x01, +0xf1, 0x0e, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x61, +0x6e, 0x79, 0x00, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, +0x65, 0x00, 0x61, 0x77, 0x61, 0x79, 0x00, 0x66, 0x72, 0x6f, +0x6d, 0x3d, 0x00, 0x50, 0x70, 0x72, 0x65, 0x76, 0x69, 0x21, +0x01, 0xc0, 0x6f, 0x6e, 0x65, 0x2c, 0x00, 0x61, 0x73, 0x00, +0x6c, 0x6f, 0x6e, 0x67, 0x08, 0x00, 0x20, 0x69, 0x74, 0x63, +0x01, 0x00, 0x92, 0x01, 0x5f, 0x77, 0x68, 0x65, 0x72, 0x65, +0x18, 0x01, 0x0b, 0x60, 0x2e, 0x00, 0x00, 0x00, 0x42, 0x79, +0x99, 0x00, 0x31, 0x76, 0x65, 0x6e, 0x1e, 0x00, 0x00, 0x1b, +0x00, 0x52, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5c, 0x01, 0x00, +0xfa, 0x01, 0x04, 0x7b, 0x01, 0x00, 0x99, 0x00, 0x60, 0x73, +0x68, 0x6f, 0x77, 0x6e, 0x3b, 0x75, 0x00, 0x61, 0x00, 0x6f, +0x72, 0x00, 0x6d, 0x6f, 0x61, 0x00, 0x55, 0x74, 0x65, 0x72, +0x69, 0x6d, 0x27, 0x00, 0x32, 0x6d, 0x61, 0x79, 0x04, 0x02, +0x82, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x00, 0x61, 0xe6, +0x01, 0x50, 0x62, 0x65, 0x67, 0x69, 0x6e, 0xfc, 0x00, 0x00, +0x74, 0x00, 0x60, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0xef, +0x01, 0xf2, 0x00, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x07, 0x02, +0xa0, 0x4a, 0x61, 0x6e, 0x6b, 0x6f, 0x00, 0x5b, 0x31, 0x37, +0x5d, 0x54, 0x01, 0x60, 0x6f, 0x00, 0x63, 0x61, 0x6c, 0x6c, +0xd9, 0x00, 0xe2, 0x60, 0x50, 0x66, 0x65, 0x69, 0x6c, 0x70, +0x66, 0x61, 0x64, 0x27, 0x00, 0x28, 0x60, 0xca, 0x01, 0x60, +0x70, 0x61, 0x74, 0x68, 0x27, 0x29, 0x55, 0x00, 0x04, 0xfc, +0x02, 0x41, 0x00, 0x77, 0x61, 0x73, 0x6c, 0x01, 0x72, 0x72, +0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x86, 0x01, 0x10, 0x69, +0x14, 0x00, 0x23, 0x6c, 0x6c, 0x05, 0x01, 0xf0, 0x00, 0x62, +0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, +0x72, 0x76, 0x65, 0x79, 0x3f, 0x00, 0x00, 0x6f, 0x00, 0x90, +0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6a, 0x81, +0x00, 0xc5, 0x2e, 0x61, 0x74, 0x2f, 0x52, 0x61, 0x65, 0x74, +0x73, 0x65, 0x6c, 0x2f, 0x79, 0x00, 0xf6, 0x02, 0x2f, 0x69, +0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0x00, +0x00, 0x33, 0x34, 0x2e, 0x31, 0x73, 0x03, 0x01, 0x73, 0x00, +0xe5, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x6f, +0x00, 0x70, 0x6c, 0x61, 0x79, 0x94, 0x00, 0x55, 0x2c, 0x00, +0x79, 0x6f, 0x75, 0xf6, 0x02, 0x06, 0xf2, 0x02, 0x60, 0x67, +0x65, 0x74, 0x68, 0x65, 0x72, 0x8f, 0x00, 0x50, 0x64, 0x72, +0x61, 0x67, 0x67, 0x1b, 0x02, 0x01, 0xe3, 0x01, 0x25, 0x6f, +0x6e, 0x36, 0x02, 0x60, 0x74, 0x6f, 0x00, 0x61, 0x6e, 0x6f, +0x27, 0x00, 0x92, 0x2c, 0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, +0x61, 0x74, 0x42, 0x02, 0x02, 0x59, 0x01, 0x11, 0x79, 0x98, +0x01, 0x84, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, +0xef, 0x01, 0xe6, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, +0x65, 0x2e, 0x00, 0x44, 0x72, 0x61, 0x67, 0xdd, 0x02, 0xb2, +0x6c, 0x65, 0x66, 0x74, 0x00, 0x62, 0x75, 0x74, 0x74, 0x6f, +0x6e, 0x69, 0x00, 0x17, 0x61, 0x67, 0x00, 0xe0, 0x69, 0x74, +0x73, 0x00, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, +0x72, 0x2c, 0xe1, 0x01, 0x05, 0x38, 0x00, 0x4f, 0x72, 0x69, +0x67, 0x68, 0x39, 0x00, 0x0b, 0x52, 0x70, 0x72, 0x65, 0x64, +0x65, 0x3b, 0x00, 0x00, 0x4e, 0x01, 0x29, 0x49, 0x66, 0xf2, +0x00, 0x05, 0xea, 0x00, 0x35, 0x74, 0x77, 0x6f, 0xff, 0x00, +0x22, 0x69, 0x6e, 0x98, 0x01, 0x00, 0xd9, 0x02, 0x00, 0x6e, +0x02, 0x01, 0x56, 0x02, 0x01, 0x9e, 0x02, 0x74, 0x6d, 0x00, +0x68, 0x61, 0x73, 0x00, 0x61, 0x23, 0x03, 0x62, 0x69, 0x6e, +0x00, 0x69, 0x74, 0x2c, 0xb7, 0x02, 0x95, 0x70, 0x70, 0x72, +0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x41, 0x03, 0x01, 0x70, +0x03, 0x03, 0x6d, 0x02, 0x03, 0xff, 0x00, 0x01, 0x2f, 0x01, +0x03, 0x68, 0x00, 0x1d, 0x2e, 0x8c, 0x00, 0x72, 0x77, 0x6f, +0x00, 0x6e, 0x6f, 0x6e, 0x2d, 0x3f, 0x00, 0x24, 0x65, 0x64, +0x90, 0x00, 0x12, 0x2c, 0x4f, 0x01, 0x01, 0x4f, 0x00, 0x00, +0x7d, 0x03, 0x50, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x3f, 0x02, +0x70, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0xd7, 0x02, +0xf9, 0x01, 0x67, 0x65, 0x62, 0x72, 0x61, 0x69, 0x63, 0x00, +0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x3a, 0x00, 0x32, 0x03, +0x8b, 0x6f, 0x63, 0x63, 0x61, 0x73, 0x69, 0x6f, 0x6e, 0x49, +0x00, 0x01, 0x2c, 0x00, 0x71, 0x6c, 0x65, 0x64, 0x00, 0x60, +0x61, 0x27, 0xe8, 0x00, 0x52, 0x60, 0x61, 0x2b, 0x31, 0x27, +0x3a, 0x05, 0x73, 0x74, 0x68, 0x65, 0x6e, 0x00, 0x60, 0x62, +0x18, 0x00, 0x15, 0x62, 0x18, 0x00, 0x82, 0x73, 0x6f, 0x00, +0x6f, 0x6e, 0x2e, 0x00, 0x43, 0xb3, 0x00, 0x00, 0xf0, 0x01, +0x01, 0x6c, 0x03, 0x04, 0x3a, 0x01, 0x24, 0x6f, 0x6e, 0x5b, +0x04, 0x41, 0x65, 0x6e, 0x64, 0x73, 0xc5, 0x05, 0x30, 0x75, +0x63, 0x68, 0x3a, 0x05, 0x10, 0x68, 0x76, 0x05, 0x01, 0x7a, +0x00, 0x52, 0x63, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x01, 0x00, +0x3f, 0x03, 0x29, 0x74, 0x6f, 0x8c, 0x00, 0x05, 0xda, 0x01, +0x30, 0x73, 0x61, 0x6d, 0x17, 0x02, 0x31, 0x74, 0x74, 0x65, +0xb8, 0x01, 0x10, 0x57, 0x91, 0x00, 0x00, 0x2e, 0x01, 0x00, +0x2a, 0x02, 0x60, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x09, +0x02, 0x01, 0x00, 0x02, 0x03, 0x0f, 0x00, 0x25, 0x69, 0x6e, +0xfd, 0x01, 0x13, 0x2c, 0x55, 0x02, 0x38, 0x67, 0x61, 0x6c, +0xc7, 0x05, 0x04, 0x6a, 0x01, 0x11, 0x69, 0x02, 0x05, 0x04, +0x08, 0x01, 0x01, 0x3c, 0x04, 0x10, 0x2e, 0x1d, 0x03, 0x07, +0x87, 0x05, 0x09, 0x75, 0x06, 0x01, 0xdd, 0x05, 0x00, 0xcf, +0x00, 0x72, 0x66, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x0c, +0x01, 0x01, 0x16, 0x04, 0x60, 0x67, 0x72, 0x65, 0x79, 0x00, +0x6f, 0x08, 0x05, 0x09, 0xcb, 0x01, 0x2e, 0x68, 0x65, 0xc0, +0x02, 0x04, 0x85, 0x02, 0x59, 0x41, 0x6c, 0x73, 0x6f, 0x2c, +0x60, 0x00, 0x02, 0xa0, 0x05, 0x40, 0x6e, 0x65, 0x65, 0x64, +0x5d, 0x02, 0x07, 0xb2, 0x02, 0x03, 0x6f, 0x02, 0x20, 0x73, +0x6d, 0x2a, 0x01, 0x25, 0x64, 0x6f, 0x47, 0x03, 0x62, 0x62, +0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x36, 0x03, 0x64, 0x63, 0x6f, +0x72, 0x6e, 0x65, 0x72, 0xe5, 0x05, 0x86, 0x76, 0x61, 0x6e, +0x69, 0x73, 0x68, 0x65, 0x73, 0x94, 0x00, 0x00, 0x88, 0x06, +0x0b, 0x16, 0x03, 0x60, 0x2e, 0x00, 0x53, 0x6f, 0x00, 0x79, +0xfa, 0x06, 0x50, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x1c, 0x07, +0x39, 0x77, 0x61, 0x79, 0x23, 0x01, 0x19, 0x61, 0x80, 0x06, +0x12, 0x61, 0xf8, 0x00, 0x03, 0x1e, 0x01, 0x2d, 0x74, 0x6f, +0x1f, 0x00, 0x42, 0x64, 0x6f, 0x74, 0x2e, 0x5f, 0x04, 0x52, +0x72, 0x65, 0x6d, 0x6f, 0x76, 0x23, 0x06, 0x00, 0x7a, 0x00, +0x11, 0x73, 0x4d, 0x05, 0x30, 0x61, 0x00, 0x70, 0x1f, 0x07, +0x55, 0x63, 0x75, 0x6c, 0x61, 0x72, 0xca, 0x07, 0xa1, 0x62, +0x6f, 0x74, 0x68, 0x00, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x38, +0x07, 0x00, 0x69, 0x03, 0x92, 0x75, 0x74, 0x67, 0x6f, 0x69, +0x6e, 0x67, 0x29, 0x2c, 0xe7, 0x01, 0x10, 0x64, 0x24, 0x04, +0x10, 0x69, 0x68, 0x07, 0x02, 0x1c, 0x06, 0x00, 0x1a, 0x08, +0x18, 0x2e, 0x65, 0x00, 0x00, 0x86, 0x05, 0x22, 0x6c, 0x65, +0x5e, 0x02, 0x13, 0x2c, 0x0d, 0x02, 0x01, 0x35, 0x00, 0x00, +0x7f, 0x00, 0x03, 0x68, 0x00, 0x03, 0x33, 0x01, 0x02, 0x82, +0x02, 0x0a, 0x4a, 0x00, 0x02, 0x77, 0x08, 0x00, 0xd5, 0x06, +0x01, 0x19, 0x06, 0x03, 0x98, 0x02, 0x40, 0x00, 0x63, 0x75, +0x72, 0x7c, 0x01, 0x22, 0x6b, 0x65, 0x13, 0x01, 0x02, 0x6b, +0x00, 0x55, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x00, 0x06, +0x56, 0x08, 0x02, 0xea, 0x07, 0x94, 0x65, 0x73, 0x2e, 0x00, +0x50, 0x72, 0x65, 0x73, 0x73, 0x45, 0x07, 0x80, 0x72, 0x65, +0x74, 0x75, 0x72, 0x6e, 0x00, 0x6b, 0x70, 0x03, 0x00, 0xbb, +0x02, 0x30, 0x6f, 0x76, 0x65, 0x07, 0x01, 0x0a, 0x51, 0x02, +0x12, 0x61, 0x9d, 0x01, 0x50, 0x6f, 0x70, 0x65, 0x72, 0x61, +0xff, 0x05, 0x02, 0x58, 0x02, 0x1f, 0x70, 0x48, 0x00, 0x04, +0x4c, 0x61, 0x67, 0x61, 0x69, 0x49, 0x00, 0x01, 0xc4, 0x02, +0x20, 0x66, 0x69, 0xf4, 0x01, 0x02, 0xf3, 0x02, 0x70, 0x69, +0x6e, 0x6b, 0x2c, 0x00, 0x69, 0x66, 0x5b, 0x03, 0x6b, 0x6f, +0x77, 0x61, 0x62, 0x6c, 0x65, 0x98, 0x00, 0x9f, 0x73, 0x70, +0x61, 0x63, 0x65, 0x00, 0x62, 0x61, 0x72, 0x49, 0x00, 0x01, +0x00, 0x0a, 0x03, 0x0d, 0xa8, 0x04, 0x12, 0x73, 0x34, 0x08, +0x01, 0x41, 0x00, 0x00, 0x3d, 0x02, 0x02, 0xa5, 0x00, 0x01, +0x60, 0x00, 0x01, 0x60, 0x02, 0x06, 0x1f, 0x09, 0x72, 0x62, +0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0xfb, 0x08, 0x0e, 0xcc, +0x00, 0x07, 0x7c, 0x00, 0x02, 0xcb, 0x00, 0x10, 0x63, 0x40, +0x08, 0x21, 0x6c, 0x73, 0x6d, 0x05, 0x00, 0x8d, 0x01, 0x42, +0x28, 0x41, 0x6c, 0x6c, 0x4d, 0x05, 0x01, 0x0d, 0x07, 0x92, +0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x46, +0x09, 0x13, 0x73, 0x23, 0x07, 0x32, 0x32, 0x2e, 0x31, 0x5b, +0x06, 0x01, 0xcc, 0x07, 0x41, 0x76, 0x61, 0x69, 0x6c, 0xe7, +0x00, 0x12, 0x29, 0xf8, 0x06, 0x16, 0x32, 0xf8, 0x06, 0xb2, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, +0x20, 0xdd, 0x03, 0x36, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, +0x44, 0x00, 0x04, 0x3f, 0x00, 0x06, 0xc1, 0x08, 0xe2, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x9a, 0x08, 0x12, 0x6e, 0x1a, 0x00, 0xa1, +0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, +0x92, 0x04, 0x81, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, +0x65, 0x83, 0x06, 0x00, 0xe7, 0x07, 0x11, 0x7a, 0x27, 0x06, +0x01, 0x1f, 0x02, 0x24, 0x69, 0x6e, 0x3e, 0x01, 0x00, 0x2b, +0x00, 0x61, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x20, 0xf5, 0x01, +0x82, 0x2f, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0xb6, +0x03, 0x12, 0x73, 0x92, 0x06, 0x33, 0x74, 0x72, 0x75, 0xb3, +0x04, 0x01, 0x24, 0x00, 0x01, 0x3a, 0x01, 0x27, 0x65, 0x6e, +0x65, 0x02, 0x24, 0x72, 0x65, 0xa3, 0x03, 0x42, 0x70, 0x6c, +0x61, 0x63, 0x10, 0x01, 0x94, 0x6f, 0x70, 0x70, 0x6f, 0x73, +0x69, 0x74, 0x65, 0x00, 0x4b, 0x00, 0x17, 0x28, 0x41, 0x00, +0x02, 0x83, 0x04, 0x31, 0x74, 0x6f, 0x70, 0x49, 0x03, 0x05, +0xd4, 0x05, 0x01, 0x56, 0x00, 0x28, 0x61, 0x74, 0x44, 0x04, +0x01, 0x35, 0x03, 0x11, 0x29, 0x8d, 0x06, 0x5f, 0x66, 0x61, +0x6c, 0x73, 0x65, 0x87, 0x00, 0x0c, 0x03, 0x80, 0x00, 0xf4, +0x03, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, 0x79, 0x00, +0x28, 0x61, 0x6c, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0xa1, +0x00, 0x01, 0xd6, 0x03, 0x01, 0x53, 0x05, 0x22, 0x29, 0x2e, +0x93, 0x01, 0x16, 0x33, 0x93, 0x01, 0xb0, 0x75, 0x73, 0x65, +0x72, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x06, 0x08, +0x01, 0x99, 0x01, 0x20, 0x4f, 0x6e, 0x55, 0x00, 0x10, 0x74, +0x44, 0x02, 0x12, 0x73, 0x3e, 0x08, 0x80, 0x73, 0x75, 0x70, +0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, 0x00, 0x17, 0x00, 0x2e, +0x00, 0x12, 0x2c, 0x87, 0x01, 0x16, 0x50, 0x12, 0x00, 0x0d, +0xa3, 0x01, 0x33, 0x47, 0x61, 0x6d, 0xa3, 0x01, 0x02, 0xd2, +0x02, 0x34, 0x6c, 0x65, 0x74, 0x99, 0x05, 0x54, 0x66, 0x69, +0x67, 0x75, 0x72, 0xdf, 0x00, 0x34, 0x79, 0x6c, 0x65, 0x71, +0x0a, 0xf0, 0x01, 0x76, 0x69, 0x63, 0x74, 0x6f, 0x72, 0x79, +0x00, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x2e, 0x00, }; -const unsigned short help_text_len = 3054; -const unsigned short help_text_words = 566; +const unsigned short help_text_len = 3255; +const unsigned short help_text_words = 595; const char quick_help_text[] = "Connect the squares into a path following the arrows."; diff --git a/apps/plugins/puzzles/help/singles.c b/apps/plugins/puzzles/help/singles.c index 3f4ecd157b..f2bd1ae4d9 100644 --- a/apps/plugins/puzzles/help/singles.c +++ b/apps/plugins/puzzles/help/singles.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,124 +6,147 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 122, TEXT_CENTER | C_RED }, - { 212, TEXT_CENTER | C_RED }, - { 229, TEXT_UNDERLINE }, - { 230, TEXT_UNDERLINE }, - { 240, TEXT_UNDERLINE }, + { 120, TEXT_CENTER | C_RED }, + { 232, TEXT_CENTER | C_RED }, + { 249, TEXT_UNDERLINE }, + { 250, TEXT_UNDERLINE }, + { 260, TEXT_UNDERLINE }, + { 272, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 1392 comp 1052 ratio 0.755747 level 10 saved 340 */ +/* orig 1780 comp 1279 ratio 0.718539 level 10 saved 501 */ const char help_text[] = { -0xf3, 0x2d, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x32, 0x3a, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, -0x73, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, -0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, -0x00, 0x6f, 0x66, 0x00, 0x77, 0x68, 0x69, 0x74, 0x65, 0x00, -0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x61, -0x6c, 0x6c, 0x16, 0x00, 0xf0, 0x04, 0x63, 0x68, 0x00, 0x63, -0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, -0x62, 0x65, 0x72, 0x73, 0x2e, 0x40, 0x00, 0xf0, 0x01, 0x72, -0x00, 0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, 0x73, 0x00, 0x74, -0x6f, 0x00, 0x63, 0x6f, 0x6c, 0x12, 0x00, 0x40, 0x73, 0x6f, -0x6d, 0x65, 0x36, 0x00, 0x25, 0x74, 0x68, 0x4a, 0x00, 0xf1, -0x01, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x00, 0x28, 0x72, -0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x1c, 0x00, 0x02, -0x48, 0x00, 0x61, 0x29, 0x00, 0x73, 0x6f, 0x00, 0x61, 0x40, -0x00, 0x74, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x79, 0x76, -0x00, 0x00, 0x24, 0x00, 0x60, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, -0x77, 0x32, 0x00, 0xf3, 0x03, 0x63, 0x6f, 0x6e, 0x64, 0x69, -0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x00, 0x00, 0x00, 0x2d, -0x00, 0x4e, 0x6f, 0x41, 0x00, 0xf0, 0x15, 0x00, 0x6f, 0x63, -0x63, 0x75, 0x72, 0x73, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, -0x74, 0x68, 0x61, 0x6e, 0x00, 0x6f, 0x6e, 0x63, 0x65, 0x00, -0x69, 0x6e, 0x00, 0x61, 0x6e, 0x79, 0x00, 0x72, 0x6f, 0x77, -0x00, 0x6f, 0x72, 0x9b, 0x00, 0x44, 0x75, 0x6d, 0x6e, 0x2e, -0x3a, 0x00, 0x02, 0x8f, 0x00, 0x02, 0x9d, 0x00, 0x00, 0xbd, -0x00, 0x50, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0xdf, 0x00, 0x30, -0x6c, 0x6c, 0x79, 0x2f, 0x00, 0x61, 0x76, 0x65, 0x72, 0x74, -0x69, 0x63, 0x0e, 0x00, 0x80, 0x61, 0x64, 0x6a, 0x61, 0x63, -0x65, 0x6e, 0x74, 0xa1, 0x00, 0x00, 0x51, 0x00, 0x59, 0x6f, -0x74, 0x68, 0x65, 0x72, 0x41, 0x00, 0x02, 0x56, 0x00, 0xa0, -0x54, 0x68, 0x65, 0x00, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, -0xae, 0x00, 0x09, 0x48, 0x01, 0x51, 0x00, 0x6d, 0x75, 0x73, -0x74, 0xd6, 0x00, 0x81, 0x66, 0x6f, 0x72, 0x6d, 0x00, 0x6f, -0x6e, 0x65, 0x4c, 0x01, 0xf0, 0x10, 0x69, 0x67, 0x75, 0x6f, -0x75, 0x73, 0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x00, -0x28, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, -0x00, 0x62, 0x79, 0x00, 0x65, 0x64, 0x67, 0x80, 0x01, 0x70, -0x6e, 0x6f, 0x74, 0x00, 0x6a, 0x75, 0x73, 0x7d, 0x00, 0x30, -0x75, 0x63, 0x68, 0x59, 0x00, 0xb0, 0x61, 0x74, 0x00, 0x63, -0x6f, 0x72, 0x6e, 0x65, 0x72, 0x73, 0x29, 0x78, 0x00, 0x60, -0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x58, 0x00, 0xf1, 0x01, -0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, -0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0x52, 0x01, 0xf0, 0x02, -0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x31, 0x35, -0x5d, 0x00, 0x77, 0x68, 0x6f, 0x00, 0x63, 0x85, 0x00, 0x90, -0x69, 0x74, 0x00, 0x48, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x41, -0x00, 0x03, 0x0f, 0x02, 0x41, 0x00, 0x77, 0x61, 0x73, 0x95, -0x00, 0x40, 0x72, 0x69, 0x62, 0x75, 0x84, 0x00, 0x22, 0x74, -0x6f, 0x51, 0x00, 0x60, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, -0x78, 0x01, 0x00, 0x97, 0x00, 0xc0, 0x4a, 0x61, 0x6d, 0x65, -0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x3e, 0x00, -0x01, 0x59, 0x00, 0xc1, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x70, 0x00, 0x82, 0x2e, -0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x2f, 0x8d, 0x00, 0x32, -0x73, 0x2f, 0x68, 0x6e, 0x00, 0xb1, 0x68, 0x74, 0x6d, 0x6c, -0x00, 0x28, 0x62, 0x65, 0x77, 0x61, 0x72, 0x20, 0x02, 0xd5, -0x46, 0x6c, 0x61, 0x73, 0x68, 0x29, 0x00, 0x00, 0x00, 0x33, -0x32, 0x2e, 0x31, 0x98, 0x02, 0x01, 0x85, 0x00, 0x21, 0x6f, -0x6c, 0xa1, 0x02, 0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, -0x6c, 0x69, 0x63, 0x6b, 0xfb, 0x00, 0x10, 0x6f, 0xd2, 0x01, -0x64, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0xbb, 0x01, 0x44, -0x77, 0x69, 0x6c, 0x6c, 0x77, 0x02, 0x22, 0x69, 0x74, 0x96, -0x01, 0x39, 0x3b, 0x00, 0x6c, 0x37, 0x00, 0x20, 0x61, 0x67, -0xb5, 0x02, 0x01, 0x2a, 0x00, 0x42, 0x72, 0x65, 0x73, 0x74, -0x26, 0x02, 0x04, 0x7e, 0x02, 0x67, 0x2e, 0x00, 0x52, 0x69, -0x67, 0x68, 0x2e, 0x00, 0x01, 0x28, 0x00, 0xf1, 0x05, 0x61, -0x64, 0x64, 0x00, 0x61, 0x00, 0x63, 0x69, 0x72, 0x63, 0x6c, -0x65, 0x00, 0x28, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x64, -0x01, 0x72, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0xc2, -0x02, 0x20, 0x61, 0x74, 0x25, 0x00, 0x30, 0x65, 0x6c, 0x6c, -0x42, 0x02, 0xa1, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, -0x65, 0x6c, 0x79, 0xb5, 0x01, 0x01, 0x8a, 0x00, 0x23, 0x29, -0x2e, 0x65, 0x03, 0xb2, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, -0x73, 0x6f, 0x00, 0x75, 0x73, 0x7d, 0x00, 0x00, 0xb1, 0x02, -0x61, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xa7, 0x01, 0x20, -0x6d, 0x6f, 0x85, 0x03, 0x51, 0x72, 0x6f, 0x75, 0x6e, 0x64, -0x1f, 0x00, 0x00, 0x8e, 0x03, 0x74, 0x2e, 0x00, 0x50, 0x72, -0x65, 0x73, 0x73, 0x2d, 0x03, 0x60, 0x72, 0x65, 0x74, 0x75, -0x72, 0x6e, 0x9c, 0x02, 0x52, 0x73, 0x70, 0x61, 0x63, 0x65, -0x3b, 0x00, 0x01, 0xad, 0x00, 0x01, 0x18, 0x00, 0x14, 0x61, -0x12, 0x01, 0x02, 0x99, 0x02, 0x2a, 0x6f, 0x72, 0xc4, 0x00, -0x40, 0x72, 0x65, 0x73, 0x70, 0xc6, 0x01, 0xb8, 0x76, 0x65, -0x6c, 0x79, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x70, 0x5d, -0x00, 0x3f, 0x6b, 0x65, 0x79, 0x27, 0x01, 0x0b, 0x00, 0x51, -0x00, 0x01, 0xbc, 0x03, 0x03, 0xbf, 0x00, 0x01, 0x56, 0x00, -0x00, 0xde, 0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x13, 0x00, -0x11, 0x61, 0x24, 0x02, 0x00, 0x08, 0x01, 0x70, 0x73, 0x63, -0x72, 0x69, 0x62, 0x65, 0x64, 0x81, 0x03, 0x13, 0x73, 0x3a, -0x02, 0x40, 0x32, 0x2e, 0x31, 0x00, 0x9d, 0x00, 0x01, 0x04, -0x01, 0xa3, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, -0x65, 0x2e, 0xfc, 0x01, 0x15, 0x32, 0xfc, 0x01, 0x91, 0x70, -0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0xfe, 0x01, -0x66, 0x54, 0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, -0x43, 0x00, 0x04, 0x3e, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, -0x6d, 0x7b, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, -0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, 0x00, -0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, -0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xad, 0x00, 0x90, 0x57, -0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0xf3, 0x01, -0x01, 0xfc, 0x02, 0x11, 0x7a, 0x89, 0x02, 0x01, 0xfd, 0x04, -0x24, 0x69, 0x6e, 0xaf, 0x03, 0x00, 0x2b, 0x00, 0xa0, 0x44, -0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x65, -0x03, 0x03, 0x93, 0x02, 0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, -0x00, 0x03, 0xa4, 0x04, 0x60, 0x67, 0x65, 0x6e, 0x65, 0x72, -0x61, 0x35, 0x03, 0x80, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, -0x2e, 0x00, +0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf3, 0x19, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, +0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, +0x77, 0x68, 0x69, 0x74, 0x65, 0x00, 0x73, 0x71, 0x75, 0x61, +0x72, 0x65, 0x73, 0x2c, 0x00, 0x61, 0x6c, 0x6c, 0x16, 0x00, +0xf0, 0x04, 0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, +0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, +0x2e, 0x40, 0x00, 0xf0, 0x01, 0x72, 0x00, 0x74, 0x61, 0x73, +0x6b, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, +0x6c, 0x12, 0x00, 0x40, 0x73, 0x6f, 0x6d, 0x65, 0x36, 0x00, +0x25, 0x74, 0x68, 0x4a, 0x00, 0xf1, 0x01, 0x00, 0x62, 0x6c, +0x61, 0x63, 0x6b, 0x00, 0x28, 0x72, 0x65, 0x6d, 0x6f, 0x76, +0x69, 0x6e, 0x67, 0x1c, 0x00, 0x02, 0x48, 0x00, 0x61, 0x29, +0x00, 0x73, 0x6f, 0x00, 0x61, 0x40, 0x00, 0x74, 0x73, 0x61, +0x74, 0x69, 0x73, 0x66, 0x79, 0x76, 0x00, 0x00, 0x24, 0x00, +0x60, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x32, 0x00, 0xf3, +0x03, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, +0x73, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x4e, 0x6f, 0x41, +0x00, 0xf0, 0x15, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x73, +0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x74, 0x68, 0x61, 0x6e, +0x00, 0x6f, 0x6e, 0x63, 0x65, 0x00, 0x69, 0x6e, 0x00, 0x61, +0x6e, 0x79, 0x00, 0x72, 0x6f, 0x77, 0x00, 0x6f, 0x72, 0x9b, +0x00, 0x44, 0x75, 0x6d, 0x6e, 0x2e, 0x3a, 0x00, 0x02, 0x8f, +0x00, 0x02, 0x9d, 0x00, 0x00, 0xbd, 0x00, 0x50, 0x68, 0x6f, +0x72, 0x69, 0x7a, 0xdf, 0x00, 0x30, 0x6c, 0x6c, 0x79, 0x2f, +0x00, 0x61, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, 0x00, +0x80, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0xa1, +0x00, 0x00, 0x51, 0x00, 0x59, 0x6f, 0x74, 0x68, 0x65, 0x72, +0x41, 0x00, 0x02, 0x56, 0x00, 0xa0, 0x54, 0x68, 0x65, 0x00, +0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0xae, 0x00, 0x09, 0x48, +0x01, 0x51, 0x00, 0x6d, 0x75, 0x73, 0x74, 0xd6, 0x00, 0x81, +0x66, 0x6f, 0x72, 0x6d, 0x00, 0x6f, 0x6e, 0x65, 0x4c, 0x01, +0xf0, 0x10, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x00, 0x72, +0x65, 0x67, 0x69, 0x6f, 0x6e, 0x00, 0x28, 0x63, 0x6f, 0x6e, +0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x62, 0x79, 0x00, +0x65, 0x64, 0x67, 0x80, 0x01, 0x70, 0x6e, 0x6f, 0x74, 0x00, +0x6a, 0x75, 0x73, 0x7d, 0x00, 0x30, 0x75, 0x63, 0x68, 0x59, +0x00, 0xb0, 0x61, 0x74, 0x00, 0x63, 0x6f, 0x72, 0x6e, 0x65, +0x72, 0x73, 0x29, 0x78, 0x00, 0x60, 0x43, 0x72, 0x65, 0x64, +0x69, 0x74, 0x58, 0x00, 0xf1, 0x01, 0x00, 0x74, 0x68, 0x69, +0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, +0x6f, 0x65, 0x52, 0x01, 0xf0, 0x02, 0x4e, 0x69, 0x6b, 0x6f, +0x6c, 0x69, 0x00, 0x5b, 0x31, 0x35, 0x5d, 0x00, 0x77, 0x68, +0x6f, 0x00, 0x63, 0x85, 0x00, 0x90, 0x69, 0x74, 0x00, 0x48, +0x69, 0x74, 0x6f, 0x72, 0x69, 0x41, 0x00, 0x03, 0x23, 0x02, +0x41, 0x00, 0x77, 0x61, 0x73, 0x95, 0x00, 0x40, 0x72, 0x69, +0x62, 0x75, 0x84, 0x00, 0x22, 0x74, 0x6f, 0x51, 0x00, 0x60, +0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x78, 0x01, 0x00, 0x97, +0x00, 0xc0, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, +0x72, 0x76, 0x65, 0x79, 0x3e, 0x00, 0x01, 0x59, 0x00, 0xd1, +0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, +0x77, 0x2e, 0x6e, 0x71, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, +0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0x90, 0x00, 0x31, 0x73, +0x2f, 0x68, 0x71, 0x00, 0x85, 0x2f, 0x00, 0x00, 0x00, 0x33, +0x32, 0x2e, 0x31, 0x99, 0x02, 0x01, 0x72, 0x00, 0xf0, 0x02, +0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x66, +0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xe8, 0x00, 0x10, +0x6f, 0xbf, 0x01, 0x64, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, +0xa8, 0x01, 0x44, 0x77, 0x69, 0x6c, 0x6c, 0x64, 0x02, 0x22, +0x69, 0x74, 0x83, 0x01, 0x30, 0x3b, 0x00, 0x6c, 0x37, 0x00, +0x15, 0x00, 0x38, 0x00, 0x20, 0x61, 0x67, 0xa3, 0x02, 0x01, +0x2b, 0x00, 0x42, 0x72, 0x65, 0x73, 0x74, 0x14, 0x02, 0x04, +0x6c, 0x02, 0x67, 0x2e, 0x00, 0x52, 0x69, 0x67, 0x68, 0x66, +0x00, 0x01, 0x28, 0x00, 0xf1, 0x05, 0x61, 0x64, 0x64, 0x00, +0x61, 0x00, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x28, +0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x01, 0x72, 0x69, +0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0xb0, 0x02, 0x20, 0x61, +0x74, 0x25, 0x00, 0x30, 0x65, 0x6c, 0x6c, 0x30, 0x02, 0xa1, +0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x6c, 0x79, +0xa3, 0x01, 0x01, 0x8b, 0x00, 0x45, 0x29, 0x2e, 0x00, 0x43, +0xbe, 0x00, 0x52, 0x75, 0x74, 0x73, 0x69, 0x64, 0x7b, 0x00, +0x01, 0x5b, 0x03, 0x01, 0x69, 0x00, 0xad, 0x74, 0x6f, 0x67, +0x67, 0x6c, 0x65, 0x00, 0x77, 0x68, 0x65, 0x44, 0x02, 0x00, +0x69, 0x01, 0x41, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x00, 0x14, +0x68, 0x3b, 0x00, 0x03, 0x6a, 0x03, 0x00, 0x0d, 0x01, 0x50, +0x74, 0x68, 0x65, 0x6d, 0x2c, 0x9b, 0x02, 0x71, 0x64, 0x69, +0x73, 0x70, 0x6c, 0x61, 0x79, 0x11, 0x00, 0x00, 0xe5, 0x02, +0x72, 0x64, 0x61, 0x72, 0x6b, 0x00, 0x67, 0x72, 0x90, 0x01, +0x00, 0xd2, 0x03, 0xb2, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, +0x73, 0x6f, 0x00, 0x75, 0x73, 0x46, 0x00, 0x00, 0x1e, 0x03, +0x61, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x14, 0x02, 0x20, +0x6d, 0x6f, 0xf2, 0x03, 0x55, 0x72, 0x6f, 0x75, 0x6e, 0x64, +0xa0, 0x00, 0x74, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, +0x9a, 0x03, 0x60, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x6e, +0x00, 0x52, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x00, 0x02, +0xc3, 0x00, 0x00, 0x18, 0x00, 0x14, 0x61, 0x92, 0x01, 0x02, +0xc2, 0x00, 0x2a, 0x6f, 0x72, 0x43, 0x01, 0x40, 0x72, 0x65, +0x73, 0x70, 0x33, 0x02, 0xb8, 0x76, 0x65, 0x6c, 0x79, 0x2c, +0x00, 0x61, 0x6e, 0x64, 0x00, 0x70, 0x5d, 0x00, 0x3f, 0x6b, +0x65, 0x79, 0xa6, 0x01, 0x0b, 0x00, 0x51, 0x00, 0x01, 0x29, +0x04, 0x03, 0xbf, 0x00, 0x01, 0x56, 0x00, 0x00, 0xde, 0x00, +0x41, 0x28, 0x41, 0x6c, 0x6c, 0x13, 0x00, 0x11, 0x61, 0x91, +0x02, 0x00, 0x87, 0x01, 0x70, 0x73, 0x63, 0x72, 0x69, 0x62, +0x65, 0x64, 0x09, 0x01, 0x13, 0x73, 0xa7, 0x02, 0x40, 0x32, +0x2e, 0x31, 0x00, 0x9d, 0x00, 0x01, 0x04, 0x01, 0xb2, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, +0x7c, 0x02, 0x15, 0x32, 0x7c, 0x02, 0x91, 0x70, 0x61, 0x72, +0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x7e, 0x02, 0x66, 0x54, +0x68, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x43, 0x00, +0x04, 0x3e, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x7b, +0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, +0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, 0x00, 0x22, 0x6f, +0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x75, 0xad, 0x00, 0x90, 0x57, 0x69, 0x64, +0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x72, 0x02, 0x01, 0x69, +0x03, 0x11, 0x7a, 0x16, 0x05, 0x01, 0x0f, 0x02, 0x24, 0x69, +0x6e, 0xf8, 0x01, 0x00, 0x2b, 0x00, 0xa0, 0x44, 0x69, 0x66, +0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0xd2, 0x03, 0x03, +0x13, 0x03, 0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x03, +0x11, 0x05, 0x60, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0xa2, +0x03, 0x02, 0x5b, 0x03, 0x12, 0x2e, 0xd7, 0x00, 0x15, 0x33, +0xd7, 0x00, 0xf1, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x70, +0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0xdd, +0x00, 0x70, 0x4f, 0x6e, 0x00, 0x70, 0x6c, 0x61, 0x74, 0x7e, +0x04, 0x12, 0x73, 0xcb, 0x02, 0x80, 0x73, 0x75, 0x70, 0x70, +0x6f, 0x72, 0x74, 0x00, 0x2e, 0x00, 0x17, 0x00, 0x2e, 0x00, +0x12, 0x2c, 0xcb, 0x00, 0x16, 0x50, 0x12, 0x00, 0x0d, 0xe7, +0x00, 0x33, 0x47, 0x61, 0x6d, 0xe7, 0x00, 0x02, 0xc1, 0x01, +0x70, 0x6c, 0x65, 0x74, 0x00, 0x79, 0x6f, 0x75, 0x3e, 0x04, +0x56, 0x66, 0x69, 0x67, 0x75, 0x72, 0xe1, 0x02, 0x07, 0xbf, +0x02, 0x0a, 0xec, 0x02, 0x00, 0x5c, 0x01, 0x50, 0x76, 0x69, +0x73, 0x69, 0x62, 0xc0, 0x00, 0x8f, 0x55, 0x6e, 0x6c, 0x69, +0x6b, 0x65, 0x00, 0x63, 0x3c, 0x03, 0x05, 0x12, 0x2c, 0x89, +0x04, 0x01, 0x6c, 0x00, 0xf0, 0x08, 0x70, 0x65, 0x72, 0x73, +0x69, 0x73, 0x74, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, +0x6e, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 1392; -const unsigned short help_text_words = 250; +const unsigned short help_text_len = 1780; +const unsigned short help_text_words = 309; const char quick_help_text[] = "Black out the right set of duplicate numbers."; diff --git a/apps/plugins/puzzles/help/sixteen.c b/apps/plugins/puzzles/help/sixteen.c index c3d52b6220..164be4ee4e 100644 --- a/apps/plugins/puzzles/help/sixteen.c +++ b/apps/plugins/puzzles/help/sixteen.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,194 +6,195 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 113, TEXT_UNDERLINE }, - { 187, TEXT_CENTER | C_RED }, - { 321, TEXT_CENTER | C_RED }, - { 339, TEXT_UNDERLINE }, - { 341, TEXT_UNDERLINE }, + { 114, TEXT_UNDERLINE }, + { 188, TEXT_CENTER | C_RED }, + { 322, TEXT_CENTER | C_RED }, + { 340, TEXT_UNDERLINE }, + { 342, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2534 comp 1755 ratio 0.692581 level 6 saved 779 */ +/* orig 2553 comp 1763 ratio 0.69056 level 6 saved 790 */ const char help_text[] = { -0xf0, 0x3b, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x36, 0x3a, 0x20, 0x53, 0x69, 0x78, 0x74, 0x65, 0x65, 0x6e, -0x20, 0x00, 0x00, 0x00, 0x41, 0x6e, 0x6f, 0x74, 0x68, 0x65, -0x72, 0x00, 0x73, 0x6c, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x00, -0x74, 0x69, 0x6c, 0x65, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, -0x65, 0x2c, 0x00, 0x76, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x6c, -0x79, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x00, -0x74, 0x6f, 0x00, 0x46, 0x69, 0x66, 0x3c, 0x00, 0x72, 0x00, -0x28, 0x73, 0x65, 0x65, 0x00, 0x63, 0x54, 0x00, 0xf0, 0x23, -0x00, 0x35, 0x29, 0x00, 0x62, 0x75, 0x74, 0x00, 0x77, 0x69, -0x74, 0x68, 0x00, 0x61, 0x00, 0x64, 0x69, 0x66, 0x66, 0x65, -0x72, 0x65, 0x6e, 0x74, 0x00, 0x74, 0x79, 0x70, 0x65, 0x00, -0x6f, 0x66, 0x00, 0x6d, 0x6f, 0x76, 0x65, 0x2e, 0x00, 0x54, -0x68, 0x69, 0x73, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x00, -0x74, 0x00, 0xf0, 0x10, 0x65, 0x00, 0x69, 0x73, 0x00, 0x6e, -0x6f, 0x00, 0x68, 0x6f, 0x6c, 0x65, 0x3a, 0x00, 0x61, 0x6c, -0x6c, 0x00, 0x31, 0x36, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, -0x65, 0x73, 0x00, 0x6f, 0x6e, 0x24, 0x00, 0xf4, 0x07, 0x00, -0x67, 0x72, 0x69, 0x64, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, -0x69, 0x6e, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, -0x64, 0x25, 0x00, 0x61, 0x2e, 0x00, 0x59, 0x6f, 0x75, 0x72, -0x5d, 0x00, 0x00, 0x4b, 0x00, 0xf0, 0x16, 0x74, 0x6f, 0x00, -0x73, 0x68, 0x69, 0x66, 0x74, 0x00, 0x61, 0x6e, 0x00, 0x65, -0x6e, 0x74, 0x69, 0x72, 0x65, 0x00, 0x72, 0x6f, 0x77, 0x00, -0x6c, 0x65, 0x66, 0x74, 0x00, 0x6f, 0x72, 0x00, 0x72, 0x69, -0x67, 0x68, 0x74, 0x2c, 0x0a, 0x00, 0x0c, 0x26, 0x00, 0x90, -0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x00, 0x75, 0x70, 0x1d, -0x00, 0xb1, 0x64, 0x6f, 0x77, 0x6e, 0x3b, 0x00, 0x65, 0x76, -0x65, 0x72, 0x79, 0xac, 0x00, 0xc1, 0x00, 0x79, 0x6f, 0x75, -0x00, 0x64, 0x6f, 0x00, 0x74, 0x68, 0x61, 0x74, 0xb8, 0x00, -0x02, 0x23, 0x01, 0x00, 0x16, 0x00, 0x02, 0x48, 0x00, 0x36, -0x6f, 0x66, 0x66, 0xab, 0x00, 0xd1, 0x72, 0x65, 0x2d, 0x61, -0x70, 0x70, 0x65, 0x61, 0x72, 0x73, 0x00, 0x61, 0x74, 0x17, -0x00, 0x02, 0x5f, 0x01, 0x52, 0x65, 0x6e, 0x64, 0x00, 0x6f, -0x28, 0x00, 0x31, 0x73, 0x61, 0x6d, 0x99, 0x00, 0x32, 0x2c, -0x00, 0x69, 0xe4, 0x00, 0x42, 0x73, 0x70, 0x61, 0x63, 0x51, -0x00, 0xf5, 0x0e, 0x6a, 0x75, 0x73, 0x74, 0x00, 0x76, 0x61, -0x63, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x54, 0x6f, 0x00, -0x77, 0x69, 0x6e, 0x2c, 0x00, 0x61, 0x72, 0x72, 0x61, 0x6e, -0x67, 0x65, 0x7c, 0x00, 0x60, 0x73, 0x00, 0x69, 0x6e, 0x74, -0x6f, 0x0e, 0x01, 0xf4, 0x06, 0x65, 0x72, 0x69, 0x63, 0x61, -0x6c, 0x00, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x00, 0x28, 0x31, -0x2c, 0x32, 0x2c, 0x33, 0x2c, 0x34, 0x3b, 0x01, 0x32, 0x74, -0x6f, 0x70, 0x67, 0x00, 0xb4, 0x31, 0x33, 0x2c, 0x31, 0x34, -0x2c, 0x31, 0x35, 0x2c, 0x31, 0x36, 0x1c, 0x00, 0xd0, 0x62, -0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x29, 0x2e, 0x00, 0x57, 0x68, -0x65, 0x6e, 0x7b, 0x00, 0x84, 0x27, 0x76, 0x65, 0x00, 0x64, -0x6f, 0x6e, 0x65, 0xe7, 0x00, 0x70, 0x72, 0x79, 0x00, 0x70, -0x6c, 0x61, 0x79, 0x12, 0x02, 0x27, 0x6f, 0x6e, 0xd1, 0x01, -0x30, 0x73, 0x69, 0x7a, 0x9d, 0x01, 0x11, 0x66, 0xee, 0x00, -0x70, 0x2e, 0x00, 0x00, 0x00, 0x49, 0x00, 0x6d, 0x58, 0x01, -0x30, 0x00, 0x68, 0x61, 0x85, 0x01, 0x90, 0x6e, 0x76, 0x65, -0x6e, 0x74, 0x65, 0x64, 0x00, 0x74, 0xea, 0x01, 0x10, 0x67, -0xe9, 0x00, 0x60, 0x6d, 0x79, 0x73, 0x65, 0x6c, 0x66, 0x39, -0x01, 0xf0, 0x03, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x6f, 0x6e, -0x6c, 0x79, 0x00, 0x62, 0x79, 0x00, 0x61, 0x63, 0x63, 0x69, -0x64, 0x51, 0x00, 0xf4, 0x03, 0x69, 0x66, 0x00, 0x73, 0x6f, -0x00, 0x28, 0x61, 0x6e, 0x64, 0x00, 0x49, 0x27, 0x6d, 0x00, -0x73, 0x75, 0x72, 0x33, 0x01, 0x64, 0x70, 0x65, 0x6f, 0x70, -0x6c, 0x65, 0x59, 0x00, 0x50, 0x64, 0x65, 0x70, 0x65, 0x6e, -0x32, 0x00, 0x26, 0x6c, 0x79, 0x67, 0x00, 0x63, 0x69, 0x74, -0x29, 0x2e, 0x00, 0x49, 0x5c, 0x00, 0xe0, 0x74, 0x00, 0x49, -0x00, 0x77, 0x61, 0x73, 0x00, 0x69, 0x6d, 0x69, 0x74, 0x61, -0x74, 0xba, 0x00, 0xf1, 0x08, 0x61, 0x00, 0x73, 0x63, 0x72, -0x65, 0x65, 0x6e, 0x73, 0x61, 0x76, 0x65, 0x72, 0x00, 0x49, -0x27, 0x64, 0x00, 0x73, 0x65, 0x65, 0x6e, 0x2c, 0xab, 0x02, -0x12, 0x49, 0x59, 0x00, 0x61, 0x61, 0x00, 0x66, 0x65, 0x65, -0x6c, 0xf9, 0x02, 0x13, 0x68, 0xb1, 0x01, 0x08, 0x34, 0x00, -0x02, 0xdc, 0x00, 0x32, 0x61, 0x63, 0x74, 0x07, 0x03, 0x01, -0x33, 0x00, 0x10, 0x62, 0xfe, 0x02, 0x14, 0x61, 0x08, 0x03, -0x11, 0x2d, 0xe3, 0x02, 0x02, 0x31, 0x03, 0x31, 0x00, 0x72, -0x61, 0xba, 0x00, 0x42, 0x74, 0x68, 0x61, 0x6e, 0x03, 0x01, -0x20, 0x73, 0x6c, 0x41, 0x00, 0x27, 0x6c, 0x79, 0x42, 0x01, -0x82, 0x6b, 0x69, 0x6e, 0x64, 0x2e, 0x00, 0x53, 0x6f, 0x21, -0x00, 0x02, 0x61, 0x00, 0x12, 0x62, 0xdd, 0x01, 0x02, 0x80, -0x01, 0x00, 0x8d, 0x00, 0x54, 0x69, 0x6e, 0x00, 0x6d, 0x79, -0x56, 0x00, 0xf2, 0x19, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, -0x74, 0x69, 0x6f, 0x6e, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, -0x00, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, -0x73, 0x00, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x69, -0x74, 0x79, 0x00, 0x6f, 0x34, 0x00, 0x39, 0x61, 0x72, 0x74, -0x88, 0x00, 0x01, 0x54, 0x02, 0xb0, 0x65, 0x6e, 0x67, 0x69, -0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xb5, 0x01, 0x35, -0x36, 0x2e, 0x31, 0x04, 0x04, 0x00, 0x5d, 0x03, 0x40, 0x72, -0x6f, 0x6c, 0x73, 0x0d, 0x04, 0xa3, 0x4c, 0x65, 0x66, 0x74, -0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xf9, 0x01, 0x20, 0x61, -0x6e, 0x7e, 0x02, 0x72, 0x6f, 0x77, 0x00, 0x77, 0x69, 0x6c, -0x6c, 0x69, 0x03, 0x00, 0xa9, 0x00, 0xa2, 0x61, 0x70, 0x70, -0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x63, 0x03, 0x24, -0x6f, 0x72, 0x44, 0x03, 0x03, 0xd3, 0x02, 0x33, 0x64, 0x69, -0x72, 0xb2, 0x00, 0x43, 0x69, 0x6e, 0x64, 0x69, 0xd0, 0x02, -0x10, 0x52, 0xec, 0x00, 0x06, 0x5f, 0x00, 0x06, 0x53, 0x00, -0x24, 0x69, 0x74, 0x38, 0x00, 0x77, 0x6f, 0x70, 0x70, 0x6f, -0x73, 0x69, 0x74, 0x41, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x41, -0x6c, 0x74, 0x65, 0x72, 0x6e, 0xe8, 0x00, 0x72, 0x65, 0x6c, -0x79, 0x2c, 0x00, 0x75, 0x73, 0x86, 0x00, 0xa1, 0x63, 0x75, -0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xfc, 0x03, -0x05, 0x9e, 0x00, 0x01, 0x43, 0x00, 0x07, 0x7c, 0x00, 0x91, -0x6f, 0x72, 0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x1e, -0x00, 0x31, 0x65, 0x64, 0x67, 0x93, 0x04, 0x04, 0xb3, 0x03, -0x20, 0x2c, 0x00, 0x7c, 0x02, 0x04, 0x54, 0x00, 0x60, 0x72, -0x65, 0x74, 0x75, 0x72, 0x6e, 0x54, 0x00, 0x09, 0x53, 0x00, -0x4f, 0x72, 0x6f, 0x77, 0x2f, 0xe2, 0x00, 0x10, 0x10, 0x00, -0x91, 0x04, 0x20, 0x00, 0x63, 0x36, 0x01, 0x27, 0x6c, 0x73, -0x3f, 0x00, 0x02, 0xb6, 0x03, 0x02, 0x33, 0x00, 0x79, 0x6c, -0x79, 0x2e, 0x00, 0x4d, 0x6f, 0x76, 0xc3, 0x00, 0x10, 0x6f, -0xd0, 0x03, 0x11, 0x61, 0x27, 0x00, 0x10, 0x2c, 0x0f, 0x05, -0x32, 0x64, 0x00, 0x43, 0x96, 0x01, 0x01, 0x9c, 0x00, 0x00, -0xed, 0x01, 0x16, 0x73, 0x8b, 0x01, 0x0c, 0x9c, 0x00, 0x01, -0x8f, 0x04, 0x20, 0x75, 0x6e, 0x03, 0x04, 0x07, 0x53, 0x00, -0x00, 0x39, 0x00, 0x1b, 0x6d, 0x67, 0x00, 0x52, 0x61, 0x6c, -0x6f, 0x6e, 0x67, 0xa5, 0x05, 0x04, 0x39, 0x00, 0x43, 0x2e, -0x00, 0x4f, 0x72, 0x73, 0x00, 0x11, 0x53, 0xce, 0x04, 0x04, -0x5a, 0x00, 0x01, 0xa9, 0x03, 0x06, 0x26, 0x00, 0x10, 0x50, -0x84, 0x00, 0x00, 0xb6, 0x01, 0x20, 0x45, 0x6e, 0xf0, 0x05, -0x91, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, -0x3b, 0x00, 0x00, 0x18, 0x00, 0x00, 0x37, 0x05, 0x05, 0xb6, -0x00, 0x12, 0x28, 0xb3, 0x00, 0x02, 0x2c, 0x00, 0x20, 0x61, -0x67, 0xbc, 0x05, 0xc0, 0x74, 0x6f, 0x00, 0x72, 0x65, 0x6c, -0x65, 0x61, 0x73, 0x65, 0x29, 0x2c, 0xc7, 0x02, 0x00, 0x66, -0x06, 0x04, 0x54, 0x00, 0x11, 0x53, 0x01, 0x05, 0x0f, 0x54, -0x00, 0x04, 0x01, 0x65, 0x05, 0x00, 0x5b, 0x01, 0x42, 0x28, -0x41, 0x6c, 0x6c, 0x7e, 0x02, 0x01, 0x78, 0x01, 0x90, 0x73, -0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x08, 0x04, -0x33, 0x6e, 0x00, 0x73, 0x8e, 0x01, 0x72, 0x32, 0x2e, 0x31, -0x00, 0x61, 0x72, 0x65, 0x81, 0x01, 0xb1, 0x61, 0x76, 0x61, -0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xf6, 0x02, -0x15, 0x32, 0xf6, 0x02, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, -0x65, 0x74, 0x65, 0x72, 0xf8, 0x02, 0x10, 0x54, 0x36, 0x02, -0x05, 0x12, 0x00, 0x06, 0x37, 0x00, 0x51, 0x00, 0x66, 0x72, -0x6f, 0x6d, 0x74, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, -0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6a, -0x00, 0x03, 0x4b, 0x05, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, -0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x79, 0x00, 0xb1, 0x3a, -0x00, 0x00, 0x00, 0x2d, 0x00, 0x57, 0x69, 0x64, 0x74, 0x68, -0x84, 0x01, 0x22, 0x48, 0x65, 0x77, 0x06, 0x02, 0xba, 0x03, -0x00, 0x9a, 0x00, 0x00, 0x10, 0x05, 0x70, 0x2d, 0x65, 0x78, -0x70, 0x6c, 0x61, 0x6e, 0x9c, 0x02, 0x21, 0x79, 0x2e, 0x32, -0x00, 0x05, 0x39, 0x02, 0x40, 0x73, 0x6b, 0x00, 0x66, 0xac, -0x01, 0x20, 0x00, 0x6c, 0xc9, 0x04, 0x00, 0xed, 0x06, 0x41, -0x68, 0x75, 0x66, 0x66, 0xa3, 0x04, 0x51, 0x6f, 0x70, 0x65, -0x72, 0x61, 0x7c, 0x00, 0x20, 0x74, 0x6f, 0x34, 0x04, 0x98, -0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, -0x07, 0xe3, 0x2e, 0x00, 0x42, 0x79, 0x00, 0x64, 0x65, 0x66, -0x61, 0x75, 0x6c, 0x74, 0x2c, 0x00, 0xf0, 0x00, 0x02, 0x6d, -0x03, 0x02, 0x4a, 0x00, 0x16, 0x65, 0xae, 0x06, 0x00, 0x38, -0x01, 0x10, 0x75, 0x97, 0x00, 0x42, 0x00, 0x77, 0x61, 0x79, -0x02, 0x05, 0x34, 0x61, 0x6e, 0x79, 0x71, 0x06, 0x11, 0x6d, -0xa0, 0x05, 0xf1, 0x00, 0x73, 0x00, 0x61, 0x62, 0x6f, 0x75, -0x74, 0x00, 0x61, 0x73, 0x00, 0x70, 0x72, 0x6f, 0x62, 0x17, -0x01, 0x21, 0x61, 0x73, 0x28, 0x00, 0x01, 0xa8, 0x05, 0x15, -0x2e, 0xbb, 0x00, 0x82, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, -0x64, 0x65, 0xda, 0x04, 0x93, 0x62, 0x79, 0x00, 0x72, 0x65, -0x71, 0x75, 0x65, 0x73, 0x8b, 0x05, 0x73, 0x70, 0x72, 0x65, -0x63, 0x69, 0x73, 0x65, 0xc5, 0x07, 0x00, 0x82, 0x03, 0x06, -0xd9, 0x00, 0x00, 0x72, 0x02, 0x1c, 0x73, 0xd5, 0x00, 0x71, -0x2e, 0x00, 0x54, 0x79, 0x70, 0x69, 0x63, 0x79, 0x05, 0x10, -0x79, 0xe8, 0x07, 0x31, 0x61, 0x69, 0x6d, 0xe7, 0x07, 0x21, -0x68, 0x65, 0x01, 0x01, 0x10, 0x64, 0xad, 0x01, 0x33, 0x6d, -0x69, 0x6e, 0xf5, 0x03, 0x03, 0x5f, 0x00, 0x3f, 0x73, 0x65, -0x74, 0x5c, 0x00, 0x01, 0x00, 0x8b, 0x01, 0x00, 0x37, 0x06, -0x11, 0x72, 0xe4, 0x05, 0x50, 0x6d, 0x00, 0x65, 0x78, 0x61, -0x8b, 0x03, 0x32, 0x2c, 0x00, 0x73, 0xda, 0x07, 0x01, 0x7f, -0x07, 0x40, 0x61, 0x6e, 0x73, 0x77, 0x49, 0x07, 0x40, 0x73, -0x61, 0x79, 0x29, 0x1a, 0x06, 0x41, 0x6f, 0x75, 0x72, 0x2d, -0x0d, 0x03, 0x04, 0x39, 0x01, 0x03, 0xe0, 0x08, 0x07, 0x19, -0x00, 0x32, 0x6f, 0x6c, 0x75, 0xa6, 0x04, 0x46, 0x4e, 0x6f, -0x74, 0x65, 0x44, 0x06, 0x43, 0x6d, 0x6f, 0x72, 0x65, 0x7a, -0x00, 0x01, 0x59, 0x00, 0x02, 0xd5, 0x01, 0x16, 0x2c, 0x1c, -0x00, 0x40, 0x6c, 0x69, 0x6b, 0x65, 0xca, 0x06, 0x12, 0x74, -0xd2, 0x00, 0x25, 0x61, 0x74, 0x4b, 0x00, 0x76, 0x73, 0x00, -0x73, 0x68, 0x6f, 0x72, 0x74, 0x47, 0x06, 0xf2, 0x00, 0x65, -0x00, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x6c, 0x65, -0x6e, 0x67, 0x74, 0x68, 0xcb, 0x01, 0x01, 0xa6, 0x04, 0x00, -0x97, 0x01, 0x03, 0x35, 0x01, 0x90, 0x6f, 0x73, 0x73, 0x69, -0x62, 0x6c, 0x65, 0x2e, 0x00, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x28, 0x00, 0x00, 0x00, +0x41, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0x73, 0x6c, +0x69, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x74, 0x69, 0x6c, 0x65, +0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x00, 0x76, +0x69, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x69, +0x6d, 0x69, 0x6c, 0x61, 0x72, 0x00, 0x74, 0x6f, 0x00, 0x46, +0x69, 0x66, 0x4f, 0x00, 0x72, 0x00, 0x28, 0x73, 0x65, 0x65, +0x00, 0x63, 0x67, 0x00, 0xf0, 0x23, 0x00, 0x35, 0x29, 0x00, +0x62, 0x75, 0x74, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x61, +0x00, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, +0x00, 0x74, 0x79, 0x70, 0x65, 0x00, 0x6f, 0x66, 0x00, 0x6d, +0x6f, 0x76, 0x65, 0x2e, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, +0x74, 0x69, 0x6d, 0x65, 0x2c, 0x00, 0x74, 0x00, 0xf0, 0x10, +0x65, 0x00, 0x69, 0x73, 0x00, 0x6e, 0x6f, 0x00, 0x68, 0x6f, +0x6c, 0x65, 0x3a, 0x00, 0x61, 0x6c, 0x6c, 0x00, 0x31, 0x36, +0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x00, 0x6f, +0x6e, 0x24, 0x00, 0xf4, 0x07, 0x00, 0x67, 0x72, 0x69, 0x64, +0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x6e, +0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x25, 0x00, 0x61, +0x2e, 0x00, 0x59, 0x6f, 0x75, 0x72, 0x5d, 0x00, 0x00, 0x4b, +0x00, 0xf0, 0x16, 0x74, 0x6f, 0x00, 0x73, 0x68, 0x69, 0x66, +0x74, 0x00, 0x61, 0x6e, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x72, +0x65, 0x00, 0x72, 0x6f, 0x77, 0x00, 0x6c, 0x65, 0x66, 0x74, +0x00, 0x6f, 0x72, 0x00, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2c, +0x0a, 0x00, 0x0c, 0x26, 0x00, 0x90, 0x63, 0x6f, 0x6c, 0x75, +0x6d, 0x6e, 0x00, 0x75, 0x70, 0x1d, 0x00, 0xb1, 0x64, 0x6f, +0x77, 0x6e, 0x3b, 0x00, 0x65, 0x76, 0x65, 0x72, 0x79, 0xac, +0x00, 0xc1, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x64, 0x6f, 0x00, +0x74, 0x68, 0x61, 0x74, 0xb8, 0x00, 0x02, 0x23, 0x01, 0x00, +0x16, 0x00, 0x02, 0x48, 0x00, 0x36, 0x6f, 0x66, 0x66, 0xab, +0x00, 0xd1, 0x72, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, +0x72, 0x73, 0x00, 0x61, 0x74, 0x17, 0x00, 0x02, 0x5f, 0x01, +0x52, 0x65, 0x6e, 0x64, 0x00, 0x6f, 0x28, 0x00, 0x31, 0x73, +0x61, 0x6d, 0x99, 0x00, 0x32, 0x2c, 0x00, 0x69, 0xe4, 0x00, +0x42, 0x73, 0x70, 0x61, 0x63, 0x51, 0x00, 0xf5, 0x0e, 0x6a, +0x75, 0x73, 0x74, 0x00, 0x76, 0x61, 0x63, 0x61, 0x74, 0x65, +0x64, 0x2e, 0x00, 0x54, 0x6f, 0x00, 0x77, 0x69, 0x6e, 0x2c, +0x00, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x7c, 0x00, +0x60, 0x73, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x0e, 0x01, 0xf4, +0x06, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x6f, 0x72, +0x64, 0x65, 0x72, 0x00, 0x28, 0x31, 0x2c, 0x32, 0x2c, 0x33, +0x2c, 0x34, 0x3b, 0x01, 0x32, 0x74, 0x6f, 0x70, 0x67, 0x00, +0xb4, 0x31, 0x33, 0x2c, 0x31, 0x34, 0x2c, 0x31, 0x35, 0x2c, +0x31, 0x36, 0x1c, 0x00, 0xd0, 0x62, 0x6f, 0x74, 0x74, 0x6f, +0x6d, 0x29, 0x2e, 0x00, 0x57, 0x68, 0x65, 0x6e, 0x7b, 0x00, +0x84, 0x27, 0x76, 0x65, 0x00, 0x64, 0x6f, 0x6e, 0x65, 0xe7, +0x00, 0x70, 0x72, 0x79, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x12, +0x02, 0x27, 0x6f, 0x6e, 0xd1, 0x01, 0x30, 0x73, 0x69, 0x7a, +0x9d, 0x01, 0x11, 0x66, 0xee, 0x00, 0x70, 0x2e, 0x00, 0x00, +0x00, 0x49, 0x00, 0x6d, 0x58, 0x01, 0x30, 0x00, 0x68, 0x61, +0x85, 0x01, 0x90, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x64, +0x00, 0x74, 0xea, 0x01, 0x10, 0x67, 0xe9, 0x00, 0x60, 0x6d, +0x79, 0x73, 0x65, 0x6c, 0x66, 0x39, 0x01, 0xf0, 0x03, 0x6f, +0x75, 0x67, 0x68, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x62, +0x79, 0x00, 0x61, 0x63, 0x63, 0x69, 0x64, 0x51, 0x00, 0xf4, +0x03, 0x69, 0x66, 0x00, 0x73, 0x6f, 0x00, 0x28, 0x61, 0x6e, +0x64, 0x00, 0x49, 0x27, 0x6d, 0x00, 0x73, 0x75, 0x72, 0x33, +0x01, 0x64, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x59, 0x00, +0x50, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x32, 0x00, 0x26, 0x6c, +0x79, 0x67, 0x00, 0x63, 0x69, 0x74, 0x29, 0x2e, 0x00, 0x49, +0x5c, 0x00, 0xe0, 0x74, 0x00, 0x49, 0x00, 0x77, 0x61, 0x73, +0x00, 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0xba, 0x00, 0xf1, +0x08, 0x61, 0x00, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, +0x61, 0x76, 0x65, 0x72, 0x00, 0x49, 0x27, 0x64, 0x00, 0x73, +0x65, 0x65, 0x6e, 0x2c, 0xab, 0x02, 0x12, 0x49, 0x59, 0x00, +0x61, 0x61, 0x00, 0x66, 0x65, 0x65, 0x6c, 0xf9, 0x02, 0x13, +0x68, 0xb1, 0x01, 0x08, 0x34, 0x00, 0x02, 0xdc, 0x00, 0x32, +0x61, 0x63, 0x74, 0x07, 0x03, 0x01, 0x33, 0x00, 0x10, 0x62, +0xfe, 0x02, 0x14, 0x61, 0x08, 0x03, 0x11, 0x2d, 0xe3, 0x02, +0x02, 0x31, 0x03, 0x31, 0x00, 0x72, 0x61, 0xba, 0x00, 0x42, +0x74, 0x68, 0x61, 0x6e, 0x03, 0x01, 0x20, 0x73, 0x6c, 0x41, +0x00, 0x27, 0x6c, 0x79, 0x42, 0x01, 0x82, 0x6b, 0x69, 0x6e, +0x64, 0x2e, 0x00, 0x53, 0x6f, 0x21, 0x00, 0x02, 0x61, 0x00, +0x12, 0x62, 0xdd, 0x01, 0x02, 0x80, 0x01, 0x00, 0x8d, 0x00, +0x54, 0x69, 0x6e, 0x00, 0x6d, 0x79, 0x56, 0x00, 0xf2, 0x19, +0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, +0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x72, 0x65, 0x70, +0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x63, 0x72, +0x65, 0x61, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x00, 0x6f, +0x34, 0x00, 0x39, 0x61, 0x72, 0x74, 0x88, 0x00, 0x01, 0x54, +0x02, 0xb0, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, +0x69, 0x6e, 0x67, 0xb5, 0x01, 0x35, 0x36, 0x2e, 0x31, 0x17, +0x04, 0x00, 0x5d, 0x03, 0xf3, 0x03, 0x72, 0x6f, 0x6c, 0x73, +0x20, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, +0x6c, 0x69, 0x63, 0x6b, 0xf9, 0x01, 0x20, 0x61, 0x6e, 0x7e, +0x02, 0x72, 0x6f, 0x77, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x69, +0x03, 0x00, 0xa9, 0x00, 0xa2, 0x61, 0x70, 0x70, 0x72, 0x6f, +0x70, 0x72, 0x69, 0x61, 0x74, 0x63, 0x03, 0x24, 0x6f, 0x72, +0x44, 0x03, 0x03, 0xd3, 0x02, 0x33, 0x64, 0x69, 0x72, 0xb2, +0x00, 0x43, 0x69, 0x6e, 0x64, 0x69, 0xd0, 0x02, 0x10, 0x52, +0xec, 0x00, 0x06, 0x5f, 0x00, 0x06, 0x53, 0x00, 0x24, 0x69, +0x74, 0x38, 0x00, 0x77, 0x6f, 0x70, 0x70, 0x6f, 0x73, 0x69, +0x74, 0x41, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x41, 0x6c, 0x74, +0x65, 0x72, 0x6e, 0xe8, 0x00, 0x72, 0x65, 0x6c, 0x79, 0x2c, +0x00, 0x75, 0x73, 0x86, 0x00, 0xa1, 0x63, 0x75, 0x72, 0x73, +0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0xfc, 0x03, 0x05, 0x9e, +0x00, 0x01, 0x43, 0x00, 0x07, 0x7c, 0x00, 0x91, 0x6f, 0x72, +0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x1e, 0x00, 0x31, +0x65, 0x64, 0x67, 0x93, 0x04, 0x04, 0xb3, 0x03, 0x20, 0x2c, +0x00, 0x7c, 0x02, 0x04, 0x54, 0x00, 0x60, 0x72, 0x65, 0x74, +0x75, 0x72, 0x6e, 0x54, 0x00, 0x09, 0x53, 0x00, 0x4f, 0x72, +0x6f, 0x77, 0x2f, 0xe2, 0x00, 0x10, 0x10, 0x00, 0x91, 0x04, +0x20, 0x00, 0x63, 0x36, 0x01, 0x27, 0x6c, 0x73, 0x3f, 0x00, +0x02, 0xb6, 0x03, 0x02, 0x33, 0x00, 0x79, 0x6c, 0x79, 0x2e, +0x00, 0x4d, 0x6f, 0x76, 0xc3, 0x00, 0x10, 0x6f, 0xd0, 0x03, +0x11, 0x61, 0x27, 0x00, 0x10, 0x2c, 0x0f, 0x05, 0x32, 0x64, +0x00, 0x43, 0x96, 0x01, 0x01, 0x9c, 0x00, 0x00, 0xed, 0x01, +0x16, 0x73, 0x8b, 0x01, 0x0c, 0x9c, 0x00, 0x01, 0x8f, 0x04, +0x20, 0x75, 0x6e, 0x03, 0x04, 0x07, 0x53, 0x00, 0x00, 0x39, +0x00, 0x1b, 0x6d, 0x67, 0x00, 0x52, 0x61, 0x6c, 0x6f, 0x6e, +0x67, 0xa5, 0x05, 0x04, 0x39, 0x00, 0x43, 0x2e, 0x00, 0x4f, +0x72, 0x73, 0x00, 0x11, 0x53, 0xce, 0x04, 0x04, 0x5a, 0x00, +0x01, 0xa9, 0x03, 0x06, 0x26, 0x00, 0x10, 0x50, 0x84, 0x00, +0x00, 0xb6, 0x01, 0x20, 0x45, 0x6e, 0xf0, 0x05, 0x91, 0x73, +0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x3b, 0x00, +0x00, 0x18, 0x00, 0x00, 0x37, 0x05, 0x05, 0xb6, 0x00, 0x12, +0x28, 0xb3, 0x00, 0x02, 0x2c, 0x00, 0x20, 0x61, 0x67, 0xbc, +0x05, 0xc0, 0x74, 0x6f, 0x00, 0x72, 0x65, 0x6c, 0x65, 0x61, +0x73, 0x65, 0x29, 0x2c, 0xc7, 0x02, 0x00, 0x66, 0x06, 0x04, +0x54, 0x00, 0x11, 0x53, 0x01, 0x05, 0x0f, 0x54, 0x00, 0x04, +0x01, 0x65, 0x05, 0x00, 0x5b, 0x01, 0x42, 0x28, 0x41, 0x6c, +0x6c, 0x7e, 0x02, 0x01, 0x78, 0x01, 0x90, 0x73, 0x00, 0x64, +0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x08, 0x04, 0x33, 0x6e, +0x00, 0x73, 0x8e, 0x01, 0x72, 0x32, 0x2e, 0x31, 0x00, 0x61, +0x72, 0x65, 0x81, 0x01, 0xb1, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xf6, 0x02, 0x15, 0x32, +0xf6, 0x02, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0xf8, 0x02, 0x10, 0x54, 0x36, 0x02, 0x05, 0x12, +0x00, 0x06, 0x37, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, +0x74, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6a, 0x00, 0x03, +0x4b, 0x05, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x75, 0x79, 0x00, 0xb1, 0x3a, 0x00, 0x00, +0x00, 0x2d, 0x00, 0x57, 0x69, 0x64, 0x74, 0x68, 0x84, 0x01, +0x22, 0x48, 0x65, 0x77, 0x06, 0x02, 0xba, 0x03, 0x00, 0x9a, +0x00, 0x00, 0x10, 0x05, 0x70, 0x2d, 0x65, 0x78, 0x70, 0x6c, +0x61, 0x6e, 0x9c, 0x02, 0x21, 0x79, 0x2e, 0x32, 0x00, 0x05, +0x39, 0x02, 0x40, 0x73, 0x6b, 0x00, 0x66, 0xac, 0x01, 0x20, +0x00, 0x6c, 0xc9, 0x04, 0x00, 0xed, 0x06, 0x41, 0x68, 0x75, +0x66, 0x66, 0xa3, 0x04, 0x51, 0x6f, 0x70, 0x65, 0x72, 0x61, +0x7c, 0x00, 0x20, 0x74, 0x6f, 0x34, 0x04, 0x98, 0x70, 0x65, +0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x07, 0xe3, +0x2e, 0x00, 0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, +0x6c, 0x74, 0x2c, 0x00, 0xf0, 0x00, 0x02, 0x6d, 0x03, 0x02, +0x4a, 0x00, 0x16, 0x65, 0xae, 0x06, 0x00, 0x38, 0x01, 0x10, +0x75, 0x97, 0x00, 0x42, 0x00, 0x77, 0x61, 0x79, 0x02, 0x05, +0x34, 0x61, 0x6e, 0x79, 0x71, 0x06, 0x11, 0x6d, 0xa0, 0x05, +0xf1, 0x00, 0x73, 0x00, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x00, +0x61, 0x73, 0x00, 0x70, 0x72, 0x6f, 0x62, 0x17, 0x01, 0x21, +0x61, 0x73, 0x28, 0x00, 0x01, 0xa8, 0x05, 0x15, 0x2e, 0xbb, +0x00, 0x82, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, +0xda, 0x04, 0x93, 0x62, 0x79, 0x00, 0x72, 0x65, 0x71, 0x75, +0x65, 0x73, 0x8b, 0x05, 0x73, 0x70, 0x72, 0x65, 0x63, 0x69, +0x73, 0x65, 0xc5, 0x07, 0x00, 0x82, 0x03, 0x06, 0xd9, 0x00, +0x00, 0x72, 0x02, 0x1c, 0x73, 0xd5, 0x00, 0x71, 0x2e, 0x00, +0x54, 0x79, 0x70, 0x69, 0x63, 0x79, 0x05, 0x10, 0x79, 0xe8, +0x07, 0x31, 0x61, 0x69, 0x6d, 0xe7, 0x07, 0x21, 0x68, 0x65, +0x01, 0x01, 0x10, 0x64, 0xad, 0x01, 0x33, 0x6d, 0x69, 0x6e, +0xf5, 0x03, 0x03, 0x5f, 0x00, 0x3f, 0x73, 0x65, 0x74, 0x5c, +0x00, 0x01, 0x00, 0x8b, 0x01, 0x00, 0x37, 0x06, 0x11, 0x72, +0xe4, 0x05, 0x50, 0x6d, 0x00, 0x65, 0x78, 0x61, 0x8b, 0x03, +0x32, 0x2c, 0x00, 0x73, 0xda, 0x07, 0x01, 0x7f, 0x07, 0x40, +0x61, 0x6e, 0x73, 0x77, 0x49, 0x07, 0x40, 0x73, 0x61, 0x79, +0x29, 0x1a, 0x06, 0x41, 0x6f, 0x75, 0x72, 0x2d, 0x0d, 0x03, +0x04, 0x39, 0x01, 0x03, 0xe0, 0x08, 0x07, 0x19, 0x00, 0x32, +0x6f, 0x6c, 0x75, 0xa6, 0x04, 0x46, 0x4e, 0x6f, 0x74, 0x65, +0x44, 0x06, 0x43, 0x6d, 0x6f, 0x72, 0x65, 0x7a, 0x00, 0x01, +0x59, 0x00, 0x02, 0xd5, 0x01, 0x16, 0x2c, 0x1c, 0x00, 0x40, +0x6c, 0x69, 0x6b, 0x65, 0xca, 0x06, 0x12, 0x74, 0xd2, 0x00, +0x25, 0x61, 0x74, 0x4b, 0x00, 0x76, 0x73, 0x00, 0x73, 0x68, +0x6f, 0x72, 0x74, 0x47, 0x06, 0xf2, 0x00, 0x65, 0x00, 0x74, +0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x6c, 0x65, 0x6e, 0x67, +0x74, 0x68, 0xcb, 0x01, 0x01, 0xa6, 0x04, 0x00, 0x97, 0x01, +0x03, 0x35, 0x01, 0x90, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, +0x65, 0x2e, 0x00, }; -const unsigned short help_text_len = 2534; -const unsigned short help_text_words = 453; +const unsigned short help_text_len = 2553; +const unsigned short help_text_words = 454; const char quick_help_text[] = "Slide a row at a time to arrange the tiles into order."; diff --git a/apps/plugins/puzzles/help/slant.c b/apps/plugins/puzzles/help/slant.c index ad4363825e..1a8168fb3b 100644 --- a/apps/plugins/puzzles/help/slant.c +++ b/apps/plugins/puzzles/help/slant.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,184 +6,197 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 125, TEXT_CENTER | C_RED }, - { 328, TEXT_CENTER | C_RED }, - { 345, TEXT_UNDERLINE }, + { 126, TEXT_CENTER | C_RED }, + { 329, TEXT_CENTER | C_RED }, { 346, TEXT_UNDERLINE }, - { 356, TEXT_UNDERLINE }, - { 379, TEXT_UNDERLINE }, + { 347, TEXT_UNDERLINE }, + { 357, TEXT_UNDERLINE }, + { 380, TEXT_UNDERLINE }, + { 447, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 2378 comp 1650 ratio 0.69386 level 10 saved 728 */ +/* orig 2582 comp 1767 ratio 0.684353 level 10 saved 815 */ const char help_text[] = { -0xf0, 0x21, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x30, 0x3a, 0x20, 0x53, 0x6c, 0x61, 0x6e, 0x74, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, -0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, -0x1c, 0x00, 0xf3, 0x1e, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, -0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x64, 0x72, 0x61, 0x77, -0x00, 0x61, 0x00, 0x64, 0x69, 0x61, 0x67, 0x6f, 0x6e, 0x61, -0x6c, 0x00, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0x74, 0x68, 0x72, -0x6f, 0x75, 0x67, 0x68, 0x00, 0x65, 0x61, 0x63, 0x68, 0x3a, -0x00, 0xf2, 0x07, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x63, -0x68, 0x6f, 0x6f, 0x73, 0x65, 0x00, 0x77, 0x68, 0x69, 0x63, -0x68, 0x00, 0x77, 0x61, 0x79, 0x22, 0x00, 0x01, 0x34, 0x00, -0x10, 0x73, 0x7d, 0x00, 0xfa, 0x24, 0x73, 0x00, 0x73, 0x6f, -0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x74, 0x68, 0x65, 0x00, -0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x00, -0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, -0x00, 0x61, 0x72, 0x65, 0x00, 0x6d, 0x65, 0x74, 0x3a, 0x00, -0x00, 0x00, 0x2d, 0x00, 0x54, 0x68, 0x65, 0x7b, 0x00, 0xf1, -0x05, 0x73, 0x00, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x00, 0x66, -0x6f, 0x72, 0x6d, 0x00, 0x61, 0x00, 0x6c, 0x6f, 0x6f, 0x70, -0x2e, 0x2a, 0x00, 0xf2, 0x1e, 0x41, 0x6e, 0x79, 0x00, 0x70, -0x6f, 0x69, 0x6e, 0x74, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, -0x61, 0x00, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x64, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x68, 0x61, 0x73, -0x00, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x6c, 0x79, -0x83, 0x00, 0x43, 0x6d, 0x61, 0x6e, 0x79, 0x55, 0x00, 0x40, -0x6d, 0x65, 0x65, 0x74, 0x88, 0x00, 0xf1, 0x02, 0x61, 0x74, -0x00, 0x69, 0x74, 0x2e, 0x00, 0x28, 0x54, 0x68, 0x75, 0x73, -0x2c, 0x00, 0x61, 0x00, 0x34, 0x06, 0x01, 0x90, 0x68, 0x65, -0x00, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x29, 0x01, 0xfe, -0x0e, 0x61, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0x73, -0x68, 0x61, 0x70, 0x65, 0x2c, 0x00, 0x77, 0x68, 0x65, 0x72, -0x65, 0x61, 0x73, 0x00, 0x61, 0x00, 0x7a, 0x65, 0x72, 0x6f, -0x2f, 0x00, 0x01, 0x3b, 0x01, 0x42, 0x6d, 0x6f, 0x6e, 0x64, -0x31, 0x00, 0xc0, 0x00, 0x2d, 0x00, 0x6f, 0x72, 0x00, 0x72, -0x61, 0x74, 0x68, 0x65, 0x72, 0x61, 0x00, 0x7a, 0x70, 0x61, -0x72, 0x74, 0x69, 0x61, 0x6c, 0x25, 0x00, 0x94, 0x2c, 0x00, -0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x56, 0x00, 0x33, -0x63, 0x61, 0x6e, 0xf8, 0x00, 0x91, 0x61, 0x70, 0x70, 0x65, -0x61, 0x72, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x51, 0x6d, 0x69, -0x64, 0x64, 0x6c, 0x67, 0x00, 0x00, 0x0e, 0x00, 0x01, 0xcb, -0x01, 0x04, 0x3a, 0x00, 0x01, 0xe2, 0x00, 0xe0, 0x77, 0x6f, -0x75, 0x6c, 0x64, 0x00, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, -0x61, 0x74, 0xf9, 0x00, 0x04, 0x57, 0x00, 0x01, 0x39, 0x01, -0xa0, 0x29, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x64, 0x69, -0x74, 0x50, 0x01, 0xf1, 0x01, 0x00, 0x74, 0x68, 0x69, 0x73, -0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, -0x65, 0xff, 0x01, 0xa0, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, -0x00, 0x5b, 0x38, 0x5d, 0x67, 0x01, 0xf1, 0x01, 0x5b, 0x38, -0x5d, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, -0x77, 0x77, 0x2e, 0x6e, 0x1d, 0x00, 0xa2, 0x2e, 0x63, 0x6f, -0x2e, 0x6a, 0x70, 0x2f, 0x6a, 0x61, 0x2f, 0x3c, 0x00, 0xf0, -0x0e, 0x73, 0x2f, 0x67, 0x6f, 0x6b, 0x69, 0x67, 0x65, 0x6e, -0x5f, 0x6e, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x28, 0x69, -0x6e, 0x00, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, -0x73, 0x00, 0x43, 0x32, 0x30, 0x2e, 0x31, 0x8c, 0x02, 0x80, -0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x95, 0x02, -0xa0, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, -0x6b, 0x8a, 0x01, 0xa3, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x62, -0x6c, 0x61, 0x6e, 0x6b, 0x61, 0x02, 0xa0, 0x00, 0x77, 0x69, -0x6c, 0x6c, 0x00, 0x70, 0x6c, 0x61, 0x63, 0xc0, 0x00, 0x10, -0x5c, 0x21, 0x00, 0x52, 0x69, 0x74, 0x00, 0x28, 0x61, 0x5e, +0x00, 0x2d, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x73, 0x2e, 0x1c, 0x00, 0xf3, 0x1e, +0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, +0x6f, 0x00, 0x64, 0x72, 0x61, 0x77, 0x00, 0x61, 0x00, 0x64, +0x69, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x6c, 0x69, +0x6e, 0x65, 0x00, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, +0x00, 0x65, 0x61, 0x63, 0x68, 0x3a, 0x00, 0xf2, 0x07, 0x2c, +0x00, 0x61, 0x6e, 0x64, 0x00, 0x63, 0x68, 0x6f, 0x6f, 0x73, +0x65, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x77, 0x61, +0x79, 0x22, 0x00, 0x01, 0x34, 0x00, 0x10, 0x73, 0x8f, 0x00, +0xfa, 0x24, 0x73, 0x00, 0x73, 0x6f, 0x00, 0x74, 0x68, 0x61, +0x74, 0x00, 0x74, 0x68, 0x65, 0x00, 0x66, 0x6f, 0x6c, 0x6c, +0x6f, 0x77, 0x69, 0x6e, 0x67, 0x00, 0x63, 0x6f, 0x6e, 0x64, +0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x61, 0x72, 0x65, +0x00, 0x6d, 0x65, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, +0x54, 0x68, 0x65, 0x7b, 0x00, 0xf1, 0x05, 0x73, 0x00, 0x6e, +0x65, 0x76, 0x65, 0x72, 0x00, 0x66, 0x6f, 0x72, 0x6d, 0x00, +0x61, 0x00, 0x6c, 0x6f, 0x6f, 0x70, 0x2e, 0x2a, 0x00, 0xf2, +0x1e, 0x41, 0x6e, 0x79, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, +0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x61, 0x00, 0x63, 0x69, +0x72, 0x63, 0x6c, 0x65, 0x64, 0x00, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0x00, 0x68, 0x61, 0x73, 0x00, 0x70, 0x72, 0x65, +0x63, 0x69, 0x73, 0x65, 0x6c, 0x79, 0x83, 0x00, 0x43, 0x6d, +0x61, 0x6e, 0x79, 0x55, 0x00, 0x40, 0x6d, 0x65, 0x65, 0x74, +0x88, 0x00, 0xf1, 0x02, 0x61, 0x74, 0x00, 0x69, 0x74, 0x2e, +0x00, 0x28, 0x54, 0x68, 0x75, 0x73, 0x2c, 0x00, 0x61, 0x00, +0x34, 0x06, 0x01, 0x90, 0x68, 0x65, 0x00, 0x63, 0x65, 0x6e, +0x74, 0x72, 0x65, 0x29, 0x01, 0xfe, 0x0e, 0x61, 0x00, 0x63, +0x72, 0x6f, 0x73, 0x73, 0x00, 0x73, 0x68, 0x61, 0x70, 0x65, +0x2c, 0x00, 0x77, 0x68, 0x65, 0x72, 0x65, 0x61, 0x73, 0x00, +0x61, 0x00, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x00, 0x01, 0x3b, +0x01, 0x42, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x00, 0xc0, 0x00, +0x2d, 0x00, 0x6f, 0x72, 0x00, 0x72, 0x61, 0x74, 0x68, 0x65, +0x72, 0x61, 0x00, 0x7a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, +0x6c, 0x25, 0x00, 0x94, 0x2c, 0x00, 0x62, 0x65, 0x63, 0x61, +0x75, 0x73, 0x65, 0x56, 0x00, 0x33, 0x63, 0x61, 0x6e, 0xf8, +0x00, 0x91, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x00, 0x69, +0x6e, 0x67, 0x00, 0x51, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x67, +0x00, 0x00, 0x0e, 0x00, 0x01, 0xcb, 0x01, 0x04, 0x3a, 0x00, +0x01, 0xe2, 0x00, 0xe0, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, +0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0xf9, 0x00, +0x04, 0x57, 0x00, 0x01, 0x39, 0x01, 0xa0, 0x29, 0x00, 0x00, +0x00, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x50, 0x01, 0xf1, +0x01, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, +0x7a, 0x6c, 0x65, 0x00, 0x67, 0x6f, 0x65, 0xff, 0x01, 0xa0, +0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, 0x38, 0x5d, +0x67, 0x01, 0xf1, 0x02, 0x5b, 0x38, 0x5d, 0x00, 0x68, 0x74, +0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, +0x6e, 0x1e, 0x00, 0xa2, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, +0x2f, 0x6a, 0x61, 0x2f, 0x3d, 0x00, 0xf0, 0x0f, 0x73, 0x2f, +0x67, 0x6f, 0x6b, 0x69, 0x67, 0x65, 0x6e, 0x5f, 0x6e, 0x61, +0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x00, 0x28, 0x69, 0x6e, 0x00, +0x4a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x75, 0x00, +0x43, 0x32, 0x30, 0x2e, 0x31, 0xa0, 0x02, 0xf0, 0x07, 0x63, +0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, +0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0x8c, 0x01, 0xa3, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x62, +0x6c, 0x61, 0x6e, 0x6b, 0x63, 0x02, 0xa0, 0x00, 0x77, 0x69, +0x6c, 0x6c, 0x00, 0x70, 0x6c, 0x61, 0x63, 0xc2, 0x00, 0x10, +0x5c, 0x21, 0x00, 0x52, 0x69, 0x74, 0x00, 0x28, 0x61, 0x60, 0x02, 0x40, 0x6c, 0x65, 0x61, 0x6e, 0x37, 0x00, 0x10, 0x74, -0x5f, 0x02, 0x00, 0x0f, 0x00, 0xc1, 0x66, 0x74, 0x2c, 0x00, +0x61, 0x02, 0x00, 0x0f, 0x00, 0xc1, 0x66, 0x74, 0x2c, 0x00, 0x69, 0x2e, 0x65, 0x2e, 0x00, 0x72, 0x75, 0x6e, 0x1a, 0x00, 0x41, 0x66, 0x72, 0x6f, 0x6d, 0x1c, 0x00, 0x31, 0x74, 0x6f, -0x70, 0x20, 0x00, 0x04, 0x37, 0x01, 0x03, 0x5f, 0x00, 0x03, +0x70, 0x20, 0x00, 0x04, 0x39, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x3a, 0x00, 0xf0, 0x01, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x00, 0x72, 0x69, 0x67, 0x68, 0x74, 0x29, 0x2e, 0x00, 0x52, 0x08, 0x00, 0x0f, 0x96, 0x00, 0x16, 0x14, 0x2f, 0x96, 0x00, 0x0b, 0x8f, 0x00, 0x01, 0x4e, 0x00, 0x1b, 0x2c, 0x8b, 0x00, 0x22, 0x6f, 0x70, 0x18, 0x00, 0x00, 0x25, 0x00, 0x03, 0x76, -0x00, 0x00, 0x97, 0x00, 0x20, 0x29, 0x2e, 0x96, 0x01, 0x63, +0x00, 0x00, 0x97, 0x00, 0x20, 0x29, 0x2e, 0x98, 0x01, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x43, 0x00, 0x01, 0x7f, -0x00, 0x30, 0x00, 0x65, 0x69, 0x35, 0x02, 0x72, 0x00, 0x62, +0x00, 0x30, 0x00, 0x65, 0x69, 0x37, 0x02, 0x72, 0x00, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x78, 0x00, 0xd2, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0xdd, 0x00, 0xc5, 0x68, 0x72, 0x65, 0x65, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0xdc, 0x00, 0x00, 0x67, -0x01, 0x62, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x00, 0xd9, 0x02, +0x01, 0x62, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x00, 0xdb, 0x02, 0x85, 0x69, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6c, 0x72, 0x01, 0xbe, 0x00, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x6c, 0x79, 0xe4, 0x00, 0x00, 0xd2, 0x00, 0x02, 0x6f, 0x00, 0x52, 0x68, 0x61, 0x6e, 0x67, 0x65, 0xbf, 0x00, 0x02, 0x21, 0x00, 0x40, 0x74, 0x6f, 0x00, 0x5c, 0x05, 0x00, 0x51, 0x2f, 0x00, 0x62, 0x61, 0x63, 0x0f, 0x00, 0x01, 0x18, 0x00, -0x02, 0x0d, 0x04, 0x03, 0x66, 0x00, 0x01, 0xe5, 0x00, 0x0e, +0x02, 0x0f, 0x04, 0x03, 0x66, 0x00, 0x01, 0xe5, 0x00, 0x0e, 0x67, 0x00, 0x07, 0x7b, 0x01, 0x0f, 0x5d, 0x00, 0x07, 0x12, -0x2f, 0x62, 0x00, 0x09, 0x5d, 0x00, 0x01, 0x9f, 0x03, 0x50, -0x65, 0x72, 0x65, 0x66, 0x6f, 0x76, 0x04, 0x00, 0x62, 0x00, -0x00, 0x1f, 0x03, 0x42, 0x70, 0x6c, 0x61, 0x79, 0x06, 0x03, -0x00, 0x73, 0x02, 0x50, 0x65, 0x6e, 0x74, 0x69, 0x72, 0xf0, -0x02, 0x01, 0x0d, 0x04, 0x34, 0x6f, 0x6e, 0x65, 0x37, 0x01, -0x03, 0x94, 0x00, 0x71, 0x6e, 0x65, 0x65, 0x64, 0x00, 0x74, -0x6f, 0x02, 0x03, 0x13, 0x59, 0x42, 0x00, 0x52, 0x61, 0x6c, -0x73, 0x6f, 0x00, 0x3b, 0x03, 0xc1, 0x65, 0x00, 0x63, 0x75, -0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x07, 0x03, -0x20, 0x6d, 0x6f, 0x2d, 0x05, 0x55, 0x72, 0x6f, 0x75, 0x6e, -0x64, 0x6b, 0x03, 0x71, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, -0x73, 0xa4, 0x01, 0x00, 0xe4, 0x01, 0x50, 0x65, 0x74, 0x75, -0x72, 0x6e, 0xde, 0x03, 0x20, 0x73, 0x70, 0x0e, 0x02, 0x01, -0x3b, 0x00, 0x0b, 0xb4, 0x02, 0x20, 0x6f, 0x72, 0x25, 0x02, -0xe2, 0x2c, 0x00, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, -0x69, 0x76, 0x65, 0x6c, 0x79, 0x2c, 0x01, 0x01, 0x29, 0x00, -0x43, 0x74, 0x68, 0x65, 0x6e, 0xd4, 0x01, 0x50, 0x74, 0x68, -0x65, 0x6d, 0x00, 0x57, 0x04, 0x5a, 0x62, 0x6f, 0x76, 0x65, -0x2e, 0xa4, 0x00, 0x10, 0x70, 0x77, 0x00, 0x20, 0x00, 0x2f, -0x4e, 0x00, 0x01, 0x7d, 0x01, 0x06, 0x7e, 0x02, 0x00, 0x12, -0x00, 0x0c, 0x5e, 0x00, 0xa1, 0x69, 0x6e, 0x64, 0x65, 0x70, -0x65, 0x6e, 0x64, 0x65, 0x6e, 0xf2, 0x02, 0x20, 0x77, 0x68, -0xe4, 0x04, 0x81, 0x73, 0x00, 0x61, 0x6c, 0x72, 0x65, 0x61, -0x64, 0xee, 0x01, 0x07, 0xf0, 0x00, 0x02, 0x91, 0x01, 0x62, -0x2e, 0x00, 0x42, 0x61, 0x63, 0x6b, 0xc7, 0x00, 0x20, 0x72, -0x65, 0xfc, 0x00, 0x24, 0x73, 0x00, 0x2c, 0x05, 0x06, 0x48, -0x03, 0x0b, 0x33, 0x00, 0x42, 0x00, 0x00, 0x28, 0x41, 0xc4, -0x00, 0x32, 0x00, 0x61, 0x63, 0xcb, 0x05, 0x90, 0x64, 0x65, -0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x66, 0x00, 0x21, -0x73, 0x65, 0x16, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, 0xe4, -0x05, 0x01, 0xcb, 0x00, 0xa3, 0x61, 0x76, 0x61, 0x69, 0x6c, -0x61, 0x62, 0x6c, 0x65, 0x2e, 0x19, 0x04, 0x13, 0x32, 0x19, -0x04, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, -0x72, 0x1b, 0x04, 0x66, 0x54, 0x68, 0x65, 0x73, 0x65, 0x00, -0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x06, 0x93, -0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, -0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x22, 0x6f, -0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0xab, 0x00, 0x91, 0x57, 0x69, 0x64, -0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x81, 0x03, 0x51, 0x00, -0x00, 0x53, 0x69, 0x7a, 0x47, 0x05, 0x01, 0x43, 0x05, 0x26, -0x69, 0x6e, 0x0e, 0x07, 0xc3, 0x00, 0x00, 0x44, 0x69, 0x66, -0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x98, 0x03, 0x00, -0xb0, 0x04, 0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x04, -0x82, 0x05, 0x40, 0x65, 0x6e, 0x65, 0x72, 0xe0, 0x02, 0x03, -0x47, 0x05, 0xf2, 0x00, 0x2e, 0x00, 0x41, 0x74, 0x00, 0x48, -0x61, 0x72, 0x64, 0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0xae, -0x02, 0x20, 0x61, 0x72, 0x56, 0x01, 0x61, 0x71, 0x75, 0x69, -0x72, 0x65, 0x64, 0x62, 0x07, 0x63, 0x6f, 0x00, 0x64, 0x65, -0x64, 0x75, 0x34, 0x01, 0x50, 0x62, 0x61, 0x73, 0x65, 0x64, -0xb6, 0x00, 0x81, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, -0x67, 0x98, 0x00, 0x41, 0x72, 0x65, 0x6c, 0x61, 0x20, 0x00, -0x45, 0x68, 0x69, 0x70, 0x73, 0xf1, 0x03, 0x03, 0xa6, 0x00, -0x03, 0x4f, 0x06, 0x00, 0xf3, 0x05, 0x00, 0x22, 0x02, 0x30, -0x77, 0x61, 0x79, 0x23, 0x00, 0x01, 0xcf, 0x06, 0x10, 0x62, -0x4b, 0x02, 0x03, 0x60, 0x00, 0x02, 0xd9, 0x02, 0x55, 0x65, -0x78, 0x61, 0x63, 0x74, 0x11, 0x04, 0x00, 0x5c, 0x00, 0x25, -0x6f, 0x6e, 0x89, 0x03, 0xf0, 0x00, 0x61, 0x74, 0x00, 0x61, -0x00, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x00, 0x28, 0x46, 0x6f, -0x72, 0x2d, 0x00, 0x33, 0x6d, 0x70, 0x6c, 0x66, 0x03, 0x11, -0x6d, 0x2c, 0x01, 0x00, 0x97, 0x00, 0x03, 0xc2, 0x07, 0x25, -0x77, 0x6f, 0x82, 0x00, 0x01, 0xdd, 0x07, 0x04, 0x4c, 0x02, -0x30, 0x73, 0x61, 0x6d, 0x1d, 0x01, 0x12, 0x72, 0xf1, 0x01, -0x55, 0x2c, 0x00, 0x65, 0x76, 0x65, 0x79, 0x03, 0x83, 0x64, -0x6f, 0x6e, 0x27, 0x74, 0x00, 0x79, 0x65, 0x49, 0x00, 0x01, -0x8e, 0x02, 0x01, 0x4e, 0x00, 0x05, 0x30, 0x00, 0x32, 0x00, -0x69, 0x73, 0x13, 0x03, 0x01, 0x8f, 0x06, 0x02, 0x75, 0x00, -0x21, 0x65, 0x6e, 0xca, 0x00, 0x00, 0x41, 0x00, 0x06, 0xce, -0x00, 0x62, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0xe7, 0x00, -0x60, 0x6f, 0x75, 0x74, 0x00, 0x73, 0x74, 0x44, 0x03, 0x11, -0x6f, 0x0b, 0x01, 0x04, 0xc0, 0x01, 0x30, 0x29, 0x00, 0x45, -0x7d, 0x00, 0x1a, 0x61, 0x86, 0x01, 0x91, 0x67, 0x75, 0x65, -0x73, 0x73, 0x77, 0x6f, 0x72, 0x6b, 0x68, 0x00, 0x00, 0x5d, -0x04, 0x32, 0x74, 0x72, 0x61, 0xe1, 0x05, 0x21, 0x73, 0x68, -0x33, 0x07, 0x02, 0x6d, 0x07, 0xe0, 0x62, 0x65, 0x00, 0x6e, -0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x2e, 0x00, +0x2f, 0x62, 0x00, 0x09, 0x5d, 0x00, 0x01, 0xa1, 0x03, 0x50, +0x65, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x04, 0x00, 0x62, 0x00, +0x00, 0x21, 0x03, 0x42, 0x70, 0x6c, 0x61, 0x79, 0x08, 0x03, +0x90, 0x61, 0x6d, 0x65, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x72, +0xf2, 0x02, 0x01, 0x0f, 0x04, 0x34, 0x6f, 0x6e, 0x65, 0x37, +0x01, 0x03, 0x94, 0x00, 0x71, 0x6e, 0x65, 0x65, 0x64, 0x00, +0x74, 0x6f, 0x04, 0x03, 0x13, 0x59, 0x42, 0x00, 0x52, 0x61, +0x6c, 0x73, 0x6f, 0x00, 0x3d, 0x03, 0xc1, 0x65, 0x00, 0x63, +0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x09, +0x03, 0x20, 0x6d, 0x6f, 0x2f, 0x05, 0x55, 0x72, 0x6f, 0x75, +0x6e, 0x64, 0x6d, 0x03, 0x71, 0x2e, 0x00, 0x50, 0x72, 0x65, +0x73, 0x73, 0xa4, 0x01, 0x00, 0xe4, 0x01, 0x50, 0x65, 0x74, +0x75, 0x72, 0x6e, 0xe0, 0x03, 0x20, 0x73, 0x70, 0x0e, 0x02, +0x01, 0x3b, 0x00, 0x0b, 0xb4, 0x02, 0x20, 0x6f, 0x72, 0x25, +0x02, 0xe2, 0x2c, 0x00, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, +0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x2c, 0x01, 0x01, 0x29, +0x00, 0x43, 0x74, 0x68, 0x65, 0x6e, 0xd4, 0x01, 0x50, 0x74, +0x68, 0x65, 0x6d, 0x00, 0x59, 0x04, 0x5a, 0x62, 0x6f, 0x76, +0x65, 0x2e, 0xa4, 0x00, 0x10, 0x70, 0x77, 0x00, 0x20, 0x00, +0x2f, 0x4e, 0x00, 0x01, 0x7d, 0x01, 0x06, 0x7e, 0x02, 0x00, +0x12, 0x00, 0x0c, 0x5e, 0x00, 0xa1, 0x69, 0x6e, 0x64, 0x65, +0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0xf2, 0x02, 0x20, 0x77, +0x68, 0xe6, 0x04, 0x81, 0x73, 0x00, 0x61, 0x6c, 0x72, 0x65, +0x61, 0x64, 0xee, 0x01, 0x07, 0xf0, 0x00, 0x02, 0x91, 0x01, +0x62, 0x2e, 0x00, 0x42, 0x61, 0x63, 0x6b, 0xc7, 0x00, 0x20, +0x72, 0x65, 0xfc, 0x00, 0x24, 0x73, 0x00, 0x2e, 0x05, 0x06, +0x48, 0x03, 0x0b, 0x33, 0x00, 0x42, 0x00, 0x00, 0x28, 0x41, +0xc4, 0x00, 0x32, 0x00, 0x61, 0x63, 0xcd, 0x05, 0x90, 0x64, +0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x66, 0x00, +0x21, 0x73, 0x65, 0x16, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, +0xe6, 0x05, 0x01, 0xcb, 0x00, 0xa3, 0x61, 0x76, 0x61, 0x69, +0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x19, 0x04, 0x13, 0x32, +0x19, 0x04, 0x91, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x1b, 0x04, 0x66, 0x54, 0x68, 0x65, 0x73, 0x65, +0x00, 0x14, 0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x06, +0x93, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, +0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6f, 0x00, 0x22, +0x6f, 0x6e, 0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0xab, 0x00, 0x91, 0x57, 0x69, +0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x81, 0x03, 0x51, +0x00, 0x00, 0x53, 0x69, 0x7a, 0x49, 0x05, 0x01, 0x45, 0x05, +0x26, 0x69, 0x6e, 0x10, 0x07, 0xc3, 0x00, 0x00, 0x44, 0x69, +0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x98, 0x03, +0x00, 0xb0, 0x04, 0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, 0x00, +0x04, 0x84, 0x05, 0x40, 0x65, 0x6e, 0x65, 0x72, 0xe0, 0x02, +0x03, 0x49, 0x05, 0xf2, 0x00, 0x2e, 0x00, 0x41, 0x74, 0x00, +0x48, 0x61, 0x72, 0x64, 0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, +0xae, 0x02, 0x20, 0x61, 0x72, 0x56, 0x01, 0x61, 0x71, 0x75, +0x69, 0x72, 0x65, 0x64, 0x64, 0x07, 0x63, 0x6f, 0x00, 0x64, +0x65, 0x64, 0x75, 0x34, 0x01, 0x50, 0x62, 0x61, 0x73, 0x65, +0x64, 0xb6, 0x00, 0x81, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, +0x64, 0x67, 0x98, 0x00, 0x41, 0x72, 0x65, 0x6c, 0x61, 0x20, +0x00, 0x45, 0x68, 0x69, 0x70, 0x73, 0xf1, 0x03, 0x03, 0xa6, +0x00, 0x03, 0x51, 0x06, 0x00, 0xf5, 0x05, 0x00, 0x22, 0x02, +0x30, 0x77, 0x61, 0x79, 0x23, 0x00, 0x01, 0xd1, 0x06, 0x10, +0x62, 0x4b, 0x02, 0x03, 0x60, 0x00, 0x02, 0xd9, 0x02, 0x55, +0x65, 0x78, 0x61, 0x63, 0x74, 0x11, 0x04, 0x00, 0x5c, 0x00, +0x25, 0x6f, 0x6e, 0x89, 0x03, 0xf0, 0x00, 0x61, 0x74, 0x00, +0x61, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x00, 0x28, 0x46, +0x6f, 0x72, 0x2d, 0x00, 0x33, 0x6d, 0x70, 0x6c, 0x66, 0x03, +0x11, 0x6d, 0x2c, 0x01, 0x00, 0x97, 0x00, 0x03, 0xc4, 0x07, +0x25, 0x77, 0x6f, 0x82, 0x00, 0x01, 0xdf, 0x07, 0x04, 0x4c, +0x02, 0x30, 0x73, 0x61, 0x6d, 0x1d, 0x01, 0x12, 0x72, 0xf1, +0x01, 0x55, 0x2c, 0x00, 0x65, 0x76, 0x65, 0x79, 0x03, 0x83, +0x64, 0x6f, 0x6e, 0x27, 0x74, 0x00, 0x79, 0x65, 0x49, 0x00, +0x01, 0x8e, 0x02, 0x01, 0x4e, 0x00, 0x05, 0x30, 0x00, 0x32, +0x00, 0x69, 0x73, 0x13, 0x03, 0x01, 0x91, 0x06, 0x02, 0x75, +0x00, 0x21, 0x65, 0x6e, 0xca, 0x00, 0x00, 0x41, 0x00, 0x06, +0xce, 0x00, 0x62, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0xe7, +0x00, 0x60, 0x6f, 0x75, 0x74, 0x00, 0x73, 0x74, 0x44, 0x03, +0x11, 0x6f, 0x0b, 0x01, 0x04, 0xc0, 0x01, 0x30, 0x29, 0x00, +0x45, 0x7d, 0x00, 0x1a, 0x61, 0x86, 0x01, 0x91, 0x67, 0x75, +0x65, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x6b, 0x68, 0x00, 0x00, +0x5d, 0x04, 0x32, 0x74, 0x72, 0x61, 0xe1, 0x05, 0x21, 0x73, +0x68, 0x35, 0x07, 0x02, 0x6f, 0x07, 0xd2, 0x62, 0x65, 0x00, +0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x2e, +0xa0, 0x02, 0x13, 0x33, 0xa0, 0x02, 0xf1, 0x00, 0x75, 0x73, +0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, +0x6e, 0x63, 0x65, 0xa6, 0x02, 0x11, 0x4f, 0x86, 0x04, 0x10, +0x74, 0x9d, 0x08, 0x12, 0x73, 0xd5, 0x00, 0x80, 0x73, 0x75, +0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, 0x00, 0x17, 0x00, +0x2e, 0x00, 0x12, 0x2c, 0x94, 0x02, 0x16, 0x50, 0x12, 0x00, +0x0d, 0xb0, 0x02, 0x33, 0x47, 0x61, 0x6d, 0xb0, 0x02, 0x02, +0x1c, 0x04, 0x32, 0x6c, 0x65, 0x74, 0xec, 0x04, 0x78, 0x6f, +0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x67, 0x09, 0x06, 0x98, +0x04, 0x44, 0x6d, 0x6f, 0x75, 0x73, 0xec, 0x04, 0x80, 0x73, +0x00, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x00, }; -const unsigned short help_text_len = 2378; -const unsigned short help_text_words = 444; +const unsigned short help_text_len = 2582; +const unsigned short help_text_words = 474; const char quick_help_text[] = "Draw a maze of slanting lines that matches the clues."; diff --git a/apps/plugins/puzzles/help/solo.c b/apps/plugins/puzzles/help/solo.c index 6ebeec86c0..ceb05fa70e 100644 --- a/apps/plugins/puzzles/help/solo.c +++ b/apps/plugins/puzzles/help/solo.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,382 +6,381 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 360, TEXT_UNDERLINE }, - { 390, TEXT_CENTER | C_RED }, - { 446, TEXT_UNDERLINE }, - { 674, TEXT_CENTER | C_RED }, - { 1059, TEXT_UNDERLINE }, + { 361, TEXT_UNDERLINE }, + { 388, TEXT_CENTER | C_RED }, + { 444, TEXT_UNDERLINE }, + { 672, TEXT_CENTER | C_RED }, + { 1057, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 6263 comp 3635 ratio 0.580393 level 10 saved 2628 */ +/* orig 6259 comp 3626 ratio 0.579326 level 10 saved 2633 */ const char help_text[] = { -0xf0, 0x53, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfb, 0x04, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x31, 0x3a, 0x20, 0x53, 0x6f, 0x6c, 0x6f, 0x20, 0x00, -0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, -0x00, 0x61, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, -0x67, 0x72, 0x69, 0x64, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, -0x68, 0x00, 0x69, 0x73, 0x00, 0x64, 0x69, 0x76, 0x69, 0x64, -0x65, 0x64, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x00, 0x61, 0x73, -0x00, 0x6d, 0x61, 0x6e, 0x79, 0x00, 0x65, 0x71, 0x75, 0x61, -0x6c, 0x6c, 0x79, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x64, 0x00, -0x73, 0x75, 0x62, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, -0x21, 0x00, 0x22, 0x74, 0x68, 0x44, 0x00, 0xf4, 0x00, 0x00, -0x68, 0x61, 0x73, 0x00, 0x72, 0x6f, 0x77, 0x73, 0x2e, 0x00, -0x45, 0x61, 0x63, 0x68, 0x5f, 0x00, 0xc1, 0x6d, 0x75, 0x73, -0x74, 0x00, 0x62, 0x65, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x57, -0x00, 0xf1, 0x08, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x61, -0x00, 0x64, 0x69, 0x67, 0x69, 0x74, 0x00, 0x66, 0x72, 0x6f, -0x6d, 0x00, 0x31, 0x00, 0x74, 0x6f, 0x48, 0x00, 0x00, 0x60, -0x00, 0x35, 0x00, 0x6f, 0x66, 0x54, 0x00, 0x10, 0x2c, 0x30, -0x00, 0x30, 0x73, 0x75, 0x63, 0x30, 0x00, 0xf0, 0x03, 0x77, -0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x00, 0x00, -0x2d, 0x00, 0x65, 0x76, 0x65, 0x72, 0x79, 0x6e, 0x00, 0xf1, -0x0d, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, -0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x6e, 0x65, 0x00, -0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x4b, -0x00, 0x10, 0x65, 0x8c, 0x00, 0x02, 0x6c, 0x00, 0x06, 0x39, -0x00, 0x6f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3c, 0x00, -0x23, 0x01, 0xfa, 0x00, 0x0f, 0x3b, 0x00, 0x18, 0x11, 0x2e, -0x3c, 0x00, 0x70, 0x28, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, -0x46, 0x01, 0xf2, 0x02, 0x2c, 0x00, 0x62, 0x79, 0x00, 0x64, -0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x6f, 0x66, 0x66, -0x29, 0x2d, 0x00, 0x03, 0xf7, 0x00, 0x02, 0x37, 0x01, 0xf0, -0x01, 0x27, 0x73, 0x00, 0x74, 0x77, 0x6f, 0x00, 0x6d, 0x61, -0x69, 0x6e, 0x00, 0x64, 0x69, 0x61, 0x67, 0x3a, 0x00, 0x1f, -0x73, 0x75, 0x00, 0x1c, 0x00, 0xeb, 0x01, 0x01, 0xe1, 0x01, -0x85, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x73, 0x6f, 0x6d, 0x5b, -0x01, 0x61, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xbe, 0x01, -0xf0, 0x00, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x3b, 0x00, 0x79, -0x6f, 0x75, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x02, 0x02, 0x81, -0x74, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2b, 0x00, -0x4c, 0x72, 0x65, 0x73, 0x74, 0x37, 0x00, 0x90, 0x63, 0x6f, -0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x66, 0x00, 0x51, -0x55, 0x6e, 0x64, 0x65, 0x72, 0x1f, 0x00, 0x04, 0xd3, 0x00, -0x92, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, -0xd0, 0x00, 0x07, 0x2d, 0x02, 0x24, 0x72, 0x65, 0x16, 0x02, -0x30, 0x6f, 0x72, 0x00, 0x43, 0x00, 0xa7, 0x61, 0x6e, 0x67, -0x75, 0x6c, 0x61, 0x72, 0x2e, 0x00, 0x54, 0x40, 0x00, 0x53, -0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x0c, 0x02, 0xf3, 0x05, 0x69, -0x73, 0x00, 0x33, 0x78, 0x33, 0x00, 0x28, 0x61, 0x00, 0x39, -0x78, 0x39, 0x00, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x1a, -0x02, 0x09, 0xa9, 0x02, 0x41, 0x6e, 0x69, 0x6e, 0x65, 0x2a, -0x00, 0x02, 0x6b, 0x00, 0x21, 0x29, 0x2e, 0xfe, 0x00, 0xf1, -0x00, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, -0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x00, 0x12, 0x73, -0x80, 0x02, 0x07, 0x7e, 0x00, 0x13, 0x00, 0x9f, 0x00, 0x70, -0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0xee, 0x00, 0x04, -0xa6, 0x00, 0x43, 0x6e, 0x65, 0x73, 0x2c, 0x80, 0x02, 0x32, -0x73, 0x00, 0x32, 0x89, 0x00, 0x32, 0x36, 0x78, 0x36, 0xf0, -0x02, 0x09, 0x81, 0x00, 0x76, 0x73, 0x69, 0x78, 0x00, 0x33, -0x78, 0x32, 0x80, 0x00, 0xb0, 0x41, 0x6c, 0x74, 0x65, 0x72, -0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0xf3, 0x01, 0x13, 0x79, -0x8f, 0x00, 0x03, 0x8a, 0x00, 0xd1, 0x60, 0x6a, 0x69, 0x67, -0x73, 0x61, 0x77, 0x27, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0xe6, -0x02, 0x02, 0x81, 0x03, 0x0f, 0x32, 0x01, 0x00, 0xe0, 0x61, -0x72, 0x62, 0x69, 0x74, 0x72, 0x61, 0x72, 0x79, 0x00, 0x73, -0x68, 0x61, 0x70, 0xc0, 0x00, 0x21, 0x68, 0x69, 0xe7, 0x01, -0xf1, 0x00, 0x66, 0x66, 0x65, 0x72, 0x00, 0x62, 0x65, 0x74, -0x77, 0x65, 0x65, 0x6e, 0x00, 0x69, 0x6e, 0x8f, 0x00, 0x00, -0x1f, 0x01, 0x02, 0x40, 0x01, 0x10, 0x73, 0x9d, 0x01, 0xf1, -0x02, 0x41, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0x61, -0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x70, 0x00, -0x00, 0x56, 0x01, 0x20, 0x60, 0x6b, 0x90, 0x03, 0xb3, 0x72, -0x27, 0x2e, 0x00, 0x49, 0x6e, 0x00, 0x74, 0x68, 0x69, 0x73, -0x8a, 0x00, 0x01, 0x10, 0x02, 0x01, 0x78, 0x00, 0x33, 0x6e, -0x6f, 0x74, 0x3b, 0x02, 0x21, 0x69, 0x6e, 0x98, 0x00, 0x40, -0x66, 0x6f, 0x72, 0x6d, 0x1d, 0x01, 0x02, 0xca, 0x03, 0x33, -0x2d, 0x69, 0x6e, 0x27, 0x01, 0x24, 0x73, 0x3b, 0x3b, 0x01, -0x16, 0x2c, 0x0d, 0x04, 0x0c, 0x4a, 0x04, 0x91, 0x60, 0x63, -0x61, 0x67, 0x65, 0x73, 0x27, 0x00, 0x62, 0x7d, 0x03, 0x81, -0x6f, 0x75, 0x72, 0x65, 0x64, 0x00, 0x6c, 0x69, 0x60, 0x01, -0x30, 0x61, 0x6e, 0x64, 0x5c, 0x00, 0x02, 0xbe, 0x02, 0x00, -0x27, 0x00, 0x02, 0x46, 0x00, 0x91, 0x61, 0x6d, 0x65, 0x00, -0x74, 0x65, 0x6c, 0x6c, 0x73, 0x3c, 0x01, 0x10, 0x77, 0xfa, -0x03, 0x02, 0x1e, 0x01, 0x01, 0x85, 0x00, 0x32, 0x61, 0x6c, -0x6c, 0x75, 0x02, 0x00, 0xee, 0x02, 0x00, 0xbc, 0x01, 0x02, -0x1c, 0x04, 0x01, 0x3f, 0x00, 0x90, 0x73, 0x68, 0x6f, 0x75, -0x6c, 0x64, 0x00, 0x62, 0x65, 0x86, 0x01, 0x63, 0x73, 0x6f, -0x2c, 0x00, 0x6e, 0x6f, 0xc6, 0x03, 0xe0, 0x6d, 0x61, 0x79, -0x00, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x00, 0x6d, 0x6f, -0x72, 0x69, 0x00, 0x40, 0x61, 0x6e, 0x00, 0x6f, 0x3e, 0x03, -0x00, 0x15, 0x02, 0x41, 0x69, 0x6e, 0x00, 0x61, 0x42, 0x00, -0x31, 0x2c, 0x00, 0x65, 0xf8, 0x00, 0x02, 0xf7, 0x02, 0x01, -0x54, 0x00, 0x62, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0xee, -0x04, 0xa1, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, -0x65, 0x73, 0x75, 0x03, 0x30, 0x78, 0x69, 0x73, 0xf0, 0x02, -0x71, 0x00, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x78, 0x01, -0x21, 0x49, 0x66, 0xb5, 0x00, 0x03, 0xed, 0x01, 0x19, 0x61, -0xd3, 0x02, 0x02, 0xbf, 0x01, 0x87, 0x72, 0x65, 0x71, 0x75, -0x69, 0x72, 0x65, 0x73, 0x88, 0x00, 0x13, 0x39, 0xcd, 0x00, -0x02, 0x46, 0x01, 0x42, 0x61, 0x64, 0x64, 0x69, 0x32, 0x04, -0x04, 0xe4, 0x00, 0x40, 0x77, 0x69, 0x6c, 0x6c, 0x4a, 0x05, -0x40, 0x6c, 0x65, 0x74, 0x74, 0x87, 0x03, 0x03, 0x96, 0x03, -0xb0, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x2e, -0x00, 0x46, 0x45, 0x01, 0x50, 0x78, 0x61, 0x6d, 0x70, 0x6c, -0x53, 0x02, 0x09, 0x83, 0x00, 0x30, 0x33, 0x78, 0x34, 0x2d, -0x00, 0x18, 0x6e, 0x34, 0x01, 0x02, 0x89, 0x00, 0x20, 0x67, -0x6f, 0x3d, 0x01, 0x01, 0x00, 0x04, 0x01, 0xb9, 0x01, 0x04, -0x66, 0x00, 0x01, 0x94, 0x05, 0xf1, 0x01, 0x39, 0x2c, 0x00, -0x70, 0x6c, 0x75, 0x73, 0x00, 0x60, 0x61, 0x27, 0x2c, 0x00, -0x60, 0x62, 0x27, 0xac, 0x01, 0x30, 0x60, 0x63, 0x27, 0xb1, -0x03, 0x20, 0x69, 0x73, 0xd1, 0x02, 0x21, 0x6e, 0x6f, 0xde, -0x05, 0x02, 0x67, 0x00, 0x12, 0x65, 0xc9, 0x01, 0x02, 0x5b, -0x02, 0x08, 0x88, 0x02, 0xb2, 0x49, 0x00, 0x66, 0x69, 0x72, -0x73, 0x74, 0x00, 0x73, 0x61, 0x77, 0x6d, 0x02, 0x03, 0x11, -0x01, 0xf2, 0x0d, 0x69, 0x6e, 0x00, 0x4e, 0x69, 0x6b, 0x6f, -0x6c, 0x69, 0x00, 0x5b, 0x35, 0x5d, 0x2c, 0x00, 0x61, 0x6c, -0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x69, 0x74, 0x27, -0x73, 0xba, 0x03, 0x10, 0x62, 0xdd, 0x02, 0x30, 0x70, 0x6f, -0x70, 0xa9, 0x03, 0x40, 0x69, 0x73, 0x65, 0x64, 0x41, 0x02, -0xf0, 0x00, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, -0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, 0x0c, 0x01, 0x15, -0x75, 0x86, 0x04, 0x10, 0x6e, 0x38, 0x02, 0x80, 0x60, 0x53, -0x75, 0x64, 0x6f, 0x6b, 0x75, 0x27, 0x68, 0x04, 0x50, 0x60, -0x53, 0x75, 0x00, 0x44, 0x0d, 0x00, 0xf1, 0x01, 0x2e, 0x00, -0x48, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x00, 0x47, 0x61, 0x72, -0x6e, 0x73, 0x00, 0x69, 0x50, 0x05, 0x40, 0x73, 0x69, 0x64, -0x65, 0x8c, 0x02, 0x20, 0x74, 0x68, 0x8e, 0x00, 0x64, 0x76, -0x65, 0x6e, 0x74, 0x6f, 0x72, 0x5a, 0x01, 0x00, 0x12, 0x03, -0x25, 0x72, 0x6e, 0xf8, 0x02, 0x00, 0x13, 0x00, 0x02, 0xb8, -0x00, 0x02, 0xb4, 0x02, 0x63, 0x69, 0x74, 0x00, 0x77, 0x61, -0x73, 0xda, 0x00, 0x72, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, -0x68, 0xe2, 0x06, 0xd2, 0x44, 0x65, 0x6c, 0x6c, 0x20, 0x50, -0x65, 0x6e, 0x63, 0x69, 0x6c, 0x20, 0x50, 0x06, 0x01, 0xd0, -0x20, 0x61, 0x6e, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x64, 0x20, -0x47, 0x61, 0x6d, 0x15, 0x01, 0x12, 0x41, 0xfa, 0x01, 0xf5, -0x03, 0x65, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, -0x00, 0x74, 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x6f, -0x05, 0x7a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x7b, -0x00, 0x01, 0x45, 0x04, 0x00, 0x4f, 0x07, 0x00, 0x84, 0x02, -0xf0, 0x02, 0x00, 0x6f, 0x6e, 0x00, 0x57, 0x69, 0x6b, 0x69, -0x70, 0x65, 0x64, 0x69, 0x61, 0x00, 0x5b, 0x36, 0x5d, 0x6c, -0x01, 0xf1, 0x01, 0x5b, 0x35, 0x5d, 0x00, 0x68, 0x74, 0x74, -0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x60, -0x01, 0xa3, 0x2e, 0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, -0x6e, 0x2f, 0x96, 0x01, 0x21, 0x2f, 0x73, 0x22, 0x01, 0xc1, -0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, 0x28, 0x62, 0x65, 0x77, -0x61, 0x72, 0x1f, 0x06, 0x60, 0x46, 0x6c, 0x61, 0x73, 0x68, -0x29, 0x47, 0x00, 0x15, 0x36, 0x47, 0x00, 0x44, 0x65, 0x6e, -0x2e, 0x77, 0x66, 0x00, 0x50, 0x2e, 0x6f, 0x72, 0x67, 0x2f, -0x0e, 0x00, 0x12, 0x2f, 0x63, 0x01, 0x72, 0x00, 0x00, 0x00, -0x31, 0x31, 0x2e, 0x31, 0x60, 0x08, 0x00, 0xa0, 0x06, 0x40, -0x72, 0x6f, 0x6c, 0x73, 0x69, 0x08, 0x11, 0x54, 0x46, 0x06, -0x20, 0x79, 0x00, 0x19, 0x00, 0xe3, 0x2c, 0x00, 0x73, 0x69, -0x6d, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, -0x5c, 0x01, 0x21, 0x75, 0x73, 0x00, 0x02, 0x01, 0x5f, 0x08, -0x44, 0x6d, 0x70, 0x74, 0x79, 0x75, 0x05, 0x00, 0x5b, 0x01, -0x02, 0xab, 0x02, 0x35, 0x79, 0x70, 0x65, 0x28, 0x08, 0x23, -0x6f, 0x72, 0xf8, 0x02, 0x22, 0x00, 0x6f, 0xc5, 0x02, 0x50, -0x6b, 0x65, 0x79, 0x62, 0x6f, 0xce, 0x01, 0x21, 0x74, 0x6f, -0x92, 0x04, 0x02, 0x00, 0x04, 0x02, 0x44, 0x00, 0x14, 0x2e, -0x81, 0x03, 0x30, 0x6d, 0x61, 0x6b, 0x43, 0x00, 0x8f, 0x6d, -0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2c, 0x80, 0x00, 0x01, -0x02, 0xf9, 0x01, 0x03, 0xd3, 0x06, 0x08, 0x84, 0x00, 0x81, -0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x0a, 0x07, -0x40, 0x6f, 0x00, 0x63, 0x6c, 0x36, 0x04, 0x50, 0x69, 0x74, -0x00, 0x61, 0x67, 0x95, 0x07, 0x62, 0x28, 0x6f, 0x72, 0x00, -0x75, 0x73, 0xab, 0x04, 0xd7, 0x55, 0x6e, 0x64, 0x6f, 0x00, -0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x29, 0xff, 0x03, -0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x74, 0x00, 0x01, -0x5c, 0x04, 0x0f, 0xe2, 0x00, 0x04, 0x02, 0x58, 0x07, 0x12, -0x2c, 0xc2, 0x00, 0x02, 0x0d, 0x00, 0x05, 0x87, 0x03, 0x52, -0x65, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x02, 0x06, 0x1e, 0x08, -0x00, 0x8e, 0x06, 0x41, 0x61, 0x00, 0x60, 0x70, 0x62, 0x02, -0x66, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x27, 0xf1, 0x06, 0x01, -0xde, 0x09, 0x07, 0x1b, 0x00, 0x11, 0x73, 0x94, 0x03, 0x76, -0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0xc5, 0x07, 0x04, -0x51, 0x00, 0x00, 0x2f, 0x03, 0x04, 0x36, 0x01, 0x12, 0x53, -0xd0, 0x05, 0x04, 0x68, 0x08, 0x00, 0xd5, 0x04, 0x06, 0xed, -0x05, 0x05, 0xfe, 0x07, 0x02, 0xf5, 0x03, 0x01, 0x9e, 0x03, -0x03, 0x29, 0x00, 0x09, 0x6f, 0x00, 0x10, 0x2e, 0xfd, 0x01, -0x04, 0xc1, 0x05, 0x40, 0x70, 0x61, 0x79, 0x73, 0x7f, 0x05, -0x50, 0x61, 0x74, 0x74, 0x65, 0x6e, 0xcf, 0x04, 0x01, 0x5e, -0x08, 0x07, 0x2e, 0x00, 0x40, 0x2c, 0x00, 0x73, 0x6f, 0xb5, -0x04, 0x00, 0x4f, 0x08, 0x02, 0xe5, 0x05, 0x00, 0x3a, 0x01, -0x03, 0x5a, 0x01, 0x11, 0x6d, 0xbb, 0x00, 0x50, 0x69, 0x73, -0x00, 0x75, 0x70, 0x38, 0x00, 0x45, 0x79, 0x6f, 0x75, 0x3a, -0x49, 0x07, 0x05, 0x23, 0x00, 0x00, 0x76, 0x0a, 0x30, 0x65, -0x6d, 0x69, 0x01, 0x04, 0x12, 0x73, 0x43, 0x01, 0x81, 0x61, -0x00, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0xdd, 0x07, 0x03, -0x32, 0x01, 0x41, 0x6e, 0x65, 0x65, 0x64, 0xdb, 0x08, 0x10, -0x62, 0xd4, 0x08, 0x10, 0x2d, 0x27, 0x05, 0x42, 0x69, 0x6e, -0x65, 0x64, 0xfd, 0x05, 0x00, 0x54, 0x00, 0x42, 0x6b, 0x6e, -0x6f, 0x77, 0x93, 0x03, 0x4b, 0x61, 0x62, 0x6f, 0x75, 0x45, -0x00, 0x04, 0xa2, 0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, 0x02, -0x55, 0x6c, 0x69, 0x73, 0x74, 0x73, 0xa8, 0x03, 0x5a, 0x6f, -0x73, 0x73, 0x69, 0x62, 0x6a, 0x01, 0x14, 0x61, 0x85, 0x09, -0x01, 0x8d, 0x00, 0x01, 0x48, 0x00, 0x50, 0x61, 0x6e, 0x79, -0x74, 0x68, 0x62, 0x01, 0x32, 0x65, 0x6c, 0x73, 0x82, 0x00, -0xa2, 0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, -0x2e, 0x3f, 0x03, 0x41, 0x65, 0x72, 0x61, 0x73, 0xa8, 0x0b, -0x49, 0x69, 0x6e, 0x67, 0x6c, 0xd3, 0x01, 0x1c, 0x2c, 0x5b, -0x02, 0x08, 0x1b, 0x02, 0x22, 0x6e, 0x64, 0x58, 0x02, 0x05, -0xde, 0x01, 0x03, 0x52, 0x02, 0x01, 0xb8, 0x02, 0x01, 0x15, -0x08, 0x2a, 0x6c, 0x6c, 0x20, 0x02, 0x09, 0x9c, 0x02, 0x22, -0x72, 0x65, 0x79, 0x00, 0x30, 0x64, 0x00, 0x77, 0xa3, 0x02, -0x00, 0x99, 0x00, 0x34, 0x6c, 0x65, 0x66, 0x6c, 0x00, 0x05, -0x5e, 0x00, 0x18, 0x61, 0x14, 0x01, 0x0f, 0x2a, 0x00, 0x05, -0x02, 0x43, 0x03, 0x10, 0x73, 0x43, 0x03, 0x36, 0x2e, 0x00, -0x52, 0xb3, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x20, 0x00, 0x00, -0x0d, 0x00, 0x01, 0x23, 0x00, 0x02, 0xf4, 0x02, 0x01, 0x58, -0x02, 0x02, 0xfb, 0x00, 0x0c, 0x56, 0x02, 0x0b, 0x53, 0x09, -0x04, 0x7f, 0x03, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x11, 0x04, 0x01, 0xe1, 0x01, 0x32, 0x6d, 0x6f, 0x76, 0x18, -0x00, 0x00, 0x38, 0x00, 0x31, 0x00, 0x61, 0x72, 0x29, 0x05, -0x04, 0x98, 0x08, 0x34, 0x2e, 0x00, 0x50, 0x74, 0x00, 0x02, -0xde, 0x0a, 0x40, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x00, 0x86, -0x00, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x73, 0x3a, 0x00, -0x11, 0x28, 0x9b, 0x0c, 0x82, 0x61, 0x00, 0x6e, 0x6f, 0x72, -0x6d, 0x61, 0x6c, 0x14, 0x00, 0x00, 0x13, 0x0d, 0x08, 0x97, -0x00, 0x24, 0x29, 0x2c, 0x12, 0x01, 0x01, 0xd3, 0x00, 0x04, -0x6b, 0x01, 0x20, 0x69, 0x6e, 0xb5, 0x02, 0x0f, 0xbb, 0x03, -0x03, 0x03, 0x0e, 0x00, 0x80, 0x61, 0x70, 0x70, 0x72, 0x6f, -0x70, 0x72, 0x69, 0xfa, 0x05, 0x44, 0x77, 0x61, 0x79, 0x3b, -0x44, 0x00, 0x01, 0x8c, 0x01, 0x21, 0x30, 0x00, 0x5e, 0x04, -0x04, 0xa6, 0x00, 0x02, 0x1e, 0x01, 0x23, 0x62, 0x61, 0x16, -0x04, 0x02, 0x8a, 0x04, 0x14, 0x61, 0x52, 0x0d, 0x04, 0xbd, -0x03, 0x43, 0x00, 0x00, 0x28, 0x41, 0x15, 0x09, 0x30, 0x61, -0x63, 0x74, 0x8a, 0x08, 0x82, 0x00, 0x64, 0x65, 0x73, 0x63, -0x72, 0x69, 0x62, 0x84, 0x00, 0x31, 0x73, 0x65, 0x63, 0x81, -0x03, 0x32, 0x32, 0x2e, 0x31, 0x58, 0x0a, 0x00, 0x69, 0x01, -0x05, 0x19, 0x0a, 0x22, 0x2e, 0x29, 0xca, 0x05, 0x12, 0x32, -0xca, 0x05, 0x60, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x67, -0x08, 0x00, 0xcc, 0x05, 0x00, 0x13, 0x00, 0x00, 0x72, 0x09, -0x22, 0x6f, 0x77, 0x8d, 0x09, 0x11, 0x74, 0xfa, 0x03, 0x40, -0x66, 0x69, 0x67, 0x75, 0xbc, 0x08, 0x10, 0x77, 0x60, 0x0b, -0x00, 0x31, 0x00, 0x10, 0x74, 0x5b, 0x08, 0x41, 0x6d, 0x65, -0x6e, 0x73, 0x7d, 0x00, 0x0a, 0xb7, 0x06, 0x01, 0x5c, 0x08, -0x03, 0xbb, 0x05, 0xc7, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, -0x00, 0x6d, 0x65, 0x6e, 0x75, 0x3a, 0x59, 0x0c, 0x00, 0x32, -0x00, 0x02, 0x99, 0x0d, 0x03, 0x15, 0x0a, 0x0a, 0x1b, 0x00, -0x00, 0x5b, 0x0e, 0x12, 0x2c, 0x4d, 0x0a, 0x06, 0x2c, 0x0b, -0x01, 0x21, 0x0d, 0x0b, 0x71, 0x0a, 0x47, 0x2e, 0x00, 0x28, -0x54, 0x4c, 0x0e, 0x13, 0x61, 0xb2, 0x0d, 0x25, 0x69, 0x73, -0xe5, 0x07, 0x23, 0x72, 0x73, 0x0b, 0x0d, 0x5f, 0x69, 0x73, -0x3a, 0x00, 0x66, 0x36, 0x09, 0x07, 0x14, 0x32, 0x90, 0x00, -0x01, 0x8f, 0x00, 0x13, 0x33, 0x83, 0x00, 0x01, 0xa8, 0x0a, -0x03, 0x8b, 0x0c, 0x02, 0x5b, 0x00, 0x01, 0x97, 0x01, 0x01, -0x78, 0x05, 0x19, 0x33, 0x32, 0x00, 0x12, 0x32, 0x10, 0x0f, -0x16, 0x29, 0x13, 0x06, 0x14, 0x74, 0x80, 0x06, 0xd2, 0x60, -0x58, 0x27, 0x00, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, -0x78, 0x2c, 0x61, 0x01, 0x02, 0xff, 0x02, 0x10, 0x70, 0x28, -0x07, 0x00, 0x22, 0x00, 0x04, 0x31, 0x0e, 0x61, 0x00, 0x65, -0x78, 0x74, 0x72, 0x61, 0xac, 0x08, 0x50, 0x74, 0x72, 0x61, -0x69, 0x6e, 0x07, 0x0b, 0x03, 0x0c, 0x0b, 0x0e, 0x23, 0x0e, -0x08, 0x3d, 0x0f, 0x0a, 0xa3, 0x05, 0x01, 0x2e, 0x0e, 0x13, -0x66, 0xc4, 0x0e, 0x03, 0x24, 0x0e, 0x11, 0x28, 0xc6, 0x09, -0x21, 0x69, 0x73, 0x1d, 0x0e, 0x51, 0x74, 0x69, 0x6d, 0x65, -0x73, 0x07, 0x05, 0x10, 0x6e, 0xd4, 0x04, 0x03, 0x43, 0x09, -0x30, 0x2d, 0x58, 0x27, 0x3d, 0x02, 0x06, 0x6b, 0x09, 0x2b, -0x2e, 0x29, 0x32, 0x0c, 0x06, 0xdc, 0x02, 0x00, 0x98, 0x0e, -0x0f, 0x98, 0x00, 0x05, 0x04, 0xd0, 0x06, 0x40, 0x73, 0x68, -0x61, 0x64, 0xb5, 0x02, 0x10, 0x6c, 0x0e, 0x04, 0x00, 0x52, -0x10, 0x12, 0x6f, 0xcf, 0x00, 0x05, 0x83, 0x05, 0x01, 0xfb, -0x09, 0x20, 0x65, 0x6e, 0x94, 0x02, 0x2f, 0x64, 0x2e, 0x39, -0x01, 0x01, 0x13, 0x4a, 0x3a, 0x0d, 0x0f, 0x3e, 0x01, 0x01, -0x41, 0x67, 0x65, 0x6e, 0x65, 0x88, 0x02, 0x73, 0x72, 0x61, -0x6e, 0x64, 0x6f, 0x6d, 0x6c, 0x34, 0x0d, 0x08, 0xb3, 0x10, -0x1e, 0x2e, 0xbf, 0x00, 0x08, 0x58, 0x0e, 0x03, 0xa4, 0x0b, -0x03, 0xae, 0x00, 0x00, 0x36, 0x08, 0x13, 0x6e, 0x36, 0x06, -0x01, 0xcd, 0x02, 0x5d, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x11, -0x0f, 0x0b, 0xea, 0x03, 0x22, 0x60, 0x43, 0x04, 0x02, 0x03, -0x2f, 0x0b, 0x30, 0x52, 0x6f, 0x77, 0xf9, 0x0c, 0x41, 0x6f, -0x78, 0x65, 0x73, 0xe9, 0x0e, 0x00, 0x05, 0x04, 0x01, 0x15, -0x07, 0x50, 0x72, 0x65, 0x61, 0x73, 0x6f, 0xfa, 0x0d, 0x34, -0x79, 0x00, 0x79, 0x97, 0x11, 0x22, 0x74, 0x6f, 0x4e, 0x00, -0x06, 0x4d, 0x04, 0x10, 0x67, 0x18, 0x0a, 0x22, 0x65, 0x72, -0x24, 0x0c, 0x10, 0x31, 0x64, 0x00, 0x42, 0x62, 0x6f, 0x74, -0x68, 0x50, 0x00, 0x22, 0x3b, 0x00, 0x0e, 0x01, 0x02, 0xd7, -0x0d, 0x21, 0x68, 0x61, 0x57, 0x00, 0x07, 0x2a, 0x02, 0x03, -0x90, 0x01, 0x05, 0xd9, 0x00, 0x05, 0xb9, 0x0a, 0x00, 0xc2, -0x06, 0x01, 0xe4, 0x0c, 0x20, 0x62, 0x65, 0xd2, 0x04, 0x26, -0x72, 0x69, 0x28, 0x06, 0x2a, 0x69, 0x66, 0x8e, 0x06, 0x3f, -0x00, 0x69, 0x74, 0x88, 0x01, 0x02, 0x12, 0x4b, 0x41, 0x0e, -0x0f, 0x88, 0x01, 0x0b, 0x10, 0x61, 0x0e, 0x10, 0x00, 0x2f, -0x01, 0x00, 0xdc, 0x03, 0x00, 0x02, 0x0e, 0x04, 0x6a, 0x12, -0x2e, 0x61, 0x72, 0xa5, 0x01, 0x00, 0x9c, 0x00, 0x41, 0x64, -0x72, 0x61, 0x77, 0x72, 0x0e, 0x00, 0x99, 0x0d, 0x20, 0x75, -0x74, 0x23, 0x0e, 0x02, 0xc5, 0x03, 0x02, 0xf0, 0x0e, 0x00, -0x1f, 0x0b, 0x02, 0x40, 0x0e, 0x03, 0x66, 0x12, 0x02, 0x8a, -0x01, 0x24, 0x73, 0x65, 0x7e, 0x0d, 0x06, 0x24, 0x11, 0x51, -0x61, 0x00, 0x73, 0x6d, 0x61, 0x89, 0x0c, 0x00, 0xd4, 0x0e, -0x03, 0x77, 0x00, 0x20, 0x73, 0x68, 0xc4, 0x04, 0x05, 0x05, -0x0d, 0x0c, 0x4e, 0x0e, 0x04, 0xc8, 0x02, 0x13, 0x69, 0x23, -0x02, 0x02, 0x55, 0x00, 0x04, 0x4d, 0x11, 0x05, 0x4f, 0x10, -0x07, 0xfd, 0x04, 0x22, 0x68, 0x65, 0x10, 0x07, 0x00, 0x35, -0x10, 0x71, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x65, -0x00, 0x05, 0x36, 0x0f, 0x04, 0x0b, 0x01, 0x16, 0x64, 0x10, -0x0d, 0x10, 0x4d, 0x66, 0x08, 0x05, 0x2e, 0x00, 0x00, 0xa4, -0x0a, 0x17, 0x73, 0x2b, 0x05, 0x60, 0x73, 0x00, 0x6c, 0x6f, -0x6f, 0x6b, 0x1c, 0x07, 0x30, 0x74, 0x74, 0x69, 0xe2, 0x0f, -0x13, 0x75, 0xb8, 0x0e, 0x00, 0x7a, 0x00, 0x01, 0xd1, 0x0a, -0x01, 0x77, 0x08, 0x60, 0x65, 0x61, 0x73, 0x69, 0x65, 0x72, -0x5a, 0x0b, 0x13, 0x6e, 0xab, 0x11, 0x05, 0x52, 0x00, 0x06, -0x01, 0x02, 0x01, 0xae, 0x09, 0x00, 0xe2, 0x04, 0x22, 0x63, -0x65, 0xdc, 0x08, 0x02, 0xdf, 0x0f, 0x01, 0x4b, 0x02, 0x60, -0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x58, 0x10, 0x02, 0xe0, -0x02, 0x00, 0x8d, 0x07, 0x70, 0x65, 0x6e, 0x74, 0x2e, 0x00, -0x43, 0x6f, 0x0c, 0x05, 0x63, 0x74, 0x65, 0x6c, 0x79, 0x00, -0x61, 0x54, 0x00, 0x25, 0x69, 0x63, 0x9d, 0x00, 0x02, 0xa6, -0x02, 0x00, 0x0f, 0x10, 0x86, 0x72, 0x65, 0x65, 0x64, 0x6f, -0x6d, 0x00, 0x74, 0x64, 0x04, 0x00, 0x0e, 0x0d, 0x24, 0x65, -0x77, 0x44, 0x10, 0x15, 0x73, 0x0b, 0x09, 0x00, 0x41, 0x01, -0x23, 0x46, 0x69, 0xfd, 0x12, 0x04, 0x41, 0x09, 0x0a, 0x45, -0x01, 0x00, 0xdf, 0x01, 0x00, 0x6d, 0x09, 0x15, 0x74, 0xf0, -0x0c, 0x0f, 0x39, 0x01, 0x00, 0x16, 0x44, 0x25, 0x00, 0x52, -0x6c, 0x65, 0x76, 0x65, 0x6c, 0xa9, 0x10, 0x42, 0x6a, 0x75, -0x64, 0x67, 0x19, 0x0e, 0x01, 0x0e, 0x08, 0x01, 0xbe, 0x00, -0x26, 0x78, 0x69, 0x49, 0x00, 0x82, 0x74, 0x65, 0x63, 0x68, -0x6e, 0x69, 0x71, 0x75, 0xaf, 0x0f, 0x42, 0x64, 0x65, 0x64, -0x75, 0x09, 0x07, 0x03, 0x83, 0x0f, 0x01, 0x42, 0x0c, 0x57, -0x73, 0x6f, 0x6c, 0x76, 0x65, 0x85, 0x01, 0x12, 0x3a, 0xe6, -0x05, 0x01, 0x66, 0x00, 0x06, 0xac, 0x0f, 0x12, 0x61, 0x68, -0x03, 0x23, 0x6f, 0x66, 0xbb, 0x03, 0x00, 0xa1, 0x07, 0x02, -0x58, 0x02, 0x11, 0x77, 0x7b, 0x03, 0x17, 0x74, 0x55, 0x01, -0x23, 0x69, 0x6e, 0x32, 0x04, 0x21, 0x65, 0x76, 0xad, 0x0e, -0x31, 0x6f, 0x6e, 0x65, 0x7b, 0x04, 0x06, 0x56, 0x0a, 0x10, -0x2c, 0x9f, 0x03, 0x1d, 0x64, 0xd3, 0x00, 0x83, 0x60, 0x54, -0x72, 0x69, 0x76, 0x69, 0x61, 0x6c, 0x3e, 0x04, 0x70, 0x42, -0x61, 0x73, 0x69, 0x63, 0x27, 0x00, 0xc7, 0x11, 0x06, 0x98, -0x04, 0x05, 0xaf, 0x09, 0x04, 0x4d, 0x01, 0x01, 0x02, 0x0d, -0x06, 0x5c, 0x15, 0x03, 0x33, 0x0a, 0x04, 0xfa, 0x09, 0x12, -0x74, 0xe1, 0x02, 0x22, 0x69, 0x6d, 0x80, 0x03, 0x10, 0x65, -0xbe, 0x00, 0x00, 0x16, 0x00, 0x20, 0x60, 0x49, 0x6b, 0x04, -0x30, 0x6d, 0x65, 0x64, 0x87, 0x08, 0x13, 0x27, 0xee, 0x00, -0x20, 0x61, 0x6e, 0x3b, 0x11, 0x42, 0x79, 0x6f, 0x6e, 0x64, -0x79, 0x11, 0x05, 0xdc, 0x06, 0x13, 0x74, 0x7f, 0x02, 0x01, -0xc2, 0x00, 0x26, 0x61, 0x6c, 0x4a, 0x01, 0x13, 0x73, 0x33, -0x0b, 0x01, 0x85, 0x02, 0x02, 0xef, 0x03, 0x04, 0x49, 0x03, -0x05, 0xc6, 0x04, 0x13, 0x63, 0x93, 0x11, 0x13, 0x00, 0x3c, -0x0d, 0x07, 0x2c, 0x00, 0x04, 0x46, 0x05, 0x02, 0xc1, 0x11, -0x07, 0x28, 0x00, 0x04, 0xe6, 0x00, 0x00, 0x4e, 0x13, 0x52, -0x74, 0x00, 0x60, 0x55, 0x6e, 0x76, 0x01, 0x00, 0x1b, 0x06, -0x03, 0xad, 0x00, 0x03, 0xa9, 0x11, 0x13, 0x74, 0xc7, 0x06, -0x00, 0x82, 0x01, 0x20, 0x65, 0x6e, 0x42, 0x10, 0x02, 0xe9, -0x04, 0x05, 0xc0, 0x00, 0x10, 0x65, 0xd9, 0x0f, 0x02, 0xc3, -0x16, 0x09, 0xcb, 0x00, 0x86, 0x61, 0x00, 0x67, 0x75, 0x65, -0x73, 0x73, 0x2c, 0x93, 0x0d, 0x70, 0x62, 0x61, 0x63, 0x6b, -0x74, 0x72, 0x61, 0x30, 0x08, 0x10, 0x66, 0x29, 0x05, 0x00, -0x20, 0x0a, 0x10, 0x73, 0x8a, 0x04, 0x03, 0x26, 0x03, 0x50, -0x77, 0x72, 0x6f, 0x6e, 0x67, 0xd0, 0x02, 0x12, 0x47, 0x9f, -0x02, 0x00, 0x03, 0x02, 0x05, 0xc4, 0x01, 0x05, 0x25, 0x03, -0x00, 0x8f, 0x00, 0x56, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x1c, -0x00, 0x1b, 0x3a, 0x5c, 0x08, 0x03, 0x90, 0x07, 0x02, 0xe9, -0x0f, 0x10, 0x67, 0xa5, 0x13, 0x0d, 0x0b, 0x02, 0x03, 0x52, -0x05, 0x2b, 0x6d, 0x61, 0xb6, 0x00, 0x01, 0x93, 0x17, 0x00, -0x52, 0x0d, 0x31, 0x6d, 0x70, 0x74, 0xc8, 0x01, 0x16, 0x67, -0x8c, 0x00, 0x05, 0x6c, 0x12, 0x30, 0x62, 0x65, 0x66, 0xf1, -0x03, 0x00, 0x63, 0x17, 0x41, 0x69, 0x6e, 0x64, 0x73, 0x70, -0x00, 0x10, 0x68, 0x30, 0x0f, 0x02, 0x21, 0x01, 0x22, 0x00, -0x66, 0xcc, 0x0c, 0x31, 0x2e, 0x00, 0x42, 0xa5, 0x02, 0x23, -0x70, 0x61, 0x0a, 0x03, 0xc1, 0x77, 0x61, 0x69, 0x74, 0x2c, -0x00, 0x65, 0x73, 0x70, 0x65, 0x63, 0x69, 0x31, 0x01, 0x26, -0x69, 0x66, 0x9e, 0x06, 0x0a, 0xfe, 0x04, 0x95, 0x64, 0x00, -0x61, 0x00, 0x6c, 0x61, 0x72, 0x67, 0x65, 0xe0, 0x12, 0x50, -0x69, 0x7a, 0x65, 0x2e, 0x00, +0x2d, 0x01, 0x00, 0xf0, 0x42, 0x00, 0x00, 0x00, 0x59, 0x6f, +0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x73, +0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x67, 0x72, 0x69, 0x64, +0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x69, 0x73, +0x00, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x00, 0x69, +0x6e, 0x74, 0x6f, 0x00, 0x61, 0x73, 0x00, 0x6d, 0x61, 0x6e, +0x79, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x00, +0x73, 0x69, 0x7a, 0x65, 0x64, 0x00, 0x73, 0x75, 0x62, 0x2d, +0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x21, 0x00, 0x22, 0x74, +0x68, 0x44, 0x00, 0xf4, 0x00, 0x00, 0x68, 0x61, 0x73, 0x00, +0x72, 0x6f, 0x77, 0x73, 0x2e, 0x00, 0x45, 0x61, 0x63, 0x68, +0x5f, 0x00, 0xc1, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x62, 0x65, +0x00, 0x66, 0x69, 0x6c, 0x6c, 0x57, 0x00, 0xf1, 0x08, 0x00, +0x77, 0x69, 0x74, 0x68, 0x00, 0x61, 0x00, 0x64, 0x69, 0x67, +0x69, 0x74, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x31, 0x00, +0x74, 0x6f, 0x48, 0x00, 0x00, 0x60, 0x00, 0x35, 0x00, 0x6f, +0x66, 0x54, 0x00, 0x10, 0x2c, 0x30, 0x00, 0x30, 0x73, 0x75, +0x63, 0x30, 0x00, 0xf0, 0x03, 0x77, 0x61, 0x79, 0x00, 0x74, +0x68, 0x61, 0x74, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x65, 0x76, +0x65, 0x72, 0x79, 0x6e, 0x00, 0xf1, 0x0d, 0x00, 0x63, 0x6f, +0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x00, 0x6f, 0x6e, 0x6c, +0x79, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0x6f, 0x63, 0x63, 0x75, +0x72, 0x72, 0x65, 0x6e, 0x63, 0x4b, 0x00, 0x10, 0x65, 0x8c, +0x00, 0x02, 0x6c, 0x00, 0x06, 0x39, 0x00, 0x6f, 0x63, 0x6f, +0x6c, 0x75, 0x6d, 0x6e, 0x3c, 0x00, 0x23, 0x01, 0xfa, 0x00, +0x0f, 0x3b, 0x00, 0x18, 0x11, 0x2e, 0x3c, 0x00, 0x70, 0x28, +0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x01, 0xf2, 0x02, +0x2c, 0x00, 0x62, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, +0x6c, 0x74, 0x00, 0x6f, 0x66, 0x66, 0x29, 0x2d, 0x00, 0x03, +0xf7, 0x00, 0x02, 0x37, 0x01, 0xf0, 0x01, 0x27, 0x73, 0x00, +0x74, 0x77, 0x6f, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x64, +0x69, 0x61, 0x67, 0x3a, 0x00, 0x1f, 0x73, 0x75, 0x00, 0x1c, +0x00, 0xeb, 0x01, 0x01, 0xe1, 0x01, 0x85, 0x69, 0x76, 0x65, +0x6e, 0x00, 0x73, 0x6f, 0x6d, 0x5b, 0x01, 0x61, 0x6e, 0x75, +0x6d, 0x62, 0x65, 0x72, 0xbe, 0x01, 0xf0, 0x00, 0x63, 0x6c, +0x75, 0x65, 0x73, 0x3b, 0x00, 0x79, 0x6f, 0x75, 0x72, 0x00, +0x61, 0x69, 0x6d, 0x02, 0x02, 0x81, 0x74, 0x6f, 0x00, 0x70, +0x6c, 0x61, 0x63, 0x65, 0x2b, 0x00, 0x4c, 0x72, 0x65, 0x73, +0x74, 0x37, 0x00, 0x90, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, +0x74, 0x6c, 0x79, 0x66, 0x00, 0x51, 0x55, 0x6e, 0x64, 0x65, +0x72, 0x1f, 0x00, 0x04, 0xd3, 0x00, 0x92, 0x73, 0x65, 0x74, +0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0xd0, 0x00, 0x07, 0x2d, +0x02, 0x24, 0x72, 0x65, 0x16, 0x02, 0x30, 0x6f, 0x72, 0x00, +0x43, 0x00, 0xa7, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, +0x2e, 0x00, 0x54, 0x40, 0x00, 0x53, 0x70, 0x75, 0x7a, 0x7a, +0x6c, 0x0c, 0x02, 0xf3, 0x05, 0x69, 0x73, 0x00, 0x33, 0x78, +0x33, 0x00, 0x28, 0x61, 0x00, 0x39, 0x78, 0x39, 0x00, 0x61, +0x63, 0x74, 0x75, 0x61, 0x6c, 0x1a, 0x02, 0x09, 0xa9, 0x02, +0x41, 0x6e, 0x69, 0x6e, 0x65, 0x2a, 0x00, 0x02, 0x6b, 0x00, +0x21, 0x29, 0x2e, 0xfe, 0x00, 0xf1, 0x00, 0x63, 0x61, 0x6e, +0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x73, 0x65, 0x6c, 0x65, +0x63, 0x74, 0x53, 0x00, 0x12, 0x73, 0x80, 0x02, 0x07, 0x7e, +0x00, 0x13, 0x00, 0x9f, 0x00, 0x70, 0x69, 0x6e, 0x73, 0x74, +0x65, 0x61, 0x64, 0xee, 0x00, 0x04, 0xa6, 0x00, 0x43, 0x6e, +0x65, 0x73, 0x2c, 0x80, 0x02, 0x32, 0x73, 0x00, 0x32, 0x89, +0x00, 0x32, 0x36, 0x78, 0x36, 0xf0, 0x02, 0x09, 0x81, 0x00, +0x76, 0x73, 0x69, 0x78, 0x00, 0x33, 0x78, 0x32, 0x80, 0x00, +0xb0, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, +0x76, 0x65, 0xf3, 0x01, 0x13, 0x79, 0x8f, 0x00, 0x03, 0x8a, +0x00, 0xd1, 0x60, 0x6a, 0x69, 0x67, 0x73, 0x61, 0x77, 0x27, +0x00, 0x6d, 0x6f, 0x64, 0x65, 0xe6, 0x02, 0x02, 0x81, 0x03, +0x0f, 0x32, 0x01, 0x00, 0xe0, 0x61, 0x72, 0x62, 0x69, 0x74, +0x72, 0x61, 0x72, 0x79, 0x00, 0x73, 0x68, 0x61, 0x70, 0xc0, +0x00, 0x21, 0x68, 0x69, 0xe7, 0x01, 0xf1, 0x00, 0x66, 0x66, +0x65, 0x72, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, +0x00, 0x69, 0x6e, 0x8f, 0x00, 0x00, 0x1f, 0x01, 0x02, 0x40, +0x01, 0x10, 0x73, 0x9d, 0x01, 0xf1, 0x02, 0x41, 0x6e, 0x6f, +0x74, 0x68, 0x65, 0x72, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x70, 0x00, 0x00, 0x56, 0x01, 0x20, +0x60, 0x6b, 0x90, 0x03, 0xb3, 0x72, 0x27, 0x2e, 0x00, 0x49, +0x6e, 0x00, 0x74, 0x68, 0x69, 0x73, 0x8a, 0x00, 0x01, 0x10, +0x02, 0x01, 0x78, 0x00, 0x33, 0x6e, 0x6f, 0x74, 0x3b, 0x02, +0x21, 0x69, 0x6e, 0x98, 0x00, 0x40, 0x66, 0x6f, 0x72, 0x6d, +0x1d, 0x01, 0x02, 0xca, 0x03, 0x33, 0x2d, 0x69, 0x6e, 0x27, +0x01, 0x24, 0x73, 0x3b, 0x3b, 0x01, 0x16, 0x2c, 0x0d, 0x04, +0x0c, 0x4a, 0x04, 0x91, 0x60, 0x63, 0x61, 0x67, 0x65, 0x73, +0x27, 0x00, 0x62, 0x7d, 0x03, 0x81, 0x6f, 0x75, 0x72, 0x65, +0x64, 0x00, 0x6c, 0x69, 0x60, 0x01, 0x30, 0x61, 0x6e, 0x64, +0x5c, 0x00, 0x02, 0xbe, 0x02, 0x00, 0x27, 0x00, 0x02, 0x46, +0x00, 0x91, 0x61, 0x6d, 0x65, 0x00, 0x74, 0x65, 0x6c, 0x6c, +0x73, 0x3c, 0x01, 0x10, 0x77, 0xfa, 0x03, 0x02, 0x1e, 0x01, +0x01, 0x85, 0x00, 0x32, 0x61, 0x6c, 0x6c, 0x75, 0x02, 0x00, +0xee, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x1c, 0x04, 0x01, 0x3f, +0x00, 0x90, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x62, +0x65, 0x86, 0x01, 0x63, 0x73, 0x6f, 0x2c, 0x00, 0x6e, 0x6f, +0xc6, 0x03, 0xe0, 0x6d, 0x61, 0x79, 0x00, 0x61, 0x70, 0x70, +0x65, 0x61, 0x72, 0x00, 0x6d, 0x6f, 0x72, 0x69, 0x00, 0x40, +0x61, 0x6e, 0x00, 0x6f, 0x3e, 0x03, 0x00, 0x15, 0x02, 0x41, +0x69, 0x6e, 0x00, 0x61, 0x42, 0x00, 0x31, 0x2c, 0x00, 0x65, +0xf8, 0x00, 0x02, 0xf7, 0x02, 0x01, 0x54, 0x00, 0x62, 0x63, +0x72, 0x6f, 0x73, 0x73, 0x65, 0xee, 0x04, 0xa1, 0x62, 0x6f, +0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, 0x65, 0x73, 0x75, 0x03, +0x30, 0x78, 0x69, 0x73, 0xf0, 0x02, 0x71, 0x00, 0x72, 0x65, +0x67, 0x69, 0x6f, 0x6e, 0x78, 0x01, 0x21, 0x49, 0x66, 0xb5, +0x00, 0x03, 0xed, 0x01, 0x19, 0x61, 0xd3, 0x02, 0x02, 0xbf, +0x01, 0x87, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, +0x88, 0x00, 0x13, 0x39, 0xcd, 0x00, 0x02, 0x46, 0x01, 0x42, +0x61, 0x64, 0x64, 0x69, 0x32, 0x04, 0x04, 0xe4, 0x00, 0x40, +0x77, 0x69, 0x6c, 0x6c, 0x4a, 0x05, 0x40, 0x6c, 0x65, 0x74, +0x74, 0x87, 0x03, 0x03, 0x96, 0x03, 0xb0, 0x61, 0x6c, 0x70, +0x68, 0x61, 0x62, 0x65, 0x74, 0x2e, 0x00, 0x46, 0x45, 0x01, +0x50, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x53, 0x02, 0x09, 0x83, +0x00, 0x30, 0x33, 0x78, 0x34, 0x2d, 0x00, 0x18, 0x6e, 0x34, +0x01, 0x02, 0x89, 0x00, 0x20, 0x67, 0x6f, 0x3d, 0x01, 0x01, +0x00, 0x04, 0x01, 0xb9, 0x01, 0x04, 0x66, 0x00, 0x01, 0x94, +0x05, 0xf1, 0x01, 0x39, 0x2c, 0x00, 0x70, 0x6c, 0x75, 0x73, +0x00, 0x60, 0x61, 0x27, 0x2c, 0x00, 0x60, 0x62, 0x27, 0xac, +0x01, 0x30, 0x60, 0x63, 0x27, 0xb1, 0x03, 0x20, 0x69, 0x73, +0xd1, 0x02, 0x21, 0x6e, 0x6f, 0xde, 0x05, 0x02, 0x67, 0x00, +0x12, 0x65, 0xc9, 0x01, 0x02, 0x5b, 0x02, 0x08, 0x88, 0x02, +0xb2, 0x49, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, 0x00, 0x73, +0x61, 0x77, 0x6d, 0x02, 0x03, 0x11, 0x01, 0xf2, 0x0d, 0x69, +0x6e, 0x00, 0x4e, 0x69, 0x6b, 0x6f, 0x6c, 0x69, 0x00, 0x5b, +0x35, 0x5d, 0x2c, 0x00, 0x61, 0x6c, 0x74, 0x68, 0x6f, 0x75, +0x67, 0x68, 0x00, 0x69, 0x74, 0x27, 0x73, 0xba, 0x03, 0x10, +0x62, 0xdd, 0x02, 0x30, 0x70, 0x6f, 0x70, 0xa9, 0x03, 0x40, +0x69, 0x73, 0x65, 0x64, 0x41, 0x02, 0xf0, 0x00, 0x76, 0x61, +0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x6e, 0x65, 0x77, 0x73, +0x70, 0x61, 0x70, 0x0c, 0x01, 0x15, 0x75, 0x86, 0x04, 0x10, +0x6e, 0x38, 0x02, 0x80, 0x60, 0x53, 0x75, 0x64, 0x6f, 0x6b, +0x75, 0x27, 0x68, 0x04, 0x50, 0x60, 0x53, 0x75, 0x00, 0x44, +0x0d, 0x00, 0xf1, 0x01, 0x2e, 0x00, 0x48, 0x6f, 0x77, 0x61, +0x72, 0x64, 0x00, 0x47, 0x61, 0x72, 0x6e, 0x73, 0x00, 0x69, +0x50, 0x05, 0x40, 0x73, 0x69, 0x64, 0x65, 0x8c, 0x02, 0x20, +0x74, 0x68, 0x8e, 0x00, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x6f, +0x72, 0x5a, 0x01, 0x00, 0x12, 0x03, 0x25, 0x72, 0x6e, 0xf8, +0x02, 0x00, 0x13, 0x00, 0x02, 0xb8, 0x00, 0x02, 0xb4, 0x02, +0x63, 0x69, 0x74, 0x00, 0x77, 0x61, 0x73, 0xda, 0x00, 0x72, +0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0xe2, 0x06, 0xd2, +0x44, 0x65, 0x6c, 0x6c, 0x20, 0x50, 0x65, 0x6e, 0x63, 0x69, +0x6c, 0x20, 0x50, 0x06, 0x01, 0xd0, 0x20, 0x61, 0x6e, 0x64, +0x20, 0x57, 0x6f, 0x72, 0x64, 0x20, 0x47, 0x61, 0x6d, 0x15, +0x01, 0x12, 0x41, 0xfa, 0x01, 0xf5, 0x03, 0x65, 0x6c, 0x61, +0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x00, 0x74, 0x72, 0x65, +0x61, 0x74, 0x6d, 0x65, 0x6e, 0x6f, 0x05, 0x7a, 0x68, 0x69, +0x73, 0x74, 0x6f, 0x72, 0x79, 0x7b, 0x00, 0x01, 0x45, 0x04, +0x00, 0x4f, 0x07, 0x00, 0x84, 0x02, 0xf0, 0x02, 0x00, 0x6f, +0x6e, 0x00, 0x57, 0x69, 0x6b, 0x69, 0x70, 0x65, 0x64, 0x69, +0x61, 0x00, 0x5b, 0x36, 0x5d, 0x6c, 0x01, 0xf1, 0x02, 0x5b, +0x35, 0x5d, 0x00, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, +0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x61, 0x01, 0xa3, 0x2e, +0x63, 0x6f, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6e, 0x2f, 0x97, +0x01, 0x21, 0x2f, 0x73, 0x23, 0x01, 0x10, 0x2f, 0x32, 0x00, +0x12, 0x36, 0x32, 0x00, 0x74, 0x3a, 0x2f, 0x2f, 0x65, 0x6e, +0x2e, 0x77, 0x51, 0x00, 0x50, 0x2e, 0x6f, 0x72, 0x67, 0x2f, +0x0e, 0x00, 0x12, 0x2f, 0x4e, 0x01, 0x72, 0x00, 0x00, 0x00, +0x31, 0x31, 0x2e, 0x31, 0x5c, 0x08, 0x00, 0x8b, 0x06, 0x91, +0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x31, +0x06, 0x20, 0x79, 0x00, 0x19, 0x00, 0xe3, 0x2c, 0x00, 0x73, +0x69, 0x6d, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0x47, 0x01, 0x21, 0x75, 0x73, 0xeb, 0x01, 0x01, 0x4a, +0x08, 0x44, 0x6d, 0x70, 0x74, 0x79, 0x60, 0x05, 0x00, 0x46, +0x01, 0x02, 0x96, 0x02, 0x35, 0x79, 0x70, 0x65, 0x13, 0x08, +0x23, 0x6f, 0x72, 0xe3, 0x02, 0x22, 0x00, 0x6f, 0xb0, 0x02, +0x50, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0xb9, 0x01, 0x21, 0x74, +0x6f, 0x7d, 0x04, 0x02, 0xeb, 0x03, 0x02, 0x44, 0x00, 0x14, +0x2e, 0x6c, 0x03, 0x30, 0x6d, 0x61, 0x6b, 0x43, 0x00, 0x8f, +0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2c, 0x80, 0x00, +0x01, 0x02, 0xe4, 0x01, 0x03, 0xbe, 0x06, 0x08, 0x84, 0x00, +0x81, 0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0xf5, +0x06, 0x40, 0x6f, 0x00, 0x63, 0x6c, 0x21, 0x04, 0x50, 0x69, +0x74, 0x00, 0x61, 0x67, 0x80, 0x07, 0x62, 0x28, 0x6f, 0x72, +0x00, 0x75, 0x73, 0x96, 0x04, 0xd7, 0x55, 0x6e, 0x64, 0x6f, +0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x29, 0xea, +0x03, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x74, 0x00, +0x01, 0x47, 0x04, 0x0f, 0xe2, 0x00, 0x04, 0x02, 0x43, 0x07, +0x12, 0x2c, 0xc2, 0x00, 0x02, 0x0d, 0x00, 0x05, 0x72, 0x03, +0x52, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x41, 0x02, 0x06, 0x09, +0x08, 0x00, 0x79, 0x06, 0x41, 0x61, 0x00, 0x60, 0x70, 0x4d, +0x02, 0x66, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x27, 0xdc, 0x06, +0x01, 0xc9, 0x09, 0x07, 0x1b, 0x00, 0x11, 0x73, 0x7f, 0x03, +0x76, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0xb0, 0x07, +0x04, 0x51, 0x00, 0x00, 0x1a, 0x03, 0x04, 0x36, 0x01, 0x12, +0x53, 0xbb, 0x05, 0x04, 0x53, 0x08, 0x00, 0xc0, 0x04, 0x06, +0xd8, 0x05, 0x05, 0xe9, 0x07, 0x02, 0xe0, 0x03, 0x01, 0x89, +0x03, 0x03, 0x29, 0x00, 0x09, 0x6f, 0x00, 0x10, 0x2e, 0xfd, +0x01, 0x04, 0xac, 0x05, 0x40, 0x70, 0x61, 0x79, 0x73, 0x6a, +0x05, 0x50, 0x61, 0x74, 0x74, 0x65, 0x6e, 0xba, 0x04, 0x01, +0x49, 0x08, 0x07, 0x2e, 0x00, 0x40, 0x2c, 0x00, 0x73, 0x6f, +0xa0, 0x04, 0x00, 0x3a, 0x08, 0x02, 0xd0, 0x05, 0x00, 0x3a, +0x01, 0x03, 0x5a, 0x01, 0x11, 0x6d, 0xbb, 0x00, 0x50, 0x69, +0x73, 0x00, 0x75, 0x70, 0x38, 0x00, 0x45, 0x79, 0x6f, 0x75, +0x3a, 0x34, 0x07, 0x05, 0x23, 0x00, 0x00, 0x61, 0x0a, 0x30, +0x65, 0x6d, 0x69, 0xec, 0x03, 0x12, 0x73, 0x43, 0x01, 0x81, +0x61, 0x00, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0xc8, 0x07, +0x03, 0x32, 0x01, 0x41, 0x6e, 0x65, 0x65, 0x64, 0xc6, 0x08, +0x10, 0x62, 0xbf, 0x08, 0x10, 0x2d, 0x12, 0x05, 0x42, 0x69, +0x6e, 0x65, 0x64, 0xe8, 0x05, 0x00, 0x54, 0x00, 0x42, 0x6b, +0x6e, 0x6f, 0x77, 0x7e, 0x03, 0x4b, 0x61, 0x62, 0x6f, 0x75, +0x45, 0x00, 0x04, 0xa2, 0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, +0x02, 0x55, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x93, 0x03, 0x5a, +0x6f, 0x73, 0x73, 0x69, 0x62, 0x6a, 0x01, 0x14, 0x61, 0x70, +0x09, 0x01, 0x8d, 0x00, 0x01, 0x48, 0x00, 0x50, 0x61, 0x6e, +0x79, 0x74, 0x68, 0x62, 0x01, 0x32, 0x65, 0x6c, 0x73, 0x82, +0x00, 0xa2, 0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, 0x69, 0x6b, +0x65, 0x2e, 0x3f, 0x03, 0x41, 0x65, 0x72, 0x61, 0x73, 0x93, +0x0b, 0x49, 0x69, 0x6e, 0x67, 0x6c, 0xd3, 0x01, 0x1c, 0x2c, +0x5b, 0x02, 0x08, 0x1b, 0x02, 0x22, 0x6e, 0x64, 0x58, 0x02, +0x05, 0xde, 0x01, 0x03, 0x52, 0x02, 0x01, 0xb8, 0x02, 0x01, +0x00, 0x08, 0x2a, 0x6c, 0x6c, 0x20, 0x02, 0x09, 0x9c, 0x02, +0x22, 0x72, 0x65, 0x79, 0x00, 0x30, 0x64, 0x00, 0x77, 0xa3, +0x02, 0x00, 0x99, 0x00, 0x34, 0x6c, 0x65, 0x66, 0x6c, 0x00, +0x05, 0x5e, 0x00, 0x18, 0x61, 0x14, 0x01, 0x0f, 0x2a, 0x00, +0x05, 0x02, 0x43, 0x03, 0x10, 0x73, 0x43, 0x03, 0x36, 0x2e, +0x00, 0x52, 0xb3, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x20, 0x00, +0x00, 0x0d, 0x00, 0x01, 0x23, 0x00, 0x02, 0xf4, 0x02, 0x01, +0x58, 0x02, 0x02, 0xfb, 0x00, 0x0c, 0x56, 0x02, 0x0b, 0x3e, +0x09, 0x04, 0x7f, 0x03, 0x60, 0x63, 0x75, 0x72, 0x73, 0x6f, +0x72, 0x11, 0x04, 0x01, 0xe1, 0x01, 0x32, 0x6d, 0x6f, 0x76, +0x18, 0x00, 0x00, 0x38, 0x00, 0x31, 0x00, 0x61, 0x72, 0x14, +0x05, 0x04, 0x83, 0x08, 0x34, 0x2e, 0x00, 0x50, 0x74, 0x00, +0x02, 0xc9, 0x0a, 0x40, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x00, +0x86, 0x00, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x73, 0x3a, +0x00, 0x11, 0x28, 0x86, 0x0c, 0x82, 0x61, 0x00, 0x6e, 0x6f, +0x72, 0x6d, 0x61, 0x6c, 0x14, 0x00, 0x00, 0xfe, 0x0c, 0x08, +0x97, 0x00, 0x24, 0x29, 0x2c, 0x12, 0x01, 0x01, 0xd3, 0x00, +0x04, 0x6b, 0x01, 0x20, 0x69, 0x6e, 0xb5, 0x02, 0x0f, 0xbb, +0x03, 0x03, 0x03, 0x0e, 0x00, 0x80, 0x61, 0x70, 0x70, 0x72, +0x6f, 0x70, 0x72, 0x69, 0xe5, 0x05, 0x44, 0x77, 0x61, 0x79, +0x3b, 0x44, 0x00, 0x01, 0x8c, 0x01, 0x21, 0x30, 0x00, 0x5e, +0x04, 0x04, 0xa6, 0x00, 0x02, 0x1e, 0x01, 0x23, 0x62, 0x61, +0x16, 0x04, 0x02, 0x8a, 0x04, 0x14, 0x61, 0x3d, 0x0d, 0x04, +0xbd, 0x03, 0x43, 0x00, 0x00, 0x28, 0x41, 0x00, 0x09, 0x30, +0x61, 0x63, 0x74, 0x75, 0x08, 0x82, 0x00, 0x64, 0x65, 0x73, +0x63, 0x72, 0x69, 0x62, 0x84, 0x00, 0x31, 0x73, 0x65, 0x63, +0x81, 0x03, 0x32, 0x32, 0x2e, 0x31, 0x43, 0x0a, 0x00, 0x69, +0x01, 0x05, 0x04, 0x0a, 0x22, 0x2e, 0x29, 0xca, 0x05, 0x12, +0x32, 0xca, 0x05, 0x60, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, +0x52, 0x08, 0x00, 0xcc, 0x05, 0x00, 0x13, 0x00, 0x00, 0x5d, +0x09, 0x22, 0x6f, 0x77, 0x78, 0x09, 0x11, 0x74, 0xfa, 0x03, +0x40, 0x66, 0x69, 0x67, 0x75, 0xa7, 0x08, 0x10, 0x77, 0x4b, +0x0b, 0x00, 0x31, 0x00, 0x10, 0x74, 0x46, 0x08, 0x41, 0x6d, +0x65, 0x6e, 0x73, 0x7d, 0x00, 0x0a, 0xa2, 0x06, 0x01, 0x47, +0x08, 0x03, 0xbb, 0x05, 0xc7, 0x60, 0x54, 0x79, 0x70, 0x65, +0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x3a, 0x44, 0x0c, 0x00, +0x32, 0x00, 0x02, 0x84, 0x0d, 0x03, 0x00, 0x0a, 0x0a, 0x1b, +0x00, 0x00, 0x46, 0x0e, 0x12, 0x2c, 0x38, 0x0a, 0x06, 0x17, +0x0b, 0x01, 0x0c, 0x0d, 0x0b, 0x5c, 0x0a, 0x47, 0x2e, 0x00, +0x28, 0x54, 0x37, 0x0e, 0x13, 0x61, 0x9d, 0x0d, 0x25, 0x69, +0x73, 0xd0, 0x07, 0x23, 0x72, 0x73, 0xf6, 0x0c, 0x5f, 0x69, +0x73, 0x3a, 0x00, 0x66, 0x21, 0x09, 0x07, 0x14, 0x32, 0x90, +0x00, 0x01, 0x8f, 0x00, 0x13, 0x33, 0x83, 0x00, 0x01, 0x93, +0x0a, 0x03, 0x76, 0x0c, 0x02, 0x5b, 0x00, 0x01, 0x97, 0x01, +0x01, 0x78, 0x05, 0x19, 0x33, 0x32, 0x00, 0x12, 0x32, 0xfb, +0x0e, 0x16, 0x29, 0x13, 0x06, 0x14, 0x74, 0x80, 0x06, 0xd2, +0x60, 0x58, 0x27, 0x00, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, +0x6f, 0x78, 0x2c, 0x61, 0x01, 0x02, 0xff, 0x02, 0x10, 0x70, +0x28, 0x07, 0x00, 0x22, 0x00, 0x04, 0x1c, 0x0e, 0x61, 0x00, +0x65, 0x78, 0x74, 0x72, 0x61, 0x97, 0x08, 0x50, 0x74, 0x72, +0x61, 0x69, 0x6e, 0xf2, 0x0a, 0x03, 0xf7, 0x0a, 0x0e, 0x0e, +0x0e, 0x08, 0x28, 0x0f, 0x0a, 0xa3, 0x05, 0x01, 0x19, 0x0e, +0x13, 0x66, 0xaf, 0x0e, 0x03, 0x0f, 0x0e, 0x11, 0x28, 0xb1, +0x09, 0x21, 0x69, 0x73, 0x08, 0x0e, 0x51, 0x74, 0x69, 0x6d, +0x65, 0x73, 0x07, 0x05, 0x10, 0x6e, 0xd4, 0x04, 0x03, 0x2e, +0x09, 0x30, 0x2d, 0x58, 0x27, 0x3d, 0x02, 0x06, 0x56, 0x09, +0x2b, 0x2e, 0x29, 0x1d, 0x0c, 0x06, 0xdc, 0x02, 0x00, 0x83, +0x0e, 0x0f, 0x98, 0x00, 0x05, 0x04, 0xd0, 0x06, 0x40, 0x73, +0x68, 0x61, 0x64, 0xb5, 0x02, 0x10, 0x6c, 0x0e, 0x04, 0x00, +0x3d, 0x10, 0x12, 0x6f, 0xcf, 0x00, 0x05, 0x83, 0x05, 0x01, +0xe6, 0x09, 0x20, 0x65, 0x6e, 0x94, 0x02, 0x2f, 0x64, 0x2e, +0x39, 0x01, 0x01, 0x13, 0x4a, 0x25, 0x0d, 0x0f, 0x3e, 0x01, +0x01, 0x41, 0x67, 0x65, 0x6e, 0x65, 0x88, 0x02, 0x73, 0x72, +0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6c, 0x1f, 0x0d, 0x08, 0x9e, +0x10, 0x1e, 0x2e, 0xbf, 0x00, 0x08, 0x43, 0x0e, 0x03, 0x8f, +0x0b, 0x03, 0xae, 0x00, 0x00, 0x36, 0x08, 0x13, 0x6e, 0x36, +0x06, 0x01, 0xcd, 0x02, 0x5d, 0x72, 0x6f, 0x64, 0x75, 0x63, +0xfc, 0x0e, 0x0b, 0xea, 0x03, 0x22, 0x60, 0x43, 0x04, 0x02, +0x03, 0x1a, 0x0b, 0x30, 0x52, 0x6f, 0x77, 0xe4, 0x0c, 0x41, +0x6f, 0x78, 0x65, 0x73, 0xd4, 0x0e, 0x00, 0x05, 0x04, 0x01, +0x15, 0x07, 0x50, 0x72, 0x65, 0x61, 0x73, 0x6f, 0xe5, 0x0d, +0x34, 0x79, 0x00, 0x79, 0x82, 0x11, 0x22, 0x74, 0x6f, 0x4e, +0x00, 0x06, 0x4d, 0x04, 0x10, 0x67, 0x03, 0x0a, 0x22, 0x65, +0x72, 0x0f, 0x0c, 0x10, 0x31, 0x64, 0x00, 0x42, 0x62, 0x6f, +0x74, 0x68, 0x50, 0x00, 0x22, 0x3b, 0x00, 0x0e, 0x01, 0x02, +0xc2, 0x0d, 0x21, 0x68, 0x61, 0x57, 0x00, 0x07, 0x2a, 0x02, +0x03, 0x90, 0x01, 0x05, 0xd9, 0x00, 0x05, 0xa4, 0x0a, 0x00, +0xc2, 0x06, 0x01, 0xcf, 0x0c, 0x20, 0x62, 0x65, 0xd2, 0x04, +0x26, 0x72, 0x69, 0x28, 0x06, 0x2a, 0x69, 0x66, 0x8e, 0x06, +0x3f, 0x00, 0x69, 0x74, 0x88, 0x01, 0x02, 0x12, 0x4b, 0x2c, +0x0e, 0x0f, 0x88, 0x01, 0x0b, 0x10, 0x61, 0xf9, 0x0f, 0x00, +0x2f, 0x01, 0x00, 0xdc, 0x03, 0x00, 0xed, 0x0d, 0x04, 0x55, +0x12, 0x2e, 0x61, 0x72, 0xa5, 0x01, 0x00, 0x9c, 0x00, 0x41, +0x64, 0x72, 0x61, 0x77, 0x5d, 0x0e, 0x00, 0x84, 0x0d, 0x20, +0x75, 0x74, 0x0e, 0x0e, 0x02, 0xc5, 0x03, 0x02, 0xdb, 0x0e, +0x00, 0x0a, 0x0b, 0x02, 0x2b, 0x0e, 0x03, 0x51, 0x12, 0x02, +0x8a, 0x01, 0x24, 0x73, 0x65, 0x69, 0x0d, 0x06, 0x0f, 0x11, +0x51, 0x61, 0x00, 0x73, 0x6d, 0x61, 0x74, 0x0c, 0x00, 0xbf, +0x0e, 0x03, 0x77, 0x00, 0x20, 0x73, 0x68, 0xc4, 0x04, 0x05, +0xf0, 0x0c, 0x0c, 0x39, 0x0e, 0x04, 0xc8, 0x02, 0x13, 0x69, +0x23, 0x02, 0x02, 0x55, 0x00, 0x04, 0x38, 0x11, 0x05, 0x3a, +0x10, 0x07, 0xfd, 0x04, 0x22, 0x68, 0x65, 0x10, 0x07, 0x00, +0x20, 0x10, 0x71, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x79, +0x65, 0x00, 0x05, 0x21, 0x0f, 0x04, 0x0b, 0x01, 0x16, 0x64, +0xfb, 0x0c, 0x10, 0x4d, 0x66, 0x08, 0x05, 0x2e, 0x00, 0x00, +0xa4, 0x0a, 0x17, 0x73, 0x2b, 0x05, 0x60, 0x73, 0x00, 0x6c, +0x6f, 0x6f, 0x6b, 0x1c, 0x07, 0x30, 0x74, 0x74, 0x69, 0xcd, +0x0f, 0x13, 0x75, 0xa3, 0x0e, 0x00, 0x7a, 0x00, 0x01, 0xd1, +0x0a, 0x01, 0x77, 0x08, 0x60, 0x65, 0x61, 0x73, 0x69, 0x65, +0x72, 0x5a, 0x0b, 0x13, 0x6e, 0x96, 0x11, 0x05, 0x52, 0x00, +0x06, 0x01, 0x02, 0x01, 0xae, 0x09, 0x00, 0xe2, 0x04, 0x22, +0x63, 0x65, 0xdc, 0x08, 0x02, 0xca, 0x0f, 0x01, 0x4b, 0x02, +0x60, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x43, 0x10, 0x02, +0xe0, 0x02, 0x00, 0x8d, 0x07, 0x70, 0x65, 0x6e, 0x74, 0x2e, +0x00, 0x43, 0x6f, 0x0c, 0x05, 0x63, 0x74, 0x65, 0x6c, 0x79, +0x00, 0x61, 0x54, 0x00, 0x25, 0x69, 0x63, 0x9d, 0x00, 0x02, +0xa6, 0x02, 0x00, 0xfa, 0x0f, 0x86, 0x72, 0x65, 0x65, 0x64, +0x6f, 0x6d, 0x00, 0x74, 0x64, 0x04, 0x00, 0xf9, 0x0c, 0x24, +0x65, 0x77, 0x2f, 0x10, 0x15, 0x73, 0x0b, 0x09, 0x00, 0x41, +0x01, 0x23, 0x46, 0x69, 0xe8, 0x12, 0x04, 0x41, 0x09, 0x0a, +0x45, 0x01, 0x00, 0xdf, 0x01, 0x00, 0x6d, 0x09, 0x15, 0x74, +0xdb, 0x0c, 0x0f, 0x39, 0x01, 0x00, 0x16, 0x44, 0x25, 0x00, +0x52, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x94, 0x10, 0x42, 0x6a, +0x75, 0x64, 0x67, 0x04, 0x0e, 0x01, 0x0e, 0x08, 0x01, 0xbe, +0x00, 0x26, 0x78, 0x69, 0x49, 0x00, 0x82, 0x74, 0x65, 0x63, +0x68, 0x6e, 0x69, 0x71, 0x75, 0x9a, 0x0f, 0x42, 0x64, 0x65, +0x64, 0x75, 0x09, 0x07, 0x03, 0x6e, 0x0f, 0x01, 0x42, 0x0c, +0x57, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x85, 0x01, 0x12, 0x3a, +0xe6, 0x05, 0x01, 0x66, 0x00, 0x06, 0x97, 0x0f, 0x12, 0x61, +0x68, 0x03, 0x23, 0x6f, 0x66, 0xbb, 0x03, 0x00, 0xa1, 0x07, +0x02, 0x58, 0x02, 0x11, 0x77, 0x7b, 0x03, 0x17, 0x74, 0x55, +0x01, 0x23, 0x69, 0x6e, 0x32, 0x04, 0x21, 0x65, 0x76, 0x98, +0x0e, 0x31, 0x6f, 0x6e, 0x65, 0x7b, 0x04, 0x06, 0x56, 0x0a, +0x10, 0x2c, 0x9f, 0x03, 0x1d, 0x64, 0xd3, 0x00, 0x83, 0x60, +0x54, 0x72, 0x69, 0x76, 0x69, 0x61, 0x6c, 0x3e, 0x04, 0x70, +0x42, 0x61, 0x73, 0x69, 0x63, 0x27, 0x00, 0xb2, 0x11, 0x06, +0x98, 0x04, 0x05, 0xaf, 0x09, 0x04, 0x4d, 0x01, 0x01, 0x02, +0x0d, 0x06, 0x47, 0x15, 0x03, 0x33, 0x0a, 0x04, 0xfa, 0x09, +0x12, 0x74, 0xe1, 0x02, 0x22, 0x69, 0x6d, 0x80, 0x03, 0x10, +0x65, 0xbe, 0x00, 0x00, 0x16, 0x00, 0x20, 0x60, 0x49, 0x6b, +0x04, 0x30, 0x6d, 0x65, 0x64, 0x87, 0x08, 0x13, 0x27, 0xee, +0x00, 0x20, 0x61, 0x6e, 0x26, 0x11, 0x42, 0x79, 0x6f, 0x6e, +0x64, 0x64, 0x11, 0x05, 0xdc, 0x06, 0x13, 0x74, 0x7f, 0x02, +0x01, 0xc2, 0x00, 0x26, 0x61, 0x6c, 0x4a, 0x01, 0x13, 0x73, +0x33, 0x0b, 0x01, 0x85, 0x02, 0x02, 0xef, 0x03, 0x04, 0x49, +0x03, 0x05, 0xc6, 0x04, 0x13, 0x63, 0x7e, 0x11, 0x13, 0x00, +0x3c, 0x0d, 0x07, 0x2c, 0x00, 0x04, 0x46, 0x05, 0x02, 0xac, +0x11, 0x07, 0x28, 0x00, 0x04, 0xe6, 0x00, 0x00, 0x39, 0x13, +0x52, 0x74, 0x00, 0x60, 0x55, 0x6e, 0x76, 0x01, 0x00, 0x1b, +0x06, 0x03, 0xad, 0x00, 0x03, 0x94, 0x11, 0x13, 0x74, 0xc7, +0x06, 0x00, 0x82, 0x01, 0x20, 0x65, 0x6e, 0x2d, 0x10, 0x02, +0xe9, 0x04, 0x05, 0xc0, 0x00, 0x10, 0x65, 0xc4, 0x0f, 0x02, +0xae, 0x16, 0x09, 0xcb, 0x00, 0x86, 0x61, 0x00, 0x67, 0x75, +0x65, 0x73, 0x73, 0x2c, 0x93, 0x0d, 0x70, 0x62, 0x61, 0x63, +0x6b, 0x74, 0x72, 0x61, 0x30, 0x08, 0x10, 0x66, 0x29, 0x05, +0x00, 0x20, 0x0a, 0x10, 0x73, 0x8a, 0x04, 0x03, 0x26, 0x03, +0x50, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0xd0, 0x02, 0x12, 0x47, +0x9f, 0x02, 0x00, 0x03, 0x02, 0x05, 0xc4, 0x01, 0x05, 0x25, +0x03, 0x00, 0x8f, 0x00, 0x56, 0x74, 0x73, 0x65, 0x6c, 0x66, +0x1c, 0x00, 0x1b, 0x3a, 0x5c, 0x08, 0x03, 0x90, 0x07, 0x02, +0xd4, 0x0f, 0x10, 0x67, 0x90, 0x13, 0x0d, 0x0b, 0x02, 0x03, +0x52, 0x05, 0x2b, 0x6d, 0x61, 0xb6, 0x00, 0x01, 0x7e, 0x17, +0x00, 0x52, 0x0d, 0x31, 0x6d, 0x70, 0x74, 0xc8, 0x01, 0x16, +0x67, 0x8c, 0x00, 0x05, 0x57, 0x12, 0x30, 0x62, 0x65, 0x66, +0xf1, 0x03, 0x00, 0x4e, 0x17, 0x41, 0x69, 0x6e, 0x64, 0x73, +0x70, 0x00, 0x10, 0x68, 0x30, 0x0f, 0x02, 0x21, 0x01, 0x22, +0x00, 0x66, 0xcc, 0x0c, 0x31, 0x2e, 0x00, 0x42, 0xa5, 0x02, +0x23, 0x70, 0x61, 0x0a, 0x03, 0xc1, 0x77, 0x61, 0x69, 0x74, +0x2c, 0x00, 0x65, 0x73, 0x70, 0x65, 0x63, 0x69, 0x31, 0x01, +0x26, 0x69, 0x66, 0x9e, 0x06, 0x0a, 0xfe, 0x04, 0x95, 0x64, +0x00, 0x61, 0x00, 0x6c, 0x61, 0x72, 0x67, 0x65, 0xcb, 0x12, +0x50, 0x69, 0x7a, 0x65, 0x2e, 0x00, }; -const unsigned short help_text_len = 6263; -const unsigned short help_text_words = 1155; +const unsigned short help_text_len = 6259; +const unsigned short help_text_words = 1153; const char quick_help_text[] = "Fill in the grid so that each row, column and square block contains one of every digit."; diff --git a/apps/plugins/puzzles/help/tents.c b/apps/plugins/puzzles/help/tents.c index f0617fefd4..11eeaef435 100644 --- a/apps/plugins/puzzles/help/tents.c +++ b/apps/plugins/puzzles/help/tents.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,160 +6,161 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 102, TEXT_UNDERLINE }, - { 160, TEXT_CENTER | C_RED }, - { 190, TEXT_UNDERLINE }, - { 207, TEXT_UNDERLINE }, - { 342, TEXT_CENTER | C_RED }, - { 359, TEXT_UNDERLINE }, + { 103, TEXT_UNDERLINE }, + { 161, TEXT_CENTER | C_RED }, + { 191, TEXT_UNDERLINE }, + { 208, TEXT_UNDERLINE }, + { 343, TEXT_CENTER | C_RED }, { 360, TEXT_UNDERLINE }, - { 370, TEXT_UNDERLINE }, + { 361, TEXT_UNDERLINE }, + { 371, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 2140 comp 1385 ratio 0.647196 level 10 saved 755 */ +/* orig 2158 comp 1394 ratio 0.645968 level 10 saved 764 */ const char help_text[] = { -0xf0, 0x26, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfc, 0x05, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x35, 0x3a, 0x20, 0x54, 0x65, 0x6e, 0x74, 0x73, 0x20, -0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, -0x65, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, -0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, -0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, 0x00, 0xf0, 0x05, 0x77, -0x68, 0x69, 0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, -0x69, 0x6e, 0x00, 0x74, 0x72, 0x65, 0x65, 0x73, 0x2e, 0x39, -0x00, 0xf0, 0x04, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, -0x73, 0x00, 0x74, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, -0x00, 0x74, 0x57, 0x00, 0x35, 0x00, 0x69, 0x6e, 0x3b, 0x00, -0xd6, 0x74, 0x68, 0x65, 0x00, 0x72, 0x65, 0x6d, 0x61, 0x69, -0x6e, 0x69, 0x6e, 0x67, 0x5a, 0x00, 0x00, 0x22, 0x00, 0xe1, -0x75, 0x63, 0x68, 0x00, 0x61, 0x00, 0x77, 0x61, 0x79, 0x00, -0x74, 0x68, 0x61, 0x74, 0x2a, 0x00, 0x60, 0x66, 0x6f, 0x6c, -0x6c, 0x6f, 0x77, 0x2a, 0x00, 0xf1, 0x0e, 0x63, 0x6f, 0x6e, -0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x61, 0x72, -0x65, 0x00, 0x6d, 0x65, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, -0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x13, 0x00, 0xf3, 0x00, -0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x00, 0x61, 0x73, -0x00, 0x6d, 0x61, 0x6e, 0x79, 0x7b, 0x00, 0x24, 0x61, 0x73, -0xa0, 0x00, 0x03, 0x2e, 0x00, 0x04, 0x18, 0x00, 0x22, 0x6e, -0x64, 0x19, 0x00, 0xff, 0x03, 0x00, 0x63, 0x61, 0x6e, 0x00, -0x62, 0x65, 0x00, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, -0x00, 0x75, 0x70, 0x8d, 0x00, 0x01, 0x41, 0x65, 0x61, 0x63, -0x68, 0x3a, 0x00, 0x00, 0xde, 0x00, 0x42, 0x64, 0x69, 0x72, -0x65, 0x6b, 0x00, 0x40, 0x64, 0x6a, 0x61, 0x63, 0x15, 0x00, -0x60, 0x28, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x10, 0x01, 0xd0, -0x6c, 0x6c, 0x79, 0x00, 0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, -0x74, 0x69, 0x63, 0x0e, 0x00, 0xf0, 0x01, 0x2c, 0x00, 0x62, -0x75, 0x74, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x64, 0x69, 0x61, -0x67, 0x6f, 0x6e, 0x14, 0x00, 0x10, 0x29, 0x21, 0x01, 0x62, -0x69, 0x74, 0x73, 0x00, 0x6f, 0x77, 0x3f, 0x01, 0xc2, 0x2e, -0x00, 0x48, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, 0x00, -0x61, 0x67, 0x00, 0x30, 0x6d, 0x61, 0x79, 0x96, 0x00, 0x05, -0x62, 0x00, 0x83, 0x74, 0x6f, 0x00, 0x6f, 0x74, 0x68, 0x65, -0x72, 0xb5, 0x00, 0x70, 0x61, 0x73, 0x00, 0x77, 0x65, 0x6c, -0x6c, 0x08, 0x00, 0x03, 0x48, 0x00, 0x02, 0xe1, 0x00, 0x64, -0x4e, 0x6f, 0x00, 0x74, 0x77, 0x6f, 0xe4, 0x00, 0x17, 0x72, -0x41, 0x00, 0x08, 0xa2, 0x00, 0x17, 0x2c, 0xa0, 0x00, 0x46, -0x00, 0x6f, 0x72, 0x20, 0x9a, 0x00, 0x06, 0x27, 0x01, 0x61, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xb3, 0x01, 0x04, 0xc4, -0x01, 0x01, 0x05, 0x01, 0x41, 0x72, 0x6f, 0x77, 0x2c, 0x3e, -0x01, 0x04, 0x11, 0x00, 0x73, 0x63, 0x6f, 0x6c, 0x75, 0x6d, -0x6e, 0x2c, 0x41, 0x01, 0x35, 0x73, 0x00, 0x74, 0x3d, 0x00, -0xd1, 0x73, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x72, -0x6f, 0x75, 0x6e, 0x64, 0x18, 0x00, 0x54, 0x73, 0x69, 0x64, -0x65, 0x73, 0x07, 0x02, 0x00, 0x5f, 0x02, 0x00, 0x70, 0x00, -0xb4, 0x54, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, -0x6c, 0x65, 0x8d, 0x01, 0x11, 0x66, 0x32, 0x00, 0x00, 0x88, -0x01, 0x00, 0x15, 0x01, 0x22, 0x61, 0x6c, 0x4e, 0x02, 0x41, -0x73, 0x00, 0x6f, 0x6e, 0x3a, 0x00, 0x82, 0x49, 0x6e, 0x74, -0x65, 0x72, 0x6e, 0x65, 0x74, 0x89, 0x00, 0xa1, 0x77, 0x61, -0x73, 0x00, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x27, 0x01, -0x50, 0x6d, 0x79, 0x00, 0x61, 0x74, 0xb4, 0x00, 0xf0, 0x28, -0x69, 0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x65, 0x2d, 0x6d, -0x61, 0x69, 0x6c, 0x2e, 0x00, 0x49, 0x00, 0x64, 0x6f, 0x6e, -0x27, 0x74, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x00, 0x77, 0x68, -0x6f, 0x00, 0x49, 0x00, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, -0x00, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, -0x72, 0x00, 0x69, 0x6e, 0x76, 0x3a, 0x00, 0x50, 0x6e, 0x67, -0x00, 0x69, 0x74, 0x9c, 0x00, 0x43, 0x32, 0x35, 0x2e, 0x31, -0x1c, 0x03, 0x00, 0xef, 0x02, 0x31, 0x72, 0x6f, 0x6c, 0x25, -0x03, 0xa1, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, -0x63, 0x6b, 0x2b, 0x00, 0x93, 0x6e, 0x00, 0x61, 0x00, 0x62, -0x6c, 0x61, 0x6e, 0x6b, 0xd1, 0x02, 0x43, 0x00, 0x77, 0x69, -0x6c, 0xb4, 0x00, 0x04, 0xd0, 0x01, 0x21, 0x69, 0x6e, 0x52, -0x00, 0x7f, 0x52, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x00, 0x3b, -0x00, 0x0d, 0x30, 0x63, 0x6f, 0x6c, 0x4e, 0x03, 0x80, 0x69, -0x74, 0x00, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x03, 0x41, -0x64, 0x69, 0x63, 0x61, 0x99, 0x00, 0x01, 0x90, 0x02, 0x31, -0x79, 0x6f, 0x75, 0xdf, 0x01, 0x60, 0x73, 0x75, 0x72, 0x65, -0x00, 0x69, 0x96, 0x02, 0x00, 0xdb, 0x00, 0x02, 0x6c, 0x00, -0x34, 0x2e, 0x00, 0x43, 0x5f, 0x00, 0x21, 0x65, 0x69, 0x34, -0x02, 0x61, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x00, -0xaa, 0x6e, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, -0x64, 0x71, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72, 0xf4, 0x00, -0x21, 0x49, 0x66, 0x5f, 0x00, 0x92, 0x64, 0x72, 0x61, 0x67, -0x00, 0x77, 0x69, 0x74, 0x68, 0xb4, 0x03, 0x00, 0xb9, 0x00, -0x04, 0x49, 0x00, 0x70, 0x61, 0x6c, 0x6f, 0x6e, 0x67, 0x00, -0x61, 0x0c, 0x02, 0x00, 0xed, 0x02, 0x04, 0x02, 0x02, 0x00, -0xac, 0x01, 0x1a, 0x79, 0xce, 0x00, 0x23, 0x69, 0x6e, 0xf2, -0x03, 0x10, 0x67, 0x8e, 0x01, 0x00, 0x57, 0x00, 0x52, 0x63, -0x6f, 0x76, 0x65, 0x72, 0x75, 0x00, 0x94, 0x62, 0x65, 0x00, -0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0xe6, 0x00, 0x00, 0xce, -0x01, 0x14, 0x6e, 0xe9, 0x02, 0x03, 0x1c, 0x04, 0x05, 0x2b, -0x00, 0xb1, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, -0x2e, 0x00, 0x28, 0x32, 0x02, 0x91, 0x69, 0x73, 0x00, 0x75, -0x73, 0x65, 0x66, 0x75, 0x6c, 0xb9, 0x01, 0x01, 0xc1, 0x00, -0x02, 0x1f, 0x01, 0x04, 0x61, 0x04, 0x12, 0x64, 0xbf, 0x02, -0x03, 0xa7, 0x00, 0x54, 0x6e, 0x63, 0x65, 0x00, 0x79, 0xdc, -0x04, 0x01, 0x9b, 0x01, 0x51, 0x64, 0x00, 0x61, 0x6c, 0x6c, -0x3f, 0x03, 0x01, 0xe2, 0x02, 0x23, 0x2e, 0x29, 0xfe, 0x04, -0x20, 0x63, 0x61, 0xe2, 0x00, 0x20, 0x73, 0x6f, 0x5f, 0x00, -0x01, 0x4f, 0x00, 0xb1, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x00, 0x6b, 0x65, 0x79, 0x73, 0x61, 0x02, 0x10, 0x6f, 0x1e, -0x05, 0x06, 0xd5, 0x02, 0x02, 0xc8, 0x02, 0x56, 0x50, 0x72, -0x65, 0x73, 0x73, 0x81, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x32, -0x00, 0x11, 0x00, 0xef, 0x00, 0x8f, 0x61, 0x6e, 0x00, 0x65, -0x6d, 0x70, 0x74, 0x79, 0x20, 0x02, 0x06, 0x02, 0xfc, 0x00, -0x18, 0x70, 0x44, 0x00, 0x20, 0x73, 0x70, 0x1f, 0x00, 0x3e, -0x62, 0x61, 0x72, 0x43, 0x00, 0x0f, 0x28, 0x02, 0x05, 0x14, -0x3b, 0xf1, 0x01, 0x00, 0x79, 0x00, 0x07, 0xd8, 0x01, 0x0e, -0xf6, 0x01, 0x00, 0x71, 0x04, 0x20, 0x6c, 0x64, 0x6b, 0x00, -0x5e, 0x53, 0x68, 0x69, 0x66, 0x74, 0x7e, 0x00, 0x08, 0xf4, -0x00, 0x08, 0x6b, 0x00, 0x08, 0x84, 0x00, 0x12, 0x73, 0x76, -0x00, 0x06, 0x4c, 0x00, 0x12, 0x43, 0x23, 0x03, 0x0f, 0x4e, -0x00, 0x17, 0x01, 0x40, 0x00, 0x5b, 0x00, 0x62, 0x6f, 0x74, -0x68, 0x59, 0x00, 0x00, 0x42, 0x00, 0x06, 0x01, 0x02, 0x12, -0x74, 0x7c, 0x05, 0x01, 0xc5, 0x05, 0x41, 0x28, 0x41, 0x6c, -0x6c, 0x54, 0x00, 0x22, 0x61, 0x63, 0x0f, 0x06, 0x83, 0x64, -0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x30, 0x04, 0x11, -0x63, 0xf8, 0x03, 0x32, 0x32, 0x2e, 0x31, 0xff, 0x04, 0x00, -0xc8, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, -0x6c, 0x65, 0x2e, 0x29, 0xd3, 0x03, 0x13, 0x32, 0xd3, 0x03, -0xb1, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, -0x73, 0x20, 0x88, 0x04, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, -0x00, 0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x51, 0x00, 0x66, -0x72, 0x6f, 0x6d, 0x79, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, -0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, -0x6f, 0x00, 0x03, 0x98, 0x04, 0xb0, 0x60, 0x54, 0x79, 0x70, -0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xab, 0x00, 0x91, -0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x3c, -0x03, 0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x04, 0x07, 0x01, -0x58, 0x07, 0x24, 0x69, 0x6e, 0xe1, 0x00, 0x00, 0x2b, 0x00, -0xc4, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, -0x79, 0x00, 0x00, 0x47, 0x01, 0x02, 0x4b, 0x05, 0x16, 0x64, -0x1a, 0x00, 0x04, 0x38, 0x05, 0x83, 0x65, 0x6e, 0x65, 0x72, -0x61, 0x74, 0x65, 0x64, 0x35, 0x05, 0x57, 0x2e, 0x00, 0x4d, -0x6f, 0x72, 0x29, 0x00, 0x03, 0x17, 0x00, 0x70, 0x73, 0x00, -0x72, 0x65, 0x71, 0x75, 0x69, 0x2d, 0x07, 0x00, 0x1f, 0x00, -0xc2, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x00, 0x64, -0x65, 0x64, 0x75, 0x3a, 0x01, 0x02, 0x9a, 0x06, 0x21, 0x61, -0x74, 0xab, 0x01, 0x20, 0x65, 0x6e, 0xa5, 0x06, 0x15, 0x6e, -0xa4, 0x07, 0x06, 0xf8, 0x00, 0x07, 0x81, 0x00, 0x55, 0x6c, -0x65, 0x76, 0x65, 0x6c, 0x58, 0x00, 0xb0, 0x73, 0x00, 0x67, -0x75, 0x65, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x6b, 0x06, 0x04, -0xe0, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x6b, -0x69, 0x6e, 0x67, 0x2e, 0x00, +0x00, 0x2d, 0x01, 0x00, 0xf0, 0x14, 0x00, 0x00, 0x00, 0x59, +0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, +0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, +0x65, 0x11, 0x00, 0xf0, 0x05, 0x77, 0x68, 0x69, 0x63, 0x68, +0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x74, +0x72, 0x65, 0x65, 0x73, 0x2e, 0x39, 0x00, 0xf0, 0x04, 0x72, +0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, +0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x00, 0x74, 0x69, 0x00, +0x35, 0x00, 0x69, 0x6e, 0x3b, 0x00, 0xd6, 0x74, 0x68, 0x65, +0x00, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, +0x5a, 0x00, 0x00, 0x22, 0x00, 0xe1, 0x75, 0x63, 0x68, 0x00, +0x61, 0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, +0x2a, 0x00, 0x60, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x2a, +0x00, 0xf1, 0x0e, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, +0x6f, 0x6e, 0x73, 0x00, 0x61, 0x72, 0x65, 0x00, 0x6d, 0x65, +0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x54, 0x68, 0x65, +0x72, 0x65, 0x13, 0x00, 0xf3, 0x00, 0x65, 0x78, 0x61, 0x63, +0x74, 0x6c, 0x79, 0x00, 0x61, 0x73, 0x00, 0x6d, 0x61, 0x6e, +0x79, 0x7b, 0x00, 0x24, 0x61, 0x73, 0xa0, 0x00, 0x03, 0x2e, +0x00, 0x04, 0x18, 0x00, 0x22, 0x6e, 0x64, 0x19, 0x00, 0xff, +0x03, 0x00, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x65, 0x00, 0x6d, +0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x00, 0x75, 0x70, 0x8d, +0x00, 0x01, 0x41, 0x65, 0x61, 0x63, 0x68, 0x3a, 0x00, 0x00, +0xde, 0x00, 0x42, 0x64, 0x69, 0x72, 0x65, 0x6b, 0x00, 0x40, +0x64, 0x6a, 0x61, 0x63, 0x15, 0x00, 0x60, 0x28, 0x68, 0x6f, +0x72, 0x69, 0x7a, 0x10, 0x01, 0xd0, 0x6c, 0x6c, 0x79, 0x00, +0x6f, 0x72, 0x00, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x0e, +0x00, 0xf0, 0x01, 0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x6e, +0x6f, 0x74, 0x00, 0x64, 0x69, 0x61, 0x67, 0x6f, 0x6e, 0x14, +0x00, 0x10, 0x29, 0x21, 0x01, 0x62, 0x69, 0x74, 0x73, 0x00, +0x6f, 0x77, 0x3f, 0x01, 0xc2, 0x2e, 0x00, 0x48, 0x6f, 0x77, +0x65, 0x76, 0x65, 0x72, 0x2c, 0x00, 0x61, 0x67, 0x00, 0x30, +0x6d, 0x61, 0x79, 0x96, 0x00, 0x05, 0x62, 0x00, 0x83, 0x74, +0x6f, 0x00, 0x6f, 0x74, 0x68, 0x65, 0x72, 0xb5, 0x00, 0x70, +0x61, 0x73, 0x00, 0x77, 0x65, 0x6c, 0x6c, 0x08, 0x00, 0x03, +0x48, 0x00, 0x02, 0xe1, 0x00, 0x64, 0x4e, 0x6f, 0x00, 0x74, +0x77, 0x6f, 0xe4, 0x00, 0x17, 0x72, 0x41, 0x00, 0x08, 0xa2, +0x00, 0x17, 0x2c, 0xa0, 0x00, 0x46, 0x00, 0x6f, 0x72, 0x20, +0x9a, 0x00, 0x06, 0x27, 0x01, 0x61, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0xb3, 0x01, 0x04, 0xc4, 0x01, 0x01, 0x05, 0x01, +0x41, 0x72, 0x6f, 0x77, 0x2c, 0x3e, 0x01, 0x04, 0x11, 0x00, +0x73, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2c, 0x41, 0x01, +0x35, 0x73, 0x00, 0x74, 0x3d, 0x00, 0xd1, 0x73, 0x00, 0x67, +0x69, 0x76, 0x65, 0x6e, 0x00, 0x72, 0x6f, 0x75, 0x6e, 0x64, +0x18, 0x00, 0x54, 0x73, 0x69, 0x64, 0x65, 0x73, 0x07, 0x02, +0x00, 0x5f, 0x02, 0x00, 0x70, 0x00, 0xb4, 0x54, 0x68, 0x69, +0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x8d, 0x01, +0x11, 0x66, 0x32, 0x00, 0x00, 0x88, 0x01, 0x00, 0x15, 0x01, +0x22, 0x61, 0x6c, 0x4e, 0x02, 0x41, 0x73, 0x00, 0x6f, 0x6e, +0x3a, 0x00, 0x82, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, +0x74, 0x89, 0x00, 0xa1, 0x77, 0x61, 0x73, 0x00, 0x62, 0x72, +0x6f, 0x75, 0x67, 0x68, 0x27, 0x01, 0x50, 0x6d, 0x79, 0x00, +0x61, 0x74, 0xb4, 0x00, 0xf0, 0x28, 0x69, 0x6f, 0x6e, 0x00, +0x62, 0x79, 0x00, 0x65, 0x2d, 0x6d, 0x61, 0x69, 0x6c, 0x2e, +0x00, 0x49, 0x00, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x00, 0x6b, +0x6e, 0x6f, 0x77, 0x00, 0x77, 0x68, 0x6f, 0x00, 0x49, 0x00, +0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x63, 0x72, 0x65, +0x64, 0x69, 0x74, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x69, 0x6e, +0x76, 0x3a, 0x00, 0x50, 0x6e, 0x67, 0x00, 0x69, 0x74, 0x9c, +0x00, 0x43, 0x32, 0x35, 0x2e, 0x31, 0x2e, 0x03, 0x00, 0xef, +0x02, 0xf1, 0x03, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, +0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, +0x6b, 0x2b, 0x00, 0x93, 0x6e, 0x00, 0x61, 0x00, 0x62, 0x6c, +0x61, 0x6e, 0x6b, 0xd1, 0x02, 0x43, 0x00, 0x77, 0x69, 0x6c, +0xb4, 0x00, 0x04, 0xd0, 0x01, 0x21, 0x69, 0x6e, 0x52, 0x00, +0x7f, 0x52, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x00, 0x3b, 0x00, +0x0d, 0x30, 0x63, 0x6f, 0x6c, 0x4e, 0x03, 0x80, 0x69, 0x74, +0x00, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x03, 0x41, 0x64, +0x69, 0x63, 0x61, 0x99, 0x00, 0x01, 0x90, 0x02, 0x31, 0x79, +0x6f, 0x75, 0xdf, 0x01, 0x60, 0x73, 0x75, 0x72, 0x65, 0x00, +0x69, 0x96, 0x02, 0x00, 0xdb, 0x00, 0x02, 0x6c, 0x00, 0x34, +0x2e, 0x00, 0x43, 0x5f, 0x00, 0x21, 0x65, 0x69, 0x34, 0x02, +0x61, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x00, 0xaa, +0x6e, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, +0x71, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72, 0xf4, 0x00, 0x21, +0x49, 0x66, 0x5f, 0x00, 0x92, 0x64, 0x72, 0x61, 0x67, 0x00, +0x77, 0x69, 0x74, 0x68, 0xb4, 0x03, 0x00, 0xb9, 0x00, 0x04, +0x49, 0x00, 0x70, 0x61, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x61, +0x0c, 0x02, 0x00, 0xed, 0x02, 0x04, 0x02, 0x02, 0x00, 0xac, +0x01, 0x1a, 0x79, 0xce, 0x00, 0x23, 0x69, 0x6e, 0xf2, 0x03, +0x10, 0x67, 0x8e, 0x01, 0x00, 0x57, 0x00, 0x52, 0x63, 0x6f, +0x76, 0x65, 0x72, 0x75, 0x00, 0x94, 0x62, 0x65, 0x00, 0x74, +0x75, 0x72, 0x6e, 0x65, 0x64, 0xe6, 0x00, 0x00, 0xce, 0x01, +0x14, 0x6e, 0xe9, 0x02, 0x03, 0x1c, 0x04, 0x05, 0x2b, 0x00, +0xb1, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, +0x00, 0x28, 0x32, 0x02, 0x91, 0x69, 0x73, 0x00, 0x75, 0x73, +0x65, 0x66, 0x75, 0x6c, 0xb9, 0x01, 0x01, 0xc1, 0x00, 0x02, +0x1f, 0x01, 0x04, 0x61, 0x04, 0x12, 0x64, 0xbf, 0x02, 0x03, +0xa7, 0x00, 0x54, 0x6e, 0x63, 0x65, 0x00, 0x79, 0xdc, 0x04, +0x01, 0x9b, 0x01, 0x51, 0x64, 0x00, 0x61, 0x6c, 0x6c, 0x3f, +0x03, 0x01, 0xe2, 0x02, 0x23, 0x2e, 0x29, 0xfe, 0x04, 0x20, +0x63, 0x61, 0xe2, 0x00, 0x20, 0x73, 0x6f, 0x5f, 0x00, 0x01, +0x4f, 0x00, 0xb1, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, +0x6b, 0x65, 0x79, 0x73, 0x61, 0x02, 0x10, 0x6f, 0x1e, 0x05, +0x06, 0xd5, 0x02, 0x02, 0xc8, 0x02, 0x56, 0x50, 0x72, 0x65, +0x73, 0x73, 0x81, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x32, 0x00, +0x11, 0x00, 0xef, 0x00, 0x8f, 0x61, 0x6e, 0x00, 0x65, 0x6d, +0x70, 0x74, 0x79, 0x20, 0x02, 0x06, 0x02, 0xfc, 0x00, 0x18, +0x70, 0x44, 0x00, 0x20, 0x73, 0x70, 0x1f, 0x00, 0x3e, 0x62, +0x61, 0x72, 0x43, 0x00, 0x0f, 0x28, 0x02, 0x05, 0x14, 0x3b, +0xf1, 0x01, 0x00, 0x79, 0x00, 0x07, 0xd8, 0x01, 0x0e, 0xf6, +0x01, 0x00, 0x71, 0x04, 0x20, 0x6c, 0x64, 0x6b, 0x00, 0x5e, +0x53, 0x68, 0x69, 0x66, 0x74, 0x7e, 0x00, 0x08, 0xf4, 0x00, +0x08, 0x6b, 0x00, 0x08, 0x84, 0x00, 0x12, 0x73, 0x76, 0x00, +0x06, 0x4c, 0x00, 0x12, 0x43, 0x23, 0x03, 0x0f, 0x4e, 0x00, +0x17, 0x01, 0x40, 0x00, 0x5b, 0x00, 0x62, 0x6f, 0x74, 0x68, +0x59, 0x00, 0x00, 0x42, 0x00, 0x06, 0x01, 0x02, 0x12, 0x74, +0x7c, 0x05, 0x01, 0xc5, 0x05, 0x41, 0x28, 0x41, 0x6c, 0x6c, +0x54, 0x00, 0x22, 0x61, 0x63, 0x0f, 0x06, 0x83, 0x64, 0x65, +0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x30, 0x04, 0x11, 0x63, +0xf8, 0x03, 0x32, 0x32, 0x2e, 0x31, 0xff, 0x04, 0x00, 0xc8, +0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, +0x65, 0x2e, 0x29, 0xd3, 0x03, 0x13, 0x32, 0xd3, 0x03, 0xb1, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, +0x20, 0x88, 0x04, 0x46, 0x65, 0x73, 0x65, 0x00, 0x14, 0x00, +0x02, 0x41, 0x00, 0x04, 0x3c, 0x00, 0x51, 0x00, 0x66, 0x72, +0x6f, 0x6d, 0x79, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, +0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x6f, +0x00, 0x03, 0x98, 0x04, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, +0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xab, 0x00, 0x91, 0x57, +0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x3c, 0x03, +0x51, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x04, 0x07, 0x01, 0x58, +0x07, 0x24, 0x69, 0x6e, 0xe1, 0x00, 0x00, 0x2b, 0x00, 0xc4, +0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, +0x00, 0x00, 0x47, 0x01, 0x02, 0x4b, 0x05, 0x16, 0x64, 0x1a, +0x00, 0x04, 0x38, 0x05, 0x83, 0x65, 0x6e, 0x65, 0x72, 0x61, +0x74, 0x65, 0x64, 0x35, 0x05, 0x57, 0x2e, 0x00, 0x4d, 0x6f, +0x72, 0x29, 0x00, 0x03, 0x17, 0x00, 0x70, 0x73, 0x00, 0x72, +0x65, 0x71, 0x75, 0x69, 0x2d, 0x07, 0x00, 0x1f, 0x00, 0xc2, +0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x00, 0x64, 0x65, +0x64, 0x75, 0x3a, 0x01, 0x02, 0x9a, 0x06, 0x21, 0x61, 0x74, +0xab, 0x01, 0x20, 0x65, 0x6e, 0xa5, 0x06, 0x15, 0x6e, 0xa4, +0x07, 0x06, 0xf8, 0x00, 0x07, 0x81, 0x00, 0x55, 0x6c, 0x65, +0x76, 0x65, 0x6c, 0x58, 0x00, 0xb0, 0x73, 0x00, 0x67, 0x75, +0x65, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x6b, 0x06, 0x04, 0xe0, +0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x69, +0x6e, 0x67, 0x2e, 0x00, }; -const unsigned short help_text_len = 2140; -const unsigned short help_text_words = 400; +const unsigned short help_text_len = 2158; +const unsigned short help_text_words = 401; const char quick_help_text[] = "Place a tent next to each tree."; diff --git a/apps/plugins/puzzles/help/towers.c b/apps/plugins/puzzles/help/towers.c index 7b27064659..b41fb7a432 100644 --- a/apps/plugins/puzzles/help/towers.c +++ b/apps/plugins/puzzles/help/towers.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,239 +6,261 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 216, TEXT_CENTER | C_RED }, - { 291, TEXT_UNDERLINE }, - { 588, TEXT_CENTER | C_RED }, - { 605, TEXT_UNDERLINE }, - { 637, TEXT_UNDERLINE }, + { 217, TEXT_CENTER | C_RED }, + { 292, TEXT_UNDERLINE }, + { 589, TEXT_CENTER | C_RED }, + { 606, TEXT_UNDERLINE }, + { 638, TEXT_UNDERLINE }, + { 677, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3541 comp 2203 ratio 0.622141 level 10 saved 1338 */ +/* orig 3906 comp 2412 ratio 0.617512 level 10 saved 1494 */ const char help_text[] = { -0xf4, 0x26, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x31, 0x3a, 0x20, 0x54, 0x6f, 0x77, 0x65, 0x72, 0x73, -0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, -0x76, 0x65, 0x00, 0x61, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, -0x65, 0x00, 0x67, 0x72, 0x69, 0x64, 0x2e, 0x00, 0x4f, 0x6e, -0x00, 0x65, 0x61, 0x63, 0x68, 0x15, 0x00, 0x52, 0x6f, 0x66, -0x00, 0x74, 0x68, 0x1c, 0x00, 0xf0, 0x03, 0x00, 0x79, 0x6f, -0x75, 0x00, 0x63, 0x61, 0x6e, 0x00, 0x62, 0x75, 0x69, 0x6c, -0x64, 0x00, 0x61, 0x00, 0x74, 0x4d, 0x00, 0xf1, 0x14, 0x2c, -0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x69, 0x74, 0x73, 0x00, -0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x72, 0x61, 0x6e, -0x67, 0x69, 0x6e, 0x67, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, -0x31, 0x00, 0x74, 0x6f, 0x42, 0x00, 0x39, 0x73, 0x69, 0x7a, -0x4e, 0x00, 0x81, 0x2e, 0x00, 0x41, 0x72, 0x6f, 0x75, 0x6e, -0x64, 0x11, 0x00, 0x3a, 0x65, 0x64, 0x67, 0x6b, 0x00, 0x00, -0x7b, 0x00, 0xf2, 0x04, 0x73, 0x6f, 0x6d, 0x65, 0x00, 0x6e, -0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x00, 0x63, 0x6c, 0x75, -0x65, 0x73, 0x2e, 0xb8, 0x00, 0x90, 0x72, 0x00, 0x74, 0x61, -0x73, 0x6b, 0x00, 0x69, 0x73, 0x5c, 0x00, 0x09, 0x8d, 0x00, -0x93, 0x00, 0x6f, 0x6e, 0x00, 0x65, 0x76, 0x65, 0x72, 0x79, -0xbf, 0x00, 0xf0, 0x0c, 0x2c, 0x00, 0x69, 0x6e, 0x00, 0x73, -0x75, 0x63, 0x68, 0x00, 0x61, 0x00, 0x77, 0x61, 0x79, 0x00, -0x74, 0x68, 0x61, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, -0x45, 0xe4, 0x00, 0xc3, 0x72, 0x6f, 0x77, 0x00, 0x63, 0x6f, -0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x38, 0x00, 0x84, 0x70, -0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0xcd, 0x00, 0x25, -0x6f, 0x66, 0x5a, 0x00, 0x26, 0x63, 0x65, 0x3a, 0x00, 0x6f, -0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3d, 0x00, 0x24, 0x08, -0xd4, 0x00, 0xa1, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x65, 0x73, 0xfd, 0x00, 0x65, 0x6e, 0x75, 0x6d, 0x62, -0x65, 0x72, 0x39, 0x00, 0x11, 0x73, 0xb2, 0x00, 0x02, 0x75, -0x01, 0x91, 0x65, 0x00, 0x73, 0x65, 0x65, 0x6e, 0x00, 0x69, -0x66, 0x88, 0x01, 0x74, 0x6c, 0x6f, 0x6f, 0x6b, 0x00, 0x69, -0x6e, 0x5d, 0x01, 0x02, 0xad, 0x01, 0x01, 0x72, 0x01, 0x01, -0x32, 0x00, 0xf0, 0x01, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, -0x69, 0x6f, 0x6e, 0x2c, 0x00, 0x61, 0x73, 0x73, 0x75, 0x6d, -0x90, 0x01, 0x01, 0x19, 0x00, 0x74, 0x73, 0x68, 0x6f, 0x72, -0x74, 0x65, 0x72, 0x5f, 0x00, 0x00, 0x36, 0x00, 0x50, 0x68, -0x69, 0x64, 0x64, 0x65, 0x61, 0x00, 0x20, 0x68, 0x69, 0x8f, -0x01, 0x31, 0x61, 0x6c, 0x6c, 0xb2, 0x00, 0x00, 0x6f, 0x01, -0xa2, 0x46, 0x6f, 0x72, 0x00, 0x65, 0x78, 0x61, 0x6d, 0x70, -0x6c, 0x4b, 0x01, 0x51, 0x61, 0x00, 0x35, 0x78, 0x35, 0xa2, -0x01, 0x32, 0x2c, 0x00, 0x61, 0xc0, 0x00, 0xf3, 0x04, 0x6d, -0x61, 0x72, 0x6b, 0x65, 0x64, 0x00, 0x60, 0x35, 0x27, 0x00, -0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0xb6, 0x00, -0x00, 0x99, 0x00, 0x43, 0x66, 0x69, 0x76, 0x65, 0x04, 0x01, -0x02, 0x14, 0x01, 0xd0, 0x73, 0x00, 0x6d, 0x75, 0x73, 0x74, -0x00, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x53, 0x00, 0x70, -0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0xa1, 0x00, 0xf1, -0x01, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x00, 0x28, 0x6f, 0x74, -0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0xe9, 0x00, 0x90, -0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6e, 0x6f, 0x74, 0x02, -0x01, 0x30, 0x61, 0x62, 0x6c, 0x4f, 0x00, 0x00, 0x0a, 0x01, -0x47, 0x00, 0x61, 0x6c, 0x6c, 0x5f, 0x00, 0x70, 0x73, 0x29, -0x2c, 0x00, 0x77, 0x68, 0x65, 0x4b, 0x00, 0x0c, 0x9a, 0x00, -0x1f, 0x31, 0x9a, 0x00, 0x02, 0x01, 0xe8, 0x00, 0x23, 0x73, -0x74, 0x9d, 0x00, 0x10, 0x28, 0x13, 0x00, 0x25, 0x6f, 0x6e, -0x35, 0x00, 0x22, 0x35, 0x29, 0xa8, 0x00, 0x30, 0x63, 0x6f, -0x6d, 0xc5, 0x00, 0x30, 0x72, 0x73, 0x74, 0x7c, 0x02, 0x51, -0x49, 0x6e, 0x00, 0x68, 0x61, 0xa5, 0x00, 0xf2, 0x03, 0x6f, -0x72, 0x00, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x00, 0x70, -0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x73, 0x2c, 0xaf, 0x02, 0x03, -0x57, 0x01, 0x41, 0x77, 0x69, 0x6c, 0x6c, 0xb2, 0x01, 0xc1, -0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x00, 0x66, -0x6f, 0x72, 0xcf, 0x00, 0x92, 0x61, 0x73, 0x00, 0x77, 0x65, -0x6c, 0x6c, 0x00, 0x61, 0xf0, 0x01, 0x01, 0xd7, 0x02, 0x1a, -0x00, 0x09, 0x03, 0x52, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x4f, -0x00, 0x01, 0x18, 0x03, 0x02, 0x24, 0x00, 0x30, 0x6d, 0x61, -0x79, 0x52, 0x00, 0x30, 0x6d, 0x69, 0x73, 0x2c, 0x01, 0x00, -0x8e, 0x00, 0x43, 0x54, 0x68, 0x69, 0x73, 0x7f, 0x00, 0x03, -0x50, 0x01, 0x10, 0x73, 0x00, 0x03, 0x00, 0x47, 0x00, 0x60, -0x77, 0x65, 0x62, 0x00, 0x75, 0x6e, 0xa9, 0x00, 0xb0, 0x76, -0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x6e, 0x61, 0x6d, -0xa5, 0x00, 0xf2, 0x21, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, -0x75, 0x6c, 0x61, 0x72, 0x6c, 0x79, 0x00, 0x60, 0x53, 0x6b, -0x79, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x72, 0x73, 0x27, -0x2c, 0x00, 0x62, 0x75, 0x74, 0x00, 0x49, 0x00, 0x64, 0x6f, -0x6e, 0x27, 0x74, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x00, 0x77, -0x68, 0x6f, 0xfc, 0x00, 0xb1, 0x00, 0x69, 0x6e, 0x76, 0x65, -0x6e, 0x74, 0x65, 0x64, 0x00, 0x69, 0x08, 0x01, 0x44, 0x33, -0x31, 0x2e, 0x31, 0x4b, 0x04, 0x00, 0x03, 0x03, 0x31, 0x72, -0x6f, 0x6c, 0x54, 0x04, 0x12, 0x54, 0xfe, 0x00, 0x40, 0x73, -0x68, 0x61, 0x72, 0xb2, 0x00, 0x00, 0x78, 0x03, 0x21, 0x6f, -0x66, 0x1b, 0x04, 0x03, 0x26, 0x00, 0x72, 0x00, 0x73, 0x79, -0x73, 0x74, 0x65, 0x6d, 0x33, 0x04, 0xd1, 0x53, 0x6f, 0x6c, -0x6f, 0x2c, 0x00, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x61, 0x6c, -0xf4, 0x00, 0x51, 0x4b, 0x65, 0x65, 0x6e, 0x2e, 0x48, 0x00, -0x53, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x00, 0xe1, 0x2c, -0x00, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0xe0, 0x00, 0x51, 0x6d, 0x6f, 0x75, 0x73, -0x65, 0x91, 0x02, 0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, 0x70, -0x74, 0x79, 0x03, 0x03, 0x12, 0x61, 0x49, 0x01, 0x50, 0x6e, -0x00, 0x74, 0x79, 0x70, 0xdc, 0x04, 0x54, 0x64, 0x69, 0x67, -0x69, 0x74, 0x17, 0x01, 0x80, 0x6b, 0x65, 0x79, 0x62, 0x6f, -0x61, 0x72, 0x64, 0x43, 0x02, 0x10, 0x66, 0xa3, 0x01, 0x02, -0x13, 0x03, 0x02, 0x3a, 0x00, 0x01, 0x94, 0x00, 0x05, 0x48, -0x04, 0x03, 0x8c, 0x04, 0x43, 0x69, 0x76, 0x65, 0x6e, 0xba, -0x02, 0x32, 0x2e, 0x00, 0x49, 0x7b, 0x03, 0x30, 0x6d, 0x61, -0x6b, 0x5a, 0x00, 0x8e, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, -0x65, 0x2c, 0x97, 0x00, 0x02, 0x6d, 0x00, 0x50, 0x69, 0x6e, -0x63, 0x6f, 0x72, 0x86, 0x03, 0x08, 0x9b, 0x00, 0xa1, 0x70, -0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x61, 0x63, 0xc8, -0x02, 0x21, 0x63, 0x6c, 0x06, 0x03, 0xc0, 0x74, 0x00, 0x61, -0x67, 0x61, 0x69, 0x6e, 0x00, 0x28, 0x6f, 0x72, 0x00, 0x42, -0x00, 0x00, 0x3f, 0x00, 0xd1, 0x55, 0x6e, 0x64, 0x6f, 0x00, -0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x29, 0x7d, 0x02, -0x02, 0x7e, 0x00, 0x10, 0x72, 0x8c, 0x00, 0x12, 0x2d, 0x74, -0x00, 0x01, 0x92, 0x03, 0x0f, 0xf9, 0x00, 0x04, 0x02, 0x4a, -0x04, 0x12, 0x2c, 0xe3, 0x00, 0x03, 0x57, 0x04, 0x04, 0x97, -0x02, 0x00, 0xcc, 0x01, 0x10, 0x72, 0xce, 0x01, 0x18, 0x6e, -0x3e, 0x04, 0x01, 0x3a, 0x03, 0x71, 0x60, 0x70, 0x65, 0x6e, -0x63, 0x69, 0x6c, 0x08, 0x03, 0x43, 0x27, 0x2e, 0x00, 0x59, -0xf3, 0x05, 0x01, 0x2a, 0x06, 0x07, 0x1b, 0x00, 0x11, 0x73, -0xd1, 0x02, 0x74, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, -0xb7, 0x04, 0x15, 0x73, 0x51, 0x00, 0x24, 0x61, 0x6d, 0x56, -0x00, 0x34, 0x2e, 0x00, 0x41, 0x60, 0x00, 0x03, 0x2d, 0x05, -0x00, 0xea, 0x03, 0x04, 0x67, 0x01, 0x30, 0x63, 0x61, 0x6e, -0xda, 0x03, 0x44, 0x61, 0x6c, 0x73, 0x6f, 0x1f, 0x00, 0x09, -0x66, 0x00, 0x02, 0xe7, 0x02, 0x30, 0x65, 0x00, 0x67, 0x51, -0x00, 0xd0, 0x70, 0x61, 0x79, 0x73, 0x00, 0x6e, 0x6f, 0x00, -0x61, 0x74, 0x74, 0x65, 0x6e, 0xdc, 0x04, 0x00, 0x42, 0x01, -0x08, 0x2e, 0x00, 0x00, 0x84, 0x03, 0x00, 0xaf, 0x04, 0x60, -0x63, 0x74, 0x6c, 0x79, 0x00, 0x77, 0xf8, 0x00, 0x00, 0x31, -0x01, 0x03, 0x51, 0x01, 0x11, 0x6d, 0xb2, 0x00, 0x50, 0x69, -0x73, 0x00, 0x75, 0x70, 0x38, 0x00, 0x45, 0x79, 0x6f, 0x75, -0x3a, 0xd1, 0x06, 0x05, 0x23, 0x00, 0x95, 0x61, 0x73, 0x00, -0x72, 0x65, 0x6d, 0x69, 0x6e, 0x64, 0x7b, 0x05, 0x17, 0x61, -0x33, 0x03, 0x04, 0xc9, 0x00, 0x42, 0x6e, 0x65, 0x65, 0x64, -0x7c, 0x06, 0x50, 0x65, 0x00, 0x72, 0x65, 0x2d, 0x21, 0x05, -0x42, 0x69, 0x6e, 0x65, 0x64, 0xe6, 0x05, 0x00, 0x54, 0x00, -0x01, 0x3e, 0x03, 0x30, 0x6d, 0x6f, 0x72, 0xb1, 0x04, 0x2b, -0x6f, 0x75, 0x45, 0x00, 0x04, 0x99, 0x01, 0x2f, 0x6f, 0x72, -0x80, 0x00, 0x02, 0x54, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x80, -0x02, 0x05, 0x51, 0x06, 0x07, 0x61, 0x01, 0x13, 0x61, 0x96, -0x02, 0x04, 0xe2, 0x06, 0x20, 0x6f, 0x72, 0x06, 0x03, 0x20, -0x74, 0x68, 0x58, 0x01, 0x23, 0x65, 0x6c, 0x36, 0x05, 0x93, -0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0x4f, -0x03, 0x41, 0x65, 0x72, 0x61, 0x73, 0xeb, 0x07, 0x49, 0x69, -0x6e, 0x67, 0x6c, 0xca, 0x01, 0x1c, 0x2c, 0x52, 0x02, 0x08, -0x12, 0x02, 0x22, 0x6e, 0x64, 0x4f, 0x02, 0x05, 0xd5, 0x01, -0x03, 0x49, 0x02, 0x01, 0xaf, 0x02, 0x00, 0x5b, 0x00, 0x3a, -0x41, 0x6c, 0x6c, 0x17, 0x02, 0x09, 0x93, 0x02, 0x22, 0x72, -0x65, 0x79, 0x00, 0x10, 0x64, 0x9b, 0x05, 0x12, 0x6e, 0xb8, -0x06, 0x24, 0x65, 0x66, 0x6c, 0x00, 0x05, 0x5e, 0x00, 0x18, -0x61, 0x14, 0x01, 0x0f, 0x2a, 0x00, 0x05, 0x02, 0x3a, 0x03, -0x10, 0x73, 0x3a, 0x03, 0x36, 0x2e, 0x00, 0x52, 0xb3, 0x00, -0x01, 0x4f, 0x02, 0x04, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x01, -0x23, 0x00, 0x02, 0xeb, 0x02, 0x01, 0x58, 0x02, 0x02, 0xfb, -0x00, 0x0c, 0x56, 0x02, 0x12, 0x41, 0xc2, 0x02, 0x02, 0x84, -0x04, 0x01, 0x8a, 0x05, 0x50, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x23, 0x04, 0x14, 0x73, 0x70, 0x07, 0x22, 0x75, 0x73, 0x24, -0x03, 0x61, 0x63, 0x6f, 0x6e, 0x6a, 0x75, 0x6e, 0x4f, 0x07, -0x02, 0x26, 0x04, 0x00, 0x30, 0x00, 0x02, 0x59, 0x04, 0x01, -0x2f, 0x00, 0x01, 0x91, 0x06, 0x15, 0x74, 0xa4, 0x01, 0x2b, -0x6f, 0x72, 0x6e, 0x00, 0x3d, 0x55, 0x73, 0x65, 0x63, 0x00, -0x51, 0x74, 0x6f, 0x00, 0x6d, 0x6f, 0x7e, 0x09, 0x51, 0x68, -0x69, 0x67, 0x68, 0x6c, 0x2f, 0x08, 0x16, 0x61, 0x08, 0x06, -0x03, 0x63, 0x07, 0x2a, 0x6e, 0x64, 0xc8, 0x04, 0x22, 0x74, -0x6f, 0xbc, 0x03, 0x00, 0x33, 0x04, 0x03, 0xab, 0x01, 0x05, -0x3f, 0x00, 0x25, 0x65, 0x64, 0x73, 0x03, 0x14, 0x50, 0x0c, -0x01, 0x50, 0x72, 0x65, 0x74, 0x75, 0x72, 0x28, 0x03, 0x5a, -0x67, 0x67, 0x6c, 0x65, 0x73, 0x30, 0x00, 0x02, 0x3e, 0x08, -0x51, 0x61, 0x00, 0x6d, 0x6f, 0x64, 0xb4, 0x04, 0x55, 0x77, -0x68, 0x69, 0x63, 0x68, 0x93, 0x02, 0x02, 0x67, 0x00, 0x20, -0x6f, 0x72, 0x10, 0x03, 0x2e, 0x6f, 0x76, 0x40, 0x01, 0x05, -0x63, 0x00, 0x12, 0x4d, 0x6b, 0x01, 0x01, 0x4f, 0x05, 0x01, -0xfd, 0x01, 0x41, 0x66, 0x75, 0x6c, 0x6c, 0x10, 0x01, 0x2d, -0x6f, 0x66, 0x1b, 0x02, 0x08, 0x9c, 0x09, 0x03, 0xa9, 0x08, -0x31, 0x6f, 0x65, 0x73, 0xde, 0x07, 0x03, 0x8c, 0x0a, 0x10, -0x6d, 0x03, 0x04, 0x02, 0xed, 0x00, 0x23, 0x69, 0x6e, 0x6f, -0x06, 0x38, 0x4c, 0x65, 0x66, 0xed, 0x01, 0x02, 0xde, 0x07, -0x01, 0x76, 0x00, 0x00, 0x59, 0x00, 0x01, 0x3f, 0x05, 0x30, -0x73, 0x00, 0x64, 0xbe, 0x07, 0x60, 0x28, 0x67, 0x72, 0x65, -0x79, 0x00, 0xf1, 0x05, 0x31, 0x75, 0x74, 0x29, 0x4f, 0x02, -0x24, 0x75, 0x6e, 0x24, 0x00, 0x10, 0x69, 0x8a, 0x06, 0x00, -0x01, 0x04, 0x73, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, -0xeb, 0x07, 0x60, 0x2e, 0x00, 0x48, 0x6f, 0x6c, 0x64, 0x59, -0x00, 0x13, 0x43, 0xa4, 0x06, 0x00, 0x17, 0x02, 0x4a, 0x68, -0x69, 0x66, 0x74, 0x57, 0x02, 0x50, 0x61, 0x6e, 0x00, 0x61, -0x72, 0x31, 0x0a, 0x31, 0x6b, 0x65, 0x79, 0x5a, 0x03, 0x01, -0xa2, 0x08, 0x02, 0xda, 0x00, 0x00, 0x86, 0x06, 0x01, 0x95, -0x00, 0x27, 0x69, 0x6e, 0x37, 0x06, 0x05, 0x84, 0x09, 0x00, -0xc4, 0x00, 0x10, 0x28, 0x2a, 0x03, 0x00, 0x1c, 0x00, 0x11, -0x61, 0x13, 0x00, 0x15, 0x73, 0xf8, 0x09, 0x11, 0x64, 0xa3, -0x0a, 0x12, 0x65, 0x5e, 0x02, 0x31, 0x32, 0x2e, 0x31, 0x36, -0x03, 0x01, 0xb9, 0x02, 0x50, 0x61, 0x76, 0x61, 0x69, 0x6c, -0xf2, 0x08, 0x22, 0x2e, 0x29, 0x74, 0x07, 0x14, 0x32, 0x74, -0x07, 0x73, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0xca, -0x0b, 0x30, 0x54, 0x68, 0x65, 0xe1, 0x02, 0x05, 0x14, 0x00, -0x02, 0x42, 0x00, 0x04, 0x3d, 0x00, 0x04, 0x15, 0x0a, 0xf1, -0x01, 0x65, 0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, -0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x70, 0x00, 0x03, -0x18, 0x07, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0xac, 0x00, 0x51, 0x47, 0x72, 0x69, -0x64, 0x20, 0xb0, 0x0b, 0x33, 0x00, 0x00, 0x53, 0xc2, 0x08, -0x1f, 0x73, 0xc5, 0x0b, 0x04, 0x11, 0x4c, 0xc8, 0x05, 0x32, -0x6c, 0x69, 0x6d, 0x5c, 0x01, 0x68, 0x33, 0x3b, 0x00, 0x75, -0x70, 0x70, 0x12, 0x00, 0x74, 0x39, 0x00, 0x28, 0x62, 0x65, -0x63, 0x61, 0xd7, 0x06, 0x20, 0x75, 0x73, 0xbe, 0x02, 0x00, -0x5d, 0x02, 0x11, 0x66, 0xa7, 0x03, 0x01, 0xde, 0x09, 0x21, -0x62, 0x65, 0x68, 0x09, 0x01, 0x32, 0x05, 0x40, 0x64, 0x69, -0x66, 0x66, 0x2a, 0x05, 0x12, 0x74, 0x6b, 0x03, 0x11, 0x60, -0x0c, 0x02, 0x70, 0x73, 0x27, 0x00, 0x62, 0x69, 0x67, 0x67, -0xb8, 0x0a, 0x61, 0x68, 0x61, 0x6e, 0x00, 0x39, 0x21, 0x12, -0x07, 0x14, 0x44, 0x2b, 0x00, 0x34, 0x79, 0x00, 0x00, 0xbe, -0x01, 0x13, 0x73, 0x9d, 0x03, 0x05, 0x1a, 0x00, 0x04, 0xae, -0x00, 0x50, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x25, 0x03, 0x02, -0x32, 0x09, 0x70, 0x2e, 0x00, 0x41, 0x74, 0x00, 0x55, 0x6e, -0x30, 0x0a, 0x21, 0x6f, 0x6e, 0x28, 0x01, 0x53, 0x6c, 0x65, -0x76, 0x65, 0x6c, 0xc7, 0x09, 0x72, 0x62, 0x61, 0x63, 0x6b, -0x74, 0x72, 0x61, 0x71, 0x02, 0x04, 0x36, 0x07, 0x82, 0x72, -0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x2a, 0x09, 0x01, -0x0f, 0x01, 0x31, 0x6f, 0x6c, 0x75, 0x48, 0x01, 0x21, 0x73, -0x68, 0xc8, 0x00, 0x23, 0x73, 0x74, 0x2b, 0x00, 0x71, 0x75, -0x6e, 0x69, 0x71, 0x75, 0x65, 0x2e, 0xbc, 0x06, 0x33, 0x72, -0x65, 0x6d, 0xf6, 0x06, 0x01, 0x62, 0x00, 0x14, 0x73, 0x48, -0x00, 0x07, 0xfa, 0x0a, 0x00, 0xdc, 0x08, 0x10, 0x6f, 0x65, -0x0b, 0x22, 0x78, 0x00, 0x91, 0x00, 0x01, 0xaf, 0x0b, 0x00, -0x02, 0x02, 0x30, 0x6f, 0x69, 0x64, 0x1a, 0x03, 0x03, 0x10, -0x00, 0xb0, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, -0x6b, 0x2e, 0x00, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf4, 0x13, 0x00, 0x00, 0x00, +0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, +0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x67, 0x72, +0x69, 0x64, 0x2e, 0x00, 0x4f, 0x6e, 0x00, 0x65, 0x61, 0x63, +0x68, 0x15, 0x00, 0x52, 0x6f, 0x66, 0x00, 0x74, 0x68, 0x1c, +0x00, 0xf0, 0x03, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x63, 0x61, +0x6e, 0x00, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x00, 0x61, 0x00, +0x74, 0x60, 0x00, 0xf1, 0x14, 0x2c, 0x00, 0x77, 0x69, 0x74, +0x68, 0x00, 0x69, 0x74, 0x73, 0x00, 0x68, 0x65, 0x69, 0x67, +0x68, 0x74, 0x00, 0x72, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, +0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x31, 0x00, 0x74, 0x6f, +0x42, 0x00, 0x39, 0x73, 0x69, 0x7a, 0x4e, 0x00, 0x81, 0x2e, +0x00, 0x41, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x11, 0x00, 0x3a, +0x65, 0x64, 0x67, 0x6b, 0x00, 0x00, 0x7b, 0x00, 0xf2, 0x04, +0x73, 0x6f, 0x6d, 0x65, 0x00, 0x6e, 0x75, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x00, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0xb8, +0x00, 0x90, 0x72, 0x00, 0x74, 0x61, 0x73, 0x6b, 0x00, 0x69, +0x73, 0x5c, 0x00, 0x09, 0x8d, 0x00, 0x93, 0x00, 0x6f, 0x6e, +0x00, 0x65, 0x76, 0x65, 0x72, 0x79, 0xbf, 0x00, 0xf0, 0x0c, +0x2c, 0x00, 0x69, 0x6e, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, +0x61, 0x00, 0x77, 0x61, 0x79, 0x00, 0x74, 0x68, 0x61, 0x74, +0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x45, 0xe4, 0x00, 0xc3, +0x72, 0x6f, 0x77, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, +0x6e, 0x73, 0x38, 0x00, 0x84, 0x70, 0x6f, 0x73, 0x73, 0x69, +0x62, 0x6c, 0x65, 0xcd, 0x00, 0x25, 0x6f, 0x66, 0x5a, 0x00, +0x26, 0x63, 0x65, 0x3a, 0x00, 0x6f, 0x63, 0x6f, 0x6c, 0x75, +0x6d, 0x6e, 0x3d, 0x00, 0x24, 0x08, 0xd4, 0x00, 0xa1, 0x00, +0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x73, 0xfd, +0x00, 0x65, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x39, 0x00, +0x11, 0x73, 0xb2, 0x00, 0x02, 0x75, 0x01, 0x91, 0x65, 0x00, +0x73, 0x65, 0x65, 0x6e, 0x00, 0x69, 0x66, 0x88, 0x01, 0x74, +0x6c, 0x6f, 0x6f, 0x6b, 0x00, 0x69, 0x6e, 0x5d, 0x01, 0x02, +0xad, 0x01, 0x01, 0x72, 0x01, 0x01, 0x32, 0x00, 0xf0, 0x01, +0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, +0x00, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x90, 0x01, 0x01, 0x19, +0x00, 0x74, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, +0x00, 0x00, 0x36, 0x00, 0x50, 0x68, 0x69, 0x64, 0x64, 0x65, +0x61, 0x00, 0x20, 0x68, 0x69, 0x8f, 0x01, 0x31, 0x61, 0x6c, +0x6c, 0xb2, 0x00, 0x00, 0x6f, 0x01, 0xa2, 0x46, 0x6f, 0x72, +0x00, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x4b, 0x01, 0x51, +0x61, 0x00, 0x35, 0x78, 0x35, 0xa2, 0x01, 0x32, 0x2c, 0x00, +0x61, 0xc0, 0x00, 0xf3, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x65, +0x64, 0x00, 0x60, 0x35, 0x27, 0x00, 0x69, 0x6e, 0x64, 0x69, +0x63, 0x61, 0x74, 0x65, 0xb6, 0x00, 0x00, 0x99, 0x00, 0x43, +0x66, 0x69, 0x76, 0x65, 0x04, 0x01, 0x02, 0x14, 0x01, 0xd0, +0x73, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x61, 0x70, 0x70, +0x65, 0x61, 0x72, 0x53, 0x00, 0x70, 0x69, 0x6e, 0x63, 0x72, +0x65, 0x61, 0x73, 0xa1, 0x00, 0xf1, 0x01, 0x6f, 0x72, 0x64, +0x65, 0x72, 0x00, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, +0x69, 0x73, 0x65, 0xe9, 0x00, 0x90, 0x77, 0x6f, 0x75, 0x6c, +0x64, 0x00, 0x6e, 0x6f, 0x74, 0x02, 0x01, 0x30, 0x61, 0x62, +0x6c, 0x4f, 0x00, 0x00, 0x0a, 0x01, 0x47, 0x00, 0x61, 0x6c, +0x6c, 0x5f, 0x00, 0x70, 0x73, 0x29, 0x2c, 0x00, 0x77, 0x68, +0x65, 0x4b, 0x00, 0x0c, 0x9a, 0x00, 0x1f, 0x31, 0x9a, 0x00, +0x02, 0x01, 0xe8, 0x00, 0x23, 0x73, 0x74, 0x9d, 0x00, 0x10, +0x28, 0x13, 0x00, 0x25, 0x6f, 0x6e, 0x35, 0x00, 0x22, 0x35, +0x29, 0xa8, 0x00, 0x30, 0x63, 0x6f, 0x6d, 0xc5, 0x00, 0x30, +0x72, 0x73, 0x74, 0x7c, 0x02, 0x51, 0x49, 0x6e, 0x00, 0x68, +0x61, 0xa5, 0x00, 0xf2, 0x03, 0x6f, 0x72, 0x00, 0x6c, 0x61, +0x72, 0x67, 0x65, 0x72, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, +0x65, 0x73, 0x2c, 0xaf, 0x02, 0x03, 0x57, 0x01, 0x41, 0x77, +0x69, 0x6c, 0x6c, 0xb2, 0x01, 0xc1, 0x70, 0x65, 0x63, 0x69, +0x66, 0x69, 0x65, 0x64, 0x00, 0x66, 0x6f, 0x72, 0xcf, 0x00, +0x92, 0x61, 0x73, 0x00, 0x77, 0x65, 0x6c, 0x6c, 0x00, 0x61, +0xf0, 0x01, 0x01, 0xd7, 0x02, 0x1a, 0x00, 0x09, 0x03, 0x52, +0x2c, 0x00, 0x61, 0x6e, 0x64, 0x4f, 0x00, 0x01, 0x18, 0x03, +0x02, 0x24, 0x00, 0x30, 0x6d, 0x61, 0x79, 0x52, 0x00, 0x30, +0x6d, 0x69, 0x73, 0x2c, 0x01, 0x00, 0x8e, 0x00, 0x43, 0x54, +0x68, 0x69, 0x73, 0x7f, 0x00, 0x03, 0x50, 0x01, 0x10, 0x73, +0x00, 0x03, 0x00, 0x47, 0x00, 0x60, 0x77, 0x65, 0x62, 0x00, +0x75, 0x6e, 0xa9, 0x00, 0xb0, 0x76, 0x61, 0x72, 0x69, 0x6f, +0x75, 0x73, 0x00, 0x6e, 0x61, 0x6d, 0xa5, 0x00, 0xf2, 0x21, +0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, +0x6c, 0x79, 0x00, 0x60, 0x53, 0x6b, 0x79, 0x73, 0x63, 0x72, +0x61, 0x70, 0x65, 0x72, 0x73, 0x27, 0x2c, 0x00, 0x62, 0x75, +0x74, 0x00, 0x49, 0x00, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x00, +0x6b, 0x6e, 0x6f, 0x77, 0x00, 0x77, 0x68, 0x6f, 0xfc, 0x00, +0xb1, 0x00, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x64, +0x00, 0x69, 0x08, 0x01, 0x44, 0x33, 0x31, 0x2e, 0x31, 0x5e, +0x04, 0x00, 0x03, 0x03, 0x50, 0x72, 0x6f, 0x6c, 0x73, 0x20, +0x92, 0x00, 0x02, 0xfe, 0x00, 0x40, 0x73, 0x68, 0x61, 0x72, +0xb2, 0x00, 0x00, 0x78, 0x03, 0x21, 0x6f, 0x66, 0x1b, 0x04, +0x03, 0x26, 0x00, 0x72, 0x00, 0x73, 0x79, 0x73, 0x74, 0x65, +0x6d, 0x33, 0x04, 0xd1, 0x53, 0x6f, 0x6c, 0x6f, 0x2c, 0x00, +0x55, 0x6e, 0x65, 0x71, 0x75, 0x61, 0x6c, 0xf4, 0x00, 0x51, +0x4b, 0x65, 0x65, 0x6e, 0x2e, 0x48, 0x00, 0x53, 0x00, 0x70, +0x6c, 0x61, 0x79, 0x50, 0x00, 0xe1, 0x2c, 0x00, 0x73, 0x69, +0x6d, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, +0xe0, 0x00, 0x51, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x91, 0x02, +0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x03, +0x03, 0x12, 0x61, 0x49, 0x01, 0x50, 0x6e, 0x00, 0x74, 0x79, +0x70, 0xdc, 0x04, 0x54, 0x64, 0x69, 0x67, 0x69, 0x74, 0x17, +0x01, 0x80, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, +0x43, 0x02, 0x10, 0x66, 0xa3, 0x01, 0x02, 0x13, 0x03, 0x02, +0x3a, 0x00, 0x01, 0x94, 0x00, 0x05, 0x48, 0x04, 0x03, 0x8c, +0x04, 0x43, 0x69, 0x76, 0x65, 0x6e, 0xba, 0x02, 0x32, 0x2e, +0x00, 0x49, 0x7b, 0x03, 0x30, 0x6d, 0x61, 0x6b, 0x5a, 0x00, +0x8e, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2c, 0x97, +0x00, 0x02, 0x6d, 0x00, 0x50, 0x69, 0x6e, 0x63, 0x6f, 0x72, +0x86, 0x03, 0x08, 0x9b, 0x00, 0xa1, 0x70, 0x72, 0x65, 0x73, +0x73, 0x00, 0x53, 0x70, 0x61, 0x63, 0xc8, 0x02, 0x21, 0x63, +0x6c, 0x06, 0x03, 0xc0, 0x74, 0x00, 0x61, 0x67, 0x61, 0x69, +0x6e, 0x00, 0x28, 0x6f, 0x72, 0x00, 0x42, 0x00, 0x00, 0x3f, +0x00, 0xd1, 0x55, 0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, 0x61, +0x74, 0x75, 0x72, 0x65, 0x29, 0x7d, 0x02, 0x02, 0x7e, 0x00, +0x10, 0x72, 0x8c, 0x00, 0x12, 0x2d, 0x74, 0x00, 0x01, 0x92, +0x03, 0x0f, 0xf9, 0x00, 0x04, 0x02, 0x4a, 0x04, 0x12, 0x2c, +0xe3, 0x00, 0x03, 0x57, 0x04, 0x04, 0x97, 0x02, 0x00, 0xcc, +0x01, 0x10, 0x72, 0xce, 0x01, 0x18, 0x6e, 0x3e, 0x04, 0x01, +0x3a, 0x03, 0x71, 0x60, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, +0x08, 0x03, 0x43, 0x27, 0x2e, 0x00, 0x59, 0xf3, 0x05, 0x01, +0x2a, 0x06, 0x07, 0x1b, 0x00, 0x11, 0x73, 0xd1, 0x02, 0x74, +0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0xb7, 0x04, 0x15, +0x73, 0x51, 0x00, 0x24, 0x61, 0x6d, 0x56, 0x00, 0x34, 0x2e, +0x00, 0x41, 0x60, 0x00, 0x03, 0x2d, 0x05, 0x00, 0xea, 0x03, +0x04, 0x67, 0x01, 0x30, 0x63, 0x61, 0x6e, 0xda, 0x03, 0x44, +0x61, 0x6c, 0x73, 0x6f, 0x1f, 0x00, 0x09, 0x66, 0x00, 0x02, +0xe7, 0x02, 0x30, 0x65, 0x00, 0x67, 0x51, 0x00, 0xd0, 0x70, +0x61, 0x79, 0x73, 0x00, 0x6e, 0x6f, 0x00, 0x61, 0x74, 0x74, +0x65, 0x6e, 0xdc, 0x04, 0x00, 0x42, 0x01, 0x08, 0x2e, 0x00, +0x00, 0x84, 0x03, 0x00, 0xaf, 0x04, 0x60, 0x63, 0x74, 0x6c, +0x79, 0x00, 0x77, 0xf8, 0x00, 0x00, 0x31, 0x01, 0x03, 0x51, +0x01, 0x11, 0x6d, 0xb2, 0x00, 0x50, 0x69, 0x73, 0x00, 0x75, +0x70, 0x38, 0x00, 0x45, 0x79, 0x6f, 0x75, 0x3a, 0xd1, 0x06, +0x05, 0x23, 0x00, 0x95, 0x61, 0x73, 0x00, 0x72, 0x65, 0x6d, +0x69, 0x6e, 0x64, 0x7b, 0x05, 0x17, 0x61, 0x33, 0x03, 0x04, +0xc9, 0x00, 0x42, 0x6e, 0x65, 0x65, 0x64, 0x7c, 0x06, 0x50, +0x65, 0x00, 0x72, 0x65, 0x2d, 0x21, 0x05, 0x42, 0x69, 0x6e, +0x65, 0x64, 0xe6, 0x05, 0x00, 0x54, 0x00, 0x01, 0x3e, 0x03, +0x30, 0x6d, 0x6f, 0x72, 0xb1, 0x04, 0x2b, 0x6f, 0x75, 0x45, +0x00, 0x04, 0x99, 0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, 0x02, +0x54, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x80, 0x02, 0x05, 0x51, +0x06, 0x07, 0x61, 0x01, 0x13, 0x61, 0x96, 0x02, 0x04, 0xe2, +0x06, 0x20, 0x6f, 0x72, 0x06, 0x03, 0x20, 0x74, 0x68, 0x58, +0x01, 0x23, 0x65, 0x6c, 0x36, 0x05, 0x93, 0x66, 0x65, 0x65, +0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0x4f, 0x03, 0x41, 0x65, +0x72, 0x61, 0x73, 0xeb, 0x07, 0x49, 0x69, 0x6e, 0x67, 0x6c, +0xca, 0x01, 0x1c, 0x2c, 0x52, 0x02, 0x08, 0x12, 0x02, 0x22, +0x6e, 0x64, 0x4f, 0x02, 0x05, 0xd5, 0x01, 0x03, 0x49, 0x02, +0x01, 0xaf, 0x02, 0x00, 0x5b, 0x00, 0x3a, 0x41, 0x6c, 0x6c, +0x17, 0x02, 0x09, 0x93, 0x02, 0x22, 0x72, 0x65, 0x79, 0x00, +0x10, 0x64, 0x9b, 0x05, 0x12, 0x6e, 0xb8, 0x06, 0x24, 0x65, +0x66, 0x6c, 0x00, 0x05, 0x5e, 0x00, 0x18, 0x61, 0x14, 0x01, +0x0f, 0x2a, 0x00, 0x05, 0x02, 0x3a, 0x03, 0x10, 0x73, 0x3a, +0x03, 0x36, 0x2e, 0x00, 0x52, 0xb3, 0x00, 0x01, 0x4f, 0x02, +0x04, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x23, 0x00, 0x02, +0xeb, 0x02, 0x01, 0x58, 0x02, 0x02, 0xfb, 0x00, 0x0c, 0x56, +0x02, 0x12, 0x41, 0xc2, 0x02, 0x02, 0x84, 0x04, 0x01, 0x8a, +0x05, 0x50, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x23, 0x04, 0x14, +0x73, 0x70, 0x07, 0x22, 0x75, 0x73, 0x24, 0x03, 0x61, 0x63, +0x6f, 0x6e, 0x6a, 0x75, 0x6e, 0x4f, 0x07, 0x02, 0x26, 0x04, +0x00, 0x30, 0x00, 0x02, 0x59, 0x04, 0x01, 0x2f, 0x00, 0x01, +0x91, 0x06, 0x15, 0x74, 0xa4, 0x01, 0x2b, 0x6f, 0x72, 0x6e, +0x00, 0x3d, 0x55, 0x73, 0x65, 0x63, 0x00, 0x51, 0x74, 0x6f, +0x00, 0x6d, 0x6f, 0x7e, 0x09, 0x51, 0x68, 0x69, 0x67, 0x68, +0x6c, 0x2f, 0x08, 0x16, 0x61, 0x08, 0x06, 0x03, 0x63, 0x07, +0x2a, 0x6e, 0x64, 0xc8, 0x04, 0x22, 0x74, 0x6f, 0xbc, 0x03, +0x00, 0x33, 0x04, 0x03, 0xab, 0x01, 0x05, 0x3f, 0x00, 0x25, +0x65, 0x64, 0x73, 0x03, 0x14, 0x50, 0x0c, 0x01, 0x50, 0x72, +0x65, 0x74, 0x75, 0x72, 0x28, 0x03, 0x5a, 0x67, 0x67, 0x6c, +0x65, 0x73, 0x30, 0x00, 0x02, 0x3e, 0x08, 0x51, 0x61, 0x00, +0x6d, 0x6f, 0x64, 0xb4, 0x04, 0x55, 0x77, 0x68, 0x69, 0x63, +0x68, 0x93, 0x02, 0x02, 0x67, 0x00, 0x20, 0x6f, 0x72, 0x10, +0x03, 0x2e, 0x6f, 0x76, 0x40, 0x01, 0x05, 0x63, 0x00, 0x12, +0x4d, 0x6b, 0x01, 0x01, 0x4f, 0x05, 0x01, 0xfd, 0x01, 0x41, +0x66, 0x75, 0x6c, 0x6c, 0x10, 0x01, 0x2d, 0x6f, 0x66, 0x1b, +0x02, 0x08, 0x9c, 0x09, 0x03, 0xa9, 0x08, 0x31, 0x6f, 0x65, +0x73, 0xde, 0x07, 0x03, 0x8c, 0x0a, 0x10, 0x6d, 0x03, 0x04, +0x02, 0xed, 0x00, 0x23, 0x69, 0x6e, 0x6f, 0x06, 0x38, 0x4c, +0x65, 0x66, 0xed, 0x01, 0x02, 0xde, 0x07, 0x01, 0x76, 0x00, +0x00, 0x59, 0x00, 0x01, 0x3f, 0x05, 0x30, 0x73, 0x00, 0x64, +0xbe, 0x07, 0x60, 0x28, 0x67, 0x72, 0x65, 0x79, 0x00, 0xf1, +0x05, 0x31, 0x75, 0x74, 0x29, 0x4f, 0x02, 0x24, 0x75, 0x6e, +0x24, 0x00, 0x10, 0x69, 0x8a, 0x06, 0x00, 0x01, 0x04, 0x73, +0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0xeb, 0x07, 0x60, +0x2e, 0x00, 0x48, 0x6f, 0x6c, 0x64, 0x59, 0x00, 0x13, 0x43, +0xa4, 0x06, 0x00, 0x17, 0x02, 0x4a, 0x68, 0x69, 0x66, 0x74, +0x57, 0x02, 0x50, 0x61, 0x6e, 0x00, 0x61, 0x72, 0x31, 0x0a, +0x31, 0x6b, 0x65, 0x79, 0x5a, 0x03, 0x01, 0xa2, 0x08, 0x02, +0xda, 0x00, 0x00, 0x86, 0x06, 0x01, 0x95, 0x00, 0x27, 0x69, +0x6e, 0x37, 0x06, 0x05, 0x84, 0x09, 0x00, 0xc4, 0x00, 0x10, +0x28, 0x2a, 0x03, 0x00, 0x1c, 0x00, 0x11, 0x61, 0x13, 0x00, +0x15, 0x73, 0xf8, 0x09, 0x11, 0x64, 0xa3, 0x0a, 0x12, 0x65, +0x5e, 0x02, 0x31, 0x32, 0x2e, 0x31, 0x36, 0x03, 0x01, 0xb9, +0x02, 0x50, 0x61, 0x76, 0x61, 0x69, 0x6c, 0xf2, 0x08, 0x22, +0x2e, 0x29, 0x74, 0x07, 0x14, 0x32, 0x74, 0x07, 0x71, 0x70, +0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0xdd, 0x0b, 0x01, 0x21, +0x05, 0x00, 0xe1, 0x02, 0x05, 0x14, 0x00, 0x02, 0x42, 0x00, +0x04, 0x3d, 0x00, 0x04, 0x15, 0x0a, 0xf1, 0x01, 0x65, 0x00, +0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, +0x27, 0x00, 0x6f, 0x70, 0x70, 0x00, 0x03, 0x18, 0x07, 0xb0, +0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, +0x75, 0xac, 0x00, 0x51, 0x47, 0x72, 0x69, 0x64, 0x20, 0xb0, +0x0b, 0x33, 0x00, 0x00, 0x53, 0xc2, 0x08, 0x1f, 0x73, 0xc5, +0x0b, 0x04, 0x11, 0x4c, 0xc8, 0x05, 0x32, 0x6c, 0x69, 0x6d, +0x5c, 0x01, 0x68, 0x33, 0x3b, 0x00, 0x75, 0x70, 0x70, 0x12, +0x00, 0x74, 0x39, 0x00, 0x28, 0x62, 0x65, 0x63, 0x61, 0xd7, +0x06, 0x20, 0x75, 0x73, 0xbe, 0x02, 0x00, 0x5d, 0x02, 0x11, +0x66, 0xa7, 0x03, 0x01, 0xde, 0x09, 0x21, 0x62, 0x65, 0x68, +0x09, 0x01, 0x32, 0x05, 0x40, 0x64, 0x69, 0x66, 0x66, 0x2a, +0x05, 0x12, 0x74, 0x6b, 0x03, 0x11, 0x60, 0x0c, 0x02, 0x70, +0x73, 0x27, 0x00, 0x62, 0x69, 0x67, 0x67, 0xb8, 0x0a, 0x61, +0x68, 0x61, 0x6e, 0x00, 0x39, 0x21, 0x12, 0x07, 0x14, 0x44, +0x2b, 0x00, 0x34, 0x79, 0x00, 0x00, 0xbe, 0x01, 0x13, 0x73, +0x9d, 0x03, 0x05, 0x1a, 0x00, 0x04, 0xae, 0x00, 0x50, 0x65, +0x6e, 0x65, 0x72, 0x61, 0x25, 0x03, 0x02, 0x32, 0x09, 0x70, +0x2e, 0x00, 0x41, 0x74, 0x00, 0x55, 0x6e, 0x30, 0x0a, 0x21, +0x6f, 0x6e, 0x28, 0x01, 0x53, 0x6c, 0x65, 0x76, 0x65, 0x6c, +0xc7, 0x09, 0x72, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, +0x71, 0x02, 0x04, 0x36, 0x07, 0x82, 0x72, 0x65, 0x71, 0x75, +0x69, 0x72, 0x65, 0x64, 0x2a, 0x09, 0x01, 0x0f, 0x01, 0x31, +0x6f, 0x6c, 0x75, 0x48, 0x01, 0x21, 0x73, 0x68, 0xc8, 0x00, +0x23, 0x73, 0x74, 0x2b, 0x00, 0x71, 0x75, 0x6e, 0x69, 0x71, +0x75, 0x65, 0x2e, 0xbc, 0x06, 0x33, 0x72, 0x65, 0x6d, 0xf6, +0x06, 0x01, 0x62, 0x00, 0x14, 0x73, 0x48, 0x00, 0x07, 0xfa, +0x0a, 0x00, 0xdc, 0x08, 0x10, 0x6f, 0x65, 0x0b, 0x22, 0x78, +0x00, 0x91, 0x00, 0x01, 0xaf, 0x0b, 0x00, 0x02, 0x02, 0x30, +0x6f, 0x69, 0x64, 0x1a, 0x03, 0x03, 0x10, 0x00, 0x05, 0x97, +0x00, 0x03, 0x85, 0x09, 0x14, 0x33, 0x11, 0x02, 0x00, 0x56, +0x01, 0xb1, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, +0x6e, 0x63, 0x65, 0x17, 0x02, 0x20, 0x4f, 0x6e, 0x45, 0x09, +0x63, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0xe9, 0x08, 0x62, +0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x84, 0x01, 0x07, 0x2e, +0x00, 0x12, 0x2c, 0x05, 0x02, 0x16, 0x50, 0x12, 0x00, 0x0d, +0x21, 0x02, 0x33, 0x47, 0x61, 0x6d, 0x21, 0x02, 0x02, 0x0f, +0x01, 0x32, 0x6c, 0x65, 0x74, 0x2b, 0x04, 0x73, 0x6f, 0x6e, +0x66, 0x69, 0x67, 0x75, 0x72, 0x23, 0x06, 0x36, 0x74, 0x79, +0x6c, 0x20, 0x02, 0x20, 0x61, 0x6d, 0x89, 0x01, 0x10, 0x73, +0xca, 0x09, 0x05, 0x3c, 0x09, 0x02, 0x5e, 0x0a, 0x00, 0x3f, +0x03, 0x02, 0x85, 0x0b, 0xf1, 0x01, 0x68, 0x72, 0x65, 0x65, +0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, +0x61, 0x6c, 0x8e, 0x04, 0x50, 0x2c, 0x00, 0x73, 0x65, 0x6c, +0x12, 0x03, 0x72, 0x6e, 0x67, 0x00, 0x60, 0x32, 0x44, 0x27, +0x73, 0x00, 0x61, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x17, +0x01, 0x02, 0x11, 0x0a, 0x24, 0x65, 0x72, 0x5f, 0x00, 0x03, +0x79, 0x00, 0x05, 0xc5, 0x04, 0x07, 0xdd, 0x0c, 0xa0, 0x73, +0x68, 0x6f, 0x77, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x6a, 0xcf, +0x0b, 0x42, 0x77, 0x72, 0x69, 0x74, 0x0b, 0x0d, 0x24, 0x65, +0x69, 0x92, 0x0c, 0x07, 0xf4, 0x06, 0x50, 0x61, 0x72, 0x65, +0x2e, 0x00, }; -const unsigned short help_text_len = 3541; -const unsigned short help_text_words = 674; +const unsigned short help_text_len = 3906; +const unsigned short help_text_words = 732; const char quick_help_text[] = "Complete the latin square of towers in accordance with the clues."; diff --git a/apps/plugins/puzzles/help/tracks.c b/apps/plugins/puzzles/help/tracks.c index dc1bd011fa..fae974619a 100644 --- a/apps/plugins/puzzles/help/tracks.c +++ b/apps/plugins/puzzles/help/tracks.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,27 +6,28 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 86, TEXT_CENTER | C_RED }, - { 207, TEXT_CENTER | C_RED }, - { 224, TEXT_UNDERLINE }, - { 225, TEXT_UNDERLINE }, - { 236, TEXT_UNDERLINE }, - { 268, TEXT_UNDERLINE }, + { 88, TEXT_CENTER | C_RED }, + { 209, TEXT_CENTER | C_RED }, + { 226, TEXT_UNDERLINE }, + { 227, TEXT_UNDERLINE }, + { 238, TEXT_UNDERLINE }, + { 270, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1862 comp 1274 ratio 0.684211 level 10 saved 588 */ +/* orig 1917 comp 1289 ratio 0.672405 level 10 saved 628 */ const char help_text[] = { -0xf0, 0x2c, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, -0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x73, -0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, -0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, -0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, -0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, -0x65, 0x11, 0x00, 0x51, 0x77, 0x68, 0x69, 0x63, 0x68, 0x2b, -0x00, 0xf1, 0x04, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, -0x77, 0x69, 0x74, 0x68, 0x00, 0x74, 0x72, 0x61, 0x69, 0x6e, -0x00, 0x74, 0x4f, 0x00, 0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05, +0xf0, 0x02, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x06, +0x00, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x00, 0x2d, 0x01, 0x00, +0x04, 0xf0, 0x19, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, +0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, +0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, +0x6f, 0x6d, 0x65, 0x11, 0x00, 0x51, 0x77, 0x68, 0x69, 0x63, +0x68, 0x2b, 0x00, 0xd0, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, +0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x74, 0x68, 0x00, 0x21, +0x00, 0x74, 0x68, 0x00, 0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05, 0x6e, 0x65, 0x65, 0x64, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, 0x74, 0x68, 0x65, 0x21, 0x00, 0x70, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x41, @@ -49,104 +50,104 @@ const char help_text[] = { 0x00, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x2c, 0x1c, 0x00, 0x06, 0xd7, 0x00, 0xf1, 0x05, 0x6d, 0x61, 0x79, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0x69, 0x74, -0x73, 0x65, 0x6c, 0x66, 0x5a, 0x00, 0x01, 0x16, 0x01, 0x32, -0x00, 0x77, 0x61, 0xd1, 0x00, 0x40, 0x72, 0x69, 0x62, 0x75, -0xa2, 0x00, 0x01, 0x95, 0x00, 0x20, 0x69, 0x73, 0xed, 0x00, -0xf0, 0x08, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, -0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, -0x61, 0x72, 0x76, 0x65, 0x79, 0x3d, 0x00, 0x44, 0x34, 0x30, -0x2e, 0x31, 0xa7, 0x01, 0x01, 0x3e, 0x00, 0x21, 0x6f, 0x6c, -0xb0, 0x01, 0xf4, 0x15, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, -0x6c, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x6f, 0x6e, -0x00, 0x61, 0x6e, 0x00, 0x65, 0x64, 0x67, 0x65, 0x00, 0x62, -0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x77, 0x6f, -0xbd, 0x01, 0x7a, 0x00, 0x61, 0x64, 0x64, 0x73, 0x00, 0x61, -0x34, 0x01, 0x06, 0x29, 0x00, 0x28, 0x68, 0x65, 0x2d, 0x00, -0x30, 0x2e, 0x00, 0x52, 0xf8, 0x00, 0x0f, 0x5c, 0x00, 0x02, -0x03, 0x48, 0x00, 0x02, 0xe1, 0x00, 0x12, 0x6f, 0x3b, 0x00, -0x00, 0x19, 0x00, 0x14, 0x2c, 0x79, 0x01, 0x00, 0x30, 0x00, -0x23, 0x6e, 0x6f, 0x69, 0x00, 0xa1, 0x69, 0x73, 0x00, 0x70, -0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0xfd, 0x01, 0x3d, 0x72, -0x65, 0x2e, 0xb8, 0x00, 0x10, 0x69, 0x6b, 0x02, 0x02, 0x79, -0x00, 0x05, 0x5d, 0x00, 0x54, 0x6f, 0x6c, 0x6f, 0x75, 0x72, -0x51, 0x00, 0x70, 0x6f, 0x72, 0x00, 0x73, 0x68, 0x6f, 0x77, -0x2c, 0x00, 0x01, 0x27, 0x02, 0x82, 0x79, 0x6f, 0x75, 0x00, -0x6b, 0x6e, 0x6f, 0x77, 0x13, 0x02, 0x02, 0x39, 0x00, 0x45, -0x6d, 0x75, 0x73, 0x74, 0x2b, 0x02, 0x03, 0xe6, 0x00, 0x30, -0x2c, 0x00, 0x65, 0xc8, 0x02, 0x21, 0x69, 0x66, 0x32, 0x00, -0x52, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x38, 0x00, 0x02, 0xbf, -0x02, 0x00, 0xb5, 0x00, 0x00, 0xa3, 0x01, 0x02, 0xcb, 0x00, -0x6d, 0x65, 0x73, 0x00, 0x79, 0x65, 0x74, 0xf9, 0x00, 0x0e, -0x9d, 0x00, 0x04, 0xdb, 0x01, 0x06, 0xed, 0x00, 0x15, 0x69, -0x7a, 0x00, 0x16, 0x73, 0xf9, 0x00, 0x03, 0x62, 0x01, 0x05, -0xef, 0x00, 0x32, 0x00, 0x6f, 0x72, 0x74, 0x02, 0x60, 0x2d, -0x64, 0x72, 0x61, 0x67, 0x67, 0x38, 0x00, 0x04, 0x7d, 0x01, -0x05, 0xa2, 0x01, 0x20, 0x6c, 0x6c, 0xfd, 0x02, 0x00, 0xad, -0x00, 0x86, 0x74, 0x6f, 0x00, 0x6c, 0x61, 0x79, 0x00, 0x61, -0x83, 0x02, 0x31, 0x6c, 0x69, 0x6e, 0x7b, 0x03, 0x32, 0x69, -0x73, 0x2d, 0x61, 0x00, 0x20, 0x6f, 0x72, 0x0c, 0x00, 0x33, -0x6e, 0x6f, 0x74, 0x10, 0x00, 0x05, 0x2d, 0x01, 0xd1, 0x73, -0x2c, 0x00, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x66, -0x6f, 0x72, 0xa1, 0x03, 0x03, 0xc9, 0x00, 0x01, 0x5b, 0x03, -0x25, 0x6f, 0x72, 0x5a, 0x03, 0x85, 0x74, 0x6f, 0x00, 0x6d, -0x61, 0x74, 0x63, 0x68, 0x25, 0x03, 0x00, 0xad, 0x00, 0x41, -0x28, 0x41, 0x6c, 0x6c, 0x11, 0x00, 0x11, 0x61, 0x8f, 0x02, -0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, -0x4f, 0x03, 0x13, 0x73, 0xa5, 0x02, 0x41, 0x32, 0x2e, 0x31, -0x00, 0x13, 0x01, 0xf2, 0x00, 0x6c, 0x73, 0x6f, 0x00, 0x61, -0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, -0xad, 0x02, 0x14, 0x32, 0xad, 0x02, 0xb2, 0x70, 0x61, 0x72, -0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x5e, 0x03, -0x36, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x42, 0x00, 0x04, -0x3d, 0x00, 0x02, 0x12, 0x04, 0x00, 0x7a, 0x00, 0xe1, 0x60, -0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, -0x00, 0x6f, 0x70, 0x70, 0x00, 0x03, 0x68, 0x02, 0xb0, 0x60, -0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, -0xac, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, -0x48, 0x65, 0x22, 0x01, 0x68, 0x00, 0x00, 0x53, 0x69, 0x7a, -0x65, 0xd3, 0x03, 0x00, 0x93, 0x02, 0x06, 0xd3, 0x02, 0xf3, -0x01, 0x00, 0x00, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, -0x6c, 0x74, 0x79, 0x00, 0x00, 0x00, 0x43, 0x49, 0x03, 0x01, -0x2e, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x04, 0x40, 0x00, 0x41, -0x65, 0x6e, 0x65, 0x72, 0x46, 0x04, 0xf3, 0x0b, 0x70, 0x75, -0x7a, 0x7a, 0x6c, 0x65, 0x3a, 0x00, 0x61, 0x74, 0x00, 0x54, -0x72, 0x69, 0x63, 0x6b, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x65, -0x6c, 0x2c, 0x00, 0x79, 0x2f, 0x05, 0x82, 0x72, 0x65, 0x71, -0x75, 0x69, 0x72, 0x65, 0x64, 0x51, 0x01, 0xc3, 0x6b, 0x65, -0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x64, 0x65, 0x64, 0x75, -0x43, 0x01, 0x60, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x86, -0x01, 0x36, 0x64, 0x69, 0x73, 0x0d, 0x00, 0x52, 0x6d, 0x6f, -0x76, 0x65, 0x73, 0xd3, 0x02, 0x91, 0x77, 0x6f, 0x75, 0x6c, -0x64, 0x00, 0x6c, 0x65, 0x61, 0x45, 0x00, 0x25, 0x69, 0x6d, -0x34, 0x03, 0x01, 0x6d, 0x02, 0xa2, 0x69, 0x6e, 0x67, 0x73, -0x00, 0x6c, 0x61, 0x74, 0x65, 0x72, 0xc6, 0x00, 0x11, 0x73, -0x2a, 0x02, 0x00, 0x0b, 0x04, 0xb2, 0x73, 0x65, 0x63, 0x75, -0x74, 0x69, 0x76, 0x65, 0x20, 0x31, 0x20, 0xe6, 0x04, 0x07, -0xd8, 0x00, 0x30, 0x77, 0x68, 0x65, 0x72, 0x03, 0x01, 0xce, -0x00, 0x03, 0x7f, 0x04, 0x35, 0x67, 0x61, 0x6d, 0xda, 0x00, -0x00, 0x57, 0x01, 0x71, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, -0x73, 0xfb, 0x03, 0x50, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x14, -0x04, 0x0f, 0x27, 0x02, 0x00, 0x81, 0x68, 0x61, 0x76, 0x65, -0x00, 0x61, 0x00, 0x31, 0x26, 0x02, 0x10, 0x2c, 0x1d, 0x00, -0x05, 0x3a, 0x00, 0x02, 0xb3, 0x05, 0x06, 0x30, 0x00, 0x04, -0x40, 0x01, 0x01, 0x95, 0x02, 0xbd, 0x27, 0x73, 0x00, 0x65, -0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x00, 0xc2, -0x2e, 0x00, 0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, -0x6c, 0x74, 0x05, 0x05, 0x21, 0x69, 0x73, 0x3b, 0x05, 0x02, -0x5b, 0x00, 0x60, 0x74, 0x65, 0x64, 0x2c, 0x00, 0x74, 0x5d, -0x02, 0x86, 0x6f, 0x69, 0x64, 0x00, 0x6c, 0x6f, 0x6e, 0x67, -0x0c, 0x03, 0x30, 0x62, 0x6f, 0x72, 0x40, 0x01, 0x05, 0xf9, -0x05, 0x05, 0x0b, 0x06, 0x00, 0x8c, 0x05, 0x01, 0x82, 0x01, -0x01, 0xc2, 0x01, 0x01, 0x46, 0x05, 0x01, 0x8c, 0x01, 0x71, -0x74, 0x77, 0x69, 0x64, 0x64, 0x6c, 0x79, 0x20, 0x00, 0x70, -0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0xba, 0x03, 0x32, -0x2e, 0x00, 0x49, 0x1c, 0x04, 0x22, 0x77, 0x61, 0xa1, 0x00, -0x00, 0x18, 0x00, 0x22, 0x6f, 0x72, 0x3f, 0x00, 0x02, 0x83, -0x01, 0xb2, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2c, 0x00, 0x74, -0x75, 0x72, 0x6e, 0xa5, 0x00, 0x03, 0x91, 0x02, 0x50, 0x6f, -0x66, 0x66, 0x2e, 0x00, +0x73, 0x65, 0x6c, 0x66, 0x5a, 0x00, 0x01, 0x1c, 0x01, 0x02, +0x84, 0x01, 0x32, 0x00, 0x77, 0x61, 0xd7, 0x00, 0x40, 0x72, +0x69, 0x62, 0x75, 0xa8, 0x00, 0x01, 0x9b, 0x00, 0x20, 0x69, +0x73, 0xf3, 0x00, 0xf0, 0x08, 0x6c, 0x65, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, +0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x43, 0x00, +0x4a, 0x34, 0x30, 0x2e, 0x31, 0xcc, 0x01, 0x01, 0x44, 0x00, +0xf4, 0x1c, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c, +0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x69, +0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x00, 0x61, 0x6e, 0x00, 0x65, +0x64, 0x67, 0x65, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, +0x6e, 0x00, 0x74, 0x77, 0x6f, 0xc9, 0x01, 0x7a, 0x00, 0x61, +0x64, 0x64, 0x73, 0x00, 0x61, 0x40, 0x01, 0x06, 0x29, 0x00, +0x28, 0x68, 0x65, 0x2d, 0x00, 0x30, 0x2e, 0x00, 0x52, 0x04, +0x01, 0x0f, 0x5c, 0x00, 0x02, 0x03, 0x48, 0x00, 0x02, 0xed, +0x00, 0x12, 0x6f, 0x3b, 0x00, 0x00, 0x19, 0x00, 0x14, 0x2c, +0x85, 0x01, 0x00, 0x30, 0x00, 0x23, 0x6e, 0x6f, 0x69, 0x00, +0xa1, 0x69, 0x73, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, +0x6c, 0x09, 0x02, 0x3d, 0x72, 0x65, 0x2e, 0xb8, 0x00, 0x10, +0x69, 0x77, 0x02, 0x02, 0x79, 0x00, 0x05, 0x5d, 0x00, 0x54, +0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x51, 0x00, 0x70, 0x6f, 0x72, +0x00, 0x73, 0x68, 0x6f, 0x77, 0x2c, 0x00, 0x01, 0x33, 0x02, +0x82, 0x79, 0x6f, 0x75, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x1f, +0x02, 0x02, 0x39, 0x00, 0x45, 0x6d, 0x75, 0x73, 0x74, 0x37, +0x02, 0x03, 0xe6, 0x00, 0x30, 0x2c, 0x00, 0x65, 0xd4, 0x02, +0x21, 0x69, 0x66, 0x32, 0x00, 0x52, 0x64, 0x6f, 0x6e, 0x27, +0x74, 0x38, 0x00, 0x02, 0xcb, 0x02, 0x00, 0xb5, 0x00, 0x00, +0xaf, 0x01, 0x02, 0xcb, 0x00, 0x6d, 0x65, 0x73, 0x00, 0x79, +0x65, 0x74, 0xf9, 0x00, 0x0e, 0x9d, 0x00, 0x04, 0xe7, 0x01, +0x06, 0xed, 0x00, 0x15, 0x69, 0x7a, 0x00, 0x16, 0x73, 0xf9, +0x00, 0x03, 0x62, 0x01, 0x05, 0xef, 0x00, 0x32, 0x00, 0x6f, +0x72, 0x80, 0x02, 0x60, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x67, +0x38, 0x00, 0x04, 0x7d, 0x01, 0x05, 0xa2, 0x01, 0x20, 0x6c, +0x6c, 0x09, 0x03, 0x00, 0xad, 0x00, 0x86, 0x74, 0x6f, 0x00, +0x6c, 0x61, 0x79, 0x00, 0x61, 0x8f, 0x02, 0x31, 0x6c, 0x69, +0x6e, 0x87, 0x03, 0x32, 0x69, 0x73, 0x2d, 0x61, 0x00, 0x20, +0x6f, 0x72, 0x0c, 0x00, 0x33, 0x6e, 0x6f, 0x74, 0x10, 0x00, +0x05, 0x2d, 0x01, 0xd1, 0x73, 0x2c, 0x00, 0x75, 0x73, 0x65, +0x66, 0x75, 0x6c, 0x00, 0x66, 0x6f, 0x72, 0xad, 0x03, 0x03, +0xc9, 0x00, 0x01, 0x67, 0x03, 0x25, 0x6f, 0x72, 0x66, 0x03, +0x85, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x31, +0x03, 0x00, 0xad, 0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x11, +0x00, 0x11, 0x61, 0x95, 0x02, 0x92, 0x73, 0x00, 0x64, 0x65, +0x73, 0x63, 0x72, 0x69, 0x62, 0x5b, 0x03, 0x13, 0x73, 0xab, +0x02, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x13, 0x01, 0xf2, 0x00, +0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, +0x62, 0x6c, 0x65, 0x2e, 0x29, 0xb3, 0x02, 0x1a, 0x32, 0xb3, +0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, +0x72, 0x73, 0x20, 0x70, 0x03, 0x36, 0x73, 0x65, 0x00, 0x14, +0x00, 0x02, 0x48, 0x00, 0x04, 0x43, 0x00, 0x02, 0x24, 0x04, +0x00, 0x80, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, +0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x76, 0x00, +0x03, 0x6e, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, +0x00, 0x6d, 0x65, 0x6e, 0x75, 0xb2, 0x00, 0x91, 0x57, 0x69, +0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x28, 0x01, 0x68, +0x00, 0x00, 0x53, 0x69, 0x7a, 0x65, 0xe5, 0x03, 0x00, 0x99, +0x02, 0x06, 0xd9, 0x02, 0xf3, 0x01, 0x00, 0x00, 0x44, 0x69, +0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x00, +0x00, 0x43, 0x4f, 0x03, 0x01, 0x2e, 0x00, 0x16, 0x64, 0x1a, +0x00, 0x04, 0x40, 0x00, 0x41, 0x65, 0x6e, 0x65, 0x72, 0x58, +0x04, 0xf3, 0x0b, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x3a, +0x00, 0x61, 0x74, 0x00, 0x54, 0x72, 0x69, 0x63, 0x6b, 0x79, +0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c, 0x00, 0x79, 0x41, +0x05, 0x82, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, +0x57, 0x01, 0xc3, 0x6b, 0x65, 0x00, 0x6d, 0x6f, 0x72, 0x65, +0x00, 0x64, 0x65, 0x64, 0x75, 0x49, 0x01, 0x60, 0x72, 0x65, +0x67, 0x61, 0x72, 0x64, 0x8c, 0x01, 0x36, 0x64, 0x69, 0x73, +0x0d, 0x00, 0x52, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0xd9, 0x02, +0x91, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6c, 0x65, 0x61, +0x45, 0x00, 0x25, 0x69, 0x6d, 0x3a, 0x03, 0x01, 0x73, 0x02, +0xa2, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x6c, 0x61, 0x74, 0x65, +0x72, 0xc6, 0x00, 0x11, 0x73, 0x30, 0x02, 0x00, 0x11, 0x04, +0xb2, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20, +0x31, 0x20, 0xf8, 0x04, 0x07, 0xd8, 0x00, 0x30, 0x77, 0x68, +0x65, 0x78, 0x03, 0x01, 0xce, 0x00, 0x09, 0x91, 0x04, 0x35, +0x67, 0x61, 0x6d, 0xe0, 0x00, 0x00, 0x5d, 0x01, 0x71, 0x70, +0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x07, 0x04, 0x50, 0x61, +0x64, 0x6a, 0x61, 0x63, 0x20, 0x04, 0x0f, 0x33, 0x02, 0x00, +0x81, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x31, 0x32, +0x02, 0x10, 0x2c, 0x1d, 0x00, 0x05, 0x3a, 0x00, 0x02, 0xcb, +0x05, 0x06, 0x30, 0x00, 0x04, 0x46, 0x01, 0x01, 0xa1, 0x02, +0xbd, 0x27, 0x73, 0x00, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x47, 0x00, 0xc2, 0x2e, 0x00, 0x42, 0x79, 0x00, +0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x17, 0x05, 0x21, +0x69, 0x73, 0x53, 0x05, 0x02, 0x5b, 0x00, 0x60, 0x74, 0x65, +0x64, 0x2c, 0x00, 0x74, 0x69, 0x02, 0x86, 0x6f, 0x69, 0x64, +0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x18, 0x03, 0x30, 0x62, 0x6f, +0x72, 0x46, 0x01, 0x05, 0x11, 0x06, 0x05, 0x23, 0x06, 0x00, +0xa4, 0x05, 0x01, 0x88, 0x01, 0x01, 0xc8, 0x01, 0x01, 0x58, +0x05, 0x01, 0x92, 0x01, 0x71, 0x74, 0x77, 0x69, 0x64, 0x64, +0x6c, 0x79, 0x20, 0x00, 0x70, 0x69, 0x6e, 0x74, 0x65, 0x72, +0x65, 0x73, 0xc6, 0x03, 0x32, 0x2e, 0x00, 0x49, 0x28, 0x04, +0x22, 0x77, 0x61, 0xa1, 0x00, 0x00, 0x18, 0x00, 0x22, 0x6f, +0x72, 0x3f, 0x00, 0x02, 0x89, 0x01, 0xb2, 0x69, 0x6c, 0x69, +0x74, 0x79, 0x2c, 0x00, 0x74, 0x75, 0x72, 0x6e, 0xa5, 0x00, +0x03, 0x97, 0x02, 0x50, 0x6f, 0x66, 0x66, 0x2e, 0x00, }; -const unsigned short help_text_len = 1862; -const unsigned short help_text_words = 336; +const unsigned short help_text_len = 1917; +const unsigned short help_text_words = 339; const char quick_help_text[] = "Fill in the railway track according to the clues."; diff --git a/apps/plugins/puzzles/help/twiddle.c b/apps/plugins/puzzles/help/twiddle.c index 48efbc10ad..1a989237b0 100644 --- a/apps/plugins/puzzles/help/twiddle.c +++ b/apps/plugins/puzzles/help/twiddle.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,202 +6,203 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 137, TEXT_CENTER | C_RED }, - { 297, TEXT_CENTER | C_RED }, + { 138, TEXT_CENTER | C_RED }, + { 298, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 2926 comp 1866 ratio 0.637731 level 10 saved 1060 */ +/* orig 2945 comp 1873 ratio 0.635993 level 10 saved 1072 */ const char help_text[] = { -0xf3, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x37, 0x3a, 0x20, 0x54, 0x77, 0x69, 0x64, 0x64, 0x6c, 0x65, -0x20, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xf2, 0x34, 0x00, 0x69, -0x73, 0x00, 0x61, 0x00, 0x74, 0x69, 0x6c, 0x65, 0x2d, 0x72, -0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x6d, 0x65, -0x6e, 0x74, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, -0x00, 0x76, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x00, -0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x00, 0x74, 0x6f, -0x00, 0x53, 0x69, 0x78, 0x74, 0x65, 0x65, 0x6e, 0x00, 0x28, -0x73, 0x65, 0x65, 0x00, 0x63, 0x5f, 0x00, 0xf0, 0x11, 0x00, -0x36, 0x29, 0x3a, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x61, 0x72, -0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, -0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, -0x75, 0x17, 0x00, 0x00, 0x67, 0x00, 0xf0, 0x11, 0x73, 0x2c, -0x00, 0x65, 0x61, 0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, 0x74, -0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x00, 0x6e, -0x75, 0x6d, 0x62, 0x65, 0x72, 0x2c, 0x00, 0x61, 0x6e, 0x64, -0x44, 0x00, 0x50, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x9a, 0x00, -0x33, 0x74, 0x6f, 0x00, 0x94, 0x00, 0x43, 0x00, 0x74, 0x68, -0x65, 0x27, 0x00, 0x40, 0x73, 0x00, 0x69, 0x6e, 0x19, 0x00, -0x50, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x40, 0x00, 0xf4, 0x02, -0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x00, 0x49, -0x6e, 0x00, 0x62, 0x61, 0x73, 0x69, 0x63, 0xdd, 0x00, 0x12, -0x2c, 0x4d, 0x00, 0x43, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x00, -0x84, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x00, 0x61, 0x92, -0x00, 0x50, 0x67, 0x72, 0x6f, 0x75, 0x70, 0xa2, 0x00, 0x10, -0x66, 0x29, 0x00, 0x01, 0xa0, 0x00, 0x60, 0x00, 0x61, 0x62, -0x6f, 0x75, 0x74, 0x70, 0x00, 0xf0, 0x0f, 0x69, 0x72, 0x00, -0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x00, 0x63, 0x65, 0x6e, -0x74, 0x72, 0x65, 0x2e, 0x00, 0x28, 0x4f, 0x72, 0x69, 0x65, -0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x00, 0xf1, -0x03, 0x6e, 0x6f, 0x74, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x69, -0x66, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x00, 0x69, 0x6e, 0xa8, -0x00, 0x02, 0x85, 0x00, 0x04, 0x42, 0x01, 0x81, 0x61, 0x6c, -0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x1e, 0x01, 0xf5, 0x1b, -0x63, 0x61, 0x6e, 0x00, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, -0x00, 0x69, 0x74, 0x2e, 0x29, 0x00, 0x4f, 0x6e, 0x00, 0x6d, -0x6f, 0x72, 0x65, 0x00, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, -0x65, 0x64, 0x00, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, -0x73, 0x2c, 0x2f, 0x00, 0x05, 0xb4, 0x00, 0x6d, 0x6c, 0x61, -0x72, 0x67, 0x65, 0x72, 0xbb, 0x00, 0x01, 0xb6, 0x00, 0x01, -0xff, 0x00, 0xd0, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, 0x00, -0x73, 0x61, 0x77, 0x00, 0x74, 0x68, 0xf1, 0x00, 0x30, 0x79, -0x70, 0x65, 0x22, 0x00, 0x02, 0x8a, 0x00, 0x04, 0x9e, 0x00, -0xf2, 0x13, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x75, 0x62, 0x65, -0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x60, 0x4d, 0x65, 0x74, -0x72, 0x6f, 0x69, 0x64, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x65, -0x00, 0x32, 0x27, 0x2e, 0x00, 0x49, 0x28, 0x00, 0xd0, 0x4d, -0x61, 0x69, 0x6e, 0x00, 0x47, 0x79, 0x72, 0x6f, 0x00, 0x43, -0x68, 0x61, 0x79, 0x01, 0x02, 0x41, 0x00, 0x21, 0x61, 0x74, -0x39, 0x00, 0x10, 0x2c, 0x24, 0x00, 0x13, 0x72, 0x40, 0x02, -0x03, 0x61, 0x00, 0x00, 0xb2, 0x00, 0x50, 0x73, 0x6f, 0x6c, -0x76, 0x65, 0x6b, 0x01, 0xf2, 0x05, 0x75, 0x6e, 0x6c, 0x6f, -0x63, 0x6b, 0x00, 0x61, 0x00, 0x64, 0x6f, 0x6f, 0x72, 0x2c, -0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x2e, 0x00, 0xb1, 0x73, -0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x00, 0x63, 0x61, 0x73, -0x9f, 0x00, 0x03, 0xae, 0x01, 0xd2, 0x2e, 0x00, 0x49, 0x00, -0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x64, 0xc1, -0x00, 0x01, 0xa2, 0x00, 0x20, 0x61, 0x73, 0x4a, 0x02, 0x82, -0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x69, 0x73, 0x7c, 0x01, -0x22, 0x6f, 0x66, 0x8a, 0x00, 0x02, 0x79, 0x00, 0x00, 0xfd, -0x00, 0x35, 0x37, 0x2e, 0x31, 0xdf, 0x02, 0x00, 0x5c, 0x02, -0x41, 0x72, 0x6f, 0x6c, 0x73, 0xe8, 0x02, 0x66, 0x6f, 0x00, -0x70, 0x6c, 0x61, 0x79, 0x13, 0x02, 0x51, 0x63, 0x6c, 0x69, -0x63, 0x6b, 0xe1, 0x00, 0x45, 0x6d, 0x6f, 0x75, 0x73, 0x16, -0x01, 0x02, 0xe3, 0x01, 0x02, 0x59, 0x00, 0x1a, 0x65, 0x64, -0x01, 0x00, 0xd7, 0x00, 0x46, 0x77, 0x69, 0x73, 0x68, 0x41, -0x02, 0x05, 0x24, 0x01, 0x02, 0xea, 0x01, 0x32, 0x6d, 0x6f, -0x64, 0x6c, 0x02, 0x06, 0xac, 0x01, 0x33, 0x32, 0x78, 0x32, -0x45, 0x00, 0x04, 0xfb, 0x00, 0x51, 0x6d, 0x65, 0x61, 0x6e, -0x73, 0x25, 0x00, 0x22, 0x68, 0x61, 0x22, 0x01, 0x02, 0x8a, -0x00, 0xf1, 0x04, 0x61, 0x74, 0x00, 0x61, 0x00, 0x63, 0x6f, -0x72, 0x6e, 0x65, 0x72, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, -0x00, 0x77, 0x59, 0x01, 0x07, 0x92, 0x02, 0x43, 0x6d, 0x65, -0x65, 0x74, 0xe0, 0x02, 0x0a, 0x2d, 0x02, 0x00, 0x79, 0x00, -0x02, 0x54, 0x00, 0x82, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x00, -0x62, 0x65, 0x82, 0x00, 0x00, 0x16, 0x03, 0xa4, 0x33, 0x78, -0x33, 0x00, 0x6f, 0x72, 0x00, 0x65, 0x76, 0x65, 0x36, 0x00, -0x11, 0x74, 0xea, 0x03, 0x53, 0x6d, 0x65, 0x3b, 0x00, 0x69, -0xe6, 0x00, 0x2c, 0x69, 0x7a, 0xf2, 0x00, 0x60, 0x69, 0x73, -0x00, 0x6f, 0x64, 0x64, 0x12, 0x00, 0x12, 0x6e, 0xcf, 0x01, -0x53, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0xab, 0x00, 0x0a, 0x2b, -0x01, 0x00, 0x9c, 0x00, 0x0b, 0x3e, 0x00, 0x01, 0x2a, 0x01, -0x00, 0x09, 0x03, 0x07, 0x2a, 0x01, 0x30, 0x00, 0x00, 0x43, -0x3d, 0x00, 0x00, 0x93, 0x00, 0x41, 0x77, 0x69, 0x74, 0x68, -0x2f, 0x00, 0x43, 0x6c, 0x65, 0x66, 0x74, 0x7f, 0x01, 0x54, -0x62, 0x75, 0x74, 0x74, 0x6f, 0xe5, 0x02, 0x11, 0x73, 0x1e, -0x00, 0x02, 0x76, 0x01, 0x50, 0x61, 0x6e, 0x74, 0x69, 0x63, -0x43, 0x02, 0x5f, 0x77, 0x69, 0x73, 0x65, 0x2e, 0x45, 0x00, -0x00, 0x12, 0x72, 0xf3, 0x00, 0x0a, 0x40, 0x00, 0x37, 0x69, -0x74, 0x00, 0x35, 0x00, 0x33, 0x00, 0x00, 0x59, 0x45, 0x03, -0x42, 0x61, 0x6c, 0x73, 0x6f, 0x09, 0x04, 0x95, 0x61, 0x6e, -0x00, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0xb6, 0x00, 0x51, -0x61, 0x72, 0x6f, 0x75, 0x6e, 0xf4, 0x00, 0x02, 0xb1, 0x04, -0x05, 0x62, 0x00, 0xcb, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, -0x00, 0x6b, 0x65, 0x79, 0x73, 0x3b, 0x25, 0x01, 0x05, 0x3f, -0x01, 0x20, 0x61, 0x62, 0x55, 0x00, 0x10, 0x28, 0xf0, 0x01, -0xb0, 0x62, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, -0x74, 0x2c, 0x7a, 0x01, 0x02, 0xaf, 0x03, 0x80, 0x29, 0x2e, -0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0xbb, 0x00, 0x01, 0xb6, -0x00, 0x50, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x54, 0x00, 0x00, -0x24, 0x00, 0x40, 0x73, 0x70, 0x61, 0x63, 0x46, 0x02, 0x64, -0x72, 0x00, 0x77, 0x69, 0x6c, 0x6c, 0x3f, 0x02, 0x03, 0x7c, -0x00, 0x10, 0x72, 0x88, 0x05, 0x04, 0xa4, 0x00, 0x08, 0x0e, -0x01, 0x00, 0x3a, 0x00, 0x06, 0x0d, 0x00, 0x20, 0x72, 0x65, -0x51, 0x03, 0x60, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0xf3, -0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x43, 0x00, 0x20, 0x61, -0x63, 0x2c, 0x03, 0xd0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, -0x72, 0x69, 0x62, 0x65, 0x64, 0x00, 0x69, 0x7d, 0x04, 0x11, -0x63, 0x42, 0x03, 0x31, 0x32, 0x2e, 0x31, 0xab, 0x05, 0x01, -0x19, 0x01, 0xb1, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, -0x6c, 0x65, 0x2e, 0x29, 0x4b, 0x03, 0x15, 0x32, 0x4b, 0x03, -0xa8, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, -0x73, 0x35, 0x06, 0x50, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x7b, -0x02, 0x30, 0x73, 0x65, 0x76, 0x97, 0x03, 0x00, 0xce, 0x05, -0x53, 0x66, 0x69, 0x67, 0x75, 0x72, 0x9e, 0x03, 0x12, 0x70, -0x79, 0x00, 0x31, 0x76, 0x69, 0x61, 0x89, 0x00, 0x83, 0x60, -0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x27, 0x19, 0x00, 0x32, -0x00, 0x6f, 0x6e, 0x17, 0x00, 0xf5, 0x00, 0x54, 0x79, 0x70, -0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x3a, 0x00, 0x00, -0x00, 0x2d, 0xad, 0x01, 0x04, 0x4e, 0x00, 0x02, 0x0a, 0x01, -0x51, 0x77, 0x69, 0x64, 0x74, 0x68, 0x1b, 0x06, 0x21, 0x68, -0x65, 0xf3, 0x01, 0x03, 0x74, 0x02, 0x03, 0x75, 0x04, 0x00, -0xb3, 0x01, 0x1f, 0x2e, 0x3f, 0x00, 0x08, 0x04, 0xe5, 0x02, -0x03, 0x49, 0x01, 0x11, 0x62, 0x96, 0x04, 0x01, 0x3d, 0x04, -0x04, 0x34, 0x02, 0x05, 0x19, 0x03, 0x0a, 0x47, 0x00, 0x52, -0x61, 0x73, 0x6b, 0x00, 0x66, 0x42, 0x03, 0x25, 0x72, 0x79, -0xfb, 0x01, 0x16, 0x6e, 0x28, 0x02, 0x20, 0x74, 0x6f, 0x71, -0x03, 0x30, 0x64, 0x69, 0x73, 0x70, 0x03, 0x40, 0x75, 0x69, -0x73, 0x68, 0x42, 0x01, 0x20, 0x00, 0x28, 0x20, 0x00, 0x03, -0x08, 0x02, 0x11, 0x29, 0x09, 0x02, 0x1b, 0x79, 0x51, 0x00, -0x12, 0x61, 0x56, 0x03, 0x57, 0x69, 0x66, 0x69, 0x65, 0x64, -0x9c, 0x05, 0x02, 0x27, 0x04, 0x02, 0x56, 0x05, 0x05, 0x7d, -0x04, 0x10, 0x73, 0xbb, 0x00, 0x30, 0x69, 0x64, 0x65, 0xff, -0x01, 0x24, 0x61, 0x6c, 0x02, 0x07, 0x05, 0x80, 0x04, 0x0e, -0x49, 0x00, 0x08, 0x3f, 0x07, 0x48, 0x6a, 0x75, 0x73, 0x74, -0x44, 0x07, 0x13, 0x61, 0x19, 0x02, 0x13, 0x31, 0x43, 0x07, -0x00, 0x0c, 0x00, 0x02, 0x33, 0x06, 0x45, 0x72, 0x6f, 0x77, -0x2c, 0x1f, 0x00, 0x17, 0x32, 0x1f, 0x00, 0x63, 0x73, 0x65, -0x63, 0x6f, 0x6e, 0x64, 0x20, 0x00, 0x8f, 0x6e, 0x64, 0x00, -0x73, 0x6f, 0x00, 0x6f, 0x6e, 0x6f, 0x01, 0x05, 0x30, 0x77, -0x68, 0x65, 0xbf, 0x00, 0x01, 0x39, 0x00, 0x17, 0x6f, 0x2a, -0x07, 0x24, 0x6f, 0x66, 0xc9, 0x04, 0x32, 0x61, 0x74, 0x74, -0xbf, 0x00, 0x12, 0x66, 0x2c, 0x08, 0x04, 0x12, 0x01, 0x14, -0x6e, 0x30, 0x00, 0x24, 0x62, 0x6c, 0xd9, 0x01, 0x03, 0x28, -0x08, 0x01, 0x66, 0x04, 0x01, 0x1d, 0x03, 0x01, 0x37, 0x05, -0xf0, 0x01, 0x61, 0x00, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, -0x6c, 0x65, 0x00, 0x64, 0x72, 0x61, 0x77, 0x6e, 0x39, 0x01, -0x44, 0x69, 0x74, 0x2e, 0x00, 0xf4, 0x02, 0x04, 0x1e, 0x00, -0x51, 0x73, 0x00, 0x6d, 0x75, 0x73, 0x11, 0x05, 0x01, 0x54, -0x05, 0x00, 0x7e, 0x03, 0x71, 0x75, 0x70, 0x77, 0x61, 0x72, -0x64, 0x73, 0x7a, 0x05, 0x77, 0x6f, 0x6d, 0x70, 0x6c, 0x65, -0x74, 0x65, 0x48, 0x02, 0x0e, 0xfc, 0x01, 0x02, 0xab, 0x01, -0x50, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x98, 0x07, 0x51, 0x68, -0x75, 0x66, 0x66, 0x6c, 0x6f, 0x08, 0x23, 0x70, 0x65, 0xe8, -0x02, 0x02, 0x01, 0x02, 0x94, 0x70, 0x65, 0x72, 0x66, 0x6f, -0x72, 0x6d, 0x65, 0x64, 0xd8, 0x02, 0x02, 0x92, 0x02, 0x17, -0x42, 0x0e, 0x04, 0x04, 0x38, 0x03, 0x01, 0xc8, 0x00, 0x02, -0x4a, 0x00, 0x16, 0x65, 0x48, 0x02, 0x00, 0x9a, 0x04, 0x11, -0x75, 0xfb, 0x01, 0x00, 0x8a, 0x02, 0x38, 0x6e, 0x79, 0x00, -0x88, 0x09, 0x14, 0x69, 0x91, 0x08, 0x20, 0x61, 0x73, 0x77, -0x03, 0x11, 0x62, 0x22, 0x01, 0x21, 0x61, 0x73, 0x28, 0x00, -0x10, 0x6f, 0x6e, 0x01, 0x15, 0x2e, 0xb5, 0x00, 0x82, 0x6f, -0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x3c, 0x07, 0x81, -0x62, 0x79, 0x00, 0x72, 0x65, 0x71, 0x75, 0x65, 0x9e, 0x02, -0x00, 0xa4, 0x07, 0x54, 0x72, 0x65, 0x63, 0x69, 0x73, 0x45, -0x09, 0x01, 0x12, 0x03, 0x05, 0xd3, 0x00, 0x00, 0x19, 0x05, -0x1c, 0x73, 0xcf, 0x00, 0x71, 0x2e, 0x00, 0x54, 0x79, 0x70, -0x69, 0x63, 0xfd, 0x09, 0x09, 0x95, 0x09, 0x21, 0x68, 0x65, -0xfb, 0x00, 0x10, 0x64, 0x17, 0x04, 0x33, 0x6d, 0x69, 0x6e, -0x46, 0x01, 0x03, 0x5f, 0x00, 0x3e, 0x73, 0x65, 0x74, 0x5c, -0x00, 0x00, 0xaf, 0x00, 0x00, 0x7e, 0x04, 0x31, 0x76, 0x65, -0x72, 0x5a, 0x09, 0xa0, 0x6d, 0x00, 0x65, 0x78, 0x61, 0x63, -0x74, 0x6c, 0x79, 0x2c, 0xfd, 0x00, 0x01, 0xf8, 0x00, 0x01, -0x0f, 0x02, 0xd1, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x00, 0x28, -0x73, 0x61, 0x79, 0x29, 0x00, 0x61, 0x02, 0x07, 0x11, 0x2d, -0xb4, 0x05, 0x04, 0x33, 0x01, 0x01, 0x9a, 0x05, 0x09, 0x19, -0x00, 0x50, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x92, 0x02, 0x21, -0x4e, 0x6f, 0xcf, 0x01, 0x11, 0x61, 0x60, 0x00, 0x02, 0xf1, -0x06, 0x02, 0x7a, 0x00, 0x07, 0x68, 0x02, 0x16, 0x2c, 0x1c, -0x00, 0x81, 0x6c, 0x69, 0x6b, 0x65, 0x6c, 0x79, 0x00, 0x69, -0x61, 0x01, 0x01, 0x37, 0x00, 0x04, 0x4b, 0x00, 0x71, 0x73, -0x00, 0x73, 0x68, 0x6f, 0x72, 0x74, 0xc7, 0x02, 0x22, 0x61, -0x6e, 0x55, 0x02, 0x00, 0xca, 0x05, 0x82, 0x74, 0x00, 0x6c, -0x65, 0x6e, 0x67, 0x74, 0x68, 0xc5, 0x01, 0x01, 0xc5, 0x05, -0x01, 0x28, 0x0a, 0x12, 0x6f, 0x65, 0x02, 0x80, 0x73, 0x73, -0x69, 0x62, 0x6c, 0x65, 0x2e, 0x00, +0x20, 0x00, 0x2d, 0x01, 0x00, 0x33, 0x00, 0x00, 0x00, 0x1e, +0x00, 0xf2, 0x34, 0x00, 0x69, 0x73, 0x00, 0x61, 0x00, 0x74, +0x69, 0x6c, 0x65, 0x2d, 0x72, 0x65, 0x61, 0x72, 0x72, 0x61, +0x6e, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x70, 0x75, +0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x00, 0x76, 0x69, 0x73, 0x75, +0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, +0x61, 0x72, 0x00, 0x74, 0x6f, 0x00, 0x53, 0x69, 0x78, 0x74, +0x65, 0x65, 0x6e, 0x00, 0x28, 0x73, 0x65, 0x65, 0x00, 0x63, +0x72, 0x00, 0xf0, 0x11, 0x00, 0x36, 0x29, 0x3a, 0x00, 0x79, +0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, +0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, +0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x17, 0x00, 0x00, 0x67, +0x00, 0xf0, 0x11, 0x73, 0x2c, 0x00, 0x65, 0x61, 0x63, 0x68, +0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, +0x67, 0x00, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, +0x2c, 0x00, 0x61, 0x6e, 0x64, 0x44, 0x00, 0x50, 0x72, 0x00, +0x61, 0x69, 0x6d, 0x9a, 0x00, 0x33, 0x74, 0x6f, 0x00, 0x94, +0x00, 0x43, 0x00, 0x74, 0x68, 0x65, 0x27, 0x00, 0x40, 0x73, +0x00, 0x69, 0x6e, 0x19, 0x00, 0x50, 0x73, 0x63, 0x65, 0x6e, +0x64, 0x40, 0x00, 0xf4, 0x02, 0x6f, 0x72, 0x64, 0x65, 0x72, +0x2e, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x00, 0x62, 0x61, 0x73, +0x69, 0x63, 0xdd, 0x00, 0x12, 0x2c, 0x4d, 0x00, 0x43, 0x6d, +0x6f, 0x76, 0x65, 0x4e, 0x00, 0x84, 0x72, 0x6f, 0x74, 0x61, +0x74, 0x65, 0x00, 0x61, 0x92, 0x00, 0x50, 0x67, 0x72, 0x6f, +0x75, 0x70, 0xa2, 0x00, 0x10, 0x66, 0x29, 0x00, 0x01, 0xa0, +0x00, 0x60, 0x00, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x70, 0x00, +0xf0, 0x0f, 0x69, 0x72, 0x00, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, +0x6e, 0x00, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x2e, 0x00, +0x28, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x52, 0x00, 0xf1, 0x03, 0x6e, 0x6f, 0x74, 0x00, +0x73, 0x69, 0x67, 0x6e, 0x69, 0x66, 0x69, 0x63, 0x61, 0x6e, +0x74, 0x00, 0x69, 0x6e, 0xa8, 0x00, 0x02, 0x85, 0x00, 0x04, +0x42, 0x01, 0x81, 0x61, 0x6c, 0x74, 0x68, 0x6f, 0x75, 0x67, +0x68, 0x1e, 0x01, 0xf5, 0x1b, 0x63, 0x61, 0x6e, 0x00, 0x73, +0x65, 0x6c, 0x65, 0x63, 0x74, 0x00, 0x69, 0x74, 0x2e, 0x29, +0x00, 0x4f, 0x6e, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x61, +0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x00, 0x73, 0x65, +0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x2f, 0x00, 0x05, +0xb4, 0x00, 0x6d, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0xbb, +0x00, 0x01, 0xb6, 0x00, 0x01, 0xff, 0x00, 0xd0, 0x00, 0x66, +0x69, 0x72, 0x73, 0x74, 0x00, 0x73, 0x61, 0x77, 0x00, 0x74, +0x68, 0xf1, 0x00, 0x30, 0x79, 0x70, 0x65, 0x22, 0x00, 0x02, +0x8a, 0x00, 0x04, 0x9e, 0x00, 0xf2, 0x13, 0x47, 0x61, 0x6d, +0x65, 0x43, 0x75, 0x62, 0x65, 0x00, 0x67, 0x61, 0x6d, 0x65, +0x00, 0x60, 0x4d, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x64, 0x00, +0x50, 0x72, 0x69, 0x6d, 0x65, 0x00, 0x32, 0x27, 0x2e, 0x00, +0x49, 0x28, 0x00, 0xd0, 0x4d, 0x61, 0x69, 0x6e, 0x00, 0x47, +0x79, 0x72, 0x6f, 0x00, 0x43, 0x68, 0x61, 0x79, 0x01, 0x02, +0x41, 0x00, 0x21, 0x61, 0x74, 0x39, 0x00, 0x10, 0x2c, 0x24, +0x00, 0x13, 0x72, 0x40, 0x02, 0x03, 0x61, 0x00, 0x00, 0xb2, +0x00, 0x50, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x6b, 0x01, 0xf2, +0x05, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x00, 0x61, 0x00, +0x64, 0x6f, 0x6f, 0x72, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, +0x68, 0x2e, 0x00, 0xb1, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61, +0x6c, 0x00, 0x63, 0x61, 0x73, 0x9f, 0x00, 0x03, 0xae, 0x01, +0xd2, 0x2e, 0x00, 0x49, 0x00, 0x64, 0x65, 0x76, 0x65, 0x6c, +0x6f, 0x70, 0x65, 0x64, 0xc1, 0x00, 0x01, 0xa2, 0x00, 0x20, +0x61, 0x73, 0x4a, 0x02, 0x82, 0x65, 0x6e, 0x65, 0x72, 0x61, +0x6c, 0x69, 0x73, 0x7c, 0x01, 0x22, 0x6f, 0x66, 0x8a, 0x00, +0x02, 0x79, 0x00, 0x00, 0xfd, 0x00, 0x35, 0x37, 0x2e, 0x31, +0xf2, 0x02, 0x00, 0x5c, 0x02, 0x50, 0x72, 0x6f, 0x6c, 0x73, +0x20, 0xe8, 0x02, 0x66, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, +0x13, 0x02, 0x51, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xe1, 0x00, +0x45, 0x6d, 0x6f, 0x75, 0x73, 0x16, 0x01, 0x02, 0xe3, 0x01, +0x02, 0x59, 0x00, 0x1a, 0x65, 0x64, 0x01, 0x00, 0xd7, 0x00, +0x46, 0x77, 0x69, 0x73, 0x68, 0x41, 0x02, 0x05, 0x24, 0x01, +0x02, 0xea, 0x01, 0x32, 0x6d, 0x6f, 0x64, 0x6c, 0x02, 0x06, +0xac, 0x01, 0x33, 0x32, 0x78, 0x32, 0x45, 0x00, 0x04, 0xfb, +0x00, 0x51, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x25, 0x00, 0x22, +0x68, 0x61, 0x22, 0x01, 0x02, 0x8a, 0x00, 0xf1, 0x04, 0x61, +0x74, 0x00, 0x61, 0x00, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, +0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x77, 0x59, 0x01, +0x07, 0x92, 0x02, 0x43, 0x6d, 0x65, 0x65, 0x74, 0xe0, 0x02, +0x0a, 0x2d, 0x02, 0x00, 0x79, 0x00, 0x02, 0x54, 0x00, 0x82, +0x6d, 0x69, 0x67, 0x68, 0x74, 0x00, 0x62, 0x65, 0x82, 0x00, +0x00, 0x16, 0x03, 0xa4, 0x33, 0x78, 0x33, 0x00, 0x6f, 0x72, +0x00, 0x65, 0x76, 0x65, 0x36, 0x00, 0x11, 0x74, 0xea, 0x03, +0x53, 0x6d, 0x65, 0x3b, 0x00, 0x69, 0xe6, 0x00, 0x2c, 0x69, +0x7a, 0xf2, 0x00, 0x60, 0x69, 0x73, 0x00, 0x6f, 0x64, 0x64, +0x12, 0x00, 0x12, 0x6e, 0xcf, 0x01, 0x53, 0x69, 0x6d, 0x70, +0x6c, 0x79, 0xab, 0x00, 0x0a, 0x2b, 0x01, 0x00, 0x9c, 0x00, +0x0b, 0x3e, 0x00, 0x01, 0x2a, 0x01, 0x00, 0x09, 0x03, 0x07, +0x2a, 0x01, 0x30, 0x00, 0x00, 0x43, 0x3d, 0x00, 0x00, 0x93, +0x00, 0x41, 0x77, 0x69, 0x74, 0x68, 0x2f, 0x00, 0x43, 0x6c, +0x65, 0x66, 0x74, 0x7f, 0x01, 0x54, 0x62, 0x75, 0x74, 0x74, +0x6f, 0xe5, 0x02, 0x11, 0x73, 0x1e, 0x00, 0x02, 0x76, 0x01, +0x50, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x43, 0x02, 0x5f, 0x77, +0x69, 0x73, 0x65, 0x2e, 0x45, 0x00, 0x00, 0x12, 0x72, 0xf3, +0x00, 0x0a, 0x40, 0x00, 0x37, 0x69, 0x74, 0x00, 0x35, 0x00, +0x33, 0x00, 0x00, 0x59, 0x45, 0x03, 0x42, 0x61, 0x6c, 0x73, +0x6f, 0x09, 0x04, 0x95, 0x61, 0x6e, 0x00, 0x6f, 0x75, 0x74, +0x6c, 0x69, 0x6e, 0xb6, 0x00, 0x51, 0x61, 0x72, 0x6f, 0x75, +0x6e, 0xf4, 0x00, 0x02, 0xb1, 0x04, 0x05, 0x62, 0x00, 0xcb, +0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, +0x73, 0x3b, 0x25, 0x01, 0x05, 0x3f, 0x01, 0x20, 0x61, 0x62, +0x55, 0x00, 0x10, 0x28, 0xf0, 0x01, 0xb0, 0x62, 0x79, 0x00, +0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x7a, 0x01, +0x02, 0xaf, 0x03, 0x80, 0x29, 0x2e, 0x00, 0x50, 0x72, 0x65, +0x73, 0x73, 0xbb, 0x00, 0x01, 0xb6, 0x00, 0x50, 0x65, 0x74, +0x75, 0x72, 0x6e, 0x54, 0x00, 0x00, 0x24, 0x00, 0x40, 0x73, +0x70, 0x61, 0x63, 0x46, 0x02, 0x64, 0x72, 0x00, 0x77, 0x69, +0x6c, 0x6c, 0x3f, 0x02, 0x03, 0x7c, 0x00, 0x10, 0x72, 0x88, +0x05, 0x04, 0xa4, 0x00, 0x08, 0x0e, 0x01, 0x00, 0x3a, 0x00, +0x06, 0x0d, 0x00, 0x20, 0x72, 0x65, 0x51, 0x03, 0x60, 0x74, +0x69, 0x76, 0x65, 0x6c, 0x79, 0xf3, 0x00, 0x41, 0x28, 0x41, +0x6c, 0x6c, 0x43, 0x00, 0x20, 0x61, 0x63, 0x2c, 0x03, 0xd0, +0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0x00, 0x69, 0x7d, 0x04, 0x11, 0x63, 0x42, 0x03, 0x31, +0x32, 0x2e, 0x31, 0xab, 0x05, 0x01, 0x19, 0x01, 0xb1, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, +0x4b, 0x03, 0x15, 0x32, 0x4b, 0x03, 0xb7, 0x70, 0x61, 0x72, +0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x35, 0x06, +0x50, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x7b, 0x02, 0x30, 0x73, +0x65, 0x76, 0x97, 0x03, 0x00, 0xce, 0x05, 0x53, 0x66, 0x69, +0x67, 0x75, 0x72, 0x9e, 0x03, 0x12, 0x70, 0x79, 0x00, 0x31, +0x76, 0x69, 0x61, 0x89, 0x00, 0x83, 0x60, 0x43, 0x75, 0x73, +0x74, 0x6f, 0x6d, 0x27, 0x19, 0x00, 0x32, 0x00, 0x6f, 0x6e, +0x17, 0x00, 0xf5, 0x00, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, +0x6d, 0x65, 0x6e, 0x75, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0xad, +0x01, 0x04, 0x4e, 0x00, 0x02, 0x0a, 0x01, 0x51, 0x77, 0x69, +0x64, 0x74, 0x68, 0x1b, 0x06, 0x21, 0x68, 0x65, 0xf3, 0x01, +0x03, 0x74, 0x02, 0x03, 0x75, 0x04, 0x00, 0xb3, 0x01, 0x1f, +0x2e, 0x3f, 0x00, 0x08, 0x04, 0xe5, 0x02, 0x03, 0x49, 0x01, +0x11, 0x62, 0x96, 0x04, 0x01, 0x3d, 0x04, 0x04, 0x34, 0x02, +0x05, 0x19, 0x03, 0x0a, 0x47, 0x00, 0x52, 0x61, 0x73, 0x6b, +0x00, 0x66, 0x42, 0x03, 0x25, 0x72, 0x79, 0xfb, 0x01, 0x16, +0x6e, 0x28, 0x02, 0x20, 0x74, 0x6f, 0x71, 0x03, 0x30, 0x64, +0x69, 0x73, 0x70, 0x03, 0x40, 0x75, 0x69, 0x73, 0x68, 0x42, +0x01, 0x20, 0x00, 0x28, 0x20, 0x00, 0x03, 0x08, 0x02, 0x11, +0x29, 0x09, 0x02, 0x1b, 0x79, 0x51, 0x00, 0x12, 0x61, 0x56, +0x03, 0x57, 0x69, 0x66, 0x69, 0x65, 0x64, 0x9c, 0x05, 0x02, +0x27, 0x04, 0x02, 0x56, 0x05, 0x05, 0x7d, 0x04, 0x10, 0x73, +0xbb, 0x00, 0x30, 0x69, 0x64, 0x65, 0xff, 0x01, 0x24, 0x61, +0x6c, 0x02, 0x07, 0x05, 0x80, 0x04, 0x0e, 0x49, 0x00, 0x08, +0x3f, 0x07, 0x48, 0x6a, 0x75, 0x73, 0x74, 0x44, 0x07, 0x13, +0x61, 0x19, 0x02, 0x13, 0x31, 0x43, 0x07, 0x00, 0x0c, 0x00, +0x02, 0x33, 0x06, 0x45, 0x72, 0x6f, 0x77, 0x2c, 0x1f, 0x00, +0x17, 0x32, 0x1f, 0x00, 0x63, 0x73, 0x65, 0x63, 0x6f, 0x6e, +0x64, 0x20, 0x00, 0x8f, 0x6e, 0x64, 0x00, 0x73, 0x6f, 0x00, +0x6f, 0x6e, 0x6f, 0x01, 0x05, 0x30, 0x77, 0x68, 0x65, 0xbf, +0x00, 0x01, 0x39, 0x00, 0x17, 0x6f, 0x2a, 0x07, 0x24, 0x6f, +0x66, 0xc9, 0x04, 0x32, 0x61, 0x74, 0x74, 0xbf, 0x00, 0x12, +0x66, 0x2c, 0x08, 0x04, 0x12, 0x01, 0x14, 0x6e, 0x30, 0x00, +0x24, 0x62, 0x6c, 0xd9, 0x01, 0x03, 0x28, 0x08, 0x01, 0x66, +0x04, 0x01, 0x1d, 0x03, 0x01, 0x37, 0x05, 0xf0, 0x01, 0x61, +0x00, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x00, +0x64, 0x72, 0x61, 0x77, 0x6e, 0x39, 0x01, 0x44, 0x69, 0x74, +0x2e, 0x00, 0xf4, 0x02, 0x04, 0x1e, 0x00, 0x51, 0x73, 0x00, +0x6d, 0x75, 0x73, 0x11, 0x05, 0x01, 0x54, 0x05, 0x00, 0x7e, +0x03, 0x71, 0x75, 0x70, 0x77, 0x61, 0x72, 0x64, 0x73, 0x7a, +0x05, 0x77, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, +0x02, 0x0e, 0xfc, 0x01, 0x02, 0xab, 0x01, 0x50, 0x6c, 0x69, +0x6d, 0x69, 0x74, 0x98, 0x07, 0x51, 0x68, 0x75, 0x66, 0x66, +0x6c, 0x6f, 0x08, 0x23, 0x70, 0x65, 0xe8, 0x02, 0x02, 0x01, +0x02, 0x94, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, +0x64, 0xd8, 0x02, 0x02, 0x92, 0x02, 0x17, 0x42, 0x0e, 0x04, +0x04, 0x38, 0x03, 0x01, 0xc8, 0x00, 0x02, 0x4a, 0x00, 0x16, +0x65, 0x48, 0x02, 0x00, 0x9a, 0x04, 0x11, 0x75, 0xfb, 0x01, +0x00, 0x8a, 0x02, 0x38, 0x6e, 0x79, 0x00, 0x88, 0x09, 0x14, +0x69, 0x91, 0x08, 0x20, 0x61, 0x73, 0x77, 0x03, 0x11, 0x62, +0x22, 0x01, 0x21, 0x61, 0x73, 0x28, 0x00, 0x10, 0x6f, 0x6e, +0x01, 0x15, 0x2e, 0xb5, 0x00, 0x82, 0x6f, 0x76, 0x65, 0x72, +0x72, 0x69, 0x64, 0x65, 0x3c, 0x07, 0x81, 0x62, 0x79, 0x00, +0x72, 0x65, 0x71, 0x75, 0x65, 0x9e, 0x02, 0x00, 0xa4, 0x07, +0x54, 0x72, 0x65, 0x63, 0x69, 0x73, 0x45, 0x09, 0x01, 0x12, +0x03, 0x05, 0xd3, 0x00, 0x00, 0x19, 0x05, 0x1c, 0x73, 0xcf, +0x00, 0x71, 0x2e, 0x00, 0x54, 0x79, 0x70, 0x69, 0x63, 0xfd, +0x09, 0x09, 0x95, 0x09, 0x21, 0x68, 0x65, 0xfb, 0x00, 0x10, +0x64, 0x17, 0x04, 0x33, 0x6d, 0x69, 0x6e, 0x46, 0x01, 0x03, +0x5f, 0x00, 0x3e, 0x73, 0x65, 0x74, 0x5c, 0x00, 0x00, 0xaf, +0x00, 0x00, 0x7e, 0x04, 0x31, 0x76, 0x65, 0x72, 0x5a, 0x09, +0xa0, 0x6d, 0x00, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, +0x2c, 0xfd, 0x00, 0x01, 0xf8, 0x00, 0x01, 0x0f, 0x02, 0xd1, +0x6e, 0x73, 0x77, 0x65, 0x72, 0x00, 0x28, 0x73, 0x61, 0x79, +0x29, 0x00, 0x61, 0x02, 0x07, 0x11, 0x2d, 0xb4, 0x05, 0x04, +0x33, 0x01, 0x01, 0x9a, 0x05, 0x09, 0x19, 0x00, 0x50, 0x6f, +0x6c, 0x75, 0x74, 0x69, 0x92, 0x02, 0x21, 0x4e, 0x6f, 0xcf, +0x01, 0x11, 0x61, 0x60, 0x00, 0x02, 0xf1, 0x06, 0x02, 0x7a, +0x00, 0x07, 0x68, 0x02, 0x16, 0x2c, 0x1c, 0x00, 0x81, 0x6c, +0x69, 0x6b, 0x65, 0x6c, 0x79, 0x00, 0x69, 0x61, 0x01, 0x01, +0x37, 0x00, 0x04, 0x4b, 0x00, 0x71, 0x73, 0x00, 0x73, 0x68, +0x6f, 0x72, 0x74, 0xc7, 0x02, 0x22, 0x61, 0x6e, 0x55, 0x02, +0x00, 0xca, 0x05, 0x82, 0x74, 0x00, 0x6c, 0x65, 0x6e, 0x67, +0x74, 0x68, 0xc5, 0x01, 0x01, 0xc5, 0x05, 0x01, 0x28, 0x0a, +0x12, 0x6f, 0x65, 0x02, 0x80, 0x73, 0x73, 0x69, 0x62, 0x6c, +0x65, 0x2e, 0x00, }; -const unsigned short help_text_len = 2926; -const unsigned short help_text_words = 548; +const unsigned short help_text_len = 2945; +const unsigned short help_text_words = 549; const char quick_help_text[] = "Rotate the tiles around themselves to arrange them into order."; diff --git a/apps/plugins/puzzles/help/undead.c b/apps/plugins/puzzles/help/undead.c index c08801003a..2ad886cd0d 100644 --- a/apps/plugins/puzzles/help/undead.c +++ b/apps/plugins/puzzles/help/undead.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,230 +6,246 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 202, TEXT_CENTER | C_RED }, - { 282, TEXT_UNDERLINE }, - { 576, TEXT_CENTER | C_RED }, - { 593, TEXT_UNDERLINE }, - { 594, TEXT_UNDERLINE }, - { 604, TEXT_UNDERLINE }, + { 203, TEXT_CENTER | C_RED }, + { 291, TEXT_UNDERLINE }, + { 591, TEXT_CENTER | C_RED }, + { 608, TEXT_UNDERLINE }, + { 609, TEXT_UNDERLINE }, + { 619, TEXT_UNDERLINE }, + { 631, TEXT_CENTER | C_RED }, LAST_STYLE_ITEM }; -/* orig 3286 comp 2109 ratio 0.641814 level 10 saved 1177 */ +/* orig 3574 comp 2258 ratio 0.631785 level 10 saved 1316 */ const char help_text[] = { -0xf0, 0x2c, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x37, 0x3a, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x61, 0x64, -0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, -0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, -0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, -0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, -0x65, 0x11, 0x00, 0xf3, 0x16, 0x77, 0x68, 0x69, 0x63, 0x68, -0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x64, -0x69, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x6d, 0x69, -0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x00, 0x45, 0x76, 0x65, -0x72, 0x79, 0x37, 0x00, 0x03, 0x2d, 0x00, 0x83, 0x69, 0x73, -0x00, 0x6e, 0x6f, 0x74, 0x00, 0x61, 0x25, 0x00, 0xf1, 0x08, -0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x62, 0x65, 0x00, 0x66, -0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68, -0x00, 0x6f, 0x6e, 0x5e, 0x00, 0xb0, 0x74, 0x68, 0x72, 0x65, -0x65, 0x00, 0x74, 0x79, 0x70, 0x65, 0x73, 0x0f, 0x00, 0x11, -0x75, 0xa0, 0x00, 0x90, 0x00, 0x6d, 0x6f, 0x6e, 0x73, 0x74, -0x65, 0x72, 0x3a, 0x98, 0x00, 0xf2, 0x12, 0x68, 0x6f, 0x73, -0x74, 0x2c, 0x00, 0x61, 0x00, 0x76, 0x61, 0x6d, 0x70, 0x69, -0x72, 0x65, 0x2c, 0x00, 0x6f, 0x72, 0x00, 0x61, 0x00, 0x7a, -0x6f, 0x6d, 0x62, 0x69, 0x65, 0x2e, 0x00, 0x00, 0x00, 0x56, -0x18, 0x00, 0x50, 0x73, 0x00, 0x63, 0x61, 0x6e, 0x65, 0x00, -0x30, 0x73, 0x65, 0x65, 0xa7, 0x00, 0xb1, 0x72, 0x65, 0x63, -0x74, 0x6c, 0x79, 0x2c, 0x00, 0x62, 0x75, 0x74, 0xe8, 0x00, -0x80, 0x69, 0x6e, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0xa4, -0x00, 0xf6, 0x00, 0x65, 0x6e, 0x00, 0x72, 0x65, 0x66, 0x6c, -0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x69, 0x6e, 0xcc, 0x00, -0x10, 0x47, 0x6d, 0x00, 0x11, 0x73, 0x30, 0x00, 0xf0, 0x08, -0x74, 0x68, 0x65, 0x00, 0x6f, 0x70, 0x70, 0x6f, 0x73, 0x69, -0x74, 0x65, 0x00, 0x77, 0x61, 0x79, 0x00, 0x72, 0x6f, 0x75, -0x6e, 0x64, 0x3a, 0x18, 0x00, 0x19, 0x79, 0x6b, 0x00, 0x06, -0x40, 0x00, 0x0f, 0x6d, 0x00, 0x06, 0x95, 0x6c, 0x6f, 0x6f, -0x6b, 0x65, 0x64, 0x00, 0x61, 0x74, 0x98, 0x00, 0x31, 0x2e, -0x00, 0x5a, 0xc1, 0x00, 0x02, 0x6c, 0x00, 0x04, 0x2d, 0x00, -0xd7, 0x62, 0x79, 0x00, 0x61, 0x6e, 0x79, 0x00, 0x6d, 0x65, -0x61, 0x6e, 0x73, 0x2e, 0xa4, 0x01, 0x91, 0x61, 0x6c, 0x73, -0x6f, 0x00, 0x74, 0x6f, 0x6c, 0x64, 0x96, 0x00, 0xc0, 0x74, -0x6f, 0x74, 0x61, 0x6c, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, -0x72, 0x34, 0x01, 0x41, 0x65, 0x61, 0x63, 0x68, 0x42, 0x01, -0x00, 0x0d, 0x00, 0x03, 0x3a, 0x01, 0x00, 0x96, 0x00, 0x00, -0x2c, 0x00, 0x00, 0xd6, 0x01, 0x30, 0x2e, 0x00, 0x41, 0x40, -0x00, 0x11, 0x61, 0xc1, 0x00, 0x01, 0x16, 0x00, 0x33, 0x65, -0x64, 0x67, 0x7d, 0x01, 0x12, 0x65, 0xf8, 0x01, 0x01, 0xbb, -0x01, 0x63, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x59, 0x00, -0x24, 0x73, 0x2c, 0xcc, 0x01, 0xd1, 0x6e, 0x64, 0x69, 0x63, -0x61, 0x74, 0x65, 0x00, 0x68, 0x6f, 0x77, 0x00, 0x6d, 0x9f, -0x00, 0x02, 0x63, 0x00, 0x1a, 0x73, 0x06, 0x01, 0x51, 0x66, -0x00, 0x79, 0x6f, 0x75, 0xea, 0x00, 0x57, 0x00, 0x69, 0x6e, -0x74, 0x6f, 0x5c, 0x00, 0xa0, 0x6c, 0x6f, 0x6e, 0x67, 0x00, -0x61, 0x00, 0x72, 0x6f, 0x77, 0xbb, 0x01, 0xf1, 0x0b, 0x63, -0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x00, 0x73, 0x74, 0x61, 0x72, -0x74, 0x69, 0x6e, 0x67, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, -0x74, 0x68, 0x61, 0x74, 0x00, 0x6c, 0x01, 0x9d, 0x69, 0x6f, -0x6e, 0x2e, 0x00, 0x28, 0x54, 0x68, 0x65, 0x6a, 0x02, 0x01, -0xa5, 0x00, 0x03, 0xb7, 0x01, 0xf1, 0x05, 0x69, 0x76, 0x65, -0x00, 0x6f, 0x6e, 0x00, 0x62, 0x6f, 0x74, 0x68, 0x00, 0x73, -0x69, 0x64, 0x65, 0x73, 0x2e, 0x00, 0x49, 0x81, 0x00, 0x17, -0x72, 0xd9, 0x01, 0x22, 0x6c, 0x69, 0x63, 0x02, 0xd1, 0x73, -0x69, 0x67, 0x68, 0x74, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, -0x65, 0x73, 0x98, 0x00, 0x45, 0x73, 0x61, 0x6d, 0x65, 0x2a, -0x01, 0x21, 0x6d, 0x6f, 0xee, 0x01, 0x81, 0x61, 0x6e, 0x00, -0x6f, 0x6e, 0x63, 0x65, 0x2c, 0x21, 0x00, 0x03, 0x5d, 0x01, -0xd3, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x63, 0x6f, 0x75, 0x6e, -0x74, 0x00, 0x69, 0x74, 0x68, 0x01, 0x30, 0x69, 0x6d, 0x65, -0x0d, 0x00, 0x24, 0x69, 0x73, 0xb6, 0x01, 0x11, 0x2c, 0xec, -0x02, 0x10, 0x6a, 0xe3, 0x02, 0x00, 0x41, 0x00, 0xf2, 0x01, -0x2e, 0x29, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, -0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x9a, 0x01, 0x30, 0x77, -0x61, 0x73, 0x15, 0x02, 0x20, 0x65, 0x6e, 0x99, 0x00, 0xf1, -0x01, 0x62, 0x79, 0x00, 0x44, 0x61, 0x76, 0x69, 0x64, 0x00, -0x4d, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x2c, 0xf6, 0x02, 0x12, -0x72, 0x79, 0x00, 0x00, 0x9a, 0x00, 0x41, 0x60, 0x48, 0x61, -0x75, 0x29, 0x00, 0x12, 0x4d, 0x3f, 0x03, 0xf3, 0x03, 0x4d, -0x61, 0x7a, 0x65, 0x27, 0x2e, 0x00, 0x53, 0x65, 0x65, 0x00, -0x5b, 0x32, 0x30, 0x5d, 0x00, 0x66, 0x6f, 0xb6, 0x00, 0x61, -0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x2b, 0x02, 0x02, 0xd9, -0x03, 0x01, 0x68, 0x00, 0x00, 0xab, 0x03, 0x40, 0x72, 0x69, -0x62, 0x75, 0x42, 0x00, 0x01, 0x89, 0x01, 0x20, 0x69, 0x73, -0x76, 0x01, 0x01, 0x38, 0x01, 0x20, 0x6f, 0x6e, 0x7e, 0x00, -0xd0, 0x53, 0x74, 0x65, 0x66, 0x66, 0x65, 0x6e, 0x00, 0x42, -0x61, 0x75, 0x65, 0x72, 0x3e, 0x00, 0x01, 0x57, 0x00, 0xf4, -0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, -0x77, 0x2e, 0x6a, 0x61, 0x6e, 0x6b, 0x6f, 0x2e, 0x61, 0x74, -0x2f, 0x52, 0x61, 0x65, 0x74, 0x73, 0x65, 0x6c, 0x2f, 0x53, -0x70, 0x75, 0x6b, 0x73, 0x63, 0x68, 0x6c, 0x6f, 0x73, 0x73, -0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, -0x00, 0x00, 0x00, 0x33, 0x37, 0x2e, 0x31, 0x55, 0x04, 0x01, -0x78, 0x00, 0x46, 0x6f, 0x6c, 0x73, 0x20, 0x8f, 0x00, 0xe3, -0x68, 0x61, 0x73, 0x00, 0x61, 0x00, 0x73, 0x69, 0x6d, 0x69, -0x6c, 0x61, 0x72, 0x00, 0x21, 0x00, 0x70, 0x00, 0x73, 0x79, -0x73, 0x74, 0x65, 0x6d, 0x9c, 0x00, 0xf0, 0x08, 0x53, 0x6f, -0x6c, 0x6f, 0x2c, 0x00, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x61, -0x6c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x4b, 0x65, 0x65, 0x6e, -0x2e, 0x42, 0x01, 0x63, 0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, -0x49, 0x00, 0x71, 0x2c, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, -0x23, 0x01, 0x40, 0x6d, 0x6f, 0x75, 0x73, 0x62, 0x03, 0x01, -0x2b, 0x03, 0x45, 0x65, 0x6d, 0x70, 0x74, 0x7d, 0x04, 0x12, -0x61, 0xdf, 0x02, 0x12, 0x6e, 0x73, 0x01, 0x60, 0x61, 0x00, -0x6c, 0x65, 0x74, 0x74, 0x23, 0x03, 0x02, 0x0b, 0x03, 0x84, -0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0xd2, 0x02, -0x00, 0x7d, 0x02, 0x01, 0x4f, 0x03, 0x0a, 0x3a, 0x03, 0x51, -0x3a, 0x00, 0x60, 0x47, 0x27, 0x63, 0x01, 0x05, 0x7c, 0x04, -0x24, 0x60, 0x56, 0x11, 0x00, 0x08, 0x84, 0x04, 0x24, 0x60, -0x5a, 0x16, 0x00, 0x04, 0x8c, 0x04, 0x12, 0x49, 0x04, 0x03, -0x41, 0x6d, 0x61, 0x6b, 0x65, 0xfc, 0x04, 0x5e, 0x73, 0x74, -0x61, 0x6b, 0x65, 0xbb, 0x00, 0x03, 0x9b, 0x03, 0x50, 0x69, -0x6e, 0x63, 0x6f, 0x72, 0x0e, 0x04, 0x08, 0xbf, 0x00, 0xb0, -0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x61, 0x63, -0x65, 0x20, 0x01, 0x50, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x6f, -0x02, 0x20, 0x61, 0x67, 0x7d, 0x05, 0x62, 0x28, 0x6f, 0x72, -0x00, 0x75, 0x73, 0x9c, 0x04, 0xd0, 0x55, 0x6e, 0x64, 0x6f, -0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x29, 0x32, -0x01, 0x03, 0x7e, 0x00, 0x10, 0x72, 0xee, 0x02, 0x12, 0x2d, -0x74, 0x00, 0x00, 0x25, 0x01, 0x0f, 0x1d, 0x01, 0x0b, 0x02, -0xef, 0x02, 0x01, 0x89, 0x00, 0x50, 0x73, 0x70, 0x6f, 0x6e, -0x64, 0x15, 0x01, 0x04, 0x19, 0x03, 0x01, 0xfe, 0x02, 0x00, -0xe0, 0x03, 0x31, 0x68, 0x6f, 0x77, 0xe7, 0x04, 0xb3, 0x72, -0x65, 0x64, 0x75, 0x63, 0x65, 0x64, 0x00, 0x73, 0x69, 0x7a, -0xc6, 0x00, 0x14, 0x61, 0xbd, 0x00, 0x21, 0x2c, 0x00, 0xea, -0x01, 0xe1, 0x60, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x00, -0x6d, 0x61, 0x72, 0x6b, 0x27, 0x2e, 0xc0, 0x04, 0x00, 0x25, -0x04, 0x57, 0x68, 0x61, 0x76, 0x65, 0x00, 0x1b, 0x00, 0x12, -0x73, 0xc3, 0x02, 0x65, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, -0x8a, 0x03, 0x00, 0x22, 0x03, 0x06, 0x9f, 0x03, 0x02, 0x58, -0x00, 0x34, 0x2e, 0x00, 0x41, 0xc1, 0x00, 0x03, 0x82, 0x06, -0x11, 0x69, 0x4d, 0x04, 0x51, 0x66, 0x75, 0x6c, 0x6c, 0x2d, -0x88, 0x00, 0x04, 0xae, 0x00, 0x31, 0x63, 0x61, 0x6e, 0x74, -0x06, 0x00, 0xeb, 0x04, 0x04, 0xad, 0x06, 0x08, 0x73, 0x00, -0x01, 0x55, 0x02, 0x00, 0x94, 0x04, 0x00, 0x5d, 0x00, 0x30, -0x70, 0x61, 0x79, 0xa3, 0x06, 0x20, 0x00, 0x61, 0xf2, 0x04, -0x01, 0x16, 0x03, 0x29, 0x74, 0x6f, 0x2e, 0x00, 0x00, 0xff, -0x06, 0x40, 0x00, 0x65, 0x78, 0x61, 0xac, 0x05, 0x20, 0x00, -0x77, 0xe8, 0x00, 0x00, 0x5c, 0x01, 0x03, 0x7c, 0x01, 0x11, -0x6d, 0xbf, 0x00, 0x50, 0x69, 0x73, 0x00, 0x75, 0x70, 0x38, -0x00, 0x63, 0x79, 0x6f, 0x75, 0x3a, 0x00, 0x79, 0xeb, 0x00, -0x05, 0x23, 0x00, 0x70, 0x61, 0x73, 0x00, 0x72, 0x65, 0x6d, -0x69, 0xda, 0x03, 0x12, 0x73, 0x2a, 0x01, 0x30, 0x61, 0x00, -0x70, 0xf4, 0x04, 0x20, 0x63, 0x75, 0x0c, 0x03, 0x03, 0xd5, -0x00, 0x50, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x45, 0x00, 0x10, -0x62, 0xdc, 0x04, 0x91, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x69, -0x6e, 0x65, 0x64, 0x4a, 0x04, 0x01, 0x54, 0x00, 0x42, 0x6b, -0x6e, 0x6f, 0x77, 0xed, 0x03, 0x4b, 0x61, 0x62, 0x6f, 0x75, -0x45, 0x00, 0x03, 0xfc, 0x00, 0x01, 0x8f, 0x02, 0x0f, 0x81, -0x00, 0x01, 0x20, 0x6c, 0x69, 0xce, 0x06, 0x03, 0xe9, 0x05, -0x32, 0x70, 0x6f, 0x73, 0x66, 0x06, 0x07, 0x23, 0x06, 0x13, -0x61, 0xff, 0x07, 0x04, 0xc5, 0x01, 0x20, 0x6f, 0x72, 0x56, -0x03, 0x20, 0x74, 0x68, 0x65, 0x01, 0x32, 0x65, 0x6c, 0x73, -0x83, 0x00, 0x93, 0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, 0x69, -0x6b, 0x65, 0x98, 0x03, 0x51, 0x65, 0x72, 0x61, 0x73, 0x65, -0xd7, 0x03, 0x39, 0x6e, 0x67, 0x6c, 0xd8, 0x01, 0x1c, 0x2c, -0x7e, 0x02, 0x01, 0xce, 0x01, 0x07, 0x80, 0x02, 0x00, 0x7b, -0x02, 0x05, 0xe2, 0x01, 0x03, 0x9f, 0x03, 0x01, 0xdb, 0x02, -0x00, 0x5b, 0x00, 0x3a, 0x41, 0x6c, 0x6c, 0x25, 0x02, 0x09, -0xbf, 0x02, 0x22, 0x72, 0x65, 0x79, 0x00, 0x12, 0x64, 0x53, -0x07, 0x01, 0x6d, 0x06, 0x24, 0x65, 0x66, 0x6c, 0x00, 0x05, -0x5e, 0x00, 0x15, 0x61, 0xdf, 0x00, 0x04, 0xe1, 0x02, 0x2f, -0x6f, 0x72, 0x32, 0x00, 0x06, 0x07, 0x6e, 0x03, 0x31, 0x2e, -0x00, 0x52, 0xbb, 0x00, 0x02, 0xae, 0x03, 0x01, 0x65, 0x02, -0x04, 0x21, 0x00, 0x00, 0x0d, 0x00, 0x11, 0x73, 0x92, 0x03, -0x01, 0x12, 0x03, 0x01, 0x62, 0x02, 0x02, 0x04, 0x01, 0x0c, -0x60, 0x02, 0x12, 0x41, 0xd9, 0x02, 0x02, 0xd6, 0x04, 0x01, -0x59, 0x03, 0x50, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x7b, 0x04, -0x05, 0x2e, 0x07, 0x22, 0x75, 0x73, 0x74, 0x08, 0x62, 0x63, -0x6f, 0x6e, 0x6a, 0x75, 0x6e, 0x93, 0x05, 0x01, 0x11, 0x09, -0x25, 0x74, 0x68, 0x13, 0x01, 0x01, 0x30, 0x00, 0x11, 0x74, -0x02, 0x05, 0x17, 0x63, 0x1f, 0x03, 0x2b, 0x6f, 0x72, 0x72, -0x00, 0x3d, 0x55, 0x73, 0x65, 0x67, 0x00, 0x60, 0x74, 0x6f, -0x00, 0x6d, 0x6f, 0x76, 0x09, 0x01, 0x51, 0x68, 0x69, 0x67, -0x68, 0x6c, 0xfc, 0x06, 0x07, 0xfb, 0x07, 0x00, 0x93, 0x07, -0x1f, 0x2c, 0x2f, 0x01, 0x07, 0x00, 0x3f, 0x00, 0x00, 0xa5, -0x06, 0x01, 0x75, 0x04, 0x03, 0xc1, 0x01, 0x05, 0x48, 0x00, -0x25, 0x65, 0x64, 0x96, 0x03, 0x14, 0x50, 0x19, 0x01, 0x50, -0x72, 0x65, 0x74, 0x75, 0x72, 0x3f, 0x03, 0x5a, 0x67, 0x67, -0x6c, 0x65, 0x73, 0x30, 0x00, 0x02, 0x09, 0x08, 0x00, 0x63, -0x00, 0x11, 0x64, 0x30, 0x04, 0x02, 0x51, 0x08, 0x04, 0xa9, -0x02, 0x02, 0x67, 0x00, 0x20, 0x6f, 0x72, 0x27, 0x03, 0x1b, -0x6f, 0x20, 0x04, 0x07, 0xd0, 0x04, 0x60, 0x70, 0x72, 0x65, -0x66, 0x65, 0x72, 0x0b, 0x01, 0x23, 0x69, 0x6e, 0xa5, 0x00, -0x05, 0xd3, 0x02, 0x81, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, -0x65, 0x74, 0x2b, 0x05, 0x26, 0x75, 0x74, 0xdb, 0x02, 0x51, -0x70, 0x69, 0x63, 0x74, 0x75, 0xc6, 0x0a, 0x04, 0x6e, 0x00, -0x02, 0xeb, 0x01, 0x31, 0x60, 0x41, 0x27, 0x13, 0x07, 0x01, -0xae, 0x00, 0x50, 0x00, 0x62, 0x65, 0x74, 0x77, 0xbc, 0x08, -0x00, 0xe1, 0x04, 0x04, 0x0e, 0x06, 0x05, 0x6d, 0x01, 0x29, -0x61, 0x73, 0x79, 0x01, 0x07, 0x24, 0x00, 0x02, 0x5b, 0x03, -0x02, 0x8a, 0x00, 0x00, 0xa9, 0x00, 0x15, 0x4c, 0x55, 0x02, -0x02, 0x9c, 0x04, 0x33, 0x63, 0x6c, 0x75, 0x2b, 0x02, 0x00, -0xcc, 0x00, 0x01, 0xbe, 0x05, 0x30, 0x73, 0x00, 0x64, 0xf0, -0x0a, 0x50, 0x28, 0x67, 0x72, 0x65, 0x79, 0x11, 0x00, 0x41, -0x6f, 0x75, 0x74, 0x29, 0x9a, 0x02, 0x24, 0x75, 0x6e, 0x24, -0x00, 0x23, 0x69, 0x66, 0x57, 0x08, 0x71, 0x61, 0x6c, 0x72, -0x65, 0x61, 0x64, 0x79, 0x3d, 0x00, 0x20, 0x65, 0x64, 0x61, -0x00, 0x10, 0x28, 0x1a, 0x03, 0x01, 0xf0, 0x00, 0x01, 0x2f, -0x02, 0x92, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x49, 0x02, 0x13, 0x73, 0xd8, 0x07, 0x36, 0x32, 0x2e, -0x31, 0x2d, 0x0a, 0x82, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, -0x62, 0x6c, 0x8f, 0x08, 0x44, 0x33, 0x37, 0x2e, 0x32, 0xa6, -0x07, 0x60, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0xbc, 0x00, -0x12, 0x20, 0x12, 0x05, 0x00, 0xc8, 0x02, 0x05, 0x14, 0x00, -0x02, 0x42, 0x00, 0x04, 0x3d, 0x00, 0x04, 0x9d, 0x09, 0xf1, -0x01, 0x65, 0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, -0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x70, 0x00, 0x03, -0x57, 0x07, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, -0x6d, 0x65, 0x6e, 0x75, 0xac, 0x00, 0x91, 0x57, 0x69, 0x64, -0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x01, 0x02, 0x51, 0x00, -0x00, 0x53, 0x69, 0x7a, 0x5e, 0x07, 0x01, 0x0b, 0x0a, 0x14, -0x69, 0x6a, 0x04, 0x01, 0x38, 0x01, 0x40, 0x44, 0x69, 0x66, -0x66, 0xc9, 0x04, 0x63, 0x74, 0x79, 0x00, 0x00, 0x00, 0x43, -0x3d, 0x08, 0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x04, -0xa6, 0x0a, 0x50, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x82, 0x02, -0x80, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2e, 0x00, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x19, 0x00, 0x00, 0x00, +0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, +0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, +0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, 0x00, 0xf3, +0x16, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x63, 0x6f, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0x00, 0x64, 0x69, 0x61, 0x67, 0x6f, +0x6e, 0x61, 0x6c, 0x00, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, +0x73, 0x2e, 0x00, 0x45, 0x76, 0x65, 0x72, 0x79, 0x37, 0x00, +0x03, 0x2d, 0x00, 0x83, 0x69, 0x73, 0x00, 0x6e, 0x6f, 0x74, +0x00, 0x61, 0x25, 0x00, 0xf1, 0x08, 0x00, 0x6d, 0x75, 0x73, +0x74, 0x00, 0x62, 0x65, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x65, +0x64, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x6f, 0x6e, 0x5e, +0x00, 0xb0, 0x74, 0x68, 0x72, 0x65, 0x65, 0x00, 0x74, 0x79, +0x70, 0x65, 0x73, 0x0f, 0x00, 0x11, 0x75, 0xb3, 0x00, 0x90, +0x00, 0x6d, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x98, +0x00, 0xf2, 0x12, 0x68, 0x6f, 0x73, 0x74, 0x2c, 0x00, 0x61, +0x00, 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x65, 0x2c, 0x00, +0x6f, 0x72, 0x00, 0x61, 0x00, 0x7a, 0x6f, 0x6d, 0x62, 0x69, +0x65, 0x2e, 0x00, 0x00, 0x00, 0x56, 0x18, 0x00, 0x50, 0x73, +0x00, 0x63, 0x61, 0x6e, 0x65, 0x00, 0x30, 0x73, 0x65, 0x65, +0xa7, 0x00, 0xb1, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2c, +0x00, 0x62, 0x75, 0x74, 0xe8, 0x00, 0x80, 0x69, 0x6e, 0x76, +0x69, 0x73, 0x69, 0x62, 0x6c, 0xa4, 0x00, 0xf6, 0x00, 0x65, +0x6e, 0x00, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x65, +0x64, 0x00, 0x69, 0x6e, 0xcc, 0x00, 0x10, 0x47, 0x6d, 0x00, +0x11, 0x73, 0x30, 0x00, 0xf0, 0x08, 0x74, 0x68, 0x65, 0x00, +0x6f, 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x00, 0x77, +0x61, 0x79, 0x00, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x18, +0x00, 0x19, 0x79, 0x6b, 0x00, 0x06, 0x40, 0x00, 0x0f, 0x6d, +0x00, 0x06, 0x95, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x00, +0x61, 0x74, 0x98, 0x00, 0x31, 0x2e, 0x00, 0x5a, 0xc1, 0x00, +0x02, 0x6c, 0x00, 0x04, 0x2d, 0x00, 0xd7, 0x62, 0x79, 0x00, +0x61, 0x6e, 0x79, 0x00, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x2e, +0xa4, 0x01, 0x91, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x74, 0x6f, +0x6c, 0x64, 0x96, 0x00, 0xc0, 0x74, 0x6f, 0x74, 0x61, 0x6c, +0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x34, 0x01, 0x41, +0x65, 0x61, 0x63, 0x68, 0x42, 0x01, 0x00, 0x0d, 0x00, 0x03, +0x3a, 0x01, 0x00, 0x96, 0x00, 0x00, 0x2c, 0x00, 0x00, 0xd6, +0x01, 0x30, 0x2e, 0x00, 0x41, 0x40, 0x00, 0x11, 0x61, 0xc1, +0x00, 0x01, 0x16, 0x00, 0x33, 0x65, 0x64, 0x67, 0x7d, 0x01, +0x12, 0x65, 0xf8, 0x01, 0x01, 0xbb, 0x01, 0x63, 0x72, 0x69, +0x74, 0x74, 0x65, 0x6e, 0x59, 0x00, 0x24, 0x73, 0x2c, 0xcc, +0x01, 0xd1, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, +0x68, 0x6f, 0x77, 0x00, 0x6d, 0x9f, 0x00, 0x02, 0x63, 0x00, +0x1a, 0x73, 0x06, 0x01, 0x51, 0x66, 0x00, 0x79, 0x6f, 0x75, +0xea, 0x00, 0x57, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x5c, 0x00, +0xa0, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x61, 0x00, 0x72, 0x6f, +0x77, 0xbb, 0x01, 0xf1, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, +0x6e, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, +0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x74, 0x68, 0x61, 0x74, +0x00, 0x6c, 0x01, 0x9d, 0x69, 0x6f, 0x6e, 0x2e, 0x00, 0x28, +0x54, 0x68, 0x65, 0x6a, 0x02, 0x01, 0xa5, 0x00, 0x03, 0xb7, +0x01, 0xf1, 0x05, 0x69, 0x76, 0x65, 0x00, 0x6f, 0x6e, 0x00, +0x62, 0x6f, 0x74, 0x68, 0x00, 0x73, 0x69, 0x64, 0x65, 0x73, +0x2e, 0x00, 0x49, 0x81, 0x00, 0x17, 0x72, 0xd9, 0x01, 0x22, +0x6c, 0x69, 0x63, 0x02, 0xd1, 0x73, 0x69, 0x67, 0x68, 0x74, +0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x98, 0x00, +0x45, 0x73, 0x61, 0x6d, 0x65, 0x2a, 0x01, 0x21, 0x6d, 0x6f, +0xee, 0x01, 0x81, 0x61, 0x6e, 0x00, 0x6f, 0x6e, 0x63, 0x65, +0x2c, 0x21, 0x00, 0x03, 0x5d, 0x01, 0xd3, 0x77, 0x69, 0x6c, +0x6c, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x69, 0x74, +0x68, 0x01, 0x30, 0x69, 0x6d, 0x65, 0x0d, 0x00, 0x24, 0x69, +0x73, 0xb6, 0x01, 0x11, 0x2c, 0xec, 0x02, 0x10, 0x6a, 0xe3, +0x02, 0x00, 0x41, 0x00, 0xf2, 0x01, 0x2e, 0x29, 0x00, 0x00, +0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, +0x6c, 0x65, 0x9a, 0x01, 0x30, 0x77, 0x61, 0x73, 0x15, 0x02, +0x20, 0x65, 0x6e, 0x99, 0x00, 0xf1, 0x01, 0x62, 0x79, 0x00, +0x44, 0x61, 0x76, 0x69, 0x64, 0x00, 0x4d, 0x69, 0x6c, 0x6c, +0x61, 0x72, 0x2c, 0xf6, 0x02, 0x12, 0x72, 0x79, 0x00, 0x00, +0x9a, 0x00, 0x41, 0x60, 0x48, 0x61, 0x75, 0x29, 0x00, 0x12, +0x4d, 0x3f, 0x03, 0xf3, 0x03, 0x4d, 0x61, 0x7a, 0x65, 0x27, +0x2e, 0x00, 0x53, 0x65, 0x65, 0x00, 0x5b, 0x32, 0x30, 0x5d, +0x00, 0x66, 0x6f, 0xb6, 0x00, 0x61, 0x64, 0x65, 0x74, 0x61, +0x69, 0x6c, 0x2b, 0x02, 0x02, 0xec, 0x03, 0x01, 0x68, 0x00, +0x00, 0xab, 0x03, 0x40, 0x72, 0x69, 0x62, 0x75, 0x42, 0x00, +0x01, 0x89, 0x01, 0x20, 0x69, 0x73, 0x76, 0x01, 0x01, 0x38, +0x01, 0x20, 0x6f, 0x6e, 0x7e, 0x00, 0xd0, 0x53, 0x74, 0x65, +0x66, 0x66, 0x65, 0x6e, 0x00, 0x42, 0x61, 0x75, 0x65, 0x72, +0x3e, 0x00, 0x01, 0x57, 0x00, 0xf4, 0x29, 0x68, 0x74, 0x74, +0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6a, 0x61, +0x6e, 0x6b, 0x6f, 0x2e, 0x61, 0x74, 0x2f, 0x52, 0x61, 0x65, +0x74, 0x73, 0x65, 0x6c, 0x2f, 0x53, 0x70, 0x75, 0x6b, 0x73, +0x63, 0x68, 0x6c, 0x6f, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x64, +0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0x00, 0x00, 0x33, +0x37, 0x2e, 0x31, 0x68, 0x04, 0x01, 0x78, 0x00, 0x46, 0x6f, +0x6c, 0x73, 0x20, 0x8f, 0x00, 0xe3, 0x68, 0x61, 0x73, 0x00, +0x61, 0x00, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x00, +0x21, 0x00, 0x70, 0x00, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, +0x9c, 0x00, 0xf0, 0x08, 0x53, 0x6f, 0x6c, 0x6f, 0x2c, 0x00, +0x55, 0x6e, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x00, 0x61, 0x6e, +0x64, 0x00, 0x4b, 0x65, 0x65, 0x6e, 0x2e, 0x42, 0x01, 0x63, +0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x00, 0x71, 0x2c, +0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x23, 0x01, 0x40, 0x6d, +0x6f, 0x75, 0x73, 0x62, 0x03, 0x01, 0x2b, 0x03, 0x45, 0x65, +0x6d, 0x70, 0x74, 0x7d, 0x04, 0x12, 0x61, 0xdf, 0x02, 0x12, +0x6e, 0x73, 0x01, 0x60, 0x61, 0x00, 0x6c, 0x65, 0x74, 0x74, +0x23, 0x03, 0x15, 0x72, 0x2d, 0x03, 0x02, 0x15, 0x03, 0x84, +0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0xdc, 0x02, +0x00, 0x87, 0x02, 0x01, 0x59, 0x03, 0x0a, 0x44, 0x03, 0x50, +0x3a, 0x00, 0x60, 0x47, 0x27, 0x3e, 0x00, 0x31, 0x60, 0x31, +0x27, 0x74, 0x01, 0x05, 0x8d, 0x04, 0x22, 0x60, 0x56, 0x18, +0x00, 0x14, 0x32, 0x18, 0x00, 0x08, 0x9c, 0x04, 0x22, 0x60, +0x5a, 0x1d, 0x00, 0x14, 0x33, 0x1d, 0x00, 0x04, 0xab, 0x04, +0x12, 0x49, 0x23, 0x03, 0x41, 0x6d, 0x61, 0x6b, 0x65, 0x1b, +0x05, 0x5e, 0x73, 0x74, 0x61, 0x6b, 0x65, 0xda, 0x00, 0x03, +0xba, 0x03, 0x50, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x2d, 0x04, +0x08, 0xde, 0x00, 0xb0, 0x70, 0x72, 0x65, 0x73, 0x73, 0x00, +0x53, 0x70, 0x61, 0x63, 0x65, 0x3f, 0x01, 0x50, 0x63, 0x6c, +0x65, 0x61, 0x72, 0x8e, 0x02, 0x20, 0x61, 0x67, 0x9c, 0x05, +0x62, 0x28, 0x6f, 0x72, 0x00, 0x75, 0x73, 0xbb, 0x04, 0xd0, +0x55, 0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, +0x72, 0x65, 0x29, 0x51, 0x01, 0x03, 0x7e, 0x00, 0x10, 0x72, +0x0d, 0x03, 0x12, 0x2d, 0x74, 0x00, 0x00, 0x44, 0x01, 0x0f, +0x3c, 0x01, 0x15, 0x02, 0x18, 0x03, 0x01, 0x93, 0x00, 0x50, +0x73, 0x70, 0x6f, 0x6e, 0x64, 0x34, 0x01, 0x04, 0x42, 0x03, +0x01, 0x27, 0x03, 0x00, 0x09, 0x04, 0x31, 0x68, 0x6f, 0x77, +0x10, 0x05, 0xb3, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x64, +0x00, 0x73, 0x69, 0x7a, 0xd0, 0x00, 0x14, 0x61, 0xc7, 0x00, +0x21, 0x2c, 0x00, 0x13, 0x02, 0xe1, 0x60, 0x70, 0x65, 0x6e, +0x63, 0x69, 0x6c, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x27, 0x2e, +0xe9, 0x04, 0x00, 0x4e, 0x04, 0x57, 0x68, 0x61, 0x76, 0x65, +0x00, 0x1b, 0x00, 0x12, 0x73, 0xec, 0x02, 0x65, 0x75, 0x6c, +0x74, 0x69, 0x70, 0x6c, 0xb3, 0x03, 0x00, 0x4b, 0x03, 0x06, +0xc8, 0x03, 0x02, 0x58, 0x00, 0x34, 0x2e, 0x00, 0x41, 0xcb, +0x00, 0x03, 0xab, 0x06, 0x11, 0x69, 0x76, 0x04, 0x51, 0x66, +0x75, 0x6c, 0x6c, 0x2d, 0x88, 0x00, 0x04, 0xae, 0x00, 0x31, +0x63, 0x61, 0x6e, 0x9d, 0x06, 0x00, 0x14, 0x05, 0x04, 0xd6, +0x06, 0x08, 0x73, 0x00, 0x01, 0x7e, 0x02, 0x00, 0xbd, 0x04, +0x00, 0x5d, 0x00, 0x30, 0x70, 0x61, 0x79, 0xcc, 0x06, 0x20, +0x00, 0x61, 0x1b, 0x05, 0x01, 0x3f, 0x03, 0x29, 0x74, 0x6f, +0x2e, 0x00, 0x00, 0x28, 0x07, 0x40, 0x00, 0x65, 0x78, 0x61, +0xd5, 0x05, 0x20, 0x00, 0x77, 0xe8, 0x00, 0x00, 0x66, 0x01, +0x03, 0x86, 0x01, 0x11, 0x6d, 0xbf, 0x00, 0x50, 0x69, 0x73, +0x00, 0x75, 0x70, 0x38, 0x00, 0x63, 0x79, 0x6f, 0x75, 0x3a, +0x00, 0x79, 0xeb, 0x00, 0x05, 0x23, 0x00, 0x70, 0x61, 0x73, +0x00, 0x72, 0x65, 0x6d, 0x69, 0x03, 0x04, 0x12, 0x73, 0x2a, +0x01, 0x30, 0x61, 0x00, 0x70, 0x1d, 0x05, 0x20, 0x63, 0x75, +0x35, 0x03, 0x03, 0xd5, 0x00, 0x50, 0x6e, 0x65, 0x65, 0x64, +0x73, 0x45, 0x00, 0x10, 0x62, 0x05, 0x05, 0x91, 0x2d, 0x65, +0x78, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x73, 0x04, 0x01, +0x54, 0x00, 0x42, 0x6b, 0x6e, 0x6f, 0x77, 0x16, 0x04, 0x4b, +0x61, 0x62, 0x6f, 0x75, 0x45, 0x00, 0x03, 0xfc, 0x00, 0x01, +0xa0, 0x02, 0x0f, 0x81, 0x00, 0x01, 0x20, 0x6c, 0x69, 0xf7, +0x06, 0x03, 0x12, 0x06, 0x32, 0x70, 0x6f, 0x73, 0x8f, 0x06, +0x07, 0x4c, 0x06, 0x13, 0x61, 0x28, 0x08, 0x04, 0xc5, 0x01, +0x20, 0x6f, 0x72, 0x7f, 0x03, 0x20, 0x74, 0x68, 0x65, 0x01, +0x32, 0x65, 0x6c, 0x73, 0x83, 0x00, 0x93, 0x66, 0x65, 0x65, +0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0xc1, 0x03, 0x51, 0x65, +0x72, 0x61, 0x73, 0x65, 0x00, 0x04, 0x39, 0x6e, 0x67, 0x6c, +0xd8, 0x01, 0x1c, 0x2c, 0x88, 0x02, 0x01, 0xce, 0x01, 0x07, +0x8a, 0x02, 0x00, 0x85, 0x02, 0x05, 0xe2, 0x01, 0x0d, 0xc8, +0x03, 0x01, 0xef, 0x02, 0x00, 0x65, 0x00, 0x3a, 0x41, 0x6c, +0x6c, 0x2f, 0x02, 0x09, 0xd3, 0x02, 0x22, 0x72, 0x65, 0x83, +0x00, 0x12, 0x64, 0x86, 0x07, 0x01, 0xa0, 0x06, 0x24, 0x65, +0x66, 0x76, 0x00, 0x05, 0x68, 0x00, 0x15, 0x61, 0xe9, 0x00, +0x02, 0x69, 0x00, 0x01, 0xde, 0x00, 0x0f, 0x32, 0x00, 0x05, +0x07, 0x82, 0x03, 0x31, 0x2e, 0x00, 0x52, 0xc5, 0x00, 0x02, +0xc2, 0x03, 0x01, 0x6f, 0x02, 0x04, 0x21, 0x00, 0x00, 0x0d, +0x00, 0x11, 0x73, 0xa6, 0x03, 0x01, 0x1c, 0x03, 0x01, 0x6c, +0x02, 0x02, 0x0e, 0x01, 0x0c, 0x6a, 0x02, 0x12, 0x41, 0xe3, +0x02, 0x02, 0x09, 0x05, 0x01, 0x63, 0x03, 0x50, 0x75, 0x72, +0x73, 0x6f, 0x72, 0xa4, 0x04, 0x05, 0x61, 0x07, 0x22, 0x75, +0x73, 0xa7, 0x08, 0x62, 0x63, 0x6f, 0x6e, 0x6a, 0x75, 0x6e, +0xc6, 0x05, 0x01, 0x44, 0x09, 0x25, 0x74, 0x68, 0x1d, 0x01, +0x01, 0x30, 0x00, 0x11, 0x74, 0x35, 0x05, 0x17, 0x63, 0x29, +0x03, 0x2b, 0x6f, 0x72, 0x72, 0x00, 0x3d, 0x55, 0x73, 0x65, +0x67, 0x00, 0x60, 0x74, 0x6f, 0x00, 0x6d, 0x6f, 0x76, 0x09, +0x01, 0x51, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x2f, 0x07, 0x07, +0x2e, 0x08, 0x00, 0xc6, 0x07, 0x1f, 0x2c, 0x2f, 0x01, 0x07, +0x07, 0x98, 0x01, 0x30, 0x74, 0x6f, 0x00, 0xe2, 0x06, 0x01, +0x93, 0x04, 0x03, 0xd5, 0x01, 0x05, 0x52, 0x00, 0x25, 0x65, +0x64, 0xaa, 0x03, 0x14, 0x50, 0x23, 0x01, 0x50, 0x72, 0x65, +0x74, 0x75, 0x72, 0x53, 0x03, 0x5a, 0x67, 0x67, 0x6c, 0x65, +0x73, 0x30, 0x00, 0x02, 0x46, 0x08, 0x00, 0x6d, 0x00, 0x11, +0x64, 0x44, 0x04, 0x02, 0x8e, 0x08, 0x04, 0xbd, 0x02, 0x02, +0x67, 0x00, 0x10, 0x6f, 0xef, 0x07, 0x2b, 0x6d, 0x6f, 0x34, +0x04, 0x07, 0xee, 0x04, 0x60, 0x70, 0x72, 0x65, 0x66, 0x65, +0x72, 0x15, 0x01, 0x23, 0x69, 0x6e, 0xaf, 0x00, 0x05, 0xe7, +0x02, 0x81, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, +0x49, 0x05, 0x26, 0x75, 0x74, 0xef, 0x02, 0x51, 0x70, 0x69, +0x63, 0x74, 0x75, 0x03, 0x0b, 0x04, 0x6e, 0x00, 0x02, 0xf5, +0x01, 0x31, 0x60, 0x41, 0x27, 0x50, 0x07, 0x01, 0xae, 0x00, +0x50, 0x00, 0x62, 0x65, 0x74, 0x77, 0xf9, 0x08, 0x00, 0xf5, +0x04, 0x04, 0x41, 0x06, 0x05, 0x77, 0x01, 0x29, 0x61, 0x73, +0x83, 0x01, 0x07, 0x24, 0x00, 0x02, 0x6f, 0x03, 0x02, 0x8a, +0x00, 0x00, 0xa9, 0x00, 0x15, 0x4c, 0x5f, 0x02, 0x02, 0xb0, +0x04, 0x33, 0x63, 0x6c, 0x75, 0x35, 0x02, 0x00, 0xcc, 0x00, +0x01, 0xdc, 0x05, 0x30, 0x73, 0x00, 0x64, 0x2d, 0x0b, 0x50, +0x28, 0x67, 0x72, 0x65, 0x79, 0x11, 0x00, 0x41, 0x6f, 0x75, +0x74, 0x29, 0xa4, 0x02, 0x24, 0x75, 0x6e, 0x24, 0x00, 0x23, +0x69, 0x66, 0x94, 0x08, 0x71, 0x61, 0x6c, 0x72, 0x65, 0x61, +0x64, 0x79, 0x3d, 0x00, 0x20, 0x65, 0x64, 0x61, 0x00, 0x10, +0x28, 0x24, 0x03, 0x01, 0xf0, 0x00, 0x01, 0x39, 0x02, 0x92, +0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x53, +0x02, 0x13, 0x73, 0x15, 0x08, 0x36, 0x32, 0x2e, 0x31, 0x6a, +0x0a, 0x82, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, +0xcc, 0x08, 0x44, 0x33, 0x37, 0x2e, 0x32, 0xe3, 0x07, 0x60, +0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0xbc, 0x00, 0x12, 0x20, +0x26, 0x05, 0x00, 0xd2, 0x02, 0x05, 0x14, 0x00, 0x02, 0x42, +0x00, 0x04, 0x3d, 0x00, 0x04, 0xda, 0x09, 0xf1, 0x01, 0x65, +0x00, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, +0x2e, 0x27, 0x00, 0x6f, 0x70, 0x70, 0x00, 0x03, 0x8a, 0x07, +0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, +0x6e, 0x75, 0xac, 0x00, 0x91, 0x57, 0x69, 0x64, 0x74, 0x68, +0x2c, 0x00, 0x48, 0x65, 0x01, 0x02, 0x51, 0x00, 0x00, 0x53, +0x69, 0x7a, 0x91, 0x07, 0x01, 0x48, 0x0a, 0x14, 0x69, 0x7e, +0x04, 0x01, 0x38, 0x01, 0x40, 0x44, 0x69, 0x66, 0x66, 0xdd, +0x04, 0x63, 0x74, 0x79, 0x00, 0x00, 0x00, 0x43, 0x7a, 0x08, +0x01, 0x54, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x04, 0xe3, 0x0a, +0x50, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x82, 0x02, 0x02, 0x93, +0x09, 0x12, 0x2e, 0xd6, 0x00, 0x14, 0x33, 0xd6, 0x00, 0x52, +0x75, 0x73, 0x65, 0x72, 0x20, 0x2b, 0x02, 0x41, 0x65, 0x6e, +0x63, 0x65, 0xdc, 0x00, 0x20, 0x4f, 0x6e, 0x36, 0x02, 0x63, +0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0xc0, 0x06, 0x70, 0x75, +0x70, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x2e, 0x00, 0x17, 0x00, +0x2e, 0x00, 0x12, 0x2c, 0xca, 0x00, 0x16, 0x50, 0x12, 0x00, +0x0d, 0xe6, 0x00, 0x33, 0x47, 0x61, 0x6d, 0xe6, 0x00, 0x02, +0xdb, 0x01, 0x32, 0x6c, 0x65, 0x74, 0x5c, 0x02, 0x71, 0x6f, +0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x27, 0x0c, 0x44, 0x74, +0x68, 0x65, 0x72, 0x38, 0x09, 0x10, 0x75, 0xaa, 0x0a, 0x05, +0xb0, 0x02, 0x06, 0x93, 0x02, 0x00, 0x80, 0x02, 0x20, 0x72, +0x65, 0x8f, 0x02, 0xe0, 0x65, 0x6e, 0x74, 0x00, 0x6d, 0x6f, +0x6e, 0x73, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x00, }; -const unsigned short help_text_len = 3286; -const unsigned short help_text_words = 614; +const unsigned short help_text_len = 3574; +const unsigned short help_text_words = 660; const char quick_help_text[] = "Place ghosts, vampires and zombies so that the right numbers of them can be seen in mirrors."; diff --git a/apps/plugins/puzzles/help/unequal.c b/apps/plugins/puzzles/help/unequal.c index 8885d70c33..445fd7d544 100644 --- a/apps/plugins/puzzles/help/unequal.c +++ b/apps/plugins/puzzles/help/unequal.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,255 +6,255 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 239, TEXT_CENTER | C_RED }, - { 306, TEXT_UNDERLINE }, - { 631, TEXT_CENTER | C_RED }, - { 648, TEXT_UNDERLINE }, - { 660, TEXT_UNDERLINE }, - { 668, TEXT_UNDERLINE }, + { 240, TEXT_CENTER | C_RED }, + { 307, TEXT_UNDERLINE }, + { 632, TEXT_CENTER | C_RED }, + { 649, TEXT_UNDERLINE }, + { 661, TEXT_UNDERLINE }, + { 669, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 3934 comp 2352 ratio 0.597865 level 10 saved 1582 */ +/* orig 3954 comp 2358 ratio 0.596358 level 10 saved 1596 */ const char help_text[] = { -0xf4, 0x24, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfe, 0x07, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x32, 0x37, 0x3a, 0x20, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x61, -0x6c, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, -0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x73, 0x71, 0x75, 0x61, -0x72, 0x65, 0x00, 0x67, 0x72, 0x69, 0x64, 0x3b, 0x00, 0x65, -0x61, 0x63, 0x68, 0x12, 0x00, 0xf1, 0x1a, 0x6d, 0x61, 0x79, -0x00, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x61, -0x00, 0x64, 0x69, 0x67, 0x69, 0x74, 0x00, 0x66, 0x72, 0x6f, -0x6d, 0x00, 0x31, 0x00, 0x74, 0x6f, 0x00, 0x74, 0x68, 0x65, -0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6f, 0x66, 0x0c, 0x00, -0x00, 0x40, 0x00, 0xa3, 0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, -0x73, 0x6f, 0x6d, 0x65, 0x44, 0x00, 0x12, 0x73, 0x65, 0x00, -0x30, 0x63, 0x6c, 0x75, 0x2d, 0x00, 0xb0, 0x67, 0x6e, 0x73, -0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x33, 0x00, -0x20, 0x6d, 0x2e, 0x87, 0x00, 0x80, 0x72, 0x00, 0x61, 0x69, -0x6d, 0x00, 0x69, 0x73, 0x54, 0x00, 0xe5, 0x66, 0x75, 0x6c, -0x6c, 0x79, 0x00, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, -0x65, 0x57, 0x00, 0xf0, 0x0f, 0x00, 0x77, 0x69, 0x74, 0x68, -0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x00, 0x73, -0x75, 0x63, 0x68, 0x00, 0x74, 0x68, 0x61, 0x74, 0x3a, 0x00, -0x00, 0x00, 0x2d, 0x00, 0x45, 0xb2, 0x00, 0x34, 0x72, 0x6f, -0x77, 0xab, 0x00, 0xf1, 0x05, 0x73, 0x00, 0x6f, 0x6e, 0x6c, -0x79, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0x6f, 0x63, 0x63, 0x75, -0x72, 0x72, 0x65, 0x6e, 0x63, 0xa5, 0x00, 0x01, 0xdb, 0x00, -0x02, 0xc6, 0x00, 0x05, 0x38, 0x00, 0x6f, 0x63, 0x6f, 0x6c, -0x75, 0x6d, 0x6e, 0x3b, 0x00, 0x1d, 0x31, 0x41, 0x6c, 0x6c, -0x9c, 0x00, 0x07, 0xd7, 0x00, 0x00, 0x30, 0x01, 0xf1, 0x03, -0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, 0x65, 0x64, 0x2e, -0x00, 0x00, 0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x17, 0x00, -0xf3, 0x0b, 0x74, 0x77, 0x6f, 0x00, 0x6d, 0x6f, 0x64, 0x65, -0x73, 0x00, 0x66, 0x6f, 0x72, 0x00, 0x74, 0x68, 0x69, 0x73, -0x00, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x00, 0x60, 0x90, 0x01, -0x11, 0x27, 0x36, 0x01, 0xa0, 0x60, 0x41, 0x64, 0x6a, 0x61, -0x63, 0x65, 0x6e, 0x74, 0x27, 0x3f, 0x00, 0x27, 0x49, 0x6e, -0x1f, 0x00, 0x00, 0x3e, 0x00, 0x1e, 0x2c, 0x72, 0x00, 0x00, -0x1d, 0x01, 0xf1, 0x0e, 0x65, 0x61, 0x74, 0x65, 0x72, 0x2d, -0x74, 0x68, 0x61, 0x6e, 0x00, 0x73, 0x79, 0x6d, 0x62, 0x6f, -0x6c, 0x73, 0x00, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, -0x69, 0x6e, 0x67, 0xca, 0x00, 0x02, 0x89, 0x01, 0x50, 0x27, -0x73, 0x00, 0x76, 0x61, 0x3d, 0x00, 0x24, 0x69, 0x73, 0x36, -0x00, 0x11, 0x00, 0x36, 0x00, 0xf0, 0x01, 0x69, 0x74, 0x73, -0x00, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x75, 0x72, -0x27, 0x73, 0x2e, 0x7a, 0x00, 0x01, 0xa4, 0x00, 0x00, 0x75, -0x00, 0x81, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x61, 0x6c, 0x6c, -0x78, 0x00, 0x11, 0x73, 0x11, 0x02, 0xf0, 0x18, 0x62, 0x65, -0x00, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x2c, 0x00, -0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, -0x6c, 0x79, 0x00, 0x61, 0x74, 0x00, 0x68, 0x69, 0x67, 0x68, -0x65, 0x72, 0x00, 0x64, 0x69, 0x66, 0x66, 0x17, 0x00, 0x94, -0x74, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0xd1, -0x00, 0x05, 0xe2, 0x00, 0x0f, 0xd2, 0x00, 0x07, 0x3f, 0x62, -0x61, 0x72, 0xc2, 0x00, 0x10, 0x90, 0x6e, 0x75, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x6c, 0x78, 0x00, 0x03, 0x55, 0x00, -0x61, 0x00, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x31, 0x00, 0x03, -0x88, 0x00, 0x21, 0x6f, 0x72, 0x0e, 0x00, 0x6f, 0x6c, 0x6f, -0x77, 0x65, 0x72, 0x29, 0xee, 0x00, 0x00, 0x0b, 0xec, 0x00, -0x06, 0xe8, 0x00, 0x20, 0x61, 0x72, 0x0e, 0x00, 0x44, 0x77, -0x61, 0x79, 0x73, 0xec, 0x00, 0x54, 0x3a, 0x00, 0x61, 0x62, -0x73, 0x0e, 0x02, 0x10, 0x61, 0xa6, 0x00, 0xb1, 0x00, 0x74, -0x68, 0x75, 0x73, 0x00, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x8d, -0x02, 0x2f, 0x00, 0x61, 0xa8, 0x00, 0x00, 0xa1, 0x64, 0x65, -0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x6c, 0x79, 0x4a, 0x01, -0x0f, 0xb7, 0x00, 0x02, 0x22, 0x74, 0x6f, 0x40, 0x00, 0x09, -0x85, 0x01, 0x02, 0x30, 0x01, 0x50, 0x54, 0x72, 0x69, 0x76, -0x69, 0x01, 0x02, 0x0c, 0x52, 0x01, 0xa0, 0x00, 0x28, 0x61, -0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x8e, 0x01, 0x11, -0x61, 0x49, 0x01, 0x81, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, -0x6d, 0x27, 0x5d, 0x02, 0xf1, 0x00, 0x00, 0x74, 0x79, 0x70, -0x65, 0x00, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, -0x29, 0x6b, 0x01, 0x03, 0x8f, 0x02, 0x2b, 0x6e, 0x6f, 0x37, -0x02, 0x01, 0x7c, 0x01, 0x1c, 0x69, 0x70, 0x02, 0x11, 0x3b, -0x55, 0x00, 0x63, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x9e, -0x03, 0x42, 0x73, 0x6f, 0x6c, 0x76, 0x95, 0x03, 0x10, 0x4c, -0x9d, 0x01, 0x04, 0x27, 0x04, 0x00, 0x34, 0x03, 0x00, 0xb2, -0x00, 0x21, 0x41, 0x74, 0x1c, 0x00, 0x31, 0x74, 0x69, 0x6d, -0x26, 0x01, 0x30, 0x77, 0x72, 0x69, 0xc2, 0x01, 0x02, 0xe6, -0x01, 0x0a, 0x5c, 0x00, 0x02, 0x33, 0x04, 0x27, 0x69, 0x73, -0x5f, 0x00, 0x60, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0xf2, -0x01, 0x21, 0x69, 0x6e, 0x32, 0x00, 0xf1, 0x06, 0x47, 0x75, -0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x00, 0x77, 0x65, 0x65, -0x6b, 0x6c, 0x79, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x1a, -0x00, 0x10, 0x6e, 0xe0, 0x00, 0xa1, 0x60, 0x46, 0x75, 0x74, -0x6f, 0x73, 0x68, 0x69, 0x6b, 0x69, 0x2f, 0x03, 0x03, 0x5f, -0x00, 0x41, 0x00, 0x77, 0x61, 0x73, 0xcd, 0x03, 0x72, 0x72, -0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x5d, 0x01, 0x20, 0x69, -0x73, 0xe8, 0x03, 0x00, 0x0b, 0x01, 0xf1, 0x03, 0x69, 0x6f, -0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, -0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0xba, 0x00, 0x45, 0x32, -0x37, 0x2e, 0x31, 0x1d, 0x05, 0x01, 0x3f, 0x00, 0x47, 0x6f, -0x6c, 0x73, 0x20, 0x57, 0x00, 0x21, 0x73, 0x68, 0xcc, 0x04, -0x10, 0x6d, 0x7a, 0x04, 0x21, 0x6f, 0x66, 0x46, 0x02, 0x03, -0x27, 0x00, 0x72, 0x00, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, -0xa2, 0x04, 0x41, 0x53, 0x6f, 0x6c, 0x6f, 0xfc, 0x03, 0x64, -0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x3f, 0x00, 0xe1, 0x2c, -0x00, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, -0x69, 0x63, 0x6b, 0xc4, 0x00, 0x60, 0x6d, 0x6f, 0x75, 0x73, -0x65, 0x00, 0x58, 0x05, 0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, -0x70, 0x74, 0x79, 0x4e, 0x01, 0x00, 0x0b, 0x04, 0x42, 0x74, -0x68, 0x65, 0x6e, 0xc2, 0x01, 0x04, 0x77, 0x05, 0x70, 0x6f, -0x72, 0x00, 0x6c, 0x65, 0x74, 0x74, 0xd5, 0x02, 0x02, 0x1f, -0x01, 0x81, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, -0x36, 0x05, 0x32, 0x69, 0x6c, 0x6c, 0x44, 0x02, 0x02, 0x44, -0x00, 0xc0, 0x2e, 0x00, 0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, -0x00, 0x6d, 0x61, 0x6b, 0x43, 0x00, 0x8e, 0x6d, 0x69, 0x73, -0x74, 0x61, 0x6b, 0x65, 0x2c, 0x80, 0x00, 0x02, 0x4c, 0x00, -0x98, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, -0x84, 0x00, 0xb0, 0x70, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, -0x70, 0x61, 0x63, 0x65, 0x64, 0x00, 0xb0, 0x63, 0x6c, 0x65, -0x61, 0x72, 0x00, 0x69, 0x74, 0x00, 0x61, 0x67, 0x0f, 0x06, -0x62, 0x28, 0x6f, 0x72, 0x00, 0x75, 0x73, 0x0d, 0x02, 0xd1, -0x55, 0x6e, 0x64, 0x6f, 0x00, 0x66, 0x65, 0x61, 0x74, 0x75, -0x72, 0x65, 0x29, 0xbb, 0x02, 0x02, 0x7e, 0x00, 0x62, 0x72, -0x69, 0x67, 0x68, 0x74, 0x2d, 0x74, 0x00, 0x01, 0x42, 0x06, -0x0f, 0xe2, 0x00, 0x04, 0x02, 0xd8, 0x05, 0x13, 0x2c, 0x06, -0x03, 0x01, 0x0d, 0x00, 0x20, 0x00, 0x77, 0xd3, 0x00, 0xa4, -0x62, 0x65, 0x00, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, -0xaa, 0x00, 0x04, 0x42, 0x00, 0xf1, 0x03, 0x73, 0x00, 0x61, -0x00, 0x60, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x00, 0x6d, -0x61, 0x72, 0x6b, 0x27, 0x2e, 0xd1, 0x06, 0x32, 0x63, 0x61, -0x6e, 0x70, 0x06, 0x07, 0x1b, 0x00, 0x02, 0x76, 0x05, 0x85, -0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x45, 0x06, -0x04, 0x51, 0x00, 0x00, 0x4c, 0x02, 0x04, 0x36, 0x01, 0x13, -0x53, 0xb3, 0x06, 0x03, 0x0e, 0x06, 0x00, 0x8d, 0x02, 0x00, -0x5b, 0x01, 0x55, 0x65, 0x64, 0x2d, 0x69, 0x6e, 0x39, 0x00, -0x32, 0x63, 0x61, 0x6e, 0x15, 0x05, 0x25, 0x73, 0x6f, 0x1d, -0x07, 0x08, 0x6f, 0x00, 0x03, 0xfc, 0x05, 0x02, 0x86, 0x03, -0x10, 0x70, 0x43, 0x04, 0x81, 0x6e, 0x6f, 0x00, 0x61, 0x74, -0x74, 0x65, 0x6e, 0x7e, 0x02, 0x29, 0x74, 0x6f, 0x2e, 0x00, -0xe0, 0x2c, 0x00, 0x73, 0x6f, 0x00, 0x65, 0x78, 0x61, 0x63, -0x74, 0x6c, 0x79, 0x00, 0x77, 0x01, 0x01, 0x00, 0x3a, 0x01, -0x03, 0x5a, 0x01, 0x11, 0x6d, 0xbb, 0x00, 0x50, 0x69, 0x73, -0x00, 0x75, 0x70, 0x38, 0x00, 0x63, 0x79, 0x6f, 0x75, 0x3a, -0x00, 0x79, 0xe7, 0x00, 0x05, 0x23, 0x00, 0x70, 0x61, 0x73, -0x00, 0x72, 0x65, 0x6d, 0x69, 0x1e, 0x03, 0x05, 0x89, 0x04, -0x06, 0x98, 0x05, 0x04, 0x32, 0x01, 0x41, 0x6e, 0x65, 0x65, -0x64, 0xc4, 0x03, 0xf0, 0x01, 0x62, 0x65, 0x00, 0x72, 0x65, -0x2d, 0x65, 0x78, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x00, -0x6f, 0xd3, 0x04, 0x00, 0x54, 0x00, 0x70, 0x6b, 0x6e, 0x6f, -0x77, 0x00, 0x6d, 0x6f, 0x5d, 0x01, 0x3b, 0x62, 0x6f, 0x75, -0x45, 0x00, 0x04, 0xa2, 0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, -0x02, 0x54, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x07, 0x08, 0x31, -0x70, 0x6f, 0x73, 0x32, 0x05, 0x08, 0x6a, 0x01, 0x64, 0x61, -0x00, 0x67, 0x69, 0x76, 0x65, 0x31, 0x04, 0x01, 0x48, 0x00, -0x50, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x62, 0x01, 0x32, 0x65, -0x6c, 0x73, 0x82, 0x00, 0x93, 0x66, 0x65, 0x65, 0x6c, 0x00, -0x6c, 0x69, 0x6b, 0x65, 0x42, 0x03, 0x41, 0x65, 0x72, 0x61, -0x73, 0x9f, 0x08, 0x49, 0x69, 0x6e, 0x67, 0x6c, 0xd3, 0x01, -0x1c, 0x2c, 0x5b, 0x02, 0x08, 0x1b, 0x02, 0x22, 0x6e, 0x64, -0x58, 0x02, 0x05, 0xde, 0x01, 0x03, 0x52, 0x02, 0x01, 0xb8, -0x02, 0x01, 0xa7, 0x04, 0x2a, 0x6c, 0x6c, 0x20, 0x02, 0x09, -0x9c, 0x02, 0x22, 0x72, 0x65, 0x79, 0x00, 0x30, 0x64, 0x00, -0x77, 0xa3, 0x02, 0x00, 0x99, 0x00, 0x34, 0x6c, 0x65, 0x66, -0x6c, 0x00, 0x05, 0x5e, 0x00, 0x18, 0x61, 0x14, 0x01, 0x0f, -0x2a, 0x00, 0x05, 0x02, 0x43, 0x03, 0x10, 0x73, 0x43, 0x03, -0x36, 0x2e, 0x00, 0x52, 0xb3, 0x00, 0x00, 0xf7, 0x00, 0x05, -0x20, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x23, 0x00, 0x02, 0xf4, -0x02, 0x01, 0x58, 0x02, 0x02, 0xfb, 0x00, 0x0c, 0x56, 0x02, -0x12, 0x41, 0xcb, 0x02, 0x00, 0x65, 0x04, 0x03, 0x3b, 0x07, -0x50, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x0b, 0x04, 0x01, 0x97, -0x02, 0x00, 0xdc, 0x01, 0x22, 0x75, 0x73, 0x2d, 0x03, 0x62, -0x63, 0x6f, 0x6e, 0x6a, 0x75, 0x6e, 0xf1, 0x04, 0x01, 0x9b, -0x04, 0x00, 0x30, 0x00, 0x02, 0x4b, 0x04, 0x01, 0x2f, 0x00, -0x00, 0xce, 0x05, 0x25, 0x65, 0x74, 0xa4, 0x01, 0x2b, 0x6f, -0x72, 0x6e, 0x00, 0x04, 0x4e, 0x03, 0x01, 0x8f, 0x00, 0x04, -0xe9, 0x03, 0x30, 0x60, 0x4d, 0x27, 0x3e, 0x00, 0x00, 0x3d, -0x00, 0x51, 0x61, 0x75, 0x74, 0x6f, 0x2d, 0x78, 0x04, 0x54, -0x65, 0x76, 0x65, 0x72, 0x79, 0xda, 0x06, 0xc1, 0x00, 0x68, -0x69, 0x6e, 0x74, 0x2c, 0x00, 0x72, 0x65, 0x61, 0x64, 0x79, -0xad, 0x00, 0x72, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, -0xa6, 0x02, 0x61, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x33, -0x01, 0x01, 0x4f, 0x00, 0x15, 0x48, 0x4f, 0x00, 0x26, 0x64, -0x6f, 0xb0, 0x01, 0x23, 0x62, 0x75, 0x5e, 0x03, 0x22, 0x74, -0x6f, 0x3f, 0x00, 0x02, 0x9a, 0x07, 0x71, 0x6f, 0x62, 0x76, -0x69, 0x6f, 0x75, 0x73, 0x62, 0x00, 0x12, 0x73, 0xc8, 0x01, -0xc5, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, -0x6c, 0x79, 0x2c, 0xa5, 0x00, 0x08, 0x15, 0x01, 0x10, 0x74, -0x79, 0x09, 0x03, 0xb3, 0x06, 0x00, 0xd9, 0x00, 0x75, 0x00, -0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x58, 0x0a, 0x34, 0x2e, -0x00, 0x50, 0x83, 0x01, 0x20, 0x74, 0x68, 0x19, 0x03, 0x43, -0x74, 0x75, 0x72, 0x6e, 0x94, 0x00, 0x56, 0x67, 0x67, 0x6c, -0x65, 0x73, 0x3a, 0x00, 0x11, 0x28, 0xf9, 0x0a, 0x72, 0x61, -0x00, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x27, 0x01, 0x01, 0x08, -0x01, 0x08, 0x38, 0x01, 0x24, 0x29, 0x2c, 0x21, 0x02, 0x01, -0xe2, 0x01, 0x04, 0x7a, 0x02, 0x20, 0x69, 0x6e, 0xc4, 0x03, -0x0f, 0xca, 0x04, 0x03, 0x03, 0x0e, 0x00, 0x80, 0x61, 0x70, -0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0xf5, 0x0a, 0x44, 0x77, -0x61, 0x79, 0x3b, 0x44, 0x00, 0x01, 0x9b, 0x02, 0x21, 0x30, -0x00, 0x6d, 0x05, 0x04, 0xa6, 0x00, 0x02, 0x2d, 0x02, 0x23, -0x62, 0x61, 0x25, 0x05, 0x02, 0x99, 0x05, 0x13, 0x61, 0xaa, -0x04, 0x05, 0xcc, 0x04, 0x58, 0x00, 0x00, 0x4c, 0x65, 0x66, -0x70, 0x02, 0x02, 0x69, 0x09, 0x01, 0x33, 0x00, 0x01, 0xbd, -0x00, 0x20, 0x69, 0x74, 0x95, 0x01, 0x10, 0x64, 0x21, 0x09, -0x60, 0x28, 0x67, 0x72, 0x65, 0x79, 0x00, 0x66, 0x06, 0x41, -0x75, 0x74, 0x29, 0x2c, 0x6e, 0x00, 0x14, 0x6e, 0x24, 0x00, -0x10, 0x69, 0xee, 0x06, 0x01, 0xa1, 0x07, 0x12, 0x6c, 0xd6, -0x01, 0x00, 0x19, 0x00, 0x00, 0xe2, 0x0a, 0x40, 0x48, 0x6f, -0x6c, 0x64, 0x59, 0x00, 0x13, 0x43, 0x08, 0x07, 0x00, 0x9a, -0x02, 0x4a, 0x68, 0x69, 0x66, 0x74, 0xda, 0x02, 0x00, 0x43, -0x02, 0x10, 0x72, 0x9d, 0x0b, 0x00, 0x55, 0x01, 0x00, 0xdd, -0x03, 0x43, 0x77, 0x69, 0x73, 0x65, 0x78, 0x03, 0x00, 0xfb, -0x06, 0x01, 0x95, 0x00, 0x0a, 0x0b, 0x09, 0x05, 0xc3, 0x01, -0x03, 0x1c, 0x01, 0x02, 0x3b, 0x04, 0x32, 0x64, 0x69, 0x72, -0xc0, 0x07, 0x00, 0xdb, 0x00, 0x14, 0x28, 0x81, 0x0b, 0x11, -0x61, 0x13, 0x00, 0x00, 0x68, 0x09, 0x52, 0x73, 0x63, 0x72, -0x69, 0x62, 0x5f, 0x01, 0x13, 0x73, 0xe9, 0x07, 0x33, 0x32, -0x2e, 0x31, 0xca, 0x09, 0x35, 0x73, 0x6f, 0x00, 0x30, 0x09, -0x22, 0x2e, 0x29, 0xf1, 0x07, 0x15, 0x32, 0xf1, 0x07, 0xb2, -0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, -0x20, 0xbc, 0x05, 0x00, 0x7c, 0x03, 0x05, 0x14, 0x00, 0x02, -0x43, 0x00, 0x05, 0x6e, 0x09, 0x01, 0x07, 0x02, 0x07, 0x6f, -0x09, 0x71, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, -0x00, 0x03, 0x9b, 0x07, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, -0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xad, 0x00, 0x10, 0x4d, -0xf1, 0x08, 0x03, 0x07, 0x00, 0x28, 0x6f, 0x66, 0x56, 0x09, -0x16, 0x28, 0x16, 0x09, 0x27, 0x6f, 0x72, 0x1e, 0x0b, 0x00, -0xa2, 0x00, 0x94, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x28, 0x73, -0x2a, 0x73, 0x0d, 0x00, 0x00, 0x3c, 0x00, 0x02, 0xb4, 0x02, -0x36, 0x00, 0x00, 0x44, 0x0f, 0x0a, 0x14, 0x00, 0x81, 0x01, -0x02, 0xac, 0x02, 0x07, 0x29, 0x0a, 0x04, 0x97, 0x0d, 0x50, -0x65, 0x6e, 0x65, 0x72, 0x61, 0x0c, 0x09, 0x02, 0x76, 0x00, -0x10, 0x2e, 0xa8, 0x09, 0x03, 0x59, 0x0a, 0x02, 0x4d, 0x0a, -0x0f, 0x1d, 0x0a, 0x0e, 0x0f, 0x0b, 0x0a, 0x1d, 0x50, 0x41, -0x74, 0x00, 0x52, 0x65, 0xc5, 0x01, 0x34, 0x69, 0x76, 0x65, -0xb0, 0x0a, 0x01, 0x59, 0x0d, 0x0f, 0xb5, 0x0a, 0x1b, 0x82, -0x00, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0xc1, 0x02, -0x04, 0x12, 0x08, 0x06, 0x47, 0x04, 0x00, 0x29, 0x04, 0x01, -0x11, 0x03, 0x31, 0x6f, 0x6c, 0x75, 0x80, 0x01, 0x93, 0x73, -0x68, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x73, 0x74, 0x2b, 0x00, -0x71, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2e, 0x8f, 0x07, -0x02, 0x89, 0x0c, 0x00, 0x1f, 0x02, 0x04, 0x81, 0x0e, 0x03, -0x49, 0x00, 0x00, 0xfe, 0x08, 0x31, 0x72, 0x65, 0x61, 0x66, -0x06, 0x00, 0xef, 0x0e, 0x60, 0x6d, 0x70, 0x6c, 0x65, 0x78, -0x00, 0x12, 0x00, 0x21, 0x6f, 0x6e, 0x73, 0x03, 0x00, 0x3c, -0x02, 0x30, 0x6f, 0x69, 0x64, 0x59, 0x08, 0x03, 0x10, 0x00, -0xb0, 0x62, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x6b, -0x2e, 0x00, +0x6c, 0x20, 0x00, 0x2d, 0x01, 0x00, 0xf4, 0x10, 0x00, 0x00, +0x00, 0x59, 0x6f, 0x75, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, +0x61, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x67, +0x72, 0x69, 0x64, 0x3b, 0x00, 0x65, 0x61, 0x63, 0x68, 0x12, +0x00, 0xf1, 0x1a, 0x6d, 0x61, 0x79, 0x00, 0x63, 0x6f, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0x00, 0x61, 0x00, 0x64, 0x69, 0x67, +0x69, 0x74, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x31, 0x00, +0x74, 0x6f, 0x00, 0x74, 0x68, 0x65, 0x00, 0x73, 0x69, 0x7a, +0x65, 0x00, 0x6f, 0x66, 0x0c, 0x00, 0x00, 0x40, 0x00, 0xa3, +0x2c, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x73, 0x6f, 0x6d, 0x65, +0x44, 0x00, 0x12, 0x73, 0x65, 0x00, 0x30, 0x63, 0x6c, 0x75, +0x2d, 0x00, 0xb0, 0x67, 0x6e, 0x73, 0x00, 0x62, 0x65, 0x74, +0x77, 0x65, 0x65, 0x6e, 0x33, 0x00, 0x20, 0x6d, 0x2e, 0x87, +0x00, 0x80, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, +0x54, 0x00, 0xe5, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x00, 0x70, +0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x57, 0x00, 0xf0, +0x0f, 0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x6e, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x73, 0x00, 0x73, 0x75, 0x63, 0x68, 0x00, +0x74, 0x68, 0x61, 0x74, 0x3a, 0x00, 0x00, 0x00, 0x2d, 0x00, +0x45, 0xb2, 0x00, 0x34, 0x72, 0x6f, 0x77, 0xab, 0x00, 0xf1, +0x05, 0x73, 0x00, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x6e, +0x65, 0x00, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, +0x63, 0xa5, 0x00, 0x01, 0xdb, 0x00, 0x02, 0xc6, 0x00, 0x05, +0x38, 0x00, 0x6f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3b, +0x00, 0x1d, 0x31, 0x41, 0x6c, 0x6c, 0x9c, 0x00, 0x07, 0xd7, +0x00, 0x00, 0x30, 0x01, 0xf1, 0x03, 0x73, 0x61, 0x74, 0x69, +0x73, 0x66, 0x69, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x00, 0x54, +0x68, 0x65, 0x72, 0x65, 0x17, 0x00, 0xf3, 0x0b, 0x74, 0x77, +0x6f, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x73, 0x00, 0x66, 0x6f, +0x72, 0x00, 0x74, 0x68, 0x69, 0x73, 0x00, 0x67, 0x61, 0x6d, +0x65, 0x2c, 0x00, 0x60, 0xa4, 0x01, 0x11, 0x27, 0x36, 0x01, +0xa0, 0x60, 0x41, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, +0x27, 0x3f, 0x00, 0x27, 0x49, 0x6e, 0x1f, 0x00, 0x00, 0x3e, +0x00, 0x1e, 0x2c, 0x72, 0x00, 0x00, 0x1d, 0x01, 0xf1, 0x0e, +0x65, 0x61, 0x74, 0x65, 0x72, 0x2d, 0x74, 0x68, 0x61, 0x6e, +0x00, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x00, 0x69, +0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0xca, +0x00, 0x02, 0x89, 0x01, 0x50, 0x27, 0x73, 0x00, 0x76, 0x61, +0x3d, 0x00, 0x24, 0x69, 0x73, 0x36, 0x00, 0x11, 0x00, 0x36, +0x00, 0xf0, 0x01, 0x69, 0x74, 0x73, 0x00, 0x6e, 0x65, 0x69, +0x67, 0x68, 0x62, 0x6f, 0x75, 0x72, 0x27, 0x73, 0x2e, 0x7a, +0x00, 0x01, 0xa4, 0x00, 0x00, 0x75, 0x00, 0x81, 0x00, 0x6e, +0x6f, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x78, 0x00, 0x11, 0x73, +0x11, 0x02, 0xf0, 0x18, 0x62, 0x65, 0x00, 0x76, 0x69, 0x73, +0x69, 0x62, 0x6c, 0x65, 0x2c, 0x00, 0x70, 0x61, 0x72, 0x74, +0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x6c, 0x79, 0x00, 0x61, +0x74, 0x00, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, 0x00, 0x64, +0x69, 0x66, 0x66, 0x17, 0x00, 0x94, 0x74, 0x79, 0x00, 0x6c, +0x65, 0x76, 0x65, 0x6c, 0x73, 0xd1, 0x00, 0x05, 0xe2, 0x00, +0x0f, 0xd2, 0x00, 0x07, 0x3f, 0x62, 0x61, 0x72, 0xc2, 0x00, +0x10, 0x90, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x6c, 0x78, 0x00, 0x03, 0x55, 0x00, 0x61, 0x00, 0x28, 0x69, +0x2e, 0x65, 0x2e, 0x31, 0x00, 0x03, 0x88, 0x00, 0x21, 0x6f, +0x72, 0x0e, 0x00, 0x6f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x29, +0xee, 0x00, 0x00, 0x0b, 0xec, 0x00, 0x06, 0xe8, 0x00, 0x20, +0x61, 0x72, 0x0e, 0x00, 0x44, 0x77, 0x61, 0x79, 0x73, 0xec, +0x00, 0x54, 0x3a, 0x00, 0x61, 0x62, 0x73, 0x0e, 0x02, 0x10, +0x61, 0xa6, 0x00, 0xb1, 0x00, 0x74, 0x68, 0x75, 0x73, 0x00, +0x6d, 0x65, 0x61, 0x6e, 0x73, 0x8d, 0x02, 0x2f, 0x00, 0x61, +0xa8, 0x00, 0x00, 0xa1, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, +0x74, 0x65, 0x6c, 0x79, 0x4a, 0x01, 0x0f, 0xb7, 0x00, 0x02, +0x22, 0x74, 0x6f, 0x40, 0x00, 0x09, 0x85, 0x01, 0x02, 0x30, +0x01, 0x50, 0x54, 0x72, 0x69, 0x76, 0x69, 0x01, 0x02, 0x0c, +0x52, 0x01, 0xa0, 0x00, 0x28, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x8e, 0x01, 0x11, 0x61, 0x49, 0x01, 0x81, +0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x27, 0x5d, 0x02, +0xf1, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, 0x00, 0x73, 0x65, +0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x29, 0x6b, 0x01, 0x03, +0x8f, 0x02, 0x2b, 0x6e, 0x6f, 0x37, 0x02, 0x01, 0x7c, 0x01, +0x1c, 0x69, 0x70, 0x02, 0x11, 0x3b, 0x55, 0x00, 0x63, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x9e, 0x03, 0x42, 0x73, 0x6f, +0x6c, 0x76, 0x95, 0x03, 0x10, 0x4c, 0x9d, 0x01, 0x04, 0x27, +0x04, 0x00, 0x34, 0x03, 0x00, 0xb2, 0x00, 0x21, 0x41, 0x74, +0x1c, 0x00, 0x31, 0x74, 0x69, 0x6d, 0x26, 0x01, 0x30, 0x77, +0x72, 0x69, 0xc2, 0x01, 0x02, 0xe6, 0x01, 0x0a, 0x5c, 0x00, +0x02, 0x33, 0x04, 0x27, 0x69, 0x73, 0x5f, 0x00, 0x60, 0x61, +0x70, 0x70, 0x65, 0x61, 0x72, 0xf2, 0x01, 0x21, 0x69, 0x6e, +0x32, 0x00, 0xf1, 0x06, 0x47, 0x75, 0x61, 0x72, 0x64, 0x69, +0x61, 0x6e, 0x00, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x00, +0x75, 0x6e, 0x64, 0x65, 0x72, 0x1a, 0x00, 0x10, 0x6e, 0xe0, +0x00, 0xa1, 0x60, 0x46, 0x75, 0x74, 0x6f, 0x73, 0x68, 0x69, +0x6b, 0x69, 0x2f, 0x03, 0x03, 0x5f, 0x00, 0x41, 0x00, 0x77, +0x61, 0x73, 0xcd, 0x03, 0x72, 0x72, 0x69, 0x62, 0x75, 0x74, +0x65, 0x64, 0x5d, 0x01, 0x20, 0x69, 0x73, 0xe8, 0x03, 0x00, +0x0b, 0x01, 0xf1, 0x03, 0x69, 0x6f, 0x6e, 0x00, 0x62, 0x79, +0x00, 0x4a, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, +0x76, 0x65, 0xba, 0x00, 0x45, 0x32, 0x37, 0x2e, 0x31, 0x31, +0x05, 0x01, 0x3f, 0x00, 0x47, 0x6f, 0x6c, 0x73, 0x20, 0x57, +0x00, 0x21, 0x73, 0x68, 0xcc, 0x04, 0x10, 0x6d, 0x7a, 0x04, +0x21, 0x6f, 0x66, 0x46, 0x02, 0x03, 0x27, 0x00, 0x72, 0x00, +0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0xa2, 0x04, 0x41, 0x53, +0x6f, 0x6c, 0x6f, 0xfc, 0x03, 0x64, 0x6f, 0x00, 0x70, 0x6c, +0x61, 0x79, 0x3f, 0x00, 0xe1, 0x2c, 0x00, 0x73, 0x69, 0x6d, +0x70, 0x6c, 0x79, 0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xc4, +0x00, 0x60, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x58, 0x05, +0x84, 0x6e, 0x79, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x4e, +0x01, 0x00, 0x0b, 0x04, 0x42, 0x74, 0x68, 0x65, 0x6e, 0xc2, +0x01, 0x04, 0x77, 0x05, 0x70, 0x6f, 0x72, 0x00, 0x6c, 0x65, +0x74, 0x74, 0xd5, 0x02, 0x02, 0x1f, 0x01, 0x81, 0x6b, 0x65, +0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x36, 0x05, 0x32, 0x69, +0x6c, 0x6c, 0x44, 0x02, 0x02, 0x44, 0x00, 0xc0, 0x2e, 0x00, +0x49, 0x66, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6d, 0x61, 0x6b, +0x43, 0x00, 0x8e, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, +0x2c, 0x80, 0x00, 0x02, 0x4c, 0x00, 0x98, 0x69, 0x6e, 0x63, +0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x84, 0x00, 0xb0, 0x70, +0x72, 0x65, 0x73, 0x73, 0x00, 0x53, 0x70, 0x61, 0x63, 0x65, +0x64, 0x00, 0xb0, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x69, +0x74, 0x00, 0x61, 0x67, 0x0f, 0x06, 0x62, 0x28, 0x6f, 0x72, +0x00, 0x75, 0x73, 0x0d, 0x02, 0xd1, 0x55, 0x6e, 0x64, 0x6f, +0x00, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x29, 0xbb, +0x02, 0x02, 0x7e, 0x00, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, +0x2d, 0x74, 0x00, 0x01, 0x42, 0x06, 0x0f, 0xe2, 0x00, 0x04, +0x02, 0xd8, 0x05, 0x13, 0x2c, 0x06, 0x03, 0x01, 0x0d, 0x00, +0x20, 0x00, 0x77, 0xd3, 0x00, 0xa4, 0x62, 0x65, 0x00, 0x65, +0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0xaa, 0x00, 0x04, 0x42, +0x00, 0xf1, 0x03, 0x73, 0x00, 0x61, 0x00, 0x60, 0x70, 0x65, +0x6e, 0x63, 0x69, 0x6c, 0x00, 0x6d, 0x61, 0x72, 0x6b, 0x27, +0x2e, 0xd1, 0x06, 0x32, 0x63, 0x61, 0x6e, 0x70, 0x06, 0x07, +0x1b, 0x00, 0x02, 0x76, 0x05, 0x85, 0x6d, 0x75, 0x6c, 0x74, +0x69, 0x70, 0x6c, 0x65, 0x45, 0x06, 0x04, 0x51, 0x00, 0x00, +0x4c, 0x02, 0x04, 0x36, 0x01, 0x13, 0x53, 0xb3, 0x06, 0x03, +0x0e, 0x06, 0x00, 0x8d, 0x02, 0x00, 0x5b, 0x01, 0x55, 0x65, +0x64, 0x2d, 0x69, 0x6e, 0x39, 0x00, 0x32, 0x63, 0x61, 0x6e, +0x15, 0x05, 0x25, 0x73, 0x6f, 0x1d, 0x07, 0x08, 0x6f, 0x00, +0x03, 0xfc, 0x05, 0x02, 0x86, 0x03, 0x10, 0x70, 0x43, 0x04, +0x81, 0x6e, 0x6f, 0x00, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x7e, +0x02, 0x29, 0x74, 0x6f, 0x2e, 0x00, 0xe0, 0x2c, 0x00, 0x73, +0x6f, 0x00, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x00, +0x77, 0x01, 0x01, 0x00, 0x3a, 0x01, 0x03, 0x5a, 0x01, 0x11, +0x6d, 0xbb, 0x00, 0x50, 0x69, 0x73, 0x00, 0x75, 0x70, 0x38, +0x00, 0x63, 0x79, 0x6f, 0x75, 0x3a, 0x00, 0x79, 0xe7, 0x00, +0x05, 0x23, 0x00, 0x70, 0x61, 0x73, 0x00, 0x72, 0x65, 0x6d, +0x69, 0x1e, 0x03, 0x05, 0x89, 0x04, 0x06, 0x98, 0x05, 0x04, +0x32, 0x01, 0x41, 0x6e, 0x65, 0x65, 0x64, 0xc4, 0x03, 0xf0, +0x01, 0x62, 0x65, 0x00, 0x72, 0x65, 0x2d, 0x65, 0x78, 0x61, +0x6d, 0x69, 0x6e, 0x65, 0x64, 0x00, 0x6f, 0xd3, 0x04, 0x00, +0x54, 0x00, 0x70, 0x6b, 0x6e, 0x6f, 0x77, 0x00, 0x6d, 0x6f, +0x5d, 0x01, 0x3b, 0x62, 0x6f, 0x75, 0x45, 0x00, 0x04, 0xa2, +0x01, 0x2f, 0x6f, 0x72, 0x80, 0x00, 0x02, 0x54, 0x6c, 0x69, +0x73, 0x74, 0x73, 0x07, 0x08, 0x31, 0x70, 0x6f, 0x73, 0x32, +0x05, 0x08, 0x6a, 0x01, 0x64, 0x61, 0x00, 0x67, 0x69, 0x76, +0x65, 0x31, 0x04, 0x01, 0x48, 0x00, 0x50, 0x61, 0x6e, 0x79, +0x74, 0x68, 0x62, 0x01, 0x32, 0x65, 0x6c, 0x73, 0x82, 0x00, +0x93, 0x66, 0x65, 0x65, 0x6c, 0x00, 0x6c, 0x69, 0x6b, 0x65, +0x42, 0x03, 0x41, 0x65, 0x72, 0x61, 0x73, 0x9f, 0x08, 0x49, +0x69, 0x6e, 0x67, 0x6c, 0xd3, 0x01, 0x1c, 0x2c, 0x5b, 0x02, +0x08, 0x1b, 0x02, 0x22, 0x6e, 0x64, 0x58, 0x02, 0x05, 0xde, +0x01, 0x03, 0x52, 0x02, 0x01, 0xb8, 0x02, 0x01, 0xa7, 0x04, +0x2a, 0x6c, 0x6c, 0x20, 0x02, 0x09, 0x9c, 0x02, 0x22, 0x72, +0x65, 0x79, 0x00, 0x30, 0x64, 0x00, 0x77, 0xa3, 0x02, 0x00, +0x99, 0x00, 0x34, 0x6c, 0x65, 0x66, 0x6c, 0x00, 0x05, 0x5e, +0x00, 0x18, 0x61, 0x14, 0x01, 0x0f, 0x2a, 0x00, 0x05, 0x02, +0x43, 0x03, 0x10, 0x73, 0x43, 0x03, 0x36, 0x2e, 0x00, 0x52, +0xb3, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x20, 0x00, 0x00, 0x0d, +0x00, 0x01, 0x23, 0x00, 0x02, 0xf4, 0x02, 0x01, 0x58, 0x02, +0x02, 0xfb, 0x00, 0x0c, 0x56, 0x02, 0x12, 0x41, 0xcb, 0x02, +0x00, 0x65, 0x04, 0x03, 0x3b, 0x07, 0x50, 0x75, 0x72, 0x73, +0x6f, 0x72, 0x0b, 0x04, 0x01, 0x97, 0x02, 0x00, 0xdc, 0x01, +0x22, 0x75, 0x73, 0x2d, 0x03, 0x62, 0x63, 0x6f, 0x6e, 0x6a, +0x75, 0x6e, 0xf1, 0x04, 0x01, 0x9b, 0x04, 0x00, 0x30, 0x00, +0x02, 0x4b, 0x04, 0x01, 0x2f, 0x00, 0x00, 0xce, 0x05, 0x25, +0x65, 0x74, 0xa4, 0x01, 0x2b, 0x6f, 0x72, 0x6e, 0x00, 0x04, +0x4e, 0x03, 0x01, 0x8f, 0x00, 0x04, 0xe9, 0x03, 0x30, 0x60, +0x4d, 0x27, 0x3e, 0x00, 0x00, 0x3d, 0x00, 0x51, 0x61, 0x75, +0x74, 0x6f, 0x2d, 0x78, 0x04, 0x54, 0x65, 0x76, 0x65, 0x72, +0x79, 0xda, 0x06, 0xc1, 0x00, 0x68, 0x69, 0x6e, 0x74, 0x2c, +0x00, 0x72, 0x65, 0x61, 0x64, 0x79, 0xad, 0x00, 0x72, 0x72, +0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0xa6, 0x02, 0x61, 0x71, +0x75, 0x69, 0x72, 0x65, 0x64, 0x33, 0x01, 0x01, 0x4f, 0x00, +0x15, 0x48, 0x4f, 0x00, 0x26, 0x64, 0x6f, 0xb0, 0x01, 0x23, +0x62, 0x75, 0x5e, 0x03, 0x22, 0x74, 0x6f, 0x3f, 0x00, 0x02, +0x9a, 0x07, 0x71, 0x6f, 0x62, 0x76, 0x69, 0x6f, 0x75, 0x73, +0x62, 0x00, 0x12, 0x73, 0xc8, 0x01, 0xc5, 0x74, 0x65, 0x72, +0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x2c, 0xa5, +0x00, 0x08, 0x15, 0x01, 0x10, 0x74, 0x79, 0x09, 0x03, 0xb3, +0x06, 0x00, 0xd9, 0x00, 0x75, 0x00, 0x61, 0x72, 0x6f, 0x75, +0x6e, 0x64, 0x58, 0x0a, 0x34, 0x2e, 0x00, 0x50, 0x83, 0x01, +0x20, 0x74, 0x68, 0x19, 0x03, 0x43, 0x74, 0x75, 0x72, 0x6e, +0x94, 0x00, 0x56, 0x67, 0x67, 0x6c, 0x65, 0x73, 0x3a, 0x00, +0x11, 0x28, 0xf9, 0x0a, 0x72, 0x61, 0x00, 0x6e, 0x6f, 0x72, +0x6d, 0x61, 0x27, 0x01, 0x01, 0x08, 0x01, 0x08, 0x38, 0x01, +0x24, 0x29, 0x2c, 0x21, 0x02, 0x01, 0xe2, 0x01, 0x04, 0x7a, +0x02, 0x20, 0x69, 0x6e, 0xc4, 0x03, 0x0f, 0xca, 0x04, 0x03, +0x03, 0x0e, 0x00, 0x80, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, +0x72, 0x69, 0xf5, 0x0a, 0x44, 0x77, 0x61, 0x79, 0x3b, 0x44, +0x00, 0x01, 0x9b, 0x02, 0x21, 0x30, 0x00, 0x6d, 0x05, 0x04, +0xa6, 0x00, 0x02, 0x2d, 0x02, 0x23, 0x62, 0x61, 0x25, 0x05, +0x02, 0x99, 0x05, 0x13, 0x61, 0xaa, 0x04, 0x05, 0xcc, 0x04, +0x58, 0x00, 0x00, 0x4c, 0x65, 0x66, 0x70, 0x02, 0x02, 0x69, +0x09, 0x01, 0x33, 0x00, 0x01, 0xbd, 0x00, 0x20, 0x69, 0x74, +0x95, 0x01, 0x10, 0x64, 0x21, 0x09, 0x60, 0x28, 0x67, 0x72, +0x65, 0x79, 0x00, 0x66, 0x06, 0x41, 0x75, 0x74, 0x29, 0x2c, +0x6e, 0x00, 0x14, 0x6e, 0x24, 0x00, 0x10, 0x69, 0xee, 0x06, +0x01, 0xa1, 0x07, 0x12, 0x6c, 0xd6, 0x01, 0x00, 0x19, 0x00, +0x00, 0xe2, 0x0a, 0x40, 0x48, 0x6f, 0x6c, 0x64, 0x59, 0x00, +0x13, 0x43, 0x08, 0x07, 0x00, 0x9a, 0x02, 0x4a, 0x68, 0x69, +0x66, 0x74, 0xda, 0x02, 0x00, 0x43, 0x02, 0x10, 0x72, 0x9d, +0x0b, 0x00, 0x55, 0x01, 0x00, 0xdd, 0x03, 0x43, 0x77, 0x69, +0x73, 0x65, 0x78, 0x03, 0x00, 0xfb, 0x06, 0x01, 0x95, 0x00, +0x0a, 0x0b, 0x09, 0x05, 0xc3, 0x01, 0x03, 0x1c, 0x01, 0x02, +0x3b, 0x04, 0x32, 0x64, 0x69, 0x72, 0xc0, 0x07, 0x00, 0xdb, +0x00, 0x14, 0x28, 0x81, 0x0b, 0x11, 0x61, 0x13, 0x00, 0x00, +0x68, 0x09, 0x52, 0x73, 0x63, 0x72, 0x69, 0x62, 0x5f, 0x01, +0x13, 0x73, 0xe9, 0x07, 0x33, 0x32, 0x2e, 0x31, 0xca, 0x09, +0x35, 0x73, 0x6f, 0x00, 0x30, 0x09, 0x22, 0x2e, 0x29, 0xf1, +0x07, 0x15, 0x32, 0xf1, 0x07, 0xb2, 0x70, 0x61, 0x72, 0x61, +0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0xbc, 0x05, 0x00, +0x7c, 0x03, 0x05, 0x14, 0x00, 0x02, 0x43, 0x00, 0x05, 0x6e, +0x09, 0x01, 0x07, 0x02, 0x07, 0x6f, 0x09, 0x71, 0x2e, 0x2e, +0x2e, 0x27, 0x00, 0x6f, 0x70, 0x71, 0x00, 0x03, 0x9b, 0x07, +0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, +0x6e, 0x75, 0xad, 0x00, 0x10, 0x4d, 0xf1, 0x08, 0x03, 0x07, +0x00, 0x28, 0x6f, 0x66, 0x56, 0x09, 0x16, 0x28, 0x16, 0x09, +0x27, 0x6f, 0x72, 0x1e, 0x0b, 0x00, 0xa2, 0x00, 0x94, 0x53, +0x69, 0x7a, 0x65, 0x20, 0x28, 0x73, 0x2a, 0x73, 0x0d, 0x00, +0x00, 0x3c, 0x00, 0x02, 0xb4, 0x02, 0x36, 0x00, 0x00, 0x44, +0x0f, 0x0a, 0x14, 0x00, 0x81, 0x01, 0x02, 0xac, 0x02, 0x07, +0x29, 0x0a, 0x04, 0x97, 0x0d, 0x50, 0x65, 0x6e, 0x65, 0x72, +0x61, 0x0c, 0x09, 0x02, 0x76, 0x00, 0x10, 0x2e, 0xa8, 0x09, +0x03, 0x59, 0x0a, 0x02, 0x4d, 0x0a, 0x0f, 0x1d, 0x0a, 0x0e, +0x0f, 0x0b, 0x0a, 0x1d, 0x50, 0x41, 0x74, 0x00, 0x52, 0x65, +0xc5, 0x01, 0x34, 0x69, 0x76, 0x65, 0xb0, 0x0a, 0x01, 0x59, +0x0d, 0x0f, 0xb5, 0x0a, 0x1b, 0x82, 0x00, 0x62, 0x61, 0x63, +0x6b, 0x74, 0x72, 0x61, 0xc1, 0x02, 0x04, 0x12, 0x08, 0x06, +0x47, 0x04, 0x00, 0x29, 0x04, 0x01, 0x11, 0x03, 0x31, 0x6f, +0x6c, 0x75, 0x80, 0x01, 0x93, 0x73, 0x68, 0x6f, 0x75, 0x6c, +0x64, 0x00, 0x73, 0x74, 0x2b, 0x00, 0x71, 0x75, 0x6e, 0x69, +0x71, 0x75, 0x65, 0x2e, 0x8f, 0x07, 0x02, 0x89, 0x0c, 0x00, +0x1f, 0x02, 0x04, 0x81, 0x0e, 0x03, 0x49, 0x00, 0x00, 0xfe, +0x08, 0x31, 0x72, 0x65, 0x61, 0x66, 0x06, 0x00, 0xef, 0x0e, +0x60, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x00, 0x12, 0x00, 0x21, +0x6f, 0x6e, 0x73, 0x03, 0x00, 0x3c, 0x02, 0x30, 0x6f, 0x69, +0x64, 0x59, 0x08, 0x03, 0x10, 0x00, 0xb0, 0x62, 0x61, 0x63, +0x6b, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x2e, 0x00, }; -const unsigned short help_text_len = 3934; -const unsigned short help_text_words = 730; +const unsigned short help_text_len = 3954; +const unsigned short help_text_words = 731; const char quick_help_text[] = "Complete the latin square in accordance with the > signs."; diff --git a/apps/plugins/puzzles/help/unruly.c b/apps/plugins/puzzles/help/unruly.c index b098642a72..39249c5949 100644 --- a/apps/plugins/puzzles/help/unruly.c +++ b/apps/plugins/puzzles/help/unruly.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,142 +6,143 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 99, TEXT_CENTER | C_RED }, - { 221, TEXT_CENTER | C_RED }, - { 238, TEXT_UNDERLINE }, + { 100, TEXT_CENTER | C_RED }, + { 222, TEXT_CENTER | C_RED }, { 239, TEXT_UNDERLINE }, - { 266, TEXT_UNDERLINE }, - { 278, TEXT_UNDERLINE }, + { 240, TEXT_UNDERLINE }, + { 267, TEXT_UNDERLINE }, + { 279, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 1688 comp 1225 ratio 0.725711 level 10 saved 463 */ +/* orig 1707 comp 1231 ratio 0.721148 level 10 saved 476 */ const char help_text[] = { -0xf0, 0x4d, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x33, 0x38, 0x3a, 0x20, 0x55, 0x6e, 0x72, 0x75, 0x6c, 0x79, -0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, -0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, -0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, -0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, -0x63, 0x68, 0x00, 0x79, 0x6f, 0x75, 0x00, 0x6d, 0x75, 0x73, -0x74, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x00, 0x65, -0x69, 0x74, 0x68, 0x65, 0x72, 0x00, 0x62, 0x6c, 0x61, 0x63, -0x6b, 0x00, 0x6f, 0x72, 0x26, 0x00, 0x84, 0x74, 0x65, 0x2e, -0x00, 0x53, 0x6f, 0x6d, 0x65, 0x3b, 0x00, 0x01, 0x57, 0x00, -0xf1, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, -0x00, 0x61, 0x73, 0x00, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x3b, -0x00, 0x74, 0x68, 0x65, 0x00, 0x72, 0x65, 0x73, 0x74, 0x20, -0x00, 0x81, 0x6c, 0x65, 0x66, 0x74, 0x00, 0x66, 0x6f, 0x72, -0x61, 0x00, 0xf0, 0x09, 0x74, 0x6f, 0x00, 0x66, 0x69, 0x6c, -0x6c, 0x00, 0x69, 0x6e, 0x2e, 0x00, 0x45, 0x61, 0x63, 0x68, -0x00, 0x72, 0x6f, 0x77, 0x00, 0x61, 0x6e, 0x64, 0x75, 0x00, -0x34, 0x75, 0x6d, 0x6e, 0x81, 0x00, 0x51, 0x6e, 0x74, 0x61, -0x69, 0x6e, 0x47, 0x00, 0xb0, 0x73, 0x61, 0x6d, 0x65, 0x00, -0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xb4, 0x00, 0x02, 0x8e, -0x00, 0x00, 0x31, 0x00, 0x01, 0x8f, 0x00, 0x06, 0xc4, 0x00, -0x00, 0x13, 0x00, 0x21, 0x6e, 0x6f, 0x4f, 0x00, 0x25, 0x6f, -0x72, 0x4e, 0x00, 0x27, 0x61, 0x79, 0x4d, 0x00, 0x30, 0x72, -0x65, 0x65, 0x0e, 0x00, 0x76, 0x73, 0x65, 0x63, 0x75, 0x74, -0x69, 0x76, 0xc5, 0x00, 0x26, 0x6f, 0x66, 0x6a, 0x00, 0x02, -0xfc, 0x00, 0xf1, 0x2d, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, -0x69, 0x73, 0x00, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, -0x74, 0x79, 0x70, 0x65, 0x00, 0x77, 0x61, 0x73, 0x00, 0x69, -0x6e, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x00, 0x62, 0x79, -0x00, 0x41, 0x64, 0x6f, 0x6c, 0x66, 0x6f, 0x00, 0x5a, 0x61, -0x6e, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x2c, 0x00, 0x75, -0x6e, 0x64, 0x65, 0x72, 0x4c, 0x00, 0x10, 0x6e, 0x4c, 0x00, -0xf1, 0x09, 0x60, 0x54, 0x6f, 0x68, 0x75, 0x00, 0x77, 0x61, -0x00, 0x56, 0x6f, 0x68, 0x75, 0x27, 0x2e, 0x00, 0x53, 0x65, -0x65, 0x00, 0x5b, 0x32, 0x31, 0x5d, 0x0d, 0x01, 0xc0, 0x6d, -0x6f, 0x72, 0x65, 0x00, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, -0x73, 0x6f, 0x00, 0x02, 0xaf, 0x01, 0x01, 0x65, 0x00, 0x00, -0xb2, 0x00, 0x40, 0x72, 0x69, 0x62, 0x75, 0x68, 0x00, 0x60, -0x74, 0x6f, 0x00, 0x74, 0x68, 0x69, 0x14, 0x00, 0x80, 0x6c, -0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x7b, 0x00, 0xe0, -0x4c, 0x65, 0x6e, 0x6e, 0x61, 0x72, 0x64, 0x00, 0x53, 0x70, -0x72, 0x6f, 0x6e, 0x67, 0x3f, 0x00, 0x01, 0x58, 0x00, 0xf0, -0x0d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, -0x77, 0x2e, 0x6a, 0x61, 0x6e, 0x6b, 0x6f, 0x2e, 0x61, 0x74, -0x2f, 0x52, 0x61, 0x65, 0x74, 0x73, 0x65, 0x6c, 0x2f, 0x8c, -0x00, 0x40, 0x2d, 0x57, 0x61, 0x2d, 0x8c, 0x00, 0xf4, 0x02, -0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, -0x00, 0x00, 0x00, 0x33, 0x38, 0x2e, 0x31, 0x2d, 0x02, 0x01, -0x7a, 0x00, 0x40, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x01, 0x63, -0x6f, 0x00, 0x70, 0x6c, 0x61, 0x79, 0x99, 0x00, 0x71, 0x2c, -0x00, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0xdd, 0x00, 0x70, 0x6d, -0x6f, 0x75, 0x73, 0x65, 0x00, 0x69, 0x4b, 0x02, 0x02, 0x43, -0x01, 0x00, 0xa6, 0x00, 0xa5, 0x63, 0x68, 0x61, 0x6e, 0x67, -0x65, 0x00, 0x69, 0x74, 0x73, 0x44, 0x01, 0x51, 0x4c, 0x65, -0x66, 0x74, 0x2d, 0x37, 0x00, 0xc4, 0x69, 0x6e, 0x67, 0x00, -0x61, 0x6e, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x34, 0x00, -0x10, 0x77, 0x07, 0x02, 0x72, 0x74, 0x75, 0x72, 0x6e, 0x00, -0x69, 0x74, 0xd7, 0x01, 0x02, 0xc5, 0x01, 0x47, 0x72, 0x69, -0x67, 0x68, 0x37, 0x00, 0x09, 0x27, 0x00, 0x03, 0x83, 0x02, -0x55, 0x4b, 0x65, 0x65, 0x70, 0x00, 0x22, 0x00, 0x05, 0xbc, -0x01, 0x61, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x8d, 0x00, -0x40, 0x79, 0x63, 0x6c, 0x65, 0xf2, 0x01, 0x41, 0x6f, 0x75, -0x67, 0x68, 0x21, 0x00, 0x02, 0xfe, 0x01, 0xf1, 0x00, 0x70, -0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x00, 0x73, 0x74, -0x61, 0x74, 0x65, 0x73, 0x89, 0x01, 0x24, 0x74, 0x68, 0x0a, -0x02, 0x42, 0x2e, 0x00, 0x49, 0x66, 0x06, 0x03, 0x52, 0x69, -0x64, 0x64, 0x6c, 0x65, 0x84, 0x00, 0x09, 0xe8, 0x00, 0x22, -0x69, 0x74, 0x90, 0x00, 0x11, 0x62, 0xdf, 0x02, 0x20, 0x65, -0x74, 0x6c, 0x00, 0x01, 0xd5, 0x00, 0x13, 0x2e, 0x67, 0x03, -0x90, 0x63, 0x61, 0x6e, 0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, -0x22, 0x01, 0x00, 0x5a, 0x00, 0xb0, 0x63, 0x75, 0x72, 0x73, -0x6f, 0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x2d, 0x00, 0xb1, -0x6d, 0x6f, 0x76, 0x65, 0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, -0x64, 0x1f, 0x00, 0x00, 0x8b, 0x03, 0x74, 0x2e, 0x00, 0x50, -0x72, 0x65, 0x73, 0x73, 0xcb, 0x00, 0x21, 0x72, 0x65, 0xee, -0x00, 0x82, 0x6f, 0x72, 0x00, 0x73, 0x70, 0x61, 0x63, 0x65, -0x3b, 0x00, 0x06, 0x06, 0x01, 0x0c, 0x47, 0x01, 0x0a, 0x9f, -0x03, 0x00, 0x97, 0x00, 0x30, 0x70, 0x65, 0x63, 0xdf, 0x02, -0x52, 0x6c, 0x79, 0x00, 0x28, 0x61, 0x67, 0x00, 0x15, 0x6e, -0x11, 0x01, 0x04, 0xe1, 0x02, 0x28, 0x73, 0x00, 0x5f, 0x03, -0x30, 0x77, 0x61, 0x79, 0xbd, 0x03, 0x06, 0xdc, 0x01, 0x02, -0x4a, 0x01, 0x22, 0x73, 0x29, 0x92, 0x01, 0x14, 0x70, 0x9f, -0x00, 0x42, 0x42, 0x61, 0x63, 0x6b, 0x95, 0x00, 0x01, 0x90, -0x00, 0x02, 0x03, 0x01, 0x08, 0x05, 0x02, 0x05, 0x0c, 0x01, -0x41, 0x28, 0x41, 0x6c, 0x6c, 0x50, 0x00, 0x11, 0x61, 0xb4, -0x02, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, -0x62, 0x65, 0x64, 0x79, 0x00, 0x13, 0x73, 0xca, 0x02, 0x31, -0x32, 0x2e, 0x31, 0x22, 0x04, 0x01, 0x32, 0x01, 0xb2, 0x61, -0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, -0x96, 0x02, 0x14, 0x32, 0x96, 0x02, 0x92, 0x70, 0x61, 0x72, -0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x98, 0x02, 0x56, 0x68, -0x65, 0x73, 0x65, 0x00, 0x14, 0x00, 0x02, 0x42, 0x00, 0x04, -0x3d, 0x00, 0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x7a, 0x00, -0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, -0x2e, 0x27, 0x00, 0x6f, 0x70, 0x70, 0x00, 0x22, 0x6f, 0x6e, -0x1a, 0x00, 0xa0, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, -0x65, 0x6e, 0x75, 0xac, 0x00, 0x90, 0x57, 0x69, 0x64, 0x74, -0x68, 0x2c, 0x00, 0x48, 0x65, 0x79, 0x02, 0x70, 0x00, 0x00, -0x00, 0x53, 0x69, 0x7a, 0x65, 0x14, 0x04, 0x01, 0x27, 0x05, -0x24, 0x69, 0x6e, 0x27, 0x04, 0x60, 0x2e, 0x00, 0x28, 0x4e, -0x6f, 0x74, 0x45, 0x01, 0x22, 0x61, 0x74, 0xa9, 0x01, 0x26, -0x75, 0x6c, 0x3d, 0x04, 0x30, 0x67, 0x61, 0x6d, 0x7d, 0x01, -0x30, 0x71, 0x75, 0x69, 0x94, 0x01, 0x22, 0x6f, 0x74, 0x76, -0x02, 0x10, 0x77, 0x5b, 0x00, 0x01, 0x44, 0x01, 0x12, 0x68, -0x5e, 0x00, 0x20, 0x74, 0x6f, 0x3c, 0x02, 0x10, 0x65, 0x88, -0x05, 0x02, 0xd4, 0x04, 0x11, 0x73, 0xee, 0x00, 0xe3, 0x44, -0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x00, -0x00, 0x00, 0x43, 0x85, 0x03, 0x01, 0x42, 0x00, 0x16, 0x64, -0x1a, 0x00, 0x04, 0x6a, 0x00, 0x50, 0x65, 0x6e, 0x65, 0x72, -0x61, 0x1c, 0x04, 0x02, 0x9d, 0x04, 0x02, 0x3d, 0x04, 0xe2, -0x69, 0x71, 0x75, 0x65, 0x20, 0x72, 0x6f, 0x77, 0x73, 0x20, -0x61, 0x6e, 0x64, 0x20, 0xff, 0x04, 0x30, 0x73, 0x00, 0x00, -0xd2, 0x02, 0x20, 0x65, 0x6e, 0x19, 0x01, 0x20, 0x64, 0x2c, -0x1f, 0x05, 0x21, 0x74, 0x77, 0x23, 0x05, 0x03, 0xb9, 0x05, -0x53, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x66, 0x04, 0xc6, 0x68, -0x61, 0x76, 0x65, 0x00, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, -0x79, 0x1a, 0x02, 0x72, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, -0x6e, 0x08, 0x02, 0x83, 0x6c, 0x69, 0x6b, 0x65, 0x77, 0x69, -0x73, 0x65, 0x5e, 0x05, 0x00, 0x12, 0x01, 0x15, 0x41, 0xc0, -0x05, 0x14, 0x61, 0x74, 0x05, 0x20, 0x63, 0x61, 0x78, 0x05, -0xe0, 0x74, 0x63, 0x68, 0x2c, 0x00, 0x74, 0x68, 0x6f, 0x75, -0x67, 0x68, 0x2e, 0x29, 0x00, +0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x3a, 0x00, 0x00, 0x00, +0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69, +0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64, +0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x73, 0x2c, 0x00, 0x77, 0x68, 0x69, 0x63, 0x68, 0x00, 0x79, +0x6f, 0x75, 0x00, 0x6d, 0x75, 0x73, 0x74, 0x00, 0x63, 0x6f, +0x6c, 0x6f, 0x75, 0x72, 0x00, 0x65, 0x69, 0x74, 0x68, 0x65, +0x72, 0x00, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x00, 0x6f, 0x72, +0x26, 0x00, 0x84, 0x74, 0x65, 0x2e, 0x00, 0x53, 0x6f, 0x6d, +0x65, 0x3b, 0x00, 0x01, 0x57, 0x00, 0xf1, 0x0c, 0x70, 0x72, +0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x00, 0x61, 0x73, 0x00, +0x63, 0x6c, 0x75, 0x65, 0x73, 0x3b, 0x00, 0x74, 0x68, 0x65, +0x00, 0x72, 0x65, 0x73, 0x74, 0x20, 0x00, 0x81, 0x6c, 0x65, +0x66, 0x74, 0x00, 0x66, 0x6f, 0x72, 0x61, 0x00, 0xf0, 0x09, +0x74, 0x6f, 0x00, 0x66, 0x69, 0x6c, 0x6c, 0x00, 0x69, 0x6e, +0x2e, 0x00, 0x45, 0x61, 0x63, 0x68, 0x00, 0x72, 0x6f, 0x77, +0x00, 0x61, 0x6e, 0x64, 0x75, 0x00, 0x34, 0x75, 0x6d, 0x6e, +0x81, 0x00, 0x51, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x47, 0x00, +0xb0, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x6e, 0x75, 0x6d, 0x62, +0x65, 0x72, 0xb4, 0x00, 0x02, 0x8e, 0x00, 0x00, 0x31, 0x00, +0x01, 0x8f, 0x00, 0x06, 0xc4, 0x00, 0x00, 0x13, 0x00, 0x21, +0x6e, 0x6f, 0x4f, 0x00, 0x25, 0x6f, 0x72, 0x4e, 0x00, 0x27, +0x61, 0x79, 0x4d, 0x00, 0x30, 0x72, 0x65, 0x65, 0x0e, 0x00, +0x76, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0xc5, 0x00, +0x26, 0x6f, 0x66, 0x6a, 0x00, 0x02, 0xfc, 0x00, 0xf1, 0x2d, +0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x00, 0x70, +0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x00, 0x74, 0x79, 0x70, 0x65, +0x00, 0x77, 0x61, 0x73, 0x00, 0x69, 0x6e, 0x76, 0x65, 0x6e, +0x74, 0x65, 0x64, 0x00, 0x62, 0x79, 0x00, 0x41, 0x64, 0x6f, +0x6c, 0x66, 0x6f, 0x00, 0x5a, 0x61, 0x6e, 0x65, 0x6c, 0x6c, +0x61, 0x74, 0x69, 0x2c, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, +0x4c, 0x00, 0x10, 0x6e, 0x4c, 0x00, 0xf1, 0x09, 0x60, 0x54, +0x6f, 0x68, 0x75, 0x00, 0x77, 0x61, 0x00, 0x56, 0x6f, 0x68, +0x75, 0x27, 0x2e, 0x00, 0x53, 0x65, 0x65, 0x00, 0x5b, 0x32, +0x31, 0x5d, 0x0d, 0x01, 0xc0, 0x6d, 0x6f, 0x72, 0x65, 0x00, +0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x6f, 0x00, 0x02, +0xc2, 0x01, 0x01, 0x65, 0x00, 0x00, 0xb2, 0x00, 0x40, 0x72, +0x69, 0x62, 0x75, 0x68, 0x00, 0x60, 0x74, 0x6f, 0x00, 0x74, +0x68, 0x69, 0x14, 0x00, 0x80, 0x6c, 0x6c, 0x65, 0x63, 0x74, +0x69, 0x6f, 0x6e, 0x7b, 0x00, 0xe0, 0x4c, 0x65, 0x6e, 0x6e, +0x61, 0x72, 0x64, 0x00, 0x53, 0x70, 0x72, 0x6f, 0x6e, 0x67, +0x3f, 0x00, 0x01, 0x58, 0x00, 0xf0, 0x0d, 0x68, 0x74, 0x74, +0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6a, 0x61, +0x6e, 0x6b, 0x6f, 0x2e, 0x61, 0x74, 0x2f, 0x52, 0x61, 0x65, +0x74, 0x73, 0x65, 0x6c, 0x2f, 0x8c, 0x00, 0x40, 0x2d, 0x57, +0x61, 0x2d, 0x8c, 0x00, 0xf4, 0x02, 0x2f, 0x69, 0x6e, 0x64, +0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0x00, 0x00, 0x33, +0x38, 0x2e, 0x31, 0x40, 0x02, 0x01, 0x7a, 0x00, 0x40, 0x6f, +0x6c, 0x73, 0x20, 0x00, 0x01, 0x63, 0x6f, 0x00, 0x70, 0x6c, +0x61, 0x79, 0x99, 0x00, 0x71, 0x2c, 0x00, 0x63, 0x6c, 0x69, +0x63, 0x6b, 0xdd, 0x00, 0x70, 0x6d, 0x6f, 0x75, 0x73, 0x65, +0x00, 0x69, 0x4b, 0x02, 0x02, 0x43, 0x01, 0x00, 0xa6, 0x00, +0xa5, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x69, 0x74, +0x73, 0x44, 0x01, 0x51, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x37, +0x00, 0xc4, 0x69, 0x6e, 0x67, 0x00, 0x61, 0x6e, 0x00, 0x65, +0x6d, 0x70, 0x74, 0x79, 0x34, 0x00, 0x10, 0x77, 0x07, 0x02, +0x72, 0x74, 0x75, 0x72, 0x6e, 0x00, 0x69, 0x74, 0xd7, 0x01, +0x02, 0xc5, 0x01, 0x47, 0x72, 0x69, 0x67, 0x68, 0x37, 0x00, +0x09, 0x27, 0x00, 0x03, 0x83, 0x02, 0x55, 0x4b, 0x65, 0x65, +0x70, 0x00, 0x22, 0x00, 0x05, 0xbc, 0x01, 0x61, 0x62, 0x75, +0x74, 0x74, 0x6f, 0x6e, 0x8d, 0x00, 0x40, 0x79, 0x63, 0x6c, +0x65, 0xf2, 0x01, 0x41, 0x6f, 0x75, 0x67, 0x68, 0x21, 0x00, +0x02, 0xfe, 0x01, 0xf1, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, +0x62, 0x6c, 0x65, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, +0x89, 0x01, 0x24, 0x74, 0x68, 0x0a, 0x02, 0x42, 0x2e, 0x00, +0x49, 0x66, 0x06, 0x03, 0x52, 0x69, 0x64, 0x64, 0x6c, 0x65, +0x84, 0x00, 0x09, 0xe8, 0x00, 0x22, 0x69, 0x74, 0x90, 0x00, +0x11, 0x62, 0xdf, 0x02, 0x20, 0x65, 0x74, 0x6c, 0x00, 0x01, +0xd5, 0x00, 0x13, 0x2e, 0x67, 0x03, 0x90, 0x63, 0x61, 0x6e, +0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x22, 0x01, 0x00, 0x5a, +0x00, 0xb0, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x00, 0x6b, +0x65, 0x79, 0x73, 0x2d, 0x00, 0xb1, 0x6d, 0x6f, 0x76, 0x65, +0x00, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x1f, 0x00, 0x00, +0x8b, 0x03, 0x74, 0x2e, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73, +0xcb, 0x00, 0x21, 0x72, 0x65, 0xee, 0x00, 0x82, 0x6f, 0x72, +0x00, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x00, 0x06, 0x06, +0x01, 0x0c, 0x47, 0x01, 0x0a, 0x9f, 0x03, 0x00, 0x97, 0x00, +0x30, 0x70, 0x65, 0x63, 0xdf, 0x02, 0x52, 0x6c, 0x79, 0x00, +0x28, 0x61, 0x67, 0x00, 0x15, 0x6e, 0x11, 0x01, 0x04, 0xe1, +0x02, 0x28, 0x73, 0x00, 0x5f, 0x03, 0x30, 0x77, 0x61, 0x79, +0xbd, 0x03, 0x06, 0xdc, 0x01, 0x02, 0x4a, 0x01, 0x22, 0x73, +0x29, 0x92, 0x01, 0x14, 0x70, 0x9f, 0x00, 0x42, 0x42, 0x61, +0x63, 0x6b, 0x95, 0x00, 0x01, 0x90, 0x00, 0x02, 0x03, 0x01, +0x08, 0x05, 0x02, 0x05, 0x0c, 0x01, 0x41, 0x28, 0x41, 0x6c, +0x6c, 0x50, 0x00, 0x11, 0x61, 0xb4, 0x02, 0xb0, 0x73, 0x00, +0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x79, +0x00, 0x13, 0x73, 0xca, 0x02, 0x31, 0x32, 0x2e, 0x31, 0x22, +0x04, 0x01, 0x32, 0x01, 0xb2, 0x61, 0x76, 0x61, 0x69, 0x6c, +0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0x96, 0x02, 0x14, 0x32, +0x96, 0x02, 0x92, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x98, 0x02, 0x56, 0x68, 0x65, 0x73, 0x65, 0x00, +0x14, 0x00, 0x02, 0x42, 0x00, 0x04, 0x3d, 0x00, 0x51, 0x00, +0x66, 0x72, 0x6f, 0x6d, 0x7a, 0x00, 0xe1, 0x60, 0x43, 0x75, +0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, +0x70, 0x70, 0x00, 0x22, 0x6f, 0x6e, 0x1a, 0x00, 0xa0, 0x54, +0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xac, +0x00, 0x90, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, +0x65, 0x79, 0x02, 0x70, 0x00, 0x00, 0x00, 0x53, 0x69, 0x7a, +0x65, 0x14, 0x04, 0x01, 0x27, 0x05, 0x24, 0x69, 0x6e, 0x27, +0x04, 0x60, 0x2e, 0x00, 0x28, 0x4e, 0x6f, 0x74, 0x45, 0x01, +0x22, 0x61, 0x74, 0xa9, 0x01, 0x26, 0x75, 0x6c, 0x3d, 0x04, +0x30, 0x67, 0x61, 0x6d, 0x7d, 0x01, 0x30, 0x71, 0x75, 0x69, +0x94, 0x01, 0x22, 0x6f, 0x74, 0x76, 0x02, 0x10, 0x77, 0x5b, +0x00, 0x01, 0x44, 0x01, 0x12, 0x68, 0x5e, 0x00, 0x20, 0x74, +0x6f, 0x3c, 0x02, 0x10, 0x65, 0x88, 0x05, 0x02, 0xd4, 0x04, +0x11, 0x73, 0xee, 0x00, 0xe3, 0x44, 0x69, 0x66, 0x66, 0x69, +0x63, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x00, 0x00, 0x43, 0x85, +0x03, 0x01, 0x42, 0x00, 0x16, 0x64, 0x1a, 0x00, 0x04, 0x6a, +0x00, 0x50, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x1c, 0x04, 0x02, +0x9d, 0x04, 0x02, 0x3d, 0x04, 0xe2, 0x69, 0x71, 0x75, 0x65, +0x20, 0x72, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, +0xff, 0x04, 0x30, 0x73, 0x00, 0x00, 0xd2, 0x02, 0x20, 0x65, +0x6e, 0x19, 0x01, 0x20, 0x64, 0x2c, 0x1f, 0x05, 0x21, 0x74, +0x77, 0x23, 0x05, 0x03, 0xb9, 0x05, 0x53, 0x65, 0x72, 0x6d, +0x69, 0x74, 0x66, 0x04, 0xc6, 0x68, 0x61, 0x76, 0x65, 0x00, +0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x1a, 0x02, 0x72, +0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x08, 0x02, 0x83, +0x6c, 0x69, 0x6b, 0x65, 0x77, 0x69, 0x73, 0x65, 0x5e, 0x05, +0x00, 0x12, 0x01, 0x15, 0x41, 0xc0, 0x05, 0x14, 0x61, 0x74, +0x05, 0x20, 0x63, 0x61, 0x78, 0x05, 0xe0, 0x74, 0x63, 0x68, +0x2c, 0x00, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x2e, 0x29, +0x00, }; -const unsigned short help_text_len = 1688; -const unsigned short help_text_words = 305; +const unsigned short help_text_len = 1707; +const unsigned short help_text_words = 306; const char quick_help_text[] = "Fill in the black and white grid to avoid runs of three."; diff --git a/apps/plugins/puzzles/help/untangle.c b/apps/plugins/puzzles/help/untangle.c index f7f5c05f24..64ebdfb364 100644 --- a/apps/plugins/puzzles/help/untangle.c +++ b/apps/plugins/puzzles/help/untangle.c @@ -1,4 +1,4 @@ -/* auto-generated on Dec 7 2020 by genhelp.sh */ +/* auto-generated on Jul 22 2024 by genhelp.sh */ /* help text is compressed using LZ4; see compress.c for details */ /* DO NOT EDIT! */ @@ -6,79 +6,95 @@ struct style_text help_text_style[] = { { 0, TEXT_CENTER | C_RED }, - { 64, TEXT_CENTER | C_RED }, - { 100, TEXT_CENTER | C_RED }, - { 119, TEXT_UNDERLINE }, + { 65, TEXT_CENTER | C_RED }, + { 136, TEXT_CENTER | C_RED }, + { 155, TEXT_UNDERLINE }, LAST_STYLE_ITEM }; -/* orig 751 comp 627 ratio 0.834887 level 4 saved 124 */ +/* orig 974 comp 787 ratio 0.808008 level 4 saved 187 */ const char help_text[] = { -0xf0, 0x2f, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, +0xff, 0x08, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x31, 0x38, 0x3a, 0x20, 0x55, 0x6e, 0x74, 0x61, 0x6e, 0x67, -0x6c, 0x65, 0x20, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, -0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, -0x61, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x6f, -0x66, 0x00, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x00, -0x73, 0x6f, 0x6d, 0x65, 0x10, 0x00, 0xf1, 0x15, 0x77, 0x68, -0x69, 0x63, 0x68, 0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x6c, -0x69, 0x6e, 0x65, 0x73, 0x00, 0x64, 0x72, 0x61, 0x77, 0x6e, -0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, -0x68, 0x65, 0x6d, 0x2e, 0x4f, 0x00, 0x80, 0x63, 0x61, 0x6e, -0x00, 0x6d, 0x6f, 0x76, 0x65, 0x13, 0x00, 0x03, 0x46, 0x00, -0xf8, 0x1c, 0x00, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x00, 0x61, -0x72, 0x62, 0x69, 0x74, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79, -0x3b, 0x00, 0x79, 0x6f, 0x75, 0x72, 0x00, 0x61, 0x69, 0x6d, -0x00, 0x69, 0x73, 0x00, 0x74, 0x6f, 0x00, 0x70, 0x6f, 0x73, -0x69, 0x74, 0x69, 0x6f, 0x6e, 0x36, 0x00, 0xa1, 0x73, 0x6f, -0x00, 0x74, 0x68, 0x61, 0x74, 0x00, 0x6e, 0x6f, 0x73, 0x00, -0xf2, 0x1c, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x73, -0x00, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x00, -0x00, 0x00, 0x49, 0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, -0x61, 0x6c, 0x6c, 0x79, 0x00, 0x73, 0x61, 0x77, 0x00, 0x74, -0x68, 0x69, 0x73, 0x00, 0x69, 0x47, 0x00, 0x40, 0x66, 0x6f, -0x72, 0x6d, 0xbb, 0x00, 0xf0, 0x2b, 0x61, 0x00, 0x46, 0x6c, -0x61, 0x73, 0x68, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x63, -0x61, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x50, 0x6c, 0x61, 0x6e, -0x61, 0x72, 0x69, 0x74, 0x79, 0x00, 0x5b, 0x37, 0x5d, 0x2c, -0x00, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x62, -0x79, 0x00, 0x4a, 0x6f, 0x68, 0x6e, 0x00, 0x54, 0x61, 0x6e, -0x74, 0x61, 0x6c, 0x6f, 0x63, 0x00, 0xc4, 0x5b, 0x37, 0x5d, -0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x35, -0x00, 0xb6, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x00, 0x00, 0x31, -0x38, 0x2e, 0x31, 0x4f, 0x01, 0x80, 0x63, 0x6f, 0x6e, 0x74, -0x72, 0x6f, 0x6c, 0x73, 0x58, 0x01, 0x22, 0x54, 0x6f, 0x04, -0x01, 0x12, 0x61, 0xcc, 0x00, 0xf1, 0x03, 0x2c, 0x00, 0x63, -0x6c, 0x69, 0x63, 0x6b, 0x00, 0x6f, 0x6e, 0x00, 0x69, 0x74, -0x00, 0x77, 0x69, 0x74, 0x68, 0xa1, 0x00, 0xf0, 0x06, 0x6c, -0x65, 0x66, 0x74, 0x00, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, -0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x00, 0x61, 0x6e, 0x64, -0x59, 0x01, 0x10, 0x67, 0x27, 0x00, 0x40, 0x69, 0x6e, 0x74, -0x6f, 0x93, 0x01, 0x25, 0x65, 0x77, 0x1e, 0x01, 0x00, 0x90, -0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x3e, 0x00, 0x20, 0x61, -0x63, 0x13, 0x00, 0xb0, 0x73, 0x00, 0x64, 0x65, 0x73, 0x63, -0x72, 0x69, 0x62, 0x65, 0x64, 0xf8, 0x00, 0x21, 0x73, 0x65, -0x16, 0x00, 0x41, 0x00, 0x32, 0x2e, 0x31, 0xd9, 0x01, 0xf2, -0x01, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, -0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xb6, 0x00, 0x16, -0x32, 0xb6, 0x00, 0x92, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, -0x74, 0x65, 0x72, 0xb8, 0x00, 0x40, 0x68, 0x65, 0x72, 0x65, -0x93, 0x01, 0x95, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x6e, -0x65, 0x00, 0x20, 0x00, 0x06, 0x46, 0x00, 0x51, 0x00, 0x66, -0x72, 0x6f, 0x6d, 0x83, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, -0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, -0x79, 0x00, 0x03, 0xc3, 0x01, 0xf1, 0x01, 0x60, 0x54, 0x79, -0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0x3a, 0x00, -0x00, 0x00, 0x4e, 0x58, 0x02, 0x43, 0x20, 0x6f, 0x66, 0x20, -0xdc, 0x01, 0x33, 0x00, 0x00, 0x43, 0x2f, 0x01, 0x01, 0x2f, -0x00, 0x31, 0x73, 0x69, 0x7a, 0x66, 0x02, 0x01, 0xfe, 0x01, -0x60, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, 0x8c, 0x01, 0xa1, -0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, -0x1a, 0x00, 0x0c, 0x9e, 0x02, 0x04, 0xe9, 0x01, 0xf0, 0x02, +0x6c, 0x65, 0x20, 0x00, 0x2d, 0x01, 0x00, 0x00, 0xf0, 0x1a, +0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, +0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x6e, +0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x6f, 0x66, 0x00, 0x70, +0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, +0x65, 0x10, 0x00, 0xf1, 0x15, 0x77, 0x68, 0x69, 0x63, 0x68, +0x00, 0x68, 0x61, 0x76, 0x65, 0x00, 0x6c, 0x69, 0x6e, 0x65, +0x73, 0x00, 0x64, 0x72, 0x61, 0x77, 0x6e, 0x00, 0x62, 0x65, +0x74, 0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x68, 0x65, 0x6d, +0x2e, 0x4f, 0x00, 0x80, 0x63, 0x61, 0x6e, 0x00, 0x6d, 0x6f, +0x76, 0x65, 0x13, 0x00, 0x03, 0x46, 0x00, 0xf8, 0x1c, 0x00, +0x61, 0x62, 0x6f, 0x75, 0x74, 0x00, 0x61, 0x72, 0x62, 0x69, +0x74, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79, 0x3b, 0x00, 0x79, +0x6f, 0x75, 0x72, 0x00, 0x61, 0x69, 0x6d, 0x00, 0x69, 0x73, +0x00, 0x74, 0x6f, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, +0x6f, 0x6e, 0x36, 0x00, 0xa1, 0x73, 0x6f, 0x00, 0x74, 0x68, +0x61, 0x74, 0x00, 0x6e, 0x6f, 0x73, 0x00, 0xf2, 0x1c, 0x00, +0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x00, 0x61, 0x6e, +0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x00, 0x49, +0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x6c, +0x79, 0x00, 0x73, 0x61, 0x77, 0x00, 0x74, 0x68, 0x69, 0x73, +0x00, 0x69, 0x47, 0x00, 0x40, 0x66, 0x6f, 0x72, 0x6d, 0xbb, +0x00, 0xf0, 0x2b, 0x61, 0x00, 0x46, 0x6c, 0x61, 0x73, 0x68, +0x00, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x63, 0x61, 0x6c, 0x6c, +0x65, 0x64, 0x00, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x69, +0x74, 0x79, 0x00, 0x5b, 0x37, 0x5d, 0x2c, 0x00, 0x77, 0x72, +0x69, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, +0x6f, 0x68, 0x6e, 0x00, 0x54, 0x61, 0x6e, 0x74, 0x61, 0x6c, +0x6f, 0x63, 0x00, 0xc4, 0x5b, 0x37, 0x5d, 0x00, 0x68, 0x74, +0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x35, 0x00, 0xb6, 0x2e, +0x6e, 0x65, 0x74, 0x00, 0x00, 0x00, 0x31, 0x38, 0x2e, 0x31, +0x64, 0x01, 0xe2, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, +0x73, 0x20, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x04, 0x01, 0x12, +0x61, 0xcc, 0x00, 0xf1, 0x03, 0x2c, 0x00, 0x63, 0x6c, 0x69, +0x63, 0x6b, 0x00, 0x6f, 0x6e, 0x00, 0x69, 0x74, 0x00, 0x77, +0x69, 0x74, 0x68, 0xa1, 0x00, 0xf0, 0x06, 0x6c, 0x65, 0x66, +0x74, 0x00, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x62, 0x75, +0x74, 0x74, 0x6f, 0x6e, 0x00, 0x61, 0x6e, 0x64, 0x59, 0x01, +0x10, 0x67, 0x27, 0x00, 0x40, 0x69, 0x6e, 0x74, 0x6f, 0x93, +0x01, 0x25, 0x65, 0x77, 0x1e, 0x01, 0x00, 0x90, 0x00, 0xf0, +0x11, 0x54, 0x68, 0x65, 0x00, 0x63, 0x75, 0x72, 0x73, 0x6f, +0x72, 0x00, 0x6b, 0x65, 0x79, 0x73, 0x00, 0x6d, 0x61, 0x79, +0x00, 0x61, 0x6c, 0x73, 0x6f, 0x00, 0x62, 0x65, 0x00, 0x75, +0x73, 0x65, 0x64, 0x4e, 0x01, 0xf7, 0x01, 0x6e, 0x61, 0x76, +0x69, 0x67, 0x61, 0x74, 0x65, 0x00, 0x61, 0x6d, 0x6f, 0x6e, +0x67, 0x73, 0x74, 0x56, 0x01, 0xa1, 0x2e, 0x00, 0x50, 0x72, +0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x15, 0x00, 0x41, 0x45, +0x6e, 0x74, 0x65, 0x49, 0x00, 0xc1, 0x00, 0x77, 0x69, 0x6c, +0x6c, 0x00, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x83, 0x00, +0x14, 0x67, 0x23, 0x00, 0xf2, 0x07, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x6c, 0x79, 0x2d, 0x00, 0x68, 0x69, 0x67, +0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4f, 0x00, +0x07, 0x4e, 0x00, 0xc2, 0x54, 0x61, 0x62, 0x00, 0x6f, 0x72, +0x00, 0x53, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x00, 0x40, 0x63, +0x79, 0x63, 0x6c, 0x07, 0x02, 0x99, 0x72, 0x6f, 0x75, 0x67, +0x68, 0x00, 0x61, 0x6c, 0x6c, 0x87, 0x00, 0x43, 0x00, 0x00, +0x28, 0x41, 0x13, 0x00, 0x20, 0x61, 0x63, 0xdd, 0x00, 0xb0, +0x73, 0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, +0x64, 0xc2, 0x01, 0x21, 0x73, 0x65, 0x16, 0x00, 0x41, 0x00, +0x32, 0x2e, 0x31, 0xa3, 0x02, 0x01, 0xe4, 0x00, 0xb2, 0x61, +0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, +0x80, 0x01, 0x16, 0x32, 0x80, 0x01, 0x92, 0x70, 0x61, 0x72, +0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x82, 0x01, 0x40, 0x68, +0x65, 0x72, 0x65, 0x5d, 0x02, 0x95, 0x6f, 0x6e, 0x6c, 0x79, +0x00, 0x6f, 0x6e, 0x65, 0x00, 0x20, 0x00, 0x06, 0x46, 0x00, +0x51, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x83, 0x00, 0xe1, 0x60, +0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, +0x00, 0x6f, 0x70, 0x79, 0x00, 0x03, 0x8d, 0x02, 0xf1, 0x01, +0x60, 0x54, 0x79, 0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, +0x75, 0x3a, 0x00, 0x00, 0x00, 0x4e, 0x22, 0x03, 0x43, 0x20, +0x6f, 0x66, 0x20, 0xa6, 0x02, 0x33, 0x00, 0x00, 0x43, 0xf9, +0x01, 0x01, 0x2f, 0x00, 0x31, 0x73, 0x69, 0x7a, 0x30, 0x03, +0x01, 0xeb, 0x00, 0x60, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x2c, +0x56, 0x02, 0x74, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, +0x54, 0x01, 0x0c, 0x68, 0x03, 0x04, 0xb3, 0x02, 0xf0, 0x02, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x00, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x00, }; -const unsigned short help_text_len = 751; -const unsigned short help_text_words = 138; +const unsigned short help_text_len = 974; +const unsigned short help_text_words = 174; const char quick_help_text[] = "Reposition the points so that the lines do not cross."; diff --git a/apps/plugins/puzzles/rbcompat.h b/apps/plugins/puzzles/rbcompat.h index 9069c1e659..f37ac8068e 100644 --- a/apps/plugins/puzzles/rbcompat.h +++ b/apps/plugins/puzzles/rbcompat.h @@ -34,6 +34,8 @@ int sscanf_wrapper(const char *ibuf, const char *fmt, ...); double atof_wrapper(const char *s); double acos_wrapper(double x); +#define NO_TGMATH_H + #define acos acos_wrapper #define atan atan_wrapper #define atan2 atan2_wrapper diff --git a/apps/plugins/puzzles/resync.sh b/apps/plugins/puzzles/resync.sh index 76679971a4..384fc79d1f 100755 --- a/apps/plugins/puzzles/resync.sh +++ b/apps/plugins/puzzles/resync.sh @@ -19,7 +19,7 @@ then fi echo "=== POTENTIALLY DANGEROUS OPERATION ===" -echo "Are you sure you want to remove all files in src/?" +echo "Are you sure you want to remove all files in src/ and help/?" echo -n "If so, type \"yes\" in all caps: " read ans if [ "YES" == $ans ] @@ -30,8 +30,9 @@ then rm -rf src echo "[2/5] Copying new sources" mkdir src - cp -r "$1"/{*.c,*.h,*.R,*.but,LICENCE,README} src + cp -r "$1"/{*.c,*.h,*.but,LICENCE,README,CMakeLists.txt} src echo "[3/5] Regenerating help" + rm -rf help ./genhelp.sh echo "[4/5] Staging for commit" diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c index 263a19f421..c95e8a8356 100644 --- a/apps/plugins/puzzles/rockbox.c +++ b/apps/plugins/puzzles/rockbox.c @@ -163,6 +163,11 @@ * cases by waiting until a key has been released before we * send the input keystroke(s) to the game. * + * e) Key repeat + * + * In some games, we would like to send repeated key events to + * allow long drags. Currently, this is only used in Untangle. + * * 5) Game configuration and preset management * * The backend games specify a hierarchy of user-adjustable game @@ -1211,7 +1216,7 @@ static void zoom_filltriangle(int x1, int y1, } /* Should probably refactor this */ -static void rb_draw_poly(void *handle, int *coords, int npoints, +static void rb_draw_poly(void *handle, const int *coords, int npoints, int fillcolor, int outlinecolor) { if(!zoom_enabled) @@ -2268,7 +2273,7 @@ static void zoom(void) zoom_clipl = 0; zoom_clipr = zoom_w; - midend_size(me, &zoom_w, &zoom_h, true); + midend_size(me, &zoom_w, &zoom_h, true, 1.0); /* Allocating the framebuffer will mostly likely grab the * audiobuffer, which will make impossible to load new fonts, and @@ -2634,10 +2639,10 @@ const char *config_formatter(int sel, void *data, char *buf, size_t len) return buf; } -static bool config_menu(void) +static bool config_menu_core(int which) { char *title; - config_item *config = midend_get_config(me, CFG_SETTINGS, &title); + config_item *config = midend_get_config(me, which, &title); rb->lcd_setfont(cur_font = FONT_UI); @@ -2689,7 +2694,7 @@ static bool config_menu(void) old_str = dupstr(old.u.string.sval); bool freed_str = do_configure_item(config, pos); - const char *err = midend_set_config(me, CFG_SETTINGS, config); + const char *err = midend_set_config(me, which, config); if(err) { @@ -2728,6 +2733,16 @@ done: return success; } +static bool config_menu(void) +{ + return config_menu_core(CFG_SETTINGS); +} + +static bool preferences_menu(void) +{ + return config_menu_core(CFG_PREFS); +} + static const char *preset_formatter(int sel, void *data, char *buf, size_t len) { struct preset_menu *menu = data; @@ -3108,8 +3123,9 @@ static int pause_menu(void) "Game Type", // 10 "Debug Menu", // 11 "Configure Game", // 12 - "Quit without Saving", // 13 - "Quit"); // 14 + "Preferences", // 13 + "Quit without Saving", // 14 + "Quit"); // 15 #if defined(FOR_REAL) && defined(DEBUG_MENU) help_times = 0; @@ -3190,9 +3206,13 @@ static int pause_menu(void) quit = true; } break; - case 13: - return -2; + case 13: + preferences_menu(); + // do not go straight into game. + break; case 14: + return -2; + case 15: return -3; default: break; @@ -3217,7 +3237,7 @@ static void fix_size(void) rb->lcd_setfont(cur_font = FONT_UI); rb->lcd_getstringsize("X", NULL, &h_x); h -= h_x; - midend_size(me, &w, &h, true); + midend_size(me, &w, &h, true, 1.0); } static void init_tlsf(void) @@ -3277,32 +3297,39 @@ static bool string_in_list(const char *target, const char **list) static void tune_input(const char *name) { static const char *want_spacebar[] = { + "Black Box", + "Bridges", + "Galaxies", + "Keen", "Magnets", "Map", "Mines", "Palisade", + "Pattern", "Rectangles", + "Signpost", + "Singles", + "Solo", + "Tents", + "Towers", + "Unequal", + "Group", NULL }; - /* these get a spacebar on long click - you must also add to the - * falling_edge list below! */ + /* these get a spacebar on long click - this implicitly enables + * falling-edge button events (see below)! */ input_settings.want_spacebar = string_in_list(name, want_spacebar); static const char *falling_edge[] = { "Inertia", - "Magnets", - "Map", - "Mines", - "Palisade", - "Rectangles", NULL }; /* wait until a key is released to send an action (useful for * chording in Inertia; must be enabled if the game needs a * spacebar) */ - input_settings.falling_edge = string_in_list(name, falling_edge); + input_settings.falling_edge = string_in_list(name, falling_edge) || input_settings.want_spacebar; /* For want_spacebar to work, events must be sent on the falling * edge */ @@ -3691,8 +3718,9 @@ static void puzzles_main(void) "Playback Control", // 4 "Game Type", // 5 "Configure Game", // 6 - "Quit without Saving", // 7 - "Quit"); // 8 + "Preferences", // 7 + "Quit without Saving", // 8 + "Quit"); // 9 bool quit = false; int sel = 0; @@ -3738,11 +3766,14 @@ static void puzzles_main(void) goto game_loop; } break; - case 8: + case 7: + preferences_menu(); + break; + case 9: if(load_success) save_game(); /* fall through */ - case 7: + case 8: /* we don't care about freeing anything because tlsf will * be wiped out the next time around */ return; diff --git a/apps/plugins/puzzles/src/CMakeLists.txt b/apps/plugins/puzzles/src/CMakeLists.txt new file mode 100644 index 0000000000..4153efc246 --- /dev/null +++ b/apps/plugins/puzzles/src/CMakeLists.txt @@ -0,0 +1,287 @@ +cmake_minimum_required(VERSION 3.5) + +project(puzzles + LANGUAGES C) + +include(cmake/setup.cmake) + +add_library(core_obj OBJECT + combi.c divvy.c drawing.c dsf.c findloop.c grid.c latin.c + laydomino.c loopgen.c malloc.c matching.c midend.c misc.c penrose.c + penrose-legacy.c ps.c random.c sort.c tdq.c tree234.c version.c + ${platform_common_sources}) +add_library(core $) +add_library(common $ hat.c spectre.c) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +puzzle(blackbox + DISPLAYNAME "Black Box" + DESCRIPTION "Ball-finding puzzle" + OBJECTIVE "Find the hidden balls in the box by bouncing laser beams \ +off them.") + +puzzle(bridges + DISPLAYNAME "Bridges" + DESCRIPTION "Bridge-placing puzzle" + OBJECTIVE "Connect all the islands with a network of bridges.") + +puzzle(cube + DISPLAYNAME "Cube" + DESCRIPTION "Rolling cube puzzle" + OBJECTIVE "Pick up all the blue squares by rolling the cube over them.") + +puzzle(dominosa + DISPLAYNAME "Dominosa" + DESCRIPTION "Domino tiling puzzle" + OBJECTIVE "Tile the rectangle with a full set of dominoes.") +solver(dominosa) + +puzzle(fifteen + DISPLAYNAME "Fifteen" + DESCRIPTION "Sliding block puzzle" + OBJECTIVE "Slide the tiles around to arrange them into order.") +solver(fifteen) + +puzzle(filling + DISPLAYNAME "Filling" + DESCRIPTION "Polyomino puzzle" + OBJECTIVE "Mark every square with the area of its containing region.") +solver(filling) + +puzzle(flip + DISPLAYNAME "Flip" + DESCRIPTION "Tile inversion puzzle" + OBJECTIVE "Flip groups of squares to light them all up at once.") + +puzzle(flood + DISPLAYNAME "Flood" + DESCRIPTION "Flood-filling puzzle" + OBJECTIVE "Turn the grid the same colour in as few flood fills as possible.") + +puzzle(galaxies + DISPLAYNAME "Galaxies" + DESCRIPTION "Symmetric polyomino puzzle" + OBJECTIVE "Divide the grid into rotationally symmetric regions each \ +centred on a dot.") +solver(galaxies) +cliprogram(galaxiespicture galaxies.c + COMPILE_DEFINITIONS STANDALONE_PICTURE_GENERATOR) +guiprogram(galaxieseditor galaxies.c + COMPILE_DEFINITIONS EDITOR) + +puzzle(guess + DISPLAYNAME "Guess" + DESCRIPTION "Combination-guessing puzzle" + OBJECTIVE "Guess the hidden combination of colours.") + +puzzle(inertia + DISPLAYNAME "Inertia" + DESCRIPTION "Gem-collecting puzzle" + OBJECTIVE "Collect all the gems without running into any of the mines.") + +puzzle(keen + DISPLAYNAME "Keen" + DESCRIPTION "Arithmetic Latin square puzzle" + OBJECTIVE "Complete the latin square in accordance with the \ +arithmetic clues.") +solver(keen latin.c) + +puzzle(lightup + DISPLAYNAME "Light Up" + DESCRIPTION "Light-bulb placing puzzle" + OBJECTIVE "Place bulbs to light up all the squares.") +solver(lightup) + +puzzle(loopy + DISPLAYNAME "Loopy" + DESCRIPTION "Loop-drawing puzzle" + OBJECTIVE "Draw a single closed loop, given clues about number of \ +adjacent edges.") +solver(loopy) + +puzzle(magnets + DISPLAYNAME "Magnets" + DESCRIPTION "Magnet-placing puzzle" + OBJECTIVE "Place magnets to satisfy the clues and avoid like poles \ +touching.") +solver(magnets) + +puzzle(map + DISPLAYNAME "Map" + DESCRIPTION "Map-colouring puzzle" + OBJECTIVE "Colour the map so that adjacent regions are never the \ +same colour.") +solver(map) + +puzzle(mines + DISPLAYNAME "Mines" + DESCRIPTION "Mine-finding puzzle" + OBJECTIVE "Find all the mines without treading on any of them.") +cliprogram(mineobfusc mines.c COMPILE_DEFINITIONS STANDALONE_OBFUSCATOR) + +puzzle(mosaic + DISPLAYNAME "Mosaic" + DESCRIPTION "Grid-filling puzzle" + OBJECTIVE "Fill in the grid given clues about number of \ +nearby black squares.") + +puzzle(net + # The Windows Net shouldn't be called 'net.exe', since Windows + # already has a reasonably important utility program by that name! + WINDOWS_EXE_NAME netgame + + DISPLAYNAME "Net" + DESCRIPTION "Network jigsaw puzzle" + OBJECTIVE "Rotate each tile to reassemble the network.") + +puzzle(netslide + DISPLAYNAME "Netslide" + DESCRIPTION "Toroidal sliding network puzzle" + OBJECTIVE "Slide a row at a time to reassemble the network.") + +puzzle(nullgame) + +puzzle(palisade + DISPLAYNAME "Palisade" + DESCRIPTION "Grid-division puzzle" + OBJECTIVE "Divide the grid into equal-sized areas in accordance with\ + the clues.") + +puzzle(pattern + DISPLAYNAME "Pattern" + DESCRIPTION "Pattern puzzle" + OBJECTIVE "Fill in the pattern in the grid, given only the lengths \ +of runs of black squares.") +solver(pattern) +cliprogram(patternpicture pattern.c + COMPILE_DEFINITIONS STANDALONE_PICTURE_GENERATOR) + +puzzle(pearl + DISPLAYNAME "Pearl" + DESCRIPTION "Loop-drawing puzzle" + OBJECTIVE "Draw a single closed loop, given clues about corner and \ +straight squares.") +solver(pearl) +cliprogram(pearlbench pearl.c COMPILE_DEFINITIONS STANDALONE_SOLVER) + +puzzle(pegs + DISPLAYNAME "Pegs" + DESCRIPTION "Peg solitaire puzzle" + OBJECTIVE "Jump pegs over each other to remove all but one.") + +puzzle(range + DISPLAYNAME "Range" + DESCRIPTION "Visible-distance puzzle" + OBJECTIVE "Place black squares to limit the visible distance from \ +each numbered cell.") + +puzzle(rect + DISPLAYNAME "Rectangles" + DESCRIPTION "Rectangles puzzle" + OBJECTIVE "Divide the grid into rectangles with areas equal to the \ +numbers.") + +puzzle(samegame + DISPLAYNAME "Same Game" + DESCRIPTION "Block-clearing puzzle" + OBJECTIVE "Clear the grid by removing touching groups of the same \ +colour squares.") + +puzzle(signpost + DISPLAYNAME "Signpost" + DESCRIPTION "Square-connecting puzzle" + OBJECTIVE "Connect the squares into a path following the arrows.") +solver(signpost) + +puzzle(singles + DISPLAYNAME "Singles" + DESCRIPTION "Number-removing puzzle" + OBJECTIVE "Black out the right set of duplicate numbers.") +solver(singles) + +puzzle(sixteen + DISPLAYNAME "Sixteen" + DESCRIPTION "Toroidal sliding block puzzle" + OBJECTIVE "Slide a row at a time to arrange the tiles into order.") + +puzzle(slant + DISPLAYNAME "Slant" + DESCRIPTION "Maze-drawing puzzle" + OBJECTIVE "Draw a maze of slanting lines that matches the clues.") +solver(slant) + +puzzle(solo + DISPLAYNAME "Solo" + DESCRIPTION "Number placement puzzle" + OBJECTIVE "Fill in the grid so that each row, column and square \ +block contains one of every digit.") +solver(solo) + +puzzle(tents + DISPLAYNAME "Tents" + DESCRIPTION "Tent-placing puzzle" + OBJECTIVE "Place a tent next to each tree.") +solver(tents) + +puzzle(towers + DISPLAYNAME "Towers" + DESCRIPTION "Tower-placing Latin square puzzle" + OBJECTIVE "Complete the latin square of towers in accordance with \ +the clues.") +solver(towers latin.c) + +puzzle(tracks + DISPLAYNAME "Tracks" + DESCRIPTION "Path-finding railway track puzzle" + OBJECTIVE "Fill in the railway track according to the clues.") +solver(tracks) + +puzzle(twiddle + DISPLAYNAME "Twiddle" + DESCRIPTION "Rotational sliding block puzzle" + OBJECTIVE "Rotate the tiles around themselves to arrange them into order.") + +puzzle(undead + DISPLAYNAME "Undead" + DESCRIPTION "Monster-placing puzzle" + OBJECTIVE "Place ghosts, vampires and zombies so that the right \ +numbers of them can be seen in mirrors.") + +puzzle(unequal + DISPLAYNAME "Unequal" + DESCRIPTION "Latin square puzzle" + OBJECTIVE "Complete the latin square in accordance with the > signs.") +solver(unequal latin.c) + +puzzle(unruly + DISPLAYNAME "Unruly" + DESCRIPTION "Black and white grid puzzle" + OBJECTIVE "Fill in the black and white grid to avoid runs of three.") +solver(unruly) + +puzzle(untangle + DISPLAYNAME "Untangle" + DESCRIPTION "Planar graph layout puzzle" + OBJECTIVE "Reposition the points so that the lines do not cross.") + +add_subdirectory(unfinished) +add_subdirectory(auxiliary) + +if(build_cli_programs) + write_generated_games_header() + include(CheckFunctionExists) + check_function_exists(HF_ITER HAVE_HF_ITER) + set(WITH_LIBFUZZER OFF + CACHE BOOL "Build fuzzpuzz using Clang's libFuzzer") + cliprogram(fuzzpuzz fuzzpuzz.c list.c ${puzzle_sources} + COMPILE_DEFINITIONS COMBINED $<$:OMIT_MAIN> + $<$:HAVE_HF_ITER>) + target_include_directories(fuzzpuzz PRIVATE ${generated_include_dir}) + if(WITH_LIBFUZZER) + target_compile_options(fuzzpuzz PRIVATE -fsanitize=fuzzer) + set_target_properties(fuzzpuzz PROPERTIES LINK_FLAGS -fsanitize=fuzzer) + endif() +endif() + +build_extras() diff --git a/apps/plugins/puzzles/src/LICENCE b/apps/plugins/puzzles/src/LICENCE index 85f67ba795..d33dae80af 100644 --- a/apps/plugins/puzzles/src/LICENCE +++ b/apps/plugins/puzzles/src/LICENCE @@ -1,9 +1,9 @@ -This software is copyright (c) 2004-2014 Simon Tatham. +This software is copyright (c) 2004-2024 Simon Tatham. Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens, Michael -Quevillon and Asher Gordon. +Quevillon, Asher Gordon, Didi Kohen and Ben Harris. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/apps/plugins/puzzles/src/README b/apps/plugins/puzzles/src/README index 00830126e8..dd76edc19b 100644 --- a/apps/plugins/puzzles/src/README +++ b/apps/plugins/puzzles/src/README @@ -2,48 +2,12 @@ This is the README accompanying the source code to Simon Tatham's puzzle collection. The collection's web site is at . -If you've obtained the source code by downloading a .tar.gz archive -from the Puzzles web site, you should find several Makefiles in the -source code. However, if you've checked the source code out from the -Puzzles git repository, you won't find the Makefiles: they're -automatically generated by `mkfiles.pl', so run that to create them. +The puzzle collection is built using CMake . To +compile in the simplest way (on any of Linux, Windows or Mac), run +these commands in the source directory: -The Makefiles include: - - - `Makefile.am', together with the static `configure.ac', is intended - as input to automake. Run `mkauto.sh' to turn these into a - configure script and Makefile.in, after which you can then run - `./configure' to create an actual Unix Makefile. - - - `Makefile.vc' should work under MS Visual C++ on Windows. Run - 'nmake /f Makefile.vc' in a Visual Studio command prompt. - - - `Makefile.cyg' should work under Cygwin / MinGW. With appropriate - tweaks and setting of TOOLPATH, it should work for both compiling - on Windows and cross-compiling on Unix. - - - `Makefile.osx' should work under Mac OS X, provided the Xcode - tools are installed. It builds a single monolithic OS X - application capable of running any of the puzzles, or even more - than one of them at a time. - - - `Makefile.wce' should work under MS eMbedded Visual C++ on - Windows and the Pocket PC SDK; it builds Pocket PC binaries. - -Many of these Makefiles build a program called `nullgame' in -addition to the actual game binaries. This program doesn't do -anything; it's just a template for people to start from when adding -a new game to the collection, and it's compiled every time to ensure -that it _does_ compile and link successfully (because otherwise it -wouldn't be much use as a template). Once it's built, you can run it -if you really want to (but it's very boring), and then you should -ignore it. - -DO NOT EDIT THE MAKEFILES DIRECTLY, if you plan to send any changes -back to the maintainer. The makefiles are generated automatically by -the Perl script `mkfiles.pl' from the file `Recipe' and the various -.R files. If you need to change the makefiles as part of a patch, -you should change Recipe, *.R, and/or mkfiles.pl. + cmake . + cmake --build . The manual is provided in Windows Help format for the Windows build; in text format for anyone who needs it; and in HTML for the Mac OS X diff --git a/apps/plugins/puzzles/src/blackbox.R b/apps/plugins/puzzles/src/blackbox.R deleted file mode 100644 index 116225206d..0000000000 --- a/apps/plugins/puzzles/src/blackbox.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -blackbox : [X] GTK COMMON blackbox blackbox-icon|no-icon - -blackbox : [G] WINDOWS COMMON blackbox blackbox.res|noicon.res - -ALL += blackbox[COMBINED] - -!begin am gtk -GAMES += blackbox -!end - -!begin >list.c - A(blackbox) \ -!end - -!begin >gamedesc.txt -blackbox:blackbox.exe:Black Box:Ball-finding puzzle:Find the hidden balls in the box by bouncing laser beams off them. -!end diff --git a/apps/plugins/puzzles/src/blackbox.c b/apps/plugins/puzzles/src/blackbox.c index a9c1f88261..ab8e382d0a 100644 --- a/apps/plugins/puzzles/src/blackbox.c +++ b/apps/plugins/puzzles/src/blackbox.c @@ -7,7 +7,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -192,12 +196,14 @@ static const char *validate_params(const game_params *params, bool full) * types, and could be worked around if required. */ if (params->w > 255 || params->h > 255) return "Widths and heights greater than 255 are not supported"; + if (params->minballs < 0) + return "Negative number of balls"; + if (params->minballs < 1) + return "Number of balls must be at least one"; if (params->minballs > params->maxballs) return "Minimum number of balls may not be greater than maximum"; if (params->minballs >= params->w * params->h) return "Too many balls to fit in grid"; - if (params->minballs < 1) - return "Number of balls must be at least one"; return NULL; } @@ -307,7 +313,7 @@ struct game_state { #define GRID(s,x,y) ((s)->grid[(y)*((s)->w+2) + (x)]) -#define RANGECHECK(s,x) ((x) >= 0 && (x) <= (s)->nlasers) +#define RANGECHECK(s,x) ((x) >= 0 && (x) < (s)->nlasers) /* specify numbers because they must match array indexes. */ enum { DIR_UP = 0, DIR_RIGHT = 1, DIR_DOWN = 2, DIR_LEFT = 3 }; @@ -468,16 +474,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return dupstr("S"); } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - struct game_ui { int flash_laserno; int errors; @@ -495,7 +491,7 @@ static game_ui *new_ui(const game_state *state) ui->newmove = false; ui->cur_x = ui->cur_y = 1; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->flash_laser = 0; @@ -517,7 +513,8 @@ static char *encode_ui(const game_ui *ui) return dupstr(buf); } -static void decode_ui(game_ui *ui, const char *encoding) +static void decode_ui(game_ui *ui, const char *encoding, + const game_state *state) { sscanf(encoding, "E%d", &ui->errors); } @@ -534,6 +531,41 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->newmove = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cur_visible && !state->reveal) { + int gx = ui->cur_x, gy = ui->cur_y, rangeno = -1; + if (gx == 0 && gy == 0 && button == CURSOR_SELECT) return "Check"; + if (gx >= 1 && gx <= state->w && gy >= 1 && gy <= state->h) { + /* Cursor somewhere in the arena. */ + if (button == CURSOR_SELECT && !(GRID(state, gx,gy) & BALL_LOCK)) + return (GRID(state, gx, gy) & BALL_GUESS) ? "Clear" : "Ball"; + if (button == CURSOR_SELECT2) + return (GRID(state, gx, gy) & BALL_LOCK) ? "Unlock" : "Lock"; + } + if (grid2range(state, gx, gy, &rangeno)) { + if (button == CURSOR_SELECT && + state->exits[rangeno] == LASER_EMPTY) + return "Fire"; + if (button == CURSOR_SELECT2) { + int n = 0; + /* Row or column lock or unlock. */ + if (gy == 0 || gy > state->h) { /* Column lock */ + for (gy = 1; gy <= state->h; gy++) + n += !!(GRID(state, gx, gy) & BALL_LOCK); + return n > state->h/2 ? "Unlock" : "Lock"; + } else { /* Row lock */ + for (gx = 1; gx <= state->w; gx++) + n += !!(GRID(state, gx, gy) & BALL_LOCK); + return n > state->w/2 ? "Unlock" : "Lock"; + } + } + } + } + return ""; +} + #define OFFSET(gx,gy,o) do { \ int off = (4 + (o) % 4) % 4; \ (gx) += offsets[off].x; \ @@ -875,7 +907,7 @@ done: #define TILE_SIZE (ds->tilesize) #define TODRAW(x) ((TILE_SIZE * (x)) + (TILE_SIZE / 2)) -#define FROMDRAW(x) (((x) - (TILE_SIZE / 2)) / TILE_SIZE) +#define FROMDRAW(x) (((x) + (TILE_SIZE / 2)) / TILE_SIZE - 1) #define CAN_REVEAL(state) ((state)->nguesses >= (state)->minballs && \ (state)->nguesses <= (state)->maxballs && \ @@ -900,7 +932,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { int cx = ui->cur_x, cy = ui->cur_y; - move_cursor(button, &cx, &cy, state->w+2, state->h+2, false); + move_cursor(button, &cx, &cy, state->w+2, state->h+2, false, NULL); if ((cx == 0 && cy == 0 && !CAN_REVEAL(state)) || (cx == 0 && cy == state->h+1) || (cx == state->w+1 && cy == 0) || @@ -909,7 +941,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->cur_x = cx; ui->cur_y = cy; ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { @@ -919,7 +951,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, wouldflash = 1; } else if (button == LEFT_RELEASE) { ui->flash_laser = 0; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (IS_CURSOR_SELECT(button)) { if (ui->cur_visible) { gx = ui->cur_x; @@ -928,7 +960,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, wouldflash = 2; } else { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } /* Fix up 'button' for the below logic. */ if (button == CURSOR_SELECT2) button = RIGHT_BUTTON; @@ -977,9 +1009,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, return nullret; ui->flash_laserno = rangeno; ui->flash_laser = wouldflash; - nullret = UI_UPDATE; + nullret = MOVE_UI_UPDATE; if (state->exits[rangeno] != LASER_EMPTY) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "F%d", rangeno); break; @@ -1034,10 +1066,10 @@ static game_state *execute_move(const game_state *from, const char *move) case 'F': sscanf(move+1, "%d", &rangeno); - if (ret->exits[rangeno] != LASER_EMPTY) - goto badmove; if (!RANGECHECK(ret, rangeno)) goto badmove; + if (ret->exits[rangeno] != LASER_EMPTY) + goto badmove; fire_laser(ret, rangeno); break; @@ -1119,7 +1151,7 @@ static void game_get_cursor_location(const game_ui *ui, */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Border is ts/2, to make things easier. * Thus we have (width) + 2 (firing range*2) + 1 (border*2) tiles @@ -1379,10 +1411,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int x0 = TODRAW(0)-1, y0 = TODRAW(0)-1; int x1 = TODRAW(state->w+2), y1 = TODRAW(state->h+2); - draw_rect(dr, 0, 0, - TILE_SIZE * (state->w+3), TILE_SIZE * (state->h+3), - COL_BACKGROUND); - /* clockwise around the outline starting at pt behind (1,1). */ draw_line(dr, x0+ts, y0+ts, x0+ts, y0, COL_HIGHLIGHT); draw_line(dr, x0+ts, y0, x1-ts, y0, COL_HIGHLIGHT); @@ -1429,14 +1457,14 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int outline = (ui->cur_visible && ui->cur_x == 0 && ui->cur_y == 0) ? COL_CURSOR : COL_BALL; clip(dr, TODRAW(0)-1, TODRAW(0)-1, TILE_SIZE+1, TILE_SIZE+1); - draw_circle(dr, TODRAW(0) + ds->crad, TODRAW(0) + ds->crad, ds->crad, + draw_circle(dr, TODRAW(0) + ds->crad-1, TODRAW(0) + ds->crad-1, ds->crad-1, outline, outline); - draw_circle(dr, TODRAW(0) + ds->crad, TODRAW(0) + ds->crad, ds->crad-2, + draw_circle(dr, TODRAW(0) + ds->crad-1, TODRAW(0) + ds->crad-1, ds->crad-3, COL_BUTTON, COL_BUTTON); unclip(dr); } else { draw_rect(dr, TODRAW(0)-1, TODRAW(0)-1, - TILE_SIZE+1, TILE_SIZE+1, COL_BACKGROUND); + TILE_SIZE, TILE_SIZE, COL_BACKGROUND); } draw_update(dr, TODRAW(0), TODRAW(0), TILE_SIZE, TILE_SIZE); ds->reveal = state->reveal; @@ -1509,19 +1537,6 @@ static int game_status(const game_state *state) return 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame blackbox #endif @@ -1542,13 +1557,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, encode_ui, decode_ui, NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1560,9 +1577,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; diff --git a/apps/plugins/puzzles/src/bridges.R b/apps/plugins/puzzles/src/bridges.R deleted file mode 100644 index 75df309152..0000000000 --- a/apps/plugins/puzzles/src/bridges.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -BRIDGES_EXTRA = dsf findloop - -bridges : [X] GTK COMMON bridges BRIDGES_EXTRA bridges-icon|no-icon - -bridges : [G] WINDOWS COMMON bridges BRIDGES_EXTRA bridges.res|noicon.res - -ALL += bridges[COMBINED] BRIDGES_EXTRA - -!begin am gtk -GAMES += bridges -!end - -!begin >list.c - A(bridges) \ -!end - -!begin >gamedesc.txt -bridges:bridges.exe:Bridges:Bridge-placing puzzle:Connect all the islands with a network of bridges. -!end diff --git a/apps/plugins/puzzles/src/bridges.c b/apps/plugins/puzzles/src/bridges.c index 83086c9761..7e87764d6d 100644 --- a/apps/plugins/puzzles/src/bridges.c +++ b/apps/plugins/puzzles/src/bridges.c @@ -72,11 +72,15 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" -/* Turn this on for hints about which lines are considered possibilities. */ #undef DRAW_GRID /* --- structures for params, state, etc. --- */ @@ -134,8 +138,8 @@ struct game_params { typedef unsigned int grid_type; /* change me later if we invent > 16 bits of flags. */ struct solver_state { - int *dsf, *comptspaces; - int *tmpdsf, *tmpcompspaces; + DSF *dsf, *tmpdsf; + int *comptspaces, *tmpcompspaces; int refcount; }; @@ -183,7 +187,7 @@ struct game_state { #define GRIDCOUNT(s,x,y,f) ((GRID(s,x,y) & (f)) ? (INDEX(s,lines,x,y)) : 0) -#define WITHIN2(x,min,max) ((x) >= (min) && (x) < (max)) +#define WITHIN2(x,min,max) ((x) >= (min) && (x) <= (max)) #define WITHIN(x,min,max) ((min) > (max) ? \ WITHIN2(x,max,min) : WITHIN2(x,min,max)) @@ -803,6 +807,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 3 || params->h < 3) return "Width and height must be at least 3"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->maxb < 1 || params->maxb > MAX_BRIDGES) return "Too many bridges."; if (full) { @@ -1133,13 +1139,13 @@ static bool map_hasloops(game_state *state, bool mark) static void map_group(game_state *state) { - int i, wh = state->w*state->h, d1, d2; + int i, d1, d2; int x, y, x2, y2; - int *dsf = state->solver->dsf; + DSF *dsf = state->solver->dsf; struct island *is, *is_join; /* Initialise dsf. */ - dsf_init(dsf, wh); + dsf_reinit(dsf); /* For each island, find connected islands right or down * and merge the dsf for the island squares as well as the @@ -1160,7 +1166,7 @@ static void map_group(game_state *state) if (!is_join) continue; d2 = DINDEX(is_join->x, is_join->y); - if (dsf_canonify(dsf,d1) == dsf_canonify(dsf,d2)) { + if (dsf_equivalent(dsf, d1, d2)) { ; /* we have a loop. See comment in map_hasloops. */ /* However, we still want to merge all squares joining * this side-that-makes-a-loop. */ @@ -1180,7 +1186,8 @@ static void map_group(game_state *state) static bool map_group_check(game_state *state, int canon, bool warn, int *nislands_r) { - int *dsf = state->solver->dsf, nislands = 0; + DSF *dsf = state->solver->dsf; + int nislands = 0; int x, y, i; bool allfull = true; struct island *is; @@ -1212,7 +1219,8 @@ static bool map_group_check(game_state *state, int canon, bool warn, static bool map_group_full(game_state *state, int *ngroups_r) { - int *dsf = state->solver->dsf, ngroups = 0; + DSF *dsf = state->solver->dsf; + int ngroups = 0; int i; bool anyfull = false; struct island *is; @@ -1267,7 +1275,8 @@ static void map_clear(game_state *state) static void solve_join(struct island *is, int direction, int n, bool is_max) { struct island *is_orth; - int d1, d2, *dsf = is->state->solver->dsf; + int d1, d2; + DSF *dsf = is->state->solver->dsf; game_state *state = is->state; /* for DINDEX */ is_orth = INDEX(is->state, gridi, @@ -1281,7 +1290,7 @@ static void solve_join(struct island *is, int direction, int n, bool is_max) if (n > 0 && !is_max) { d1 = DINDEX(is->x, is->y); d2 = DINDEX(is_orth->x, is_orth->y); - if (dsf_canonify(dsf, d1) != dsf_canonify(dsf, d2)) + if (!dsf_equivalent(dsf, d1, d2)) dsf_merge(dsf, d1, d2); } } @@ -1382,7 +1391,8 @@ static bool solve_island_stage1(struct island *is, bool *didsth_r) static bool solve_island_checkloop(struct island *is, int direction) { struct island *is_orth; - int *dsf = is->state->solver->dsf, d1, d2; + DSF *dsf = is->state->solver->dsf; + int d1, d2; game_state *state = is->state; if (is->state->allowloops) @@ -1399,7 +1409,7 @@ static bool solve_island_checkloop(struct island *is, int direction) d1 = DINDEX(is->x, is->y); d2 = DINDEX(is_orth->x, is_orth->y); - if (dsf_canonify(dsf, d1) == dsf_canonify(dsf, d2)) { + if (dsf_equivalent(dsf, d1, d2)) { /* two islands are connected already; don't join them. */ return true; } @@ -1457,7 +1467,8 @@ static bool solve_island_stage2(struct island *is, bool *didsth_r) static bool solve_island_subgroup(struct island *is, int direction) { struct island *is_join; - int nislands, *dsf = is->state->solver->dsf; + int nislands; + DSF *dsf = is->state->solver->dsf; game_state *state = is->state; debug(("..checking subgroups.\n")); @@ -1520,7 +1531,6 @@ static bool solve_island_stage3(struct island *is, bool *didsth_r) { int i, n, x, y, missing, spc, curr, maxb; bool didsth = false; - int wh = is->state->w * is->state->h; struct solver_state *ss = is->state->solver; assert(didsth_r); @@ -1544,7 +1554,7 @@ static bool solve_island_stage3(struct island *is, bool *didsth_r) maxb = -1; /* We have to squirrel the dsf away and restore it afterwards; * it is additive only, and can't be removed from. */ - memcpy(ss->tmpdsf, ss->dsf, wh*sizeof(int)); + dsf_copy(ss->tmpdsf, ss->dsf); for (n = curr+1; n <= curr+spc; n++) { solve_join(is, i, n, false); map_update_possibles(is->state); @@ -1560,7 +1570,7 @@ static bool solve_island_stage3(struct island *is, bool *didsth_r) } } solve_join(is, i, curr, false); /* put back to before. */ - memcpy(ss->dsf, ss->tmpdsf, wh*sizeof(int)); + dsf_copy(ss->dsf, ss->tmpdsf); if (maxb != -1) { /*debug_state(is->state);*/ @@ -1629,7 +1639,7 @@ static bool solve_island_stage3(struct island *is, bool *didsth_r) is->adj.points[j].dx ? G_LINEH : G_LINEV); if (before[i] != 0) continue; /* this idea is pointless otherwise */ - memcpy(ss->tmpdsf, ss->dsf, wh*sizeof(int)); + dsf_copy(ss->tmpdsf, ss->dsf); for (j = 0; j < is->adj.npoints; j++) { spc = island_adjspace(is, true, missing, j); @@ -1644,7 +1654,7 @@ static bool solve_island_stage3(struct island *is, bool *didsth_r) for (j = 0; j < is->adj.npoints; j++) solve_join(is, j, before[j], false); - memcpy(ss->dsf, ss->tmpdsf, wh*sizeof(int)); + dsf_copy(ss->dsf, ss->tmpdsf); if (got) { debug(("island at (%d,%d) must connect in direction (%d,%d) to" @@ -1763,8 +1773,8 @@ static game_state *new_state(const game_params *params) ret->completed = false; ret->solver = snew(struct solver_state); - ret->solver->dsf = snew_dsf(wh); - ret->solver->tmpdsf = snewn(wh, int); + ret->solver->dsf = dsf_new(wh); + ret->solver->tmpdsf = dsf_new(wh); ret->solver->refcount = 1; @@ -1813,8 +1823,8 @@ static game_state *dup_game(const game_state *state) static void free_game(game_state *state) { if (--state->solver->refcount <= 0) { - sfree(state->solver->dsf); - sfree(state->solver->tmpdsf); + dsf_free(state->solver->dsf); + dsf_free(state->solver->tmpdsf); sfree(state->solver); } @@ -2004,28 +2014,38 @@ generated: static const char *validate_desc(const game_params *params, const char *desc) { - int i, wh = params->w * params->h; + int i, j, wh = params->w * params->h, nislands = 0; + bool *last_row = snewn(params->w, bool); + memset(last_row, 0, params->w * sizeof(bool)); for (i = 0; i < wh; i++) { - if (*desc >= '1' && *desc <= '9') - /* OK */; - else if (*desc >= 'a' && *desc <= 'z') + if ((*desc >= '1' && *desc <= '9') || (*desc >= 'A' && *desc <= 'G')) { + nislands++; + /* Look for other islands to the left and above. */ + if ((i % params->w > 0 && last_row[i % params->w - 1]) || + last_row[i % params->w]) { + sfree(last_row); + return "Game description contains joined islands"; + } + last_row[i % params->w] = true; + } else if (*desc >= 'a' && *desc <= 'z') { + for (j = 0; j < *desc - 'a' + 1; j++) + last_row[(i + j) % params->w] = false; i += *desc - 'a'; /* plus the i++ */ - else if (*desc >= 'A' && *desc <= 'G') - /* OK */; - else if (*desc == 'V' || *desc == 'W' || - *desc == 'X' || *desc == 'Y' || - *desc == 'H' || *desc == 'I' || - *desc == 'J' || *desc == 'K') - /* OK */; - else if (!*desc) + } else if (!*desc) { + sfree(last_row); return "Game description shorter than expected"; - else + } else { + sfree(last_row); return "Game description contains unexpected character"; + } desc++; } + sfree(last_row); if (*desc || i > wh) return "Game description longer than expected"; + if (nislands < 2) + return "Game description has too few islands"; return NULL; } @@ -2105,32 +2125,47 @@ static char *ui_cancel_drag(game_ui *ui) ui->dragx_src = ui->dragy_src = -1; ui->dragx_dst = ui->dragy_dst = -1; ui->dragging = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui_cancel_drag(ui); - ui->cur_x = state->islands[0].x; - ui->cur_y = state->islands[0].y; - ui->cur_visible = false; + if (state != NULL) { + ui->cur_x = state->islands[0].x; + ui->cur_y = state->islands[0].y; + } + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->show_hints = false; return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Show possible bridge locations"; + ret[0].kw = "show-hints"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->show_hints; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->show_hints = cfg[0].u.boolean.bval; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -2138,6 +2173,20 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, { } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) + return ""; /* Actually shows cursor. */ + if (ui->dragging || button == CURSOR_SELECT2) + return "Finished"; + if (GRID(state, ui->cur_x, ui->cur_y) & G_ISLAND) + return "Select"; + } + return ""; +} + struct game_drawstate { int tilesize; int w, h; @@ -2307,7 +2356,7 @@ static char *update_drag_dst(const game_state *state, game_ui *ui, /*debug(("update_drag src (%d,%d) d(%d,%d) dst (%d,%d)\n", ui->dragx_src, ui->dragy_src, dx, dy, ui->dragx_dst, ui->dragy_dst));*/ - return UI_UPDATE; + return MOVE_UI_UPDATE; } static char *finish_drag(const game_state *state, game_ui *ui) @@ -2342,15 +2391,15 @@ static char *interpret_move(const game_state *state, game_ui *ui, char buf[80], *ret; grid_type ggrid = INGRID(state,gx,gy) ? GRID(state,gx,gy) : 0; bool shift = button & MOD_SHFT, control = button & MOD_CTRL; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { - if (!INGRID(state, gx, gy)) return NULL; + if (!INGRID(state, gx, gy)) return MOVE_UNUSED; ui->cur_visible = false; if (ggrid & G_ISLAND) { ui->dragx_src = gx; ui->dragy_src = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else return ui_cancel_drag(ui); } else if (button == LEFT_DRAG || button == RIGHT_DRAG) { @@ -2364,7 +2413,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, /* cancel a drag when we go back to the starting point */ ui->dragx_dst = -1; ui->dragy_dst = -1; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (button == LEFT_RELEASE || button == RIGHT_RELEASE) { if (ui->dragging) { @@ -2375,8 +2424,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, return ui_cancel_drag(ui); } ui_cancel_drag(ui); - if (!INGRID(state, gx, gy)) return NULL; - if (!(GRID(state, gx, gy) & G_ISLAND)) return NULL; + if (!INGRID(state, gx, gy)) return MOVE_UNUSED; + if (!(GRID(state, gx, gy) & G_ISLAND)) return MOVE_NO_EFFECT; sprintf(buf, "M%d,%d", gx, gy); return dupstr(buf); } @@ -2397,9 +2446,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->dragging) { int nx = ui->cur_x, ny = ui->cur_y; - move_cursor(button, &nx, &ny, state->w, state->h, false); + move_cursor(button, &nx, &ny, state->w, state->h, false, NULL); if (nx == ui->cur_x && ny == ui->cur_y) - return NULL; + return MOVE_NO_EFFECT; update_drag_dst(state, ui, ds, COORD(nx)+TILE_SIZE/2, COORD(ny)+TILE_SIZE/2); @@ -2451,19 +2500,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (!dingrid) break; } - if (!oingrid) return UI_UPDATE; + if (!oingrid) return MOVE_UI_UPDATE; } /* not reached */ found: ui->cur_x = nx; ui->cur_y = ny; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->dragging || button == CURSOR_SELECT2) { ui_cancel_drag(ui); @@ -2471,7 +2520,7 @@ found: sprintf(buf, "M%d,%d", ui->cur_x, ui->cur_y); return dupstr(buf); } else - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { grid_type v = GRID(state, ui->cur_x, ui->cur_y); if (v & G_ISLAND) { @@ -2480,7 +2529,7 @@ found: ui->dragy_src = ui->cur_y; ui->dragx_dst = ui->dragy_dst = -1; ui->drag_is_noline = (button == CURSOR_SELECT2); - return UI_UPDATE; + return MOVE_UI_UPDATE; } } } else if ((button >= '0' && button <= '9') || @@ -2498,7 +2547,7 @@ found: if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } for (i = 0; i < state->n_islands; ++i) { @@ -2525,15 +2574,15 @@ found: if (best_x != -1 && best_y != -1) { ui->cur_x = best_x; ui->cur_y = best_y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else - return NULL; + return MOVE_NO_EFFECT; } else if (button == 'g' || button == 'G') { ui->show_hints = !ui->show_hints; - return UI_UPDATE; + return MOVE_UI_UPDATE; } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -2557,6 +2606,8 @@ static game_state *execute_move(const game_state *state, const char *move) goto badmove; if (!INGRID(ret, x1, y1) || !INGRID(ret, x2, y2)) goto badmove; + /* Precisely one co-ordinate must differ between islands. */ + if ((x1 != x2) + (y1 != y2) != 1) goto badmove; is1 = INDEX(ret, gridi, x1, y1); is2 = INDEX(ret, gridi, x2, y2); if (!is1 || !is2) goto badmove; @@ -2568,6 +2619,7 @@ static game_state *execute_move(const game_state *state, const char *move) goto badmove; if (!INGRID(ret, x1, y1) || !INGRID(ret, x2, y2)) goto badmove; + if ((x1 != x2) + (y1 != y2) != 1) goto badmove; is1 = INDEX(ret, gridi, x1, y1); is2 = INDEX(ret, gridi, x2, y2); if (!is1 || !is2) goto badmove; @@ -2636,7 +2688,7 @@ static char *solve_game(const game_state *state, const game_state *currstate, */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2987,9 +3039,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, /* Clear screen, if required. */ if (!ds->started) { - draw_rect(dr, 0, 0, - TILE_SIZE * ds->w + 2 * BORDER, - TILE_SIZE * ds->h + 2 * BORDER, COL_BACKGROUND); #ifdef DRAW_GRID draw_rect_outline(dr, COORD(0)-1, COORD(0)-1, @@ -3177,22 +3226,19 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* 10mm squares by default. */ - game_compute_size(params, 1000, &pw, &ph); + game_compute_size(params, 1000, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int ts) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int ts) { int ink = print_mono_colour(dr, 0); int paper = print_mono_colour(dr, 1); @@ -3266,12 +3312,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3285,7 +3333,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; diff --git a/apps/plugins/puzzles/src/combi.c b/apps/plugins/puzzles/src/combi.c index 3460183c9c..132d74027e 100644 --- a/apps/plugins/puzzles/src/combi.c +++ b/apps/plugins/puzzles/src/combi.c @@ -71,40 +71,3 @@ void free_combi(combi_ctx *combi) sfree(combi->a); sfree(combi); } - -/* compile this with: - * gcc -o combi.exe -DSTANDALONE_COMBI_TEST combi.c malloc.c - */ -#ifdef STANDALONE_COMBI_TEST - -#include - -void fatal(const char *fmt, ...) -{ - abort(); -} - -int main(int argc, char *argv[]) -{ - combi_ctx *c; - int i, r, n; - - if (argc < 3) { - fprintf(stderr, "Usage: combi R N\n"); - exit(1); - } - - r = atoi(argv[1]); n = atoi(argv[2]); - c = new_combi(r, n); - printf("combi %d of %d, %d elements.\n", c->r, c->n, c->total); - - while (next_combi(c)) { - for (i = 0; i < c->r; i++) { - printf("%d ", c->a[i]); - } - printf("\n"); - } - free_combi(c); -} - -#endif diff --git a/apps/plugins/puzzles/src/cube.R b/apps/plugins/puzzles/src/cube.R deleted file mode 100644 index 85b081ec76..0000000000 --- a/apps/plugins/puzzles/src/cube.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -cube : [X] GTK COMMON cube cube-icon|no-icon - -cube : [G] WINDOWS COMMON cube cube.res|noicon.res - -ALL += cube[COMBINED] - -!begin am gtk -GAMES += cube -!end - -!begin >list.c - A(cube) \ -!end - -!begin >gamedesc.txt -cube:cube.exe:Cube:Rolling cube puzzle:Pick up all the blue squares by rolling the cube over them. -!end diff --git a/apps/plugins/puzzles/src/cube.c b/apps/plugins/puzzles/src/cube.c index 8c8c46faed..08788cbd65 100644 --- a/apps/plugins/puzzles/src/cube.c +++ b/apps/plugins/puzzles/src/cube.c @@ -7,7 +7,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -171,7 +175,7 @@ enum { LEFT, RIGHT, UP, DOWN, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT }; (ra)[0] = rx; (ra)[1] = ry; (ra)[2] = rz; \ } while (0) -#define APPROXEQ(x,y) ( SQ(x-y) < 0.1 ) +#define APPROXEQ(x,y) ( SQ(x-y) < 0.1F ) struct grid_square { float x, y; @@ -202,8 +206,8 @@ struct game_grid { }; #define SET_SQUARE(state, i, val) \ - ((state)->bluemask[(i)/32] &= ~(1 << ((i)%32)), \ - (state)->bluemask[(i)/32] |= ((!!val) << ((i)%32))) + ((state)->bluemask[(i)/32] &= ~(1UL << ((i)%32)), \ + (state)->bluemask[(i)/32] |= ((unsigned long)(!!val) << ((i)%32))) #define GET_SQUARE(state, i) \ (((state)->bluemask[(i)/32] >> ((i)%32)) & 1) @@ -542,12 +546,38 @@ static const char *validate_params(const game_params *params, bool full) if (params->solid < 0 || params->solid >= lenof(solids)) return "Unrecognised solid type"; + if (params->d1 < 0 || params->d2 < 0) + return "Grid dimensions may not be negative"; + if (solids[params->solid]->order == 4) { if (params->d1 <= 1 || params->d2 <= 1) return "Both grid dimensions must be greater than one"; + if (params->d2 > INT_MAX / params->d1) + return "Grid area must not be unreasonably large"; } else { if (params->d1 <= 0 && params->d2 <= 0) return "At least one grid dimension must be greater than zero"; + + /* + * Check whether d1^2 + d2^2 + 4 d1 d2 > INT_MAX, without overflow: + * + * First check d1^2 doesn't overflow by itself. + * + * Then check d2^2 doesn't exceed the remaining space between + * d1^2 and INT_MAX. + * + * If that's all OK then we know both d1 and d2 are + * individually less than the square root of INT_MAX, so we + * can safely multiply them and compare against the + * _remaining_ space. + */ + if ((params->d1 > 0 && params->d1 > INT_MAX / params->d1) || + (params->d2 > 0 && + params->d2 > (INT_MAX - params->d1*params->d1) / params->d2) || + (params->d2 > 0 && + params->d1*params->d2 > (INT_MAX - params->d1*params->d1 - + params->d2*params->d2) / params->d2)) + return "Grid area must not be unreasonably large"; } for (i = 0; i < 4; i++) @@ -761,7 +791,7 @@ static bool align_poly(const struct solid *solid, struct grid_square *sq, dist += SQ(solid->vertices[i*3+1] * flip - sq->points[j*2+1] + sq->y); dist += SQ(solid->vertices[i*3+2] - zmin); - if (dist < 0.1) { + if (dist < 0.1F) { matches++; index = i; } @@ -811,7 +841,7 @@ static struct solid *transform_poly(const struct solid *solid, bool flip, */ vx = ret->vertices[key1*3+0] - ret->vertices[key0*3+0]; vy = ret->vertices[key1*3+1] - ret->vertices[key0*3+1]; - assert(APPROXEQ(vx*vx + vy*vy, 1.0)); + assert(APPROXEQ(vx*vx + vy*vy, 1.0F)); vmatrix[0] = vx; vmatrix[3] = vy; vmatrix[6] = 0; vmatrix[1] = -vy; vmatrix[4] = vx; vmatrix[7] = 0; @@ -999,22 +1029,6 @@ static void free_game(game_state *state) sfree(state); } -static char *solve_game(const game_state *state, const game_state *currstate, - const char *aux, const char **error) -{ - return NULL; -} - -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - static game_ui *new_ui(const game_state *state) { return NULL; @@ -1024,15 +1038,6 @@ static void free_ui(game_ui *ui) { } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -1081,11 +1086,11 @@ static int find_move_dest(const game_state *from, int direction, for (j = 0; j < from->grid->squares[i].npoints; j++) { dist = (SQ(from->grid->squares[i].points[j*2] - points[0]) + SQ(from->grid->squares[i].points[j*2+1] - points[1])); - if (dist < 0.1) + if (dist < 0.1F) dkey[match++] = j; dist = (SQ(from->grid->squares[i].points[j*2] - points[2]) + SQ(from->grid->squares[i].points[j*2+1] - points[3])); - if (dist < 0.1) + if (dist < 0.1F) dkey[match++] = j; } @@ -1140,7 +1145,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, cy = (int)(state->grid->squares[state->current].y * GRID_SCALE) + ds->oy; if (x == cx && y == cy) - return NULL; /* clicked in exact centre! */ + return MOVE_NO_EFFECT; /* clicked in exact centre! */ angle = atan2(y - cy, x - cx); /* @@ -1191,11 +1196,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, direction = RIGHT; } } else - return NULL; + return MOVE_UNUSED; mask = state->grid->squares[state->current].directions[direction]; if (mask == 0) - return NULL; + return MOVE_NO_EFFECT; /* * Translate diagonal directions into orthogonal ones. @@ -1210,14 +1215,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (find_move_dest(state, direction, skey, dkey) < 0) - return NULL; + return MOVE_NO_EFFECT; if (direction == LEFT) return dupstr("L"); if (direction == RIGHT) return dupstr("R"); if (direction == UP) return dupstr("U"); if (direction == DOWN) return dupstr("D"); - return NULL; /* should never happen */ + return MOVE_NO_EFFECT; /* should never happen */ } static game_state *execute_move(const game_state *from, const char *move) @@ -1484,7 +1489,7 @@ static struct bbox find_bbox(const game_params *params) ((int)(((bb).d - (bb).u + 2*(solid)->border) * gs)) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { struct bbox bb = find_bbox(params); @@ -1734,19 +1739,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame cube #endif @@ -1766,14 +1758,16 @@ const struct game thegame = { new_game, dup_game, free_game, - false, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, /* solve */ + false, NULL, NULL, /* can_format_as_text_now, text_format */ + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, PREFERRED_GRID_SCALE, game_compute_size, game_set_size, @@ -1785,8 +1779,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/devel.but b/apps/plugins/puzzles/src/devel.but index 7521596df9..c201a3e6c9 100644 --- a/apps/plugins/puzzles/src/devel.but +++ b/apps/plugins/puzzles/src/devel.but @@ -32,10 +32,11 @@ Puzzle Collection (henceforth referred to simply as \q{Puzzles}), for use by anyone attempting to implement a new puzzle or port to a new platform. -This guide is believed correct as of r6190. Hopefully it will be -updated along with the code in future, but if not, I've at least -left this version number in here so you can figure out what's -changed by tracking commit comments from there onwards. +This guide is believed correct as of \cw{git} commit +\cw{a2212e82aa2f4b9a4ee22783d6fed2761c213432}. Hopefully it will be +updated along with the code in future, but if not, I've at least left +this version number in here so you can figure out what's changed by +tracking commit comments from there onwards. \C{intro} Introduction @@ -52,25 +53,21 @@ that you replace completely when you port to a different platform. So it's responsible for all system calls, all GUI interaction, and anything else platform-specific. -The current front ends in the main code base are for Windows, GTK -and MacOS X; I also know of a third-party front end for PalmOS. - The front end contains \cw{main()} or the local platform's equivalent. Top-level control over the application's execution flow belongs to the front end (it isn't, for example, a set of functions called by a universal \cw{main()} somewhere else). The front end has complete freedom to design the GUI for any given -port of Puzzles. There is no centralised mechanism for maintaining -the menu layout, for example. This has a cost in consistency (when I -\e{do} want the same menu layout on more than one platform, I have -to edit two pieces of code in parallel every time I make a change), -but the advantage is that local GUI conventions can be conformed to -and local constraints adapted to. For example, MacOS X has strict -human interface guidelines which specify a different menu layout -from the one I've used on Windows and GTK; there's nothing stopping -the OS X front end from providing a menu layout consistent with -those guidelines. +port of Puzzles. There is no centralised mechanism for maintaining the +menu layout, for example. This has a cost in consistency (when I +\e{do} want the same menu layout on more than one platform, I have to +edit N pieces of code in parallel every time I make a change), but the +advantage is that local GUI conventions can be conformed to and local +constraints adapted to. For example, MacOS has strict human interface +guidelines which specify a different menu layout from the one I've +used on Windows and GTK; there's nothing stopping the MacOS front end +from providing a menu layout consistent with those guidelines. Although the front end is mostly caller rather than the callee in its interactions with other parts of the code, it is required to @@ -143,9 +140,10 @@ etc). \b Handling the dialog boxes which ask the user for a game ID. \b Handling serialisation of entire games (for loading and saving a -half-finished game to a disk file, or for handling application -shutdown and restart on platforms such as PalmOS where state is -expected to be saved). +half-finished game to a disk file; for handling application shutdown +and restart on platforms such as PalmOS where state is expected to be +saved; for storing the previous game in order to undo and redo across +a New Game event). Thus, there's a lot of work done once by the mid-end so that individual back ends don't have to worry about it. All the back end @@ -193,9 +191,8 @@ end module builds a different puzzle. \b On platforms such as MacOS X and PalmOS, which build all the puzzles into a single monolithic binary, the game structure in each back end must have a different name, and there's a helper module -\c{list.c} (constructed automatically by the same Perl script that -builds the \cw{Makefile}s) which contains a complete list of those -game structures. +\c{list.c} which constructs a complete list of those game structures +from a header file generated by CMake. On the latter type of platform, source files may assume that the preprocessor symbol \c{COMBINED} has been defined. Thus, the usual @@ -249,14 +246,15 @@ yet been necessary to do this in any puzzle so far, but the capability is there just in case.) \c{game_params} is also the only structure which the game's -\cw{compute_size()} function may refer to; this means that any -aspect of the game which affects the size of the window it needs to -be drawn in must be stored in \c{game_params}. In particular, this -imposes the fundamental limitation that random game generation may -not have a random effect on the window size: game generation -algorithms are constrained to work by starting from the grid size -rather than generating it as an emergent phenomenon. (Although this -is a restriction in theory, it has not yet seemed to be a problem.) +\cw{compute_size()} function may refer to; this means that any aspect +of the game which affects the size of the window it needs to be drawn +in (other than the magnification level) must be stored in +\c{game_params}. In particular, this imposes the fundamental +limitation that random game generation may not have a random effect on +the window size: game generation algorithms are constrained to work by +starting from the grid size rather than generating it as an emergent +phenomenon. (Although this is a restriction in theory, it has not yet +seemed to be a problem.) \S{backend-game-state} \c{game_state} @@ -268,14 +266,25 @@ The mid-end keeps \c{game_state}s in a list, and adds to the list every time the player makes a move; the Undo and Redo functions step back and forth through that list. -Therefore, a good means of deciding whether a data item needs to go -in \c{game_state} is: would a player expect that data item to be -restored on undo? If so, put it in \c{game_state}, and this will -automatically happen without you having to lift a finger. If not -\dash for example, the deaths counter in Mines is precisely -something that does \e{not} want to be reset to its previous state -on an undo \dash then you might have found a data item that needs to -go in \c{game_ui} instead. +Therefore, a good means of deciding whether a data item needs to go in +\c{game_state} is: would a player expect that data item to be restored +on undo? If so, put it in \c{game_state}, and this will automatically +happen without you having to lift a finger. If not, then you might +have found a data item that needs to go in \c{game_ui} instead. + +Two quite different examples of this: + +\b if the game provides an interface for making moves by moving a +cursor around the grid with the keyboard and pressing some other key +when you get to a square you want to change, then the location of that +cursor belongs in \c{game_ui}, because the player will want to undo +one \e{square change} at a time, not one \e{cursor movement} at a +time. + +\b Mines tracks the number of times you opened a mine square and died. +Every time you do that, you can only continue the game by pressing +Undo. So the deaths counter belongs in \c{game_ui}, because otherwise, +it would revert to 0 every time you undid your mistaken move. During play, \c{game_state}s are often passed around without an accompanying \c{game_params} structure. Therefore, any information @@ -293,12 +302,12 @@ is passed to every call to the game redraw function, so that it can remember what it has already drawn and what needs redrawing. A typical use for a \c{game_drawstate} is to have an array mirroring -the array of grid squares in the \c{game_state}; then every time the -redraw function was passed a \c{game_state}, it would loop over all -the squares, and physically redraw any whose description in the -\c{game_state} (i.e. what the square needs to look like when the -redraw is completed) did not match its description in the -\c{game_drawstate} (i.e. what the square currently looks like). +the array of grid squares in the \c{game_state}, but describing what +was drawn in the window on the most recent redraw. This is used to +identify the squares that need redrawing next time, by deciding what +the new value in that array should be, and comparing it to what was +drawn last time. See \k{writing-howto-redraw} for more on this +subject. \c{game_drawstate} is occasionally completely torn down and reconstructed by the mid-end, if the user somehow forces a full @@ -323,23 +332,49 @@ game ID etc). It persists until the user finishes playing that game and begins another one (or closes the window); in particular, \q{Restart Game} does \e{not} destroy the \c{game_ui}. -\c{game_ui} is useful for implementing user-interface state which is -not part of \c{game_state}. Common examples are keyboard control -(you wouldn't want to have to separately Undo through every cursor -motion) and mouse dragging. See \k{writing-keyboard-cursor} and -\k{writing-howto-dragging}, respectively, for more details. +There are various things that you might store in \c{game_ui}, which +are conceptually different from each other, but I haven't yet found a +need to split them out into smaller sub-structures for different +purposes: + +\dt Transient UI state: + +\dd Storing a piece of UI state in \c{game_state} means that you can +only update it by appending a move to the undo chain. Some UI state +shouldn't really be treated this way. For example, if your puzzle has +a keyboard-controlled cursor, you probably don't want every cursor +movement to be an undoable action, because the history of where the +cursor went just isn't interesting. More likely the cursor should just +move freely, and the only undoable actions are the ones where you +modify the element under the cursor. So you'd store the cursor +position in \c{game_ui} rather than \c{game_state}. See +\k{writing-keyboard-cursor} for more details. + +\lcont{ Another example of this is the state of an ongoing mouse drag. +If there's an undoable action involved, it will probably occur when +the drag is released. In between, you still need to store state that +the redraw function will use to update the display \dash and that can +live in \c{game_ui}. See \k{writing-howto-dragging} for more details +of this. } + +\dt Persistent UI state: + +\dd An example of this is the counter of deaths in Mines or Inertia. +This shouldn't be reverted by pressing Undo, for the opposite reason +to the cursor position: the cursor position is too boring to store the +history of, but the deaths counter is too \e{important}! + +\dt Information about recent changes to the game state: -Another use for \c{game_ui} is to store highly persistent data such -as the Mines death counter. This is conceptually rather different: -where the Net cursor position was \e{not important enough} to -preserve for the player to restore by Undo, the Mines death counter -is \e{too important} to permit the player to revert by Undo! +\dd This is used in Mines, for example, to indicate whether a +requested \q{flash} should be a white flash for victory or a red flash +for defeat; see \k{writing-flash-types}. -A final use for \c{game_ui} is to pass information to the redraw -function about recent changes to the game state. This is used in -Mines, for example, to indicate whether a requested \q{flash} should -be a white flash for victory or a red flash for defeat; see -\k{writing-flash-types}. +\dt User preferences: + +\dd Any user preference about display or UI handled by +\cw{get_prefs()} and \cw{set_prefs()} will need to live in +\c{game_ui}, because that's the structure that those functions access. \H{backend-simple} Simple data in the back end @@ -356,24 +391,41 @@ name will be used in window titles, in game selection menus on monolithic platforms, and anywhere else that the front end needs to know the name of a game. -\S{backend-winhelp} \c{winhelp_topic} +\S{backend-winhelp} \c{winhelp_topic} and \c{htmlhelp_topic} -\c const char *winhelp_topic; +\c const char *winhelp_topic, *htmlhelp_topic; -This member is used on Windows only, to provide online help. +These members are used on Windows only, to provide online help. Although the Windows front end provides a separate binary for each puzzle, it has a single monolithic help file; so when a user selects \q{Help} from the menu, the program needs to open the help file and jump to the chapter describing that particular puzzle. -Therefore, each chapter in \c{puzzles.but} is labelled with a -\e{help topic} name, similar to this: +This code base still supports the legacy \cw{.HLP} Windows Help format +as well as the less old \cw{.CHM} HTML Help format. The two use +different methods of identifying topics, so you have to specify both. + +Each chapter about a puzzle in \c{puzzles.but} is labelled with a +\e{help topic} name for Windows Help, which typically appears just +after the \cw{\\C} chapter title paragraph, similar to this: +\c \C{net} \i{Net} +\c \c \cfg{winhelp-topic}{games.net} -And then the corresponding game back end encodes the topic string -(here \cq{games.net}) in the \c{winhelp_topic} element of the game -structure. +But HTML Help is able to use the Halibut identifier for the chapter +itself, i.e. the keyword that appears in braces immediatey after the +\cw{\\C}. + +So the corresponding game back end encodes the \c{winhelp-topic} +string (here \cq{games.net}) in the \c{winhelp_topic} element of the +game structure, and puts the chapter identifier (here \cq{net}) in the +\c{htmlhelp_topic} element. For example: + +\c const struct game thegame = { +\c "Net", "games.net", "net", +\c // ... +\c }; \H{backend-params} Handling game parameter sets @@ -439,8 +491,8 @@ from the game, and before passing it on to the front end. \c char *(*encode_params)(const game_params *params, bool full); The job of this function is to take a \c{game_params}, and encode it -in a string form for use in game IDs. The return value must be a -newly allocated C string, and \e{must} not contain a colon or a hash +in a printable ASCII string form for use in game IDs. The return value must +be a newly allocated C string, and \e{must} not contain a colon or a hash (since those characters are used to mark the end of the parameter section in a game ID). @@ -454,7 +506,7 @@ away with commas, periods or underscores without causing anybody any major inconvenience. If you venture far beyond that, you're likely to irritate \e{somebody}. -(At the time of writing this, all existing games have purely +(At the time of writing this, most existing games have purely alphanumeric string parameter formats. Usually these involve a letter denoting a parameter, followed optionally by a number giving the value of that parameter, with a few mandatory parts at the @@ -466,15 +518,17 @@ call to \cw{decode_params()} (\k{backend-decode-params}) will yield an identical structure. If \c{full} is \cw{false}, however, you should leave out anything which is not necessary to describe a \e{specific puzzle instance}, i.e. anything which only takes effect -when a new puzzle is \e{generated}. For example, the Solo -\c{game_params} includes a difficulty rating used when constructing -new puzzles; but a Solo game ID need not explicitly include the -difficulty, since to describe a puzzle once generated it's -sufficient to give the grid dimensions and the location and contents -of the clue squares. (Indeed, one might very easily type in a puzzle -out of a newspaper without \e{knowing} what its difficulty level is -in Solo's terminology.) Therefore, Solo's \cw{encode_params()} only -encodes the difficulty level if \c{full} is set. +when a new puzzle is \e{generated}. + +For example, the Solo \c{game_params} includes a difficulty rating +used when constructing new puzzles; but a Solo game ID need not +explicitly include the difficulty, since to describe a puzzle once +generated it's sufficient to give the grid dimensions and the location +and contents of the clue squares. (Indeed, one might very easily type +in a puzzle out of a newspaper without \e{knowing} what its difficulty +level is in Solo's terminology.) Therefore, Solo's +\cw{encode_params()} only encodes the difficulty level if \c{full} is +set. \S{backend-decode-params} \cw{decode_params()} @@ -489,7 +543,7 @@ to create a \e{new} \c{game_params}, but to modify an existing one. This function can receive a string which only encodes a subset of the parameters. The most obvious way in which this can happen is if the string was constructed by \cw{encode_params()} with its \c{full} -parameter set to \cw{FALSE}; however, it could also happen if the +parameter set to \cw{false}; however, it could also happen if the user typed in a parameter set manually and missed something out. Be prepared to deal with a wide range of possibilities. @@ -551,9 +605,10 @@ its initial value; the front end will modify the value fields and return the updated array to \cw{custom_params()} (see \k{backend-custom-params}). -The \cw{config_item} structure contains the following elements: +The \cw{config_item} structure contains the following elements used by +this function: -\c char *name; +\c const char *name; \c int type; \c union { /* type-specific fields */ } u; \e iiiiiiiiiiiiiiiiiiiiiiiiii @@ -592,9 +647,7 @@ of the input box. For controls of this type, \c{u.boolean} contains a single field -\c int bval; - -which is either \cw{TRUE} or \cw{FALSE}. +\c bool bval; } @@ -634,8 +687,8 @@ The array returned from this function is expected to have filled in the initial values of all the controls according to the input \c{game_params} structure. -If the game's \c{can_configure} flag is set to \cw{FALSE}, this -function is never called and need not do anything at all. +If the game's \c{can_configure} flag is set to \cw{false}, this +function is never called and can be \cw{NULL}. \S{backend-custom-params} \cw{custom_params()} @@ -659,8 +712,63 @@ This function is not expected to (and indeed \e{must not}) free the input \c{config_item} array. (If the parameters fail to validate, the dialog box will stay open.) -If the game's \c{can_configure} flag is set to \cw{FALSE}, this -function is never called and need not do anything at all. +If the game's \c{can_configure} flag is set to \cw{false}, this +function is never called and can be \cw{NULL}. + +\S{backend-get-prefs} \cw{get_prefs()} + +\c config_item *(*get_prefs)(game_ui *ui); + +This function works very like \cw{configure()}, but instead of +receiving a \c{game_params} and returning GUI elements describing the +data in it, this function receives a \c{game_ui} and returns GUI +elements describing any user preferences stored in that. + +This function should only deal with fields of \c{game_ui} that are +user-settable preferences. In-game state like cursor position and +mouse drags, or per-game state like death counters, are nothing to do +with this function. + +If there are no user preferences, you can set both this function +pointer and \c{set_prefs} to \cw{NULL}. + +If you implement these functions, you must also ensure that your +game's \cw{new_ui()} function can be called with a null \c{game_state} +pointer. (See \k{backend-new-ui}.) + +In every \c{config_item} returned from this function, you must set an +additional field beyond the ones described in \k{backend-configure}: + +\c const char *kw; + +This should be an identifying keyword for the user preference in +question, suitable for use in configuration files. That means it +should remain stable, even if the user-facing wording in the \c{name} +field is reworded for clarity. If it doesn't stay stable, old +configuration files will not be read correctly. + +For \c{config_item}s of type \cw{C_CHOICES}, you must also set an +extra field in \c{u.choices}: + +\c const char *choicekws; + +This has the same structure as the \c{choicenames} field (a list of +values delimited by the first character in the whole string), and it +provides an identifying keyword for each individual choice in the +list, in the same order as the entries of \c{choicenames}. + +\S{backend-set-prefs} \cw{set_prefs()} + +\c void (*set_prefs)(game_ui *ui, const config_item *cfg); + +This function is the counterpart to \cw{set_prefs()}, as +\cw{custom_params()} is to \cw{configure()}. It receives an array of +\c{config_item}s which was originally created by \cw{get_prefs()}, +with the controls' values updated from user input, and it should +transcribe the new settings into the provided \c{game_ui}. + +If there are no user preferences, you can set both this function +pointer and \c{get_prefs} to \cw{NULL}. \S{backend-validate-params} \cw{validate_params()} @@ -718,8 +826,8 @@ ensuring solubility and uniqueness as appropriate. As input it is given a \c{game_params} structure and a random state (see \k{utils-random} for the random number API). It must invent a -puzzle instance, encode it in string form, and return a dynamically -allocated C string containing that encoding. +puzzle instance, encode it in printable ASCII string form, and +return a dynamically allocated C string containing that encoding. Additionally, it may return a second dynamically allocated string in \c{*aux}. (If it doesn't want to, then it can leave that parameter @@ -824,9 +932,17 @@ allocations contained within it. \c game_ui *(*new_ui)(const game_state *state); This function allocates and returns a new \c{game_ui} structure for -playing a particular puzzle. It is passed a pointer to the initial -\c{game_state}, in case it needs to refer to that when setting up -the initial values for the new game. +playing a particular puzzle. + +Usually, this function is passed a pointer to the initial +\c{game_state}, in case it needs to refer to that when setting up the +initial values for the new game. + +However, if the puzzle defines \c{get_prefs()} and \c{set_prefs()} +functions, then this function may also be called with +\cw{state==NULL}. In this situation it must still allocate a +\c{game_ui} which can be used by \c{get_prefs()} and \c{set_prefs()}, +although it need not be usable for actually playing a game. \S{backend-free-ui} \cw{free_ui()} @@ -840,8 +956,8 @@ allocations contained within it. \c char *(*encode_ui)(const game_ui *ui); This function encodes any \e{important} data in a \c{game_ui} -structure in string form. It is only called when saving a -half-finished game to a file. +structure in printable ASCII string form. It is only called when +saving a half-finished game to a file. It should be used sparingly. Almost all data in a \c{game_ui} is not important enough to save. The location of the keyboard-controlled @@ -859,13 +975,25 @@ user could edit the save file by hand... But if the user is \e{that} determined to cheat, they could just as easily modify the game's source.) +The \cw{encode_ui()} function is optional. If a back-end doesn't need +this function it can just set the pointer to \cw{NULL}. + \S{backend-decode-ui} \cw{decode_ui()} -\c void (*decode_ui)(game_ui *ui, const char *encoding); +\c void (*decode_ui)(game_ui *ui, const char *encoding, +\c const game_state *state); This function parses a string previously output by \cw{encode_ui()}, -and writes the decoded data back into the provided \c{game_ui} -structure. +and writes the decoded data back into the freshly-created \c{game_ui} +structure provided. If the string is invalid, the function should do +the best it can, which might just mean not changing the \c{game_ui} +structure at all. This might happen if a save file is corrupted, or +simply from a newer version that encodes more \c{game_ui} data. The +current \c{game_state} is provided in case the function needs to +refer to it for validation. + +Like \cw{encode_ui()}, \cw{decode_ui()} is optional. If a back-end +doesn't need this function it can just set the pointer to \cw{NULL}. \S{backend-changed-state} \cw{changed_state()} @@ -928,13 +1056,18 @@ puzzle's drawing area. pointer will be to read the game's tile size parameter in order to divide mouse coordinates by it.) -\cw{interpret_move()} may return in three different ways: +\cw{interpret_move()} may return in four different ways: -\b Returning \cw{NULL} indicates that no action whatsoever occurred -in response to the input event; the puzzle was not interested in it -at all. +\b Returning \cw{MOVE_UNUSED} or \cw{MOVE_NO_EFFECT} indicates that no +action whatsoever occurred in response to the input event; the puzzle +was not interested in it at all. The distinction between this is that +\cw{MOVE_NO_EFFECT} implies that the state of the game is what makes +the event uninteresting, while \cw{MOVE_NO_EFFECT} means that the +event is intrinsically uninteresting. For example, a mouse click on +an already-revealed square in Mines might return \cw{MOVE_NO_EFFECT} +while a click outside the board would return \cw{MOVE_UNUSED}. -\b Returning the special value \cw{UI_UPDATE} indicates that the input +\b Returning the special value \cw{MOVE_UI_UPDATE} indicates that the input event has resulted in a change being made to the \c{game_ui} which will require a redraw of the game window, but that no actual \e{move} was made (i.e. no new \c{game_state} needs to be created). @@ -942,8 +1075,8 @@ was made (i.e. no new \c{game_state} needs to be created). \b Returning anything else indicates that a move was made and that a new \c{game_state} must be created. However, instead of actually constructing a new \c{game_state} itself, this function is required -to return a string description of the details of the move. This -string will be passed to \cw{execute_move()} +to return a printable ASCII string description of the details of the +move. This string will be passed to \cw{execute_move()} (\k{backend-execute-move}) to actually create the new \c{game_state}. (Encoding moves as strings in this way means that the mid-end can keep the strings as well as the game states, and the @@ -952,7 +1085,8 @@ strings can be written to disk when saving the game and fed to The return value from \cw{interpret_move()} is expected to be dynamically allocated if and only if it is not either \cw{NULL} -\e{or} the special string constant \c{UI_UPDATE}. +\e{or} one of the special string constants \cw{MOVE_UNUSED}, +\cw{MOVE_NO_EFFECT}, or \cw{MOVE_UI_UPDATE}. After this function is called, the back end is permitted to rely on some subsequent operations happening in sequence: @@ -999,19 +1133,21 @@ mouse button will have appeared in between. \dd Indicate that an arrow key was pressed. -\dt \cw{CURSOR_SELECT} +\dt \cw{CURSOR_SELECT}, \cw{CURSOR_SELECT2} -\dd On platforms which have a prominent \q{select} button alongside -their cursor keys, indicates that that button was pressed. +\dd On platforms which have one or two prominent \q{select} button +alongside their cursor keys, indicates that one of those buttons was +pressed. On other platforms, these represent the Enter (or Return) +and Space keys respectively. In addition, there are some modifiers which can be bitwise-ORed into the \c{button} parameter: \dt \cw{MOD_CTRL}, \cw{MOD_SHFT} -\dd These indicate that the Control or Shift key was pressed -alongside the key. They only apply to the cursor keys, not to mouse -buttons or anything else. +\dd These indicate that the Control or Shift key was pressed alongside +the key. They only apply to the cursor keys and the ASCII horizontal +tab character \cw{\\t}, not to mouse buttons or anything else. \dt \cw{MOD_NUM_KEYPAD} @@ -1025,8 +1161,10 @@ input probably just wants to treat the numeric keypad as numbers). \dt \cw{MOD_MASK} \dd This mask is the bitwise OR of all the available modifiers; you -can bitwise-AND with \cw{~MOD_MASK} to strip all the modifiers off -any input value. +can bitwise-AND with \cw{~MOD_MASK} to strip all the modifiers off any +input value; as this is a common operation, the +\cw{STRIP_BUTTON_MODIFIERS()} macro can do this for you (see +\k{utils-strip-button-modifiers}). \S{backend-execute-move} \cw{execute_move()} @@ -1058,7 +1196,8 @@ offer the \q{Solve} menu option. \c const char *aux, const char **error); This function is called when the user selects the \q{Solve} option -from the menu. +from the menu. If \cw{can_solve} is \cw{false} then it will never +be called and can be \cw{NULL}. It is passed two input game states: \c{orig} is the game state from the very start of the puzzle, and \c{curr} is the current one. @@ -1075,8 +1214,8 @@ it may return \cw{NULL}. If it does this, it must also set \q{Solution not known for this puzzle}); that error message is not expected to be dynamically allocated. -If this function \e{does} produce a solution, it returns a move string -suitable for feeding to \cw{execute_move()} +If this function \e{does} produce a solution, it returns a printable +ASCII move string suitable for feeding to \cw{execute_move()} (\k{backend-execute-move}). Like a (non-empty) string returned from \cw{interpret_move()}, the returned string should be dynamically allocated. @@ -1132,15 +1271,15 @@ requirement that the \q{tile size} be proportional to the game window size. Window size is required to increase monotonically with \q{tile size}, however. -The data element \c{preferred_tilesize} indicates the tile size -which should be used in the absence of a good reason to do otherwise -(such as the screen being too small, or the user explicitly -requesting a resize if that ever gets implemented). +The data element \c{preferred_tilesize} indicates the tile size which +should be used in the absence of a good reason to do otherwise (such +as the screen being too small to fit the whole puzzle, or the user +explicitly requesting a resize). \S{backend-compute-size} \cw{compute_size()} \c void (*compute_size)(const game_params *params, int tilesize, -\c int *x, int *y); +\c const game_ui *ui, int *x, int *y); This function is passed a \c{game_params} structure and a tile size. It returns, in \c{*x} and \c{*y}, the size in pixels of the drawing @@ -1193,6 +1332,12 @@ end's default colour as their background, apart from a few which depend on drawing relief highlights so they adjust the background colour if it's too light for highlights to show up against it. +The first colour in the list is slightly special. The mid-end fills +the drawing area with it before the first call to \cw{redraw()} (see +\k{backend-redraw}). Some front ends also use it fill the part of the +puzzle window outside the puzzle. This means that it is usually +sensible to make colour 0 the background colour for the puzzle. + Note that the colours returned from this function are for \e{drawing}, not for printing. Printing has an entirely different colour allocation policy. @@ -1275,7 +1420,7 @@ activity, so that the victory flash in Net is not cancelled by that final locking move. The input parameters to \cw{flash_length()} are exactly the same as -the ones to \cw{anim_length()}. +the ones to \cw{anim_length()}: see \k{backend-anim-length}. Just like \cw{anim_length()}, when this function is called, it may rely on \cw{changed_state()} having been called previously, so if it @@ -1303,7 +1448,7 @@ containing the cursor (in games that have one), or other region of interest. This function is called by only -\cw{midend_get_cursor_location()}(\k{midend-get-cursor-location}). Its +\cw{midend_get_cursor_location()} (\k{midend-get-cursor-location}). Its purpose is to allow front ends to query the location of the backend's cursor. With knowledge of this location, a front end can, for example, ensure that the region of interest remains visible if the puzzle is @@ -1392,6 +1537,14 @@ that the animation has already been running. If \c{oldstate} is \cw{NULL}, then \c{anim_time} is unused (and will hopefully be set to zero to avoid confusion). +\c{dir} specifies the chronological order of those states: if it is +positive, then the transition is the result of a move or a redo (and +so \c{newstate} is the later of the two moves), whereas if it is +negative then the transition is the result of an undo (so that +\c{newstate} is the \e{earlier} move). This allows move animations +that are not time-symmetric (such as Inertia, where gems are consumed +during the animation) to be drawn the right way round. + \c{flash_time}, if it is is non-zero, denotes that the game is in the middle of a flash, and gives the time since the start of the flash. See \k{backend-flash-length} for general discussion of @@ -1402,7 +1555,9 @@ The very first time this function is called for a new area. Since this often involves drawing visual furniture which is never subsequently altered, it is often simplest to arrange this by having a special \q{first time} flag in the draw state, and -resetting it after the first redraw. +resetting it after the first redraw. This function can assume that +the mid-end has filled the drawing area with colour 0 before the first +call. When this function (or any subfunction) calls the drawing API, it is expected to pass colour indices which were previously defined by the @@ -1424,7 +1579,7 @@ Twiddle, inherently involve moving things around and so would not make sense to print.) If this flag is \cw{false}, then the functions \cw{print_size()} -and \cw{print()} will never be called. +and \cw{print()} will never be called and can be \cw{NULL}. \S{backend-can-print-in-colour} \c{can_print_in_colour} @@ -1440,18 +1595,20 @@ ignored. \S{backend-print-size} \cw{print_size()} -\c void (*print_size)(const game_params *params, float *x, float *y); +\c void (*print_size)(const game_params *params, const game_ui *ui, +\c float *x, float *y); This function is passed a \c{game_params} structure and a tile size. It returns, in \c{*x} and \c{*y}, the preferred size in \e{millimetres} of that puzzle if it were to be printed out on paper. -If the \c{can_print} flag is \cw{FALSE}, this function will never be +If the \c{can_print} flag is \cw{false}, this function will never be called. \S{backend-print} \cw{print()} -\c void (*print)(drawing *dr, const game_state *state, int tilesize); +\c void (*print)(drawing *dr, const game_state *state, +\c const game_ui *ui, int tilesize); This function is called when a puzzle is to be printed out on paper. It should use the drawing API functions (see \k{drawing}) to print @@ -1500,7 +1657,7 @@ write \c c = print_mono_colour(dr, 0); assert(c == COL_THIS); \c c = print_mono_colour(dr, 0); assert(c == COL_THAT); -If the \c{can_print} flag is \cw{FALSE}, this function will never be +If the \c{can_print} flag is \cw{false}, this function will never be called. \H{backend-misc} Miscellaneous @@ -1522,7 +1679,8 @@ just too difficult. If this field is \cw{false}, the functions \cw{can_format_as_text_now()} (\k{backend-can-format-as-text-now}) -and \cw{text_format()} (\k{backend-text-format}) are never called. +and \cw{text_format()} (\k{backend-text-format}) are never called +and can be \cw{NULL}. \S{backend-can-format-as-text-now} \c{can_format_as_text_now()} @@ -1544,7 +1702,7 @@ game of exactly the same type is generated. This function should not take into account aspects of the game parameters which are not encoded by \cw{encode_params()} (\k{backend-encode-params}) when the \c{full} parameter is set to -\cw{FALSE}. Such parameters will not necessarily match up between a +\cw{false}. Such parameters will not necessarily match up between a call to this function and a subsequent call to \cw{text_format()} itself. (For instance, game \e{difficulty} should not affect whether the game can be copied to the clipboard. Only the actual visible @@ -1561,8 +1719,8 @@ ends. This function will only ever be called if the back end field \c{can_format_as_text_ever} (\k{backend-can-format-as-text-ever}) is -\cw{TRUE} \e{and} the function \cw{can_format_as_text_now()} -(\k{backend-can-format-as-text-now}) has returned \cw{TRUE} for the +\cw{true} \e{and} the function \cw{can_format_as_text_now()} +(\k{backend-can-format-as-text-now}) has returned \cw{true} for the currently selected game parameters. The returned string may contain line endings (and will probably want @@ -1579,7 +1737,9 @@ whether that should come with a newline or not.) This field is set to \cw{true} if the puzzle has a use for a textual status line (to display score, completion status, currently active -tiles, etc). +tiles, etc). If the \c{redraw()} function ever intends to call +\c{status_bar()} in the drawing API (\k{drawing-status-bar}), then it +should set this flag to \c{true}. \S{backend-is-timed} \c{is_timed} @@ -1589,7 +1749,7 @@ This field is \cw{true} if the puzzle is time-critical. If so, the mid-end will maintain a game timer while the user plays. If this field is \cw{false}, then \cw{timing_state()} will never be -called and need not do anything. +called and can be \cw{NULL}. \S{backend-timing-state} \cw{timing_state()} @@ -1618,7 +1778,7 @@ the game size and the backspace character, \cw{\\b}, even though it play the game. Each \cw{key_label} item contains the following fields: \c struct key_label { -\c const char *label; /* label for frontend use */ +\c char *label; /* label for frontend use */ \c int button; /* button to pass to midend */ \c } key_label; @@ -1628,6 +1788,12 @@ the backend to \cw{NULL}, in which case the midend will instead call label. The \cw{button} field is the associated code that can be passed to the midend when the frontend deems appropriate. +If \cw{label} is not \cw{NULL}, then it's a dynamically allocated +string. Therefore, freeing an array of these structures needs more +than just a single free operatio. The function \c{free_keys()} +(\k{utils-free-keys}) can be used to free a whole array of these +structures conveniently. + The backend should set \cw{*nkeys} to the number of elements in the returned array. @@ -1640,6 +1806,44 @@ This function should not be called directly by frontends. Instead, frontends should use \cw{midend_request_keys()} (\k{midend-request-keys}). +\S{backend-current-key-label} \cw{current_key_label()} + +\c const char *(*current_key_label)(const game_ui *ui, +\c const game_state *state, +\c int button); + +This function is called to ask the back-end how certain keys should be +labelled on platforms (such a feature phones) where this is +conventional. +These labels are expected to reflect what the keys will do right now, +so they can change depending on the game and UI state. + +The \c{ui} and \c{state} arguments describe the state of the game for +which key labels are required. +The \c{button} argument is the same as the one passed to +\cw{interpret_move()}. +At present, the only values of \c{button} that can be passed to +\cw{current_key_label()} are \cw{CURSOR_SELECT} and \cw{CURSOR_SELECT2}. +The return value is a short string describing what the requested key +will do if pressed. +Usually the string should be a static string constant. +If it's really necessary to use a dynamically-allocated string, it +should remain valid until the next call to \cw{current_key_label()} or +\cw{free_ui()} with the same \cw{game_ui} (so it can be referenced from +the \cw{game_ui} and freed at the next one of those calls). + +There's no fixed upper limit on the length of string that this +function can return, but more than about 12 characters is likely to +cause problems for front-ends. If two buttons have the same effect, +their labels should be identical so that the front end can detect +this. Similarly, keys that do different things should have different +labels. The label should be an empty string (\cw{""}) if the key does +nothing. + +Like \cw{request_keys()}, the \cw{current_key_label} pointer in the +\c{game} structure is allowed to be \cw{NULL}, in which case the +mid-end will treat it as though it always returned \cw{""}. + \S{backend-flags} \c{flags} \c int flags; @@ -1754,12 +1958,13 @@ whatever it was you needed to do. \C{drawing} The drawing API The back end function \cw{redraw()} (\k{backend-redraw}) is required -to draw the puzzle's graphics on the window's drawing area, or on -paper if the puzzle is printable. To do this portably, it is -provided with a drawing API allowing it to talk directly to the -front end. In this chapter I document that API, both for the benefit -of back end authors trying to use it and for front end authors -trying to implement it. +to draw the puzzle's graphics on the window's drawing area. The back +end function \cw{print()} similarly draws the puzzle on paper, if the +puzzle is printable. To do this portably, the back end is provided +with a drawing API allowing it to talk directly to the front end. In +this chapter I document that API, both for the benefit of back end +authors trying to use it and for front end authors trying to implement +it. The drawing API as seen by the back end is a collection of global functions, each of which takes a pointer to a \c{drawing} structure @@ -1911,6 +2116,22 @@ implement it, since it is actually implemented centrally (in This function may be used for both drawing and printing. +\S{drawing-draw-rect-corner} \cw{draw_rect_corners()} + +\c void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); + +Draws four L-shapes at the corners of a square, in the manner of a +target reticule. This is a convenience function for back ends to use +to display a keyboard cursor (if they want one in that style). + +\c{cx} and \c{cy} give the coordinates of the centre of the square. +\c{r} is half the side length of the square, so that the corners are +at \cw{(cx-r,cy-r)}, \cw{(cx+r,cy-r)}, \cw{(cx-r,cy+r)} and +\cw{(cx+r,cy+r)}. + +\c{colour} is an integer index into the colours array returned by +the back end function \cw{colours()} (\k{backend-colours}). + \S{drawing-draw-line} \cw{draw_line()} \c void draw_line(drawing *dr, int x1, int y1, int x2, int y2, @@ -1935,7 +2156,7 @@ This function may be used for both drawing and printing. \S{drawing-draw-polygon} \cw{draw_polygon()} -\c void draw_polygon(drawing *dr, int *coords, int npoints, +\c void draw_polygon(drawing *dr, const int *coords, int npoints, \c int fillcolour, int outlinecolour); Draws an outlined or filled polygon in the puzzle window. @@ -2133,6 +2354,7 @@ multiplication sign (U+00D7 in Unicode, represented by the bytes C3 \c static const char *const times_signs[] = { "\xC3\x97", "x" }; \c char *times_sign = text_fallback(dr, times_signs, 2); \c sprintf(buffer, "%d%s%d", width, times_sign, height); +\c sfree(times_sign); \c draw_text(dr, x, y, font, size, align, colour, buffer); \c sfree(buffer); @@ -2211,8 +2433,9 @@ modify the buffer after use. (This function is not exactly a \e{drawing} function, but it shares with the drawing API the property that it may only be called from -within the back end redraw function, so this is as good a place as -any to document it.) +within the back end redraw function. And it's implemented by front +ends via the \c{drawing_api} function pointer table. So this is the +best place to document it.) The supplied text is filtered through the mid-end for optional rewriting before being passed on to the front end; the mid-end will @@ -2497,7 +2720,7 @@ function; see \k{drawing-draw-line}. \S{drawingapi-draw-polygon} \cw{draw_polygon()} -\c void (*draw_polygon)(void *handle, int *coords, int npoints, +\c void (*draw_polygon)(void *handle, const int *coords, int npoints, \c int fillcolour, int outlinecolour); This function behaves exactly like the back end \cw{draw_polygon()} @@ -2750,6 +2973,17 @@ Implementations of this API which do not provide printing services may define this function pointer to be \cw{NULL}; it will never be called unless printing is attempted. +\S{drawingapi-line-dotted} \cw{line_dotted()} + +\c void (*line_dotted)(void *handle, bool dotted); + +This function is called to toggle drawing of dotted lines, during +printing only. + +Implementations of this API which do not provide printing services +may define this function pointer to be \cw{NULL}; it will never be +called unless printing is attempted. + \S{drawingapi-text-fallback} \cw{text_fallback()} \c char *(*text_fallback)(void *handle, const char *const *strings, @@ -2796,16 +3030,17 @@ the front end. \S{drawing-print-get-colour} \cw{print_get_colour()} -\c void print_get_colour(drawing *dr, int colour, int printincolour, -\c int *hatch, float *r, float *g, float *b) +\c void print_get_colour(drawing *dr, int colour, +\c bool printing_in_colour, +\c int *hatch, float *r, float *g, float *b); This function is called by the implementations of the drawing API functions when they are called in a printing context. It takes a colour index as input, and returns the description of the colour as requested by the back end. -\c{printincolour} is \cw{TRUE} iff the implementation is printing in -colour. This will alter the results returned if the colour in +\c{printing_in_colour} is \cw{true} iff the implementation is printing +in colour. This will alter the results returned if the colour in question was specified with a black-and-white fallback value. If the colour should be rendered by hatching, \c{*hatch} is filled @@ -2835,7 +3070,7 @@ puzzle window. \H{midend-new} \cw{midend_new()} \c midend *midend_new(frontend *fe, const game *ourgame, -\c const drawing_api *drapi, void *drhandle) +\c const drawing_api *drapi, void *drhandle); Allocates and returns a new mid-end structure. @@ -2898,7 +3133,8 @@ when finished with by passing it to the game's own \H{midend-size} \cw{midend_size()} -\c void midend_size(midend *me, int *x, int *y, bool user_size); +\c void midend_size(midend *me, int *x, int *y, +\c bool user_size, double device_pixel_ratio); Tells the mid-end to figure out its window size. @@ -2926,7 +3162,7 @@ by the user. Use this option if you want your front end to support dynamic resizing of the puzzle window with automatic scaling of the puzzle to fit. -If \c{user_size} is set to \cw{FALSE}, then the game's tile size +If \c{user_size} is set to \cw{false}, then the game's tile size will never go over its preferred one, although it may go under in order to fit within the maximum bounds specified by \c{*x} and \c{*y}. This is the recommended approach when opening a new window @@ -2955,6 +3191,24 @@ to use scroll bars for large puzzles), you can pass dimensions of \cw{INT_MAX} as input to this function. You should probably not do that \e{and} set the \c{user_size} flag, though! +The \cw{device_pixel_ratio} allows the front end to specify that its +pixels are unusually large or small (or should be treated as such). +The mid-end uses this to adjust the tile size, both at startup (if the +ratio is not 1) and if the ratio changes. + +A \cw{device_pixel_ratio} of 1 indicates normal-sized pixels. +\q{Normal} is not precisely defined, but it's about 4 pixels per +millimetre on a screen designed to be viewed from a metre away, or a +size such that text 15 pixels high is comfortably readable. Some +platforms have a concept of a logical pixel that this can be mapped +onto. For instance, Cascading Style Sheets (CSS) has a unit called +\cq{px} that only matches physical pixels at a \cw{device_pixel_ratio} +of 1. + +The \cw{device_pixel_ratio} indicates the number of physical pixels in +a normal-sized pixel, so values less than 1 indicate unusually large +pixels and values greater than 1 indicate unusually small pixels. + The midend relies on the frontend calling \cw{midend_new_game()} (\k{midend-new-game}) before calling \cw{midend_size()}. @@ -2972,7 +3226,7 @@ the puzzle configuration changes. If you \e{don't} want that, e.g. if you want to provide a command to explicitly reset the puzzle size back to its default, then you can call this just before calling \cw{midend_size()} (which, in turn, you would probably call with -\c{user_size} set to \cw{FALSE}). +\c{user_size} set to \cw{false}). \H{midend-new-game} \cw{midend_new_game()} @@ -3039,14 +3293,19 @@ call to this function. Some back ends require that \cw{midend_size()} \H{midend-process-key} \cw{midend_process_key()} -\c bool midend_process_key(midend *me, int x, int y, int button); +\c int midend_process_key(midend *me, int x, int y, int button) + +The front end calls this function to report a mouse or keyboard event. +The parameters \c{x} and \c{y} are identical to the ones passed to the +back end function \cw{interpret_move()} (\k{backend-interpret-move}). -The front end calls this function to report a mouse or keyboard -event. The parameters \c{x}, \c{y} and \c{button} are almost -identical to the ones passed to the back end function -\cw{interpret_move()} (\k{backend-interpret-move}), except that the -front end is \e{not} required to provide the guarantees about mouse -event ordering. The mid-end will sort out multiple simultaneous +\c{button} is similar to the parameter passed to +\cw{interpret_move()}. However, the midend is more relaxed about +values passed to in, and some additional special button values +are defined for the front end to pass to the midend (see below). + +Also, the front end is \e{not} required to provide guarantees about +mouse event ordering. The mid-end will sort out multiple simultaneous button presses and changes of button; the front end's responsibility is simply to pass on the mouse events it receives as accurately as possible. @@ -3072,10 +3331,71 @@ Calling this function is very likely to result in calls back to the front end's drawing API and/or \cw{activate_timer()} (\k{frontend-activate-timer}). -The return value from \cw{midend_process_key()} is \cw{true} unless -the effect of the keypress was to request termination of the program. -A front end should shut down the puzzle in response to a \cw{false} -return. +The return value from \cw{midend_process_key()} is one of the +following constants: + +\dt \cw{PKR_QUIT} + +\dd Means that the effect of the keypress was to request termination +of the program. A front end should shut down the puzzle in response +to a \cw{PKR_QUIT} return. + +\dt \cw{PKR_SOME_EFFECT} + +\dd The keypress had some other effect, either in the mid-end or in +the puzzle itself. + +\dt \cw{PKR_NO_EFFECT} + +\dd The keypress had no effect, but might have had an effect in +slightly different circumstances. For instance it requested a move +that wasn't possible. + +\dt \cw{PKR_UNUSED} + +\dd The key was one that neither the mid-end nor the back-end has any +use for at all. + +A front end might respond to the last value by passing the key on to +something else that might be interested in it. + +The following additional values of \c{button} are permitted to be +passed to this function by the front end, but are never passed on to +the back end. They indicate front-end specific UI operations, such as +selecting an option from a drop-down menu. (Otherwise the front end +would have to translate the \q{New Game} menu item into an \cq{n} +keypress, for example.) + +\dt \cw{UI_NEWGAME} + +\dd Indicates that the user requested a new game, similar to pressing +\cq{n}. + +\dt \cw{UI_SOLVE} + +\dd Indicates that the user requested the solution of the current game. + +\dt \cw{UI_UNDO} + +\dd Indicates that the user attempted to undo a move. + +\dt \cw{UI_REDO} + +\dd Indicates that the user attempted to redo an undone move. + +\dt \cw{UI_QUIT} + +\dd Indicates that the user asked to quit the game. (Of course, a +front end might perfectly well handle this on its own. But including +it in this enumeration allows the front end to treat all these menu +items the same, by translating each of them into a button code passed +to the midend, and handle quitting by noticing the \c{false} return +value from \cw{midend_process_key()}.) + +The midend tolerates any modifier being set on any key and removes +them as necessary before passing the key on to the backend. It will +also handle translating printable characters combined with +\cw{MOD_CTRL} into control characters. \H{midend-request-keys} \cw{midend_request_keys()} @@ -3089,6 +3409,20 @@ labels (i.e. the \cw{key_label} items that have their \cw{label} fields set to \cw{NULL}) by using \cw{button2label()} (\k{utils-button2label}). +\H{midend-current-key-label} \cw{midend_current_key_label()} + +\c const char *midend_current_key_label(midend *me, int button); + +This is a thin wrapper around the backend's \cw{current_key_label()} +function (\k{backend-current-key-label}). Front ends that need to +label \cw{CURSOR_SELECT} or \cw{CURSOR_SELECT2} should call this +function after each move (at least after each call to +\cw{midend_process_key()}) to get the current labels. The front end +should arrange to copy the returned string somewhere before the next +call to the mid-end, just in case it's dynamically allocated. If the +button supplied does nothing, the label returned will be an empty +string. + \H{midend-colours} \cw{midend_colours()} \c float *midend_colours(midend *me, int *ncolours); @@ -3232,6 +3566,17 @@ viewing the existing one). The mid-end generates this dialog box description itself. This should be used when the user selects \q{Random Seed} from the game menu (or equivalent). +\dt \cw{CFG_PREFS} + +\dd Requests a box suitable for configuring user preferences. + +(An additional value \cw{CFG_FRONTEND_SPECIFIC} is provided in this +enumeration, so that frontends can extend it for their own internal +use. For example, you might wrap this function with a +\cw{frontend_get_config} which handles some values of \c{which} itself +and hands others on to the midend, depending on whether \cw{which < +CFG_FRONTEND_SPECIFIC}.) + The returned value is an array of \cw{config_item}s, exactly as described in \k{backend-configure}. Another returned value is an ASCII string giving a suitable title for the configuration window, @@ -3292,7 +3637,7 @@ using \cw{midend_size()} and eventually case a refresh using \H{midend-get-game-id} \cw{midend_get_game_id()} -\c char *midend_get_game_id(midend *me) +\c char *midend_get_game_id(midend *me); Returns a descriptive game ID (i.e. one in the form \cq{params:description}) describing the game currently active in the @@ -3300,7 +3645,7 @@ mid-end. The returned string is dynamically allocated. \H{midend-get-random-seed} \cw{midend_get_random_seed()} -\c char *midend_get_random_seed(midend *me) +\c char *midend_get_random_seed(midend *me); Returns a random game ID (i.e. one in the form \cq{params#seedstring}) describing the game currently active in the mid-end, if there is one. @@ -3309,6 +3654,9 @@ currently exist and this function will return \cw{NULL}. The returned string, if it is non-\cw{NULL}, is dynamically allocated. +Unlike the descriptive game ID, the random seed can contain characters +outside the printable ASCII set. + \H{midend-can-format-as-text-now} \cw{midend_can_format_as_text_now()} \c bool midend_can_format_as_text_now(midend *me); @@ -3327,8 +3675,8 @@ Formats the current game's current state as ASCII text suitable for copying to the clipboard. The returned string is dynamically allocated. -If the game's \c{can_format_as_text_ever} flag is \cw{FALSE}, or if -its \cw{can_format_as_text_now()} function returns \cw{FALSE}, then +If the game's \c{can_format_as_text_ever} flag is \cw{false}, or if +its \cw{can_format_as_text_now()} function returns \cw{false}, then this function will return \cw{NULL}. If the returned string contains multiple lines (which is likely), it @@ -3420,6 +3768,8 @@ visually activate and deactivate a redo button. Calling this function causes the mid-end to convert its entire internal state into a long ASCII text string, and to pass that string (piece by piece) to the supplied \c{write} function. +The string will consist of printable ASCII characters and line +feeds. Desktop implementations can use this function to save a game in any state (including half-finished) to a disk file, by supplying a @@ -3474,6 +3824,32 @@ application is a monolithic one containing all the puzzles. See identify a save file before you instantiate your mid-end in the first place. +\H{midend-save-prefs} \cw{midend_save_prefs()} + +\c void midend_save_prefs( +\c midend *me, void (*write)(void *ctx, const void *buf, int len), +\c void *wctx); + +Calling this function causes the mid-end to write out the states of +all user-settable preference options, including its own cross-platform +preferences and ones exported by a particular game via +\cw{get_prefs()} and \cw{set_prefs()} (\k{backend-get-prefs}, +\k{backend-set-prefs}). The output is a textual format suitable for +writing into a configuration file on disk. + +The \c{write} and \c{wctx} parameters have the same semantics as for +\cw{midend_serialise()} (\k{midend-serialise}). + +\H{midend-load-prefs} \cw{midend_load_prefs()} + +\c const char *midend_load_prefs( +\c midend *me, bool (*read)(void *ctx, void *buf, int len), +\c void *rctx); + +This function is used to load a configuration file in the same format +emitted by \cw{midend_save_prefs()}, and import all the preferences +described in the file into the current mid-end. + \H{identify-game} \cw{identify_game()} \c const char *identify_game(char **name, @@ -3524,6 +3900,13 @@ so I make it a callback rather than a static function in order to relieve most front ends of the need to provide an empty implementation. +\H{midend-which-game} \cw{midend_which_game()} + +\c const game *midend_which_preset(midend *me); + +This function returns the \c{game} structure for the puzzle type this +midend is committed to. + \H{frontend-backend} Direct reference to the back end structure by the front end @@ -3685,7 +4068,7 @@ printable ASCII, or NUL-terminated strings, or anything like that. Allocates a new \c{random_state}, copies the contents of another \c{random_state} into it, and returns the new state. If exactly the -same sequence of functions is subseqently called on both the copy and +same sequence of functions is subsequently called on both the copy and the original, the results will be identical. This may be useful for speculatively performing some operation using a given random state, and later replaying that operation precisely. @@ -3707,7 +4090,8 @@ should be between 1 and 32 inclusive. \c unsigned long random_upto(random_state *state, unsigned long limit); -Returns a random number from 0 to \cw{limit-1} inclusive. +Returns a random number from 0 to \cw{limit-1} inclusive. \c{limit} +may not be zero. \S{utils-random-state-encode} \cw{random_state_encode()} @@ -3890,6 +4274,16 @@ dynamically allocated. (See \k{backend-configure} for details of the \c{config_item} structure.) +\S{utils-free-keys} \cw{free_keys()} + +\c void free_keys(key_label *keys, int nkeys); + +This function correctly frees an array of \c{key_label}s, including +the dynamically allocated label string for each key. + +(See \k{backend-request-keys} for details of the \c{key_label} +structure.) + \H{utils-tree234} Sorted and counted tree functions Many games require complex algorithms for generating random puzzles, @@ -4206,19 +4600,422 @@ element. That function has the prototype and every time it is called, the \c{state} parameter will be set to the value you passed in as \c{copyfnstate}. +\H{utils-dsf} Disjoint set forests + +This section describes a set of functions implementing the data +structure variously known as \q{union-find} or \q{Tarjan's disjoint +set forest}. In this code base, it's universally abbreviated as a +\q{dsf}. + +A dsf represents a collection of elements partitioned into +\q{equivalence classes}, in circumstances where equivalences are added +incrementally. That is, all elements start off considered to be +different, and you gradually declare more and more of them to be equal +via the \cw{dsf_merge()} operation, which says that two particular +elements should be regarded as equal from now on. + +For example, if I start off with A,B,U,V all distinct, and I merge A +with B and merge U with V, then the structure will tell me that A and +U are not equivalent. But if I then merge B with V, then after that, +the structure will tell me that A and U \e{are} equivalent, by +following the transitive chain of equivalences it knows about. + +The dsf data structure is therefore ideal for tracking incremental +connectivity in an undirected graph (again, \q{incremental} meaning +that you only ever add edges, never delete them), and other +applications in which you gradually acquire knowledge you didn't +previously have about what things are the same as each other. It's +used extensively in puzzle solver and generator algorithms, and +sometimes during gameplay as well. + +The time complexity of dsf operations is not \e{quite} constant time, +in theory, but it's so close to it as to make no difference in +practice. In particular, any time a dsf has to do non-trivial work, it +updates the structure so that that work won't be needed a second time. +Use dsf operations without worrying about how long they take! + +For some puzzle-game applications, it's useful to augment this data +structure with extra information about how the elements of an +equivalence class relate to each other. There's more than one way you +might do this; the one supported here is useful in cases where the +objects you're tracking are going to end up in one of two states (say, +black/white, or on/off), and for any two objects you either know that +they're in the same one of those states, or you know they're in +opposite states, or you don't know which yet. Puzzles calls this a +\q{flip dsf}: it tracks whether objects in the same equivalence class +are flipped relative to each other. + +As well as querying whether two elements are equivalent, this dsf +implementation also allows you to ask for the number of elements in a +given equivalence class, and the smallest element in the class. (The +latter is used, for example, to decide which square to print the clue +in each region of a Keen puzzle.) + +\S{utils-dsf-new} \cw{dsf_new()}, \cw{dsf_new_flip()}, \cw{dsf_new_min()} + +\c DSF *dsf_new(int size); +\c DSF *dsf_new_flip(int size); +\c DSF *dsf_new_min(int size); + +Each of these functions allocates space for a dsf describing \c{size} +elements, and initialises it so that every element is in an +equivalence class by itself. + +The elements described by the dsf are represented by the integers from +\cw{0} to \cw{size-1} inclusive. + +\cw{dsf_new_flip()} will create a dsf which has the extra ability to +track whether objects in the same equivalence class are flipped +relative to each other. + +\cw{dsf_new_min()} will create a dsf which has the extra ability to +track the smallest element of each equivalence class. + +The returned object from any of these functions must be freed using +\cw{dsf_free()}. + +\S{utils-dsf-free} \cw{dsf_free()} + +\c void dsf_free(DSF *dsf); + +Frees a dsf allocated by any of the \cw{dsf_new()} functions. + +\S{utils-dsf-reinit} \cw{dsf_reinit()} + +\c void dsf_reinit(DSF *dsf); + +Reinitialises an existing dsf to the state in which all elements are +distinct, without having to free and reallocate it. + +\S{utils-dsf-copy} \cw{dsf_copy()} + +\c void dsf_copy(DSF *to, DSF *from); + +Copies the contents of one dsf over the top of another. Everything +previously stored in \c{to} is overwritten. + +The two dsfs must have been created with the same size, and the +destination dsf may not have any extra information that the source dsf +does not have. + +\S{utils-dsf-merge} \cw{dsf_merge()} + +\c void dsf_merge(DSF *dsf, int v1, int v2); + +Updates a dsf so that elements \c{v1} and \c{v2} will now be +considered to be in the same equivalence class. If they were already +in the same class, this function will safely do nothing. + +This function may not be called on a flip dsf. Use \cw{dsf_merge_flip} +instead. + +\S{utils-dsf-canonify} \cw{dsf_canonify()} + +\c int dsf_canonify(DSF *dsf, int val); + +Returns the \q{canonical} element of the equivalence class in the dsf +containing \c{val}. This will be some element of the same equivalence +class. So in order to determine whether two elements are in the same +equivalence class, you can call \cw{dsf_canonify} on both of them, and +compare the results. + +Canonical elements don't necessarily stay the same if the dsf is +mutated via \c{dsf_merge}. But between two calls to \c{dsf_merge}, +they stay the same. + +\S{utils-dsf-size} \cw{dsf_size()} + +\c int dsf_size(DSF *dsf, int val); + +Returns the number of elements currently in the equivalence class +containing \c{val}. + +\c{val} itself counts, so in a newly created dsf, the return value +will be 1. + +\S{utils-dsf-merge-flip} \cw{dsf_merge_flip()} + +\c void edsf_merge(DSF *dsf, int v1, int v2, bool flip); + +Updates a flip dsf so that elements \c{v1} and \c{v2} are in the same +equivalence class. If \c{flip} is \cw{false}, they will be regarded as +in the same state as each other; if \c{flip} is \cw{true} then they +will be regarded as being in opposite states. + +If \c{v1} and \c{v2} were already in the same equivalence class, then +the new value of \c{flip} will be checked against what the edsf +previously believed, and an assertion failure will occur if you +contradict that. + +For example, if you start from a blank flip dsf and do this: + +\c dsf_merge_flip(dsf, 0, 1, false); +\c dsf_merge_flip(dsf, 1, 2, true); + +then it will create a dsf in which elements 0,1,2 are all in the same +class, with 0,1 in the same state as each other and 2 in the opposite +state from both. And then this call will do nothing, because it agrees +with what the dsf already knew: + +\c dsf_merge_flip(dsf, 0, 2, true); + +But this call will fail an assertion: + +\c dsf_merge_flip(dsf, 0, 2, false); + +\S{utils-dsf-canonify-flip} \cw{dsf_canonify_flip()} + +\c int dsf_canonify_flip(DSF *dsf, int val, bool *inverse); + +Like \c{dsf_canonify()}, this returns the canonical element of the +equivalence class of a dsf containing \c{val}. + +However, it may only be called on a flip dsf, and it also fills in +\c{*flip} with a flag indicating whether \c{val} and the canonical +element are in opposite states: \cw{true} if they are in opposite +states, or \cw{false} if they're in the same state. + +So if you want to know the relationship between \c{v1} and \c{v2}, you +can do this: + +\c bool inv1, inv2; +\c int canon1 = dsf_canonify_flip(dsf, v1, &inv1); +\c int canon2 = dsf_canonify_flip(dsf, v2, &inv2); +\c if (canon1 != canon2) { +\c // v1 and v2 have no known relation +\c } else if (inv1 == inv2) { +\c // v1 and v2 are known to be in the same state as each other +\c } else { +\c // v1 and v2 are known to be in opposite states +\c } + +\S{utils-dsf-minimal} \cw{dsf_minimal()} + +\c int dsf_minimal(DSF *dsf, int val); + +Returns the smallest element of the equivalence class in the dsf +containing \c{val}. + +For this function to work, the dsf must have been created using +\cw{dsf_new_min()}. + +\H{utils-tdq} To-do queues + +This section describes a set of functions implementing a \q{to-do +queue}, a simple de-duplicating to-do list mechanism. The code calls +this a \q{tdq}. + +A tdq can store integers up to a given size (specified at creation +time). But it can't store the same integer more than once. So you can +quickly \e{make sure} an integer is in the queue (which will do +nothing if it's already there), and you can quickly pop an integer +from the queue and return it, both in constant time. + +The idea is that you might use this in a game solver, in the kind of +game where updating your knowledge about one square of a grid means +there's a specific other set of squares (such as its neighbours) where +it's now worth attempting further deductions. So you keep a tdq of all +the grid squares you plan to look at next, and every time you make a +deduction in one square, you add the neighbouring squares to the tdq +to make sure they get looked at again after that. + +In solvers where deductions are mostly localised, this avoids the +slowdown of having to find the next thing to do every time by looping +over the whole grid: instead, you can keep checking the tdq for +\e{specific} squares to look at, until you run out. + +However, it's common to have games in which \e{most} deductions are +localised, but not all. In that situation, when your tdq is empty, you +can re-fill it with every square in the grid using \cw{tdq_fill()}, +which will force an iteration over everything again. And then if the +tdq becomes empty \e{again} without you having made any progress, give +up. + +\S{utils-tdq-new} \cw{tdq_new()} + +\c tdq *tdq_new(int n); + +Allocates space for a tdq that tracks items from \cw{0} to \cw{size-1} +inclusive. + +\S{utils-tdq-free} \cw{tdq_free()} + +\c void tdq_free(tdq *tdq); + +Frees a tdq. + +\S{utils-tdq-add} \cw{tdq_add()} + +\c void tdq_add(tdq *tdq, int k); + +Adds the value \c{k} to a tdq. If \c{k} was already in the to-do list, +does nothing. + +\S{utils-tdq-remove} \cw{tdq_remove()} + +\c int tdq_remove(tdq *tdq); + +Removes one item from the tdq, and returns it. If the tdq is empty, +returns \cw{-1}. + +\S{utils-tdq-fill} \cw{tdq_fill()} + +\c void tdq_fill(tdq *tdq); + +Fills a tdq with every element it can possibly keep track of. + +\H{utils-findloop} Finding loops in graphs and grids + +Many puzzles played on grids or graphs have a common gameplay element +of connecting things together into paths in such a way that you need +to avoid making loops (or, perhaps, making the \e{wrong} kind of +loop). + +Just determining \e{whether} a loop exists in a graph is easy, using a +dsf tracking connectivity between the vertices. Simply iterate over +each edge of the graph, merging the two vertices at each end of the +edge \dash but before you do that, check whether those vertices are +\e{already} known to be connected to each other, and if they are, then +the new edge is about to complete a loop. + +But if you also want to identify \e{exactly} the set of edges that are +part of any loop, e.g. to highlight the whole loop red during +gameplay, then that's a harder problem. This API is provided here for +all puzzles to use for that purpose. + +\S{utils-findloop-new-state} \cw{findloop_new_state()} + +\c struct findloopstate *findloop_new_state(int nvertices); + +Allocates a new state structure for the findloop algorithm, capable of +handling a graph with up to \c{nvertices} vertices. The vertices will +be represented by integers between \c{0} and \c{nvertices-1} inclusive. + +\S{utils-findloop-free-state} \cw{findloop_free_state()} + +\c void findloop_free_state(struct findloopstate *state); + +Frees a state structure allocated by \cw{findloop_new_state()}. + +\S{utils-findloop-run} \cw{findloop_run()} + +\c bool findloop_run(struct findloopstate *state, int nvertices, +\c neighbour_fn_t neighbour, void *ctx); + +Runs the loop-finding algorithm, which will explore the graph and +identify whether each edge is or is not part of any loop. + +The algorithm will call the provided function \c{neighbour} to list +the neighbouring vertices of each vertex. It should have this +prototype: + +\c int neighbour(int vertex, void *ctx); + +In this callback, \c{vertex} will be the index of a vertex when the +algorithm \e{first} calls it for a given vertex. The function should +return the index of one of that vertex's neighbours, or a negative +number if there are none. + +If the function returned a vertex, the algorithm will then call +\c{neighbour} again with a \e{negative} number as the \c{vertex} +parameter, which means \q{please give me another neighbour of the same +vertex as last time}. Again, the function should return a vertex +index, or a negative number to indicate that there are no more +vertices. + +The \c{ctx} parameter passed to \cw{findloop_run()} is passed on +unchanged to \c{neighbour}, so you can point that at your game state +or solver state or whatever. + +The return value is \cw{true} if at least one loop exists in the +graph, and \cw{false} if no loop exists. Also, the algorithm state +will have been filled in with information that the following query +functions can use to ask about individual graph edges. + +\S{utils-findloop-is-loop-edge} \cw{findloop_is_loop_edge()} + +\c bool findloop_is_loop_edge(struct findloopstate *state, +\c int u, int v); + +Queries whether the graph edge between vertices \c{u} and \c{v} is +part of a loop. If so, the return value is \cw{true}, otherwise +\cw{false}. + +\S{utils-findloop-is-bridge} \cw{findloop_is_bridge()} + +\c bool findloop_is_bridge(struct findloopstate *pv, +\c int u, int v, int *u_vertices, int *v_vertices); + +Queries whether the graph edge between vertices \c{u} and \c{v} is a +\q{bridge}, i.e. an edge which would break the graph into (more) +disconnected components if it were removed. + +This is the exact inverse of the \q{loop edge} criterion: a vertex +returns \cw{true} from \cw{findloop_is_loop_edge()} if and only if it +returns \cw{false} from \cw{findloop_is_bridge()}, and vice versa. + +However, \cw{findloop_is_bridge()} returns more information. If it +returns \cw{true}, then it also fills in \c{*u_vertices} and +\c{*v_vertices} with the number of vertices connected to the \c{u} and +\c{v} sides of the bridge respectively. + +For example, if you have three vertices A,B,C all connected to each +other, and four vertices U,V,W,X all connected to each other, and a +single edge between A and V, then calling \cw{findloop_is_bridge()} on +the pair A,V will return true (removing that edge would separate the +two sets from each other), and will report that there are three +vertices on the A side and four on the V side. + +\H{utils-combi} Choosing r things out of n + +This section describes a small API for iterating over all combinations +of r things out of n. + +For example, if you asked for all combinations of 3 things out of 5, +you'd get back the sets \{0,1,2\}, \{0,1,3\}, \{0,1,4\}, \{0,2,3\}, +\{0,2,4\}, \{0,3,4\}, \{1,2,3\}, \{1,2,4\}, \{1,3,4\}, and \{2,3,4\}. + +These functions use a structure called a \c{combi_ctx}, which contains +an element \c{int *a} holding each returned combination, plus other +fields for implementation use only. + +\S{utils-combi-new} \cw{new_combi()} + +\c combi_ctx *new_combi(int r, int n); + +Allocates a new \c{combi_ctx} structure for enumerating r things out +of n. + +\S{utils-combi-free} \cw{free_combi()} + +\c void free_combi(combi_ctx *combi); + +Frees a \c{combi_ctx} structure. + +\S{utils-combi-reset} \cw{reset_combi()} + +\c void reset_combi(combi_ctx *combi); + +Resets an existing \c{combi_ctx} structure to the start of its +iteration + +\S{utils-combi-next} \cw{next_combi()} + +\c combi_ctx *next_combi(combi_ctx *combi); + +Requests a combination from a \c{combi_ctx}. + +If there are none left to return, the return value is \cw{NULL}. +Otherwise, it returns the input structure \c{combi}, indicating that +it has filled in \cw{combi->a[0]}, \cw{combi->a[1]}, ..., +\cw{combi->a[r-1]} with an increasing sequence of distinct integers +from \cw{0} to \cw{n-1} inclusive. + \H{utils-misc} Miscellaneous utility functions and macros This section contains all the utility functions which didn't sensibly fit anywhere else. -\S{utils-truefalse} \cw{TRUE} and \cw{FALSE} - -The main Puzzles header file defines the macros \cw{TRUE} and -\cw{FALSE}, which are used throughout the code in place of 1 and 0 -(respectively) to indicate that the values are in a boolean context. -For code base consistency, I'd prefer it if submissions of new code -followed this convention as well. - \S{utils-maxmin} \cw{max()} and \cw{min()} The main Puzzles header file defines the pretty standard macros @@ -4228,6 +5025,17 @@ returns the one which compares greater or less respectively. These macros may evaluate their arguments multiple times. Avoid side effects. +\S{utils-max-digits} \cw{MAX_DIGITS()} + +The \cw{MAX_DIGITS()} macro, defined in the main Puzzles header file, +takes a type (or a variable of that type) and expands to an integer +constant representing a reasonable upper bound on the number of +characters that a number of that type could expand to when formatted +as a decimal number using the \c{%u} or \c{%d} format of +\cw{printf()}. This is useful for allocating a fixed-size buffer +that's guaranteed to be big enough to \cw{sprintf()} a value into. +Don't forget to add one for the trailing \cw{'\\0'}! + \S{utils-pi} \cw{PI} The main Puzzles header file defines a macro \cw{PI} which expands @@ -4238,7 +5046,7 @@ It'd be so useful!) \S{utils-obfuscate-bitmap} \cw{obfuscate_bitmap()} -\c void obfuscate_bitmap(unsigned char *bmp, int bits, int decode); +\c void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); This function obscures the contents of a piece of data, by cryptographic methods. It is useful for games of hidden information @@ -4269,8 +5077,8 @@ considered to be used from the top down: thus, for example, setting two} bits of \cw{bmp[1]}. The remainder of a partially used byte is undefined (i.e. it may be corrupted by the function). -The parameter \c{decode} is \cw{FALSE} for an encoding operation, -and \cw{TRUE} for a decoding operation. Each is the inverse of the +The parameter \c{decode} is \cw{false} for an encoding operation, +and \cw{true} for a decoding operation. Each is the inverse of the other. (There's no particular reason you shouldn't obfuscate by decoding and restore cleartext by encoding, if you really wanted to; it should still work.) @@ -4299,6 +5107,67 @@ resulting array will be undefined. This function is the inverse of \cw{bin2hex()}. +\S{utils-fgetline} \cw{fgetline()} + +\c char *fgetline(FILE *fp); + +This function reads a single line of text from a standard C input +stream, and returns it as a dynamically allocated string. The returned +string still has a newline on the end. + +\S{utils-arraysort} \cw{arraysort()} + +Sorts an array, with slightly more flexibility than the standard C +\cw{qsort()}. + +This function is really implemented as a macro, so it doesn't have a +prototype as such. But you could imagine it having a prototype like +this: + +\c void arraysort(element_t *array, size_t nmemb, +\c arraysort_cmpfn_t cmp, void *ctx); + +in which \c{element_t} is an unspecified type. + +(Really, there's an underlying function that takes an extra parameter +giving the size of each array element. But callers are encouraged to +use this macro version, which fills that in automatically using +\c{sizeof}.) + +This function behaves essentially like \cw{qsort()}: it expects +\c{array} to point to an array of \c{nmemb} elements, and it will sort +them in place into the order specified by the comparison function +\c{cmp}. + +The comparison function should have this prototype: + +\c int cmp(const void *a, const void *b, void *ctx); + +in which \c{a} and \c{b} point at the two elements to be compared, and +the return value is negative if \cw{ab}, or zero if +\c{a=b}. + +The \c{ctx} parameter to \cw{arraysort()} is passed directly to the +comparison function. This is the feature that makes \cw{arraysort()} +more flexible than standard \cw{qsort()}: it lets you vary the sorting +criterion in a dynamic manner without having to write global variables +in the caller for the compare function to read. + +\S{utils-colour-mix} \cw{colour_mix()} + +\c void colour_mix(const float src1[3], const float src2[3], float p, +\c float dst[3]); + +This function mixes the colours \c{src1} and \c{src2} in specified +proportions, producing \c{dst}. \c{p} is the proportion of \c{src2} +in the result. So if \c{p} is \cw{1.0}, \cw{dst} will be the same as +\c{src2}. If \c{p} is \cw{0.0}, \cw{dst} will be the same as +\c{src1}. And if \c{p} is somewhere in between, so will \c{dst} be. +\c{p} is not restricted to the range \cw{0.0} to \cw{1.0}. Values +outside that range will produce extrapolated colours, which may be +useful for some purposes, but may also produce impossible colours. + \S{utils-game-mkhighlight} \cw{game_mkhighlight()} \c void game_mkhighlight(frontend *fe, float *ret, @@ -4310,7 +5179,7 @@ sections. Fifteen, Sixteen and Twiddle are good examples of this. Puzzles using this graphical style are running a risk if they just use whatever background colour is supplied to them by the front end, -because that background colour might be too light to see any +because that background colour might be too light or dark to see any highlights on at all. (In particular, it's not unheard of for the front end to specify a default background colour of white.) @@ -4334,6 +5203,24 @@ Thus, \cw{ret[background*3]} to \cw{ret[background*3+2]} will be set to RGB values defining a sensible background colour, and similary \c{highlight} and \c{lowlight} will be set to sensible colours. +Either \c{highlight} or \c{lowlight} may be passed in as \cw{-1} to +indicate that the back-end does not require a highlight or lowlight +colour, respectively. + +\S{utils-game-mkhighlight-specific} \cw{game_mkhighlight_specific()} + +\c void game_mkhighlight_specific(frontend *fe, float *ret, +\c int background, int highlight, int lowlight); + +This function behaves exactly like \cw{game_mkhighlight()}, except +that it expects the background colour to have been filled in +\e{already} in the elements \cw{ret[background*3]} to +\cw{ret[background*3+2]}. It will fill in the other two colours as +brighter and darker versions of that. + +This is useful if you want to show relief sections of a puzzle in more +than one base colour. + \S{utils-button2label} \cw{button2label()} \c char *button2label(int button); @@ -4352,6 +5239,104 @@ the corresponding \cw{button} field. The returned string is dynamically allocated and should be \cw{sfree}'d by the caller. +\S{utils-move-cursor} \cw{move_cursor()} + +\c char *move_cursor(int button, int *x, int *y, int w, int h, +\c bool wrap, bool *visible); + +This function can be called by \cw{interpret_move()} to implement the +default keyboard API for moving a cursor around a grid. + +\c{button} is the same value passed in to \cw{interpret_move()}. If +it's not any of \cw{CURSOR_UP}, \cw{CURSOR_DOWN}, \cw{CURSOR_LEFT} or +\cw{CURSOR_RIGHT}, the function will do nothing. + +\c{x} and \c{y} point to two integers which on input give the current +location of a cursor in a square grid. \c{w} and \c{h} give the +dimensions of the grid. On return, \c{x} and \c{y} are updated to give +the cursor's new position according to which arrow key was pressed. + +This function assumes that the grid coordinates run from \cw{0} to +\cw{w-1} inclusive (left to right), and from \cw{0} to \cw{h-1} +inclusive (top to bottom). + +If \c{wrap} is \cw{true}, then trying to move the cursor off any edge +of the grid will result in it wrapping round to the corresponding +square on the opposite edge. If \c{wrap} is \cw{false}, such a move +will have no effect. + +If \c{visible} is not \cw{NULL}, it points to a flag indicating +whether the cursor is visible. This will be set to \cw{true} if +\c{button} represents a cursor-movement key. + +The function returns one of the special constants that can be returned +by \cw{interpret_move()}. The return value is \cw{MOVE_UNUSED} if +\c{button} is unrecognised, \cw{MOVE_UI_UPDATE} if \c{x}, \c{y}, or +\c{visible} was updated, and \cw{MOVE_NO EFFECT} otherwise. + +\S{utils-divvy-rectangle} \cw{divvy_rectangle()} + +\c int *divvy_rectangle(int w, int h, int k, random_state *rs); + +Invents a random division of a rectangle into same-sized polyominoes, +such as is found in the block layout of a Solo puzzle in jigsaw mode, +or the solution to a Palisade puzzle. + +\c{w} and \c{h} are the dimensions of the rectangle. \c{k} is the size +of polyomino desired. It must be a factor of \c{w*h}. + +\c{rs} is a \cw{random_state} used to supply the random numbers to +select a random division of the rectangle. + +The return value is a dsf (see \k{utils-dsf}) whose equivalence +classes correspond to the polyominoes that the rectangle is divided +into. The indices of the dsf are of the form \c{y*w+x}, for the cell +with coordinates \cw{x,y}. + +\S{utils-domino-layout} \cw{domino_layout()} + +\c int *domino_layout(int w, int h, random_state *rs); + +Invents a random tiling of a rectangle with dominoes. + +\c{w} and \c{h} are the dimensions of the rectangle. If they are both +odd, then one square will be left untiled. + +\c{rs} is a \cw{random_state} used to supply the random numbers to +select a random division of the rectangle. + +The return value is an array in which element \c{y*w+x} represents the +cell with coordinates \cw{x,y}. Each element of the array gives the +index (in the same representation) of the other end of its domino. If +there's a left-over square, then that element contains its own index. + +\S{utils-domino-layout-prealloc} \cw{domino_layout_prealloc()} + +\c void domino_layout_prealloc(int w, int h, random_state *rs, +\c int *grid, int *grid2, int *list); + +Just like \cw{domino_layout()}, but does no memory allocation. You can +use this to save allocator overhead if you expect to need to generate +many domino tilings of the same grid. + +\c{grid} and \c{grid2} should each have space for \cw{w*h} ints. +\c{list} should have space for \c{2*w*h} ints. + +The returned array is delivered in \c{grid}. + +\S{utils-strip-button-modifiers} \cw{STRIP_BUTTON_MODIFIERS()} + +This macro, defined in the main Puzzles header file, strips the +modifier flags from the key code passed as an argument. It is +equivalent to a bitwise-AND with \cw{~MOD_MASK}. + +\S{utils-swap-regions} \cw{swap_regions()} + +\c void swap_regions(void *av, void *bv, size_t size); + +Swap two regions of memory of \cw{size} bytes. The two regions must +not overlap. + \C{writing} How to write a new puzzle This chapter gives a guide to how to actually write a new puzzle: @@ -4370,42 +5355,48 @@ official Puzzles distribution, then there's a criterion it has to meet. The current Puzzles editorial policy is that all games should be -\e{fair}. A fair game is one which a player can only fail to -complete through demonstrable lack of skill \dash that is, such that -a better player in the same situation would have \e{known} to do +\e{fair}. A fair game is one which a player can only fail to complete +through demonstrable lack of skill \dash that is, such that a better +player presented with the same game state would have \e{known} to do something different. For a start, that means every game presented to the user must have -\e{at least one solution}. Giving the unsuspecting user a puzzle -which is actually impossible is not acceptable. (There is an -exception: if the user has selected some non-default option which is -clearly labelled as potentially unfair, \e{then} you're allowed to -generate possibly insoluble puzzles, because the user isn't -unsuspecting any more. Same Game and Mines both have options of this -type.) - -Also, this actually \e{rules out} games such as Klondike, or the -normal form of Mahjong Solitaire. Those games have the property that -even if there is a solution (i.e. some sequence of moves which will -get from the start state to the solved state), the player doesn't -necessarily have enough information to \e{find} that solution. In -both games, it is possible to reach a dead end because you had an -arbitrary choice to make and made it the wrong way. This violates -the fairness criterion, because a better player couldn't have known -they needed to make the other choice. - -(GNOME has a variant on Mahjong Solitaire which makes it fair: there -is a Shuffle operation which randomly permutes all the remaining -tiles without changing their positions, which allows you to get out -of a sticky situation. Using this operation adds a 60-second penalty -to your solution time, so it's to the player's advantage to try to -minimise the chance of having to use it. It's still possible to -render the game uncompletable if you end up with only two tiles -vertically stacked, but that's easy to foresee and avoid using a -shuffle operation. This form of the game \e{is} fair. Implementing -it in Puzzles would require an infrastructure change so that the -back end could communicate time penalties to the mid-end, but that -would be easy enough.) +\e{at least one solution}. Giving the unsuspecting user a puzzle which +is actually impossible is not acceptable. + +(An exception to this: if the user has selected some non-default +option which is clearly labelled as potentially unfair, \e{then} +you're allowed to generate possibly insoluble puzzles, because the +user isn't unsuspecting any more. Same Game and Mines both have +options of this type.) + +Secondly, if the game includes hidden information, then it must be +possible to deduce a correct move at every stage from the currently +available information. It's not enough that there should exist some +sequence of moves which will get from the start state to the solved +state, if the player doesn't necessarily have enough information to +\e{find} that solution. For example, in the card solitaire game +Klondike, it's possible to reach a dead end because you had an +arbitrary choice to make on no information, and made it the wrong way, +which violates the fairness criterion, because a better player +couldn't have known they needed to make the other choice. + +(Of course, games in this collection always have an Undo function, so +if you did take the wrong route through a Klondike game, you could use +Undo to back up and try a different choice. This doesn't count. In a +fair game, you should be able to determine a correct move from the +information visible \e{now}, without having to make moves to get more +information that you can then back up and use.) + +Sometimes you can adjust the rules of an unfair puzzle to make it meet +this definition of fairness. For example, more than one implementation +of solitaire-style games (including card solitaires and Mahjong +Solitaire) include a UI action to shuffle the remaining cards or tiles +without changing their position; this action might be available at any +time with a time or points penalty, or it might be illegal to use +unless you have no other possible move. Adding an option like this +would make a game \e{technically} fair, but it's better to avoid even +that if you can. Providing a \e{unique} solution is a little more negotiable; it depends on the puzzle. Solo would have been of unacceptably low @@ -4441,15 +5432,11 @@ So start by copying \c{nullgame.c} into your new source file. Then you'll gradually add functionality until the very boring Null Game turns into your real game. -Next you'll need to add your puzzle to the Makefiles, in order to -compile it conveniently. \e{Do not edit the Makefiles}: they are -created automatically by the script \c{mkfiles.pl}, from the file -called \c{Recipe}. Edit \c{Recipe}, and then re-run \c{mkfiles.pl}. - -Also, don't forget to add your puzzle to \c{list.c}: if you don't, -then it will still run fine on platforms which build each puzzle -separately, but Mac OS X and other monolithic platforms will not -include your new puzzle in their single binary. +Next you'll need to add your puzzle to the build scripts, in order to +compile it conveniently. Puzzles is a CMake project, so you do this by +adding a \cw{puzzle()} statement to CMakeLists.txt. Look at the +existing ones to see what those look like, and add one that looks +similar. Once your source file is building, you can move on to the fun bit. @@ -4726,7 +5713,102 @@ This section lists some common things people want to do when writing a puzzle, and describes how to achieve them within the Puzzles framework. -\S{writing-howto-cursor} Drawing objects at only one position +\S{writing-howto-redraw} Redrawing just the changed parts of the window + +Redrawing the entire window on every move is wasteful. If the user +makes a move changing only one square of a grid, it's better to redraw +just that square. + +(Yes, computers are fast these days, but these puzzles still try to be +portable to devices at the less fast end of the spectrum, so it's +still worth saving effort where it's easy. On the other hand, some +puzzles just \e{can't} do this easily \dash Untangle is an example +that really does have no better option than to redraw everything.) + +For a typical grid-oriented puzzle, a robust way to do this is: + +\b Invent a data representation that describes everything about the +appearance of a grid cell in the puzzle window. + +\b Have \c{game_drawstate} contain an array of those, describing the +current appearance of each cell, as it was last drawn in the window. + +\b In \cw{redraw()}, loop over each cell deciding what the new +appearance should be. If it's not the same as the value stored in +\c{game_drawstate}, then redraw that cell, and update the entry in the +\c{game_drawstate} array. + +Where possible, I generally make my data representation an integer +full of bit flags, to save space, and to make it easy to compare the +old and new versions. If yours needs to be bigger than that, you may +have to define a small \cw{struct} and write an equality-checking +function. + +The data representation of the \e{appearance} of a square in +\c{game_drawstate} will not generally be identical to the +representation of the \e{logical state} of a square in \c{game_state}, +because many things contribute to a square's appearance other than its +logical state. For example: + +\b Extra information overlaid on the square by the user interface, +such as a keyboard-controlled cursor, or highlighting of squares +currently involved in a mouse drag action. + +\b Error highlights marking violations of the puzzle constraints. + +\b Visual intrusions into one square because of things in nearby +squares. For example, if you draw thick lines along the edges between +grid squares, then the corners of those lines will be visible in +logically unrelated squares. An entry in the \c{game_drawstate} array +should describe a specific \e{rectangular area of the screen}, so that +those areas can be erased and redrawn independently \dash so it must +represent anything that appears in that area, even if it's sticking +out from a graphic that logically lives in some other square. + +\b Temporary changes to the appearance of a square because of an +ongoing completion flash. + +\b The current display mode, if a game provides more than one. (For +example, the optional letters distinguishing the different coloured +pegs in Guess.) + +All of this must be included in the \c{game_drawstate} representation, +but should not be in the \c{game_state} at all. \cw{redraw()} will +pull it all together from the \c{game_state}, the \c{game_ui}, and the +animation and flash parameters. + +To make sure that \e{everything} affecting a square's appearance is +included in this representation, it's a good idea to have a separate +function for drawing a grid square, and deliberately \e{not} pass it a +copy of the \c{game_state} or the \c{game_ui} at all. That way, if you +want that function to draw anything differently, you \e{have} to do it +by including that information in the representation of a square's +appearance. + +But of course there are a couple of exceptions to this rule. A few +things \e{don't} have to go in the \c{game_drawstate} array, and can +safely be passed separately to the redraw-square function: + +\b Anything that remains completely fixed throughout the whole of a +game, such as the clues provided by the puzzle. This is safe because a +\c{game_drawstate} is never reused between puzzle instances: when you +press New Game, a new \c{game_drawstate} will always be created from +scratch. So the \c{game_drawstate} only needs to describe everything +that might \e{change} during gameplay. If you have a sub-\cw{struct} +in your \c{game_state} that describes immutable properties of the +current game, as suggested in \k{writing-ref-counting}, then it's safe +to pass \e{that substructure} to the redraw-square function, and have +it retrieve that information directly. + +\b How far through a move animation the last redraw was. When +\cw{redraw()} is called multiple times during an animated move, it's +much easier to just assume that any square involved in the animation +will \e{always} need redrawing. So \c{anim_length} can safely be +passed separately to the redraw-square function \dash but you also +have to remember to redraw a square if \e{either} its appearance is +different from the last redraw \e{or} it's involved in an animation. + +\S{writing-howto-cursor} Drawing an object at only one position A common phenomenon is to have an object described in the \c{game_state} or the \c{game_ui} which can only be at one position. @@ -4742,41 +5824,19 @@ which you ended up with two cursors or none. The obviously sensible way to store a cursor in the \c{game_ui} is to have fields directly encoding the cursor's coordinates. -However, it is a mistake to assume that the same logic applies to -the \c{game_drawstate}. If you replicate the cursor position fields -in the draw state, the redraw code will get very complicated. In the -draw state, in fact, it \e{is} probably the right thing to have a -cursor flag for every position in the grid. You probably have an -array for the whole grid in the drawstate already (stating what is -currently displayed in the window at each position); the sensible -approach is to add a \q{cursor} flag to each element of that array. -Then the main redraw loop will look something like this -(pseudo-code): - -\c for (y = 0; y < h; y++) { -\c for (x = 0; x < w; x++) { -\c int value = state->symbol_at_position[y][x]; -\c if (x == ui->cursor_x && y == ui->cursor_y) -\c value |= CURSOR; -\c if (ds->symbol_at_position[y][x] != value) { -\c symbol_drawing_subroutine(dr, ds, x, y, value); -\c ds->symbol_at_position[y][x] = value; -\c } -\c } -\c } - -This loop is very simple, pretty hard to get wrong, and -\e{automatically} deals both with erasing the previous cursor and -drawing the new one, with no special case code required. - -This type of loop is generally a sensible way to write a redraw -function, in fact. The best thing is to ensure that the information -stored in the draw state for each position tells you \e{everything} -about what was drawn there. A good way to ensure that is to pass -precisely the same information, and \e{only} that information, to a -subroutine that does the actual drawing; then you know there's no -additional information which affects the drawing but which you don't -notice changes in. +However, it is a mistake to assume that the same logic applies to the +\c{game_drawstate}. If you replicate the cursor position fields in the +draw state, the redraw code will get very complicated. In the draw +state, in fact, it \e{is} probably the right thing to have a cursor +flag for every position in the grid, and make it part of the +representation of each square's appearance, as described in +\k{writing-howto-redraw}. So when you iterate over each square in +\c{redraw()} working out its position, you set the \q{cursor here} +flag in the representation of the square's appearance, if its +coordinates match the cursor coordinates stored in the \c{game_ui}. +This will automatically ensure that when the cursor moves, the redraw +loop will redraw the square that \e{previously} contained the cursor +and doesn't any more, and the one that now contains the cursor. \S{writing-keyboard-cursor} Implementing a keyboard-controlled cursor @@ -4790,10 +5850,11 @@ be: \b Put cursor position fields in the \c{game_ui}. \b \cw{interpret_move()} responds to arrow keys by modifying the -cursor position fields and returning \cw{""}. +cursor position fields and returning \cw{MOVE_UI_UPDATE}. -\b \cw{interpret_move()} responds to some sort of fire button by -actually performing a move based on the current cursor location. +\b \cw{interpret_move()} responds to some other button \dash either +\cw{CURSOR_SELECT} or some more specific thing like a number key \dash +by actually performing a move based on the current cursor location. \b You might want an additional \c{game_ui} field stating whether the cursor is currently visible, and having it disappear when a @@ -4983,21 +6044,21 @@ The solution is to have \e{two} flags in a queue. \b Define two flags in \c{game_ui}; let's call them \q{current} and \q{next}. -\b Set both to \cw{FALSE} in \c{new_ui()}. +\b Set both to \cw{false} in \c{new_ui()}. \b When a drag operation completes in \cw{interpret_move()}, set the -\q{next} flag to \cw{TRUE}. +\q{next} flag to \cw{true}. \b Every time \cw{changed_state()} is called, set the value of \q{current} to the value in \q{next}, and then set the value of -\q{next} to \cw{FALSE}. +\q{next} to \cw{false}. -\b That way, \q{current} will be \cw{TRUE} \e{after} a call to +\b That way, \q{current} will be \cw{true} \e{after} a call to \cw{changed_state()} if and only if that call to \cw{changed_state()} was the result of a drag operation processed by \cw{interpret_move()}. Any other call to \cw{changed_state()}, due to an Undo or a Redo or a Restart or a Solve, will leave \q{current} -\cw{FALSE}. +\cw{false}. \b So now \cw{anim_length()} can request a move animation if and only if the \q{current} flag is \e{not} set. @@ -5013,7 +6074,7 @@ This is easily done: \b Add a \q{cheated} flag to the \c{game_state}. -\b Set this flag to \cw{FALSE} in \cw{new_game()}. +\b Set this flag to \cw{false} in \cw{new_game()}. \b Have \cw{solve()} return a move description string which clearly identifies the move as a solve operation. diff --git a/apps/plugins/puzzles/src/divvy.c b/apps/plugins/puzzles/src/divvy.c index ea018010cf..61b04eb80d 100644 --- a/apps/plugins/puzzles/src/divvy.c +++ b/apps/plugins/puzzles/src/divvy.c @@ -260,9 +260,10 @@ static bool addremcommon(int w, int h, int x, int y, int *own, int val) * In both of the above suggested use cases, the user would * probably want w==h==k, but that isn't a requirement. */ -static int *divvy_internal(int w, int h, int k, random_state *rs) +DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs) { - int *order, *queue, *tmp, *own, *sizes, *addable, *retdsf; + int *order, *queue, *tmp, *own, *sizes, *addable; + DSF *retdsf, *tmpdsf; bool *removable; int wh = w*h; int i, j, n, x, y, qhead, qtail; @@ -277,6 +278,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) queue = snewn(n, int); addable = snewn(wh*4, int); removable = snewn(wh, bool); + retdsf = tmpdsf = NULL; /* * Permute the grid squares into a random order, which will be @@ -609,7 +611,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) assert(own[i] >= 0 && own[i] < n); tmp[own[i]] = i; } - retdsf = snew_dsf(wh); + retdsf = dsf_new(wh); for (i = 0; i < wh; i++) { dsf_merge(retdsf, i, tmp[own[i]]); } @@ -619,18 +621,18 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) * the ominoes really are k-ominoes and we haven't * accidentally split one into two disconnected pieces. */ - dsf_init(tmp, wh); + tmpdsf = dsf_new(wh); for (y = 0; y < h; y++) for (x = 0; x+1 < w; x++) if (own[y*w+x] == own[y*w+(x+1)]) - dsf_merge(tmp, y*w+x, y*w+(x+1)); + dsf_merge(tmpdsf, y*w+x, y*w+(x+1)); for (x = 0; x < w; x++) for (y = 0; y+1 < h; y++) if (own[y*w+x] == own[(y+1)*w+x]) - dsf_merge(tmp, y*w+x, (y+1)*w+x); + dsf_merge(tmpdsf, y*w+x, (y+1)*w+x); for (i = 0; i < wh; i++) { j = dsf_canonify(retdsf, i); - assert(dsf_canonify(tmp, j) == dsf_canonify(tmp, i)); + assert(dsf_equivalent(tmpdsf, j, i)); } cleanup: @@ -640,6 +642,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) */ sfree(order); sfree(tmp); + dsf_free(tmpdsf); sfree(own); sfree(sizes); sfree(queue); @@ -652,131 +655,13 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) return retdsf; } -#ifdef TESTMODE -static int fail_counter = 0; -#endif - -int *divvy_rectangle(int w, int h, int k, random_state *rs) +DSF *divvy_rectangle(int w, int h, int k, random_state *rs) { - int *ret; + DSF *ret; do { - ret = divvy_internal(w, h, k, rs); - -#ifdef TESTMODE - if (!ret) - fail_counter++; -#endif - + ret = divvy_rectangle_attempt(w, h, k, rs); } while (!ret); return ret; } - -#ifdef TESTMODE - -/* - * gcc -g -O0 -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c - * - * or to debug - * - * gcc -g -O0 -DDIVVY_DIAGNOSTICS -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c - */ - -int main(int argc, char **argv) -{ - int *dsf; - int i; - int w = 9, h = 4, k = 6, tries = 100; - random_state *rs; - - rs = random_new("123456", 6); - - if (argc > 1) - w = atoi(argv[1]); - if (argc > 2) - h = atoi(argv[2]); - if (argc > 3) - k = atoi(argv[3]); - if (argc > 4) - tries = atoi(argv[4]); - - for (i = 0; i < tries; i++) { - int x, y; - - dsf = divvy_rectangle(w, h, k, rs); - assert(dsf); - - for (y = 0; y <= 2*h; y++) { - for (x = 0; x <= 2*w; x++) { - int miny = y/2 - 1, maxy = y/2; - int minx = x/2 - 1, maxx = x/2; - int classes[4], tx, ty; - for (ty = 0; ty < 2; ty++) - for (tx = 0; tx < 2; tx++) { - int cx = minx+tx, cy = miny+ty; - if (cx < 0 || cx >= w || cy < 0 || cy >= h) - classes[ty*2+tx] = -1; - else - classes[ty*2+tx] = dsf_canonify(dsf, cy*w+cx); - } - switch (y%2 * 2 + x%2) { - case 0: /* corner */ - /* - * Cases for the corner: - * - * - if all four surrounding squares belong - * to the same omino, we print a space. - * - * - if the top two are the same and the - * bottom two are the same, we print a - * horizontal line. - * - * - if the left two are the same and the - * right two are the same, we print a - * vertical line. - * - * - otherwise, we print a cross. - */ - if (classes[0] == classes[1] && - classes[1] == classes[2] && - classes[2] == classes[3]) - printf(" "); - else if (classes[0] == classes[1] && - classes[2] == classes[3]) - printf("-"); - else if (classes[0] == classes[2] && - classes[1] == classes[3]) - printf("|"); - else - printf("+"); - break; - case 1: /* horiz edge */ - if (classes[1] == classes[3]) - printf(" "); - else - printf("--"); - break; - case 2: /* vert edge */ - if (classes[2] == classes[3]) - printf(" "); - else - printf("|"); - break; - case 3: /* square centre */ - printf(" "); - break; - } - } - printf("\n"); - } - printf("\n"); - sfree(dsf); - } - - printf("%d retries needed for %d successes\n", fail_counter, tries); - - return 0; -} - -#endif diff --git a/apps/plugins/puzzles/src/dominosa.R b/apps/plugins/puzzles/src/dominosa.R deleted file mode 100644 index b85e7dc1e0..0000000000 --- a/apps/plugins/puzzles/src/dominosa.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -DOMINOSA_EXTRA = laydomino dsf sort findloop - -dominosa : [X] GTK COMMON dominosa DOMINOSA_EXTRA dominosa-icon|no-icon - -dominosa : [G] WINDOWS COMMON dominosa DOMINOSA_EXTRA dominosa.res|noicon.res - -ALL += dominosa[COMBINED] DOMINOSA_EXTRA - -dominosasolver : [U] dominosa[STANDALONE_SOLVER] DOMINOSA_EXTRA STANDALONE -dominosasolver : [C] dominosa[STANDALONE_SOLVER] DOMINOSA_EXTRA STANDALONE - -!begin am gtk -GAMES += dominosa -!end - -!begin >list.c - A(dominosa) \ -!end - -!begin >gamedesc.txt -dominosa:dominosa.exe:Dominosa:Domino tiling puzzle:Tile the rectangle with a full set of dominoes. -!end diff --git a/apps/plugins/puzzles/src/dominosa.c b/apps/plugins/puzzles/src/dominosa.c index 758db4f506..3ac723e6e1 100644 --- a/apps/plugins/puzzles/src/dominosa.c +++ b/apps/plugins/puzzles/src/dominosa.c @@ -47,7 +47,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -243,6 +248,10 @@ static const char *validate_params(const game_params *params, bool full) { if (params->n < 1) return "Maximum face number must be at least one"; + if (params->n > INT_MAX - 2 || + params->n + 2 > INT_MAX / (params->n + 1)) + return "Maximum face number must not be unreasonably large"; + if (params->diff >= DIFFCOUNT) return "Unknown difficulty rating"; return NULL; @@ -254,9 +263,9 @@ static const char *validate_params(const game_params *params, bool full) #ifdef STANDALONE_SOLVER #define SOLVER_DIAGNOSTICS -bool solver_diagnostics = false; +static bool solver_diagnostics = false; #elif defined SOLVER_DIAGNOSTICS -const bool solver_diagnostics = true; +static const bool solver_diagnostics = true; #endif struct solver_domino; @@ -342,6 +351,7 @@ struct solver_scratch { struct findloopstate *fls; bool squares_by_number_initialised; int *wh_scratch, *pc_scratch, *pc_scratch2, *dc_scratch; + DSF *dsf_scratch; }; static struct solver_scratch *solver_make_scratch(int n) @@ -473,6 +483,7 @@ static struct solver_scratch *solver_make_scratch(int n) sc->wh_scratch = NULL; sc->pc_scratch = sc->pc_scratch2 = NULL; sc->dc_scratch = NULL; + sc->dsf_scratch = NULL; return sc; } @@ -500,6 +511,7 @@ static void solver_free_scratch(struct solver_scratch *sc) sfree(sc->pc_scratch); sfree(sc->pc_scratch2); sfree(sc->dc_scratch); + dsf_free(sc->dsf_scratch); sfree(sc); } @@ -925,7 +937,7 @@ struct parity_findloop_ctx { int i; }; -int parity_neighbour(int vertex, void *vctx) +static int parity_neighbour(int vertex, void *vctx) { struct parity_findloop_ctx *ctx = (struct parity_findloop_ctx *)vctx; struct solver_placement *p; @@ -1416,21 +1428,23 @@ static bool deduce_forcing_chain(struct solver_scratch *sc) sc->pc_scratch2 = snewn(sc->pc, int); if (!sc->dc_scratch) sc->dc_scratch = snewn(sc->dc, int); + if (!sc->dsf_scratch) + sc->dsf_scratch = dsf_new_flip(sc->pc); /* * Start by identifying chains of placements which must all occur * together if any of them occurs. We do this by making - * pc_scratch2 an edsf binding the placements into an equivalence + * dsf_scratch a flip dsf binding the placements into an equivalence * class for each entire forcing chain, with the two possible sets * of dominoes for the chain listed as inverses. */ - dsf_init(sc->pc_scratch2, sc->pc); + dsf_reinit(sc->dsf_scratch); for (si = 0; si < sc->wh; si++) { struct solver_square *sq = &sc->squares[si]; if (sq->nplacements == 2) - edsf_merge(sc->pc_scratch2, - sq->placements[0]->index, - sq->placements[1]->index, true); + dsf_merge_flip(sc->dsf_scratch, + sq->placements[0]->index, + sq->placements[1]->index, true); } /* * Now read out the whole dsf into pc_scratch, flattening its @@ -1443,7 +1457,7 @@ static bool deduce_forcing_chain(struct solver_scratch *sc) */ for (pi = 0; pi < sc->pc; pi++) { bool inv; - int c = edsf_canonify(sc->pc_scratch2, pi, &inv); + int c = dsf_canonify_flip(sc->dsf_scratch, pi, &inv); sc->pc_scratch[pi] = c * 2 + (inv ? 1 : 0); } @@ -2708,7 +2722,7 @@ static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->highlight_1 = ui->highlight_2 = -1; return ui; } @@ -2718,15 +2732,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -2734,6 +2739,33 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cur_visible = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button)) { + int d1, d2, w = state->w; + + if (!((ui->cur_x ^ ui->cur_y) & 1)) + return ""; /* must have exactly one dimension odd */ + d1 = (ui->cur_y / 2) * w + (ui->cur_x / 2); + d2 = ((ui->cur_y+1) / 2) * w + ((ui->cur_x+1) / 2); + + /* We can't mark an edge next to any domino. */ + if (button == CURSOR_SELECT2 && + (state->grid[d1] != d1 || state->grid[d2] != d2)) + return ""; + if (button == CURSOR_SELECT) { + if (state->grid[d1] == d2) return "Remove"; + return "Place"; + } else { + int edge = d2 == d1 + 1 ? EDGE_R : EDGE_B; + if (state->edges[d1] & edge) return "Remove"; + return "Line"; + } + } + return ""; +} + #define PREFERRED_TILESIZE 32 #define TILESIZE (ds->tilesize) #define BORDER (TILESIZE * 3 / 4) @@ -2746,7 +2778,6 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, #define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 ) struct game_drawstate { - bool started; int w, h, tilesize; unsigned long *visible; }; @@ -2768,7 +2799,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int d1, d2; if (tx < 0 || tx >= w || ty < 0 || ty >= h) - return NULL; + return MOVE_UNUSED; /* * Now we know which square the click was in, decide which @@ -2786,29 +2817,26 @@ static char *interpret_move(const game_state *state, game_ui *ui, else if (abs(dy) > abs(dx) && dy > 0 && ty+1 < h) d1 = t, d2 = t + w; /* clicked in top half of domino */ else - return NULL; + return MOVE_NO_EFFECT; /* clicked precisely on a diagonal */ /* * We can't mark an edge next to any domino. */ if (button == RIGHT_BUTTON && (state->grid[d1] != d1 || state->grid[d2] != d2)) - return NULL; + return MOVE_NO_EFFECT; ui->cur_visible = false; sprintf(buf, "%c%d,%d", (int)(button == RIGHT_BUTTON ? 'E' : 'D'), d1, d2); return dupstr(buf); } else if (IS_CURSOR_MOVE(button)) { - ui->cur_visible = true; - - move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false); - - return UI_UPDATE; + return move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false, + &ui->cur_visible); } else if (IS_CURSOR_SELECT(button)) { int d1, d2; if (!((ui->cur_x ^ ui->cur_y) & 1)) - return NULL; /* must have exactly one dimension odd */ + return MOVE_NO_EFFECT; /* must have exactly one dimension odd */ d1 = (ui->cur_y / 2) * w + (ui->cur_x / 2); d2 = ((ui->cur_y+1) / 2) * w + ((ui->cur_x+1) / 2); @@ -2817,14 +2845,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, */ if (button == CURSOR_SELECT2 && (state->grid[d1] != d1 || state->grid[d2] != d2)) - return NULL; + return MOVE_NO_EFFECT; sprintf(buf, "%c%d,%d", (int)(button == CURSOR_SELECT2 ? 'E' : 'D'), d1, d2); return dupstr(buf); } else if (isdigit(button)) { int n = state->params.n, num = button - '0'; if (num > n) { - return NULL; + return MOVE_UNUSED; } else if (ui->highlight_1 == num) { ui->highlight_1 = -1; } else if (ui->highlight_2 == num) { @@ -2834,12 +2862,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, } else if (ui->highlight_2 == -1) { ui->highlight_2 = num; } else { - return NULL; + return MOVE_NO_EFFECT; } - return UI_UPDATE; + return MOVE_UI_UPDATE; } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -2865,7 +2893,8 @@ static game_state *execute_move(const game_state *state, const char *move) move++; } else if (move[0] == 'D' && sscanf(move+1, "%d,%d%n", &d1, &d2, &p) == 2 && - d1 >= 0 && d1 < wh && d2 >= 0 && d2 < wh && d1 < d2) { + d1 >= 0 && d1 < wh && d2 >= 0 && d2 < wh && d1 < d2 && + (d2 - d1 == 1 || d2 - d1 == w)) { /* * Toggle domino presence between d1 and d2. @@ -2933,7 +2962,8 @@ static game_state *execute_move(const game_state *state, const char *move) } else if (move[0] == 'E' && sscanf(move+1, "%d,%d%n", &d1, &d2, &p) == 2 && d1 >= 0 && d1 < wh && d2 >= 0 && d2 < wh && d1 < d2 && - ret->grid[d1] == d1 && ret->grid[d2] == d2) { + ret->grid[d1] == d1 && ret->grid[d2] == d2 && + (d2 - d1 == 1 || d2 - d1 == w)) { /* * Toggle edge presence between d1 and d2. @@ -2998,7 +3028,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { int n = params->n, w = n+2, h = n+1; @@ -3059,7 +3089,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) struct game_drawstate *ds = snew(struct game_drawstate); int i; - ds->started = false; ds->w = state->w; ds->h = state->h; ds->visible = snewn(ds->w * ds->h, unsigned long); @@ -3225,14 +3254,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int x, y, i; unsigned char *used; - if (!ds->started) { - int pw, ph; - game_compute_size(&state->params, TILESIZE, &pw, &ph); - draw_rect(dr, 0, 0, pw, ph, COL_BACKGROUND); - draw_update(dr, 0, 0, pw, ph); - ds->started = true; - } - /* * See how many dominoes of each type there are, so we can * highlight clashes in red. @@ -3347,24 +3368,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->w, h = state->h; int c, x, y; @@ -3421,12 +3439,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -3440,7 +3460,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/drawing.c b/apps/plugins/puzzles/src/drawing.c index a8eb8cfd5f..2c8816c31a 100644 --- a/apps/plugins/puzzles/src/drawing.c +++ b/apps/plugins/puzzles/src/drawing.c @@ -27,7 +27,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -90,8 +94,8 @@ void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) void draw_thick_line(drawing *dr, float thickness, float x1, float y1, float x2, float y2, int colour) { - if (thickness < 1.0) - thickness = 1.0; + if (thickness < 1.0F) + thickness = 1.0F; if (dr->api->draw_thick_line) { dr->api->draw_thick_line(dr->handle, thickness, x1, y1, x2, y2, colour); @@ -101,8 +105,8 @@ void draw_thick_line(drawing *dr, float thickness, * polygon rendering uses integer coordinates. */ float len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); - float tvhatx = (x2 - x1)/len * (thickness/2 - 0.2); - float tvhaty = (y2 - y1)/len * (thickness/2 - 0.2); + float tvhatx = (x2 - x1)/len * (thickness/2 - 0.2F); + float tvhaty = (y2 - y1)/len * (thickness/2 - 0.2F); int p[8]; p[0] = x1 - tvhaty; @@ -117,7 +121,7 @@ void draw_thick_line(drawing *dr, float thickness, } } -void draw_polygon(drawing *dr, int *coords, int npoints, +void draw_polygon(drawing *dr, const int *coords, int npoints, int fillcolour, int outlinecolour) { dr->api->draw_polygon(dr->handle, coords, npoints, fillcolour, diff --git a/apps/plugins/puzzles/src/dsf.c b/apps/plugins/puzzles/src/dsf.c index 832bb3005a..bed564f8ec 100644 --- a/apps/plugins/puzzles/src/dsf.c +++ b/apps/plugins/puzzles/src/dsf.c @@ -5,188 +5,301 @@ */ #include +#include #include #include "puzzles.h" -/*void print_dsf(int *dsf, int size) +#define DSF_INDEX_MASK (UINT_MAX >> 1) +#define DSF_FLAG_CANONICAL (UINT_MAX & ~(UINT_MAX >> 1)) +#define DSF_MAX (DSF_INDEX_MASK + 1) + +struct DSF { + /* + * Size of the dsf. + */ + size_t size; + + /* + * Main array storing the data structure. + * + * If n is the canonical element of an equivalence class, + * parent_or_size[n] holds the number of elements in that class, + * bitwise-ORed with DSF_FLAG_CANONICAL. + * + * If n is not the canonical element, parent_or_size[n] holds the + * index of another element nearer to the root of the tree for + * that class. + */ + unsigned *parent_or_size; + + /* + * Extra storage for flip tracking. + * + * If n is not a canonical element, flip[n] indicates whether the + * sense of this element is flipped relative to parent_or_size[n]. + * + * If n is a canonical element, flip[n] is unused. + */ + unsigned char *flip; + + /* + * Extra storage for minimal-element tracking. + * + * If n is a canonical element, min[n] holds the index of the + * smallest value in n's equivalence class. + * + * If n is not a canonical element, min[n] is unused. + */ + unsigned *min; +}; + +static DSF *dsf_new_internal(int size, bool flip, bool min) { - int *printed_elements = snewn(size, int); - int *equal_elements = snewn(size, int); - int *inverse_elements = snewn(size, int); - int printed_count = 0, equal_count, inverse_count; - int i, n; - bool inverse; + DSF *dsf; - memset(printed_elements, -1, sizeof(int) * size); + assert(0 < size && size <= DSF_MAX && "Bad dsf size"); - while (1) { - equal_count = 0; - inverse_count = 0; - for (i = 0; i < size; ++i) { - if (!memchr(printed_elements, i, sizeof(int) * size)) - break; - } - if (i == size) - goto done; - - i = dsf_canonify(dsf, i); - - for (n = 0; n < size; ++n) { - if (edsf_canonify(dsf, n, &inverse) == i) { - if (inverse) - inverse_elements[inverse_count++] = n; - else - equal_elements[equal_count++] = n; - } - } - - for (n = 0; n < equal_count; ++n) { - fprintf(stderr, "%d ", equal_elements[n]); - printed_elements[printed_count++] = equal_elements[n]; - } - if (inverse_count) { - fprintf(stderr, "!= "); - for (n = 0; n < inverse_count; ++n) { - fprintf(stderr, "%d ", inverse_elements[n]); - printed_elements[printed_count++] = inverse_elements[n]; - } - } - fprintf(stderr, "\n"); - } -done: + dsf = snew(DSF); + dsf->size = size; + dsf->parent_or_size = snewn(size, unsigned); + dsf->flip = flip ? snewn(size, unsigned char) : NULL; + dsf->min = min ? snewn(size, unsigned) : NULL; + + dsf_reinit(dsf); - sfree(printed_elements); - sfree(equal_elements); - sfree(inverse_elements); -}*/ + return dsf; +} -void dsf_init(int *dsf, int size) +DSF *dsf_new(int size) { - int i; + return dsf_new_internal(size, false, false); +} - for (i = 0; i < size; i++) dsf[i] = 6; - /* Bottom bit of each element of this array stores whether that - * element is opposite to its parent, which starts off as - * false. Second bit of each element stores whether that element - * is the root of its tree or not. If it's not the root, the - * remaining 30 bits are the parent, otherwise the remaining 30 - * bits are the number of elements in the tree. */ +DSF *dsf_new_flip(int size) +{ + return dsf_new_internal(size, true, false); } -int *snew_dsf(int size) +DSF *dsf_new_min(int size) { - int *ret; - - ret = snewn(size, int); - dsf_init(ret, size); + return dsf_new_internal(size, false, true); +} + +void dsf_reinit(DSF *dsf) +{ + size_t i; + + /* Every element starts as the root of an equivalence class of size 1 */ + for (i = 0; i < dsf->size; i++) + dsf->parent_or_size[i] = DSF_FLAG_CANONICAL | 1; - /*print_dsf(ret, size); */ + /* If we're tracking minima then every element is also its own min */ + if (dsf->min) + for (i = 0; i < dsf->size; i++) + dsf->min[i] = i; - return ret; + /* No need to initialise dsf->flip, even if it exists, because + * only the entries for non-root elements are meaningful, and + * currently there are none. */ } -int dsf_canonify(int *dsf, int index) +void dsf_copy(DSF *to, DSF *from) { - return edsf_canonify(dsf, index, NULL); + assert(to->size == from->size && "Mismatch in dsf_copy"); + memcpy(to->parent_or_size, from->parent_or_size, + to->size * sizeof(*to->parent_or_size)); + if (to->flip) { + assert(from->flip && "Copying a non-flip dsf to a flip one"); + memcpy(to->flip, from->flip, to->size * sizeof(*to->flip)); + } + if (to->min) { + assert(from->min && "Copying a non-min dsf to a min one"); + memcpy(to->min, from->min, to->size * sizeof(*to->min)); + } } -void dsf_merge(int *dsf, int v1, int v2) + +void dsf_free(DSF *dsf) { - edsf_merge(dsf, v1, v2, false); + if (dsf) { + sfree(dsf->parent_or_size); + sfree(dsf->flip); + sfree(dsf->min); + sfree(dsf); + } } -int dsf_size(int *dsf, int index) { - return dsf[dsf_canonify(dsf, index)] >> 2; +static inline size_t dsf_find_root(DSF *dsf, size_t n) +{ + while (!(dsf->parent_or_size[n] & DSF_FLAG_CANONICAL)) + n = dsf->parent_or_size[n]; + return n; +} + +static inline void dsf_path_compress(DSF *dsf, size_t n, size_t root) +{ + while (!(dsf->parent_or_size[n] & DSF_FLAG_CANONICAL)) { + size_t prev = n; + n = dsf->parent_or_size[n]; + dsf->parent_or_size[prev] = root; + } + assert(n == root); } -int edsf_canonify(int *dsf, int index, bool *inverse_return) +int dsf_canonify(DSF *dsf, int n) { - int start_index = index, canonical_index; - bool inverse = false; + size_t root; -/* fprintf(stderr, "dsf = %p\n", dsf); */ -/* fprintf(stderr, "Canonify %2d\n", index); */ + assert(0 <= n && n < dsf->size && "Overrun in dsf_canonify"); - assert(index >= 0); + root = dsf_find_root(dsf, n); + dsf_path_compress(dsf, n, root); + return root; +} + +void dsf_merge(DSF *dsf, int n1, int n2) +{ + size_t r1, r2, s1, s2, root; + + assert(0 <= n1 && n1 < dsf->size && "Overrun in dsf_merge"); + assert(0 <= n2 && n2 < dsf->size && "Overrun in dsf_merge"); + assert(!dsf->flip && "dsf_merge on a flip dsf"); + + /* Find the root elements */ + r1 = dsf_find_root(dsf, n1); + r2 = dsf_find_root(dsf, n2); + + if (r1 == r2) { + /* Classes are already the same, so we have a common root */ + root = r1; + } else { + /* Classes must be merged */ + + /* Decide which one to use as the overall root, based on size */ + s1 = dsf->parent_or_size[r1] & DSF_INDEX_MASK; + s2 = dsf->parent_or_size[r2] & DSF_INDEX_MASK; + if (s1 > s2) { + dsf->parent_or_size[r2] = root = r1; + } else { + dsf->parent_or_size[r1] = root = r2; + } + dsf->parent_or_size[root] = (s1 + s2) | DSF_FLAG_CANONICAL; - /* Find the index of the canonical element of the 'equivalence class' of - * which start_index is a member, and figure out whether start_index is the - * same as or inverse to that. */ - while ((dsf[index] & 2) == 0) { - inverse ^= (dsf[index] & 1); - index = dsf[index] >> 2; -/* fprintf(stderr, "index = %2d, ", index); */ -/* fprintf(stderr, "inverse = %d\n", inverse); */ + if (dsf->min) { + /* Update the min of the merged class */ + unsigned m1 = dsf->min[r1], m2 = dsf->min[r2]; + dsf->min[root] = m1 < m2 ? m1 : m2; + } } - canonical_index = index; - - if (inverse_return) - *inverse_return = inverse; - - /* Update every member of this 'equivalence class' to point directly at the - * canonical member. */ - index = start_index; - while (index != canonical_index) { - int nextindex = dsf[index] >> 2; - bool nextinverse = inverse ^ (dsf[index] & 1); - dsf[index] = (canonical_index << 2) | inverse; - inverse = nextinverse; - index = nextindex; + + /* Path-compress both paths from n1 and n2 so they point at the new root */ + dsf_path_compress(dsf, n1, root); + dsf_path_compress(dsf, n2, root); +} + +bool dsf_equivalent(DSF *dsf, int n1, int n2) +{ + return dsf_canonify(dsf, n1) == dsf_canonify(dsf, n2); +} + +int dsf_size(DSF *dsf, int n) +{ + size_t root = dsf_canonify(dsf, n); + return dsf->parent_or_size[root] & DSF_INDEX_MASK; +} + +static inline size_t dsf_find_root_flip(DSF *dsf, size_t n, unsigned *flip) +{ + *flip = 0; + while (!(dsf->parent_or_size[n] & DSF_FLAG_CANONICAL)) { + *flip ^= dsf->flip[n]; + n = dsf->parent_or_size[n]; + } + return n; +} + +static inline void dsf_path_compress_flip(DSF *dsf, size_t n, size_t root, + unsigned flip) +{ + while (!(dsf->parent_or_size[n] & DSF_FLAG_CANONICAL)) { + size_t prev = n; + unsigned flip_prev = flip; + n = dsf->parent_or_size[n]; + flip ^= dsf->flip[prev]; + dsf->flip[prev] = flip_prev; + dsf->parent_or_size[prev] = root; } + assert(n == root); +} + +int dsf_canonify_flip(DSF *dsf, int n, bool *inverse) +{ + size_t root; + unsigned flip; + + assert(0 <= n && n < dsf->size && "Overrun in dsf_canonify_flip"); + assert(dsf->flip && "dsf_canonify_flip on a non-flip dsf"); + + root = dsf_find_root_flip(dsf, n, &flip); + dsf_path_compress_flip(dsf, n, root, flip); + *inverse = flip; + return root; +} + +void dsf_merge_flip(DSF *dsf, int n1, int n2, bool inverse) +{ + size_t r1, r2, s1, s2, root; + unsigned f1, f2; + + assert(0 <= n1 && n1 < dsf->size && "Overrun in dsf_merge_flip"); + assert(0 <= n2 && n2 < dsf->size && "Overrun in dsf_merge_flip"); + assert(dsf->flip && "dsf_merge_flip on a non-flip dsf"); + + /* Find the root elements */ + r1 = dsf_find_root_flip(dsf, n1, &f1); + r2 = dsf_find_root_flip(dsf, n2, &f2); + + if (r1 == r2) { + /* Classes are already the same, so we have a common root */ + assert((f1 ^ f2 ^ inverse) == 0 && "Inconsistency in dsf_merge_flip"); + root = r1; + } else { + /* Classes must be merged */ - assert(!inverse); - -/* fprintf(stderr, "Return %2d\n", index); */ - - return index; -} - -void edsf_merge(int *dsf, int v1, int v2, bool inverse) -{ - bool i1, i2; - -/* fprintf(stderr, "dsf = %p\n", dsf); */ -/* fprintf(stderr, "Merge [%2d,%2d], %d\n", v1, v2, inverse); */ - - v1 = edsf_canonify(dsf, v1, &i1); - assert(dsf[v1] & 2); - inverse ^= i1; - v2 = edsf_canonify(dsf, v2, &i2); - assert(dsf[v2] & 2); - inverse ^= i2; - -/* fprintf(stderr, "Doing [%2d,%2d], %d\n", v1, v2, inverse); */ - - if (v1 == v2) - assert(!inverse); - else { - /* - * We always make the smaller of v1 and v2 the new canonical - * element. This ensures that the canonical element of any - * class in this structure is always the first element in - * it. 'Keen' depends critically on this property. - * - * (Jonas Koelker previously had this code choosing which - * way round to connect the trees by examining the sizes of - * the classes being merged, so that the root of the - * larger-sized class became the new root. This gives better - * asymptotic performance, but I've changed it to do it this - * way because I like having a deterministic canonical - * element.) - */ - if (v1 > v2) { - int v3 = v1; - v1 = v2; - v2 = v3; - } - dsf[v1] += (dsf[v2] >> 2) << 2; - dsf[v2] = (v1 << 2) | inverse; + /* Decide which one to use as the overall root, based on size */ + s1 = dsf->parent_or_size[r1] & DSF_INDEX_MASK; + s2 = dsf->parent_or_size[r2] & DSF_INDEX_MASK; + if (s1 > s2) { + dsf->parent_or_size[r2] = root = r1; + dsf->flip[r2] = f1 ^ f2 ^ inverse; + f2 ^= dsf->flip[r2]; + } else { + root = r2; + dsf->parent_or_size[r1] = root = r2; + dsf->flip[r1] = f1 ^ f2 ^ inverse; + f1 ^= dsf->flip[r1]; + } + dsf->parent_or_size[root] = (s1 + s2) | DSF_FLAG_CANONICAL; + + if (dsf->min) { + /* Update the min of the merged class */ + unsigned m1 = dsf->min[r1], m2 = dsf->min[r2]; + dsf->min[root] = m1 < m2 ? m1 : m2; + } } - - v2 = edsf_canonify(dsf, v2, &i2); - assert(v2 == v1); - assert(i2 == inverse); -/* fprintf(stderr, "dsf[%2d] = %2d\n", v2, dsf[v2]); */ + /* Path-compress both paths from n1 and n2 so they point at the new root */ + dsf_path_compress_flip(dsf, n1, root, f1); + dsf_path_compress_flip(dsf, n2, root, f2); +} + +int dsf_minimal(DSF *dsf, int n) +{ + size_t root; + + assert(dsf->min && "dsf_minimal on a non-min dsf"); + + root = dsf_canonify(dsf, n); + return dsf->min[root]; } diff --git a/apps/plugins/puzzles/src/emcc.c b/apps/plugins/puzzles/src/emcc.c index 9a6c742482..6aa9c6b093 100644 --- a/apps/plugins/puzzles/src/emcc.c +++ b/apps/plugins/puzzles/src/emcc.c @@ -12,19 +12,8 @@ /* * Further thoughts on possible enhancements: * - * - I think it might be feasible to have these JS puzzles permit - * loading and saving games in disk files. Saving would be done by - * constructing a data: URI encapsulating the save file, and then - * telling the browser to visit that URI with the effect that it - * would naturally pop up a 'where would you like to save this' - * dialog box. Loading, more or less similarly, might be feasible - * by using the DOM File API to ask the user to select a file and - * permit us to see its contents. - * * - I should think about whether these webified puzzles can support - * touchscreen-based tablet browsers (assuming there are any that - * can cope with the reasonably modern JS and run it fast enough to - * be worthwhile). + * touchscreen-based tablet browsers. * * - think about making use of localStorage. It might be useful to * let the user save games into there as an alternative to disk @@ -32,11 +21,7 @@ * out of your browser to (e.g.) email to me as a bug report, but * for just resuming a game you were in the middle of, you'd * probably rather have a nice simple 'quick save' and 'quick load' - * button pair. Also, that might be a useful place to store - * preferences, if I ever get round to writing a preferences UI. - * - * - some CSS to make the button bar and configuration dialogs a - * little less ugly would probably not go amiss. + * button pair. * * - this is a downright silly idea, but it does occur to me that if * I were to write a PDF output driver for the Puzzles printing @@ -57,6 +42,8 @@ /* * Extern references to Javascript functions provided in emcclib.js. */ +extern void js_init_puzzle(void); +extern void js_post_init(void); extern void js_debug(const char *); extern void js_error_box(const char *message); extern void js_remove_type_dropdown(void); @@ -65,37 +52,39 @@ extern void js_add_preset(int menuid, const char *name, int value); extern int js_add_preset_submenu(int menuid, const char *name); extern int js_get_selected_preset(void); extern void js_select_preset(int n); +extern void js_default_colour(float *output); +extern void js_set_colour(int colour_number, const char *colour_string); extern void js_get_date_64(unsigned *p); extern void js_update_permalinks(const char *desc, const char *seed); extern void js_enable_undo_redo(bool undo, bool redo); -extern void js_activate_timer(); -extern void js_deactivate_timer(); +extern void js_update_key_labels(const char *lsk, const char *csk); +extern void js_activate_timer(void); +extern void js_deactivate_timer(void); extern void js_canvas_start_draw(void); extern void js_canvas_draw_update(int x, int y, int w, int h); extern void js_canvas_end_draw(void); -extern void js_canvas_draw_rect(int x, int y, int w, int h, - const char *colour); +extern void js_canvas_draw_rect(int x, int y, int w, int h, int colour); extern void js_canvas_clip_rect(int x, int y, int w, int h); extern void js_canvas_unclip(void); extern void js_canvas_draw_line(float x1, float y1, float x2, float y2, - int width, const char *colour); -extern void js_canvas_draw_poly(int *points, int npoints, - const char *fillcolour, - const char *outlinecolour); + int width, int colour); +extern void js_canvas_draw_poly(const int *points, int npoints, + int fillcolour, int outlinecolour); extern void js_canvas_draw_circle(int x, int y, int r, - const char *fillcolour, - const char *outlinecolour); -extern int js_canvas_find_font_midpoint(int height, const char *fontptr); + int fillcolour, int outlinecolour); +extern int js_canvas_find_font_midpoint(int height, bool monospaced); extern void js_canvas_draw_text(int x, int y, int halign, - const char *colptr, const char *fontptr, - const char *text); + int colour, int height, + bool monospaced, const char *text); extern int js_canvas_new_blitter(int w, int h); extern void js_canvas_free_blitter(int id); extern void js_canvas_copy_to_blitter(int id, int x, int y, int w, int h); extern void js_canvas_copy_from_blitter(int id, int x, int y, int w, int h); -extern void js_canvas_make_statusbar(void); +extern void js_canvas_remove_statusbar(void); extern void js_canvas_set_statusbar(const char *text); +extern bool js_canvas_get_preferred_size(int *wp, int *hp); extern void js_canvas_set_size(int w, int h); +extern double js_get_device_pixel_ratio(void); extern void js_dialog_init(const char *title); extern void js_dialog_string(int i, const char *title, const char *initvalue); @@ -106,6 +95,38 @@ extern void js_dialog_launch(void); extern void js_dialog_cleanup(void); extern void js_focus_canvas(void); +extern bool js_savefile_read(void *buf, int len); + +extern void js_save_prefs(const char *); +extern void js_load_prefs(midend *); + +/* + * These functions are called from JavaScript, so their prototypes + * need to be kept in sync with emccpre.js. + */ +bool mouseup(int x, int y, int button); +bool mousedown(int x, int y, int button); +bool mousemove(int x, int y, int buttons); +bool key(int keycode, const char *key, const char *chr, int location, + bool shift, bool ctrl); +void timer_callback(double tplus); +void command(int n); +char *get_text_format(void); +void free_save_file(char *buffer); +char *get_save_file(void); +void free_save_file(char *buffer); +void load_game(void); +void dlg_return_sval(int index, const char *val); +void dlg_return_ival(int index, int val); +void resize_puzzle(int w, int h); +void restore_puzzle_size(int w, int h); +void rescale_puzzle(void); + +/* + * Internal forward references. + */ +static void save_prefs(midend *me); + /* * Call JS to get the date, and use that to initialise our random * number generator to invent the first game seed. @@ -136,6 +157,7 @@ void fatal(const char *fmt, ...) js_error_box(buf); } +#ifdef DEBUGGING void debug_printf(const char *fmt, ...) { char buf[512]; @@ -145,33 +167,28 @@ void debug_printf(const char *fmt, ...) va_end(ap); js_debug(buf); } +#endif /* * Helper function that makes it easy to test strings that might be * NULL. */ -int strnullcmp(const char *a, const char *b) +static int strnullcmp(const char *a, const char *b) { if (a == NULL || b == NULL) return a != NULL ? +1 : b != NULL ? -1 : 0; return strcmp(a, b); } -/* - * HTMLish names for the colours allocated by the puzzle. - */ -char **colour_strings; -int ncolours; - /* * The global midend object. */ -midend *me; +static midend *me; /* ---------------------------------------------------------------------- * Timing functions. */ -bool timer_active = false; +static bool timer_active = false; void deactivate_timer(frontend *fe) { js_deactivate_timer(); @@ -196,21 +213,33 @@ void timer_callback(double tplus) */ static int canvas_w, canvas_h; -/* Called when we resize as a result of changing puzzle settings */ +/* + * Called when we resize as a result of changing puzzle settings + * or device pixel ratio. + */ static void resize(void) { int w, h; + bool user; w = h = INT_MAX; - midend_size(me, &w, &h, false); + user = js_canvas_get_preferred_size(&w, &h); + midend_size(me, &w, &h, user, js_get_device_pixel_ratio()); js_canvas_set_size(w, h); canvas_w = w; canvas_h = h; } +/* Called from JS when the device pixel ratio changes */ +void rescale_puzzle(void) +{ + resize(); + midend_force_redraw(me); +} + /* Called from JS when the user uses the resize handle */ void resize_puzzle(int w, int h) { - midend_size(me, &w, &h, true); + midend_size(me, &w, &h, true, js_get_device_pixel_ratio()); if (canvas_w != w || canvas_h != h) { js_canvas_set_size(w, h); canvas_w = w; @@ -228,12 +257,13 @@ void restore_puzzle_size(int w, int h) } /* - * HTML doesn't give us a default frontend colour of its own, so we - * just make up a lightish grey ourselves. + * Try to extract a background colour from the canvas's CSS. In case + * it doesn't have a usable one, make up a lightish grey ourselves. */ void frontend_default_colour(frontend *fe, float *output) { output[0] = output[1] = output[2] = 0.9F; + js_default_colour(output); } /* @@ -241,60 +271,85 @@ void frontend_default_colour(frontend *fe, float *output) * and redo buttons get properly enabled and disabled after every move * or undo or new-game event. */ -static void update_undo_redo(void) +static void post_move(void) { js_enable_undo_redo(midend_can_undo(me), midend_can_redo(me)); + js_update_key_labels(midend_current_key_label(me, CURSOR_SELECT2), + midend_current_key_label(me, CURSOR_SELECT)); } /* * Mouse event handlers called from JS. */ -void mousedown(int x, int y, int button) +bool mousedown(int x, int y, int button) { + bool handled; + button = (button == 0 ? LEFT_BUTTON : button == 1 ? MIDDLE_BUTTON : RIGHT_BUTTON); - midend_process_key(me, x, y, button); - update_undo_redo(); + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; + post_move(); + return handled; } -void mouseup(int x, int y, int button) +bool mouseup(int x, int y, int button) { + bool handled; + button = (button == 0 ? LEFT_RELEASE : button == 1 ? MIDDLE_RELEASE : RIGHT_RELEASE); - midend_process_key(me, x, y, button); - update_undo_redo(); + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; + post_move(); + return handled; } -void mousemove(int x, int y, int buttons) +bool mousemove(int x, int y, int buttons) { int button = (buttons & 2 ? MIDDLE_DRAG : buttons & 4 ? RIGHT_DRAG : LEFT_DRAG); - midend_process_key(me, x, y, button); - update_undo_redo(); + bool handled; + + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; + post_move(); + return handled; } /* - * Keyboard handler called from JS. + * Keyboard handler called from JS. Returns true if the key was + * handled and hence the keydown event should be cancelled. */ -void key(int keycode, int charcode, const char *key, const char *chr, +bool key(int keycode, const char *key, const char *chr, int location, bool shift, bool ctrl) { + /* Key location constants from JavaScript. */ + #define DOM_KEY_LOCATION_STANDARD 0 + #define DOM_KEY_LOCATION_LEFT 1 + #define DOM_KEY_LOCATION_RIGHT 2 + #define DOM_KEY_LOCATION_NUMPAD 3 int keyevent = -1; + int process_key_result; - if (!strnullcmp(key, "Backspace") || !strnullcmp(key, "Del") || - keycode == 8 || keycode == 46) { + if (!strnullcmp(key, "Backspace") || !strnullcmp(key, "Delete") || + !strnullcmp(key, "Del")) keyevent = 127; /* Backspace / Delete */ - } else if (!strnullcmp(key, "Enter") || keycode == 13) { + else if (!strnullcmp(key, "Enter")) keyevent = 13; /* return */ - } else if (!strnullcmp(key, "Left") || keycode == 37) { + else if (!strnullcmp(key, "Spacebar")) + keyevent = ' '; + else if (!strnullcmp(key, "Escape")) + keyevent = 27; + else if (!strnullcmp(key, "ArrowLeft") || !strnullcmp(key, "Left")) keyevent = CURSOR_LEFT; - } else if (!strnullcmp(key, "Up") || keycode == 38) { + else if (!strnullcmp(key, "ArrowUp") || !strnullcmp(key, "Up")) keyevent = CURSOR_UP; - } else if (!strnullcmp(key, "Right") || keycode == 39) { + else if (!strnullcmp(key, "ArrowRight") || !strnullcmp(key, "Right")) keyevent = CURSOR_RIGHT; - } else if (!strnullcmp(key, "Down") || keycode == 40) { + else if (!strnullcmp(key, "ArrowDown") || !strnullcmp(key, "Down")) keyevent = CURSOR_DOWN; - } else if (!strnullcmp(key, "End") || keycode == 35) { + else if (!strnullcmp(key, "SoftLeft")) + /* Left soft key on KaiOS. */ + keyevent = CURSOR_SELECT2; + else if (!strnullcmp(key, "End")) /* * We interpret Home, End, PgUp and PgDn as numeric keypad * controls regardless of whether they're the ones on the @@ -304,40 +359,73 @@ void key(int keycode, int charcode, const char *key, const char *chr, * puzzles like Cube and Inertia. */ keyevent = MOD_NUM_KEYPAD | '1'; - } else if (!strnullcmp(key, "PageDown") || keycode==34) { + else if (!strnullcmp(key, "PageDown")) keyevent = MOD_NUM_KEYPAD | '3'; - } else if (!strnullcmp(key, "Home") || keycode==36) { + else if (!strnullcmp(key, "Home")) keyevent = MOD_NUM_KEYPAD | '7'; - } else if (!strnullcmp(key, "PageUp") || keycode==33) { + else if (!strnullcmp(key, "PageUp")) keyevent = MOD_NUM_KEYPAD | '9'; - } else if (shift && ctrl && (keycode & 0x1F) == 26) { + else if (shift && ctrl && (!strnullcmp(key, "Z") || !strnullcmp(key, "z"))) keyevent = UI_REDO; - } else if (chr && chr[0] && !chr[1]) { + else if (key && (unsigned char)key[0] < 0x80 && key[1] == '\0') + /* Key generating a single ASCII character. */ + keyevent = key[0]; + /* + * In modern browsers (since about 2017), all keys that Puzzles + * cares about should be matched by one of the clauses above. The + * code below that checks keycode and chr should be relavent only + * in older browsers. + */ + else if (keycode == 8 || keycode == 46) + keyevent = 127; /* Backspace / Delete */ + else if (keycode == 13) + keyevent = 13; /* return */ + else if (keycode == 37) + keyevent = CURSOR_LEFT; + else if (keycode == 38) + keyevent = CURSOR_UP; + else if (keycode == 39) + keyevent = CURSOR_RIGHT; + else if (keycode == 40) + keyevent = CURSOR_DOWN; + else if (keycode == 35) + keyevent = MOD_NUM_KEYPAD | '1'; + else if (keycode == 34) + keyevent = MOD_NUM_KEYPAD | '3'; + else if (keycode == 36) + keyevent = MOD_NUM_KEYPAD | '7'; + else if (keycode == 33) + keyevent = MOD_NUM_KEYPAD | '9'; + else if (shift && ctrl && (keycode & 0x1F) == 26) + keyevent = UI_REDO; + else if (chr && chr[0] && !chr[1]) keyevent = chr[0] & 0xFF; - } else if (keycode >= 96 && keycode < 106) { + else if (keycode >= 96 && keycode < 106) keyevent = MOD_NUM_KEYPAD | ('0' + keycode - 96); - } else if (keycode >= 65 && keycode <= 90) { + else if (keycode >= 65 && keycode <= 90) keyevent = keycode + (shift ? 0 : 32); - } else if (keycode >= 48 && keycode <= 57) { + else if (keycode >= 48 && keycode <= 57) keyevent = keycode; - } else if (keycode == 32) { /* space / CURSOR_SELECT2 */ + else if (keycode == 32) /* space / CURSOR_SELECT2 */ keyevent = keycode; - } if (keyevent >= 0) { - if (shift && (keyevent >= 0x100 && !IS_UI_FAKE_KEY(keyevent))) - keyevent |= MOD_SHFT; - - if (ctrl && !IS_UI_FAKE_KEY(keyevent)) { - if (keyevent >= 0x100) - keyevent |= MOD_CTRL; - else - keyevent &= 0x1F; - } + if (shift) keyevent |= MOD_SHFT; + if (ctrl) keyevent |= MOD_CTRL; + if (location == DOM_KEY_LOCATION_NUMPAD) keyevent |= MOD_NUM_KEYPAD; - midend_process_key(me, 0, 0, keyevent); - update_undo_redo(); + process_key_result = midend_process_key(me, 0, 0, keyevent); + post_move(); + /* + * Treat Backspace specially because that's expected on KaiOS. + * https://developer.kaiostech.com/docs/design-guide/key + */ + if (process_key_result == PKR_NO_EFFECT && + !strnullcmp(key, "Backspace")) + return false; + return process_key_result != PKR_UNUSED; } + return false; /* Event not handled, because we don't even recognise it. */ } /* @@ -387,14 +475,10 @@ static void js_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int colour, const char *text) { - char fontstyle[80]; int halign; - sprintf(fontstyle, "%dpx %s", fontsize, - fonttype == FONT_FIXED ? "monospace" : "sans-serif"); - if (align & ALIGN_VCENTRE) - y += js_canvas_find_font_midpoint(fontsize, fontstyle); + y += js_canvas_find_font_midpoint(fontsize, fonttype == FONT_FIXED); if (align & ALIGN_HCENTRE) halign = 1; @@ -403,41 +487,38 @@ static void js_draw_text(void *handle, int x, int y, int fonttype, else halign = 0; - js_canvas_draw_text(x, y, halign, colour_strings[colour], fontstyle, text); + js_canvas_draw_text(x, y, halign, colour, + fontsize, fonttype == FONT_FIXED, text); } static void js_draw_rect(void *handle, int x, int y, int w, int h, int colour) { - js_canvas_draw_rect(x, y, w, h, colour_strings[colour]); + js_canvas_draw_rect(x, y, w, h, colour); } static void js_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour) { - js_canvas_draw_line(x1, y1, x2, y2, 1, colour_strings[colour]); + js_canvas_draw_line(x1, y1, x2, y2, 1, colour); } static void js_draw_thick_line(void *handle, float thickness, float x1, float y1, float x2, float y2, int colour) { - js_canvas_draw_line(x1, y1, x2, y2, thickness, colour_strings[colour]); + js_canvas_draw_line(x1, y1, x2, y2, thickness, colour); } -static void js_draw_poly(void *handle, int *coords, int npoints, +static void js_draw_poly(void *handle, const int *coords, int npoints, int fillcolour, int outlinecolour) { - js_canvas_draw_poly(coords, npoints, - fillcolour >= 0 ? colour_strings[fillcolour] : NULL, - colour_strings[outlinecolour]); + js_canvas_draw_poly(coords, npoints, fillcolour, outlinecolour); } static void js_draw_circle(void *handle, int cx, int cy, int radius, int fillcolour, int outlinecolour) { - js_canvas_draw_circle(cx, cy, radius, - fillcolour >= 0 ? colour_strings[fillcolour] : NULL, - colour_strings[outlinecolour]); + js_canvas_draw_circle(cx, cy, radius, fillcolour, outlinecolour); } struct blitter { @@ -527,7 +608,7 @@ static char *js_text_fallback(void *handle, const char *const *strings, return dupstr(strings[0]); /* Emscripten has no trouble with UTF-8 */ } -const struct drawing_api js_drawing = { +static const struct drawing_api js_drawing = { js_draw_text, js_draw_rect, js_draw_line, @@ -554,9 +635,9 @@ const struct drawing_api js_drawing = { */ static game_params **presets; static int npresets; -bool have_presets_dropdown; +static bool have_presets_dropdown; -void populate_js_preset_menu(int menuid, struct preset_menu *menu) +static void populate_js_preset_menu(int menuid, struct preset_menu *menu) { int i; for (i = 0; i < menu->n_entries; i++) { @@ -571,7 +652,7 @@ void populate_js_preset_menu(int menuid, struct preset_menu *menu) } } -void select_appropriate_preset(void) +static void select_appropriate_preset(void) { if (have_presets_dropdown) { int preset = midend_which_preset(me); @@ -665,10 +746,20 @@ static void cfg_end(bool use_results) * open for the user to adjust them and try again. */ js_error_box(err); + } else if (cfg_which == CFG_PREFS) { + /* + * Acceptable settings for user preferences: enact them + * without blowing away the current game. + */ + resize(); + midend_redraw(me); + free_cfg(cfg); + js_dialog_cleanup(); + save_prefs(me); } else { /* - * New settings are fine; start a new game and close the - * dialog. + * Acceptable settings for the remaining configuration + * types: start a new game and close the dialog. */ select_appropriate_preset(); midend_new_game(me); @@ -686,10 +777,7 @@ static void cfg_end(bool use_results) * select Custom from the list, but change your mind and hit * Esc. The Custom option will now still be selected in the * list, whereas obviously it should show the preset you still - * _actually_ have selected. Worse still, it'll be the visible - * rather than invisible Custom option - see the comment in - * js_add_preset in emcclib.js - so you won't even be able to - * select Custom without a faffy workaround.) + * _actually_ have selected.) */ select_appropriate_preset(); @@ -731,7 +819,7 @@ void command(int n) midend_new_game(me); resize(); midend_redraw(me); - update_undo_redo(); + post_move(); js_focus_canvas(); select_appropriate_preset(); } @@ -739,30 +827,30 @@ void command(int n) break; case 3: /* OK clicked in a config box */ cfg_end(true); - update_undo_redo(); + post_move(); break; case 4: /* Cancel clicked in a config box */ cfg_end(false); - update_undo_redo(); + post_move(); break; case 5: /* New Game */ midend_process_key(me, 0, 0, UI_NEWGAME); - update_undo_redo(); + post_move(); js_focus_canvas(); break; case 6: /* Restart */ midend_restart_game(me); - update_undo_redo(); + post_move(); js_focus_canvas(); break; case 7: /* Undo */ midend_process_key(me, 0, 0, UI_UNDO); - update_undo_redo(); + post_move(); js_focus_canvas(); break; case 8: /* Redo */ midend_process_key(me, 0, 0, UI_REDO); - update_undo_redo(); + post_move(); js_focus_canvas(); break; case 9: /* Solve */ @@ -771,12 +859,25 @@ void command(int n) if (msg) js_error_box(msg); } - update_undo_redo(); + post_move(); js_focus_canvas(); break; + case 10: /* user preferences */ + cfg_start(CFG_PREFS); + break; } } +char *get_text_format(void) +{ + return midend_text_format(me); +} + +void free_text_format(char *buffer) +{ + sfree(buffer); +} + /* ---------------------------------------------------------------------- * Called from JS to prepare a save-game file, and free one after it's * been used. @@ -824,30 +925,20 @@ void free_save_file(char *buffer) sfree(buffer); } -struct savefile_read_ctx { - const char *buffer; - int len_remaining; -}; - static bool savefile_read(void *vctx, void *buf, int len) { - struct savefile_read_ctx *ctx = (struct savefile_read_ctx *)vctx; - if (ctx->len_remaining < len) - return false; - memcpy(buf, ctx->buffer, len); - ctx->len_remaining -= len; - ctx->buffer += len; - return true; + return js_savefile_read(buf, len); } -void load_game(const char *buffer, int len) +void load_game(void) { - struct savefile_read_ctx ctx; const char *err; - ctx.buffer = buffer; - ctx.len_remaining = len; - err = midend_deserialise(me, savefile_read, &ctx); + /* + * savefile_read_callback in JavaScript was set up by our caller + * as a closure that knows what file we're loading. + */ + err = midend_deserialise(me, savefile_read, NULL); if (err) { js_error_box(err); @@ -855,9 +946,69 @@ void load_game(const char *buffer, int len) select_appropriate_preset(); resize(); midend_redraw(me); + update_permalinks(); + post_move(); } } +/* ---------------------------------------------------------------------- + * Functions to load and save preferences, calling out to JS to access + * the appropriate localStorage slot. + */ + +static void save_prefs(midend *me) +{ + struct savefile_write_ctx ctx; + size_t size; + + /* First pass, to count up the size */ + ctx.buffer = NULL; + ctx.pos = 0; + midend_save_prefs(me, savefile_write, &ctx); + size = ctx.pos; + + /* Second pass, to actually write out the data. As with + * get_save_file, we append a terminating \0. */ + ctx.buffer = snewn(size+1, char); + ctx.pos = 0; + midend_save_prefs(me, savefile_write, &ctx); + assert(ctx.pos == size); + ctx.buffer[ctx.pos] = '\0'; + + js_save_prefs(ctx.buffer); + + sfree(ctx.buffer); +} + +struct prefs_read_ctx { + const char *buffer; + size_t pos, len; +}; + +static bool prefs_read(void *vctx, void *buf, int len) +{ + struct prefs_read_ctx *ctx = (struct prefs_read_ctx *)vctx; + + if (len < 0) + return false; + if (ctx->len - ctx->pos < len) + return false; + memcpy(buf, ctx->buffer + ctx->pos, len); + ctx->pos += len; + return true; +} + +void prefs_load_callback(midend *me, const char *prefs) +{ + struct prefs_read_ctx ctx; + + ctx.buffer = prefs; + ctx.len = strlen(prefs); + ctx.pos = 0; + + midend_load_prefs(me, prefs_read, &ctx); +} + /* ---------------------------------------------------------------------- * Setup function called at page load time. It's called main() because * that's the most convenient thing in Emscripten, but it's not main() @@ -870,12 +1021,18 @@ int main(int argc, char **argv) { const char *param_err; float *colours; - int i; + int i, ncolours; + + /* + * Initialise JavaScript event handlers. + */ + js_init_puzzle(); /* * Instantiate a midend. */ me = midend_new(NULL, &thegame, &js_drawing, NULL); + js_load_prefs(me); /* * Chuck in the HTML fragment ID if we have one (trimming the @@ -896,10 +1053,10 @@ int main(int argc, char **argv) resize(); /* - * Create a status bar, if needed. + * Remove the status bar, if not needed. */ - if (midend_wants_statusbar(me)) - js_canvas_make_statusbar(); + if (!midend_wants_statusbar(me)) + js_canvas_remove_statusbar(); /* * Set up the game-type dropdown with presets and/or the Custom @@ -907,23 +1064,33 @@ int main(int argc, char **argv) */ { struct preset_menu *menu = midend_get_presets(me, &npresets); + bool may_configure = false; presets = snewn(npresets, game_params *); for (i = 0; i < npresets; i++) presets[i] = NULL; populate_js_preset_menu(0, menu); - if (thegame.can_configure) - js_add_preset(0, "Custom", -1); - - have_presets_dropdown = true; - /* - * Now ensure the appropriate element of the presets menu - * starts off selected, in case it isn't the first one in the - * list (e.g. Slant). + * Crude hack to allow the "Custom..." item to be hidden on + * KaiOS, where dialogs don't yet work. */ - select_appropriate_preset(); + if (thegame.can_configure && getenv_bool("PUZZLES_ALLOW_CUSTOM", true)) + may_configure = true; + if (may_configure) + js_add_preset(0, "Custom...", -1); + + have_presets_dropdown = npresets > 1 || may_configure; + + if (have_presets_dropdown) + /* + * Now ensure the appropriate element of the presets menu + * starts off selected, in case it isn't the first one in the + * list (e.g. Slant). + */ + select_appropriate_preset(); + else + js_remove_type_dropdown(); } /* @@ -937,14 +1104,13 @@ int main(int argc, char **argv) * hex ID strings. */ colours = midend_colours(me, &ncolours); - colour_strings = snewn(ncolours, char *); for (i = 0; i < ncolours; i++) { char col[40]; sprintf(col, "#%02x%02x%02x", - (unsigned)(0.5 + 255 * colours[i*3+0]), - (unsigned)(0.5 + 255 * colours[i*3+1]), - (unsigned)(0.5 + 255 * colours[i*3+2])); - colour_strings[i] = dupstr(col); + (unsigned)(0.5F + 255 * colours[i*3+0]), + (unsigned)(0.5F + 255 * colours[i*3+1]), + (unsigned)(0.5F + 255 * colours[i*3+2])); + js_set_colour(i, col); } /* @@ -960,7 +1126,7 @@ int main(int argc, char **argv) */ midend_redraw(me); update_permalinks(); - update_undo_redo(); + post_move(); /* * If we were given an erroneous game ID in argv[1], now's the @@ -971,6 +1137,11 @@ int main(int argc, char **argv) if (param_err) js_error_box(param_err); + /* + * Reveal the puzzle! + */ + js_post_init(); + /* * Done. Return to JS, and await callbacks! */ diff --git a/apps/plugins/puzzles/src/emcccopy.but b/apps/plugins/puzzles/src/emcccopy.but new file mode 100644 index 0000000000..5332e0df38 --- /dev/null +++ b/apps/plugins/puzzles/src/emcccopy.but @@ -0,0 +1,128 @@ +\A{thirdparty} Third-party software licences + +\# This file should contain the copyright notices for third-party code +included in the Emscripten builds of Puzzles. To get a list of +relevant source files, you can build Puzzles with "-gsource-map" and +then do something like: + +\# jq -r '.sources[]' *.map | sort -u + +\# This file is based on a build of Git commit +2e48ce132e011e83517a9fc4905edcc8f9a5ef58 using Emscripten 3.1.35 + +\# system/lib/compiler-rt/lib/builtins/* +\# upstream/lib/clang/17/include/tgmath.h + +\# These are under the Apache Licence v2.0 with LLVM Exceptions. The +LLVM Exceptions allow us not to mention them in binary distributions. + +\# system/lib/dlmalloc.c + +\# dlmalloc is in the public domain and so needs no acknowledgement. + +The JavaScript and KaiOS versions of Puzzles incorporate some third +party software. Most of it is licensed under the \i{MIT licence} (see +\k{licence}) and requires the following \i{copyright} notices: + +\quote{ + +\# system/lib/libc/emscripten_get_heap_size.c +\# system/lib/libc/emscripten_memcpy.c +\# system/lib/libc/emscripten_syscall_stubs.c +\# system/lib/libc/wasi-helpers.c +\# system/lib/pthread/library_pthread_stub.c +\# system/lib/pthread/pthread_self_stub.c +\# system/lib/sbrk.c + +\# These are parts of Emscripten and either refer explicitly to the +Emscripten LICENSE file or make no mention of a licence. LICENSE +allows use under the MIT licence and specifies this copyright notice: + +Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file. + +\# cache/sysroot/include/math.h +\# system/lib/libc/musl/src/ctype/* +\# system/lib/libc/musl/src/env/* +\# system/lib/libc/musl/src/errno/* +\# system/lib/libc/musl/src/internal/atomic.h +\# system/lib/libc/musl/src/internal/floatscan.c +\# system/lib/libc/musl/src/internal/intscan.c +\# system/lib/libc/musl/src/internal/shgetc.c +\# system/lib/libc/musl/src/math/copysignl.c +\# system/lib/libc/musl/src/math/fabs.c +\# system/lib/libc/musl/src/math/fabsl.c +\# system/lib/libc/musl/src/math/floor.c +\# system/lib/libc/musl/src/math/fmodl.c +\# system/lib/libc/musl/src/math/__fpclassifyl.c +\# system/lib/libc/musl/src/math/frexp.c +\# system/lib/libc/musl/src/math/scalbn.c +\# system/lib/libc/musl/src/math/scalbnl.c +\# system/lib/libc/musl/src/math/sqrtf.c +\# system/lib/libc/musl/src/multibyte/* +\# system/lib/libc/musl/src/stdio/* +\# system/lib/libc/musl/src/stdlib/abs.c +\# system/lib/libc/musl/src/stdlib/atof.c +\# system/lib/libc/musl/src/stdlib/atoi.c +\# system/lib/libc/musl/src/stdlib/atol.c +\# system/lib/libc/musl/src/stdlib/labs.c +\# system/lib/libc/musl/src/stdlib/qsort_nr.c +\# system/lib/libc/musl/src/stdlib/strtod.c +\# system/lib/libc/musl/src/stdlib/strtol.c +\# system/lib/libc/musl/src/string/* +\# system/lib/libc/musl/src/unistd/getpid.c + +\# These are parts of musl, which is licensed "as a whole" under the +MIT licence. These parts don't carry any licence notice themselves. +This is the copyright notice from musl's COPYRIGHT file, modified to +allow for non-Unicode targets: + +Copyright \u00A9{(C)} 2005-2020 Rich Felker, et al. + +\# system/lib/libc/musl/src/stdlib/qsort.c + +\# This is part of musl, but has its own copyright notice and MIT +licence in its source file. + +Copyright (C) 2011 by Valentin Ochs + +} + +Other incorporated software requires these notices: + +\quote{ + +\# system/lib/libc/musl/src/math/acosf.c +\# system/lib/libc/musl/src/math/atan.c +\# system/lib/libc/musl/src/math/cos.c +\# system/lib/libc/musl/src/math/__cosdf.c +\# system/lib/libc/musl/src/math/cosf.c +\# system/lib/libc/musl/src/math/__rem_pio2f.c +\# system/lib/libc/musl/src/math/sin.c +\# system/lib/libc/musl/src/math/__sindf.c +\# system/lib/libc/musl/src/math/sinf.c + +\# These are parts of musl with a SunPro copyright notice and licence. + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + +\# system/lib/libc/musl/src/math/atan2.c +\# system/lib/libc/musl/src/math/__cos.c +\# system/lib/libc/musl/src/math/__rem_pio2.c +\# system/lib/libc/musl/src/math/__rem_pio2_large.c +\# system/lib/libc/musl/src/math/__sin.c + +\# These are parts of musl with a SunSoft copyright notice and licence. + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + +} \ No newline at end of file diff --git a/apps/plugins/puzzles/src/fifteen.R b/apps/plugins/puzzles/src/fifteen.R deleted file mode 100644 index b2292acc69..0000000000 --- a/apps/plugins/puzzles/src/fifteen.R +++ /dev/null @@ -1,22 +0,0 @@ -# -*- makefile -*- - -fifteen : [X] GTK COMMON fifteen fifteen-icon|no-icon - -fifteen : [G] WINDOWS COMMON fifteen fifteen.res|noicon.res - -fifteensolver : [U] fifteen[STANDALONE_SOLVER] STANDALONE -fifteensolver : [C] fifteen[STANDALONE_SOLVER] STANDALONE - -ALL += fifteen[COMBINED] - -!begin am gtk -GAMES += fifteen -!end - -!begin >list.c - A(fifteen) \ -!end - -!begin >gamedesc.txt -fifteen:fifteen.exe:Fifteen:Sliding block puzzle:Slide the tiles around to arrange them into order. -!end diff --git a/apps/plugins/puzzles/src/fifteen.c b/apps/plugins/puzzles/src/fifteen.c index 4b877dc098..a2a9554523 100644 --- a/apps/plugins/puzzles/src/fifteen.c +++ b/apps/plugins/puzzles/src/fifteen.c @@ -7,7 +7,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -138,6 +143,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; return NULL; } @@ -156,6 +163,14 @@ static int perm_parity(int *perm, int n) return ret; } +static int is_completed(int *tiles, int n) { + int p; + for (p = 0; p < n; p++) + if (tiles[p] != (p < n-1 ? p+1 : 0)) + return 0; + return 1; +} + static char *new_game_desc(const game_params *params, random_state *rs, char **aux, bool interactive) { @@ -171,81 +186,83 @@ static char *new_game_desc(const game_params *params, random_state *rs, tiles = snewn(n, int); used = snewn(n, bool); - for (i = 0; i < n; i++) { - tiles[i] = -1; - used[i] = false; - } + do { + for (i = 0; i < n; i++) { + tiles[i] = -1; + used[i] = false; + } - gap = random_upto(rs, n); - tiles[gap] = 0; - used[0] = true; + gap = random_upto(rs, n); + tiles[gap] = 0; + used[0] = true; - /* - * Place everything else except the last two tiles. - */ - for (x = 0, i = n-1; i > 2; i--) { - int k = random_upto(rs, i); - int j; + /* + * Place everything else except the last two tiles. + */ + for (x = 0, i = n - 1; i > 2; i--) { + int k = random_upto(rs, i); + int j; - for (j = 0; j < n; j++) - if (!used[j] && (k-- == 0)) - break; + for (j = 0; j < n; j++) + if (!used[j] && (k-- == 0)) + break; - assert(j < n && !used[j]); - used[j] = true; + assert(j < n && !used[j]); + used[j] = true; + + while (tiles[x] >= 0) + x++; + assert(x < n); + tiles[x] = j; + } + /* + * Find the last two locations, and the last two pieces. + */ while (tiles[x] >= 0) x++; assert(x < n); - tiles[x] = j; - } - - /* - * Find the last two locations, and the last two pieces. - */ - while (tiles[x] >= 0) - x++; - assert(x < n); - x1 = x; - x++; - while (tiles[x] >= 0) + x1 = x; x++; - assert(x < n); - x2 = x; - - for (i = 0; i < n; i++) - if (!used[i]) - break; - p1 = i; - for (i = p1+1; i < n; i++) - if (!used[i]) - break; - p2 = i; + while (tiles[x] >= 0) + x++; + assert(x < n); + x2 = x; - /* - * Determine the required parity of the overall permutation. - * This is the XOR of: - * - * - The chessboard parity ((x^y)&1) of the gap square. The - * bottom right counts as even. - * - * - The parity of n. (The target permutation is 1,...,n-1,0 - * rather than 0,...,n-1; this is a cyclic permutation of - * the starting point and hence is odd iff n is even.) - */ - parity = PARITY_P(params, gap); + for (i = 0; i < n; i++) + if (!used[i]) + break; + p1 = i; + for (i = p1 + 1; i < n; i++) + if (!used[i]) + break; + p2 = i; - /* - * Try the last two tiles one way round. If that fails, swap - * them. - */ - tiles[x1] = p1; - tiles[x2] = p2; - if (perm_parity(tiles, n) != parity) { - tiles[x1] = p2; - tiles[x2] = p1; - assert(perm_parity(tiles, n) == parity); - } + /* + * Determine the required parity of the overall permutation. + * This is the XOR of: + * + * - The chessboard parity ((x^y)&1) of the gap square. The + * bottom right counts as even. + * + * - The parity of n. (The target permutation is 1,...,n-1,0 + * rather than 0,...,n-1; this is a cyclic permutation of + * the starting point and hence is odd iff n is even.) + */ + parity = PARITY_P(params, gap); + + /* + * Try the last two tiles one way round. If that fails, swap + * them. + */ + tiles[x1] = p1; + tiles[x2] = p2; + if (perm_parity(tiles, n) != parity) { + tiles[x1] = p2; + tiles[x2] = p1; + assert(perm_parity(tiles, n) == parity); + } + } while (is_completed(tiles, n)); /* * Now construct the game description, by describing the tile @@ -432,22 +449,68 @@ static char *game_text_format(const game_state *state) return ret; } +struct game_ui { + /* + * User-preference option: invert the direction of arrow-key + * control, so that the arrow on the key you press indicates in + * which direction you want the _space_ to move, rather than in + * which direction you want a tile to move to fill the space. + */ + bool invert_cursor; +}; + +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int invert_cursor = -1; + + if (!initialised) { + initialised = true; + invert_cursor = getenv_bool("FIFTEEN_INVERT_CURSOR", -1); + } + + if (invert_cursor != -1) + ui_out->invert_cursor = invert_cursor; +} + static game_ui *new_ui(const game_state *state) { - return NULL; + struct game_ui *ui = snew(struct game_ui); + + ui->invert_cursor = false; + + legacy_prefs_override(ui); + + return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Sense of arrow keys"; + ret[0].kw = "arrow-semantics"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = ":Move the tile:Move the gap"; + ret[0].u.choices.choicekws = ":tile:gap"; + ret[0].u.choices.selected = ui->invert_cursor; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->invert_cursor = cfg[0].u.choices.selected; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -692,28 +755,23 @@ static char *interpret_move(const game_state *state, game_ui *ui, int cy = Y(state, state->gap_pos), ny = cy; char buf[80]; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (button == LEFT_BUTTON) { nx = FROMCOORD(x); ny = FROMCOORD(y); if (nx < 0 || nx >= state->w || ny < 0 || ny >= state->h) - return NULL; /* out of bounds */ + return MOVE_UNUSED; /* out of bounds */ } else if (IS_CURSOR_MOVE(button)) { - static int invert_cursor = -1; - if (invert_cursor == -1) { - char *env = getenv("FIFTEEN_INVERT_CURSOR"); - invert_cursor = (env && (env[0] == 'y' || env[0] == 'Y')); - } button = flip_cursor(button); /* the default */ - if (invert_cursor) + if (ui->invert_cursor) button = flip_cursor(button); /* undoes the first flip */ - move_cursor(button, &nx, &ny, state->w, state->h, false); + move_cursor(button, &nx, &ny, state->w, state->h, false, NULL); } else if ((button == 'h' || button == 'H') && !state->completed) { if (!compute_hint(state, &nx, &ny)) - return NULL; /* shouldn't happen, since ^^we^^checked^^ */ + return MOVE_NO_EFFECT;/* shouldn't happen, since ^^we^^checked^^ */ } else - return NULL; /* no move */ + return MOVE_UNUSED; /* no move */ /* * Any click location should be equal to the gap location @@ -724,7 +782,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, return dupstr(buf); } - return NULL; + return MOVE_NO_EFFECT; } static game_state *execute_move(const game_state *from, const char *move) @@ -786,11 +844,8 @@ static game_state *execute_move(const game_state *from, const char *move) /* * See if the game has been completed. */ - if (!ret->completed) { + if (!ret->completed && is_completed(ret->tiles, ret->n)) { ret->completed = ret->movecount; - for (p = 0; p < ret->n; p++) - if (ret->tiles[p] != (p < ret->n-1 ? p+1 : 0)) - ret->completed = 0; } return ret; @@ -801,7 +856,7 @@ static game_state *execute_move(const game_state *from, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -904,13 +959,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -1077,19 +1125,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame fifteen #endif @@ -1111,12 +1146,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1128,9 +1165,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/filling.R b/apps/plugins/puzzles/src/filling.R deleted file mode 100644 index cffbafaa0a..0000000000 --- a/apps/plugins/puzzles/src/filling.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -FILLING_EXTRA = dsf - -fillingsolver : [U] filling[STANDALONE_SOLVER] FILLING_EXTRA STANDALONE -fillingsolver : [C] filling[STANDALONE_SOLVER] FILLING_EXTRA STANDALONE - -filling : [X] GTK COMMON filling FILLING_EXTRA filling-icon|no-icon - -filling : [G] WINDOWS COMMON filling FILLING_EXTRA filling.res|noicon.res - -ALL += filling[COMBINED] FILLING_EXTRA - -!begin am gtk -GAMES += filling -!end - -!begin >list.c - A(filling) \ -!end - -!begin >gamedesc.txt -filling:filling.exe:Filling:Polyomino puzzle:Mark every square with the area of its containing region. -!end diff --git a/apps/plugins/puzzles/src/filling.c b/apps/plugins/puzzles/src/filling.c index 6d9beb5c28..a0c144714b 100644 --- a/apps/plugins/puzzles/src/filling.c +++ b/apps/plugins/puzzles/src/filling.c @@ -1,4 +1,4 @@ -/* -*- tab-width: 8; indent-tabs-mode: t -*- +/* * filling.c: An implementation of the Nikoli game fillomino. * Copyright (C) 2007 Jonas Kölker. See LICENSE for the license. */ @@ -58,7 +58,11 @@ #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include #include #include @@ -68,16 +72,11 @@ static bool verbose; -static void printv(const char *fmt, ...) { -#if !defined(PALM) && !defined(ROCKBOX) - if (verbose) { - va_list va; - va_start(va, fmt); - vprintf(fmt, va); - va_end(va); - } +#ifdef STANDALONE_SOLVER +#define printv if (!verbose); else printf +#else +#define printv(...) #endif -} /***************************************************************************** * GAME CONFIGURATION AND PARAMETERS * @@ -188,6 +187,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 1) return "Width must be at least one"; if (params->h < 1) return "Height must be at least one"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; return NULL; } @@ -289,14 +290,15 @@ static const int dy[4] = {0, 0, -1, 1}; struct solver_state { - int *dsf; + DSF *dsf; int *board; int *connected; int nempty; /* Used internally by learn_bitmap_deductions; kept here to avoid * mallocing/freeing them every time that function is called. */ - int *bm, *bmdsf, *bmminsize; + int *bm, *bmminsize; + DSF *bmdsf; }; static void print_board(int *board, int w, int h) { @@ -310,7 +312,7 @@ static void print_board(int *board, int w, int h) { static game_state *new_game(midend *, const game_params *, const char *); static void free_game(game_state *); -#define SENTINEL sz +#define SENTINEL (sz+1) static bool mark_region(int *board, int w, int h, int i, int n, int m) { int j; @@ -390,7 +392,8 @@ static void make_board(int *board, int w, int h, random_state *rs) { /* Note that if 1 in {w, h} then it's impossible to have a region * of size > w*h, so the special case only affects w=h=2. */ - int i, *dsf; + int i; + DSF *dsf; bool change; assert(w >= 1); @@ -401,9 +404,9 @@ static void make_board(int *board, int w, int h, random_state *rs) { * contains a shuffled list of numbers {0, ..., sz-1}. */ for (i = 0; i < sz; ++i) board[i] = i; - dsf = snewn(sz, int); + dsf = dsf_new(sz); retry: - dsf_init(dsf, sz); + dsf_reinit(dsf); shuffle(board, sz, sizeof (int), rs); do { @@ -414,10 +417,15 @@ retry: int merge = SENTINEL, min = maxsize - size + 1; bool error = false; int neighbour, neighbour_size, j; + int directions[4]; + + for (j = 0; j < 4; ++j) + directions[j] = j; + shuffle(directions, 4, sizeof(int), rs); for (j = 0; j < 4; ++j) { - const int x = (board[i] % w) + dx[j]; - const int y = (board[i] / w) + dy[j]; + const int x = (board[i] % w) + dx[directions[j]]; + const int y = (board[i] / w) + dy[directions[j]]; if (x < 0 || x >= w || y < 0 || y >= h) continue; neighbour = dsf_canonify(dsf, w*y + x); @@ -429,7 +437,7 @@ retry: /* find the smallest neighbour to merge with, which * wouldn't make the region too large. (This is * guaranteed by the initial value of `min'.) */ - if (neighbour_size < min) { + if (neighbour_size < min && random_upto(rs, 10)) { min = neighbour_size; merge = neighbour; } @@ -453,10 +461,10 @@ retry: for (i = 0; i < sz; ++i) board[i] = dsf_size(dsf, i); merge_ones(board, w, h); - sfree(dsf); + dsf_free(dsf); } -static void merge(int *dsf, int *connected, int a, int b) { +static void merge(DSF *dsf, int *connected, int a, int b) { int c; assert(dsf); assert(connected); @@ -532,7 +540,7 @@ static bool check_capacity(int *board, int w, int h, int i) { return n == 0; } -static int expandsize(const int *board, int *dsf, int w, int h, int i, int n) { +static int expandsize(const int *board, DSF *dsf, int w, int h, int i, int n) { int j; int nhits = 0; int hits[4]; @@ -548,7 +556,7 @@ static int expandsize(const int *board, int *dsf, int w, int h, int i, int n) { root = dsf_canonify(dsf, idx); for (m = 0; m < nhits && root != hits[m]; ++m); if (m < nhits) continue; - printv("\t (%d, %d) contrib %d to size\n", x, y, dsf[root] >> 2); + printv("\t (%d, %d) contrib %d to size\n", x, y, dsf_size(dsf, root)); size += dsf_size(dsf, root); assert(dsf_size(dsf, root) >= 1); hits[nhits++] = root; @@ -833,7 +841,7 @@ static bool learn_bitmap_deductions(struct solver_state *s, int w, int h) { const int sz = w * h; int *bm = s->bm; - int *dsf = s->bmdsf; + DSF *dsf = s->bmdsf; int *minsize = s->bmminsize; int x, y, i, j, n; bool learn = false; @@ -933,7 +941,7 @@ static bool learn_bitmap_deductions(struct solver_state *s, int w, int h) * have a completely new n-region in it. */ for (n = 1; n <= 9; n++) { - dsf_init(dsf, sz); + dsf_reinit(dsf); /* Build the dsf */ for (y = 0; y < h; y++) @@ -1076,12 +1084,12 @@ static bool solver(const int *orig, int w, int h, char **solution) { struct solver_state ss; ss.board = memdup(orig, sz, sizeof (int)); - ss.dsf = snew_dsf(sz); /* eqv classes: connected components */ + ss.dsf = dsf_new(sz); /* eqv classes: connected components */ ss.connected = snewn(sz, int); /* connected[n] := n.next; */ /* cyclic disjoint singly linked lists, same partitioning as dsf. * The lists lets you iterate over a partition given any member */ ss.bm = snewn(sz, int); - ss.bmdsf = snew_dsf(sz); + ss.bmdsf = dsf_new(sz); ss.bmminsize = snewn(sz, int); printv("trying to solve this:\n"); @@ -1105,28 +1113,26 @@ static bool solver(const int *orig, int w, int h, char **solution) { **solution = 's'; for (i = 0; i < sz; ++i) (*solution)[i + 1] = ss.board[i] + '0'; (*solution)[sz + 1] = '\0'; - /* We don't need the \0 for execute_move (the only user) - * I'm just being printf-friendly in case I wanna print */ } - sfree(ss.dsf); + dsf_free(ss.dsf); sfree(ss.board); sfree(ss.connected); sfree(ss.bm); - sfree(ss.bmdsf); + dsf_free(ss.bmdsf); sfree(ss.bmminsize); return !ss.nempty; } -static int *make_dsf(int *dsf, int *board, const int w, const int h) { +static DSF *make_dsf(DSF *dsf, int *board, const int w, const int h) { const int sz = w * h; int i; if (!dsf) - dsf = snew_dsf(w * h); + dsf = dsf_new_min(w * h); else - dsf_init(dsf, w * h); + dsf_reinit(dsf); for (i = 0; i < sz; ++i) { int j; @@ -1145,7 +1151,8 @@ static void minimize_clue_set(int *board, int w, int h, random_state *rs) { const int sz = w * h; int *shuf = snewn(sz, int), i; - int *dsf, *next; + DSF *dsf; + int *next; for (i = 0; i < sz; ++i) shuf[i] = i; shuffle(shuf, sz, sizeof (int), rs); @@ -1162,14 +1169,14 @@ static void minimize_clue_set(int *board, int w, int h, random_state *rs) dsf = make_dsf(NULL, board, w, h); next = snewn(sz, int); for (i = 0; i < sz; ++i) { - int j = dsf_canonify(dsf, i); + int j = dsf_minimal(dsf, i); if (i == j) { /* First cell of a region; set next[i] = -1 to indicate * end-of-list. */ next[i] = -1; } else { /* Add this cell to a region which already has a - * linked-list head, by pointing the canonical element j + * linked-list head, by pointing the minimal element j * at this one, and pointing this one in turn at wherever * j previously pointed. (This should end up with the * elements linked in the order 1,n,n-1,n-2,...,2, which @@ -1197,7 +1204,7 @@ static void minimize_clue_set(int *board, int w, int h, random_state *rs) * if we can. */ for (i = 0; i < sz; ++i) { - int j = dsf_canonify(dsf, shuf[i]); + int j = dsf_minimal(dsf, shuf[i]); if (next[j] != -2) { int tmp = board[j]; int k; @@ -1217,7 +1224,7 @@ static void minimize_clue_set(int *board, int w, int h, random_state *rs) } } sfree(next); - sfree(dsf); + dsf_free(dsf); /* * Now go through individual cells, in the same shuffled order, @@ -1391,7 +1398,7 @@ static game_ui *new_ui(const game_state *state) ui->sel = NULL; ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->keydragging = false; return ui; @@ -1404,15 +1411,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -1424,6 +1422,23 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->keydragging = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + const int w = state->shared->params.w; + + if (IS_CURSOR_SELECT(button) && ui->cur_visible) { + if (button == CURSOR_SELECT) { + if (ui->keydragging) return "Stop"; + return "Multiselect"; + } + if (button == CURSOR_SELECT2 && + !state->shared->clues[w*ui->cur_y + ui->cur_x]) + return (ui->sel[w*ui->cur_y + ui->cur_x]) ? "Deselect" : "Select"; + } + return ""; +} + #define PREFERRED_TILE_SIZE 32 #define TILE_SIZE (ds->tilesize) #define BORDER (TILE_SIZE / 2) @@ -1434,7 +1449,8 @@ struct game_drawstate { int tilesize; bool started; int *v, *flags; - int *dsf_scratch, *border_scratch; + DSF *dsf_scratch; + int *border_scratch; }; static char *interpret_move(const game_state *state, game_ui *ui, @@ -1453,7 +1469,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, assert(ui); assert(ds); - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (button == LEFT_BUTTON || button == LEFT_DRAG) { /* A left-click anywhere will clear the current selection. */ @@ -1472,22 +1488,22 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->sel[w*ty+tx] = true; } ui->cur_visible = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_MOVE(button)) { ui->cur_visible = true; - move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false, NULL); if (ui->keydragging) goto select_square; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == CURSOR_SELECT) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } ui->keydragging = !ui->keydragging; - if (!ui->keydragging) return UI_UPDATE; + if (!ui->keydragging) return MOVE_UI_UPDATE; select_square: if (!ui->sel) { @@ -1496,12 +1512,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (!state->shared->clues[w*ui->cur_y + ui->cur_x]) ui->sel[w*ui->cur_y + ui->cur_x] = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == CURSOR_SELECT2) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (!ui->sel) { ui->sel = snewn(w*h, bool); @@ -1515,19 +1531,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, sfree(ui->sel); ui->sel = NULL; } - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == '\b' || button == 27) { sfree(ui->sel); ui->sel = NULL; ui->keydragging = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } - if (button < '0' || button > '9') return NULL; + if (button < '0' || button > '9') return MOVE_UNUSED; button -= '0'; - if (button > (w == 2 && h == 2 ? 3 : max(w, h))) return NULL; + if (button > (w == 2 && h == 2 ? 3 : max(w, h))) return MOVE_UNUSED; ui->keydragging = false; for (i = 0; i < w*h; i++) { @@ -1553,11 +1569,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, move = srealloc(move, strlen(move)+strlen(buf)+1); strcat(move, buf); } - if (!ui->sel) return move ? move : NULL; + if (!ui->sel) return move ? move : MOVE_NO_EFFECT; sfree(ui->sel); ui->sel = NULL; /* Need to update UI at least, as we cleared the selection */ - return move ? move : UI_UPDATE; + return move ? move : MOVE_UI_UPDATE; } static game_state *execute_move(const game_state *state, const char *move) @@ -1567,6 +1583,7 @@ static game_state *execute_move(const game_state *state, const char *move) if (*move == 's') { int i = 0; + if (strlen(move) != sz + 1) return NULL; new_state = dup_game(state); for (++move; i < sz; ++i) new_state->board[i] = move[i] - '0'; new_state->cheated = true; @@ -1596,10 +1613,10 @@ static game_state *execute_move(const game_state *state, const char *move) const int w = new_state->shared->params.w; const int h = new_state->shared->params.h; const int sz = w * h; - int *dsf = make_dsf(NULL, new_state->board, w, h); + DSF *dsf = make_dsf(NULL, new_state->board, w, h); int i; for (i = 0; i < sz && new_state->board[i] == dsf_size(dsf, i); ++i); - sfree(dsf); + dsf_free(dsf); if (i == sz) new_state->completed = true; } @@ -1630,7 +1647,7 @@ enum { }; static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = (params->w + 1) * tilesize; *y = (params->h + 1) * tilesize; @@ -1652,9 +1669,9 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_GRID * 3 + 1] = 0.0F; ret[COL_GRID * 3 + 2] = 0.0F; - ret[COL_HIGHLIGHT * 3 + 0] = 0.85F * ret[COL_BACKGROUND * 3 + 0]; - ret[COL_HIGHLIGHT * 3 + 1] = 0.85F * ret[COL_BACKGROUND * 3 + 1]; - ret[COL_HIGHLIGHT * 3 + 2] = 0.85F * ret[COL_BACKGROUND * 3 + 2]; + ret[COL_HIGHLIGHT * 3 + 0] = 0.7F * ret[COL_BACKGROUND * 3 + 0]; + ret[COL_HIGHLIGHT * 3 + 1] = 0.7F * ret[COL_BACKGROUND * 3 + 1]; + ret[COL_HIGHLIGHT * 3 + 2] = 0.7F * ret[COL_BACKGROUND * 3 + 2]; ret[COL_CORRECT * 3 + 0] = 0.9F * ret[COL_BACKGROUND * 3 + 0]; ret[COL_CORRECT * 3 + 1] = 0.9F * ret[COL_BACKGROUND * 3 + 1]; @@ -1699,7 +1716,7 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) sfree(ds->v); sfree(ds->flags); sfree(ds->border_scratch); - sfree(ds->dsf_scratch); + dsf_free(ds->dsf_scratch); sfree(ds); } @@ -2016,17 +2033,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds, (flashtime <= FLASH_TIME/3 || flashtime >= FLASH_TIME*2/3); if (!ds->started) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all games - * should start by drawing a big background-colour rectangle - * covering the whole window. - */ - draw_rect(dr, 0, 0, w*TILE_SIZE + 2*BORDER, h*TILE_SIZE + 2*BORDER, - COL_BACKGROUND); - /* - * Smaller black rectangle which is the main grid. + * Black rectangle which is the main grid. */ draw_rect(dr, BORDER - BORDER_WIDTH, BORDER - BORDER_WIDTH, w*TILE_SIZE + 2*BORDER_WIDTH + 1, @@ -2079,24 +2087,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { const int w = state->shared->params.w; const int h = state->shared->params.h; @@ -2164,12 +2169,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2183,13 +2190,18 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_NUMPAD, /* flags */ }; #ifdef STANDALONE_SOLVER /* solver? hah! */ int main(int argc, char **argv) { + if (!strcmp(argv[1], "--verbose")) { + verbose = true; + argv++; + } + while (*++argv) { game_params *params; game_state *state; diff --git a/apps/plugins/puzzles/src/flip.R b/apps/plugins/puzzles/src/flip.R deleted file mode 100644 index 03241f015b..0000000000 --- a/apps/plugins/puzzles/src/flip.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -FLIP_EXTRA = tree234 - -flip : [X] GTK COMMON flip FLIP_EXTRA flip-icon|no-icon - -flip : [G] WINDOWS COMMON flip FLIP_EXTRA flip.res|noicon.res - -ALL += flip[COMBINED] FLIP_EXTRA - -!begin am gtk -GAMES += flip -!end - -!begin >list.c - A(flip) \ -!end - -!begin >gamedesc.txt -flip:flip.exe:Flip:Tile inversion puzzle:Flip groups of squares to light them all up at once. -!end diff --git a/apps/plugins/puzzles/src/flip.c b/apps/plugins/puzzles/src/flip.c index 5d4f2250aa..044d6c30c3 100644 --- a/apps/plugins/puzzles/src/flip.c +++ b/apps/plugins/puzzles/src/flip.c @@ -8,7 +8,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -181,9 +186,16 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { + int wh; + if (params->w <= 0 || params->h <= 0) return "Width and height must both be greater than zero"; - return NULL; + if (params->w > (INT_MAX - 3) / params->h) + return "Width times height must not be unreasonably large"; + wh = params->w * params->h; + if (wh > (INT_MAX - 3) / wh) + return "Width times height is too large"; + return NULL; } static char *encode_bitmap(unsigned char *bmp, int len) @@ -905,7 +917,7 @@ static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cx = ui->cy = 0; - ui->cdraw = false; + ui->cdraw = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -914,18 +926,16 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + if (IS_CURSOR_SELECT(button)) return "Flip"; + return ""; } struct game_drawstate { @@ -940,7 +950,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int x, int y, int button) { int w = state->w, h = state->h, wh = w * h; - char buf[80], *nullret = NULL; + char buf[80], *nullret = MOVE_UNUSED; if (button == LEFT_BUTTON || IS_CURSOR_SELECT(button)) { int tx, ty; @@ -951,7 +961,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, tx = ui->cx; ty = ui->cy; ui->cdraw = true; } - nullret = UI_UPDATE; + nullret = MOVE_UI_UPDATE; if (tx >= 0 && tx < w && ty >= 0 && ty < h) { /* @@ -969,25 +979,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, sprintf(buf, "M%d,%d", tx, ty); return dupstr(buf); } else { - return NULL; + return MOVE_NO_EFFECT; } } - } - else if (IS_CURSOR_MOVE(button)) { - int dx = 0, dy = 0; - switch (button) { - case CURSOR_UP: dy = -1; break; - case CURSOR_DOWN: dy = 1; break; - case CURSOR_RIGHT: dx = 1; break; - case CURSOR_LEFT: dx = -1; break; - default: assert(!"shouldn't get here"); - } - ui->cx += dx; ui->cy += dy; - ui->cx = min(max(ui->cx, 0), state->w - 1); - ui->cy = min(max(ui->cy, 0), state->h - 1); - ui->cdraw = true; - nullret = UI_UPDATE; - } + } else if (IS_CURSOR_MOVE(button)) + nullret = move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, + false, &ui->cdraw); return nullret; } @@ -1045,7 +1042,7 @@ static game_state *execute_move(const game_state *from, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1145,7 +1142,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state, coords[7] = by + TILE_SIZE - (int)((float)TILE_SIZE * animtime); colour = (tile & 1 ? COL_WRONG : COL_RIGHT); - if (animtime < 0.5) + if (animtime < 0.5F) colour = COL_WRONG + COL_RIGHT - colour; draw_polygon(dr, coords, 4, colour, COL_GRID); @@ -1159,7 +1156,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state, for (j = 0; j < w; j++) if (state->matrix->matrix[(y*w+x)*wh + i*w+j]) { int ox = j - x, oy = i - y; - int td = TILE_SIZE / 16; + int td = TILE_SIZE / 16 ? TILE_SIZE / 16 : 1; int cx = (bx + TILE_SIZE/2) + (2 * ox - 1) * td; int cy = (by + TILE_SIZE/2) + (2 * oy - 1) * td; if (ox == 0 && oy == 0) @@ -1202,9 +1199,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int i, flashframe; if (!ds->started) { - draw_rect(dr, 0, 0, TILE_SIZE * w + 2 * BORDER, - TILE_SIZE * h + 2 * BORDER, COL_BACKGROUND); - /* * Draw the grid lines. */ @@ -1309,19 +1303,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame flip #endif @@ -1343,12 +1324,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1360,8 +1343,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/flood.R b/apps/plugins/puzzles/src/flood.R deleted file mode 100644 index 359bbb5dce..0000000000 --- a/apps/plugins/puzzles/src/flood.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -flood : [X] GTK COMMON flood flood-icon|no-icon - -flood : [G] WINDOWS COMMON flood flood.res|noicon.res - -ALL += flood[COMBINED] - -!begin am gtk -GAMES += flood -!end - -!begin >list.c - A(flood) \ -!end - -!begin >gamedesc.txt -flood:flood.exe:Flood:Flood-filling puzzle:Turn the grid the same colour in as few flood fills as possible. -!end diff --git a/apps/plugins/puzzles/src/flood.c b/apps/plugins/puzzles/src/flood.c index 74214a50b6..fe809745db 100644 --- a/apps/plugins/puzzles/src/flood.c +++ b/apps/plugins/puzzles/src/flood.c @@ -31,7 +31,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -140,13 +145,13 @@ static void decode_params(game_params *ret, char const *string) if (*string == 'c') { string++; ret->colours = atoi(string); - while (string[1] && isdigit((unsigned char)string[1])) string++; + while (*string && isdigit((unsigned char)*string)) string++; } else if (*string == 'm') { string++; ret->leniency = atoi(string); - while (string[1] && isdigit((unsigned char)string[1])) string++; - } - string++; + while (*string && isdigit((unsigned char)*string)) string++; + } else + string++; } } @@ -210,7 +215,9 @@ static const char *validate_params(const game_params *params, bool full) if (params->w * params->h < 2) return "Grid must contain at least two squares"; if (params->w < 1 || params->h < 1) - return "Width and height must both be at least one"; + return "Width and height must be at least one"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->colours < 3 || params->colours > 10) return "Must have between 3 and 10 colours"; if (params->leniency < 0) @@ -554,8 +561,10 @@ static char *new_game_desc(const game_params *params, random_state *rs, /* * Invent a random grid. */ - for (i = 0; i < wh; i++) - scratch->grid[i] = random_upto(rs, params->colours); + do { + for (i = 0; i < wh; i++) + scratch->grid[i] = random_upto(rs, params->colours); + } while (completed(w, h, scratch->grid)); /* * Run the solver, and count how many moves it uses. @@ -770,7 +779,7 @@ struct game_ui { static game_ui *new_ui(const game_state *state) { struct game_ui *ui = snew(struct game_ui); - ui->cursor_visible = false; + ui->cursor_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->cx = FILLX; ui->cy = FILLY; return ui; @@ -781,18 +790,21 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + if (button == CURSOR_SELECT && + state->grid[0] != state->grid[ui->cy*state->w+ui->cx]) + return "Fill"; + if (button == CURSOR_SELECT2 && + state->soln && state->solnpos < state->soln->nmoves) + return "Advance"; + return ""; } struct game_drawstate { @@ -818,35 +830,26 @@ static char *interpret_move(const game_state *state, game_ui *ui, { int w = state->w, h = state->h; int tx = -1, ty = -1, move = -1; + char *nullret = MOVE_NO_EFFECT; if (button == LEFT_BUTTON) { tx = FROMCOORD(x); ty = FROMCOORD(y); - ui->cursor_visible = false; - } else if (button == CURSOR_LEFT && ui->cx > 0) { - ui->cx--; - ui->cursor_visible = true; - return UI_UPDATE; - } else if (button == CURSOR_RIGHT && ui->cx+1 < w) { - ui->cx++; - ui->cursor_visible = true; - return UI_UPDATE; - } else if (button == CURSOR_UP && ui->cy > 0) { - ui->cy--; - ui->cursor_visible = true; - return UI_UPDATE; - } else if (button == CURSOR_DOWN && ui->cy+1 < h) { - ui->cy++; - ui->cursor_visible = true; - return UI_UPDATE; + if (ui->cursor_visible) { + ui->cursor_visible = false; + nullret = MOVE_UI_UPDATE; + } + } else if (IS_CURSOR_MOVE(button)) { + return move_cursor(button, &ui->cx, &ui->cy, w, h, false, + &ui->cursor_visible); } else if (button == CURSOR_SELECT) { tx = ui->cx; ty = ui->cy; - } else if (button == CURSOR_SELECT2 && - state->soln && state->solnpos < state->soln->nmoves) { - move = state->soln->moves[state->solnpos]; + } else if (button == CURSOR_SELECT2) { + if (state->soln && state->solnpos < state->soln->nmoves) + move = state->soln->moves[state->solnpos]; } else { - return NULL; + return MOVE_UNUSED; } if (tx >= 0 && tx < w && ty >= 0 && ty < h && @@ -859,7 +862,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, return dupstr(buf); } - return NULL; + return nullret; } static game_state *execute_move(const game_state *state, const char *move) @@ -869,7 +872,8 @@ static game_state *execute_move(const game_state *state, const char *move) if (move[0] == 'M' && sscanf(move+1, "%d", &c) == 1 && - c >= 0 && + c >= 0 && c < state->colours && + c != state->grid[FILLY * state->w + FILLX] && !state->complete) { int *queue = snewn(state->w * state->h, int); ret = dup_game(state); @@ -920,11 +924,23 @@ static game_state *execute_move(const game_state *state, const char *move) sol->moves = snewn(sol->nmoves, char); for (i = 0, p = move; i < sol->nmoves; i++) { - assert(*p); + if (!*p) { + badsolve: + sfree(sol->moves); + sfree(sol); + return NULL; + }; sol->moves[i] = atoi(p); + if (sol->moves[i] < 0 || sol->moves[i] >= state->colours || + (i == 0 ? + sol->moves[i] == state->grid[FILLY * state->w + FILLX] : + sol->moves[i] == sol->moves[i-1])) + /* Solution contains a fill with an invalid colour or + * the current colour. */ + goto badsolve; p += strspn(p, "0123456789"); if (*p) { - assert(*p == ','); + if (*p != ',') goto badsolve; p++; } } @@ -949,7 +965,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1076,31 +1092,33 @@ static void draw_tile(drawing *dr, game_drawstate *ds, colour += COL_1; draw_rect(dr, tx, ty, TILESIZE, TILESIZE, colour); - if (tile & BORDER_L) - draw_rect(dr, tx, ty, - SEP_WIDTH, TILESIZE, COL_SEPARATOR); - if (tile & BORDER_R) - draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty, - SEP_WIDTH, TILESIZE, COL_SEPARATOR); - if (tile & BORDER_U) - draw_rect(dr, tx, ty, - TILESIZE, SEP_WIDTH, COL_SEPARATOR); - if (tile & BORDER_D) - draw_rect(dr, tx, ty + TILESIZE - SEP_WIDTH, - TILESIZE, SEP_WIDTH, COL_SEPARATOR); - - if (tile & CORNER_UL) - draw_rect(dr, tx, ty, - SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); - if (tile & CORNER_UR) - draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty, - SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); - if (tile & CORNER_DL) - draw_rect(dr, tx, ty + TILESIZE - SEP_WIDTH, - SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); - if (tile & CORNER_DR) - draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty + TILESIZE - SEP_WIDTH, - SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); + if (SEP_WIDTH > 0) { + if (tile & BORDER_L) + draw_rect(dr, tx, ty, + SEP_WIDTH, TILESIZE, COL_SEPARATOR); + if (tile & BORDER_R) + draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty, + SEP_WIDTH, TILESIZE, COL_SEPARATOR); + if (tile & BORDER_U) + draw_rect(dr, tx, ty, + TILESIZE, SEP_WIDTH, COL_SEPARATOR); + if (tile & BORDER_D) + draw_rect(dr, tx, ty + TILESIZE - SEP_WIDTH, + TILESIZE, SEP_WIDTH, COL_SEPARATOR); + + if (tile & CORNER_UL) + draw_rect(dr, tx, ty, + SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); + if (tile & CORNER_UR) + draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty, + SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); + if (tile & CORNER_DL) + draw_rect(dr, tx, ty + TILESIZE - SEP_WIDTH, + SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); + if (tile & CORNER_DR) + draw_rect(dr, tx + TILESIZE - SEP_WIDTH, ty + TILESIZE - SEP_WIDTH, + SEP_WIDTH, SEP_WIDTH, COL_SEPARATOR); + } if (tile & CURSOR) draw_rect_outline(dr, tx + CURSOR_INSET, ty + CURSOR_INSET, @@ -1130,13 +1148,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILESIZE * w + 2 * BORDER, - TILESIZE * h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILESIZE * w + 2 * BORDER, - TILESIZE * h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -1326,19 +1337,6 @@ static float game_flash_length(const game_state *oldstate, return 0.0F; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame flood #endif @@ -1360,12 +1358,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -1377,8 +1377,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/fuzzpuzz.c b/apps/plugins/puzzles/src/fuzzpuzz.c new file mode 100644 index 0000000000..3fb632ec57 --- /dev/null +++ b/apps/plugins/puzzles/src/fuzzpuzz.c @@ -0,0 +1,250 @@ +/* + * fuzzpuzz.c: Fuzzing frontend to all puzzles. + */ + +/* + * The idea here is that this front-end supports all back-ends and can + * feed them save files. It then asks the back-end to draw the puzzle + * (through a null drawing API) and reserialises the state. This + * tests the deserialiser, the code for loading game descriptions, the + * processing of move strings, the redraw code, and the serialisation + * routines, but is still pretty quick. + * + * To use AFL++ to drive fuzzpuzz, you can do something like: + * + * CC=afl-cc cmake -B build-afl + * cmake --build build-afl --target fuzzpuzz + * mkdir fuzz-in && ln icons/''*.sav fuzz-in + * afl-fuzz -i fuzz-in -o fuzz-out -x fuzzpuzz.dict -- build-afl/fuzzpuzz + * + * Similarly with Honggfuzz: + * + * CC=hfuzz-cc cmake -B build-honggfuzz + * cmake --build build-honggfuzz --target fuzzpuzz + * mkdir fuzz-corpus && ln icons/''*.sav fuzz-corpus + * honggfuzz -s -i fuzz-corpus -w fuzzpuzz.dict -- build-honggfuzz/fuzzpuzz + * + * You can also use libFuzzer, though it's not really a good fit for + * Puzzles. The experimental forking mode seems to work OK: + * + * CC=clang cmake -B build-clang -DWITH_LIBFUZZER=Y + * cmake --build build-clang --target fuzzpuzz + * mkdir fuzz-corpus && ln icons/''*.sav fuzz-corpus + * build-clang/fuzzpuzz -fork=1 -ignore_crashes=1 -dict=fuzzpuzz.dict \ + * fuzz-corpus + */ + +#include +#include +#include +#include +#ifdef __AFL_FUZZ_TESTCASE_LEN +# include /* read() is used by __AFL_FUZZ_TESTCASE_LEN. */ +#endif + +#include "puzzles.h" + +#ifdef __AFL_FUZZ_INIT +__AFL_FUZZ_INIT(); +#endif + +#ifdef HAVE_HF_ITER +extern int HF_ITER(unsigned char **, size_t *); +#endif + +/* This function is expected by libFuzzer. */ + +int LLVMFuzzerTestOneInput(unsigned char *data, size_t size); + +static const char *fuzz_one(bool (*readfn)(void *, void *, int), void *rctx, + void (*rewindfn)(void *), + void (*writefn)(void *, const void *, int), + void *wctx) +{ + const char *err; + char *gamename; + int i, w, h; + const game *ourgame = NULL; + static const drawing_api drapi = { NULL }; + midend *me; + + err = identify_game(&gamename, readfn, rctx); + if (err != NULL) return err; + + for (i = 0; i < gamecount; i++) + if (strcmp(gamename, gamelist[i]->name) == 0) + ourgame = gamelist[i]; + sfree(gamename); + if (ourgame == NULL) + return "Game not recognised"; + + me = midend_new(NULL, ourgame, &drapi, NULL); + + rewindfn(rctx); + err = midend_deserialise(me, readfn, rctx); + if (err != NULL) { + midend_free(me); + return err; + } + w = h = INT_MAX; + midend_size(me, &w, &h, false, 1); + midend_redraw(me); + midend_serialise(me, writefn, wctx); + midend_free(me); + return NULL; +} + +#if defined(__AFL_FUZZ_TESTCASE_LEN) || defined(HAVE_HF_ITER) || \ + !defined(OMIT_MAIN) +static void savefile_write(void *wctx, const void *buf, int len) +{ + FILE *fp = (FILE *)wctx; + + fwrite(buf, 1, len, fp); +} +#endif + +struct memread { + const unsigned char *buf; + size_t pos; + size_t len; +}; + +static bool mem_read(void *wctx, void *buf, int len) +{ + struct memread *ctx = wctx; + + if (ctx->pos + len > ctx->len) return false; + memcpy(buf, ctx->buf + ctx->pos, len); + ctx->pos += len; + return true; +} + +static void mem_rewind(void *wctx) +{ + struct memread *ctx = wctx; + + ctx->pos = 0; +} + +static void null_write(void *wctx, const void *buf, int len) +{ +} + +int LLVMFuzzerTestOneInput(unsigned char *data, size_t size) { + struct memread ctx; + + ctx.buf = data; + ctx.len = size; + ctx.pos = 0; + fuzz_one(mem_read, &ctx, mem_rewind, null_write, NULL); + return 0; +} + +#if defined(__AFL_FUZZ_TESTCASE_LEN) || defined(HAVE_HF_ITER) +static const char *fuzz_one_mem(unsigned char *data, size_t size) { + struct memread ctx; + + ctx.buf = data; + ctx.len = size; + ctx.pos = 0; + return fuzz_one(mem_read, &ctx, mem_rewind, savefile_write, stdout); +} +#endif + +/* + * Three different versions of main(), for standalone, AFL, and + * Honggfuzz modes. LibFuzzer brings its own main(). + */ + +#ifdef OMIT_MAIN +/* Nothing. */ +#elif defined(__AFL_FUZZ_TESTCASE_LEN) +/* + * AFL persistent mode, where we fuzz from a RAM buffer provided + * by AFL in a loop. This version can still be run standalone if + * necessary, for instance to diagnose a crash. + */ +int main(int argc, char **argv) +{ + const char *err; + int ret; + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", argv[0]); + return 1; + } +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + while (__AFL_LOOP(10000)) { + err = fuzz_one_mem(__AFL_FUZZ_TESTCASE_BUF, __AFL_FUZZ_TESTCASE_LEN); + if (err != NULL) { + fprintf(stderr, "%s\n", err); + ret = 1; + } else + ret = 0; + } + return ret; +} +#elif defined(HAVE_HF_ITER) +/* + * Honggfuzz persistent mode. Unlike AFL persistent mode, the + * resulting executable cannot be run outside of Honggfuzz. + */ +int main(int argc, char **argv) +{ + if (argc != 1) { + fprintf(stderr, "usage: %s\n", argv[0]); + return 1; + } + while (true) { + unsigned char *testcase_buf; + size_t testcase_len; + HF_ITER(&testcase_buf, &testcase_len); + fuzz_one_mem(testcase_buf, testcase_len); + } +} +#else +/* + * Stand-alone mode: just handle a single test case on stdin. + */ +static bool savefile_read(void *wctx, void *buf, int len) +{ + FILE *fp = (FILE *)wctx; + int ret; + + ret = fread(buf, 1, len, fp); + return (ret == len); +} + +static void savefile_rewind(void *wctx) +{ + FILE *fp = (FILE *)wctx; + + rewind(fp); +} + +int main(int argc, char **argv) +{ + const char *err; + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", argv[0]); + return 1; + } + + /* Might in theory use this mode under AFL. */ +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + + err = fuzz_one(savefile_read, stdin, savefile_rewind, + savefile_write, stdout); + if (err != NULL) { + fprintf(stderr, "%s\n", err); + return 1; + } + return 0; +} +#endif diff --git a/apps/plugins/puzzles/src/galaxies.R b/apps/plugins/puzzles/src/galaxies.R deleted file mode 100644 index 957e5dad90..0000000000 --- a/apps/plugins/puzzles/src/galaxies.R +++ /dev/null @@ -1,28 +0,0 @@ -# -*- makefile -*- - -GALAXIES_EXTRA = dsf - -galaxies : [X] GTK COMMON galaxies GALAXIES_EXTRA galaxies-icon|no-icon - -galaxies : [G] WINDOWS COMMON galaxies GALAXIES_EXTRA galaxies.res|noicon.res - -galaxiessolver : [U] galaxies[STANDALONE_SOLVER] GALAXIES_EXTRA STANDALONE m.lib -galaxiessolver : [C] galaxies[STANDALONE_SOLVER] GALAXIES_EXTRA STANDALONE - -galaxiespicture : [U] galaxies[STANDALONE_PICTURE_GENERATOR] GALAXIES_EXTRA STANDALONE - + m.lib -galaxiespicture : [C] galaxies[STANDALONE_PICTURE_GENERATOR] GALAXIES_EXTRA STANDALONE - -ALL += galaxies[COMBINED] GALAXIES_EXTRA - -!begin am gtk -GAMES += galaxies -!end - -!begin >list.c - A(galaxies) \ -!end - -!begin >gamedesc.txt -galaxies:galaxies.exe:Galaxies:Symmetric polyomino puzzle:Divide the grid into rotationally symmetric regions each centred on a dot. -!end diff --git a/apps/plugins/puzzles/src/galaxies.c b/apps/plugins/puzzles/src/galaxies.c index 9172b90e12..8859917558 100644 --- a/apps/plugins/puzzles/src/galaxies.c +++ b/apps/plugins/puzzles/src/galaxies.c @@ -13,9 +13,46 @@ * Edges have on/off state; obviously the actual edges of the * board are fixed to on, and everything else starts as off. * - * TTD: - * Cleverer solver - * Think about how to display remote groups of tiles? + * Future solver directions: + * + * - Non-local version of the exclave extension? Suppose you have an + * exclave with multiple potential paths back home, but all of them + * go through the same tile somewhere in the middle of the path. + * Then _that_ critical square can be assigned to the home dot, + * even if we don't yet know the details of the path from it to + * either existing region. + * + * - Permit non-simply-connected puzzle instances in sub-Unreasonable + * mode? Even the simplest case 5x3:ubb is graded Unreasonable at + * present, because we have no solution technique short of + * recursion that can handle it. + * + * The reasoning a human uses for that puzzle is to observe that + * the centre left square has to connect to the centre dot, so it + * must have _some_ path back there. It could go round either side + * of the dot in the way. But _whichever_ way it goes, that rules + * out the left dot extending to the squares above and below it, + * because if it did that, that would block _both_ routes back to + * the centre. + * + * But the exclave-extending deduction we have at present is only + * capable of extending an exclave with _one_ liberty. This has + * two, so the only technique we have available is to try them one + * by one via recursion. + * + * My vague plan to fix this would be to re-run the exclave + * extension on a per-dot basis (probably after working out a + * non-local version as described above): instead of trying to find + * all exclaves at once, try it for one exclave at a time, or + * perhaps all exclaves relating to a particular home dot H. The + * point of this is that then you could spot pairs of squares with + * _two_ possible dots, one of which is H, and which are opposite + * to each other with respect to their other dot D (such as the + * squares above/below the left dot in this example). And then you + * merge those into one vertex of the connectivity graph, on the + * grounds that they're either both H or both D - and _then_ you + * have an exclave with only one path back home, and can make + * progress. * * Bugs: * @@ -42,15 +79,22 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #ifdef DEBUGGING #define solvep debug -#else +#elif defined STANDALONE_SOLVER static bool solver_show_working; #define solvep(x) do { if (solver_show_working) { printf x; } } while(0) +#else +#define solvep(x) ((void)0) #endif #ifdef STANDALONE_PICTURE_GENERATOR @@ -148,13 +192,15 @@ struct game_state { or -1 if stale. */ }; -static bool check_complete(const game_state *state, int *dsf, int *colours); +static bool check_complete(const game_state *state, DSF *dsf, int *colours); +static int solver_state_inner(game_state *state, int maxdiff, int depth); static int solver_state(game_state *state, int maxdiff); static int solver_obvious(game_state *state); static int solver_obvious_dot(game_state *state, space *dot); static space *space_opposite_dot(const game_state *state, const space *sp, const space *dot); static space *tile_opposite(const game_state *state, const space *sp); +static game_state *execute_move(const game_state *state, const char *move); /* ---------------------------------------------------------- * Game parameters and presets @@ -168,7 +214,9 @@ static const game_params galaxies_presets[] = { { 7, 7, DIFF_NORMAL }, { 7, 7, DIFF_UNREASONABLE }, { 10, 10, DIFF_NORMAL }, + { 10, 10, DIFF_UNREASONABLE }, { 15, 15, DIFF_NORMAL }, + { 15, 15, DIFF_UNREASONABLE }, }; static bool game_fetch_preset(int i, char **name, game_params **params) @@ -281,6 +329,10 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 3 || params->h < 3) return "Width and height must both be at least 3"; + if (params->w > INT_MAX / 2 || params->h > INT_MAX / 2 || + params->w > (INT_MAX - params->w*2 - params->h*2 - 1) / 4 / params->h) + return "Width times height must not be unreasonably large"; + /* * This shouldn't be able to happen at all, since decode_params * and custom_params will never generate anything that isn't @@ -352,6 +404,8 @@ static bool ok_to_add_assoc_with_opposite_internal( int *colors; bool toret; + if (tile->type != s_tile) + return false; if (tile->flags & F_DOT) return false; if (opposite == NULL) @@ -372,20 +426,21 @@ static bool ok_to_add_assoc_with_opposite_internal( return toret; } +#ifndef EDITOR static bool ok_to_add_assoc_with_opposite( const game_state *state, space *tile, space *dot) { space *opposite = space_opposite_dot(state, tile, dot); return ok_to_add_assoc_with_opposite_internal(state, tile, opposite); } +#endif static void add_assoc_with_opposite(game_state *state, space *tile, space *dot) { space *opposite = space_opposite_dot(state, tile, dot); - if(opposite) + if(opposite && ok_to_add_assoc_with_opposite_internal( + state, tile, opposite)) { - assert(ok_to_add_assoc_with_opposite_internal(state, tile, opposite)); - remove_assoc_with_opposite(state, tile); add_assoc(state, tile, dot); remove_assoc_with_opposite(state, opposite); @@ -393,12 +448,14 @@ static void add_assoc_with_opposite(game_state *state, space *tile, space *dot) } } +#ifndef EDITOR static space *sp2dot(const game_state *state, int x, int y) { space *sp = &SPACE(state, x, y); if (!(sp->flags & F_TILE_ASSOC)) return NULL; return &SPACE(state, sp->dotx, sp->doty); } +#endif #define IS_VERTICAL_EDGE(x) ((x % 2) == 0) @@ -407,8 +464,24 @@ static bool game_can_format_as_text_now(const game_params *params) return true; } +static char *encode_game(const game_state *state); + static char *game_text_format(const game_state *state) { +#ifdef EDITOR + game_params par; + char *params, *desc, *ret; + par.w = state->w; + par.h = state->h; + par.diff = DIFF_MAX; /* shouldn't be used */ + params = encode_params(&par, false); + desc = encode_game(state); + ret = snewn(strlen(params) + strlen(desc) + 2, char); + sprintf(ret, "%s:%s", params, desc); + sfree(params); + sfree(desc); + return ret; +#else int maxlen = (state->sx+1)*state->sy, x, y; char *ret, *p; space *sp; @@ -462,6 +535,7 @@ static char *game_text_format(const game_state *state) *p = '\0'; return ret; +#endif } static void dbg_state(const game_state *state) @@ -684,7 +758,7 @@ static void tiles_from_edge(game_state *state, space *sp, space **ts) /* Returns a move string for use by 'solve', including the initial * 'S' if issolve is true. */ static char *diff_game(const game_state *src, const game_state *dest, - bool issolve) + bool issolve, int set_cdiff) { int movelen = 0, movesize = 256, x, y, len; char *move = snewn(movesize, char), buf[80]; @@ -698,6 +772,26 @@ static char *diff_game(const game_state *src, const game_state *dest, move[movelen++] = 'S'; sep = ";"; } +#ifdef EDITOR + if (set_cdiff >= 0) { + switch (set_cdiff) { + case DIFF_IMPOSSIBLE: + movelen += sprintf(move+movelen, "%sII", sep); + break; + case DIFF_AMBIGUOUS: + movelen += sprintf(move+movelen, "%sIA", sep); + break; + case DIFF_UNFINISHED: + movelen += sprintf(move+movelen, "%sIU", sep); + break; + default: + movelen += sprintf(move+movelen, "%si%c", + sep, galaxies_diffchars[set_cdiff]); + break; + } + sep = ";"; + } +#endif move[movelen] = '\0'; for (x = 0; x < src->sx; x++) { for (y = 0; y < src->sy; y++) { @@ -747,7 +841,8 @@ static char *diff_game(const game_state *src, const game_state *dest, /* Returns true if a dot here would not be too close to any other dots * (and would avoid other game furniture). */ -static bool dot_is_possible(game_state *state, space *sp, bool allow_assoc) +static bool dot_is_possible(const game_state *state, space *sp, + bool allow_assoc) { int bx = 0, by = 0, dx, dy; space *adj; @@ -921,7 +1016,7 @@ static void free_game(game_state *state) * an edit mode. */ -static char *encode_game(game_state *state) +static char *encode_game(const game_state *state) { char *desc, *p; int run, x, y, area; @@ -1229,10 +1324,7 @@ static bool generate_try_block(game_state *state, random_state *rs, } #ifdef STANDALONE_SOLVER -int maxtries; -#define MAXTRIES maxtries -#else -#define MAXTRIES 50 +static bool one_try; /* override for soak testing */ #endif #define GP_DOTS 1 @@ -1242,6 +1334,8 @@ static void generate_pass(game_state *state, random_state *rs, int *scratch, { int sz = state->sx*state->sy, nspc, i, ret; + /* Random list of squares to try and process, one-by-one. */ + for (i = 0; i < sz; i++) scratch[i] = i; shuffle(scratch, sz, sizeof(int), rs); /* This bug took me a, er, little while to track down. On PalmOS, @@ -1297,30 +1391,94 @@ static void generate_pass(game_state *state, random_state *rs, int *scratch, dbg_state(state); } +/* + * We try several times to generate a grid at all, before even feeding + * it to the solver. Then we pick whichever of the resulting grids was + * the most 'wiggly', as measured by the number of inward corners in + * the shape of any region. + * + * Rationale: wiggly shapes are what make this puzzle fun, and it's + * disappointing to be served a game whose entire solution is a + * collection of rectangles. But we also don't want to introduce a + * _hard requirement_ of wiggliness, because a player who knew that + * was there would be able to use it as an extra clue. This way, we + * just probabilistically skew in favour of wiggliness. + */ +#define GENERATE_TRIES 10 + +static bool is_wiggle(const game_state *state, int x, int y, int dx, int dy) +{ + int x1 = x+2*dx, y1 = y+2*dy; + int x2 = x-2*dy, y2 = y+2*dx; + space *t, *t1, *t2; + + if (!INGRID(state, x1, y1) || !INGRID(state, x2, y2)) + return false; + + t = &SPACE(state, x, y); + t1 = &SPACE(state, x1, y1); + t2 = &SPACE(state, x2, y2); + return ((t1->dotx == t2->dotx && t1->doty == t2->doty) && + !(t1->dotx == t->dotx && t1->doty == t->doty)); +} + +static int measure_wiggliness(const game_state *state, int *scratch) +{ + int sz = state->sx*state->sy; + int x, y, nwiggles = 0; + memset(scratch, 0, sz); + + for (y = 1; y < state->sy; y += 2) { + for (x = 1; x < state->sx; x += 2) { + if (y+2 < state->sy) { + nwiggles += is_wiggle(state, x, y, 0, +1); + nwiggles += is_wiggle(state, x, y, 0, -1); + nwiggles += is_wiggle(state, x, y, +1, 0); + nwiggles += is_wiggle(state, x, y, -1, 0); + } + } + } + + return nwiggles; +} + static char *new_game_desc(const game_params *params, random_state *rs, char **aux, bool interactive) { game_state *state = blank_game(params->w, params->h), *copy; char *desc; int *scratch, sz = state->sx*state->sy, i; - int diff, ntries = 0; + int diff, best_wiggliness; bool cc; - /* Random list of squares to try and process, one-by-one. */ scratch = snewn(sz, int); - for (i = 0; i < sz; i++) scratch[i] = i; generate: - clear_game(state, true); - ntries++; - - /* generate_pass(state, rs, scratch, 10, GP_DOTS); */ - /* generate_pass(state, rs, scratch, 100, 0); */ - generate_pass(state, rs, scratch, 100, GP_DOTS); - - game_update_dots(state); - - if (state->ndots == 1) goto generate; + best_wiggliness = -1; + copy = NULL; + for (i = 0; i < GENERATE_TRIES; i++) { + int this_wiggliness; + + do { + clear_game(state, true); + generate_pass(state, rs, scratch, 100, GP_DOTS); + game_update_dots(state); + } while (state->ndots == 1); + + this_wiggliness = measure_wiggliness(state, scratch); + debug(("Grid gen #%d: wiggliness=%d", i, this_wiggliness)); + if (this_wiggliness > best_wiggliness) { + best_wiggliness = this_wiggliness; + if (copy) + free_game(copy); + copy = dup_game(state); + debug((" new best")); + } + debug(("\n")); + } + assert(copy); + free_game(state); + state = copy; #ifdef DEBUGGING { @@ -1345,12 +1503,17 @@ generate: assert(diff != DIFF_IMPOSSIBLE); if (diff != params->diff) { /* - * We'll grudgingly accept a too-easy puzzle, but we must - * _not_ permit a too-hard one (one which the solver - * couldn't handle at all). + * If the puzzle was insoluble at this difficulty level (i.e. + * too hard), _or_ soluble at a lower level (too easy), go + * round again. + * + * An exception is in soak-testing mode, where we return the + * first puzzle we got regardless. */ - if (diff > params->diff || - ntries < MAXTRIES) goto generate; +#ifdef STANDALONE_SOLVER + if (!one_try) +#endif + goto generate; } #ifdef STANDALONE_PICTURE_GENERATOR @@ -1527,6 +1690,10 @@ generate: dbg_state(state); #endif + game_state *blank = blank_game(params->w, params->h); + *aux = diff_game(blank, state, true, -1); + free_game(blank); + free_game(state); sfree(scratch); @@ -1623,13 +1790,17 @@ static game_state *new_game(midend *me, const game_params *params, * Solver and all its little wizards. */ +#if defined DEBUGGING || defined STANDALONE_SOLVER static int solver_recurse_depth; +#define STATIC_RECURSION_DEPTH +#endif typedef struct solver_ctx { game_state *state; int sz; /* state->sx * state->sy */ space **scratch; /* size sz */ - + DSF *dsf; /* size sz */ + int *iscratch; /* size sz */ } solver_ctx; static solver_ctx *new_solver(game_state *state) @@ -1638,12 +1809,16 @@ static solver_ctx *new_solver(game_state *state) sctx->state = state; sctx->sz = state->sx*state->sy; sctx->scratch = snewn(sctx->sz, space *); + sctx->dsf = dsf_new(sctx->sz); + sctx->iscratch = snewn(sctx->sz, int); return sctx; } static void free_solver(solver_ctx *sctx) { sfree(sctx->scratch); + dsf_free(sctx->dsf); + sfree(sctx->iscratch); sfree(sctx); } @@ -1804,7 +1979,7 @@ static int solver_lines_opposite_cb(game_state *state, space *edge, void *ctx) if (!(edge_opp->flags & F_EDGE_SET)) { solvep(("%*sSetting edge %d,%d as opposite %d,%d\n", solver_recurse_depth*4, "", - tile_opp->x-dx, tile_opp->y-dy, edge->x, edge->y)); + tile_opp->x+dx, tile_opp->y+dy, edge->x, edge->y)); edge_opp->flags |= F_EDGE_SET; didsth = 1; } @@ -2097,6 +2272,177 @@ static int solver_expand_dots(game_state *state, solver_ctx *sctx) return foreach_tile(state, solver_expand_postcb, IMPOSSIBLE_QUITS, sctx); } +static int solver_extend_exclaves(game_state *state, solver_ctx *sctx) +{ + int x, y, done_something = 0; + + /* + * Make a dsf by unifying any two adjacent tiles associated with + * the same dot. This will identify separate connected components + * of the tiles belonging to a given dot. Any such component that + * doesn't contain its own dot is an 'exclave', and will need some + * kind of path of tiles to connect it back to the dot. + */ + dsf_reinit(sctx->dsf); + for (x = 1; x < state->sx; x += 2) { + for (y = 1; y < state->sy; y += 2) { + int dotx, doty; + space *tile, *othertile; + + tile = &SPACE(state, x, y); + if (!(tile->flags & F_TILE_ASSOC)) + continue; /* not associated with any dot */ + dotx = tile->dotx; + doty = tile->doty; + + if (INGRID(state, x+2, y)) { + othertile = &SPACE(state, x+2, y); + if ((othertile->flags & F_TILE_ASSOC) && + othertile->dotx == dotx && othertile->doty == doty) + dsf_merge(sctx->dsf, y*state->sx+x, y*state->sx+(x+2)); + } + + if (INGRID(state, x, y+2)) { + othertile = &SPACE(state, x, y+2); + if ((othertile->flags & F_TILE_ASSOC) && + othertile->dotx == dotx && othertile->doty == doty) + dsf_merge(sctx->dsf, y*state->sx+x, (y+2)*state->sx+x); + } + } + } + + /* + * Go through the grid again, and count the 'liberties' of each + * connected component, in the Go sense, i.e. the number of + * currently unassociated squares adjacent to the component. The + * idea is that if an exclave has just one liberty, then that + * square _must_ extend the exclave, or else it will be completely + * cut off from connecting back to its home dot. + * + * We need to count each adjacent square just once, even if it + * borders the component on multiple edges. So we'll go through + * each unassociated square, check all four of its neighbours, and + * de-duplicate them. + * + * We'll store the count of liberties in the entry of iscratch + * corresponding to the square centre (i.e. with odd coordinates). + * Every time we find a liberty, we store its index in the square + * to the left of that, so that when a component has exactly one + * liberty we can remember what it was. + * + * Square centres that are not the canonical dsf element of a + * connected component will get their liberty count set to -1, + * which will allow us to identify them in the later loop (after + * we start making changes and need to spot that an associated + * square _now_ was not associated when the dsf was built). + */ + + /* Initialise iscratch */ + for (x = 1; x < state->sx; x += 2) { + for (y = 1; y < state->sy; y += 2) { + int index = y * state->sx + x; + if (!(SPACE(state, x, y).flags & F_TILE_ASSOC) || + dsf_canonify(sctx->dsf, index) != index) { + sctx->iscratch[index] = -1; /* mark as not a component */ + } else { + sctx->iscratch[index] = 0; /* zero liberty count */ + sctx->iscratch[index-1] = 0; /* initialise neighbour id */ + } + } + } + + /* Find each unassociated square and see what it's a liberty of */ + for (x = 1; x < state->sx; x += 2) { + for (y = 1; y < state->sy; y += 2) { + int dx, dy, ni[4], nn, i; + + if ((SPACE(state, x, y).flags & F_TILE_ASSOC)) + continue; /* not an unassociated square */ + + /* Find distinct indices of adjacent components */ + nn = 0; + for (dx = -1; dx <= 1; dx++) { + for (dy = -1; dy <= 1; dy++) { + if (dx != 0 && dy != 0) continue; + if (dx == 0 && dy == 0) continue; + + if (INGRID(state, x+2*dx, y+2*dy) && + (SPACE(state, x+2*dx, y+2*dy).flags & F_TILE_ASSOC)) { + /* Find id of the component adjacent to x,y */ + int nindex = (y+2*dy) * state->sx + (x+2*dx); + nindex = dsf_canonify(sctx->dsf, nindex); + + /* See if we've seen it before in another direction */ + for (i = 0; i < nn; i++) + if (ni[i] == nindex) + break; + if (i == nn) { + /* No, it's new. Mark x,y as a liberty of it */ + sctx->iscratch[nindex]++; + assert(nindex > 0); + sctx->iscratch[nindex-1] = y * state->sx + x; + + /* And record this component as having been seen */ + ni[nn++] = nindex; + } + } + } + } + } + } + + /* + * Now we have all the data we need to find exclaves with exactly + * one liberty. In each case, associate the unique liberty square + * with the same dot. + */ + for (x = 1; x < state->sx; x += 2) { + for (y = 1; y < state->sy; y += 2) { + int index, dotx, doty, ex, ey, added; + space *tile; + + index = y*state->sx+x; + if (sctx->iscratch[index] == -1) + continue; /* wasn't canonical when dsf was built */ + + tile = &SPACE(state, x, y); + if (!(tile->flags & F_TILE_ASSOC)) + continue; /* not associated with any dot */ + dotx = tile->dotx; + doty = tile->doty; + + if (index == dsf_canonify( + sctx->dsf, (doty | 1) * state->sx + (dotx | 1))) + continue; /* not an exclave - contains its own dot */ + + if (sctx->iscratch[index] == 0) { + solvep(("%*sExclave at %d,%d has no liberties!\n", + solver_recurse_depth*4, "", x, y)); + return -1; + } + + if (sctx->iscratch[index] != 1) + continue; /* more than one liberty, can't be sure which */ + + assert(sctx->iscratch[index-1] != 0); + ex = sctx->iscratch[index-1] % state->sx; + ey = sctx->iscratch[index-1] / state->sx; + tile = &SPACE(state, ex, ey); + if (tile->flags & F_TILE_ASSOC) + continue; /* already done by earlier iteration of this loop */ + + added = solver_add_assoc(state, tile, dotx, doty, + "to connect exclave"); + if (added < 0) + return -1; + if (added > 0) + done_something = 1; + } + } + + return done_something; +} + struct recurse_ctx { space *best; int bestn; @@ -2124,14 +2470,14 @@ static int solver_recurse_cb(game_state *state, space *tile, void *ctx) #define MAXRECURSE 5 -static int solver_recurse(game_state *state, int maxdiff) +static int solver_recurse(game_state *state, int maxdiff, int depth) { int diff = DIFF_IMPOSSIBLE, ret, n, gsz = state->sx * state->sy; space *ingrid, *outgrid = NULL, *bestopp; struct recurse_ctx rctx; - if (solver_recurse_depth >= MAXRECURSE) { - solvep(("Limiting recursion to %d, returning.", MAXRECURSE)); + if (depth >= MAXRECURSE) { + solvep(("Limiting recursion to %d, returning.\n", MAXRECURSE)); return DIFF_UNFINISHED; } @@ -2149,10 +2495,6 @@ static int solver_recurse(game_state *state, int maxdiff) solver_recurse_depth*4, "", rctx.best->x, rctx.best->y, rctx.bestn)); -#ifdef STANDALONE_SOLVER - solver_recurse_depth++; -#endif - ingrid = snewn(gsz, space); memcpy(ingrid, state->grid, gsz * sizeof(space)); @@ -2166,7 +2508,11 @@ static int solver_recurse(game_state *state, int maxdiff) state->dots[n]->x, state->dots[n]->y, "Attempting for recursion"); - ret = solver_state(state, maxdiff); + ret = solver_state_inner(state, maxdiff, depth + 1); + +#ifdef STATIC_RECURSION_DEPTH + solver_recurse_depth = depth; /* restore after recursion returns */ +#endif if (diff == DIFF_IMPOSSIBLE && ret != DIFF_IMPOSSIBLE) { /* we found our first solved grid; copy it away. */ @@ -2198,10 +2544,6 @@ static int solver_recurse(game_state *state, int maxdiff) break; } -#ifdef STANDALONE_SOLVER - solver_recurse_depth--; -#endif - if (outgrid) { /* we found (at least one) soln; copy it back to state */ memcpy(state->grid, outgrid, gsz * sizeof(space)); @@ -2211,7 +2553,7 @@ static int solver_recurse(game_state *state, int maxdiff) return diff; } -static int solver_state(game_state *state, int maxdiff) +static int solver_state_inner(game_state *state, int maxdiff, int depth) { solver_ctx *sctx = new_solver(state); int ret, diff = DIFF_NORMAL; @@ -2223,6 +2565,10 @@ static int solver_state(game_state *state, int maxdiff) picture = NULL; #endif +#ifdef STATIC_RECURSION_DEPTH + solver_recurse_depth = depth; +#endif + ret = solver_obvious(state); if (ret < 0) { diff = DIFF_IMPOSSIBLE; @@ -2247,6 +2593,9 @@ cont: ret = solver_expand_dots(state, sctx); CHECKRET(DIFF_NORMAL); + ret = solver_extend_exclaves(state, sctx); + CHECKRET(DIFF_NORMAL); + if (maxdiff <= DIFF_NORMAL) break; @@ -2259,7 +2608,7 @@ cont: if (check_complete(state, NULL, NULL)) goto got_result; diff = (maxdiff >= DIFF_UNREASONABLE) ? - solver_recurse(state, maxdiff) : DIFF_UNFINISHED; + solver_recurse(state, maxdiff, depth) : DIFF_UNFINISHED; got_result: free_solver(sctx); @@ -2275,6 +2624,11 @@ got_result: return diff; } +static int solver_state(game_state *state, int maxdiff) +{ + return solver_state_inner(state, maxdiff, 0); +} + #ifndef EDITOR static char *solve_game(const game_state *state, const game_state *currstate, const char *aux, const char **error) @@ -2284,21 +2638,26 @@ static char *solve_game(const game_state *state, const game_state *currstate, int i; int diff; - tosolve = dup_game(currstate); - diff = solver_state(tosolve, DIFF_UNREASONABLE); - if (diff != DIFF_UNFINISHED && diff != DIFF_IMPOSSIBLE) { - debug(("solve_game solved with current state.\n")); + if (aux) { + tosolve = execute_move(state, aux); goto solved; - } - free_game(tosolve); + } else { + tosolve = dup_game(currstate); + diff = solver_state(tosolve, DIFF_UNREASONABLE); + if (diff != DIFF_UNFINISHED && diff != DIFF_IMPOSSIBLE) { + debug(("solve_game solved with current state.\n")); + goto solved; + } + free_game(tosolve); - tosolve = dup_game(state); - diff = solver_state(tosolve, DIFF_UNREASONABLE); - if (diff != DIFF_UNFINISHED && diff != DIFF_IMPOSSIBLE) { - debug(("solve_game solved with original state.\n")); - goto solved; + tosolve = dup_game(state); + diff = solver_state(tosolve, DIFF_UNREASONABLE); + if (diff != DIFF_UNFINISHED && diff != DIFF_IMPOSSIBLE) { + debug(("solve_game solved with original state.\n")); + goto solved; + } + free_game(tosolve); } - free_game(tosolve); return NULL; @@ -2309,7 +2668,7 @@ solved: */ for (i = 0; i < tosolve->sx*tosolve->sy; i++) tosolve->grid[i].flags &= ~F_TILE_ASSOC; - ret = diff_game(currstate, tosolve, true); + ret = diff_game(currstate, tosolve, true, -1); free_game(tosolve); return ret; } @@ -2333,7 +2692,7 @@ static game_ui *new_ui(const game_state *state) game_ui *ui = snew(game_ui); ui->dragging = false; ui->cur_x = ui->cur_y = 1; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -2342,15 +2701,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -2383,7 +2733,7 @@ struct game_drawstate { blitter *blmirror; bool dragging; - int dragx, dragy; + int dragx, dragy, oppx, oppy; int *colour_scratch; @@ -2445,34 +2795,74 @@ static char *interpret_move(const game_state *state, game_ui *ui, int px, py; space *sp; - px = 2*FROMCOORD((float)x) + 0.5; - py = 2*FROMCOORD((float)y) + 0.5; - - state->cdiff = -1; + px = 2*FROMCOORD((float)x) + 0.5F; + py = 2*FROMCOORD((float)y) + 0.5F; if (button == 'C' || button == 'c') return dupstr("C"); if (button == 'S' || button == 's') { char *ret; game_state *tmp = dup_game(state); - state->cdiff = solver_state(tmp, DIFF_UNREASONABLE-1); - ret = diff_game(state, tmp, 0); + int cdiff = solver_state(tmp, DIFF_UNREASONABLE-1); + ret = diff_game(state, tmp, 0, cdiff); free_game(tmp); return ret; } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { - if (!INUI(state, px, py)) return NULL; + if (!INUI(state, px, py)) return MOVE_UNUSED; sp = &SPACE(state, px, py); - if (!dot_is_possible(state, sp, 1)) return NULL; + if (!dot_is_possible(state, sp, 1)) return MOVE_NO_EFFECT; sprintf(buf, "%c%d,%d", (char)((button == LEFT_BUTTON) ? 'D' : 'd'), px, py); return dupstr(buf); } - return NULL; + return MOVE_UNUSED; } #else +static bool edge_placement_legal(const game_state *state, int x, int y) +{ + space *sp = &SPACE(state, x, y); + if (sp->type != s_edge) + return false; /* this is a face-centre or a grid vertex */ + + /* Check this line doesn't actually intersect a dot */ + unsigned int flags = (GRID(state, grid, x, y).flags | + GRID(state, grid, x & ~1U, y & ~1U).flags | + GRID(state, grid, (x+1) & ~1U, (y+1) & ~1U).flags); + if (flags & F_DOT) + return false; + return true; +} + +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + space *sp; + + if (IS_CURSOR_SELECT(button) && ui->cur_visible) { + sp = &SPACE(state, ui->cur_x, ui->cur_y); + if (ui->dragging) { + if (ui->cur_x == ui->srcx && ui->cur_y == ui->srcy) + return "Cancel"; + if (ok_to_add_assoc_with_opposite( + state, &SPACE(state, ui->cur_x, ui->cur_y), + &SPACE(state, ui->dotx, ui->doty))) + return "Place"; + return (ui->srcx == ui->dotx && ui->srcy == ui->doty) ? + "Cancel" : "Remove"; + } else if (sp->flags & F_DOT) + return "New arrow"; + else if (sp->flags & F_TILE_ASSOC) + return "Move arrow"; + else if (sp->type == s_edge && + edge_placement_legal(state, ui->cur_x, ui->cur_y)) + return (sp->flags & F_EDGE_SET) ? "Clear" : "Edge"; + } + return ""; +} + static char *interpret_move(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) @@ -2499,7 +2889,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char *ret; game_state *tmp = dup_game(state); solver_obvious(tmp); - ret = diff_game(state, tmp, false); + ret = diff_game(state, tmp, false, -1); free_game(tmp); return ret; } @@ -2509,21 +2899,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, coord_round_to_edge(FROMCOORD((float)x), FROMCOORD((float)y), &px, &py); - if (!INUI(state, px, py)) return NULL; + if (!INUI(state, px, py)) return MOVE_UNUSED; + if (!edge_placement_legal(state, px, py)) + return MOVE_NO_EFFECT; - sp = &SPACE(state, px, py); - assert(sp->type == s_edge); - { - sprintf(buf, "E%d,%d", px, py); - return dupstr(buf); - } + sprintf(buf, "E%d,%d", px, py); + return dupstr(buf); } else if (button == RIGHT_BUTTON) { int px1, py1; ui->cur_visible = false; - px = (int)(2*FROMCOORD((float)x) + 0.5); - py = (int)(2*FROMCOORD((float)y) + 0.5); + px = (int)(2*FROMCOORD((float)x) + 0.5F); + py = (int)(2*FROMCOORD((float)y) + 0.5F); dot = NULL; @@ -2575,28 +2963,29 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->dy = y; ui->dotx = dot->x; ui->doty = dot->y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } + return MOVE_NO_EFFECT; } else if (button == RIGHT_DRAG && ui->dragging) { /* just move the drag coords. */ ui->dx = x; ui->dy = y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (button == RIGHT_RELEASE && ui->dragging) { - ui->dragging = false; - /* * Drags are always targeted at a single square. */ px = 2*FROMCOORD(x+TILE_SIZE) - 1; py = 2*FROMCOORD(y+TILE_SIZE) - 1; + dropped: /* We arrive here from the end of a keyboard drag. */ + ui->dragging = false; /* * Dragging an arrow on to the same square it started from * is a null move; just update the ui and finish. */ if (px == ui->srcx && py == ui->srcy) - return UI_UPDATE; + return MOVE_UI_UPDATE; /* * Otherwise, we remove the arrow from its starting @@ -2630,43 +3019,33 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (buf[0]) return dupstr(buf); else - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->sx-1, state->sy-1, false); - if (ui->cur_x < 1) ui->cur_x = 1; - if (ui->cur_y < 1) ui->cur_y = 1; - ui->cur_visible = true; + int cx = ui->cur_x - 1, cy = ui->cur_y - 1; + char *ret = move_cursor(button, &cx, &cy, state->sx-2, state->sy-2, + false, &ui->cur_visible); + ui->cur_x = cx + 1, ui->cur_y = cy + 1; if (ui->dragging) { ui->dx = SCOORD(ui->cur_x); ui->dy = SCOORD(ui->cur_y); } - return UI_UPDATE; + return ret; } else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } sp = &SPACE(state, ui->cur_x, ui->cur_y); if (ui->dragging) { - ui->dragging = false; - - if ((ui->srcx != ui->dotx || ui->srcy != ui->doty) && - SPACE(state, ui->srcx, ui->srcy).flags & F_TILE_ASSOC) { - sprintf(buf, "%sU%d,%d", sep, ui->srcx, ui->srcy); - sep = ";"; - } - if (sp->type == s_tile && !(sp->flags & F_DOT) && !(sp->flags & F_TILE_ASSOC)) { - sprintf(buf + strlen(buf), "%sA%d,%d,%d,%d", - sep, ui->cur_x, ui->cur_y, ui->dotx, ui->doty); - } - return dupstr(buf); + px = ui->cur_x; py = ui->cur_y; + goto dropped; } else if (sp->flags & F_DOT) { ui->dragging = true; ui->dx = SCOORD(ui->cur_x); ui->dy = SCOORD(ui->cur_y); ui->dotx = ui->srcx = ui->cur_x; ui->doty = ui->srcy = ui->cur_y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (sp->flags & F_TILE_ASSOC) { assert(sp->type == s_tile); ui->dragging = true; @@ -2676,18 +3055,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->doty = sp->doty; ui->srcx = ui->cur_x; ui->srcy = ui->cur_y; - return UI_UPDATE; - } else if (sp->type == s_edge) { + return MOVE_UI_UPDATE; + } else if (sp->type == s_edge && + edge_placement_legal(state, ui->cur_x, ui->cur_y)) { sprintf(buf, "E%d,%d", ui->cur_x, ui->cur_y); return dupstr(buf); } } - return NULL; + return MOVE_UNUSED; } #endif -static bool check_complete(const game_state *state, int *dsf, int *colours) +static bool check_complete(const game_state *state, DSF *dsf, int *colours) { int w = state->w, h = state->h; int x, y, i; @@ -2702,10 +3082,10 @@ static bool check_complete(const game_state *state, int *dsf, int *colours) } *sqdata; if (!dsf) { - dsf = snew_dsf(w*h); + dsf = dsf_new(w*h); free_dsf = true; } else { - dsf_init(dsf, w*h); + dsf_reinit(dsf); free_dsf = false; } @@ -2861,7 +3241,7 @@ static bool check_complete(const game_state *state, int *dsf, int *colours) sfree(sqdata); if (free_dsf) - sfree(dsf); + dsf_free(dsf); return ret; } @@ -2959,6 +3339,35 @@ static game_state *execute_move(const game_state *state, const char *move) } else if (c == 'C') { move++; clear_game(ret, true); + } else if (c == 'i') { + int diff; + move++; + for (diff = 0; diff <= DIFF_UNREASONABLE; diff++) + if (*move == galaxies_diffchars[diff]) + break; + if (diff > DIFF_UNREASONABLE) + goto badmove; + + ret->cdiff = diff; + move++; + } else if (c == 'I') { + int diff; + move++; + switch (*move) { + case 'A': + diff = DIFF_AMBIGUOUS; + break; + case 'I': + diff = DIFF_IMPOSSIBLE; + break; + case 'U': + diff = DIFF_UNFINISHED; + break; + default: + goto badmove; + } + ret->cdiff = diff; + move++; #endif } else if (c == 'S') { move++; @@ -2997,7 +3406,7 @@ badmove: */ static void game_compute_size(const game_params *params, int sz, - int *x, int *y) + const game_ui *ui, int *x, int *y) { struct { int tilesize, w, h; } ads, *ds = &ads; @@ -3098,7 +3507,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) ds->bl = NULL; ds->blmirror = NULL; ds->dragging = false; - ds->dragx = ds->dragy = 0; + ds->dragx = ds->dragy = ds->oppx = ds->oppy = 0; ds->colour_scratch = snewn(ds->w * ds->h, int); @@ -3145,7 +3554,10 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) static void draw_arrow(drawing *dr, game_drawstate *ds, int cx, int cy, int ddx, int ddy, int col) { - float vlen = (float)sqrt(ddx*ddx+ddy*ddy); + int sqdist = ddx*ddx+ddy*ddy; + if (sqdist == 0) + return; /* avoid division by zero */ + float vlen = (float)sqrt(sqdist); float xdx = ddx/vlen, xdy = ddy/vlen; float ydx = -xdy, ydy = xdx; int e1x = cx + (int)(xdx*TILE_SIZE/3), e1y = cy + (int)(xdy*TILE_SIZE/3); @@ -3257,7 +3669,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int w = ds->w, h = ds->h; int x, y; bool flashing = false; - int oppx, oppy; if (flashtime > 0) { int frame = (int)(flashtime / FLASH_TIME); @@ -3267,14 +3678,10 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (ds->dragging) { assert(ds->bl); assert(ds->blmirror); - calculate_opposite_point(ui, ds, ds->dragx + TILE_SIZE/2, - ds->dragy + TILE_SIZE/2, &oppx, &oppy); - oppx -= TILE_SIZE/2; - oppy -= TILE_SIZE/2; + blitter_load(dr, ds->blmirror, ds->oppx, ds->oppy); + draw_update(dr, ds->oppx, ds->oppy, TILE_SIZE, TILE_SIZE); blitter_load(dr, ds->bl, ds->dragx, ds->dragy); draw_update(dr, ds->dragx, ds->dragy, TILE_SIZE, TILE_SIZE); - blitter_load(dr, ds->blmirror, oppx, oppy); - draw_update(dr, oppx, oppy, TILE_SIZE, TILE_SIZE); ds->dragging = false; } if (ds->cur_visible) { @@ -3285,7 +3692,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } if (!ds->started) { - draw_rect(dr, 0, 0, DRAW_WIDTH, DRAW_HEIGHT, COL_BACKGROUND); draw_rect(dr, BORDER - EDGE_THICKNESS + 1, BORDER - EDGE_THICKNESS + 1, w*TILE_SIZE + EDGE_THICKNESS*2 - 1, h*TILE_SIZE + EDGE_THICKNESS*2 - 1, COL_EDGE); @@ -3433,16 +3839,28 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } if (ui->dragging) { + int oppx, oppy; + ds->dragging = true; ds->dragx = ui->dx - TILE_SIZE/2; ds->dragy = ui->dy - TILE_SIZE/2; calculate_opposite_point(ui, ds, ui->dx, ui->dy, &oppx, &oppy); + ds->oppx = oppx - TILE_SIZE/2; + ds->oppy = oppy - TILE_SIZE/2; + blitter_save(dr, ds->bl, ds->dragx, ds->dragy); - blitter_save(dr, ds->blmirror, oppx - TILE_SIZE/2, oppy - TILE_SIZE/2); + clip(dr, ds->dragx, ds->dragy, TILE_SIZE, TILE_SIZE); draw_arrow(dr, ds, ui->dx, ui->dy, SCOORD(ui->dotx) - ui->dx, SCOORD(ui->doty) - ui->dy, COL_ARROW); + unclip(dr); + draw_update(dr, ds->dragx, ds->dragy, TILE_SIZE, TILE_SIZE); + + blitter_save(dr, ds->blmirror, ds->oppx, ds->oppy); + clip(dr, ds->oppx, ds->oppy, TILE_SIZE, TILE_SIZE); draw_arrow(dr, ds, oppx, oppy, SCOORD(ui->dotx) - oppx, SCOORD(ui->doty) - oppy, COL_ARROW); + unclip(dr); + draw_update(dr, ds->oppx, ds->oppy, TILE_SIZE, TILE_SIZE); } #ifdef EDITOR { @@ -3508,13 +3926,9 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - #ifndef EDITOR -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; @@ -3522,17 +3936,19 @@ static void game_print_size(const game_params *params, float *x, float *y) * 8mm squares by default. (There isn't all that much detail * that needs to go in each square.) */ - game_compute_size(params, 800, &pw, &ph); + game_compute_size(params, 800, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int sz) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int sz) { int w = state->w, h = state->h; int white, black, blackish; int x, y, i, j; - int *colours, *dsf; + int *colours; + DSF *dsf; int *coords = NULL; int ncoords = 0, coordsize = 0; @@ -3547,7 +3963,7 @@ static void game_print(drawing *dr, const game_state *state, int sz) /* * Get the completion information. */ - dsf = snewn(w * h, int); + dsf = dsf_new(w * h); colours = snewn(w * h, int); check_complete(state, dsf, colours); @@ -3683,7 +4099,7 @@ static void game_print(drawing *dr, const game_state *state, int sz) black : white), black); } - sfree(dsf); + dsf_free(dsf); sfree(colours); sfree(coords); } @@ -3714,12 +4130,18 @@ const struct game thegame = { true, solve_game, #endif true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, +#ifdef EDITOR + NULL, +#else + current_key_label, +#endif interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3738,13 +4160,13 @@ const struct game thegame = { true, false, game_print_size, game_print, false, /* wants_statusbar */ #endif - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; #ifdef STANDALONE_SOLVER -const char *quis; +static const char *quis; #include @@ -3802,7 +4224,7 @@ static void soak(game_params *p, random_state *rs) #endif tt_start = tt_now = time(NULL); for (i = 0; i < DIFF_MAX; i++) diffs[i] = 0; - maxtries = 1; + one_try = true; printf("Soak-generating a %dx%d grid, max. diff %s.\n", p->w, p->h, galaxies_diffnames[p->diff]); @@ -3812,7 +4234,9 @@ static void soak(game_params *p, random_state *rs) printf("]\n"); while (1) { - desc = new_game_desc(p, rs, NULL, false); + char *aux; + desc = new_game_desc(p, rs, &aux, false); + sfree(aux); st = new_game(NULL, p, desc); diff = solver_state(st, p->diff); nspaces += st->w*st->h; @@ -3866,8 +4290,6 @@ int main(int argc, char **argv) } } - maxtries = 50; - p = default_params(); rs = random_new((void*)&seed, sizeof(time_t)); diff --git a/apps/plugins/puzzles/src/grid.c b/apps/plugins/puzzles/src/grid.c index 5ea37439d4..04bb8a36cd 100644 --- a/apps/plugins/puzzles/src/grid.c +++ b/apps/plugins/puzzles/src/grid.c @@ -11,13 +11,21 @@ #include #include #include -#include #include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" #include "grid.h" +#include "penrose-legacy.h" #include "penrose.h" +#include "hat.h" +#include "spectre.h" /* Debugging options */ @@ -36,12 +44,17 @@ void grid_free(grid *g) if (g->refcount == 0) { int i; for (i = 0; i < g->num_faces; i++) { - sfree(g->faces[i].dots); - sfree(g->faces[i].edges); + sfree(g->faces[i]->dots); + sfree(g->faces[i]->edges); + sfree(g->faces[i]); } for (i = 0; i < g->num_dots; i++) { - sfree(g->dots[i].faces); - sfree(g->dots[i].edges); + sfree(g->dots[i]->faces); + sfree(g->dots[i]->edges); + sfree(g->dots[i]); + } + for (i = 0; i < g->num_edges; i++) { + sfree(g->edges[i]); } sfree(g->faces); sfree(g->edges); @@ -59,6 +72,7 @@ static grid *grid_empty(void) g->edges = NULL; g->dots = NULL; g->num_faces = g->num_edges = g->num_dots = 0; + g->size_faces = g->size_edges = g->size_dots = 0; g->refcount = 1; g->lowest_x = g->lowest_y = g->highest_x = g->highest_y = 0; return g; @@ -116,7 +130,7 @@ grid_edge *grid_nearest_edge(grid *g, int x, int y) best_edge = NULL; for (i = 0; i < g->num_edges; i++) { - grid_edge *e = &g->edges[i]; + grid_edge *e = g->edges[i]; long e2; /* squared length of edge */ long a2, b2; /* squared lengths of other sides */ double dist; @@ -185,7 +199,7 @@ xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\n"); if (which & SVG_FACES) { fprintf(fp, "\n"); for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; fprintf(fp, "order; j++) { grid_dot *d = f->dots[j]; @@ -200,7 +214,7 @@ xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\n"); if (which & SVG_EDGES) { fprintf(fp, "\n"); for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; grid_dot *d1 = e->dot1, *d2 = e->dot2; fprintf(fp, "\n\n"); if (which & SVG_DOTS) { fprintf(fp, "\n"); for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; fprintf(fp, "", d->x, d->y, g->tilesize/20, g->tilesize/20, DOT_COLOUR); } @@ -251,13 +265,17 @@ static void grid_debug_basic(grid *g) #ifdef DEBUG_GRID int i; printf("--- Basic Grid Data ---\n"); + for (i = 0; i < g->num_dots; i++) { + grid_dot *d = g->dots[i]; + printf("Dot %d at (%d,%d)\n", i, d->x, d->y); + } for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; printf("Face %d: dots[", i); int j; for (j = 0; j < f->order; j++) { grid_dot *d = f->dots[j]; - printf("%s%d", j ? "," : "", (int)(d - g->dots)); + printf("%s%d", j ? "," : "", (int)(d->index)); } printf("]\n"); } @@ -275,38 +293,38 @@ static void grid_debug_derived(grid *g) int i; printf("--- Derived Grid Data ---\n"); for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; printf("Edge %d: dots[%d,%d] faces[%d,%d]\n", - i, (int)(e->dot1 - g->dots), (int)(e->dot2 - g->dots), - e->face1 ? (int)(e->face1 - g->faces) : -1, - e->face2 ? (int)(e->face2 - g->faces) : -1); + i, (int)(e->dot1->index), (int)(e->dot2->index), + e->face1 ? (int)(e->face1->index) : -1, + e->face2 ? (int)(e->face2->index) : -1); } /* faces */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int j; printf("Face %d: faces[", i); for (j = 0; j < f->order; j++) { grid_edge *e = f->edges[j]; grid_face *f2 = (e->face1 == f) ? e->face2 : e->face1; - printf("%s%d", j ? "," : "", f2 ? (int)(f2 - g->faces) : -1); + printf("%s%d", j ? "," : "", f2 ? f2->index : -1); } printf("]\n"); } /* dots */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int j; printf("Dot %d: dots[", i); for (j = 0; j < d->order; j++) { grid_edge *e = d->edges[j]; grid_dot *d2 = (e->dot1 == d) ? e->dot2 : e->dot1; - printf("%s%d", j ? "," : "", (int)(d2 - g->dots)); + printf("%s%d", j ? "," : "", d2->index); } printf("] faces["); for (j = 0; j < d->order; j++) { grid_face *f = d->faces[j]; - printf("%s%d", j ? "," : "", f ? (int)(f - g->faces) : -1); + printf("%s%d", j ? "," : "", f ? f->index : -1); } printf("]\n"); } @@ -324,21 +342,23 @@ static int grid_edge_bydots_cmpfn(void *v1, void *v2) grid_edge *b = v2; grid_dot *da, *db; - /* Pointer subtraction is valid here, because all dots point into the - * same dot-list (g->dots). - * Edges are not "normalised" - the 2 dots could be stored in any order, + /* Edges are not "normalised" - the 2 dots could be stored in any order, * so we need to take this into account when comparing edges. */ /* Compare first dots */ da = (a->dot1 < a->dot2) ? a->dot1 : a->dot2; db = (b->dot1 < b->dot2) ? b->dot1 : b->dot2; - if (da != db) - return db - da; + if (da->index < db->index) + return -1; + if (da->index > db->index) + return +1; /* Compare last dots */ da = (a->dot1 < a->dot2) ? a->dot2 : a->dot1; db = (b->dot1 < b->dot2) ? b->dot2 : b->dot1; - if (da != db) - return db - da; + if (da->index < db->index) + return -1; + if (da->index > db->index) + return +1; return 0; } @@ -358,7 +378,7 @@ static int grid_edge_bydots_cmpfn(void *v1, void *v2) static void grid_trim_vigorously(grid *g) { int *dotpairs, *faces, *dots; - int *dsf; + DSF *dsf; int i, j, k, size, newfaces, newdots; /* @@ -371,10 +391,10 @@ static void grid_trim_vigorously(grid *g) for (j = 0; j < g->num_dots; j++) dotpairs[i*g->num_dots+j] = -1; for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; - int dot0 = f->dots[f->order-1] - g->dots; + grid_face *f = g->faces[i]; + int dot0 = f->dots[f->order-1]->index; for (j = 0; j < f->order; j++) { - int dot1 = f->dots[j] - g->dots; + int dot1 = f->dots[j]->index; dotpairs[dot0 * g->num_dots + dot1] = i; dot0 = dot1; } @@ -398,7 +418,7 @@ static void grid_trim_vigorously(grid *g) * Now identify connected pairs of landlocked dots, and form a dsf * unifying them. */ - dsf = snew_dsf(g->num_dots); + dsf = dsf_new(g->num_dots); for (i = 0; i < g->num_dots; i++) for (j = 0; j < i; j++) if (dots[i] && dots[j] && @@ -434,60 +454,52 @@ static void grid_trim_vigorously(grid *g) for (i = 0; i < g->num_dots; i++) dots[i] = 0; for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; bool keep = false; for (k = 0; k < f->order; k++) - if (dsf_canonify(dsf, f->dots[k] - g->dots) == j) + if (dsf_canonify(dsf, f->dots[k]->index) == j) keep = true; if (keep) { faces[i] = 1; for (k = 0; k < f->order; k++) - dots[f->dots[k]-g->dots] = 1; + dots[f->dots[k]->index] = 1; } } /* - * Work out the new indices of those faces and dots, when we - * compact the arrays containing them. - */ - for (i = newfaces = 0; i < g->num_faces; i++) - faces[i] = (faces[i] ? newfaces++ : -1); - for (i = newdots = 0; i < g->num_dots; i++) - dots[i] = (dots[i] ? newdots++ : -1); - - /* - * Free the dynamically allocated 'dots' pointer lists in faces - * we're going to discard. + * Compact the faces array, rewriting the faces' indices and + * freeing the unwanted ones. */ - for (i = 0; i < g->num_faces; i++) - if (faces[i] < 0) - sfree(g->faces[i].dots); + for (i = newfaces = 0; i < g->num_faces; i++) { + grid_face *f = g->faces[i]; + if (faces[i]) { + f->index = newfaces++; + g->faces[f->index] = f; + } else { + sfree(f->dots); + sfree(f); + } + } + g->num_faces = newfaces; /* - * Go through and compact the arrays. + * Compact the dots array, similarly. */ - for (i = 0; i < g->num_dots; i++) - if (dots[i] >= 0) { - grid_dot *dnew = g->dots + dots[i], *dold = g->dots + i; - *dnew = *dold; /* structure copy */ - } - for (i = 0; i < g->num_faces; i++) - if (faces[i] >= 0) { - grid_face *fnew = g->faces + faces[i], *fold = g->faces + i; - *fnew = *fold; /* structure copy */ - for (j = 0; j < fnew->order; j++) { - /* - * Reindex the dots in this face. - */ - k = fnew->dots[j] - g->dots; - fnew->dots[j] = g->dots + dots[k]; - } + for (i = newdots = 0; i < g->num_dots; i++) { + grid_dot *d = g->dots[i]; + if (dots[i]) { + d->index = newdots++; + g->dots[d->index] = d; + } else { + sfree(d->edges); + sfree(d->faces); + sfree(d); } - g->num_faces = newfaces; + } g->num_dots = newdots; sfree(dotpairs); - sfree(dsf); + dsf_free(dsf); sfree(dots); sfree(faces); } @@ -505,7 +517,6 @@ static void grid_make_consistent(grid *g) { int i; tree234 *incomplete_edges; - grid_edge *next_new_edge; /* Where new edge will go into g->edges */ grid_debug_basic(g); @@ -513,14 +524,6 @@ static void grid_make_consistent(grid *g) * Generate edges */ - /* We know how many dots and faces there are, so we can find the exact - * number of edges from Euler's polyhedral formula: F + V = E + 2 . - * We use "-1", not "-2" here, because Euler's formula includes the - * infinite face, which we don't count. */ - g->num_edges = g->num_faces + g->num_dots - 1; - g->edges = snewn(g->num_edges, grid_edge); - next_new_edge = g->edges; - /* Iterate over faces, and over each face's dots, generating edges as we * go. As we find each new edge, we can immediately fill in the edge's * dots, but only one of the edge's faces. Later on in the iteration, we @@ -530,7 +533,7 @@ static void grid_make_consistent(grid *g) * their dots. */ incomplete_edges = newtree234(grid_edge_bydots_cmpfn); for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int j; for (j = 0; j < f->order; j++) { grid_edge e; /* fake edge for searching */ @@ -548,18 +551,28 @@ static void grid_make_consistent(grid *g) * Edge is already removed from incomplete_edges. */ edge_found->face2 = f; } else { - assert(next_new_edge - g->edges < g->num_edges); - next_new_edge->dot1 = e.dot1; - next_new_edge->dot2 = e.dot2; - next_new_edge->face1 = f; - next_new_edge->face2 = NULL; /* potentially infinite face */ - add234(incomplete_edges, next_new_edge); - ++next_new_edge; + grid_edge *new_edge = snew(grid_edge); + new_edge->dot1 = e.dot1; + new_edge->dot2 = e.dot2; + new_edge->face1 = f; + new_edge->face2 = NULL; /* potentially infinite face */ + add234(incomplete_edges, new_edge); + + /* And add it to g->edges. */ + if (g->num_edges >= g->size_edges) { + int increment = g->num_edges / 4 + 128; + g->size_edges = (increment < INT_MAX - g->num_edges ? + g->num_edges + increment : INT_MAX); + g->edges = sresize(g->edges, g->size_edges, grid_edge *); + } + assert(g->num_edges < INT_MAX); + new_edge->index = g->num_edges++; + g->edges[new_edge->index] = new_edge; } } } freetree234(incomplete_edges); - + /* ====== Stage 2 ====== * For each face, build its edge list. */ @@ -567,7 +580,7 @@ static void grid_make_consistent(grid *g) /* Allocate space for each edge list. Can do this, because each face's * edge-list is the same size as its dot-list. */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int j; f->edges = snewn(f->order, grid_edge*); /* Preload with NULLs, to help detect potential bugs. */ @@ -579,7 +592,7 @@ static void grid_make_consistent(grid *g) * the face's edge-list, after finding where it should go in the * sequence. */ for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; int j; for (j = 0; j < 2; j++) { grid_face *f = j ? e->face2 : e->face1; @@ -641,16 +654,16 @@ static void grid_make_consistent(grid *g) * allocate the right space for these lists. Pre-compute the sizes by * iterating over each edge and recording a tally against each dot. */ for (i = 0; i < g->num_dots; i++) { - g->dots[i].order = 0; + g->dots[i]->order = 0; } for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; ++(e->dot1->order); ++(e->dot2->order); } /* Now we have the sizes, pre-allocate the edge and face lists. */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int j; assert(d->order >= 2); /* sanity check */ d->edges = snewn(d->order, grid_edge*); @@ -663,7 +676,7 @@ static void grid_make_consistent(grid *g) /* For each dot, need to find a face that touches it, so we can seed * the edge-face-edge-face process around each dot. */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int j; for (j = 0; j < f->order; j++) { grid_dot *d = f->dots[j]; @@ -677,7 +690,7 @@ static void grid_make_consistent(grid *g) * blocks progress. But there's only one such face, so we will * succeed in finding every edge and face this way. */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int current_face1 = 0; /* ascends clockwise */ int current_face2 = 0; /* descends anticlockwise */ @@ -774,7 +787,7 @@ static void grid_make_consistent(grid *g) /* Bounding rectangle */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; if (i == 0) { g->lowest_x = g->highest_x = d->x; g->lowest_y = g->highest_y = d->y; @@ -802,36 +815,52 @@ static int grid_point_cmp_fn(void *v1, void *v2) else return p2->x - p1->x; } -/* Add a new face to the grid, with its dot list allocated. - * Assumes there's enough space allocated for the new face in grid->faces */ +/* Add a new face to the grid, with its dot list allocated. */ static void grid_face_add_new(grid *g, int face_size) { int i; - grid_face *new_face = g->faces + g->num_faces; + grid_face *new_face = snew(grid_face); + assert(g->num_faces < INT_MAX); + if (g->num_faces >= g->size_faces) { + int increment = g->num_faces / 4 + 128; + g->size_faces = (increment < INT_MAX - g->num_faces ? + g->num_faces + increment : INT_MAX); + g->faces = sresize(g->faces, g->size_faces, grid_face *); + } + new_face->index = g->num_faces++; + g->faces[new_face->index] = new_face; + new_face->order = face_size; new_face->dots = snewn(face_size, grid_dot*); for (i = 0; i < face_size; i++) new_face->dots[i] = NULL; new_face->edges = NULL; new_face->has_incentre = false; - g->num_faces++; } -/* Assumes dot list has enough space */ static grid_dot *grid_dot_add_new(grid *g, int x, int y) { - grid_dot *new_dot = g->dots + g->num_dots; + grid_dot *new_dot = snew(grid_dot); + if (g->num_dots >= g->size_dots) { + int increment = g->num_dots / 4 + 128; + g->size_dots = (increment < INT_MAX - g->num_dots ? + g->num_dots + increment : INT_MAX); + g->dots = sresize(g->dots, g->size_dots, grid_dot *); + } + assert(g->num_dots < INT_MAX); + new_dot->index = g->num_dots++; + g->dots[new_dot->index] = new_dot; + new_dot->order = 0; new_dot->edges = NULL; new_dot->faces = NULL; new_dot->x = x; new_dot->y = y; - g->num_dots++; + return new_dot; } /* Retrieve a dot with these (x,y) coordinates. Either return an existing dot * in the dot_list, or add a new dot to the grid (and the dot_list) and - * return that. - * Assumes g->dots has enough capacity allocated */ + * return that. */ static grid_dot *grid_get_dot(grid *g, tree234 *dot_list, int x, int y) { grid_dot test, *ret; @@ -855,7 +884,7 @@ static grid_dot *grid_get_dot(grid *g, tree234 *dot_list, int x, int y) * previously been added, with the required number of dots allocated) */ static void grid_face_set_dot(grid *g, grid_dot *d, int position) { - grid_face *last_face = g->faces + g->num_faces - 1; + grid_face *last_face = g->faces[g->num_faces - 1]; last_face->dots[position] = d; } @@ -1388,6 +1417,15 @@ void grid_find_incentre(grid_face *f) #define SQUARE_TILESIZE 20 +static const char *grid_validate_params_square(int width, int height) +{ + if (width > INT_MAX / SQUARE_TILESIZE || /* xextent */ + height > INT_MAX / SQUARE_TILESIZE || /* yextent */ + width + 1 > INT_MAX / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_square(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1404,16 +1442,10 @@ static grid *grid_new_square(int width, int height, const char *desc) /* Side length */ int a = SQUARE_TILESIZE; - /* Upper bounds - don't have to be exact */ - int max_faces = width * height; - int max_dots = (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = a; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -1438,8 +1470,6 @@ static grid *grid_new_square(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -1450,6 +1480,18 @@ static grid *grid_new_square(int width, int height, const char *desc) #define HONEY_A 15 #define HONEY_B 26 +static const char *grid_validate_params_honeycomb(int width, int height) +{ + int a = HONEY_A; + int b = HONEY_B; + + if (width - 1 > (INT_MAX - 4*a) / (3 * a) || /* xextent */ + height - 1 > (INT_MAX - 3*b) / (2 * b) || /* yextent */ + width + 1 > INT_MAX / 2 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_honeycomb(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1467,16 +1509,10 @@ static grid *grid_new_honeycomb(int width, int height, const char *desc) int a = HONEY_A; int b = HONEY_B; - /* Upper bounds - don't have to be exact */ - int max_faces = width * height; - int max_dots = 2 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = HONEY_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -1507,8 +1543,6 @@ static grid *grid_new_honeycomb(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -1519,6 +1553,18 @@ static grid *grid_new_honeycomb(int width, int height, const char *desc) #define TRIANGLE_VEC_X 15 #define TRIANGLE_VEC_Y 26 +static const char *grid_validate_params_triangular(int width, int height) +{ + int vec_x = TRIANGLE_VEC_X; + int vec_y = TRIANGLE_VEC_Y; + + if (width > INT_MAX / (2 * vec_x) - 1 || /* xextent */ + height > INT_MAX / vec_y || /* yextent */ + width + 1 > INT_MAX / 4 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_triangular(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1582,16 +1628,18 @@ static grid *grid_new_triangular(int width, int height, const char *desc) * 5x6t1:a022a212h1a1d1a12c2b11a012b1a20d1a0a12e */ - g->num_faces = width * height * 2; - g->num_dots = (width + 1) * (height + 1); - g->faces = snewn(g->num_faces, grid_face); - g->dots = snewn(g->num_dots, grid_dot); + g->num_faces = g->size_faces = width * height * 2; + g->num_dots = g->size_dots = (width + 1) * (height + 1); + g->faces = snewn(g->size_faces, grid_face *); + g->dots = snewn(g->size_dots, grid_dot *); /* generate dots */ index = 0; for (y = 0; y <= height; y++) { for (x = 0; x <= width; x++) { - grid_dot *d = g->dots + index; + grid_dot *d = snew(grid_dot); + d->index = index; + g->dots[d->index] = d; /* odd rows are offset to the right */ d->order = 0; d->edges = NULL; @@ -1607,8 +1655,11 @@ static grid *grid_new_triangular(int width, int height, const char *desc) for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { /* initialise two faces for this (x,y) */ - grid_face *f1 = g->faces + index; - grid_face *f2 = f1 + 1; + grid_face *f1 = snew(grid_face), *f2 = snew(grid_face); + f1->index = index; + f2->index = index + 1; + g->faces[f1->index] = f1; + g->faces[f2->index] = f2; f1->edges = NULL; f1->order = 3; f1->dots = snewn(f1->order, grid_dot*); @@ -1621,19 +1672,19 @@ static grid *grid_new_triangular(int width, int height, const char *desc) /* face descriptions depend on whether the row-number is * odd or even */ if (y % 2) { - f1->dots[0] = g->dots + y * w + x; - f1->dots[1] = g->dots + (y + 1) * w + x + 1; - f1->dots[2] = g->dots + (y + 1) * w + x; - f2->dots[0] = g->dots + y * w + x; - f2->dots[1] = g->dots + y * w + x + 1; - f2->dots[2] = g->dots + (y + 1) * w + x + 1; + f1->dots[0] = g->dots[y * w + x]; + f1->dots[1] = g->dots[(y + 1) * w + x + 1]; + f1->dots[2] = g->dots[(y + 1) * w + x]; + f2->dots[0] = g->dots[y * w + x]; + f2->dots[1] = g->dots[y * w + x + 1]; + f2->dots[2] = g->dots[(y + 1) * w + x + 1]; } else { - f1->dots[0] = g->dots + y * w + x; - f1->dots[1] = g->dots + y * w + x + 1; - f1->dots[2] = g->dots + (y + 1) * w + x; - f2->dots[0] = g->dots + y * w + x + 1; - f2->dots[1] = g->dots + (y + 1) * w + x + 1; - f2->dots[2] = g->dots + (y + 1) * w + x; + f1->dots[0] = g->dots[y * w + x]; + f1->dots[1] = g->dots[y * w + x + 1]; + f1->dots[2] = g->dots[(y + 1) * w + x]; + f2->dots[0] = g->dots[y * w + x + 1]; + f2->dots[1] = g->dots[(y + 1) * w + x + 1]; + f2->dots[2] = g->dots[(y + 1) * w + x]; } index += 2; } @@ -1650,12 +1701,6 @@ static grid *grid_new_triangular(int width, int height, const char *desc) * 5x6t1:0_a1212c22c2a02a2f22a0c12a110d0e1c0c0a101121a1 */ tree234 *points = newtree234(grid_point_cmp_fn); - /* Upper bounds - don't have to be exact */ - int max_faces = height * (2*width+1); - int max_dots = (height+1) * (width+1) * 4; - - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); for (y = 0; y < height; y++) { /* @@ -1703,8 +1748,6 @@ static grid *grid_new_triangular(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); } grid_make_consistent(g); @@ -1716,6 +1759,19 @@ static grid *grid_new_triangular(int width, int height, const char *desc) #define SNUBSQUARE_A 15 #define SNUBSQUARE_B 26 +static const char *grid_validate_params_snubsquare(int width, int height) +{ + int a = SNUBSQUARE_A; + int b = SNUBSQUARE_B; + + if (width-1 > (INT_MAX - (a + b)) / (a+b) || /* xextent */ + height > (INT_MAX - (a + b)) / (a+b) || /* yextent */ + width > INT_MAX / 3 / height || /* max_faces */ + width + 1 > INT_MAX / 2 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_snubsquare(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1733,16 +1789,10 @@ static grid *grid_new_snubsquare(int width, int height, const char *desc) int a = SNUBSQUARE_A; int b = SNUBSQUARE_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 3 * width * height; - int max_dots = 2 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = SNUBSQUARE_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -1818,8 +1868,6 @@ static grid *grid_new_snubsquare(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -1830,6 +1878,18 @@ static grid *grid_new_snubsquare(int width, int height, const char *desc) #define CAIRO_A 14 #define CAIRO_B 31 +static const char *grid_validate_params_cairo(int width, int height) +{ + int b = CAIRO_B; /* a unused in determining grid size. */ + + if (width - 1 > (INT_MAX - 2*b) / (2*b) || /* xextent */ + height - 1 > (INT_MAX - 2*b) / (2*b) || /* yextent */ + width > INT_MAX / 2 / height || /* max_faces */ + width + 1 > INT_MAX / 3 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_cairo(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1846,16 +1906,10 @@ static grid *grid_new_cairo(int width, int height, const char *desc) int a = CAIRO_A; int b = CAIRO_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 2 * width * height; - int max_dots = 3 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = CAIRO_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -1924,8 +1978,6 @@ static grid *grid_new_cairo(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -1936,6 +1988,18 @@ static grid *grid_new_cairo(int width, int height, const char *desc) #define GREATHEX_A 15 #define GREATHEX_B 26 +static const char *grid_validate_params_greathexagonal(int width, int height) +{ + int a = GREATHEX_A; + int b = GREATHEX_B; + + if (width-1 > (INT_MAX - 4*a) / (3*a + b) || /* xextent */ + height-1 > (INT_MAX - (3*b + a)) / (2*a + 2*b) || /* yextent */ + width + 1 > INT_MAX / 6 / (height + 1)) /* max_faces */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_greathexagonal(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -1953,16 +2017,10 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc) int a = GREATHEX_A; int b = GREATHEX_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 6 * (width + 1) * (height + 1); - int max_dots = 6 * width * height; - tree234 *points; grid *g = grid_empty(); g->tilesize = GREATHEX_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2054,8 +2112,6 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -2066,6 +2122,18 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc) #define KAGOME_A 15 #define KAGOME_B 26 +static const char *grid_validate_params_kagome(int width, int height) +{ + int a = KAGOME_A; + int b = KAGOME_B; + + if (width-1 > (INT_MAX - 6*a) / (4*a) || /* xextent */ + height-1 > (INT_MAX - 2*b) / (2*b) || /* yextent */ + width + 1 > INT_MAX / 6 / (height + 1)) /* max_faces */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_kagome(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2083,16 +2151,10 @@ static grid *grid_new_kagome(int width, int height, const char *desc) int a = KAGOME_A; int b = KAGOME_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 6 * (width + 1) * (height + 1); - int max_dots = 6 * width * height; - tree234 *points; grid *g = grid_empty(); g->tilesize = KAGOME_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2150,8 +2212,6 @@ static grid *grid_new_kagome(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -2162,6 +2222,18 @@ static grid *grid_new_kagome(int width, int height, const char *desc) #define OCTAGONAL_A 29 #define OCTAGONAL_B 41 +static const char *grid_validate_params_octagonal(int width, int height) +{ + int a = OCTAGONAL_A; + int b = OCTAGONAL_B; + + if (width > INT_MAX / (2*a + b) || /* xextent */ + height > INT_MAX / (2*a + b) || /* yextent */ + height + 1 > INT_MAX / 4 / (width + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_octagonal(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2179,16 +2251,10 @@ static grid *grid_new_octagonal(int width, int height, const char *desc) int a = OCTAGONAL_A; int b = OCTAGONAL_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 2 * width * height; - int max_dots = 4 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = OCTAGONAL_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2233,8 +2299,6 @@ static grid *grid_new_octagonal(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -2245,6 +2309,18 @@ static grid *grid_new_octagonal(int width, int height, const char *desc) #define KITE_A 15 #define KITE_B 26 +static const char *grid_validate_params_kites(int width, int height) +{ + int a = KITE_A; + int b = KITE_B; + + if (width > (INT_MAX - 2*b) / (4*b) || /* xextent */ + height - 1 > (INT_MAX - 8*a) / (6*a) || /* yextent */ + width + 1 > INT_MAX / 6 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_kites(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2262,16 +2338,10 @@ static grid *grid_new_kites(int width, int height, const char *desc) int a = KITE_A; int b = KITE_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 6 * width * height; - int max_dots = 6 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = KITE_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2353,8 +2423,6 @@ static grid *grid_new_kites(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -2367,6 +2435,20 @@ static grid *grid_new_kites(int width, int height, const char *desc) #define FLORET_PX 75 #define FLORET_PY -26 +static const char *grid_validate_params_floret(int width, int height) +{ + int px = FLORET_PX, py = FLORET_PY; /* |( 75, -26)| = 79.43 */ + int qx = 4*px/5, qy = -py*2; /* |( 60, 52)| = 79.40 */ + int ry = qy-py; + /* rx unused in determining grid size. */ + + if (width - 1 > (INT_MAX - (4*qx + 2*px)) / ((6*px+3*qx)/2) ||/* xextent */ + height - 1 > (INT_MAX - (4*qy + 2*ry)) / (5*qy-4*py) || /* yextent */ + width + 1 > INT_MAX / 9 / (height + 1)) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_floret(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2393,16 +2475,10 @@ static grid *grid_new_floret(int width, int height, const char *desc) int qx = 4*px/5, qy = -py*2; /* |( 60, 52)| = 79.40 */ int rx = qx-px, ry = qy-py; /* |(-15, 78)| = 79.38 */ - /* Upper bounds - don't have to be exact */ - int max_faces = 6 * width * height; - int max_dots = 9 * (width + 1) * (height + 1); - tree234 *points; grid *g = grid_empty(); g->tilesize = FLORET_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2463,8 +2539,6 @@ static grid *grid_new_floret(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; @@ -2476,6 +2550,18 @@ static grid *grid_new_floret(int width, int height, const char *desc) #define DODEC_A 15 #define DODEC_B 26 +static const char *grid_validate_params_dodecagonal(int width, int height) +{ + int a = DODEC_A; + int b = DODEC_B; + + if (width - 1 > (INT_MAX - 3*(2*a + b)) / (4*a + 2*b) || /* xextent */ + height - 1 > (INT_MAX - 2*(2*a + b)) / (3*a + 2*b) || /* yextent */ + width > INT_MAX / 14 / height) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_dodecagonal(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2493,16 +2579,10 @@ static grid *grid_new_dodecagonal(int width, int height, const char *desc) int a = DODEC_A; int b = DODEC_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 3 * width * height; - int max_dots = 14 * width * height; - tree234 *points; grid *g = grid_empty(); g->tilesize = DODEC_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2549,13 +2629,23 @@ static grid *grid_new_dodecagonal(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; } +static const char *grid_validate_params_greatdodecagonal(int width, int height) +{ + int a = DODEC_A; + int b = DODEC_B; + + if (width - 1 > (INT_MAX - (2*(2*a + b) + 3*a + b)) / (6*a + 2*b) || + height - 1 > (INT_MAX - 2*(2*a + b)) / (3*a + 3*b) || /* yextent */ + width > INT_MAX / 200 / height) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_greatdodecagonal(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2574,16 +2664,10 @@ static grid *grid_new_greatdodecagonal(int width, int height, const char *desc) int a = DODEC_A; int b = DODEC_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 30 * width * height; - int max_dots = 200 * width * height; - tree234 *points; grid *g = grid_empty(); g->tilesize = DODEC_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2663,13 +2747,24 @@ static grid *grid_new_greatdodecagonal(int width, int height, const char *desc) } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; } +static const char *grid_validate_params_greatgreatdodecagonal( + int width, int height) +{ + int a = DODEC_A; + int b = DODEC_B; + + if (width-1 > (INT_MAX - (2*(2*a + b) + 2*a + 2*b)) / (4*a + 4*b) || + height-1 > (INT_MAX - 2*(2*a + b)) / (6*a + 2*b) || /* yextent */ + width > INT_MAX / 300 / height) /* max_dots */ + return "Grid size must not be unreasonably large"; + return NULL; +} + static void grid_size_greatgreatdodecagonal(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -2688,16 +2783,10 @@ static grid *grid_new_greatgreatdodecagonal(int width, int height, const char *d int a = DODEC_A; int b = DODEC_B; - /* Upper bounds - don't have to be exact */ - int max_faces = 50 * width * height; - int max_dots = 300 * width * height; - tree234 *points; grid *g = grid_empty(); g->tilesize = DODEC_TILESIZE; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -2747,7 +2836,7 @@ static grid *grid_new_greatgreatdodecagonal(int width, int height, const char *d d = grid_get_dot(g, points, px + (2*a + 2*b), py - 2*a); grid_face_set_dot(g, d, 5); } - /* hexagon on bottom right of dodecagon */ + /* hexagon on bottom right of dodecagon */ if ((y < height - 1) && (x < width - 1 || !(y % 2))) { grid_face_add_new(g, 6); d = grid_get_dot(g, points, px + (a + 2*b), py + (2*a + b)); grid_face_set_dot(g, d, 0); @@ -2832,29 +2921,165 @@ static grid *grid_new_greatgreatdodecagonal(int width, int height, const char *d } freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); grid_make_consistent(g); return g; } -typedef struct setface_ctx +static const char *grid_validate_params_compassdodecagonal( + int width, int height) +{ + int a = DODEC_A; + int b = DODEC_B; + + if (width > INT_MAX / (4*a + 2*b) || /* xextent */ + height > INT_MAX / (4*a + 2*b) || /* yextent */ + width > INT_MAX / 18 / height) /* max_dots */ + return "Grid must not be unreasonably large"; + return NULL; +} + +static void grid_size_compassdodecagonal(int width, int height, + int *tilesize, int *xextent, int *yextent) +{ + int a = DODEC_A; + int b = DODEC_B; + + *tilesize = DODEC_TILESIZE; + *xextent = (4*a + 2*b) * width; + *yextent = (4*a + 2*b) * height; +} + +static grid *grid_new_compassdodecagonal(int width, int height, const char *desc) { + int x, y; + /* Vector for side of triangle - ratio is close to sqrt(3) */ + int a = DODEC_A; + int b = DODEC_B; + + tree234 *points; + + grid *g = grid_empty(); + g->tilesize = DODEC_TILESIZE; + + points = newtree234(grid_point_cmp_fn); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + grid_dot *d; + /* centre of dodecagon */ + int px = (4*a + 2*b) * x; + int py = (4*a + 2*b) * y; + + /* dodecagon */ + grid_face_add_new(g, 12); + d = grid_get_dot(g, points, px + ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + (2*a + b), py - ( a )); grid_face_set_dot(g, d, 2); + d = grid_get_dot(g, points, px + (2*a + b), py + ( a )); grid_face_set_dot(g, d, 3); + d = grid_get_dot(g, points, px + ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 4); + d = grid_get_dot(g, points, px + ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 5); + d = grid_get_dot(g, points, px - ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 6); + d = grid_get_dot(g, points, px - ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 7); + d = grid_get_dot(g, points, px - (2*a + b), py + ( a )); grid_face_set_dot(g, d, 8); + d = grid_get_dot(g, points, px - (2*a + b), py - ( a )); grid_face_set_dot(g, d, 9); + d = grid_get_dot(g, points, px - ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 10); + d = grid_get_dot(g, points, px - ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 11); + + if (x < width - 1 && y < height - 1) { + /* north triangle */ + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + (2*a + b), py + ( a )); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + (3*a + b), py + ( a + b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 2); + + /* east triangle */ + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + (3*a + 2*b), py + (2*a + b)); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + (3*a + b), py + (3*a + b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + (3*a + b), py + ( a + b)); grid_face_set_dot(g, d, 2); + + /* south triangle */ + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + (3*a + b), py + (3*a + b)); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + (2*a + b), py + (3*a + 2*b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + ( a + b), py + (3*a + b)); grid_face_set_dot(g, d, 2); + + /* west triangle */ + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + (a + b), py + ( a + b)); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + (a + b), py + (3*a + b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + (a ), py + (2*a + b)); grid_face_set_dot(g, d, 2); + + /* square in center */ + grid_face_add_new(g, 4); + d = grid_get_dot(g, points, px + (3*a + b), py + ( a + b)); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + (3*a + b), py + (3*a + b)); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + ( a + b), py + (3*a + b)); grid_face_set_dot(g, d, 2); + d = grid_get_dot(g, points, px + ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 3); + } + } + } + + freetree234(points); + + grid_make_consistent(g); + return g; +} + +/* + * Penrose tilings. For historical reasons, we support two totally + * different generation algorithms: the legacy one is only supported + * by grid_new_penrose, for backwards compatibility with game + * descriptions generated before we switched. New grid generation uses + * only the new system. + */ + +#define PENROSE_TILESIZE 100 + +static const char *grid_validate_params_penrose(int width, int height) +{ + int l = PENROSE_TILESIZE; + + if (width > INT_MAX / l || /* xextent */ + height > INT_MAX / l || /* yextent */ + width > INT_MAX / (3 * 3 * 4 * height)) /* max_dots */ + return "Grid must not be unreasonably large"; + return NULL; +} + +static void grid_size_penrose(int width, int height, + int *tilesize, int *xextent, int *yextent) +{ + int l = PENROSE_TILESIZE; + + *tilesize = l; + *xextent = l * width; + *yextent = l * height; +} + +/* + * Legacy generation by selecting a patch of tiling from the expansion + * of a big triangle. + */ + +typedef struct penrose_legacy_set_faces_ctx { int xmin, xmax, ymin, ymax; grid *g; tree234 *points; -} setface_ctx; +} penrose_legacy_set_faces_ctx; static double round_int_nearest_away(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } -static int set_faces(penrose_state *state, vector *vs, int n, int depth) +static int penrose_legacy_set_faces(penrose_legacy_state *state, vector *vs, + int n, int depth) { - setface_ctx *sf_ctx = (setface_ctx *)state->ctx; + penrose_legacy_set_faces_ctx *sf_ctx = + (penrose_legacy_set_faces_ctx *)state->ctx; int i; int xs[4], ys[4]; @@ -2864,7 +3089,7 @@ static int set_faces(penrose_state *state, vector *vs, int n, int depth) #endif for (i = 0; i < n; i++) { - double tx = v_x(vs, i), ty = v_y(vs, i); + double tx = penrose_legacy_vx(vs, i), ty = penrose_legacy_vy(vs, i); xs[i] = (int)round_int_nearest_away(tx); ys[i] = (int)round_int_nearest_away(ty); @@ -2875,88 +3100,24 @@ static int set_faces(penrose_state *state, vector *vs, int n, int depth) grid_face_add_new(sf_ctx->g, n); debug(("penrose: new face l=%f gen=%d...", - penrose_side_length(state->start_size, depth), depth)); + penrose_legacy_side_length(state->start_size, depth), depth)); for (i = 0; i < n; i++) { grid_dot *d = grid_get_dot(sf_ctx->g, sf_ctx->points, xs[i], ys[i]); grid_face_set_dot(sf_ctx->g, d, i); debug((" ... dot 0x%x (%d,%d) (was %2.2f,%2.2f)", - d, d->x, d->y, v_x(vs, i), v_y(vs, i))); + d, d->x, d->y, penrose_legacy_vx(vs, i), + penrose_legacy_vy(vs, i))); } return 0; } -#define PENROSE_TILESIZE 100 - -static void grid_size_penrose(int width, int height, - int *tilesize, int *xextent, int *yextent) -{ - int l = PENROSE_TILESIZE; - - *tilesize = l; - *xextent = l * width; - *yextent = l * height; -} - -static grid *grid_new_penrose(int width, int height, int which, const char *desc); /* forward reference */ - -static char *grid_new_desc_penrose(grid_type type, int width, int height, random_state *rs) -{ - int tilesize = PENROSE_TILESIZE, startsz, depth, xoff, yoff, aoff; - double outer_radius; - int inner_radius; - char gd[255]; - int which = (type == GRID_PENROSE_P2 ? PENROSE_P2 : PENROSE_P3); - grid *g; - - while (1) { - /* We want to produce a random bit of penrose tiling, so we - * calculate a random offset (within the patch that penrose.c - * calculates for us) and an angle (multiple of 36) to rotate - * the patch. */ - - penrose_calculate_size(which, tilesize, width, height, - &outer_radius, &startsz, &depth); - - /* Calculate radius of (circumcircle of) patch, subtract from - * radius calculated. */ - inner_radius = (int)(outer_radius - sqrt(width*width + height*height)); - - /* Pick a random offset (the easy way: choose within outer - * square, discarding while it's outside the circle) */ - do { - xoff = random_upto(rs, 2*inner_radius) - inner_radius; - yoff = random_upto(rs, 2*inner_radius) - inner_radius; - } while (sqrt(xoff*xoff+yoff*yoff) > inner_radius); - - aoff = random_upto(rs, 360/36) * 36; - - debug(("grid_desc: ts %d, %dx%d patch, orad %2.2f irad %d", - tilesize, width, height, outer_radius, inner_radius)); - debug((" -> xoff %d yoff %d aoff %d", xoff, yoff, aoff)); - - sprintf(gd, "G%d,%d,%d", xoff, yoff, aoff); - - /* - * Now test-generate our grid, to make sure it actually - * produces something. - */ - g = grid_new_penrose(width, height, which, gd); - if (g) { - grid_free(g); - break; - } - /* If not, go back to the top of this while loop and try again - * with a different random offset. */ - } - - return dupstr(gd); -} +static grid *grid_new_penrose_legacy(int width, int height, int which, + const char *desc); -static const char *grid_validate_desc_penrose(grid_type type, - int width, int height, - const char *desc) +static const char *grid_validate_desc_penrose_legacy( + grid_type type, int width, int height, const char *desc) { int tilesize = PENROSE_TILESIZE, startsz, depth, xoff, yoff, aoff, inner_radius; double outer_radius; @@ -2966,8 +3127,8 @@ static const char *grid_validate_desc_penrose(grid_type type, if (!desc) return "Missing grid description string."; - penrose_calculate_size(which, tilesize, width, height, - &outer_radius, &startsz, &depth); + penrose_legacy_calculate_size(which, tilesize, width, height, + &outer_radius, &startsz, &depth); inner_radius = (int)(outer_radius - sqrt(width*width + height*height)); if (sscanf(desc, "G%d,%d,%d", &xoff, &yoff, &aoff) != 3) @@ -2982,7 +3143,7 @@ static const char *grid_validate_desc_penrose(grid_type type, * Test-generate to ensure these parameters don't end us up with * no grid at all. */ - g = grid_new_penrose(width, height, which, desc); + g = grid_new_penrose_legacy(width, height, which, desc); if (!g) return "Patch coordinates do not identify a usable grid fragment"; grid_free(g); @@ -2990,40 +3151,30 @@ static const char *grid_validate_desc_penrose(grid_type type, return NULL; } -/* - * We're asked for a grid of a particular size, and we generate enough - * of the tiling so we can be sure to have enough random grid from which - * to pick. - */ - -static grid *grid_new_penrose(int width, int height, int which, const char *desc) +static grid *grid_new_penrose_legacy(int width, int height, int which, + const char *desc) { - int max_faces, max_dots, tilesize = PENROSE_TILESIZE; + int tilesize = PENROSE_TILESIZE; int xsz, ysz, xoff, yoff, aoff; double rradius; tree234 *points; grid *g; - penrose_state ps; - setface_ctx sf_ctx; + penrose_legacy_state ps; + penrose_legacy_set_faces_ctx sf_ctx; - penrose_calculate_size(which, tilesize, width, height, - &rradius, &ps.start_size, &ps.max_depth); + penrose_legacy_calculate_size(which, tilesize, width, height, + &rradius, &ps.start_size, &ps.max_depth); debug(("penrose: w%d h%d, tile size %d, start size %d, depth %d", width, height, tilesize, ps.start_size, ps.max_depth)); - ps.new_tile = set_faces; + ps.new_tile = penrose_legacy_set_faces; ps.ctx = &sf_ctx; - max_faces = (width*3) * (height*3); /* somewhat paranoid... */ - max_dots = max_faces * 4; /* ditto... */ - g = grid_empty(); g->tilesize = tilesize; - g->faces = snewn(max_faces, grid_face); - g->dots = snewn(max_dots, grid_dot); points = newtree234(grid_point_cmp_fn); @@ -3051,11 +3202,9 @@ static grid *grid_new_penrose(int width, int height, int which, const char *desc debug(("penrose: x range (%f --> %f), y range (%f --> %f)", sf_ctx.xmin, sf_ctx.xmax, sf_ctx.ymin, sf_ctx.ymax)); - penrose(&ps, which, aoff); + penrose_legacy(&ps, which, aoff); freetree234(points); - assert(g->num_faces <= max_faces); - assert(g->num_dots <= max_dots); debug(("penrose: %d faces total (equivalent to %d wide by %d high)", g->num_faces, g->num_faces/height, g->num_faces/width)); @@ -3091,6 +3240,223 @@ static grid *grid_new_penrose(int width, int height, int which, const char *desc return g; } +/* + * Combinatorial-coordinate generation. + * + * We receive coordinates from the generator in the form of x,y pairs + * each of which is an integer combination of 1 and sqrt(5), but those + * pairs have different scale units in the x and y directions. The + * scale units are 1/4 for x and sin(pi/5)/2 for y, which makes their + * ratio equal to 2 sin(pi/5) ~= 1.1756. We fudge that irrational + * aspect ratio into a rational approximation, by simply taking a pair + * of integer scale factors for the x and y dimensions; this distorts + * the output tiling slightly, but the distortion is consistent, and + * doesn't accumulate over a large patch of tiling, so it won't make + * anything end up totally out of place. + * + * (However, we compute the subsequent combination of 1 and sqrt(5) + * exactly, because using an approximation to sqrt(5) _could_ mean + * that in a sufficiently large patch of tiling two such combinations + * ended up misordered.) + * + * Adding to the confusion, we also flip round the x and y + * coordinates, because it's slightly nicer to have vertical edges in + * the tiling rather than horizontal ones. (Both for aesthetics, and + * also because if two P3 thin rhombs are separated by a horizontal + * line and both contain numeric clues then the clue numbers look a + * bit crowded, due to digits being taller than they are wide.) + * + * Finally, we have different base unit sizes for the two tiling + * types, because sensible sizes for the two are actually different. + * Each of P2 and P3 can be subdivided into the other, via dividing + * the larger triangle type in two, so that L large and S small become + * L+S large and L small. In the limit, this means that you expect the + * number of triangles (hence tiles) to grow by a factor of phi in + * each of those subdivisions (and hence by a factor of phi^2 in a + * full subdivision of P2 to a finer P2). So a sensible size ratio + * between the two tilings is one that makes them fit about the same + * number of tiles into the same area - and since tile area is + * proportional to _square_ of length, it follows that the P2 and P3 + * length unit should differ by a factor of sqrt(phi). + */ +#define PENROSE_XUNIT_P2 37 +#define PENROSE_YUNIT_P2 44 +#define PENROSE_XUNIT_P3 30 +#define PENROSE_YUNIT_P3 35 + +struct size { int w, h; }; +static struct size api_size_penrose(int width, int height, int which) +{ + int xunit = (which == PENROSE_P2 ? PENROSE_XUNIT_P2 : PENROSE_XUNIT_P3); + int yunit = (which == PENROSE_P2 ? PENROSE_YUNIT_P2 : PENROSE_YUNIT_P3); + struct size size = { + width * PENROSE_TILESIZE / yunit, + height * PENROSE_TILESIZE / xunit, + }; + return size; +} + +static grid *grid_new_penrose(int width, int height, int which, + const char *desc); /* forward reference */ + +static char *grid_new_desc_penrose(grid_type type, int width, int height, + random_state *rs) +{ + char *buf; + struct PenrosePatchParams params; + int which = (type == GRID_PENROSE_P2 ? PENROSE_P2 : PENROSE_P3); + struct size size = api_size_penrose(width, height, which); + + penrose_tiling_randomise(¶ms, which, size.h, size.w, rs); + + buf = snewn(params.ncoords + 3, char); + buf[0] = '0' + params.orientation; + buf[1] = '0' + params.start_vertex; + memcpy(buf + 2, params.coords, params.ncoords); + buf[2 + params.ncoords] = '\0'; + + sfree(params.coords); + return buf; +} + +/* Shared code between validating and reading grid descs. + * Always allocates params->coords, whether or not it returns an error. */ +static const char *grid_desc_to_penrose_params( + const char *desc, int which, struct PenrosePatchParams *params) +{ + int i; + + if (!*desc) + return "empty grid description"; + + params->ncoords = strlen(desc) - 2; + params->coords = snewn(params->ncoords, char); + + { + char c = desc[0]; + if (isdigit((unsigned char)c)) + params->orientation = c - '0'; + else + return "expected digit at start of grid description"; + + c = desc[1]; + if (c >= '0' && c < '3') + params->start_vertex = c - '0'; + else + return "expected digit as second char of grid description"; + } + + for (i = 0; i < params->ncoords; i++) { + char c = desc[i+2]; + if (!penrose_valid_letter(c, which)) + return "expected tile letter in grid description"; + params->coords[i] = c; + } + + return NULL; +} + +static const char *grid_validate_desc_penrose(grid_type type, + int width, int height, + const char *desc) +{ + struct PenrosePatchParams params; + const char *error = NULL; + int which = (type == GRID_PENROSE_P2 ? PENROSE_P2 : PENROSE_P3); + + if (!desc) + return "Missing grid description string."; + + if (*desc == 'G') + return grid_validate_desc_penrose_legacy(type, width, height, desc); + + error = grid_desc_to_penrose_params(desc, which, ¶ms); + if (!error) + error = penrose_tiling_params_invalid(¶ms, which); + + sfree(params.coords); + return error; +} + +struct penrosecontext { + grid *g; + tree234 *points; + int xunit, yunit; +}; + +static void grid_penrose_callback(void *vctx, const int *coords) +{ + struct penrosecontext *ctx = (struct penrosecontext *)vctx; + size_t i; + + grid_face_add_new(ctx->g, 4); + for (i = 0; i < 4; i++) { + grid_dot *d = grid_get_dot( + ctx->g, ctx->points, + coords[4*i+2] * ctx->yunit + n_times_root_k( + coords[4*i+3] * ctx->yunit, 5), + coords[4*i+0] * ctx->xunit + n_times_root_k( + coords[4*i+1] * ctx->xunit, 5)); + grid_face_set_dot(ctx->g, d, i); + } +} + +static grid *grid_new_penrose(int width, int height, int which, + const char *desc) +{ + struct PenrosePatchParams params; + const char *error = NULL; + struct penrosecontext ctx[1]; + struct size size; + + if (*desc == 'G') + return grid_new_penrose_legacy(width, height, which, desc); + + error = grid_desc_to_penrose_params(desc, which, ¶ms); + assert(error == NULL && "grid_validate_desc_penrose should have failed"); + + ctx->g = grid_empty(); + ctx->g->tilesize = PENROSE_TILESIZE; + + ctx->points = newtree234(grid_point_cmp_fn); + + ctx->xunit = (which == PENROSE_P2 ? PENROSE_XUNIT_P2 : PENROSE_XUNIT_P3); + ctx->yunit = (which == PENROSE_P2 ? PENROSE_YUNIT_P2 : PENROSE_YUNIT_P3); + + size = api_size_penrose(width, height, which); + penrose_tiling_generate(¶ms, size.h, size.w, + grid_penrose_callback, ctx); + + freetree234(ctx->points); + sfree(params.coords); + + grid_trim_vigorously(ctx->g); + grid_make_consistent(ctx->g); + + /* + * Centre the grid in its originally promised rectangle. + */ + { + int w = width * PENROSE_TILESIZE, h = height * PENROSE_TILESIZE; + ctx->g->lowest_x -= (w - (ctx->g->highest_x - ctx->g->lowest_x))/2; + ctx->g->lowest_y -= (h - (ctx->g->highest_y - ctx->g->lowest_y))/2; + ctx->g->highest_x = ctx->g->lowest_x + w; + ctx->g->highest_y = ctx->g->lowest_y + h; + } + + return ctx->g; +} + +static const char *grid_validate_params_penrose_p2_kite(int width, int height) +{ + return grid_validate_params_penrose(width, height); +} + +static const char *grid_validate_params_penrose_p3_thick(int width, int height) +{ + return grid_validate_params_penrose(width, height); +} + static void grid_size_penrose_p2_kite(int width, int height, int *tilesize, int *xextent, int *yextent) { @@ -3113,18 +3479,349 @@ static grid *grid_new_penrose_p3_thick(int width, int height, const char *desc) return grid_new_penrose(width, height, PENROSE_P3, desc); } +#define HATS_TILESIZE 32 +#define HATS_XSQUARELEN 4 +#define HATS_YSQUARELEN 6 +#define HATS_XUNIT 14 +#define HATS_YUNIT 8 + +static const char *grid_validate_params_hats( + int width, int height) +{ + int l = HATS_TILESIZE; + + if (width > INT_MAX / l || /* xextent */ + height > INT_MAX / l || /* yextent */ + width > INT_MAX / (6 * height)) /* max_dots */ + return "Grid must not be unreasonably large"; + return NULL; +} + +static void grid_size_hats(int width, int height, + int *tilesize, int *xextent, int *yextent) +{ + *tilesize = HATS_TILESIZE; + *xextent = width * HATS_XUNIT * HATS_XSQUARELEN; + *yextent = height * HATS_YUNIT * HATS_YSQUARELEN; +} + +static char *grid_new_desc_hats( + grid_type type, int width, int height, random_state *rs) +{ + char *buf, *p; + size_t bufmax, i; + struct HatPatchParams hp; + + hat_tiling_randomise(&hp, width, height, rs); + + bufmax = 3 * hp.ncoords + 2; + buf = snewn(bufmax, char); + p = buf; + for (i = 0; i < hp.ncoords; i++) { + assert(hp.coords[i] < 100); /* at most 2 digits */ + assert(p - buf <= bufmax-4); /* room for 2 digits, comma and NUL */ + p += sprintf(p, "%d,", (int)hp.coords[i]); + } + assert(p - buf <= bufmax-2); /* room for final letter and NUL */ + p[0] = hp.final_metatile; + p[1] = '\0'; + + sfree(hp.coords); + return buf; +} + +/* Shared code between validating and reading grid descs. + * Always allocates hp->coords, whether or not it returns an error. */ +static const char *grid_desc_to_hat_params( + const char *desc, struct HatPatchParams *hp) +{ + size_t maxcoords; + const char *p = desc; + + maxcoords = (strlen(desc) + 1) / 2; + hp->coords = snewn(maxcoords, unsigned char); + hp->ncoords = 0; + + while (isdigit((unsigned char)*p)) { + const char *p_orig = p; + int n = atoi(p); + while (*p && isdigit((unsigned char)*p)) p++; + if (*p != ',') + return "expected ',' in grid description"; + if (p - p_orig > 2 || n > 0xFF) + return "too-large coordinate in grid description"; + p++; /* eat the comma */ + + /* This assert should be guaranteed by the way we calculated + * maxcoords, so a failure of this check is a bug in this + * function, not an indication of an invalid input string */ + assert(hp->ncoords < maxcoords); + hp->coords[hp->ncoords++] = n; + } + + if (*p == 'H' || *p == 'T' || *p == 'P' || *p == 'F') + hp->final_metatile = *p; + else + return "invalid character in grid description"; + + return NULL; +} + +static const char *grid_validate_desc_hats( + grid_type type, int width, int height, const char *desc) +{ + struct HatPatchParams hp; + const char *error = NULL; + + if (!desc) + return "Missing grid description string."; + + error = grid_desc_to_hat_params(desc, &hp); + if (!error) + error = hat_tiling_params_invalid(&hp); + + sfree(hp.coords); + return error; +} + +struct hatcontext { + grid *g; + tree234 *points; +}; + +static void grid_hats_callback(void *vctx, size_t nvertices, int *coords) +{ + struct hatcontext *ctx = (struct hatcontext *)vctx; + size_t i; + + grid_face_add_new(ctx->g, nvertices); + for (i = 0; i < nvertices; i++) { + grid_dot *d = grid_get_dot( + ctx->g, ctx->points, + coords[2*i] * HATS_XUNIT, + coords[2*i+1] * HATS_YUNIT); + grid_face_set_dot(ctx->g, d, i); + } +} + +static grid *grid_new_hats(int width, int height, const char *desc) +{ + struct HatPatchParams hp; + const char *error = NULL; + + error = grid_desc_to_hat_params(desc, &hp); + assert(error == NULL && "grid_validate_desc_hats should have failed"); + + struct hatcontext ctx[1]; + + ctx->g = grid_empty(); + ctx->g->tilesize = HATS_TILESIZE; + + ctx->points = newtree234(grid_point_cmp_fn); + + hat_tiling_generate(&hp, width, height, grid_hats_callback, ctx); + + freetree234(ctx->points); + sfree(hp.coords); + + grid_trim_vigorously(ctx->g); + grid_make_consistent(ctx->g); + return ctx->g; +} + +#define SPECTRE_TILESIZE 32 +#define SPECTRE_SQUARELEN 7 +#define SPECTRE_UNIT 8 + +static const char *grid_validate_params_spectres( + int width, int height) +{ + int l = SPECTRE_UNIT * SPECTRE_SQUARELEN; + + if (width > INT_MAX / l || /* xextent */ + height > INT_MAX / l || /* yextent */ + width > (INT_MAX / SPECTRE_SQUARELEN / + SPECTRE_SQUARELEN / height)) /* max_faces */ + return "Grid must not be unreasonably large"; + return NULL; +} + +static void grid_size_spectres(int width, int height, + int *tilesize, int *xextent, int *yextent) +{ + *tilesize = SPECTRE_TILESIZE; + *xextent = width * SPECTRE_UNIT * SPECTRE_SQUARELEN; + *yextent = height * SPECTRE_UNIT * SPECTRE_SQUARELEN; +} + +static char *grid_new_desc_spectres( + grid_type type, int width, int height, random_state *rs) +{ + char *buf; + size_t i; + struct SpectrePatchParams sp; + + spectre_tiling_randomise(&sp, width * SPECTRE_SQUARELEN, + height * SPECTRE_SQUARELEN, rs); + + buf = snewn(sp.ncoords + 3, char); + buf[0] = (sp.orientation < 10 ? '0' + sp.orientation : + 'A' + sp.orientation - 10); + for (i = 0; i < sp.ncoords; i++) { + assert(sp.coords[i] < 10); /* all indices are 1 digit */ + buf[i+1] = '0' + sp.coords[i]; + } + buf[sp.ncoords+1] = sp.final_hex; + buf[sp.ncoords+2] = '\0'; + + sfree(sp.coords); + return buf; +} + +/* Shared code between validating and reading grid descs. + * Always allocates sp->coords, whether or not it returns an error. */ +static const char *grid_desc_to_spectre_params( + const char *desc, struct SpectrePatchParams *sp) +{ + size_t i; + + if (!*desc) + return "empty grid description"; + + sp->ncoords = strlen(desc) - 2; + sp->coords = snewn(sp->ncoords, unsigned char); + + { + char c = desc[0]; + if (isdigit((unsigned char)c)) + sp->orientation = c - '0'; + else if (c == 'A' || c == 'B') + sp->orientation = 10 + c - 'A'; + else + return "expected digit or A,B at start of grid description"; + } + + for (i = 0; i < sp->ncoords; i++) { + char c = desc[i+1]; + if (!isdigit((unsigned char)c)) + return "expected digit in grid description"; + sp->coords[i] = c - '0'; + } + + sp->final_hex = desc[sp->ncoords+1]; + + return NULL; +} + +static const char *grid_validate_desc_spectres( + grid_type type, int width, int height, const char *desc) +{ + struct SpectrePatchParams sp; + const char *error = NULL; + + if (!desc) + return "Missing grid description string."; + + error = grid_desc_to_spectre_params(desc, &sp); + if (!error) + error = spectre_tiling_params_invalid(&sp); + + sfree(sp.coords); + return error; +} + +struct spectrecontext { + grid *g; + tree234 *points; +}; + +static void grid_spectres_callback(void *vctx, const int *coords) +{ + struct spectrecontext *ctx = (struct spectrecontext *)vctx; + size_t i; + + grid_face_add_new(ctx->g, SPECTRE_NVERTICES); + for (i = 0; i < SPECTRE_NVERTICES; i++) { + grid_dot *d = grid_get_dot( + ctx->g, ctx->points, + (coords[4*i+0] * SPECTRE_UNIT + + n_times_root_k(coords[4*i+1] * SPECTRE_UNIT, 3)), + (coords[4*i+2] * SPECTRE_UNIT + + n_times_root_k(coords[4*i+3] * SPECTRE_UNIT, 3))); + grid_face_set_dot(ctx->g, d, i); + } +} + +static grid *grid_new_spectres(int width, int height, const char *desc) +{ + struct SpectrePatchParams sp; + const char *error = NULL; + int width2 = width * SPECTRE_SQUARELEN; + int height2 = height * SPECTRE_SQUARELEN; + + error = grid_desc_to_spectre_params(desc, &sp); + assert(error == NULL && "grid_validate_desc_spectres should have failed"); + + struct spectrecontext ctx[1]; + + ctx->g = grid_empty(); + ctx->g->tilesize = SPECTRE_TILESIZE; + + ctx->points = newtree234(grid_point_cmp_fn); + + spectre_tiling_generate(&sp, width2, height2, grid_spectres_callback, ctx); + + freetree234(ctx->points); + sfree(sp.coords); + + grid_trim_vigorously(ctx->g); + grid_make_consistent(ctx->g); + + /* + * As with the Penrose tiling, we're likely to have different + * sized margins due to the lack of a neat grid that this tiling + * fits on. So now we know what tiles we're left with, recentre + * them. + */ + { + int w = width2 * SPECTRE_UNIT, h = height2 * SPECTRE_UNIT; + ctx->g->lowest_x -= (w - (ctx->g->highest_x - ctx->g->lowest_x))/2; + ctx->g->lowest_y -= (h - (ctx->g->highest_y - ctx->g->lowest_y))/2; + ctx->g->highest_x = ctx->g->lowest_x + w; + ctx->g->highest_y = ctx->g->lowest_y + h; + } + + return ctx->g; +} + /* ----------- End of grid generators ------------- */ +#define FNVAL(upper,lower) &grid_validate_params_ ## lower, #define FNNEW(upper,lower) &grid_new_ ## lower, #define FNSZ(upper,lower) &grid_size_ ## lower, +static const char *(*(grid_validate_paramses[]))(int, int) = + { GRIDGEN_LIST(FNVAL) }; static grid *(*(grid_news[]))(int, int, const char*) = { GRIDGEN_LIST(FNNEW) }; static void(*(grid_sizes[]))(int, int, int*, int*, int*) = { GRIDGEN_LIST(FNSZ) }; +/* Work out if a grid can be made, and complain if not. */ + +const char *grid_validate_params(grid_type type, int width, int height) +{ + if (width <= 0 || height <= 0) + return "Width and height must both be positive"; + return grid_validate_paramses[type](width, height); +} + char *grid_new_desc(grid_type type, int width, int height, random_state *rs) { if (type == GRID_PENROSE_P2 || type == GRID_PENROSE_P3) { return grid_new_desc_penrose(type, width, height, rs); + } else if (type == GRID_HATS) { + return grid_new_desc_hats(type, width, height, rs); + } else if (type == GRID_SPECTRES) { + return grid_new_desc_spectres(type, width, height, rs); } else if (type == GRID_TRIANGULAR) { return dupstr("0"); /* up-to-date version of triangular grid */ } else { @@ -3137,6 +3834,10 @@ const char *grid_validate_desc(grid_type type, int width, int height, { if (type == GRID_PENROSE_P2 || type == GRID_PENROSE_P3) { return grid_validate_desc_penrose(type, width, height, desc); + } else if (type == GRID_HATS) { + return grid_validate_desc_hats(type, width, height, desc); + } else if (type == GRID_SPECTRES) { + return grid_validate_desc_spectres(type, width, height, desc); } else if (type == GRID_TRIANGULAR) { return grid_validate_desc_triangular(type, width, height, desc); } else { diff --git a/apps/plugins/puzzles/src/grid.h b/apps/plugins/puzzles/src/grid.h index 7ca3ff1d5f..77c8dd800f 100644 --- a/apps/plugins/puzzles/src/grid.h +++ b/apps/plugins/puzzles/src/grid.h @@ -33,6 +33,7 @@ typedef struct grid_edge grid_edge; typedef struct grid_dot grid_dot; struct grid_face { + int index; /* index in grid->faces[] where this face appears */ int order; /* Number of edges, also the number of dots */ grid_edge **edges; /* edges around this face */ grid_dot **dots; /* corners of this face */ @@ -56,8 +57,10 @@ struct grid_face { struct grid_edge { grid_dot *dot1, *dot2; grid_face *face1, *face2; /* Use NULL for the infinite outside face */ + int index; /* index in grid->edges[] where this edge appears */ }; struct grid_dot { + int index; /* index in grid->dots[] where this dot appears */ int order; grid_edge **edges; grid_face **faces; /* A NULL grid_face* means infinite outside face */ @@ -69,11 +72,13 @@ struct grid_dot { int x, y; }; typedef struct grid { - /* These are (dynamically allocated) arrays of all the - * faces, edges, dots that are in the grid. */ - int num_faces; grid_face *faces; - int num_edges; grid_edge *edges; - int num_dots; grid_dot *dots; + /* Arrays of all the faces, edges, dots that are in the grid. + * The arrays themselves are dynamically allocated, and so is each object + * inside them. num_foo indicates the number of things actually stored, + * and size_foo indicates the allocated size of the array. */ + int num_faces, size_faces; grid_face **faces; + int num_edges, size_edges; grid_edge **edges; + int num_dots, size_dots; grid_dot **dots; /* Cache the bounding-box of the grid, so the drawing-code can quickly * figure out the proper scaling to draw onto a given area. */ @@ -107,13 +112,19 @@ typedef struct grid { A(DODECAGONAL,dodecagonal) \ A(GREATDODECAGONAL,greatdodecagonal) \ A(GREATGREATDODECAGONAL,greatgreatdodecagonal) \ + A(COMPASSDODECAGONAL,compassdodecagonal) \ A(PENROSE_P2,penrose_p2_kite) \ - A(PENROSE_P3,penrose_p3_thick) + A(PENROSE_P3,penrose_p3_thick) \ + A(HATS,hats) \ + A(SPECTRES,spectres) \ + /* end of list */ #define ENUM(upper,lower) GRID_ ## upper, typedef enum grid_type { GRIDGEN_LIST(ENUM) GRID_TYPE_MAX } grid_type; #undef ENUM +const char *grid_validate_params(grid_type type, int width, int height); + /* Free directly after use if non-NULL. Will never contain an underscore * (so clients can safely use that as a separator). */ char *grid_new_desc(grid_type type, int width, int height, random_state *rs); diff --git a/apps/plugins/puzzles/src/gtk.c b/apps/plugins/puzzles/src/gtk.c index 7588ee0dc6..a40a70187f 100644 --- a/apps/plugins/puzzles/src/gtk.c +++ b/apps/plugins/puzzles/src/gtk.c @@ -2,6 +2,10 @@ * gtk.c: GTK front end for my puzzle collection. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 /* for strcasestr */ +#endif + #include #include #include @@ -9,8 +13,16 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif +#include +#include +#include +#include #include #include @@ -25,6 +37,7 @@ #include #include "puzzles.h" +#include "gtk.h" #if GTK_CHECK_VERSION(2,0,0) # define USE_PANGO @@ -82,7 +95,7 @@ #ifdef DEBUGGING static FILE *debug_fp = NULL; -void dputs(const char *buf) +static void dputs(const char *buf) { if (!debug_fp) { debug_fp = fopen("debug.log", "w"); @@ -131,6 +144,8 @@ void fatal(const char *fmt, ...) */ static void changed_preset(frontend *fe); +static void load_prefs(frontend *fe); +static char *save_prefs(frontend *fe); struct font { #ifdef USE_PANGO @@ -314,7 +329,7 @@ void frontend_default_colour(frontend *fe, float *output) output[0] = output[1] = output[2] = 0.9F; } -void gtk_status_bar(void *handle, const char *text) +static void gtk_status_bar(void *handle, const char *text) { frontend *fe = (frontend *)handle; @@ -389,6 +404,21 @@ static void print_set_colour(frontend *fe, int colour) static void set_window_background(frontend *fe, int colour) { +#if GTK_CHECK_VERSION(3,0,0) + /* In case the user's chosen theme is dark, we should not override + * the background colour for the whole window as this makes the + * menu and status bars unreadable. This might be visible through + * the gtk-application-prefer-dark-theme flag or else we have to + * work it out from the name. */ + gboolean dark_theme = false; + char *theme_name = NULL; + g_object_get(gtk_settings_get_default(), + "gtk-application-prefer-dark-theme", &dark_theme, + "gtk-theme-name", &theme_name, + NULL); + if (theme_name && strcasestr(theme_name, "-dark")) + dark_theme = true; + g_free(theme_name); #if GTK_CHECK_VERSION(3,20,0) char css_buf[512]; sprintf(css_buf, ".background { " @@ -401,23 +431,28 @@ static void set_window_background(frontend *fe, int colour) if (!gtk_css_provider_load_from_data( GTK_CSS_PROVIDER(fe->css_provider), css_buf, -1, NULL)) assert(0 && "Couldn't load CSS"); - gtk_style_context_add_provider( - gtk_widget_get_style_context(fe->window), - GTK_STYLE_PROVIDER(fe->css_provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + if (!dark_theme) { + gtk_style_context_add_provider( + gtk_widget_get_style_context(fe->window), + GTK_STYLE_PROVIDER(fe->css_provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } gtk_style_context_add_provider( gtk_widget_get_style_context(fe->area), GTK_STYLE_PROVIDER(fe->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); -#elif GTK_CHECK_VERSION(3,0,0) +#else // still at least GTK 3.0 but less than 3.20 GdkRGBA rgba; rgba.red = fe->colours[3*colour + 0]; rgba.green = fe->colours[3*colour + 1]; rgba.blue = fe->colours[3*colour + 2]; rgba.alpha = 1.0; gdk_window_set_background_rgba(gtk_widget_get_window(fe->area), &rgba); - gdk_window_set_background_rgba(gtk_widget_get_window(fe->window), &rgba); -#else + if (!dark_theme) + gdk_window_set_background_rgba(gtk_widget_get_window(fe->window), + &rgba); +#endif // GTK_CHECK_VERSION(3,20,0) +#else // GTK 2 version comes next GdkColormap *colmap; colmap = gdk_colormap_get_system(); @@ -571,7 +606,7 @@ static void do_draw_thick_line(frontend *fe, float thickness, cairo_restore(fe->cr); } -static void do_draw_poly(frontend *fe, int *coords, int npoints, +static void do_draw_poly(frontend *fe, const int *coords, int npoints, int fillcolour, int outlinecolour) { int i; @@ -832,7 +867,7 @@ static void do_draw_thick_line(frontend *fe, float thickness, save.join_style); } -static void do_draw_poly(frontend *fe, int *coords, int npoints, +static void do_draw_poly(frontend *fe, const int *coords, int npoints, int fillcolour, int outlinecolour) { GdkPoint *points = snewn(npoints, GdkPoint); @@ -1129,7 +1164,7 @@ static void align_and_draw_text(int index, int align, int x, int y, * The exported drawing functions. */ -void gtk_start_draw(void *handle) +static void gtk_start_draw(void *handle) { frontend *fe = (frontend *)handle; fe->bbox_l = fe->w; @@ -1139,20 +1174,21 @@ void gtk_start_draw(void *handle) setup_drawing(fe); } -void gtk_clip(void *handle, int x, int y, int w, int h) +static void gtk_clip(void *handle, int x, int y, int w, int h) { frontend *fe = (frontend *)handle; do_clip(fe, x, y, w, h); } -void gtk_unclip(void *handle) +static void gtk_unclip(void *handle) { frontend *fe = (frontend *)handle; do_unclip(fe); } -void gtk_draw_text(void *handle, int x, int y, int fonttype, int fontsize, - int align, int colour, const char *text) +static void gtk_draw_text(void *handle, int x, int y, int fonttype, + int fontsize, int align, int colour, + const char *text) { frontend *fe = (frontend *)handle; int i; @@ -1184,43 +1220,45 @@ void gtk_draw_text(void *handle, int x, int y, int fonttype, int fontsize, align_and_draw_text(fe, i, align, x, y, text); } -void gtk_draw_rect(void *handle, int x, int y, int w, int h, int colour) +static void gtk_draw_rect(void *handle, int x, int y, int w, int h, int colour) { frontend *fe = (frontend *)handle; fe->dr_api->set_colour(fe, colour); do_draw_rect(fe, x, y, w, h); } -void gtk_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour) +static void gtk_draw_line(void *handle, int x1, int y1, int x2, int y2, + int colour) { frontend *fe = (frontend *)handle; fe->dr_api->set_colour(fe, colour); do_draw_line(fe, x1, y1, x2, y2); } -void gtk_draw_thick_line(void *handle, float thickness, - float x1, float y1, float x2, float y2, int colour) +static void gtk_draw_thick_line(void *handle, float thickness, + float x1, float y1, float x2, float y2, + int colour) { frontend *fe = (frontend *)handle; fe->dr_api->set_colour(fe, colour); do_draw_thick_line(fe, thickness, x1, y1, x2, y2); } -void gtk_draw_poly(void *handle, int *coords, int npoints, - int fillcolour, int outlinecolour) +static void gtk_draw_poly(void *handle, const int *coords, int npoints, + int fillcolour, int outlinecolour) { frontend *fe = (frontend *)handle; do_draw_poly(fe, coords, npoints, fillcolour, outlinecolour); } -void gtk_draw_circle(void *handle, int cx, int cy, int radius, - int fillcolour, int outlinecolour) +static void gtk_draw_circle(void *handle, int cx, int cy, int radius, + int fillcolour, int outlinecolour) { frontend *fe = (frontend *)handle; do_draw_circle(fe, cx, cy, radius, fillcolour, outlinecolour); } -blitter *gtk_blitter_new(void *handle, int w, int h) +static blitter *gtk_blitter_new(void *handle, int w, int h) { blitter *bl = snew(blitter); setup_blitter(bl, w, h); @@ -1229,13 +1267,13 @@ blitter *gtk_blitter_new(void *handle, int w, int h) return bl; } -void gtk_blitter_free(void *handle, blitter *bl) +static void gtk_blitter_free(void *handle, blitter *bl) { teardown_blitter(bl); sfree(bl); } -void gtk_blitter_save(void *handle, blitter *bl, int x, int y) +static void gtk_blitter_save(void *handle, blitter *bl, int x, int y) { frontend *fe = (frontend *)handle; do_blitter_save(fe, bl, x, y); @@ -1243,7 +1281,7 @@ void gtk_blitter_save(void *handle, blitter *bl, int x, int y) bl->y = y; } -void gtk_blitter_load(void *handle, blitter *bl, int x, int y) +static void gtk_blitter_load(void *handle, blitter *bl, int x, int y) { frontend *fe = (frontend *)handle; if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) { @@ -1253,7 +1291,7 @@ void gtk_blitter_load(void *handle, blitter *bl, int x, int y) do_blitter_load(fe, bl, x, y); } -void gtk_draw_update(void *handle, int x, int y, int w, int h) +static void gtk_draw_update(void *handle, int x, int y, int w, int h) { frontend *fe = (frontend *)handle; if (fe->bbox_l > x ) fe->bbox_l = x ; @@ -1262,7 +1300,7 @@ void gtk_draw_update(void *handle, int x, int y, int w, int h) if (fe->bbox_d < y+h) fe->bbox_d = y+h; } -void gtk_end_draw(void *handle) +static void gtk_end_draw(void *handle) { frontend *fe = (frontend *)handle; @@ -1286,7 +1324,8 @@ void gtk_end_draw(void *handle) } #ifdef USE_PANGO -char *gtk_text_fallback(void *handle, const char *const *strings, int nstrings) +static char *gtk_text_fallback(void *handle, const char *const *strings, + int nstrings) { /* * We assume Pango can cope with any UTF-8 likely to be emitted @@ -1297,18 +1336,18 @@ char *gtk_text_fallback(void *handle, const char *const *strings, int nstrings) #endif #ifdef USE_PRINTING -void gtk_begin_doc(void *handle, int pages) +static void gtk_begin_doc(void *handle, int pages) { frontend *fe = (frontend *)handle; gtk_print_operation_set_n_pages(fe->printop, pages); } -void gtk_begin_page(void *handle, int number) +static void gtk_begin_page(void *handle, int number) { } -void gtk_begin_puzzle(void *handle, float xm, float xc, - float ym, float yc, int pw, int ph, float wmm) +static void gtk_begin_puzzle(void *handle, float xm, float xc, + float ym, float yc, int pw, int ph, float wmm) { frontend *fe = (frontend *)handle; double ppw, pph, pox, poy, dpmmx, dpmmy; @@ -1346,27 +1385,27 @@ void gtk_begin_puzzle(void *handle, float xm, float xc, fe->hatchspace = 1.0 * pw / wmm; } -void gtk_end_puzzle(void *handle) +static void gtk_end_puzzle(void *handle) { frontend *fe = (frontend *)handle; cairo_restore(fe->cr); } -void gtk_end_page(void *handle, int number) +static void gtk_end_page(void *handle, int number) { } -void gtk_end_doc(void *handle) +static void gtk_end_doc(void *handle) { } -void gtk_line_width(void *handle, float width) +static void gtk_line_width(void *handle, float width) { frontend *fe = (frontend *)handle; cairo_set_line_width(fe->cr, width); } -void gtk_line_dotted(void *handle, bool dotted) +static void gtk_line_dotted(void *handle, bool dotted) { frontend *fe = (frontend *)handle; @@ -1379,7 +1418,7 @@ void gtk_line_dotted(void *handle, bool dotted) } #endif /* USE_PRINTING */ -const struct internal_drawing_api internal_drawing = { +static const struct internal_drawing_api internal_drawing = { draw_set_colour, #ifdef USE_CAIRO do_draw_fill, @@ -1388,14 +1427,14 @@ const struct internal_drawing_api internal_drawing = { }; #ifdef USE_CAIRO -const struct internal_drawing_api internal_printing = { +static const struct internal_drawing_api internal_printing = { print_set_colour, do_print_fill, do_print_fill_preserve, }; #endif -const struct drawing_api gtk_drawing = { +static const struct drawing_api gtk_drawing = { gtk_draw_text, gtk_draw_rect, gtk_draw_line, @@ -1502,13 +1541,18 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) keyval = '\177'; else if ((event->keyval == 'z' || event->keyval == 'Z') && shift && ctrl) keyval = UI_REDO; + else if (event->keyval == GDK_KEY_ISO_Left_Tab) { + /* SHIFT+TAB gets special handling. Ref: + * https://mail.gnome.org/archives/gtk-list/1999-August/msg00145.html */ + keyval = '\t' | MOD_SHFT; + } else if (event->string[0] && !event->string[1]) keyval = (unsigned char)event->string[0]; else keyval = -1; if (keyval >= 0 && - !midend_process_key(fe->me, 0, 0, keyval)) + midend_process_key(fe->me, 0, 0, keyval) == PKR_QUIT) gtk_widget_destroy(fe->window); return true; @@ -1542,8 +1586,8 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, if (event->type == GDK_BUTTON_RELEASE && button >= LEFT_BUTTON) button += LEFT_RELEASE - LEFT_BUTTON; - if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button)) + if (midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button) == PKR_QUIT) gtk_widget_destroy(fe->window); return true; @@ -1567,8 +1611,8 @@ static gint motion_event(GtkWidget *widget, GdkEventMotion *event, else return false; /* don't even know what button! */ - if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button)) + if (midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button) == PKR_QUIT) gtk_widget_destroy(fe->window); #if GTK_CHECK_VERSION(2,12,0) gdk_event_request_motions(event); @@ -1649,7 +1693,7 @@ static void resize_puzzle_to_area(frontend *fe, int x, int y) fe->w = x; fe->h = y; - midend_size(fe->me, &x, &y, true); + midend_size(fe->me, &x, &y, true, 1.0); fe->pw = x; fe->ph = y; #if GTK_CHECK_VERSION(3,10,0) @@ -1773,8 +1817,8 @@ static void align_label(GtkLabel *label, double x, double y) } #if GTK_CHECK_VERSION(3,0,0) -bool message_box(GtkWidget *parent, const char *title, const char *msg, - bool centre, int type) +static bool message_box(GtkWidget *parent, const char *title, const char *msg, + bool centre, int type) { GtkWidget *window; gint ret; @@ -1807,7 +1851,7 @@ bool message_box(GtkWidget *parent, const char *title, const char *msg, bool centre, int type) { GtkWidget *window, *hbox, *text, *button; - char *titles; + const char *titles; int i, def, cancel; window = gtk_dialog_new(); @@ -1868,7 +1912,7 @@ bool message_box(GtkWidget *parent, const char *title, const char *msg, } #endif /* GTK_CHECK_VERSION(3,0,0) */ -void error_box(GtkWidget *parent, const char *msg) +static void error_box(GtkWidget *parent, const char *msg) { message_box(parent, "Error", msg, false, MB_OK); } @@ -1883,9 +1927,17 @@ static void config_ok_button_clicked(GtkButton *button, gpointer data) if (err) error_box(fe->cfgbox, err); else { + if (fe->cfg_which == CFG_PREFS) { + char *prefs_err = save_prefs(fe); + if (prefs_err) { + error_box(fe->cfgbox, prefs_err); + sfree(prefs_err); + } + } fe->cfgret = true; gtk_widget_destroy(fe->cfgbox); - changed_preset(fe); + if (fe->cfg_which != CFG_PREFS) + changed_preset(fe); } } @@ -2163,7 +2215,7 @@ static void menu_key_event(GtkMenuItem *menuitem, gpointer data) frontend *fe = (frontend *)data; int key = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "user-data")); - if (!midend_process_key(fe->me, 0, 0, key)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) gtk_widget_destroy(fe->window); } @@ -2185,7 +2237,7 @@ static void get_size(frontend *fe, int *px, int *py) */ x = INT_MAX; y = INT_MAX; - midend_size(fe->me, &x, &y, false); + midend_size(fe->me, &x, &y, false, 1.0); *px = x; *py = y; } @@ -2362,8 +2414,8 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data) midend_redraw(fe->me); } -GdkAtom compound_text_atom, utf8_string_atom; -bool paste_initialised = false; +static GdkAtom compound_text_atom, utf8_string_atom; +static bool paste_initialised = false; static void set_selection(frontend *fe, GdkAtom selection) { @@ -2380,16 +2432,16 @@ static void set_selection(frontend *fe, GdkAtom selection) * COMPOUND_TEXT or UTF8_STRING. */ - if (gtk_selection_owner_set(fe->area, selection, CurrentTime)) { - gtk_selection_clear_targets(fe->area, selection); - gtk_selection_add_target(fe->area, selection, + if (gtk_selection_owner_set(fe->window, selection, CurrentTime)) { + gtk_selection_clear_targets(fe->window, selection); + gtk_selection_add_target(fe->window, selection, GDK_SELECTION_TYPE_STRING, 1); - gtk_selection_add_target(fe->area, selection, compound_text_atom, 1); - gtk_selection_add_target(fe->area, selection, utf8_string_atom, 1); + gtk_selection_add_target(fe->window, selection, compound_text_atom, 1); + gtk_selection_add_target(fe->window, selection, utf8_string_atom, 1); } } -void write_clip(frontend *fe, char *data) +static void write_clip(frontend *fe, char *data) { if (fe->paste_data) sfree(fe->paste_data); @@ -2401,16 +2453,16 @@ void write_clip(frontend *fe, char *data) set_selection(fe, GDK_SELECTION_CLIPBOARD); } -void selection_get(GtkWidget *widget, GtkSelectionData *seldata, - guint info, guint time_stamp, gpointer data) +static void selection_get(GtkWidget *widget, GtkSelectionData *seldata, + guint info, guint time_stamp, gpointer data) { frontend *fe = (frontend *)data; gtk_selection_data_set(seldata, gtk_selection_data_get_target(seldata), 8, fe->paste_data, fe->paste_data_len); } -gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata, - gpointer data) +static gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata, + gpointer data) { frontend *fe = (frontend *)data; @@ -2508,7 +2560,7 @@ static char *file_selector(frontend *fe, const char *title, bool save) #endif #ifdef USE_PRINTING -GObject *create_print_widget(GtkPrintOperation *print, gpointer data) +static GObject *create_print_widget(GtkPrintOperation *print, gpointer data) { GtkLabel *count_label, *width_label, *height_label, *scale_llabel, *scale_rlabel; @@ -2649,8 +2701,8 @@ GObject *create_print_widget(GtkPrintOperation *print, gpointer data) return G_OBJECT(grid); } -void apply_print_widget(GtkPrintOperation *print, - GtkWidget *widget, gpointer data) +static void apply_print_widget(GtkPrintOperation *print, + GtkWidget *widget, gpointer data) { frontend *fe = (frontend *)data; @@ -2673,8 +2725,8 @@ void apply_print_widget(GtkPrintOperation *print, } } -void print_begin(GtkPrintOperation *printop, - GtkPrintContext *context, gpointer data) +static void print_begin(GtkPrintOperation *printop, + GtkPrintContext *context, gpointer data) { frontend *fe = (frontend *)data; midend *nme = NULL; /* non-interactive midend for bulk puzzle generation */ @@ -2708,6 +2760,8 @@ void print_begin(GtkPrintOperation *printop, thegame.free_params(params); } + load_prefs(fe); + midend_new_game(nme); err = midend_print_puzzle(nme, fe->doc, fe->printsolns); } @@ -2725,16 +2779,16 @@ void print_begin(GtkPrintOperation *printop, document_begin(fe->doc, fe->print_dr); } -void draw_page(GtkPrintOperation *printop, - GtkPrintContext *context, - gint page_nr, gpointer data) +static void draw_page(GtkPrintOperation *printop, + GtkPrintContext *context, + gint page_nr, gpointer data) { frontend *fe = (frontend *)data; document_print_page(fe->doc, fe->print_dr, page_nr); } -void print_end(GtkPrintOperation *printop, - GtkPrintContext *context, gpointer data) +static void print_end(GtkPrintOperation *printop, + GtkPrintContext *context, gpointer data) { frontend *fe = (frontend *)data; @@ -2919,6 +2973,206 @@ static void menu_load_event(GtkMenuItem *menuitem, gpointer data) } } +static char *prefs_dir(void) +{ + const char *var; + if ((var = getenv("SGT_PUZZLES_DIR")) != NULL) + return dupstr(var); + if ((var = getenv("XDG_CONFIG_HOME")) != NULL) { + size_t size = strlen(var) + 20; + char *dir = snewn(size, char); + sprintf(dir, "%s/sgt-puzzles", var); + return dir; + } + if ((var = getenv("HOME")) != NULL) { + size_t size = strlen(var) + 32; + char *dir = snewn(size, char); + sprintf(dir, "%s/.config/sgt-puzzles", var); + return dir; + } + return NULL; +} + +static char *prefs_path_general(const game *game, const char *suffix) +{ + char *dir, *path; + + dir = prefs_dir(); + if (!dir) + return NULL; + + path = make_prefs_path(dir, "/", game, suffix); + + sfree(dir); + return path; +} + +static char *prefs_path(const game *game) +{ + return prefs_path_general(game, ".conf"); +} + +static char *prefs_tmp_path(const game *game) +{ + return prefs_path_general(game, ".conf.tmp"); +} + +static void load_prefs(frontend *fe) +{ + const game *game = midend_which_game(fe->me); + char *path = prefs_path(game); + if (!path) + return; + FILE *fp = fopen(path, "r"); + if (!fp) + return; + const char *err = midend_load_prefs(fe->me, savefile_read, fp); + fclose(fp); + if (err) + fprintf(stderr, "Unable to load preferences file %s:\n%s\n", + path, err); + sfree(path); +} + +static char *save_prefs(frontend *fe) +{ + const game *game = midend_which_game(fe->me); + char *dir_path = prefs_dir(); + char *file_path = prefs_path(game); + char *tmp_path = prefs_tmp_path(game); + struct savefile_write_ctx wctx[1]; + int fd; + bool cleanup_dir = false, cleanup_tmpfile = false; + char *err = NULL; + + if (!dir_path || !file_path || !tmp_path) { + sprintf(err = snewn(256, char), + "Unable to save preferences:\n" + "Could not determine pathname for configuration files"); + goto out; + } + + if (mkdir(dir_path, 0777) < 0) { + /* Ignore errors while trying to make the directory. It may + * well already exist, and even if we got some error code + * other than EEXIST, it's still worth at least _trying_ to + * make the file inside it, and see if that goes wrong. */ + } else { + cleanup_dir = true; + } + + fd = open(tmp_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666); + if (fd < 0) { + const char *os_err = strerror(errno); + sprintf(err = snewn(256 + strlen(tmp_path) + strlen(os_err), char), + "Unable to save preferences:\n" + "Unable to create file '%s': %s", tmp_path, os_err); + goto out; + } else { + cleanup_tmpfile = true; + } + + wctx->error = 0; + wctx->fp = fdopen(fd, "w"); + midend_save_prefs(fe->me, savefile_write, wctx); + fclose(wctx->fp); + if (wctx->error) { + const char *os_err = strerror(wctx->error); + sprintf(err = snewn(80 + strlen(tmp_path) + strlen(os_err), char), + "Unable to write file '%s': %s", tmp_path, os_err); + goto out; + } + + if (rename(tmp_path, file_path) < 0) { + const char *os_err = strerror(errno); + sprintf(err = snewn(256 + strlen(tmp_path) + strlen(file_path) + + strlen(os_err), char), + "Unable to save preferences:\n" + "Unable to rename '%s' to '%s': %s", tmp_path, file_path, + os_err); + goto out; + } else { + cleanup_dir = false; + cleanup_tmpfile = false; + } + + out: + if (cleanup_tmpfile) { + if (unlink(tmp_path) < 0) { /* can't do anything about this */ } + } + if (cleanup_dir) { + if (rmdir(dir_path) < 0) { /* can't do anything about this */ } + } + sfree(dir_path); + sfree(file_path); + sfree(tmp_path); + return err; +} + +static bool delete_prefs(const game *game, char **msg) +{ + char *dir_path = prefs_dir(); + char *file_path = prefs_path(game); + char *tmp_path = prefs_tmp_path(game); + char *msgs[3]; + int i, len, nmsgs = 0; + char *p; + bool ok = true; + + if (unlink(file_path) == 0) { + sprintf(msgs[nmsgs++] = snewn(256 + strlen(file_path), char), + "Removed preferences file %s\n", file_path); + } else if (errno != ENOENT) { + const char *os_err = strerror(errno); + sprintf(msgs[nmsgs++] = snewn(256 + strlen(file_path) + strlen(os_err), + char), + "Failed to remove preferences file %s: %s\n", + file_path, os_err); + ok = false; + } + + if (unlink(tmp_path) == 0) { + sprintf(msgs[nmsgs++] = snewn(256 + strlen(tmp_path), char), + "Removed temporary file %s\n", tmp_path); + } else if (errno != ENOENT) { + const char *os_err = strerror(errno); + sprintf(msgs[nmsgs++] = snewn(256 + strlen(tmp_path) + strlen(os_err), + char), + "Failed to remove temporary file %s: %s\n", tmp_path, os_err); + ok = false; + } + + if (rmdir(dir_path) == 0) { + sprintf(msgs[nmsgs++] = snewn(256 + strlen(dir_path), char), + "Removed empty preferences directory %s\n", dir_path); + } else if (errno != ENOENT && errno != ENOTEMPTY) { + const char *os_err = strerror(errno); + sprintf(msgs[nmsgs++] = snewn(256 + strlen(dir_path) + strlen(os_err), + char), + "Failed to remove preferences directory %s: %s\n", + dir_path, os_err); + ok = false; + } + + for (i = len = 0; i < nmsgs; i++) + len += strlen(msgs[i]); + *msg = snewn(len + 1, char); + p = *msg; + for (i = len = 0; i < nmsgs; i++) { + size_t len = strlen(msgs[i]); + memcpy(p, msgs[i], len); + p += len; + sfree(msgs[i]); + } + *p = '\0'; + + sfree(dir_path); + sfree(file_path); + sfree(tmp_path); + + return ok; +} + #ifdef USE_PRINTING static void menu_print_event(GtkMenuItem *menuitem, gpointer data) { @@ -2960,11 +3214,85 @@ static void menu_config_event(GtkMenuItem *menuitem, gpointer data) if (!get_config(fe, which)) return; - midend_new_game(fe->me); + if (which != CFG_PREFS) + midend_new_game(fe->me); + resize_fe(fe); midend_redraw(fe->me); } +#ifndef HELP_BROWSER_PATH +#define HELP_BROWSER_PATH "xdg-open:sensible-browser:$BROWSER" +#endif + +static bool try_show_help(const char *browser, const char *help_name) +{ + const char *argv[3] = { browser, help_name, NULL }; + + return g_spawn_async(NULL, (char **)argv, NULL, + G_SPAWN_SEARCH_PATH, + NULL, NULL, NULL, NULL); +} + +static void show_help(frontend *fe, const char *topic) +{ + char *path = dupstr(HELP_BROWSER_PATH); + char *path_entry; + char *help_name; + size_t help_name_size; + bool succeeded = true; + + help_name_size = strlen(HELP_DIR) + 4 + strlen(topic) + 6; + help_name = snewn(help_name_size, char); + sprintf(help_name, "%s/en/%s.html", + HELP_DIR, topic); + + if (access(help_name, R_OK)) { + error_box(fe->window, "Help file is not installed"); + sfree(path); + sfree(help_name); + return; + } + + path_entry = path; + for (;;) { + size_t len; + bool last; + + len = strcspn(path_entry, ":"); + last = path_entry[len] == 0; + path_entry[len] = 0; + + if (path_entry[0] == '$') { + const char *command = getenv(path_entry + 1); + + if (command) + succeeded = try_show_help(command, help_name); + } else { + succeeded = try_show_help(path_entry, help_name); + } + + if (last || succeeded) + break; + path_entry += len + 1; + } + + if (!succeeded) + error_box(fe->window, "Failed to start a help browser"); + sfree(path); + sfree(help_name); +} + +static void menu_help_contents_event(GtkMenuItem *menuitem, gpointer data) +{ + show_help((frontend *)data, "index"); +} + +static void menu_help_specific_event(GtkMenuItem *menuitem, gpointer data) +{ + show_help((frontend *)data, thegame.htmlhelp_topic); +} + static void menu_about_event(GtkMenuItem *menuitem, gpointer data) { frontend *fe = (frontend *)data; @@ -2975,12 +3303,9 @@ static void menu_about_event(GtkMenuItem *menuitem, gpointer data) "version", ver, \ "comments", "Part of Simon Tatham's Portable Puzzle Collection" - extern char *const *const xpm_icons[]; - extern const int n_xpm_icons; - if (n_xpm_icons) { GdkPixbuf *icon = gdk_pixbuf_new_from_xpm_data - ((const gchar **)xpm_icons[n_xpm_icons-1]); + ((const gchar **)xpm_icons[0]); gtk_show_about_dialog (GTK_WINDOW(fe->window), @@ -3092,8 +3417,6 @@ static frontend *new_window( GList *iconlist; int x, y, n; char errbuf[1024]; - extern char *const *const xpm_icons[]; - extern const int n_xpm_icons; struct preset_menu *preset_menu; fe = snew(frontend); @@ -3113,6 +3436,7 @@ static frontend *new_window( fe->timer_id = -1; fe->me = midend_new(fe, &thegame, >k_drawing, fe); + load_prefs(fe); fe->dr_api = &internal_drawing; @@ -3376,6 +3700,16 @@ static frontend *new_window( G_CALLBACK(menu_solve_event), fe); gtk_widget_show(menuitem); } + + add_menu_separator(GTK_CONTAINER(menu)); + menuitem = gtk_menu_item_new_with_label("Preferences..."); + gtk_container_add(GTK_CONTAINER(menu), menuitem); + g_object_set_data(G_OBJECT(menuitem), "user-data", + GINT_TO_POINTER(CFG_PREFS)); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_config_event), fe); + gtk_widget_show(menuitem); + add_menu_separator(GTK_CONTAINER(menu)); add_menu_ui_item(fe, GTK_CONTAINER(menu), "Exit", UI_QUIT, 'q', 0); @@ -3386,6 +3720,25 @@ static frontend *new_window( menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu); + menuitem = gtk_menu_item_new_with_label("Contents"); + gtk_container_add(GTK_CONTAINER(menu), menuitem); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_help_contents_event), fe); + gtk_widget_show(menuitem); + + if (thegame.htmlhelp_topic) { + char *item; + assert(thegame.name); + item = snewn(9 + strlen(thegame.name), char); + sprintf(item, "Help on %s", thegame.name); + menuitem = gtk_menu_item_new_with_label(item); + sfree(item); + gtk_container_add(GTK_CONTAINER(menu), menuitem); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_help_specific_event), fe); + gtk_widget_show(menuitem); + } + menuitem = gtk_menu_item_new_with_label("About"); gtk_container_add(GTK_CONTAINER(menu), menuitem); g_signal_connect(G_OBJECT(menuitem), "activate", @@ -3503,9 +3856,9 @@ static frontend *new_window( G_CALLBACK(button_event), fe); g_signal_connect(G_OBJECT(fe->area), "motion_notify_event", G_CALLBACK(motion_event), fe); - g_signal_connect(G_OBJECT(fe->area), "selection_get", + g_signal_connect(G_OBJECT(fe->window), "selection_get", G_CALLBACK(selection_get), fe); - g_signal_connect(G_OBJECT(fe->area), "selection_clear_event", + g_signal_connect(G_OBJECT(fe->window), "selection_clear_event", G_CALLBACK(selection_clear), fe); #if GTK_CHECK_VERSION(3,0,0) g_signal_connect(G_OBJECT(fe->area), "draw", @@ -3534,7 +3887,7 @@ static frontend *new_window( if (n_xpm_icons) { gtk_window_set_icon(GTK_WINDOW(fe->window), gdk_pixbuf_new_from_xpm_data - ((const gchar **)xpm_icons[0])); + ((const gchar **)xpm_icons[n_xpm_icons-1])); iconlist = NULL; for (n = 0; n < n_xpm_icons; n++) { @@ -3578,10 +3931,10 @@ static void list_presets_from_menu(struct preset_menu *menu) int main(int argc, char **argv) { char *pname = argv[0]; - char *error; int ngenerate = 0, px = 1, py = 1; bool print = false; bool time_generation = false, test_solve = false, list_presets = false; + bool delete_prefs_action = false; bool soln = false, colour = false; float scale = 1.0F; float redo_proportion = 0.0F; @@ -3640,6 +3993,9 @@ int main(int argc, char **argv) test_solve = true; } else if (doing_opts && !strcmp(p, "--list-presets")) { list_presets = true; + } else if (doing_opts && (!strcmp(p, "--delete-prefs") || + !strcmp(p, "--delete-preferences"))) { + delete_prefs_action = true; } else if (doing_opts && !strcmp(p, "--save")) { if (--ac > 0) { savefile = *++av; @@ -3988,9 +4344,20 @@ int main(int argc, char **argv) list_presets_from_menu(menu); midend_free(me); return 0; + } else if (delete_prefs_action) { + char *msg = NULL; + bool ok = delete_prefs(&thegame, &msg); + if (!ok) { + fputs(msg, stderr); + return 1; + } else { + fputs(msg, stdout); + return 0; + } } else { frontend *fe; bool headless = screenshot_file != NULL; + char *error = NULL; if (!headless) gtk_init(&argc, &argv); @@ -3999,6 +4366,7 @@ int main(int argc, char **argv) if (!fe) { fprintf(stderr, "%s: %s\n", pname, error); + sfree(error); return 1; } @@ -4014,7 +4382,7 @@ int main(int argc, char **argv) if (redo_proportion) { /* Start a redo. */ - midend_process_key(fe->me, 0, 0, 'r'); + midend_process_key(fe->me, 0, 0, 'r'); /* And freeze the timer at the specified position. */ midend_freeze_timer(fe->me, redo_proportion); } diff --git a/apps/plugins/puzzles/src/gtk.h b/apps/plugins/puzzles/src/gtk.h new file mode 100644 index 0000000000..a039f0dc36 --- /dev/null +++ b/apps/plugins/puzzles/src/gtk.h @@ -0,0 +1,7 @@ +#ifndef PUZZLES_GTK_H +#define PUZZLES_GTK_H + +extern const char *const *const xpm_icons[]; +extern const int n_xpm_icons; + +#endif /* PUZZLES_GTK_H */ diff --git a/apps/plugins/puzzles/src/guess.R b/apps/plugins/puzzles/src/guess.R deleted file mode 100644 index 0e1a00c073..0000000000 --- a/apps/plugins/puzzles/src/guess.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -guess : [X] GTK COMMON guess guess-icon|no-icon - -guess : [G] WINDOWS COMMON guess guess.res|noicon.res - -ALL += guess[COMBINED] - -!begin am gtk -GAMES += guess -!end - -!begin >list.c - A(guess) \ -!end - -!begin >gamedesc.txt -guess:guess.exe:Guess:Combination-guessing puzzle:Guess the hidden combination of colours. -!end diff --git a/apps/plugins/puzzles/src/guess.c b/apps/plugins/puzzles/src/guess.c index a501579442..5c5f941230 100644 --- a/apps/plugins/puzzles/src/guess.c +++ b/apps/plugins/puzzles/src/guess.c @@ -7,7 +7,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -35,6 +39,11 @@ typedef struct pegrow { int *pegs; /* 0 is 'empty' */ int *feedback; /* may well be unused */ } *pegrow; +/* Pegs can have these flags OR'ed into them. */ +#define PEG_CURSOR 0x1000 +#define PEG_HOLD 0x2000 +#define PEG_LABELLED 0x4000 +#define PEG_FLAGS (PEG_CURSOR | PEG_HOLD | PEG_LABELLED) struct game_state { game_params params; @@ -88,13 +97,7 @@ static bool game_fetch_preset(int i, char **name, game_params **params) return false; *name = dupstr(guess_presets[i].name); - /* - * get round annoying const issues - */ - { - game_params tmp = guess_presets[i].params; - *params = dup_params(&tmp); - } + *params = dup_params(&guess_presets[i].params); return true; } @@ -365,16 +368,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return dupstr("S"); } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - static bool is_markable(const game_params *params, pegrow pegs) { int i, nset = 0, nrequired; @@ -386,6 +379,7 @@ static bool is_markable(const game_params *params, pegrow pegs) for (i = 0; i < params->npegs; i++) { int c = pegs->pegs[i]; if (c > 0) { + assert(c <= params->ncolours); colcount->pegs[c-1]++; nset++; } @@ -414,7 +408,7 @@ struct game_ui { int drag_col, drag_x, drag_y; /* x and y are *center* of peg! */ int drag_opeg; /* peg index, if dragged from a peg (from current guess), otherwise -1 */ - bool show_labels; /* label the colours with letters */ + bool show_labels; /* label the colours with numbers */ pegrow hint; }; @@ -422,19 +416,45 @@ static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); memset(ui, 0, sizeof(game_ui)); - ui->params = state->params; /* structure copy */ - ui->curr_pegs = new_pegrow(state->params.npegs); - ui->holds = snewn(state->params.npegs, bool); - memset(ui->holds, 0, sizeof(bool)*state->params.npegs); + if (state != NULL) { + ui->params = state->params; /* structure copy */ + ui->curr_pegs = new_pegrow(state->params.npegs); + ui->holds = snewn(state->params.npegs, bool); + memset(ui->holds, 0, sizeof(bool)*state->params.npegs); + } + ui->display_cur = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->drag_opeg = -1; return ui; } +static config_item *get_prefs(game_ui *ui) +{ + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Label colours with numbers"; + ret[0].kw = "show-labels"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->show_labels; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; +} + +static void set_prefs(game_ui *ui, const config_item *cfg) +{ + ui->show_labels = cfg[0].u.boolean.bval; +} + static void free_ui(game_ui *ui) { if (ui->hint) free_pegrow(ui->hint); - free_pegrow(ui->curr_pegs); + if (ui->curr_pegs) + free_pegrow(ui->curr_pegs); sfree(ui->holds); sfree(ui); } @@ -462,12 +482,16 @@ static char *encode_ui(const game_ui *ui) return sresize(ret, p - ret, char); } -static void decode_ui(game_ui *ui, const char *encoding) +static void decode_ui(game_ui *ui, const char *encoding, + const game_state *state) { int i; const char *p = encoding; for (i = 0; i < ui->curr_pegs->npegs; i++) { ui->curr_pegs->pegs[i] = atoi(p); + if (ui->curr_pegs->pegs[i] < 0 || + ui->curr_pegs->pegs[i] > ui->params.ncolours) + ui->curr_pegs->pegs[i] = 0; /* Remove invalid pegs. */ while (*p && isdigit((unsigned char)*p)) p++; if (*p == '_') { /* NB: old versions didn't store holds */ @@ -507,7 +531,20 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->markable = is_markable(&newstate->params, ui->curr_pegs); /* Clean up cursor position */ if (!ui->markable && ui->peg_cur == newstate->solution->npegs) - ui->peg_cur--; + ui->peg_cur = 0; +} + +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (state->solved) return ""; + if (button == CURSOR_SELECT) { + if (ui->peg_cur == state->params.npegs) return "Submit"; + return "Place"; + } + if (button == CURSOR_SELECT2 && ui->peg_cur != state->params.npegs) + return "Hold"; + return ""; } #define PEGSZ (ds->pegsz) @@ -700,7 +737,11 @@ static void compute_hint(const game_state *state, game_ui *ui) for (j = 0; j < state->params.npegs; ++j) if (state->guesses[i]->pegs[j] > maxcolour) maxcolour = state->guesses[i]->pegs[j]; - maxcolour = min(maxcolour + 1, state->params.ncolours); + if (state->params.allow_multiple) + maxcolour = min(maxcolour + 1, state->params.ncolours); + else + maxcolour = min(maxcolour + state->params.npegs, + state->params.ncolours); increase_mincolour: for (i = 0; i < state->next_go; ++i) { @@ -722,6 +763,7 @@ increase_mincolour: } while (ui->hint->pegs[0] <= state->params.ncolours) { + if (!is_markable(&state->params, ui->hint)) goto increment_pegrow; for (i = 0; i < state->next_go; ++i) { mark_pegs(ui->hint, state->guesses[i], maxcolour); for (j = 0; j < state->params.npegs; ++j) @@ -777,7 +819,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, */ if (button == 'l' || button == 'L') { ui->show_labels = !ui->show_labels; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (from->solved) return NULL; @@ -834,13 +876,13 @@ static char *interpret_move(const game_state *from, game_ui *ui, ui->drag_y = y; debug(("Start dragging, col = %d, (%d,%d)", ui->drag_col, ui->drag_x, ui->drag_y)); - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } } else if (button == LEFT_DRAG && ui->drag_col) { ui->drag_x = x; ui->drag_y = y; debug(("Keep dragging, (%d,%d)", ui->drag_x, ui->drag_y)); - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } else if (button == LEFT_RELEASE && ui->drag_col) { if (over_guess > -1) { debug(("Dropping colour %d onto guess peg %d", @@ -857,13 +899,13 @@ static char *interpret_move(const game_state *from, game_ui *ui, ui->drag_opeg = -1; ui->display_cur = false; debug(("Stop dragging.")); - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } else if (button == RIGHT_BUTTON) { if (over_guess > -1) { /* we use ths feedback in the game_ui to signify * 'carry this peg to the next guess as well'. */ ui->holds[over_guess] ^= 1; - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } } else if (button == LEFT_RELEASE && over_hint && ui->markable) { /* NB this won't trigger if on the end of a drag; that's on @@ -872,44 +914,47 @@ static char *interpret_move(const game_state *from, game_ui *ui, } /* keyboard input */ - if (button == CURSOR_UP || button == CURSOR_DOWN) { - ui->display_cur = true; - if (button == CURSOR_DOWN && (ui->colour_cur+1) < from->params.ncolours) - ui->colour_cur++; - if (button == CURSOR_UP && ui->colour_cur > 0) - ui->colour_cur--; - ret = UI_UPDATE; - } else if (button == 'h' || button == 'H' || button == '?') { - compute_hint(from, ui); - ret = UI_UPDATE; - } else if (button == CURSOR_LEFT || button == CURSOR_RIGHT) { + if (IS_CURSOR_MOVE(button)) { int maxcur = from->params.npegs; if (ui->markable) maxcur++; - ui->display_cur = true; - if (button == CURSOR_RIGHT && (ui->peg_cur+1) < maxcur) - ui->peg_cur++; - if (button == CURSOR_LEFT && ui->peg_cur > 0) - ui->peg_cur--; - ret = UI_UPDATE; - } else if (IS_CURSOR_SELECT(button)) { + ret = move_cursor(button, &ui->peg_cur, &ui->colour_cur, + maxcur, from->params.ncolours, + false, &ui->display_cur); + } else if (button == 'h' || button == 'H' || button == '?') { + compute_hint(from, ui); + ret = MOVE_UI_UPDATE; + } else if (button == CURSOR_SELECT) { ui->display_cur = true; if (ui->peg_cur == from->params.npegs) { ret = encode_move(from, ui); } else { set_peg(&from->params, ui, ui->peg_cur, ui->colour_cur+1); - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } - } else if (button == 'D' || button == 'd' || button == '\b') { + } else if (((button >= '1' && button <= '0' + from->params.ncolours) || + (button == '0' && from->params.ncolours == 10)) && + ui->peg_cur < from->params.npegs) { ui->display_cur = true; - set_peg(&from->params, ui, ui->peg_cur, 0); - ret = UI_UPDATE; + /* Number keys insert a peg and advance the cursor. */ + set_peg(&from->params, ui, ui->peg_cur, + button == '0' ? 10 : button - '0'); + if (ui->peg_cur + 1 < from->params.npegs + ui->markable) + ui->peg_cur++; + ret = MOVE_UI_UPDATE; + } else if (button == 'D' || button == 'd' || button == '\b') { + if (!ui->display_cur || ui->curr_pegs->pegs[ui->peg_cur] != 0) { + ui->display_cur = true; + set_peg(&from->params, ui, ui->peg_cur, 0); + ret = MOVE_UI_UPDATE; + } else + ret = MOVE_NO_EFFECT; } else if (button == CURSOR_SELECT2) { if (ui->peg_cur == from->params.npegs) return NULL; ui->display_cur = true; ui->holds[ui->peg_cur] ^= 1; - ret = UI_UPDATE; + ret = MOVE_UI_UPDATE; } return ret; } @@ -925,6 +970,8 @@ static game_state *execute_move(const game_state *from, const char *move) ret->solved = -1; return ret; } else if (move[0] == 'G') { + /* No guesses are allowed once the game is solved. */ + if (from->solved) return NULL; p = move+1; ret = dup_game(from); @@ -975,7 +1022,7 @@ static game_state *execute_move(const game_state *from, const char *move) #define BORDER 0.5 static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { double hmul, vmul_c, vmul_g, vmul; int hintw = (params->npegs+1)/2; @@ -1019,7 +1066,8 @@ static void game_set_size(drawing *dr, game_drawstate *ds, guessh = ((ds->pegsz + ds->gapsz) * params->nguesses); /* guesses */ guessh += ds->gapsz + ds->pegsz; /* solution */ - game_compute_size(params, tilesize, &ds->w, &ds->h); + /* We know we don't need anything from the game_ui we haven't got */ + game_compute_size(params, tilesize, NULL, &ds->w, &ds->h); ds->colx = ds->border; ds->coly = (ds->h - colh) / 2; @@ -1196,7 +1244,7 @@ static void draw_peg(drawing *dr, game_drawstate *ds, int cx, int cy, if (labelled && col) { char buf[2]; - buf[0] = 'a'-1 + col; + buf[0] = '0' + (col % 10); buf[1] = '\0'; draw_text(dr, cx+PEGRAD, cy+PEGRAD, FONT_VARIABLE, PEGRAD, ALIGN_HCENTRE|ALIGN_VCENTRE, COL_FRAME, buf); @@ -1233,23 +1281,25 @@ static void guess_redraw(drawing *dr, game_drawstate *ds, int guess, for (i = 0; i < dest->npegs; i++) { scol = src ? src->pegs[i] : 0; if (i == cur_col) - scol |= 0x1000; + scol |= PEG_CURSOR; if (holds && holds[i]) - scol |= 0x2000; + scol |= PEG_HOLD; if (labelled) - scol |= 0x4000; + scol |= PEG_LABELLED; if ((dest->pegs[i] != scol) || force) { draw_peg(dr, ds, rowx + PEGOFF * i, rowy, false, labelled, - scol &~ 0x7000); + scol &~ PEG_FLAGS); + if (scol & PEG_CURSOR) + draw_cursor(dr, ds, rowx + PEGOFF * i, rowy); /* * Hold marker. */ - draw_rect(dr, rowx + PEGOFF * i, rowy + PEGSZ + ds->gapsz/2, - PEGSZ, 2, (scol & 0x2000 ? COL_HOLD : COL_BACKGROUND)); - draw_update(dr, rowx + PEGOFF * i, rowy + PEGSZ + ds->gapsz/2, - PEGSZ, 2); - if (scol & 0x1000) - draw_cursor(dr, ds, rowx + PEGOFF * i, rowy); + if (scol & PEG_HOLD) { + draw_rect(dr, rowx + PEGOFF * i, + rowy + PEGSZ + ds->gapsz/2 - 2, PEGSZ, 2, COL_HOLD); + } + draw_update(dr, rowx + PEGOFF * i, + rowy + PEGSZ + ds->gapsz/2 - 2, PEGSZ, 2); } dest->pegs[i] = scol; } @@ -1276,9 +1326,9 @@ static void hint_redraw(drawing *dr, game_drawstate *ds, int guess, for (i = 0; i < dest->npegs; i++) { scol = src ? src->feedback[i] : 0; if (i == 0 && cursor) - scol |= 0x1000; + scol |= PEG_CURSOR; if (i == 0 && markable) - scol |= 0x2000; + scol |= PEG_HOLD; if ((scol != dest->feedback[i]) || force) { need_redraw = true; } @@ -1349,7 +1399,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, new_move = (state->next_go != ds->next_go) || !ds->started; if (!ds->started) { - draw_rect(dr, 0, 0, ds->w, ds->h, COL_BACKGROUND); draw_rect(dr, SOLN_OX, SOLN_OY - ds->gapsz - 1, SOLN_W, 2, COL_FRAME); draw_update(dr, 0, 0, ds->w, ds->h); } @@ -1364,19 +1413,18 @@ static void game_redraw(drawing *dr, game_drawstate *ds, for (i = 0; i < state->params.ncolours; i++) { int val = i+1; if (ui->display_cur && ui->colour_cur == i) - val |= 0x1000; + val |= PEG_CURSOR; if (ui->show_labels) - val |= 0x2000; + val |= PEG_HOLD; if (ds->colours->pegs[i] != val) { draw_peg(dr, ds, COL_X(i), COL_Y(i), false, ui->show_labels, i+1); - if (val & 0x1000) + if (val & PEG_CURSOR) draw_cursor(dr, ds, COL_X(i), COL_Y(i)); ds->colours->pegs[i] = val; } } - /* draw the guesses (so far) and the hints - * (in reverse order to avoid trampling holds, and postponing the + /* draw the guesses (so far) and the hints (postponing the * next_go'th to not overrender the top of the circular cursor) */ for (i = state->params.nguesses - 1; i >= 0; i--) { if (i < state->next_go || state->solved) { @@ -1473,19 +1521,6 @@ static int game_status(const game_state *state) return state->solved; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame guess #endif @@ -1506,13 +1541,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + get_prefs, set_prefs, new_ui, free_ui, encode_ui, decode_ui, NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PEG_PREFER_SZ, game_compute_size, game_set_size, @@ -1524,9 +1561,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/hat-internal.h b/apps/plugins/puzzles/src/hat-internal.h new file mode 100644 index 0000000000..2be96327a8 --- /dev/null +++ b/apps/plugins/puzzles/src/hat-internal.h @@ -0,0 +1,271 @@ +/* + * Internal definitions for the hat.c tiling generator, shared between + * hat.c itself and hat-test.c. + */ + +#include "puzzles.h" + +/* + * Coordinate system: + * + * The output of this code lives on the tiling known to grid.c as + * 'Kites', which can be viewed as a tiling of hexagons each of which + * is subdivided into six kites sharing their pointy vertex, or + * (equivalently) a tiling of equilateral triangles each subdivided + * into three kits sharing their blunt vertex. + * + * We express coordinates in this system relative to the basis (1, r) + * where r = (1 + sqrt(3)i) / 2 is a primitive 6th root of unity. This + * gives us a system in which two integer coordinates can address any + * grid point, provided we scale up so that the side length of the + * equilateral triangles in the tiling is 6. + */ + +typedef struct Point { + int x, y; /* represents x + yr */ +} Point; + +static inline Point pointscale(int scale, Point a) +{ + Point r = { scale * a.x, scale * a.y }; + return r; +} + +static inline Point pointadd(Point a, Point b) +{ + Point r = { a.x + b.x, a.y + b.y }; + return r; +} + +/* + * We identify a single kite by the coordinates of its four vertices. + * This allows us to construct the coordinates of an adjacent kite by + * taking affine transformations of the original kite's vertices. + * + * This is a useful way to do it because it means that if you reflect + * the kite (by swapping its left and right vertices) then these + * transformations also perform in a reflected way. This will be + * useful in the code below that outputs the coordinates of each hat, + * because this way it can work by walking around its 8 kites using a + * fixed set of steps, and if the hat is reflected, then we just + * reflect the starting kite before doing that, and everything still + * works. + */ + +typedef struct Kite { + Point centre, left, right, outer; +} Kite; + +static inline Kite kite_left(Kite k) +{ + Kite r; + r.centre = k.centre; + r.right = k.left; + r.outer = pointadd(pointscale(2, k.left), pointscale(-1, k.outer)); + r.left = pointadd(pointadd(k.centre, k.left), pointscale(-1, k.right)); + return r; +} + +static inline Kite kite_right(Kite k) +{ + Kite r; + r.centre = k.centre; + r.left = k.right; + r.outer = pointadd(pointscale(2, k.right), pointscale(-1, k.outer)); + r.right = pointadd(pointadd(k.centre, k.right), pointscale(-1, k.left)); + return r; +} + +static inline Kite kite_forward_left(Kite k) +{ + Kite r; + r.outer = k.outer; + r.right = k.left; + r.centre = pointadd(pointscale(2, k.left), pointscale(-1, k.centre)); + r.left = pointadd(pointadd(k.right, k.left), pointscale(-1, k.centre)); + return r; +} + +static inline Kite kite_forward_right(Kite k) +{ + Kite r; + r.outer = k.outer; + r.left = k.right; + r.centre = pointadd(pointscale(2, k.right), pointscale(-1, k.centre)); + r.right = pointadd(pointadd(k.left, k.right), pointscale(-1, k.centre)); + return r; +} + +typedef enum KiteStep { KS_LEFT, KS_RIGHT, KS_F_LEFT, KS_F_RIGHT } KiteStep; + +static inline Kite kite_step(Kite k, KiteStep step) +{ + switch (step) { + case KS_LEFT: return kite_left(k); + case KS_RIGHT: return kite_right(k); + case KS_F_LEFT: return kite_forward_left(k); + default /* case KS_F_RIGHT */: return kite_forward_right(k); + } +} + +/* + * Functiond to enumerate the kites in a rectangular region, in a + * serpentine-raster fashion so that every kite delivered shares an + * edge with a recent previous one. + */ +#define KE_NKEEP 3 +typedef struct KiteEnum { + /* Fields private to the enumerator */ + int state; + int x, y, w, h; + unsigned curr_index; + + /* Fields the client can legitimately read out */ + Kite *curr; + Kite recent[KE_NKEEP]; + unsigned last_index; + KiteStep last_step; /* step that got curr from recent[last_index] */ +} KiteEnum; +void hat_kiteenum_first(KiteEnum *s, int w, int h); +bool hat_kiteenum_next(KiteEnum *s); + +/* + * Assorted useful definitions. + */ +typedef enum TileType { TT_H, TT_T, TT_P, TT_F, TT_KITE, TT_HAT } TileType; +static const char tilechars[] = "HTPF"; + +#define HAT_KITES 8 /* number of kites in a hat */ +#define MT_MAXEXPAND 13 /* largest number of metatiles in any expansion */ + +/* + * Definitions for the autogenerated hat-tables.h header file that + * defines all the lookup tables. + */ +typedef struct KitemapEntry { + int kite, hat, meta; /* all -1 if impossible */ +} KitemapEntry; + +typedef struct MetamapEntry { + int meta, meta2; +} MetamapEntry; + +static inline size_t kitemap_index(KiteStep step, unsigned kite, + unsigned hat, unsigned meta) +{ + return step + 4 * (kite + 8 * (hat + 4 * meta)); +} + +static inline size_t metamap_index(unsigned meta, unsigned meta2) +{ + return meta2 * MT_MAXEXPAND + meta; +} + +/* + * Coordinate system for tracking kites within a randomly selected + * part of the recursively expanded hat tiling. + * + * HatCoords will store an array of HatCoord, in little-endian + * arrangement. So hc->c[0] will always have type TT_KITE and index a + * single kite within a hat; hc->c[1] will have type TT_HAT and index + * a hat within a first-order metatile; hc->c[2] will be the smallest + * metatile containing this hat, and hc->c[3, 4, 5, ...] will be + * higher-order metatiles as needed. + * + * The last coordinate stored, hc->c[hc->nc-1], will have a tile type + * but no index (represented by index==-1). This means "we haven't + * decided yet what this level of metatile needs to be". If we need to + * refer to this level during the hatctx_step algorithm, we make it up + * at random, based on a table of what metatiles each type can + * possibly be part of, at what index. + */ +typedef struct HatCoord { + int index; /* index within that tile, or -1 if not yet known */ + TileType type; /* type of this tile */ +} HatCoord; + +typedef struct HatCoords { + HatCoord *c; + size_t nc, csize; +} HatCoords; + +HatCoords *hat_coords_new(void); +void hat_coords_free(HatCoords *hc); +void hat_coords_make_space(HatCoords *hc, size_t size); +HatCoords *hat_coords_copy(HatCoords *hc_in); + +#ifdef HAT_COORDS_DEBUG +static inline void hat_coords_debug(const char *prefix, HatCoords *hc, + const char *suffix) +{ + const char *sep = ""; + static const char *const types[] = {"H","T","P","F","kite","hat"}; + + fputs(prefix, stderr); + for (size_t i = 0; i < hc->nc; i++) { + fprintf(stderr, "%s %s ", sep, types[hc->c[i].type]); + sep = " ."; + if (hc->c[i].index == -1) + fputs("?", stderr); + else + fprintf(stderr, "%d", hc->c[i].index); + } + fputs(suffix, stderr); +} +#else +#define hat_coords_debug(p,c,s) ((void)0) +#endif + +/* + * HatContext is the shared context of a whole run of the algorithm. + * Its 'prototype' HatCoords object represents the coordinates of the + * starting kite, and is extended as necessary; any other HatCoord + * that needs extending will copy the higher-order values from + * ctx->prototype as needed, so that once each choice has been made, + * it remains consistent. + * + * When we're inventing a random piece of tiling in the first place, + * we append to ctx->prototype by choosing a random (but legal) + * higher-level metatile for the current topmost one to turn out to be + * part of. When we're replaying a generation whose parameters are + * already stored, we don't have a random_state, and we make fixed + * decisions if not enough coordinates were provided. + * + * (Of course another approach would be to reject grid descriptions + * that didn't define enough coordinates! But that would involve a + * whole extra iteration over the whole grid region just for + * validation, and that seems like more timewasting than really + * needed. So we tolerate short descriptions, and do something + * deterministic with them.) + */ + +typedef struct HatContext { + random_state *rs; + HatCoords *prototype; +} HatContext; + +void hatctx_init_random(HatContext *ctx, random_state *rs); +void hatctx_cleanup(HatContext *ctx); +HatCoords *hatctx_initial_coords(HatContext *ctx); +void hatctx_extend_coords(HatContext *ctx, HatCoords *hc, size_t n); +HatCoords *hatctx_step(HatContext *ctx, HatCoords *hc_in, KiteStep step); + +/* + * Subroutine of hat_tiling_generate, called for each kite in the grid + * as we iterate over it, to decide whether to generate an output hat + * and pass it to the client. Exposed in this header file so that + * hat-test can reuse it. + * + * We do this by starting from kite #0 of each hat, and tracing round + * the boundary. If the whole boundary is within the caller's bounding + * region, we return it; if it goes off the edge, we don't. + * + * (Of course, every hat we _do_ want to return will have all its + * kites inside the rectangle, so its kite #0 will certainly be caught + * by this iteration.) + */ + +typedef void (*internal_hat_callback_fn)(void *ctx, Kite kite0, HatCoords *hc, + int *coords); +void maybe_report_hat(int w, int h, Kite kite, HatCoords *hc, + internal_hat_callback_fn cb, void *cbctx); diff --git a/apps/plugins/puzzles/src/hat-tables.h b/apps/plugins/puzzles/src/hat-tables.h new file mode 100644 index 0000000000..b55fbb405b --- /dev/null +++ b/apps/plugins/puzzles/src/hat-tables.h @@ -0,0 +1,2120 @@ +/* + * Header file autogenerated by auxiliary/hatgen.c + * + * To regenerate, run 'hatgen --tables > hat-tables.h' + */ + +static const unsigned hats_in_metatile[] = { 4, 1, 2, 2, }; + +static const TileType children_H[] = { + TT_H, TT_H, TT_H, TT_T, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F, +}; +static const TileType children_T[] = { + TT_H, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F, +}; +static const TileType children_P[] = { + TT_H, TT_H, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F, +}; +static const TileType children_F[] = { + TT_H, TT_H, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F, +}; +static const TileType *const children[] = { + children_H, + children_T, + children_P, + children_F, +}; +static const size_t nchildren[] = { + 13, + 7, + 11, + 11, +}; + +static const KitemapEntry kitemap_H[] = { + /* hat #0 in metatile #0 (type H) */ + {1,0,0}, {7,3,0}, {3,0,4}, {4,0,4}, + {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0}, + {3,0,4}, {3,0,0}, {1,0,0}, {5,0,0}, + {2,0,0}, {1,2,1}, {4,0,0}, {6,2,1}, + {3,0,3}, {5,0,0}, {6,2,1}, {3,0,0}, + {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0}, + {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0}, + {6,0,0}, {2,0,3}, {7,1,0}, {0,0,3}, + /* hat #1 in metatile #0 (type H) */ + {1,1,0}, {2,0,5}, {7,1,8}, {0,0,5}, + {3,0,2}, {0,1,0}, {5,1,0}, {2,1,0}, + {7,1,8}, {3,1,0}, {1,1,0}, {5,1,0}, + {2,1,0}, {4,1,8}, {4,1,0}, {0,3,0}, + {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0}, + {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0}, + {5,1,0}, {7,1,0}, {3,0,2}, {4,0,2}, + {6,1,0}, {3,3,0}, {0,0,3}, {7,0,0}, + /* hat #2 in metatile #0 (type H) */ + {1,2,0}, {1,0,7}, {7,1,4}, {6,0,7}, + {3,0,8}, {0,2,0}, {5,2,0}, {2,2,0}, + {7,1,4}, {3,2,0}, {1,2,0}, {5,2,0}, + {2,2,0}, {4,1,4}, {4,2,0}, {6,3,0}, + {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0}, + {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0}, + {5,2,0}, {7,2,0}, {3,0,8}, {4,0,8}, + {6,2,0}, {0,3,0}, {3,1,8}, {4,1,8}, + /* hat #3 in metatile #0 (type H) */ + {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0}, + {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0}, + {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0}, + {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0}, + {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0}, + {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0}, + {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0}, + {0,0,0}, {6,3,0}, {3,1,4}, {4,1,4}, + /* hat #0 in metatile #1 (type H) */ + {1,0,1}, {7,3,1}, {3,0,9}, {4,0,9}, + {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1}, + {3,0,9}, {3,0,1}, {1,0,1}, {5,0,1}, + {2,0,1}, {1,0,10}, {4,0,1}, {6,0,10}, + {0,0,6}, {5,0,1}, {6,0,10}, {3,0,1}, + {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1}, + {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1}, + {6,0,1}, {1,0,6}, {7,1,1}, {6,0,6}, + /* hat #1 in metatile #1 (type H) */ + {1,1,1}, {1,1,2}, {7,0,3}, {6,1,2}, + {0,1,6}, {0,1,1}, {5,1,1}, {2,1,1}, + {7,0,3}, {3,1,1}, {1,1,1}, {5,1,1}, + {2,1,1}, {4,0,3}, {4,1,1}, {0,3,1}, + {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1}, + {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1}, + {5,1,1}, {7,1,1}, {0,1,6}, {7,0,6}, + {6,1,1}, {3,3,1}, {6,0,6}, {7,0,1}, + /* hat #2 in metatile #1 (type H) */ + {1,2,1}, {2,0,4}, {7,1,9}, {0,0,4}, + {3,0,0}, {0,2,1}, {5,2,1}, {2,2,1}, + {7,1,9}, {3,2,1}, {1,2,1}, {5,2,1}, + {2,2,1}, {4,1,9}, {4,2,1}, {6,3,1}, + {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1}, + {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1}, + {5,2,1}, {7,2,1}, {3,0,0}, {4,0,0}, + {6,2,1}, {0,3,1}, {3,0,3}, {4,0,3}, + /* hat #3 in metatile #1 (type H) */ + {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1}, + {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1}, + {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1}, + {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1}, + {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1}, + {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1}, + {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1}, + {0,0,1}, {6,3,1}, {3,1,9}, {4,1,9}, + /* hat #0 in metatile #2 (type H) */ + {1,0,2}, {7,3,2}, {3,0,5}, {4,0,5}, + {4,3,2}, {0,0,2}, {5,0,2}, {2,0,2}, + {3,0,5}, {3,0,2}, {1,0,2}, {5,0,2}, + {2,0,2}, {1,1,0}, {4,0,2}, {6,1,0}, + {0,0,3}, {5,0,2}, {6,1,0}, {3,0,2}, + {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2}, + {5,0,2}, {7,0,2}, {4,3,2}, {3,3,2}, + {6,0,2}, {1,0,3}, {7,1,2}, {6,0,3}, + /* hat #1 in metatile #2 (type H) */ + {1,1,2}, {1,1,6}, {7,1,12}, {6,1,6}, + {0,1,1}, {0,1,2}, {5,1,2}, {2,1,2}, + {7,1,12}, {3,1,2}, {1,1,2}, {5,1,2}, + {2,1,2}, {4,1,12}, {4,1,2}, {0,3,2}, + {2,3,2}, {5,1,2}, {0,3,2}, {3,1,2}, + {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2}, + {5,1,2}, {7,1,2}, {0,1,1}, {7,0,3}, + {6,1,2}, {3,3,2}, {6,0,3}, {7,0,2}, + /* hat #2 in metatile #2 (type H) */ + {1,2,2}, {1,0,11}, {7,1,5}, {6,0,11}, + {3,0,12}, {0,2,2}, {5,2,2}, {2,2,2}, + {7,1,5}, {3,2,2}, {1,2,2}, {5,2,2}, + {2,2,2}, {4,1,5}, {4,2,2}, {6,3,2}, + {1,3,2}, {5,2,2}, {6,3,2}, {3,2,2}, + {4,2,2}, {6,2,2}, {2,2,2}, {1,2,2}, + {5,2,2}, {7,2,2}, {3,0,12}, {4,0,12}, + {6,2,2}, {0,3,2}, {3,1,12}, {4,1,12}, + /* hat #3 in metatile #2 (type H) */ + {7,2,2}, {1,3,2}, {3,1,2}, {4,1,2}, + {0,3,2}, {4,2,2}, {2,3,2}, {5,3,2}, + {3,3,2}, {4,1,2}, {5,3,2}, {1,3,2}, + {7,1,2}, {2,3,2}, {6,0,2}, {4,3,2}, + {5,3,2}, {1,0,2}, {3,3,2}, {6,0,2}, + {6,3,2}, {4,3,2}, {1,3,2}, {2,3,2}, + {7,3,2}, {5,3,2}, {3,2,2}, {4,2,2}, + {0,0,2}, {6,3,2}, {3,1,5}, {4,1,5}, + /* hat #0 in metatile #3 (type T) */ + {1,0,3}, {4,0,2}, {7,0,0}, {7,1,0}, + {7,0,2}, {0,0,3}, {5,0,3}, {2,0,3}, + {7,0,0}, {3,0,3}, {1,0,3}, {5,0,3}, + {2,0,3}, {4,0,0}, {4,0,3}, {7,2,1}, + {3,1,1}, {5,0,3}, {7,2,1}, {3,0,3}, + {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3}, + {5,0,3}, {7,0,3}, {7,0,2}, {7,1,2}, + {6,0,3}, {2,1,1}, {6,1,2}, {0,1,1}, + /* hat #1 in metatile #3 (type T) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #2 in metatile #3 (type T) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #3 (type T) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #4 (type P) */ + {1,0,4}, {-1,-1,-1}, {0,2,1}, {7,1,9}, + {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4}, + {0,2,1}, {3,0,4}, {1,0,4}, {5,0,4}, + {2,0,4}, {2,0,0}, {4,0,4}, {0,0,0}, + {3,1,4}, {5,0,4}, {0,0,0}, {3,0,4}, + {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4}, + {5,0,4}, {7,0,4}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,4}, {2,1,4}, {-1,-1,-1}, {0,1,4}, + /* hat #1 in metatile #4 (type P) */ + {1,1,4}, {-1,-1,-1}, {7,0,4}, {-1,-1,-1}, + {0,1,7}, {0,1,4}, {5,1,4}, {2,1,4}, + {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4}, + {2,1,4}, {4,0,4}, {4,1,4}, {7,3,0}, + {3,2,0}, {5,1,4}, {7,3,0}, {3,1,4}, + {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4}, + {5,1,4}, {7,1,4}, {0,1,7}, {7,0,7}, + {6,1,4}, {2,2,0}, {6,0,7}, {0,2,0}, + /* hat #2 in metatile #4 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #4 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #5 (type P) */ + {1,0,5}, {-1,-1,-1}, {0,1,0}, {7,1,8}, + {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5}, + {0,1,0}, {3,0,5}, {1,0,5}, {5,0,5}, + {2,0,5}, {2,0,2}, {4,0,5}, {0,0,2}, + {3,1,5}, {5,0,5}, {0,0,2}, {3,0,5}, + {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5}, + {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,5}, {2,1,5}, {-1,-1,-1}, {0,1,5}, + /* hat #1 in metatile #5 (type P) */ + {1,1,5}, {-1,-1,-1}, {7,0,5}, {-1,-1,-1}, + {0,1,11}, {0,1,5}, {5,1,5}, {2,1,5}, + {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5}, + {2,1,5}, {4,0,5}, {4,1,5}, {7,3,2}, + {3,2,2}, {5,1,5}, {7,3,2}, {3,1,5}, + {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5}, + {5,1,5}, {7,1,5}, {0,1,11}, {7,0,11}, + {6,1,5}, {2,2,2}, {6,0,11}, {0,2,2}, + /* hat #2 in metatile #5 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #5 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #6 (type P) */ + {1,0,6}, {4,0,1}, {0,1,10}, {7,0,10}, + {7,0,1}, {0,0,6}, {5,0,6}, {2,0,6}, + {0,1,10}, {3,0,6}, {1,0,6}, {5,0,6}, + {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1}, + {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6}, + {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6}, + {5,0,6}, {7,0,6}, {7,0,1}, {7,1,1}, + {6,0,6}, {2,1,6}, {6,1,1}, {0,1,6}, + /* hat #1 in metatile #6 (type P) */ + {1,1,6}, {1,1,1}, {7,0,6}, {6,1,1}, + {0,1,2}, {0,1,6}, {5,1,6}, {2,1,6}, + {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6}, + {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6}, + {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6}, + {5,1,6}, {7,1,6}, {0,1,2}, {7,1,12}, + {6,1,6}, {-1,-1,-1}, {6,1,12}, {-1,-1,-1}, + /* hat #2 in metatile #6 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #6 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #7 (type F) */ + {1,0,7}, {2,0,8}, {-1,-1,-1}, {0,0,8}, + {0,2,0}, {0,0,7}, {5,0,7}, {2,0,7}, + {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7}, + {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1}, + {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7}, + {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7}, + {5,0,7}, {7,0,7}, {0,2,0}, {7,1,4}, + {6,0,7}, {2,1,7}, {6,1,4}, {0,1,7}, + /* hat #1 in metatile #7 (type F) */ + {1,1,7}, {1,1,4}, {7,0,7}, {6,1,4}, + {-1,-1,-1}, {0,1,7}, {5,1,7}, {2,1,7}, + {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7}, + {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7}, + {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7}, + {5,1,7}, {7,1,7}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #2 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #8 (type F) */ + {1,0,8}, {-1,-1,-1}, {0,0,7}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8}, + {0,0,7}, {3,0,8}, {1,0,8}, {5,0,8}, + {2,0,8}, {1,2,0}, {4,0,8}, {6,2,0}, + {3,1,8}, {5,0,8}, {6,2,0}, {3,0,8}, + {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8}, + {5,0,8}, {7,0,8}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,8}, {2,1,8}, {-1,-1,-1}, {0,1,8}, + /* hat #1 in metatile #8 (type F) */ + {1,1,8}, {-1,-1,-1}, {7,0,8}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,8}, {5,1,8}, {2,1,8}, + {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8}, + {2,1,8}, {4,0,8}, {4,1,8}, {7,2,0}, + {3,1,0}, {5,1,8}, {7,2,0}, {3,1,8}, + {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8}, + {5,1,8}, {7,1,8}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,8}, {2,1,0}, {0,0,5}, {0,1,0}, + /* hat #2 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #9 (type F) */ + {1,0,9}, {-1,-1,-1}, {0,0,10}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,9}, {5,0,9}, {2,0,9}, + {0,0,10}, {3,0,9}, {1,0,9}, {5,0,9}, + {2,0,9}, {2,0,1}, {4,0,9}, {0,0,1}, + {3,1,9}, {5,0,9}, {0,0,1}, {3,0,9}, + {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9}, + {5,0,9}, {7,0,9}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,9}, {2,1,9}, {-1,-1,-1}, {0,1,9}, + /* hat #1 in metatile #9 (type F) */ + {1,1,9}, {-1,-1,-1}, {7,0,9}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,9}, {5,1,9}, {2,1,9}, + {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9}, + {2,1,9}, {4,0,9}, {4,1,9}, {7,3,1}, + {3,2,1}, {5,1,9}, {7,3,1}, {3,1,9}, + {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9}, + {5,1,9}, {7,1,9}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,9}, {2,2,1}, {0,0,4}, {0,2,1}, + /* hat #2 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #10 (type F) */ + {1,0,10}, {2,0,9}, {-1,-1,-1}, {0,0,9}, + {3,0,1}, {0,0,10}, {5,0,10}, {2,0,10}, + {-1,-1,-1}, {3,0,10}, {1,0,10}, {5,0,10}, + {2,0,10}, {-1,-1,-1}, {4,0,10}, {-1,-1,-1}, + {3,1,10}, {5,0,10}, {-1,-1,-1}, {3,0,10}, + {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10}, + {5,0,10}, {7,0,10}, {3,0,1}, {4,0,1}, + {6,0,10}, {2,1,10}, {0,0,6}, {0,1,10}, + /* hat #1 in metatile #10 (type F) */ + {1,1,10}, {2,0,6}, {7,0,10}, {0,0,6}, + {-1,-1,-1}, {0,1,10}, {5,1,10}, {2,1,10}, + {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10}, + {2,1,10}, {4,0,10}, {4,1,10}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,10}, {-1,-1,-1}, {3,1,10}, + {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10}, + {5,1,10}, {7,1,10}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,10}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #2 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #11 (type F) */ + {1,0,11}, {2,0,12}, {-1,-1,-1}, {0,0,12}, + {0,2,2}, {0,0,11}, {5,0,11}, {2,0,11}, + {-1,-1,-1}, {3,0,11}, {1,0,11}, {5,0,11}, + {2,0,11}, {-1,-1,-1}, {4,0,11}, {-1,-1,-1}, + {3,1,11}, {5,0,11}, {-1,-1,-1}, {3,0,11}, + {4,0,11}, {6,0,11}, {2,0,11}, {1,0,11}, + {5,0,11}, {7,0,11}, {0,2,2}, {7,1,5}, + {6,0,11}, {2,1,11}, {6,1,5}, {0,1,11}, + /* hat #1 in metatile #11 (type F) */ + {1,1,11}, {1,1,5}, {7,0,11}, {6,1,5}, + {-1,-1,-1}, {0,1,11}, {5,1,11}, {2,1,11}, + {7,0,11}, {3,1,11}, {1,1,11}, {5,1,11}, + {2,1,11}, {4,0,11}, {4,1,11}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,11}, {-1,-1,-1}, {3,1,11}, + {4,1,11}, {6,1,11}, {2,1,11}, {1,1,11}, + {5,1,11}, {7,1,11}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,11}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #2 in metatile #11 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #11 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #12 (type F) */ + {1,0,12}, {-1,-1,-1}, {0,0,11}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,12}, {5,0,12}, {2,0,12}, + {0,0,11}, {3,0,12}, {1,0,12}, {5,0,12}, + {2,0,12}, {1,2,2}, {4,0,12}, {6,2,2}, + {3,1,12}, {5,0,12}, {6,2,2}, {3,0,12}, + {4,0,12}, {6,0,12}, {2,0,12}, {1,0,12}, + {5,0,12}, {7,0,12}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,12}, {2,1,12}, {-1,-1,-1}, {0,1,12}, + /* hat #1 in metatile #12 (type F) */ + {1,1,12}, {-1,-1,-1}, {7,0,12}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,12}, {5,1,12}, {2,1,12}, + {7,0,12}, {3,1,12}, {1,1,12}, {5,1,12}, + {2,1,12}, {4,0,12}, {4,1,12}, {7,2,2}, + {3,1,2}, {5,1,12}, {7,2,2}, {3,1,12}, + {4,1,12}, {6,1,12}, {2,1,12}, {1,1,12}, + {5,1,12}, {7,1,12}, {-1,-1,-1}, {7,1,6}, + {6,1,12}, {2,1,2}, {6,1,6}, {0,1,2}, + /* hat #2 in metatile #12 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #12 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, +}; +static const KitemapEntry kitemap_T[] = { + /* hat #0 in metatile #0 (type H) */ + {1,0,0}, {7,3,0}, {3,0,3}, {4,0,3}, + {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0}, + {3,0,3}, {3,0,0}, {1,0,0}, {5,0,0}, + {2,0,0}, {1,1,6}, {4,0,0}, {6,1,6}, + {0,0,2}, {5,0,0}, {6,1,6}, {3,0,0}, + {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0}, + {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0}, + {6,0,0}, {1,0,2}, {7,1,0}, {6,0,2}, + /* hat #1 in metatile #0 (type H) */ + {1,1,0}, {1,1,4}, {7,1,1}, {6,1,4}, + {0,1,2}, {0,1,0}, {5,1,0}, {2,1,0}, + {7,1,1}, {3,1,0}, {1,1,0}, {5,1,0}, + {2,1,0}, {4,1,1}, {4,1,0}, {0,3,0}, + {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0}, + {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0}, + {5,1,0}, {7,1,0}, {0,1,2}, {7,0,2}, + {6,1,0}, {3,3,0}, {6,0,2}, {7,0,0}, + /* hat #2 in metatile #0 (type H) */ + {1,2,0}, {1,1,5}, {7,1,3}, {6,1,5}, + {3,0,1}, {0,2,0}, {5,2,0}, {2,2,0}, + {7,1,3}, {3,2,0}, {1,2,0}, {5,2,0}, + {2,2,0}, {4,1,3}, {4,2,0}, {6,3,0}, + {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0}, + {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0}, + {5,2,0}, {7,2,0}, {3,0,1}, {4,0,1}, + {6,2,0}, {0,3,0}, {3,1,1}, {4,1,1}, + /* hat #3 in metatile #0 (type H) */ + {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0}, + {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0}, + {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0}, + {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0}, + {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0}, + {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0}, + {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0}, + {0,0,0}, {6,3,0}, {3,1,3}, {4,1,3}, + /* hat #0 in metatile #1 (type P) */ + {1,0,1}, {-1,-1,-1}, {0,1,5}, {7,0,5}, + {-1,-1,-1}, {0,0,1}, {5,0,1}, {2,0,1}, + {0,1,5}, {3,0,1}, {1,0,1}, {5,0,1}, + {2,0,1}, {1,2,0}, {4,0,1}, {6,2,0}, + {3,1,1}, {5,0,1}, {6,2,0}, {3,0,1}, + {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1}, + {5,0,1}, {7,0,1}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,1}, {2,1,1}, {-1,-1,-1}, {0,1,1}, + /* hat #1 in metatile #1 (type P) */ + {1,1,1}, {-1,-1,-1}, {7,0,1}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,1}, {5,1,1}, {2,1,1}, + {7,0,1}, {3,1,1}, {1,1,1}, {5,1,1}, + {2,1,1}, {4,0,1}, {4,1,1}, {7,2,0}, + {3,1,0}, {5,1,1}, {7,2,0}, {3,1,1}, + {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1}, + {5,1,1}, {7,1,1}, {-1,-1,-1}, {7,1,4}, + {6,1,1}, {2,1,0}, {6,1,4}, {0,1,0}, + /* hat #2 in metatile #1 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #1 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #2 (type P) */ + {1,0,2}, {4,0,0}, {-1,-1,-1}, {7,1,6}, + {7,0,0}, {0,0,2}, {5,0,2}, {2,0,2}, + {-1,-1,-1}, {3,0,2}, {1,0,2}, {5,0,2}, + {2,0,2}, {-1,-1,-1}, {4,0,2}, {-1,-1,-1}, + {3,1,2}, {5,0,2}, {-1,-1,-1}, {3,0,2}, + {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2}, + {5,0,2}, {7,0,2}, {7,0,0}, {7,1,0}, + {6,0,2}, {2,1,2}, {6,1,0}, {0,1,2}, + /* hat #1 in metatile #2 (type P) */ + {1,1,2}, {1,1,0}, {7,0,2}, {6,1,0}, + {0,1,4}, {0,1,2}, {5,1,2}, {2,1,2}, + {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2}, + {2,1,2}, {4,0,2}, {4,1,2}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,2}, {-1,-1,-1}, {3,1,2}, + {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2}, + {5,1,2}, {7,1,2}, {0,1,4}, {7,0,4}, + {6,1,2}, {-1,-1,-1}, {6,0,4}, {-1,-1,-1}, + /* hat #2 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #3 (type P) */ + {1,0,3}, {-1,-1,-1}, {0,1,6}, {7,0,6}, + {-1,-1,-1}, {0,0,3}, {5,0,3}, {2,0,3}, + {0,1,6}, {3,0,3}, {1,0,3}, {5,0,3}, + {2,0,3}, {2,0,0}, {4,0,3}, {0,0,0}, + {3,1,3}, {5,0,3}, {0,0,0}, {3,0,3}, + {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3}, + {5,0,3}, {7,0,3}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,3}, {2,1,3}, {-1,-1,-1}, {0,1,3}, + /* hat #1 in metatile #3 (type P) */ + {1,1,3}, {-1,-1,-1}, {7,0,3}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,3}, {5,1,3}, {2,1,3}, + {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3}, + {2,1,3}, {4,0,3}, {4,1,3}, {7,3,0}, + {3,2,0}, {5,1,3}, {7,3,0}, {3,1,3}, + {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3}, + {5,1,3}, {7,1,3}, {-1,-1,-1}, {7,1,5}, + {6,1,3}, {2,2,0}, {6,1,5}, {0,2,0}, + /* hat #2 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #4 (type F) */ + {1,0,4}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4}, + {-1,-1,-1}, {3,0,4}, {1,0,4}, {5,0,4}, + {2,0,4}, {-1,-1,-1}, {4,0,4}, {-1,-1,-1}, + {3,1,4}, {5,0,4}, {-1,-1,-1}, {3,0,4}, + {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4}, + {5,0,4}, {7,0,4}, {-1,-1,-1}, {7,1,2}, + {6,0,4}, {2,1,4}, {6,1,2}, {0,1,4}, + /* hat #1 in metatile #4 (type F) */ + {1,1,4}, {1,1,2}, {7,0,4}, {6,1,2}, + {0,1,0}, {0,1,4}, {5,1,4}, {2,1,4}, + {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4}, + {2,1,4}, {4,0,4}, {4,1,4}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,4}, {-1,-1,-1}, {3,1,4}, + {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4}, + {5,1,4}, {7,1,4}, {0,1,0}, {7,1,1}, + {6,1,4}, {-1,-1,-1}, {6,1,1}, {-1,-1,-1}, + /* hat #2 in metatile #4 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #4 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #5 (type F) */ + {1,0,5}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5}, + {-1,-1,-1}, {3,0,5}, {1,0,5}, {5,0,5}, + {2,0,5}, {-1,-1,-1}, {4,0,5}, {-1,-1,-1}, + {3,1,5}, {5,0,5}, {-1,-1,-1}, {3,0,5}, + {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5}, + {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,5}, {2,1,5}, {0,0,1}, {0,1,5}, + /* hat #1 in metatile #5 (type F) */ + {1,1,5}, {2,0,1}, {7,0,5}, {0,0,1}, + {0,2,0}, {0,1,5}, {5,1,5}, {2,1,5}, + {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5}, + {2,1,5}, {4,0,5}, {4,1,5}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,5}, {-1,-1,-1}, {3,1,5}, + {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5}, + {5,1,5}, {7,1,5}, {0,2,0}, {7,1,3}, + {6,1,5}, {-1,-1,-1}, {6,1,3}, {-1,-1,-1}, + /* hat #2 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #6 (type F) */ + {1,0,6}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,6}, {5,0,6}, {2,0,6}, + {-1,-1,-1}, {3,0,6}, {1,0,6}, {5,0,6}, + {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1}, + {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6}, + {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6}, + {5,0,6}, {7,0,6}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,6}, {2,1,6}, {0,0,3}, {0,1,6}, + /* hat #1 in metatile #6 (type F) */ + {1,1,6}, {2,0,3}, {7,0,6}, {0,0,3}, + {3,0,0}, {0,1,6}, {5,1,6}, {2,1,6}, + {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6}, + {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6}, + {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6}, + {5,1,6}, {7,1,6}, {3,0,0}, {4,0,0}, + {6,1,6}, {-1,-1,-1}, {0,0,2}, {-1,-1,-1}, + /* hat #2 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, +}; +static const KitemapEntry kitemap_P[] = { + /* hat #0 in metatile #0 (type H) */ + {1,0,0}, {7,3,0}, {3,0,4}, {4,0,4}, + {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0}, + {3,0,4}, {3,0,0}, {1,0,0}, {5,0,0}, + {2,0,0}, {1,1,9}, {4,0,0}, {6,1,9}, + {0,0,3}, {5,0,0}, {6,1,9}, {3,0,0}, + {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0}, + {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0}, + {6,0,0}, {1,0,3}, {7,1,0}, {6,0,3}, + /* hat #1 in metatile #0 (type H) */ + {1,1,0}, {1,1,8}, {7,1,5}, {6,1,8}, + {0,1,3}, {0,1,0}, {5,1,0}, {2,1,0}, + {7,1,5}, {3,1,0}, {1,1,0}, {5,1,0}, + {2,1,0}, {4,1,5}, {4,1,0}, {0,3,0}, + {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0}, + {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0}, + {5,1,0}, {7,1,0}, {0,1,3}, {7,0,3}, + {6,1,0}, {3,3,0}, {6,0,3}, {7,0,0}, + /* hat #2 in metatile #0 (type H) */ + {1,2,0}, {1,0,6}, {7,1,4}, {6,0,6}, + {3,0,5}, {0,2,0}, {5,2,0}, {2,2,0}, + {7,1,4}, {3,2,0}, {1,2,0}, {5,2,0}, + {2,2,0}, {4,1,4}, {4,2,0}, {6,3,0}, + {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0}, + {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0}, + {5,2,0}, {7,2,0}, {3,0,5}, {4,0,5}, + {6,2,0}, {0,3,0}, {3,1,5}, {4,1,5}, + /* hat #3 in metatile #0 (type H) */ + {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0}, + {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0}, + {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0}, + {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0}, + {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0}, + {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0}, + {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0}, + {0,0,0}, {6,3,0}, {3,1,4}, {4,1,4}, + /* hat #0 in metatile #1 (type H) */ + {1,0,1}, {7,3,1}, {3,0,10}, {4,0,10}, + {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1}, + {3,0,10}, {3,0,1}, {1,0,1}, {5,0,1}, + {2,0,1}, {1,0,9}, {4,0,1}, {6,0,9}, + {0,0,4}, {5,0,1}, {6,0,9}, {3,0,1}, + {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1}, + {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1}, + {6,0,1}, {1,0,4}, {7,1,1}, {6,0,4}, + /* hat #1 in metatile #1 (type H) */ + {1,1,1}, {1,1,6}, {7,1,2}, {6,1,6}, + {0,1,4}, {0,1,1}, {5,1,1}, {2,1,1}, + {7,1,2}, {3,1,1}, {1,1,1}, {5,1,1}, + {2,1,1}, {4,1,2}, {4,1,1}, {0,3,1}, + {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1}, + {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1}, + {5,1,1}, {7,1,1}, {0,1,4}, {7,0,4}, + {6,1,1}, {3,3,1}, {6,0,4}, {7,0,1}, + /* hat #2 in metatile #1 (type H) */ + {1,2,1}, {1,1,7}, {7,1,10}, {6,1,7}, + {3,0,2}, {0,2,1}, {5,2,1}, {2,2,1}, + {7,1,10}, {3,2,1}, {1,2,1}, {5,2,1}, + {2,2,1}, {4,1,10}, {4,2,1}, {6,3,1}, + {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1}, + {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1}, + {5,2,1}, {7,2,1}, {3,0,2}, {4,0,2}, + {6,2,1}, {0,3,1}, {3,1,2}, {4,1,2}, + /* hat #3 in metatile #1 (type H) */ + {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1}, + {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1}, + {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1}, + {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1}, + {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1}, + {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1}, + {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1}, + {0,0,1}, {6,3,1}, {3,1,10}, {4,1,10}, + /* hat #0 in metatile #2 (type P) */ + {1,0,2}, {-1,-1,-1}, {0,1,7}, {7,0,7}, + {-1,-1,-1}, {0,0,2}, {5,0,2}, {2,0,2}, + {0,1,7}, {3,0,2}, {1,0,2}, {5,0,2}, + {2,0,2}, {1,2,1}, {4,0,2}, {6,2,1}, + {3,1,2}, {5,0,2}, {6,2,1}, {3,0,2}, + {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2}, + {5,0,2}, {7,0,2}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,2}, {2,1,2}, {-1,-1,-1}, {0,1,2}, + /* hat #1 in metatile #2 (type P) */ + {1,1,2}, {-1,-1,-1}, {7,0,2}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,2}, {5,1,2}, {2,1,2}, + {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2}, + {2,1,2}, {4,0,2}, {4,1,2}, {7,2,1}, + {3,1,1}, {5,1,2}, {7,2,1}, {3,1,2}, + {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2}, + {5,1,2}, {7,1,2}, {-1,-1,-1}, {7,1,6}, + {6,1,2}, {2,1,1}, {6,1,6}, {0,1,1}, + /* hat #2 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #3 (type P) */ + {1,0,3}, {4,0,0}, {-1,-1,-1}, {7,1,9}, + {7,0,0}, {0,0,3}, {5,0,3}, {2,0,3}, + {-1,-1,-1}, {3,0,3}, {1,0,3}, {5,0,3}, + {2,0,3}, {-1,-1,-1}, {4,0,3}, {-1,-1,-1}, + {3,1,3}, {5,0,3}, {-1,-1,-1}, {3,0,3}, + {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3}, + {5,0,3}, {7,0,3}, {7,0,0}, {7,1,0}, + {6,0,3}, {2,1,3}, {6,1,0}, {0,1,3}, + /* hat #1 in metatile #3 (type P) */ + {1,1,3}, {1,1,0}, {7,0,3}, {6,1,0}, + {0,1,8}, {0,1,3}, {5,1,3}, {2,1,3}, + {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3}, + {2,1,3}, {4,0,3}, {4,1,3}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,3}, {-1,-1,-1}, {3,1,3}, + {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3}, + {5,1,3}, {7,1,3}, {0,1,8}, {7,0,8}, + {6,1,3}, {-1,-1,-1}, {6,0,8}, {-1,-1,-1}, + /* hat #2 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #4 (type P) */ + {1,0,4}, {4,0,1}, {0,1,9}, {7,0,9}, + {7,0,1}, {0,0,4}, {5,0,4}, {2,0,4}, + {0,1,9}, {3,0,4}, {1,0,4}, {5,0,4}, + {2,0,4}, {2,0,0}, {4,0,4}, {0,0,0}, + {3,1,4}, {5,0,4}, {0,0,0}, {3,0,4}, + {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4}, + {5,0,4}, {7,0,4}, {7,0,1}, {7,1,1}, + {6,0,4}, {2,1,4}, {6,1,1}, {0,1,4}, + /* hat #1 in metatile #4 (type P) */ + {1,1,4}, {1,1,1}, {7,0,4}, {6,1,1}, + {0,1,6}, {0,1,4}, {5,1,4}, {2,1,4}, + {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4}, + {2,1,4}, {4,0,4}, {4,1,4}, {7,3,0}, + {3,2,0}, {5,1,4}, {7,3,0}, {3,1,4}, + {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4}, + {5,1,4}, {7,1,4}, {0,1,6}, {7,0,6}, + {6,1,4}, {2,2,0}, {6,0,6}, {0,2,0}, + /* hat #2 in metatile #4 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #4 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #5 (type F) */ + {1,0,5}, {-1,-1,-1}, {0,0,6}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5}, + {0,0,6}, {3,0,5}, {1,0,5}, {5,0,5}, + {2,0,5}, {1,2,0}, {4,0,5}, {6,2,0}, + {3,1,5}, {5,0,5}, {6,2,0}, {3,0,5}, + {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5}, + {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,5}, {2,1,5}, {-1,-1,-1}, {0,1,5}, + /* hat #1 in metatile #5 (type F) */ + {1,1,5}, {-1,-1,-1}, {7,0,5}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,5}, {5,1,5}, {2,1,5}, + {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5}, + {2,1,5}, {4,0,5}, {4,1,5}, {7,2,0}, + {3,1,0}, {5,1,5}, {7,2,0}, {3,1,5}, + {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5}, + {5,1,5}, {7,1,5}, {-1,-1,-1}, {7,1,8}, + {6,1,5}, {2,1,0}, {6,1,8}, {0,1,0}, + /* hat #2 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #6 (type F) */ + {1,0,6}, {2,0,5}, {-1,-1,-1}, {0,0,5}, + {0,2,0}, {0,0,6}, {5,0,6}, {2,0,6}, + {-1,-1,-1}, {3,0,6}, {1,0,6}, {5,0,6}, + {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1}, + {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6}, + {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6}, + {5,0,6}, {7,0,6}, {0,2,0}, {7,1,4}, + {6,0,6}, {2,1,6}, {6,1,4}, {0,1,6}, + /* hat #1 in metatile #6 (type F) */ + {1,1,6}, {1,1,4}, {7,0,6}, {6,1,4}, + {0,1,1}, {0,1,6}, {5,1,6}, {2,1,6}, + {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6}, + {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6}, + {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6}, + {5,1,6}, {7,1,6}, {0,1,1}, {7,1,2}, + {6,1,6}, {-1,-1,-1}, {6,1,2}, {-1,-1,-1}, + /* hat #2 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #7 (type F) */ + {1,0,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,7}, {5,0,7}, {2,0,7}, + {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7}, + {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1}, + {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7}, + {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7}, + {5,0,7}, {7,0,7}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,7}, {2,1,7}, {0,0,2}, {0,1,7}, + /* hat #1 in metatile #7 (type F) */ + {1,1,7}, {2,0,2}, {7,0,7}, {0,0,2}, + {0,2,1}, {0,1,7}, {5,1,7}, {2,1,7}, + {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7}, + {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7}, + {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7}, + {5,1,7}, {7,1,7}, {0,2,1}, {7,1,10}, + {6,1,7}, {-1,-1,-1}, {6,1,10}, {-1,-1,-1}, + /* hat #2 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #8 (type F) */ + {1,0,8}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8}, + {-1,-1,-1}, {3,0,8}, {1,0,8}, {5,0,8}, + {2,0,8}, {-1,-1,-1}, {4,0,8}, {-1,-1,-1}, + {3,1,8}, {5,0,8}, {-1,-1,-1}, {3,0,8}, + {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8}, + {5,0,8}, {7,0,8}, {-1,-1,-1}, {7,1,3}, + {6,0,8}, {2,1,8}, {6,1,3}, {0,1,8}, + /* hat #1 in metatile #8 (type F) */ + {1,1,8}, {1,1,3}, {7,0,8}, {6,1,3}, + {0,1,0}, {0,1,8}, {5,1,8}, {2,1,8}, + {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8}, + {2,1,8}, {4,0,8}, {4,1,8}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,8}, {-1,-1,-1}, {3,1,8}, + {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8}, + {5,1,8}, {7,1,8}, {0,1,0}, {7,1,5}, + {6,1,8}, {-1,-1,-1}, {6,1,5}, {-1,-1,-1}, + /* hat #2 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #9 (type F) */ + {1,0,9}, {2,0,10}, {-1,-1,-1}, {0,0,10}, + {3,0,1}, {0,0,9}, {5,0,9}, {2,0,9}, + {-1,-1,-1}, {3,0,9}, {1,0,9}, {5,0,9}, + {2,0,9}, {-1,-1,-1}, {4,0,9}, {-1,-1,-1}, + {3,1,9}, {5,0,9}, {-1,-1,-1}, {3,0,9}, + {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9}, + {5,0,9}, {7,0,9}, {3,0,1}, {4,0,1}, + {6,0,9}, {2,1,9}, {0,0,4}, {0,1,9}, + /* hat #1 in metatile #9 (type F) */ + {1,1,9}, {2,0,4}, {7,0,9}, {0,0,4}, + {3,0,0}, {0,1,9}, {5,1,9}, {2,1,9}, + {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9}, + {2,1,9}, {4,0,9}, {4,1,9}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,9}, {-1,-1,-1}, {3,1,9}, + {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9}, + {5,1,9}, {7,1,9}, {3,0,0}, {4,0,0}, + {6,1,9}, {-1,-1,-1}, {0,0,3}, {-1,-1,-1}, + /* hat #2 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #10 (type F) */ + {1,0,10}, {-1,-1,-1}, {0,0,9}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,10}, {5,0,10}, {2,0,10}, + {0,0,9}, {3,0,10}, {1,0,10}, {5,0,10}, + {2,0,10}, {2,0,1}, {4,0,10}, {0,0,1}, + {3,1,10}, {5,0,10}, {0,0,1}, {3,0,10}, + {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10}, + {5,0,10}, {7,0,10}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,10}, {2,1,10}, {-1,-1,-1}, {0,1,10}, + /* hat #1 in metatile #10 (type F) */ + {1,1,10}, {-1,-1,-1}, {7,0,10}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,10}, {5,1,10}, {2,1,10}, + {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10}, + {2,1,10}, {4,0,10}, {4,1,10}, {7,3,1}, + {3,2,1}, {5,1,10}, {7,3,1}, {3,1,10}, + {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10}, + {5,1,10}, {7,1,10}, {-1,-1,-1}, {7,1,7}, + {6,1,10}, {2,2,1}, {6,1,7}, {0,2,1}, + /* hat #2 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, +}; +static const KitemapEntry kitemap_F[] = { + /* hat #0 in metatile #0 (type H) */ + {1,0,0}, {7,3,0}, {3,0,3}, {4,0,3}, + {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0}, + {3,0,3}, {3,0,0}, {1,0,0}, {5,0,0}, + {2,0,0}, {1,1,9}, {4,0,0}, {6,1,9}, + {0,0,2}, {5,0,0}, {6,1,9}, {3,0,0}, + {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0}, + {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0}, + {6,0,0}, {1,0,2}, {7,1,0}, {6,0,2}, + /* hat #1 in metatile #0 (type H) */ + {1,1,0}, {1,1,8}, {7,1,4}, {6,1,8}, + {0,1,2}, {0,1,0}, {5,1,0}, {2,1,0}, + {7,1,4}, {3,1,0}, {1,1,0}, {5,1,0}, + {2,1,0}, {4,1,4}, {4,1,0}, {0,3,0}, + {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0}, + {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0}, + {5,1,0}, {7,1,0}, {0,1,2}, {7,0,2}, + {6,1,0}, {3,3,0}, {6,0,2}, {7,0,0}, + /* hat #2 in metatile #0 (type H) */ + {1,2,0}, {1,0,5}, {7,1,3}, {6,0,5}, + {3,0,4}, {0,2,0}, {5,2,0}, {2,2,0}, + {7,1,3}, {3,2,0}, {1,2,0}, {5,2,0}, + {2,2,0}, {4,1,3}, {4,2,0}, {6,3,0}, + {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0}, + {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0}, + {5,2,0}, {7,2,0}, {3,0,4}, {4,0,4}, + {6,2,0}, {0,3,0}, {3,1,4}, {4,1,4}, + /* hat #3 in metatile #0 (type H) */ + {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0}, + {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0}, + {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0}, + {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0}, + {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0}, + {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0}, + {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0}, + {0,0,0}, {6,3,0}, {3,1,3}, {4,1,3}, + /* hat #0 in metatile #1 (type H) */ + {1,0,1}, {7,3,1}, {3,0,10}, {4,0,10}, + {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1}, + {3,0,10}, {3,0,1}, {1,0,1}, {5,0,1}, + {2,0,1}, {1,0,9}, {4,0,1}, {6,0,9}, + {0,0,3}, {5,0,1}, {6,0,9}, {3,0,1}, + {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1}, + {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1}, + {6,0,1}, {1,0,3}, {7,1,1}, {6,0,3}, + /* hat #1 in metatile #1 (type H) */ + {1,1,1}, {1,1,5}, {7,1,6}, {6,1,5}, + {0,1,3}, {0,1,1}, {5,1,1}, {2,1,1}, + {7,1,6}, {3,1,1}, {1,1,1}, {5,1,1}, + {2,1,1}, {4,1,6}, {4,1,1}, {0,3,1}, + {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1}, + {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1}, + {5,1,1}, {7,1,1}, {0,1,3}, {7,0,3}, + {6,1,1}, {3,3,1}, {6,0,3}, {7,0,1}, + /* hat #2 in metatile #1 (type H) */ + {1,2,1}, {1,0,7}, {7,1,10}, {6,0,7}, + {3,0,6}, {0,2,1}, {5,2,1}, {2,2,1}, + {7,1,10}, {3,2,1}, {1,2,1}, {5,2,1}, + {2,2,1}, {4,1,10}, {4,2,1}, {6,3,1}, + {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1}, + {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1}, + {5,2,1}, {7,2,1}, {3,0,6}, {4,0,6}, + {6,2,1}, {0,3,1}, {3,1,6}, {4,1,6}, + /* hat #3 in metatile #1 (type H) */ + {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1}, + {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1}, + {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1}, + {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1}, + {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1}, + {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1}, + {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1}, + {0,0,1}, {6,3,1}, {3,1,10}, {4,1,10}, + /* hat #0 in metatile #2 (type P) */ + {1,0,2}, {4,0,0}, {-1,-1,-1}, {7,1,9}, + {7,0,0}, {0,0,2}, {5,0,2}, {2,0,2}, + {-1,-1,-1}, {3,0,2}, {1,0,2}, {5,0,2}, + {2,0,2}, {-1,-1,-1}, {4,0,2}, {-1,-1,-1}, + {3,1,2}, {5,0,2}, {-1,-1,-1}, {3,0,2}, + {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2}, + {5,0,2}, {7,0,2}, {7,0,0}, {7,1,0}, + {6,0,2}, {2,1,2}, {6,1,0}, {0,1,2}, + /* hat #1 in metatile #2 (type P) */ + {1,1,2}, {1,1,0}, {7,0,2}, {6,1,0}, + {0,1,8}, {0,1,2}, {5,1,2}, {2,1,2}, + {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2}, + {2,1,2}, {4,0,2}, {4,1,2}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,2}, {-1,-1,-1}, {3,1,2}, + {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2}, + {5,1,2}, {7,1,2}, {0,1,8}, {7,0,8}, + {6,1,2}, {-1,-1,-1}, {6,0,8}, {-1,-1,-1}, + /* hat #2 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #2 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #3 (type P) */ + {1,0,3}, {4,0,1}, {0,1,9}, {7,0,9}, + {7,0,1}, {0,0,3}, {5,0,3}, {2,0,3}, + {0,1,9}, {3,0,3}, {1,0,3}, {5,0,3}, + {2,0,3}, {2,0,0}, {4,0,3}, {0,0,0}, + {3,1,3}, {5,0,3}, {0,0,0}, {3,0,3}, + {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3}, + {5,0,3}, {7,0,3}, {7,0,1}, {7,1,1}, + {6,0,3}, {2,1,3}, {6,1,1}, {0,1,3}, + /* hat #1 in metatile #3 (type P) */ + {1,1,3}, {1,1,1}, {7,0,3}, {6,1,1}, + {0,1,5}, {0,1,3}, {5,1,3}, {2,1,3}, + {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3}, + {2,1,3}, {4,0,3}, {4,1,3}, {7,3,0}, + {3,2,0}, {5,1,3}, {7,3,0}, {3,1,3}, + {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3}, + {5,1,3}, {7,1,3}, {0,1,5}, {7,0,5}, + {6,1,3}, {2,2,0}, {6,0,5}, {0,2,0}, + /* hat #2 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #3 (type P) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #4 (type F) */ + {1,0,4}, {-1,-1,-1}, {0,0,5}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4}, + {0,0,5}, {3,0,4}, {1,0,4}, {5,0,4}, + {2,0,4}, {1,2,0}, {4,0,4}, {6,2,0}, + {3,1,4}, {5,0,4}, {6,2,0}, {3,0,4}, + {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4}, + {5,0,4}, {7,0,4}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,4}, {2,1,4}, {-1,-1,-1}, {0,1,4}, + /* hat #1 in metatile #4 (type F) */ + {1,1,4}, {-1,-1,-1}, {7,0,4}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,4}, {5,1,4}, {2,1,4}, + {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4}, + {2,1,4}, {4,0,4}, {4,1,4}, {7,2,0}, + {3,1,0}, {5,1,4}, {7,2,0}, {3,1,4}, + {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4}, + {5,1,4}, {7,1,4}, {-1,-1,-1}, {7,1,8}, + {6,1,4}, {2,1,0}, {6,1,8}, {0,1,0}, + /* hat #2 in metatile #4 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #4 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #5 (type F) */ + {1,0,5}, {2,0,4}, {-1,-1,-1}, {0,0,4}, + {0,2,0}, {0,0,5}, {5,0,5}, {2,0,5}, + {-1,-1,-1}, {3,0,5}, {1,0,5}, {5,0,5}, + {2,0,5}, {-1,-1,-1}, {4,0,5}, {-1,-1,-1}, + {3,1,5}, {5,0,5}, {-1,-1,-1}, {3,0,5}, + {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5}, + {5,0,5}, {7,0,5}, {0,2,0}, {7,1,3}, + {6,0,5}, {2,1,5}, {6,1,3}, {0,1,5}, + /* hat #1 in metatile #5 (type F) */ + {1,1,5}, {1,1,3}, {7,0,5}, {6,1,3}, + {0,1,1}, {0,1,5}, {5,1,5}, {2,1,5}, + {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5}, + {2,1,5}, {4,0,5}, {4,1,5}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,5}, {-1,-1,-1}, {3,1,5}, + {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5}, + {5,1,5}, {7,1,5}, {0,1,1}, {7,1,6}, + {6,1,5}, {-1,-1,-1}, {6,1,6}, {-1,-1,-1}, + /* hat #2 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #5 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #6 (type F) */ + {1,0,6}, {-1,-1,-1}, {0,0,7}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,6}, {5,0,6}, {2,0,6}, + {0,0,7}, {3,0,6}, {1,0,6}, {5,0,6}, + {2,0,6}, {1,2,1}, {4,0,6}, {6,2,1}, + {3,1,6}, {5,0,6}, {6,2,1}, {3,0,6}, + {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6}, + {5,0,6}, {7,0,6}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,6}, {2,1,6}, {-1,-1,-1}, {0,1,6}, + /* hat #1 in metatile #6 (type F) */ + {1,1,6}, {-1,-1,-1}, {7,0,6}, {-1,-1,-1}, + {-1,-1,-1}, {0,1,6}, {5,1,6}, {2,1,6}, + {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6}, + {2,1,6}, {4,0,6}, {4,1,6}, {7,2,1}, + {3,1,1}, {5,1,6}, {7,2,1}, {3,1,6}, + {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6}, + {5,1,6}, {7,1,6}, {-1,-1,-1}, {7,1,5}, + {6,1,6}, {2,1,1}, {6,1,5}, {0,1,1}, + /* hat #2 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #6 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #7 (type F) */ + {1,0,7}, {2,0,6}, {-1,-1,-1}, {0,0,6}, + {0,2,1}, {0,0,7}, {5,0,7}, {2,0,7}, + {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7}, + {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1}, + {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7}, + {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7}, + {5,0,7}, {7,0,7}, {0,2,1}, {7,1,10}, + {6,0,7}, {2,1,7}, {6,1,10}, {0,1,7}, + /* hat #1 in metatile #7 (type F) */ + {1,1,7}, {1,1,10}, {7,0,7}, {6,1,10}, + {-1,-1,-1}, {0,1,7}, {5,1,7}, {2,1,7}, + {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7}, + {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7}, + {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7}, + {5,1,7}, {7,1,7}, {-1,-1,-1}, {-1,-1,-1}, + {6,1,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #2 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #7 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #8 (type F) */ + {1,0,8}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8}, + {-1,-1,-1}, {3,0,8}, {1,0,8}, {5,0,8}, + {2,0,8}, {-1,-1,-1}, {4,0,8}, {-1,-1,-1}, + {3,1,8}, {5,0,8}, {-1,-1,-1}, {3,0,8}, + {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8}, + {5,0,8}, {7,0,8}, {-1,-1,-1}, {7,1,2}, + {6,0,8}, {2,1,8}, {6,1,2}, {0,1,8}, + /* hat #1 in metatile #8 (type F) */ + {1,1,8}, {1,1,2}, {7,0,8}, {6,1,2}, + {0,1,0}, {0,1,8}, {5,1,8}, {2,1,8}, + {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8}, + {2,1,8}, {4,0,8}, {4,1,8}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,8}, {-1,-1,-1}, {3,1,8}, + {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8}, + {5,1,8}, {7,1,8}, {0,1,0}, {7,1,4}, + {6,1,8}, {-1,-1,-1}, {6,1,4}, {-1,-1,-1}, + /* hat #2 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #8 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #9 (type F) */ + {1,0,9}, {2,0,10}, {-1,-1,-1}, {0,0,10}, + {3,0,1}, {0,0,9}, {5,0,9}, {2,0,9}, + {-1,-1,-1}, {3,0,9}, {1,0,9}, {5,0,9}, + {2,0,9}, {-1,-1,-1}, {4,0,9}, {-1,-1,-1}, + {3,1,9}, {5,0,9}, {-1,-1,-1}, {3,0,9}, + {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9}, + {5,0,9}, {7,0,9}, {3,0,1}, {4,0,1}, + {6,0,9}, {2,1,9}, {0,0,3}, {0,1,9}, + /* hat #1 in metatile #9 (type F) */ + {1,1,9}, {2,0,3}, {7,0,9}, {0,0,3}, + {3,0,0}, {0,1,9}, {5,1,9}, {2,1,9}, + {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9}, + {2,1,9}, {4,0,9}, {4,1,9}, {-1,-1,-1}, + {-1,-1,-1}, {5,1,9}, {-1,-1,-1}, {3,1,9}, + {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9}, + {5,1,9}, {7,1,9}, {3,0,0}, {4,0,0}, + {6,1,9}, {-1,-1,-1}, {0,0,2}, {-1,-1,-1}, + /* hat #2 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #9 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #0 in metatile #10 (type F) */ + {1,0,10}, {-1,-1,-1}, {0,0,9}, {-1,-1,-1}, + {-1,-1,-1}, {0,0,10}, {5,0,10}, {2,0,10}, + {0,0,9}, {3,0,10}, {1,0,10}, {5,0,10}, + {2,0,10}, {2,0,1}, {4,0,10}, {0,0,1}, + {3,1,10}, {5,0,10}, {0,0,1}, {3,0,10}, + {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10}, + {5,0,10}, {7,0,10}, {-1,-1,-1}, {-1,-1,-1}, + {6,0,10}, {2,1,10}, {-1,-1,-1}, {0,1,10}, + /* hat #1 in metatile #10 (type F) */ + {1,1,10}, {-1,-1,-1}, {7,0,10}, {-1,-1,-1}, + {0,1,7}, {0,1,10}, {5,1,10}, {2,1,10}, + {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10}, + {2,1,10}, {4,0,10}, {4,1,10}, {7,3,1}, + {3,2,1}, {5,1,10}, {7,3,1}, {3,1,10}, + {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10}, + {5,1,10}, {7,1,10}, {0,1,7}, {7,0,7}, + {6,1,10}, {2,2,1}, {6,0,7}, {0,2,1}, + /* hat #2 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + /* hat #3 in metatile #10 (type F) does not exist */ + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, + {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, +}; +static const KitemapEntry *const kitemap[] = { + kitemap_H, + kitemap_T, + kitemap_P, + kitemap_F, +}; + +static const MetamapEntry metamap_H[] = { + /* 0, 0 -> */ {0, 0}, /* no alternatives */ + /* 1, 0 -> */ {1, 0}, /* no alternatives */ + /* 2, 0 -> */ {2, 0}, /* no alternatives */ + /* 3, 0 -> */ {3, 0}, /* no alternatives */ + /* 4, 0 -> */ {3, 4}, + /* 5, 0 -> */ {2, 8}, + /* 6, 0 -> */ {3, 3}, + /* 7, 0 -> */ {8, 4}, + /* 8, 0 -> */ {9, 8}, + /* 9, 0 -> */ {9, 4}, + /* 10, 0 -> */ {8, 1}, + /* 11, 0 -> */ {10, 5}, + /* 12, 0 -> */ {5, 3}, + /* 0, 1 -> */ {0, 1}, /* no alternatives */ + /* 1, 1 -> */ {1, 1}, /* no alternatives */ + /* 2, 1 -> */ {2, 1}, /* no alternatives */ + /* 3, 1 -> */ {3, 1}, /* no alternatives */ + /* 4, 1 -> */ {2, 9}, + /* 5, 1 -> */ {2, 3}, + /* 6, 1 -> */ {2, 6}, + /* 7, 1 -> */ {10, 4}, + /* 8, 1 -> */ {6, 3}, + /* 9, 1 -> */ {9, 9}, + /* 10, 1 -> */ {6, 10}, + /* 11, 1 -> */ {4, 3}, + /* 12, 1 -> */ {6, 6}, + /* 0, 2 -> */ {0, 2}, /* no alternatives */ + /* 1, 2 -> */ {1, 2}, /* no alternatives */ + /* 2, 2 -> */ {2, 2}, /* no alternatives */ + /* 3, 2 -> */ {3, 2}, /* no alternatives */ + /* 4, 2 -> */ {3, 5}, + /* 5, 2 -> */ {2, 12}, + /* 6, 2 -> */ {1, 3}, + /* 7, 2 -> */ {8, 5}, + /* 8, 2 -> */ {9, 12}, + /* 9, 2 -> */ {9, 5}, + /* 10, 2 -> */ {12, 0}, + /* 11, 2 -> */ {5, 6}, + /* 12, 2 -> */ {11, 1}, + /* 0, 3 -> */ {0, 3}, /* no alternatives */ + /* 1, 3 -> */ {6, 2}, + /* 2, 3 -> */ {5, 1}, + /* 3, 3 -> */ {6, 0}, + /* 4, 3 -> */ {12, 2}, + /* 5, 3 -> */ {10, 2}, + /* 6, 3 -> */ {10, 0}, + /* 7, 3 -> */ {-1,-1}, /* does not exist */ + /* 8, 3 -> */ {-1,-1}, /* does not exist */ + /* 9, 3 -> */ {-1,-1}, /* does not exist */ + /* 10, 3 -> */ {-1,-1}, /* does not exist */ + /* 11, 3 -> */ {-1,-1}, /* does not exist */ + /* 12, 3 -> */ {-1,-1}, /* does not exist */ + /* 0, 4 -> */ {0, 4}, /* no alternatives */ + /* 1, 4 -> */ {1, 4}, /* no alternatives */ + /* 2, 4 -> */ {2, 4}, /* no alternatives */ + /* 3, 4 -> */ {4, 0}, + /* 4, 4 -> */ {4, 4}, /* no alternatives */ + /* 5, 4 -> */ {5, 7}, + /* 6, 4 -> */ {6, 4}, /* no alternatives */ + /* 7, 4 -> */ {4, 9}, + /* 8, 4 -> */ {6, 7}, + /* 9, 4 -> */ {9, 0}, + /* 10, 4 -> */ {8, 9}, + /* 11, 4 -> */ {-1,-1}, /* does not exist */ + /* 12, 4 -> */ {-1,-1}, /* does not exist */ + /* 0, 5 -> */ {0, 5}, /* no alternatives */ + /* 1, 5 -> */ {1, 5}, /* no alternatives */ + /* 2, 5 -> */ {2, 5}, /* no alternatives */ + /* 3, 5 -> */ {4, 2}, + /* 4, 5 -> */ {4, 5}, /* no alternatives */ + /* 5, 5 -> */ {5, 11}, + /* 6, 5 -> */ {6, 5}, /* no alternatives */ + /* 7, 5 -> */ {4, 8}, + /* 8, 5 -> */ {6, 11}, + /* 9, 5 -> */ {9, 2}, + /* 10, 5 -> */ {8, 8}, + /* 11, 5 -> */ {-1,-1}, /* does not exist */ + /* 12, 5 -> */ {-1,-1}, /* does not exist */ + /* 0, 6 -> */ {0, 6}, /* no alternatives */ + /* 1, 6 -> */ {1, 6}, /* no alternatives */ + /* 2, 6 -> */ {6, 1}, + /* 3, 6 -> */ {3, 6}, /* no alternatives */ + /* 4, 6 -> */ {4, 6}, /* no alternatives */ + /* 5, 6 -> */ {8, 12}, + /* 6, 6 -> */ {12, 1}, + /* 7, 6 -> */ {10, 1}, + /* 8, 6 -> */ {4, 12}, + /* 9, 6 -> */ {9, 6}, /* no alternatives */ + /* 10, 6 -> */ {5, 10}, + /* 11, 6 -> */ {-1,-1}, /* does not exist */ + /* 12, 6 -> */ {-1,-1}, /* does not exist */ + /* 0, 7 -> */ {0, 7}, /* no alternatives */ + /* 1, 7 -> */ {1, 7}, /* no alternatives */ + /* 2, 7 -> */ {2, 7}, /* no alternatives */ + /* 3, 7 -> */ {3, 7}, /* no alternatives */ + /* 4, 7 -> */ {4, 7}, /* no alternatives */ + /* 5, 7 -> */ {5, 4}, + /* 6, 7 -> */ {7, 0}, + /* 7, 7 -> */ {10, 8}, + /* 8, 7 -> */ {8, 7}, /* no alternatives */ + /* 9, 7 -> */ {9, 7}, /* no alternatives */ + /* 10, 7 -> */ {10, 7}, /* no alternatives */ + /* 11, 7 -> */ {-1,-1}, /* does not exist */ + /* 12, 7 -> */ {-1,-1}, /* does not exist */ + /* 0, 8 -> */ {0, 8}, /* no alternatives */ + /* 1, 8 -> */ {1, 8}, /* no alternatives */ + /* 2, 8 -> */ {5, 0}, + /* 3, 8 -> */ {3, 8}, /* no alternatives */ + /* 4, 8 -> */ {7, 5}, + /* 5, 8 -> */ {5, 8}, /* no alternatives */ + /* 6, 8 -> */ {6, 8}, /* no alternatives */ + /* 7, 8 -> */ {7, 8}, /* no alternatives */ + /* 8, 8 -> */ {11, 0}, + /* 9, 8 -> */ {8, 0}, + /* 10, 8 -> */ {7, 7}, + /* 11, 8 -> */ {-1,-1}, /* does not exist */ + /* 12, 8 -> */ {-1,-1}, /* does not exist */ + /* 0, 9 -> */ {0, 9}, /* no alternatives */ + /* 1, 9 -> */ {1, 9}, /* no alternatives */ + /* 2, 9 -> */ {4, 1}, + /* 3, 9 -> */ {3, 9}, /* no alternatives */ + /* 4, 9 -> */ {7, 4}, + /* 5, 9 -> */ {5, 9}, /* no alternatives */ + /* 6, 9 -> */ {6, 9}, /* no alternatives */ + /* 7, 9 -> */ {7, 9}, /* no alternatives */ + /* 8, 9 -> */ {7, 1}, + /* 9, 9 -> */ {9, 1}, + /* 10, 9 -> */ {7, 10}, + /* 11, 9 -> */ {-1,-1}, /* does not exist */ + /* 12, 9 -> */ {-1,-1}, /* does not exist */ + /* 0, 10 -> */ {0, 10}, /* no alternatives */ + /* 1, 10 -> */ {1, 10}, /* no alternatives */ + /* 2, 10 -> */ {2, 10}, /* no alternatives */ + /* 3, 10 -> */ {3, 10}, /* no alternatives */ + /* 4, 10 -> */ {4, 10}, /* no alternatives */ + /* 5, 10 -> */ {10, 6}, + /* 6, 10 -> */ {7, 6}, + /* 7, 10 -> */ {10, 9}, + /* 8, 10 -> */ {8, 10}, /* no alternatives */ + /* 9, 10 -> */ {9, 10}, /* no alternatives */ + /* 10, 10 -> */ {10, 10}, /* no alternatives */ + /* 11, 10 -> */ {-1,-1}, /* does not exist */ + /* 12, 10 -> */ {-1,-1}, /* does not exist */ + /* 0, 11 -> */ {0, 11}, /* no alternatives */ + /* 1, 11 -> */ {1, 11}, /* no alternatives */ + /* 2, 11 -> */ {2, 11}, /* no alternatives */ + /* 3, 11 -> */ {3, 11}, /* no alternatives */ + /* 4, 11 -> */ {4, 11}, /* no alternatives */ + /* 5, 11 -> */ {5, 5}, + /* 6, 11 -> */ {7, 2}, + /* 7, 11 -> */ {10, 12}, + /* 8, 11 -> */ {8, 11}, /* no alternatives */ + /* 9, 11 -> */ {9, 11}, /* no alternatives */ + /* 10, 11 -> */ {10, 11}, /* no alternatives */ + /* 11, 11 -> */ {-1,-1}, /* does not exist */ + /* 12, 11 -> */ {-1,-1}, /* does not exist */ + /* 0, 12 -> */ {0, 12}, /* no alternatives */ + /* 1, 12 -> */ {1, 12}, /* no alternatives */ + /* 2, 12 -> */ {5, 2}, + /* 3, 12 -> */ {3, 12}, /* no alternatives */ + /* 4, 12 -> */ {8, 6}, + /* 5, 12 -> */ {5, 12}, /* no alternatives */ + /* 6, 12 -> */ {6, 12}, /* no alternatives */ + /* 7, 12 -> */ {7, 12}, /* no alternatives */ + /* 8, 12 -> */ {11, 2}, + /* 9, 12 -> */ {8, 2}, + /* 10, 12 -> */ {7, 11}, + /* 11, 12 -> */ {-1,-1}, /* does not exist */ + /* 12, 12 -> */ {-1,-1}, /* does not exist */ +}; +static const MetamapEntry metamap_T[] = { + /* 0, 0 -> */ {0, 0}, /* no alternatives */ + /* 1, 0 -> */ {1, 0}, /* no alternatives */ + /* 2, 0 -> */ {2, 0}, /* no alternatives */ + /* 3, 0 -> */ {3, 0}, /* no alternatives */ + /* 4, 0 -> */ {3, 3}, + /* 5, 0 -> */ {3, 1}, + /* 6, 0 -> */ {2, 2}, + /* 7, 0 -> */ {8, 3}, + /* 8, 0 -> */ {9, 1}, + /* 9, 0 -> */ {9, 3}, + /* 10, 0 -> */ {4, 6}, + /* 11, 0 -> */ {4, 4}, + /* 12, 0 -> */ {6, 2}, + /* 0, 1 -> */ {0, 1}, /* no alternatives */ + /* 1, 1 -> */ {1, 1}, /* no alternatives */ + /* 2, 1 -> */ {2, 1}, /* no alternatives */ + /* 3, 1 -> */ {5, 0}, + /* 4, 1 -> */ {4, 1}, /* no alternatives */ + /* 5, 1 -> */ {8, 4}, + /* 6, 1 -> */ {6, 1}, /* no alternatives */ + /* 7, 1 -> */ {6, 5}, + /* 8, 1 -> */ {11, 0}, + /* 9, 1 -> */ {8, 0}, + /* 10, 1 -> */ {5, 5}, + /* 11, 1 -> */ {-1,-1}, /* does not exist */ + /* 12, 1 -> */ {-1,-1}, /* does not exist */ + /* 0, 2 -> */ {0, 2}, /* no alternatives */ + /* 1, 2 -> */ {1, 2}, /* no alternatives */ + /* 2, 2 -> */ {6, 0}, + /* 3, 2 -> */ {3, 2}, /* no alternatives */ + /* 4, 2 -> */ {4, 2}, /* no alternatives */ + /* 5, 2 -> */ {5, 4}, + /* 6, 2 -> */ {12, 0}, + /* 7, 2 -> */ {10, 0}, + /* 8, 2 -> */ {6, 4}, + /* 9, 2 -> */ {9, 2}, /* no alternatives */ + /* 10, 2 -> */ {8, 6}, + /* 11, 2 -> */ {-1,-1}, /* does not exist */ + /* 12, 2 -> */ {-1,-1}, /* does not exist */ + /* 0, 3 -> */ {0, 3}, /* no alternatives */ + /* 1, 3 -> */ {1, 3}, /* no alternatives */ + /* 2, 3 -> */ {2, 3}, /* no alternatives */ + /* 3, 3 -> */ {4, 0}, + /* 4, 3 -> */ {4, 3}, /* no alternatives */ + /* 5, 3 -> */ {8, 5}, + /* 6, 3 -> */ {6, 3}, /* no alternatives */ + /* 7, 3 -> */ {6, 6}, + /* 8, 3 -> */ {4, 5}, + /* 9, 3 -> */ {9, 0}, + /* 10, 3 -> */ {5, 6}, + /* 11, 3 -> */ {-1,-1}, /* does not exist */ + /* 12, 3 -> */ {-1,-1}, /* does not exist */ + /* 0, 4 -> */ {0, 4}, /* no alternatives */ + /* 1, 4 -> */ {1, 4}, /* no alternatives */ + /* 2, 4 -> */ {2, 4}, /* no alternatives */ + /* 3, 4 -> */ {3, 4}, /* no alternatives */ + /* 4, 4 -> */ {8, 1}, + /* 5, 4 -> */ {5, 2}, + /* 6, 4 -> */ {8, 2}, + /* 7, 4 -> */ {7, 4}, /* no alternatives */ + /* 8, 4 -> */ {5, 1}, + /* 9, 4 -> */ {9, 4}, /* no alternatives */ + /* 10, 4 -> */ {10, 4}, /* no alternatives */ + /* 11, 4 -> */ {-1,-1}, /* does not exist */ + /* 12, 4 -> */ {-1,-1}, /* does not exist */ + /* 0, 5 -> */ {0, 5}, /* no alternatives */ + /* 1, 5 -> */ {1, 5}, /* no alternatives */ + /* 2, 5 -> */ {2, 5}, /* no alternatives */ + /* 3, 5 -> */ {3, 5}, /* no alternatives */ + /* 4, 5 -> */ {7, 0}, + /* 5, 5 -> */ {10, 1}, + /* 6, 5 -> */ {7, 1}, + /* 7, 5 -> */ {7, 5}, /* no alternatives */ + /* 8, 5 -> */ {5, 3}, + /* 9, 5 -> */ {9, 5}, /* no alternatives */ + /* 10, 5 -> */ {10, 5}, /* no alternatives */ + /* 11, 5 -> */ {-1,-1}, /* does not exist */ + /* 12, 5 -> */ {-1,-1}, /* does not exist */ + /* 0, 6 -> */ {0, 6}, /* no alternatives */ + /* 1, 6 -> */ {1, 6}, /* no alternatives */ + /* 2, 6 -> */ {2, 6}, /* no alternatives */ + /* 3, 6 -> */ {3, 6}, /* no alternatives */ + /* 4, 6 -> */ {7, 2}, + /* 5, 6 -> */ {10, 3}, + /* 6, 6 -> */ {7, 3}, + /* 7, 6 -> */ {7, 6}, /* no alternatives */ + /* 8, 6 -> */ {10, 2}, + /* 9, 6 -> */ {9, 6}, /* no alternatives */ + /* 10, 6 -> */ {10, 6}, /* no alternatives */ + /* 11, 6 -> */ {-1,-1}, /* does not exist */ + /* 12, 6 -> */ {-1,-1}, /* does not exist */ +}; +static const MetamapEntry metamap_P[] = { + /* 0, 0 -> */ {0, 0}, /* no alternatives */ + /* 1, 0 -> */ {1, 0}, /* no alternatives */ + /* 2, 0 -> */ {2, 0}, /* no alternatives */ + /* 3, 0 -> */ {3, 0}, /* no alternatives */ + /* 4, 0 -> */ {3, 4}, + /* 5, 0 -> */ {2, 5}, + /* 6, 0 -> */ {2, 3}, + /* 7, 0 -> */ {8, 4}, + /* 8, 0 -> */ {9, 5}, + /* 9, 0 -> */ {9, 4}, + /* 10, 0 -> */ {4, 9}, + /* 11, 0 -> */ {4, 8}, + /* 12, 0 -> */ {6, 3}, + /* 0, 1 -> */ {0, 1}, /* no alternatives */ + /* 1, 1 -> */ {1, 1}, /* no alternatives */ + /* 2, 1 -> */ {2, 1}, /* no alternatives */ + /* 3, 1 -> */ {3, 1}, /* no alternatives */ + /* 4, 1 -> */ {2, 10}, + /* 5, 1 -> */ {3, 2}, + /* 6, 1 -> */ {2, 4}, + /* 7, 1 -> */ {8, 10}, + /* 8, 1 -> */ {9, 2}, + /* 9, 1 -> */ {9, 10}, + /* 10, 1 -> */ {7, 4}, + /* 11, 1 -> */ {8, 2}, + /* 12, 1 -> */ {6, 4}, + /* 0, 2 -> */ {0, 2}, /* no alternatives */ + /* 1, 2 -> */ {1, 2}, /* no alternatives */ + /* 2, 2 -> */ {2, 2}, /* no alternatives */ + /* 3, 2 -> */ {5, 1}, + /* 4, 2 -> */ {4, 2}, /* no alternatives */ + /* 5, 2 -> */ {8, 6}, + /* 6, 2 -> */ {6, 2}, /* no alternatives */ + /* 7, 2 -> */ {6, 7}, + /* 8, 2 -> */ {4, 6}, + /* 9, 2 -> */ {8, 1}, + /* 10, 2 -> */ {5, 7}, + /* 11, 2 -> */ {-1,-1}, /* does not exist */ + /* 12, 2 -> */ {-1,-1}, /* does not exist */ + /* 0, 3 -> */ {0, 3}, /* no alternatives */ + /* 1, 3 -> */ {1, 3}, /* no alternatives */ + /* 2, 3 -> */ {6, 0}, + /* 3, 3 -> */ {3, 3}, /* no alternatives */ + /* 4, 3 -> */ {4, 3}, /* no alternatives */ + /* 5, 3 -> */ {5, 8}, + /* 6, 3 -> */ {12, 0}, + /* 7, 3 -> */ {10, 0}, + /* 8, 3 -> */ {6, 8}, + /* 9, 3 -> */ {9, 3}, /* no alternatives */ + /* 10, 3 -> */ {8, 9}, + /* 11, 3 -> */ {-1,-1}, /* does not exist */ + /* 12, 3 -> */ {-1,-1}, /* does not exist */ + /* 0, 4 -> */ {0, 4}, /* no alternatives */ + /* 1, 4 -> */ {1, 4}, /* no alternatives */ + /* 2, 4 -> */ {6, 1}, + /* 3, 4 -> */ {4, 0}, + /* 4, 4 -> */ {4, 4}, /* no alternatives */ + /* 5, 4 -> */ {5, 6}, + /* 6, 4 -> */ {12, 1}, + /* 7, 4 -> */ {6, 9}, + /* 8, 4 -> */ {6, 6}, + /* 9, 4 -> */ {9, 0}, + /* 10, 4 -> */ {5, 9}, + /* 11, 4 -> */ {-1,-1}, /* does not exist */ + /* 12, 4 -> */ {-1,-1}, /* does not exist */ + /* 0, 5 -> */ {0, 5}, /* no alternatives */ + /* 1, 5 -> */ {1, 5}, /* no alternatives */ + /* 2, 5 -> */ {5, 0}, + /* 3, 5 -> */ {3, 5}, /* no alternatives */ + /* 4, 5 -> */ {8, 8}, + /* 5, 5 -> */ {5, 5}, /* no alternatives */ + /* 6, 5 -> */ {6, 5}, /* no alternatives */ + /* 7, 5 -> */ {7, 5}, /* no alternatives */ + /* 8, 5 -> */ {11, 0}, + /* 9, 5 -> */ {8, 0}, + /* 10, 5 -> */ {7, 6}, + /* 11, 5 -> */ {-1,-1}, /* does not exist */ + /* 12, 5 -> */ {-1,-1}, /* does not exist */ + /* 0, 6 -> */ {0, 6}, /* no alternatives */ + /* 1, 6 -> */ {1, 6}, /* no alternatives */ + /* 2, 6 -> */ {2, 6}, /* no alternatives */ + /* 3, 6 -> */ {3, 6}, /* no alternatives */ + /* 4, 6 -> */ {11, 1}, + /* 5, 6 -> */ {5, 4}, + /* 6, 6 -> */ {7, 0}, + /* 7, 6 -> */ {10, 5}, + /* 8, 6 -> */ {5, 2}, + /* 9, 6 -> */ {9, 6}, /* no alternatives */ + /* 10, 6 -> */ {10, 6}, /* no alternatives */ + /* 11, 6 -> */ {-1,-1}, /* does not exist */ + /* 12, 6 -> */ {-1,-1}, /* does not exist */ + /* 0, 7 -> */ {0, 7}, /* no alternatives */ + /* 1, 7 -> */ {1, 7}, /* no alternatives */ + /* 2, 7 -> */ {2, 7}, /* no alternatives */ + /* 3, 7 -> */ {3, 7}, /* no alternatives */ + /* 4, 7 -> */ {7, 1}, + /* 5, 7 -> */ {10, 2}, + /* 6, 7 -> */ {7, 2}, + /* 7, 7 -> */ {7, 7}, /* no alternatives */ + /* 8, 7 -> */ {4, 10}, + /* 9, 7 -> */ {9, 7}, /* no alternatives */ + /* 10, 7 -> */ {10, 7}, /* no alternatives */ + /* 11, 7 -> */ {-1,-1}, /* does not exist */ + /* 12, 7 -> */ {-1,-1}, /* does not exist */ + /* 0, 8 -> */ {0, 8}, /* no alternatives */ + /* 1, 8 -> */ {1, 8}, /* no alternatives */ + /* 2, 8 -> */ {2, 8}, /* no alternatives */ + /* 3, 8 -> */ {3, 8}, /* no alternatives */ + /* 4, 8 -> */ {8, 5}, + /* 5, 8 -> */ {5, 3}, + /* 6, 8 -> */ {8, 3}, + /* 7, 8 -> */ {7, 8}, /* no alternatives */ + /* 8, 8 -> */ {4, 5}, + /* 9, 8 -> */ {9, 8}, /* no alternatives */ + /* 10, 8 -> */ {10, 8}, /* no alternatives */ + /* 11, 8 -> */ {-1,-1}, /* does not exist */ + /* 12, 8 -> */ {-1,-1}, /* does not exist */ + /* 0, 9 -> */ {0, 9}, /* no alternatives */ + /* 1, 9 -> */ {1, 9}, /* no alternatives */ + /* 2, 9 -> */ {2, 9}, /* no alternatives */ + /* 3, 9 -> */ {3, 9}, /* no alternatives */ + /* 4, 9 -> */ {7, 3}, + /* 5, 9 -> */ {10, 4}, + /* 6, 9 -> */ {10, 1}, + /* 7, 9 -> */ {10, 10}, + /* 8, 9 -> */ {10, 3}, + /* 9, 9 -> */ {9, 9}, /* no alternatives */ + /* 10, 9 -> */ {10, 9}, /* no alternatives */ + /* 11, 9 -> */ {-1,-1}, /* does not exist */ + /* 12, 9 -> */ {-1,-1}, /* does not exist */ + /* 0, 10 -> */ {0, 10}, /* no alternatives */ + /* 1, 10 -> */ {1, 10}, /* no alternatives */ + /* 2, 10 -> */ {4, 1}, + /* 3, 10 -> */ {3, 10}, /* no alternatives */ + /* 4, 10 -> */ {8, 7}, + /* 5, 10 -> */ {5, 10}, /* no alternatives */ + /* 6, 10 -> */ {6, 10}, /* no alternatives */ + /* 7, 10 -> */ {7, 10}, /* no alternatives */ + /* 8, 10 -> */ {4, 7}, + /* 9, 10 -> */ {9, 1}, + /* 10, 10 -> */ {7, 9}, + /* 11, 10 -> */ {-1,-1}, /* does not exist */ + /* 12, 10 -> */ {-1,-1}, /* does not exist */ +}; +static const MetamapEntry metamap_F[] = { + /* 0, 0 -> */ {0, 0}, /* no alternatives */ + /* 1, 0 -> */ {1, 0}, /* no alternatives */ + /* 2, 0 -> */ {2, 0}, /* no alternatives */ + /* 3, 0 -> */ {3, 0}, /* no alternatives */ + /* 4, 0 -> */ {3, 3}, + /* 5, 0 -> */ {2, 4}, + /* 6, 0 -> */ {2, 2}, + /* 7, 0 -> */ {8, 3}, + /* 8, 0 -> */ {9, 4}, + /* 9, 0 -> */ {9, 3}, + /* 10, 0 -> */ {4, 9}, + /* 11, 0 -> */ {4, 8}, + /* 12, 0 -> */ {6, 2}, + /* 0, 1 -> */ {0, 1}, /* no alternatives */ + /* 1, 1 -> */ {1, 1}, /* no alternatives */ + /* 2, 1 -> */ {2, 1}, /* no alternatives */ + /* 3, 1 -> */ {3, 1}, /* no alternatives */ + /* 4, 1 -> */ {2, 10}, + /* 5, 1 -> */ {2, 6}, + /* 6, 1 -> */ {2, 3}, + /* 7, 1 -> */ {8, 10}, + /* 8, 1 -> */ {9, 6}, + /* 9, 1 -> */ {9, 10}, + /* 10, 1 -> */ {7, 3}, + /* 11, 1 -> */ {8, 6}, + /* 12, 1 -> */ {6, 3}, + /* 0, 2 -> */ {0, 2}, /* no alternatives */ + /* 1, 2 -> */ {1, 2}, /* no alternatives */ + /* 2, 2 -> */ {6, 0}, + /* 3, 2 -> */ {3, 2}, /* no alternatives */ + /* 4, 2 -> */ {4, 2}, /* no alternatives */ + /* 5, 2 -> */ {5, 8}, + /* 6, 2 -> */ {12, 0}, + /* 7, 2 -> */ {10, 0}, + /* 8, 2 -> */ {6, 8}, + /* 9, 2 -> */ {9, 2}, /* no alternatives */ + /* 10, 2 -> */ {8, 9}, + /* 11, 2 -> */ {-1,-1}, /* does not exist */ + /* 12, 2 -> */ {-1,-1}, /* does not exist */ + /* 0, 3 -> */ {0, 3}, /* no alternatives */ + /* 1, 3 -> */ {1, 3}, /* no alternatives */ + /* 2, 3 -> */ {6, 1}, + /* 3, 3 -> */ {4, 0}, + /* 4, 3 -> */ {4, 3}, /* no alternatives */ + /* 5, 3 -> */ {5, 5}, + /* 6, 3 -> */ {12, 1}, + /* 7, 3 -> */ {6, 9}, + /* 8, 3 -> */ {6, 5}, + /* 9, 3 -> */ {9, 0}, + /* 10, 3 -> */ {5, 9}, + /* 11, 3 -> */ {-1,-1}, /* does not exist */ + /* 12, 3 -> */ {-1,-1}, /* does not exist */ + /* 0, 4 -> */ {0, 4}, /* no alternatives */ + /* 1, 4 -> */ {1, 4}, /* no alternatives */ + /* 2, 4 -> */ {5, 0}, + /* 3, 4 -> */ {3, 4}, /* no alternatives */ + /* 4, 4 -> */ {8, 8}, + /* 5, 4 -> */ {5, 4}, /* no alternatives */ + /* 6, 4 -> */ {6, 4}, /* no alternatives */ + /* 7, 4 -> */ {7, 4}, /* no alternatives */ + /* 8, 4 -> */ {11, 0}, + /* 9, 4 -> */ {8, 0}, + /* 10, 4 -> */ {7, 5}, + /* 11, 4 -> */ {-1,-1}, /* does not exist */ + /* 12, 4 -> */ {-1,-1}, /* does not exist */ + /* 0, 5 -> */ {0, 5}, /* no alternatives */ + /* 1, 5 -> */ {1, 5}, /* no alternatives */ + /* 2, 5 -> */ {2, 5}, /* no alternatives */ + /* 3, 5 -> */ {3, 5}, /* no alternatives */ + /* 4, 5 -> */ {11, 1}, + /* 5, 5 -> */ {5, 3}, + /* 6, 5 -> */ {7, 0}, + /* 7, 5 -> */ {10, 4}, + /* 8, 5 -> */ {4, 6}, + /* 9, 5 -> */ {9, 5}, /* no alternatives */ + /* 10, 5 -> */ {10, 5}, /* no alternatives */ + /* 11, 5 -> */ {-1,-1}, /* does not exist */ + /* 12, 5 -> */ {-1,-1}, /* does not exist */ + /* 0, 6 -> */ {0, 6}, /* no alternatives */ + /* 1, 6 -> */ {1, 6}, /* no alternatives */ + /* 2, 6 -> */ {5, 1}, + /* 3, 6 -> */ {3, 6}, /* no alternatives */ + /* 4, 6 -> */ {8, 5}, + /* 5, 6 -> */ {5, 6}, /* no alternatives */ + /* 6, 6 -> */ {6, 6}, /* no alternatives */ + /* 7, 6 -> */ {7, 6}, /* no alternatives */ + /* 8, 6 -> */ {4, 5}, + /* 9, 6 -> */ {8, 1}, + /* 10, 6 -> */ {7, 7}, + /* 11, 6 -> */ {-1,-1}, /* does not exist */ + /* 12, 6 -> */ {-1,-1}, /* does not exist */ + /* 0, 7 -> */ {0, 7}, /* no alternatives */ + /* 1, 7 -> */ {1, 7}, /* no alternatives */ + /* 2, 7 -> */ {2, 7}, /* no alternatives */ + /* 3, 7 -> */ {3, 7}, /* no alternatives */ + /* 4, 7 -> */ {4, 7}, /* no alternatives */ + /* 5, 7 -> */ {4, 10}, + /* 6, 7 -> */ {7, 1}, + /* 7, 7 -> */ {10, 6}, + /* 8, 7 -> */ {8, 7}, /* no alternatives */ + /* 9, 7 -> */ {9, 7}, /* no alternatives */ + /* 10, 7 -> */ {10, 7}, /* no alternatives */ + /* 11, 7 -> */ {-1,-1}, /* does not exist */ + /* 12, 7 -> */ {-1,-1}, /* does not exist */ + /* 0, 8 -> */ {0, 8}, /* no alternatives */ + /* 1, 8 -> */ {1, 8}, /* no alternatives */ + /* 2, 8 -> */ {2, 8}, /* no alternatives */ + /* 3, 8 -> */ {3, 8}, /* no alternatives */ + /* 4, 8 -> */ {8, 4}, + /* 5, 8 -> */ {5, 2}, + /* 6, 8 -> */ {8, 2}, + /* 7, 8 -> */ {7, 8}, /* no alternatives */ + /* 8, 8 -> */ {4, 4}, + /* 9, 8 -> */ {9, 8}, /* no alternatives */ + /* 10, 8 -> */ {10, 8}, /* no alternatives */ + /* 11, 8 -> */ {-1,-1}, /* does not exist */ + /* 12, 8 -> */ {-1,-1}, /* does not exist */ + /* 0, 9 -> */ {0, 9}, /* no alternatives */ + /* 1, 9 -> */ {1, 9}, /* no alternatives */ + /* 2, 9 -> */ {2, 9}, /* no alternatives */ + /* 3, 9 -> */ {3, 9}, /* no alternatives */ + /* 4, 9 -> */ {7, 2}, + /* 5, 9 -> */ {10, 3}, + /* 6, 9 -> */ {10, 1}, + /* 7, 9 -> */ {10, 10}, + /* 8, 9 -> */ {10, 2}, + /* 9, 9 -> */ {9, 9}, /* no alternatives */ + /* 10, 9 -> */ {10, 9}, /* no alternatives */ + /* 11, 9 -> */ {-1,-1}, /* does not exist */ + /* 12, 9 -> */ {-1,-1}, /* does not exist */ + /* 0, 10 -> */ {0, 10}, /* no alternatives */ + /* 1, 10 -> */ {1, 10}, /* no alternatives */ + /* 2, 10 -> */ {4, 1}, + /* 3, 10 -> */ {3, 10}, /* no alternatives */ + /* 4, 10 -> */ {5, 7}, + /* 5, 10 -> */ {5, 10}, /* no alternatives */ + /* 6, 10 -> */ {6, 10}, /* no alternatives */ + /* 7, 10 -> */ {7, 10}, /* no alternatives */ + /* 8, 10 -> */ {6, 7}, + /* 9, 10 -> */ {9, 1}, + /* 10, 10 -> */ {7, 9}, + /* 11, 10 -> */ {-1,-1}, /* does not exist */ + /* 12, 10 -> */ {-1,-1}, /* does not exist */ +}; +static const MetamapEntry *const metamap[] = { + metamap_H, + metamap_T, + metamap_P, + metamap_F, +}; diff --git a/apps/plugins/puzzles/src/hat.c b/apps/plugins/puzzles/src/hat.c new file mode 100644 index 0000000000..176d1f049e --- /dev/null +++ b/apps/plugins/puzzles/src/hat.c @@ -0,0 +1,891 @@ +/* + * Code to generate patches of the aperiodic 'hat' tiling discovered + * in 2023. + * + * This uses the 'combinatorial coordinates' system documented in my + * public article + * https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-tilings/ + * + * The internal document auxiliary/doc/hats.html also contains an + * explanation of the basic ideas of this algorithm (less polished but + * containing more detail). + * + * Neither of those documents can really be put in a source file, + * because they just have too many complicated diagrams. So read at + * least one of those first; the comments in here will refer to it. + * + * Discoverers' website: https://cs.uwaterloo.ca/~csk/hat/ + * Preprint of paper: https://arxiv.org/abs/2303.10798 + */ + +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif +#include +#include +#include +#include + +#include "puzzles.h" +#include "hat.h" +#include "hat-internal.h" + +void hat_kiteenum_first(KiteEnum *s, int w, int h) +{ + Kite start = { {0,0}, {0, 3}, {3, 0}, {2, 2} }; + size_t i; + + for (i = 0; i < KE_NKEEP; i++) + s->recent[i] = start; /* initialise to *something* */ + s->curr_index = 0; + s->curr = &s->recent[s->curr_index]; + s->state = 1; + s->w = w; + s->h = h; + s->x = 0; + s->y = 0; +} + +bool hat_kiteenum_next(KiteEnum *s) +{ + unsigned lastbut1 = s->last_index; + s->last_index = s->curr_index; + s->curr_index = (s->curr_index + 1) % KE_NKEEP; + s->curr = &s->recent[s->curr_index]; + + switch (s->state) { + /* States 1,2,3 walk rightwards along the upper side of a + * horizontal grid line with a pointy kite end at the start + * point */ + case 1: + s->last_step = KS_F_RIGHT; + s->state = 2; + break; + + case 2: + if (s->x+1 >= s->w) { + s->last_step = KS_F_RIGHT; + s->state = 4; + break; + } + s->last_step = KS_RIGHT; + s->state = 3; + s->x++; + break; + + case 3: + s->last_step = KS_RIGHT; + s->state = 1; + break; + + /* State 4 is special: we've just moved up into a row below a + * grid line, but we can't produce the rightmost tile of that + * row because it's not adjacent any tile so far emitted. So + * instead, emit the second-rightmost tile, and next time, + * we'll emit the rightmost. */ + case 4: + s->last_step = KS_LEFT; + s->state = 5; + break; + + /* And now we have to emit the third-rightmost tile relative + * to the last but one tile we emitted (the one from state 2, + * not state 4). */ + case 5: + s->last_step = KS_RIGHT; + s->last_index = lastbut1; + s->state = 6; + break; + + /* Now states 6-8 handle the general case of walking leftwards + * along the lower side of a line, starting from a + * right-angled kite end. */ + case 6: + if (s->x <= 0) { + if (s->y+1 >= s->h) { + s->state = 0; + return false; + } + s->last_step = KS_RIGHT; + s->state = 9; + s->y++; + break; + } + s->last_step = KS_F_RIGHT; + s->state = 7; + s->x--; + break; + + case 7: + s->last_step = KS_RIGHT; + s->state = 8; + break; + + case 8: + s->last_step = KS_RIGHT; + s->state = 6; + break; + + /* States 9,10,11 walk rightwards along the upper side of a + * horizontal grid line with a right-angled kite end at the + * start point. This time there's no awkward transition from + * the previous row. */ + case 9: + s->last_step = KS_RIGHT; + s->state = 10; + break; + + case 10: + s->last_step = KS_RIGHT; + s->state = 11; + break; + + case 11: + if (s->x+1 >= s->w) { + /* Another awkward transition to the next row, where we + * have to generate it based on the previous state-9 tile. + * But this time at least we generate the rightmost tile + * of the new row, so the next states will be simple. */ + s->last_step = KS_F_RIGHT; + s->last_index = lastbut1; + s->state = 12; + break; + } + s->last_step = KS_F_RIGHT; + s->state = 9; + s->x++; + break; + + /* States 12,13,14 walk leftwards along the upper edge of a + * horizontal grid line with a pointy kite end at the start + * point */ + case 12: + s->last_step = KS_F_RIGHT; + s->state = 13; + break; + + case 13: + if (s->x <= 0) { + if (s->y+1 >= s->h) { + s->state = 0; + return false; + } + s->last_step = KS_LEFT; + s->state = 1; + s->y++; + break; + } + s->last_step = KS_RIGHT; + s->state = 14; + s->x--; + break; + + case 14: + s->last_step = KS_RIGHT; + s->state = 12; + break; + + default: + return false; + } + + *s->curr = kite_step(s->recent[s->last_index], s->last_step); + return true; +} + +/* + * The actual tables. + */ +#include "hat-tables.h" + +/* + * One set of tables that we write by hand: the permitted ways to + * extend the coordinate system outwards from a given metatile. + * + * One obvious approach would be to make a table of all the places + * each metatile can appear in the expansion of another (e.g. H can be + * subtile 0, 1 or 2 of another H, subtile 0 of a T, or 0 or 1 of a P + * or an F), and when we need to decide what our current topmost tile + * turns out to be a subtile of, choose equiprobably at random from + * those options. + * + * That's what I did originally, but a better approach is to skew the + * probabilities. We'd like to generate our patch of actual tiling + * uniformly at random, in the sense that if you selected uniformly + * from a very large region of the plane, the distribution of possible + * finite patches of tiling would converge to some limit as that + * region tended to infinity, and we'd be picking from that limiting + * distribution on finite patches. + * + * For this we have to refer back to the original paper, which + * indicates the subset of each metatile's expansion that can be + * considered to 'belong' to that metatile, such that every subtile + * belongs to exactly one parent metatile, and the overlaps are + * eliminated. Reading out the diagrams from their Figure 2.8: + * + * - H: we discard three of the outer F subtiles, in the symmetric + * positions index by our coordinates as 7, 10, 11. So we keep the + * remaining subtiles {0,1,2,3,4,5,6,8,9,12}, which consist of + * three H, one T, three P and three F. + * + * - T: only the central H expanded from a T is considered to belong + * to it, so we just keep {0}, a single H. + * + * - P: we discard everything intersected by a long edge of the + * parallelogram, leaving the central three tiles and the endmost + * pair of F. That is, we keep {0,1,4,5,10}, consisting of two H, + * one P and two F. + * + * - F: looks like P at one end, and we retain the corresponding set + * of tiles there, but at the other end we keep the two F on either + * side of the endmost one. So we keep {0,1,3,6,8,10}, consisting of + * two H, one P and _three_ F. + * + * Adding up the tile numbers gives us this matrix system: + * + * (H_1) (3 1 2 2)(H_0) + * (T_1) = (1 0 0 0)(T_0) + * (P_1) (3 0 1 1)(P_0) + * (F_1) (3 0 2 3)(F_0) + * + * which says that if you have a patch of metatiling consisting of H_0 + * H tiles, T_0 T tiles etc, then this matrix shows the number H_1 of + * smaller H tiles, etc, expanded from it. + * + * If you expand _many_ times, that's equivalent to raising the matrix + * to a power: + * + * n + * (H_n) (3 1 2 2) (H_0) + * (T_n) = (1 0 0 0) (T_0) + * (P_n) (3 0 1 1) (P_0) + * (F_n) (3 0 2 3) (F_0) + * + * The limiting distribution of metatiles is obtained by looking at + * the four-way ratio between H_n, T_n, P_n and F_n as n tends to + * infinity. To calculate this, we find the eigenvalues and + * eigenvectors of the matrix, and extract the eigenvector + * corresponding to the eigenvalue of largest magnitude. (Things get + * more complicated in cases where there isn't a _unique_ eigenvalue + * of largest magnitude, but here, there is.) + * + * That eigenvector is + * + * [ 1 ] [ 1 ] + * [ (7 - 3 sqrt(5)) / 2 ] ~= [ 0.14589803375031545538 ] + * [ 3 sqrt(5) - 6 ] [ 0.70820393249936908922 ] + * [ (9 - 3 sqrt(5)) / 2 ] [ 1.14589803375031545538 ] + * + * So those are the limiting relative proportions of metatiles. + * + * So if we have a particular metatile, how likely is it for its + * parent to be one of those? We have to adjust by the number of + * metatiles of each type that each tile has as its children. For + * example, the P and F tiles have one P child each, but the H has + * three P children. So if we have a P, the proportion of H in its + * potential ancestry is three times what's shown here. (And T can't + * occur at all as a parent.) + * + * In other words, we should choose _each coordinate_ with probability + * corresponding to one of those numbers (scaled down so they all sum + * to 1). Continuing to use P as an example, it will be: + * + * - child 4 of H with relative probability 1 + * - child 5 of H with relative probability 1 + * - child 6 of H with relative probability 1 + * - child 4 of P with relative probability 0.70820393249936908922 + * - child 3 of F with relative probability 1.14589803375031545538 + * + * and then we obtain the true probabilities by scaling those values + * down so that they sum to 1. + * + * The tables below give a reasonable approximation in 32-bit + * integers to these proportions. + */ + +typedef struct MetatilePossibleParent { + TileType type; + unsigned index; + unsigned long probability; +} MetatilePossibleParent; + +/* The above probabilities scaled up by 10000000 */ +#define PROB_H 10000000 +#define PROB_T 1458980 +#define PROB_P 7082039 +#define PROB_F 11458980 + +static const MetatilePossibleParent parents_H[] = { + { TT_H, 0, PROB_H }, + { TT_H, 1, PROB_H }, + { TT_H, 2, PROB_H }, + { TT_T, 0, PROB_T }, + { TT_P, 0, PROB_P }, + { TT_P, 1, PROB_P }, + { TT_F, 0, PROB_F }, + { TT_F, 1, PROB_F }, +}; +static const MetatilePossibleParent parents_T[] = { + { TT_H, 3, PROB_H }, +}; +static const MetatilePossibleParent parents_P[] = { + { TT_H, 4, PROB_H }, + { TT_H, 5, PROB_H }, + { TT_H, 6, PROB_H }, + { TT_P, 4, PROB_P }, + { TT_F, 3, PROB_F }, +}; +static const MetatilePossibleParent parents_F[] = { + { TT_H, 8, PROB_H }, + { TT_H, 9, PROB_H }, + { TT_H, 12, PROB_H }, + { TT_P, 5, PROB_P }, + { TT_P, 10, PROB_P }, + { TT_F, 6, PROB_F }, + { TT_F, 8, PROB_F }, + { TT_F, 10, PROB_F }, +}; + +static const MetatilePossibleParent *const possible_parents[] = { + parents_H, parents_T, parents_P, parents_F, +}; +static const size_t n_possible_parents[] = { + lenof(parents_H), lenof(parents_T), lenof(parents_P), lenof(parents_F), +}; + +/* + * Similarly, we also want to choose our absolute starting hat with + * close to uniform probability, which again we do by looking at the + * limiting ratio of the metatile types, and this time, scaling by the + * number of hats in each metatile. + * + * We cheatingly use the same MetatilePossibleParent struct, because + * it's got all the right fields, even if it has an inappropriate + * name. + */ +static const MetatilePossibleParent starting_hats[] = { + { TT_H, 0, PROB_H }, + { TT_H, 1, PROB_H }, + { TT_H, 2, PROB_H }, + { TT_H, 3, PROB_H }, + { TT_T, 0, PROB_P }, + { TT_P, 0, PROB_P }, + { TT_P, 1, PROB_P }, + { TT_F, 0, PROB_F }, + { TT_F, 1, PROB_F }, +}; + +#undef PROB_H +#undef PROB_T +#undef PROB_P +#undef PROB_F + +HatCoords *hat_coords_new(void) +{ + HatCoords *hc = snew(HatCoords); + hc->nc = hc->csize = 0; + hc->c = NULL; + return hc; +} + +void hat_coords_free(HatCoords *hc) +{ + if (hc) { + sfree(hc->c); + sfree(hc); + } +} + +void hat_coords_make_space(HatCoords *hc, size_t size) +{ + if (hc->csize < size) { + hc->csize = hc->csize * 5 / 4 + 16; + if (hc->csize < size) + hc->csize = size; + hc->c = sresize(hc->c, hc->csize, HatCoord); + } +} + +HatCoords *hat_coords_copy(HatCoords *hc_in) +{ + HatCoords *hc_out = hat_coords_new(); + hat_coords_make_space(hc_out, hc_in->nc); + memcpy(hc_out->c, hc_in->c, hc_in->nc * sizeof(*hc_out->c)); + hc_out->nc = hc_in->nc; + return hc_out; +} + +static const MetatilePossibleParent *choose_mpp( + random_state *rs, const MetatilePossibleParent *parents, size_t nparents) +{ + /* + * If we needed to do this _efficiently_, we'd rewrite all those + * tables above as cumulative frequency tables and use binary + * search. But this happens about log n times in a grid of area n, + * so it hardly matters, and it's easier to keep the tables + * legible. + */ + unsigned long limit = 0, value; + size_t i; + + for (i = 0; i < nparents; i++) + limit += parents[i].probability; + + value = random_upto(rs, limit); + + for (i = 0; i+1 < nparents; i++) { + if (value < parents[i].probability) + return &parents[i]; + value -= parents[i].probability; + } + + assert(i == nparents - 1); + assert(value < parents[i].probability); + return &parents[i]; +} +void hatctx_init_random(HatContext *ctx, random_state *rs) +{ + const MetatilePossibleParent *starting_hat = choose_mpp( + rs, starting_hats, lenof(starting_hats)); + + ctx->rs = rs; + ctx->prototype = hat_coords_new(); + hat_coords_make_space(ctx->prototype, 3); + ctx->prototype->c[2].type = starting_hat->type; + ctx->prototype->c[2].index = -1; + ctx->prototype->c[1].type = TT_HAT; + ctx->prototype->c[1].index = starting_hat->index; + ctx->prototype->c[0].type = TT_KITE; + ctx->prototype->c[0].index = random_upto(rs, HAT_KITES); + ctx->prototype->nc = 3; +} + +static inline int metatile_char_to_enum(char metatile) +{ + return (metatile == 'H' ? TT_H : + metatile == 'T' ? TT_T : + metatile == 'P' ? TT_P : + metatile == 'F' ? TT_F : -1); +} + +static void init_coords_params(HatContext *ctx, + const struct HatPatchParams *hp) +{ + size_t i; + + ctx->rs = NULL; + ctx->prototype = hat_coords_new(); + + assert(hp->ncoords >= 3); + + hat_coords_make_space(ctx->prototype, hp->ncoords + 1); + ctx->prototype->nc = hp->ncoords + 1; + + for (i = 0; i < hp->ncoords; i++) + ctx->prototype->c[i].index = hp->coords[i]; + + ctx->prototype->c[hp->ncoords].type = + metatile_char_to_enum(hp->final_metatile); + ctx->prototype->c[hp->ncoords].index = -1; + + ctx->prototype->c[0].type = TT_KITE; + ctx->prototype->c[1].type = TT_HAT; + + for (i = hp->ncoords - 1; i > 1; i--) { + TileType metatile = ctx->prototype->c[i+1].type; + assert(hp->coords[i] < nchildren[metatile]); + ctx->prototype->c[i].type = children[metatile][hp->coords[i]]; + } + + assert(hp->coords[0] < 8); +} + +HatCoords *hatctx_initial_coords(HatContext *ctx) +{ + return hat_coords_copy(ctx->prototype); +} + +/* + * Extend hc until it has at least n coordinates in, by copying from + * ctx->prototype if needed, and extending ctx->prototype if needed in + * order to do that. + */ +void hatctx_extend_coords(HatContext *ctx, HatCoords *hc, size_t n) +{ + if (ctx->prototype->nc < n) { + hat_coords_make_space(ctx->prototype, n); + while (ctx->prototype->nc < n) { + TileType type = ctx->prototype->c[ctx->prototype->nc - 1].type; + assert(ctx->prototype->c[ctx->prototype->nc - 1].index == -1); + const MetatilePossibleParent *parent; + + if (ctx->rs) + parent = choose_mpp(ctx->rs, possible_parents[type], + n_possible_parents[type]); + else + parent = possible_parents[type]; + + ctx->prototype->c[ctx->prototype->nc - 1].index = parent->index; + ctx->prototype->c[ctx->prototype->nc].index = -1; + ctx->prototype->c[ctx->prototype->nc].type = parent->type; + ctx->prototype->nc++; + } + } + + hat_coords_make_space(hc, n); + while (hc->nc < n) { + assert(hc->c[hc->nc - 1].index == -1); + assert(hc->c[hc->nc - 1].type == ctx->prototype->c[hc->nc - 1].type); + hc->c[hc->nc - 1].index = ctx->prototype->c[hc->nc - 1].index; + hc->c[hc->nc].index = -1; + hc->c[hc->nc].type = ctx->prototype->c[hc->nc].type; + hc->nc++; + } +} + +void hatctx_cleanup(HatContext *ctx) +{ + hat_coords_free(ctx->prototype); +} + +/* + * The actual system for finding the coordinates of an adjacent kite. + */ + +/* + * Kitemap step: ensure we have enough coordinates to know two levels + * of meta-tiling, and use the kite map for the outer layer to move + * around the individual kites. If this fails, return NULL. + */ +static HatCoords *try_step_coords_kitemap( + HatContext *ctx, HatCoords *hc_in, KiteStep step) +{ + hatctx_extend_coords(ctx, hc_in, 4); + hat_coords_debug(" try kitemap ", hc_in, "\n"); + unsigned kite = hc_in->c[0].index; + unsigned hat = hc_in->c[1].index; + unsigned meta = hc_in->c[2].index; + TileType meta2type = hc_in->c[3].type; + const KitemapEntry *ke = &kitemap[meta2type][ + kitemap_index(step, kite, hat, meta)]; + if (ke->kite >= 0) { + /* + * Success! We've got coordinates for the next kite in this + * direction. + */ + HatCoords *hc_out = hat_coords_copy(hc_in); + + hc_out->c[2].index = ke->meta; + hc_out->c[2].type = children[meta2type][ke->meta]; + hc_out->c[1].index = ke->hat; + hc_out->c[1].type = TT_HAT; + hc_out->c[0].index = ke->kite; + hc_out->c[0].type = TT_KITE; + + hat_coords_debug(" success! ", hc_out, "\n"); + return hc_out; + } + + return NULL; +} + +/* + * Recursive metamap step. Try using the metamap to rewrite the + * coordinates at hc->c[depth] and hc->c[depth+1] (using the metamap + * for the tile type described in hc->c[depth+2]). If successful, + * recurse back down to see if this led to a successful step via the + * kitemap. If even that fails (so that we need to try a higher-order + * metamap rewrite), return NULL. + */ +static HatCoords *try_step_coords_metamap( + HatContext *ctx, HatCoords *hc_in, KiteStep step, size_t depth) +{ + HatCoords *hc_tmp = NULL, *hc_out; + + hatctx_extend_coords(ctx, hc_in, depth+3); +#ifdef HAT_COORDS_DEBUG + fprintf(stderr, " try meta %-4d", (int)depth); + hat_coords_debug("", hc_in, "\n"); +#endif + unsigned meta_orig = hc_in->c[depth].index; + unsigned meta2_orig = hc_in->c[depth+1].index; + TileType meta3type = hc_in->c[depth+2].type; + + unsigned meta = meta_orig, meta2 = meta2_orig; + + while (true) { + const MetamapEntry *me; + HatCoords *hc_curr = hc_tmp ? hc_tmp : hc_in; + + if (depth > 2) + hc_out = try_step_coords_metamap(ctx, hc_curr, step, depth - 1); + else + hc_out = try_step_coords_kitemap(ctx, hc_curr, step); + if (hc_out) { + hat_coords_free(hc_tmp); + return hc_out; + } + + me = &metamap[meta3type][metamap_index(meta, meta2)]; + assert(me->meta != -1); + if (me->meta == meta_orig && me->meta2 == meta2_orig) { + hat_coords_free(hc_tmp); + return NULL; + } + + meta = me->meta; + meta2 = me->meta2; + + /* + * We must do the rewrite in a copy of hc_in. It's not + * _necessarily_ obvious that that's the case (any successful + * rewrite leaves the coordinates still valid and still + * referring to the same kite, right?). But the problem is + * that we might do a rewrite at this level more than once, + * and in between, a metamap rewrite at the next level down + * might have modified _one_ of the two coordinates we're + * messing about with. So it's easiest to let the recursion + * just use a separate copy. + */ + if (!hc_tmp) + hc_tmp = hat_coords_copy(hc_in); + + hc_tmp->c[depth+1].index = meta2; + hc_tmp->c[depth+1].type = children[meta3type][meta2]; + hc_tmp->c[depth].index = meta; + hc_tmp->c[depth].type = children[hc_tmp->c[depth+1].type][meta]; + + hat_coords_debug(" rewritten -> ", hc_tmp, "\n"); + } +} + +/* + * The top-level algorithm for finding the next tile. + */ +HatCoords *hatctx_step(HatContext *ctx, HatCoords *hc_in, KiteStep step) +{ + HatCoords *hc_out; + size_t depth; + +#ifdef HAT_COORDS_DEBUG + static const char *const directions[] = { + " left\n", " right\n", " forward left\n", " forward right\n" }; + hat_coords_debug("step start ", hc_in, directions[step]); +#endif + + /* + * First, just try a kitemap step immediately. If that succeeds, + * we're done. + */ + if ((hc_out = try_step_coords_kitemap(ctx, hc_in, step)) != NULL) + return hc_out; + + /* + * Otherwise, try metamap rewrites at successively higher layers + * until one works. Each one will recurse back down to the + * kitemap, as described above. + */ + for (depth = 2;; depth++) { + if ((hc_out = try_step_coords_metamap( + ctx, hc_in, step, depth)) != NULL) + return hc_out; + } +} + +/* + * Generate a random set of parameters for a tiling of a given size. + * To do this, we iterate over the whole tiling via hat_kiteenum_first + * and hat_kiteenum_next, and for each kite, calculate its + * coordinates. But then we throw the coordinates away and don't do + * anything with them! + * + * But the side effect of _calculating_ all those coordinates is that + * we found out how far ctx->prototype needed to be extended, and did + * so, pulling random choices out of our random_state. So after this + * iteration, ctx->prototype contains everything we need to replicate + * the same piece of tiling next time. + */ +void hat_tiling_randomise(struct HatPatchParams *hp, int w, int h, + random_state *rs) +{ + HatContext ctx[1]; + HatCoords *coords[KE_NKEEP]; + KiteEnum s[1]; + size_t i; + + hatctx_init_random(ctx, rs); + for (i = 0; i < lenof(coords); i++) + coords[i] = NULL; + + hat_kiteenum_first(s, w, h); + coords[s->curr_index] = hatctx_initial_coords(ctx); + + while (hat_kiteenum_next(s)) { + hat_coords_free(coords[s->curr_index]); + coords[s->curr_index] = hatctx_step( + ctx, coords[s->last_index], s->last_step); + } + + hp->ncoords = ctx->prototype->nc - 1; + hp->coords = snewn(hp->ncoords, unsigned char); + for (i = 0; i < hp->ncoords; i++) + hp->coords[i] = ctx->prototype->c[i].index; + hp->final_metatile = tilechars[ctx->prototype->c[hp->ncoords].type]; + + hatctx_cleanup(ctx); + for (i = 0; i < lenof(coords); i++) + hat_coords_free(coords[i]); +} + +const char *hat_tiling_params_invalid(const struct HatPatchParams *hp) +{ + TileType metatile; + size_t i; + + if (hp->ncoords < 3) + return "Grid parameters require at least three coordinates"; + if (metatile_char_to_enum(hp->final_metatile) < 0) + return "Grid parameters contain an invalid final metatile"; + if (hp->coords[0] >= 8) + return "Grid parameters contain an invalid kite index"; + + metatile = metatile_char_to_enum(hp->final_metatile); + for (i = hp->ncoords - 1; i > 1; i--) { + if (hp->coords[i] >= nchildren[metatile]) + return "Grid parameters contain an invalid metatile index"; + metatile = children[metatile][hp->coords[i]]; + } + + if (hp->coords[1] >= hats_in_metatile[metatile]) + return "Grid parameters contain an invalid hat index"; + + return NULL; +} + +void maybe_report_hat(int w, int h, Kite kite, HatCoords *hc, + internal_hat_callback_fn cb, void *cbctx) +{ + Kite kite0; + Point vertices[14]; + size_t i, j; + bool reversed = false; + int coords[28]; + + /* Only iterate from kite #0 of a hat */ + if (hc->c[0].index != 0) + return; + kite0 = kite; + + /* + * Identify reflected hats: they are always hat #3 of an H + * metatile. If we find one, reflect the starting kite so that the + * kite_step operations below will go in the other direction. + */ + if (hc->c[2].type == TT_H && hc->c[1].index == 3) { + reversed = true; + Point tmp = kite.left; + kite.left = kite.right; + kite.right = tmp; + } + + vertices[0] = kite.centre; + vertices[1] = kite.right; + vertices[2] = kite.outer; + vertices[3] = kite.left; + kite = kite_left(kite); /* now on kite #1 */ + kite = kite_forward_right(kite); /* now on kite #2 */ + vertices[4] = kite.centre; + kite = kite_right(kite); /* now on kite #3 */ + vertices[5] = kite.right; + vertices[6] = kite.outer; + kite = kite_forward_left(kite); /* now on kite #4 */ + vertices[7] = kite.left; + vertices[8] = kite.centre; + kite = kite_right(kite); /* now on kite #5 */ + kite = kite_right(kite); /* now on kite #6 */ + kite = kite_right(kite); /* now on kite #7 */ + vertices[9] = kite.right; + vertices[10] = kite.outer; + vertices[11] = kite.left; + kite = kite_left(kite); /* now on kite #6 again */ + vertices[12] = kite.outer; + vertices[13] = kite.left; + + if (reversed) { + /* For a reversed kite, also reverse the vertex order, so that + * we report every polygon in a consistent orientation */ + for (i = 0, j = 13; i < j; i++, j--) { + Point tmp = vertices[i]; + vertices[i] = vertices[j]; + vertices[j] = tmp; + } + } + + /* + * Convert from our internal coordinate system into the orthogonal + * one used in this module's external API. In the same loop, we + * might as well do the bounds check. + */ + for (i = 0; i < 14; i++) { + Point v = vertices[i]; + int x = (v.x * 2 + v.y) / 3, y = v.y; + + if (x < 0 || x > 4*w || y < 0 || y > 6*h) + return; /* a vertex of this kite is out of bounds */ + + coords[2*i] = x; + coords[2*i+1] = y; + } + + cb(cbctx, kite0, hc, coords); +} + +struct internal_ctx { + hat_tile_callback_fn external_cb; + void *external_cbctx; +}; +static void report_hat(void *vctx, Kite kite0, HatCoords *hc, int *coords) +{ + struct internal_ctx *ctx = (struct internal_ctx *)vctx; + ctx->external_cb(ctx->external_cbctx, 14, coords); +} + +/* + * Generate a hat tiling from a previously generated set of parameters. + */ +void hat_tiling_generate(const struct HatPatchParams *hp, int w, int h, + hat_tile_callback_fn cb, void *cbctx) +{ + HatContext ctx[1]; + HatCoords *coords[KE_NKEEP]; + KiteEnum s[1]; + size_t i; + struct internal_ctx report_hat_ctx[1]; + + report_hat_ctx->external_cb = cb; + report_hat_ctx->external_cbctx = cbctx; + + init_coords_params(ctx, hp); + for (i = 0; i < lenof(coords); i++) + coords[i] = NULL; + + hat_kiteenum_first(s, w, h); + coords[s->curr_index] = hatctx_initial_coords(ctx); + maybe_report_hat(w, h, *s->curr, coords[s->curr_index], + report_hat, report_hat_ctx); + + while (hat_kiteenum_next(s)) { + hat_coords_free(coords[s->curr_index]); + coords[s->curr_index] = hatctx_step( + ctx, coords[s->last_index], s->last_step); + maybe_report_hat(w, h, *s->curr, coords[s->curr_index], + report_hat, report_hat_ctx); + } + + hatctx_cleanup(ctx); + for (i = 0; i < lenof(coords); i++) + hat_coords_free(coords[i]); +} diff --git a/apps/plugins/puzzles/src/hat.h b/apps/plugins/puzzles/src/hat.h new file mode 100644 index 0000000000..39e2d31a66 --- /dev/null +++ b/apps/plugins/puzzles/src/hat.h @@ -0,0 +1,67 @@ +#ifndef PUZZLES_HAT_H +#define PUZZLES_HAT_H + +struct HatPatchParams { + /* + * A patch of hat tiling is identified by giving the coordinates + * of the kite in one corner, using a multi-level coordinate + * system based on metatile expansions. Coordinates are a sequence + * of small non-negative integers. The valid range for each + * coordinate depends on the next coordinate, or on final_metatile + * if it's the last one in the list. The largest valid range is + * {0,...,12}. + * + * 'final_metatile' is one of the characters 'H', 'T', 'P' or 'F'. + */ + size_t ncoords; + unsigned char *coords; + char final_metatile; +}; + +/* + * Fill in HatPatchParams with a randomly selected set of coordinates, + * in enough detail to generate a patch of tiling covering an area of + * w x h 'squares' of a kite tiling. + * + * The kites grid is considered to be oriented so that it includes + * horizontal lines and not vertical ones. So each of the smallest + * equilateral triangles in the grid has a bounding rectangle whose + * height is sqrt(3)/2 times its width, and either the top or the + * bottom of that bounding rectangle is the horizontal edge of the + * triangle. A 'square' of a kite tiling (for convenience of choosing + * grid dimensions) counts as one of those bounding rectangles. + * + * The 'coords' field of the structure will be filled in with a new + * dynamically allocated array. Any previous pointer in that field + * will be overwritten. + */ +void hat_tiling_randomise(struct HatPatchParams *params, int w, int h, + random_state *rs); + +/* + * Validate a HatPatchParams to ensure it contains no illegal + * coordinates. Returns NULL if it's acceptable, or an error string if + * not. + */ +const char *hat_tiling_params_invalid(const struct HatPatchParams *params); + +/* + * Generate the actual set of hat tiles from a HatPatchParams, passing + * each one to a callback. The callback receives the vertices of each + * point, as a sequence of 2*nvertices integers, with x,y coordinates + * interleaved. + * + * The x coordinates are measured in units of 1/4 of the side length + * of the smallest equilateral triangle, or equivalently, 1/2 the + * length of one of the long edges of a single kite. The y coordinates + * are measured in units of 1/6 the height of the triangle, which is + * also 1/2 the length of the short edge of a kite. Therefore, you can + * expect x to go up to 4*w and y up to 6*h. + */ +typedef void (*hat_tile_callback_fn)(void *ctx, size_t nvertices, + int *coords); + +void hat_tiling_generate(const struct HatPatchParams *params, int w, int h, + hat_tile_callback_fn cb, void *cbctx); + +#endif diff --git a/apps/plugins/puzzles/src/inertia.R b/apps/plugins/puzzles/src/inertia.R deleted file mode 100644 index e6e86beaec..0000000000 --- a/apps/plugins/puzzles/src/inertia.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -inertia : [X] GTK COMMON inertia inertia-icon|no-icon - -inertia : [G] WINDOWS COMMON inertia inertia.res|noicon.res - -ALL += inertia[COMBINED] - -!begin am gtk -GAMES += inertia -!end - -!begin >list.c - A(inertia) \ -!end - -!begin >gamedesc.txt -inertia:inertia.exe:Inertia:Gem-collecting puzzle:Collect all the gems without running into any of the mines. -!end diff --git a/apps/plugins/puzzles/src/inertia.c b/apps/plugins/puzzles/src/inertia.c index 726c89c7dd..d120411f55 100644 --- a/apps/plugins/puzzles/src/inertia.c +++ b/apps/plugins/puzzles/src/inertia.c @@ -11,7 +11,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -202,6 +207,8 @@ static const char *validate_params(const game_params *params, bool full) */ if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; /* * The grid construction algorithm creates 1/5 as many gems as @@ -1520,7 +1527,8 @@ static char *encode_ui(const game_ui *ui) return dupstr(buf); } -static void decode_ui(game_ui *ui, const char *encoding) +static void decode_ui(game_ui *ui, const char *encoding, + const game_state *state) { int p = 0; sscanf(encoding, "D%d%n", &ui->deaths, &p); @@ -1545,6 +1553,15 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->just_made_move = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && + state->soln && state->solnpos < state->soln->len) + return "Advance"; + return ""; +} + struct game_drawstate { game_params p; int tilesize; @@ -1593,7 +1610,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, * end up the right way round. */ angle = atan2(dx, -dy); - angle = (angle + (PI/8)) / (PI/4); + angle = (angle + (float)(PI/8)) / (float)(PI/4); assert(angle > -16.0F); dir = (int)(angle + 16.0F) & 7; } @@ -1618,20 +1635,20 @@ static char *interpret_move(const game_state *state, game_ui *ui, dir = state->soln->list[state->solnpos]; if (dir < 0) - return NULL; + return MOVE_UNUSED; /* * Reject the move if we can't make it at all due to a wall * being in the way. */ if (AT(w, h, state->grid, state->px+DX(dir), state->py+DY(dir)) == WALL) - return NULL; + return MOVE_NO_EFFECT; /* * Reject the move if we're dead! */ if (state->dead) - return NULL; + return MOVE_NO_EFFECT; /* * Otherwise, we can make the move. All we need to specify is @@ -1685,6 +1702,7 @@ static game_state *execute_move(const game_state *state, const char *move) * This is a solve move, so we don't actually _change_ the * grid but merely set up a stored solution path. */ + if (move[1] == '\0') return NULL; /* Solution must be non-empty. */ ret = dup_game(state); install_new_solution(ret, move); return ret; @@ -1729,11 +1747,10 @@ static game_state *execute_move(const game_state *state, const char *move) if (ret->soln) { if (ret->dead || ret->gems == 0) discard_solution(ret); - else if (ret->soln->list[ret->solnpos] == dir) { + else if (ret->soln->list[ret->solnpos] == dir && + ret->solnpos+1 < ret->soln->len) ++ret->solnpos; - assert(ret->solnpos < ret->soln->len); /* or gems == 0 */ - assert(!ret->dead); /* or not a solution */ - } else { + else { const char *error = NULL; char *soln = solve_game(NULL, ret, NULL, &error); if (!error) { @@ -1751,7 +1768,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1869,11 +1886,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, coords[d*4+2] = x + TILESIZE/2 + (int)((TILESIZE*3/7) * x2); coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2); } - /* rockbox hack */ - int tmp[2] = { coords[0], coords[1] }; - memmove(coords, coords + 2, sizeof(int) * DIRECTIONS * 4 - 2); - memcpy(coords + DIRECTIONS * 4 - 2, tmp, 2 * sizeof(int)); - draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE); } else { draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2, @@ -1889,6 +1901,8 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, int coords[14], *c; c = coords; + *c++ = ox + px/9; + *c++ = oy + py/9; *c++ = ox + px/9 + ax*2/3; *c++ = oy + py/9 + ay*2/3; *c++ = ox + px/3 + ax*2/3; @@ -1901,8 +1915,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, *c++ = oy - py/9 + ay*2/3; *c++ = ox - px/9; *c++ = oy - py/9; - *c++ = ox + px/9; - *c++ = oy + py/9; draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE); } @@ -2013,15 +2025,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, * Initialise a fresh drawstate. */ if (!ds->started) { - int wid, ht; - - /* - * Blank out the window initially. - */ - game_compute_size(&ds->p, TILESIZE, &wid, &ht); - draw_rect(dr, 0, 0, wid, ht, COL_BACKGROUND); - draw_update(dr, 0, 0, wid, ht); - /* * Draw the grid lines. */ @@ -2207,19 +2210,6 @@ static int game_status(const game_state *state) return state->gems == 0 ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame inertia #endif @@ -2241,12 +2231,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, encode_ui, decode_ui, NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -2258,8 +2250,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/keen.R b/apps/plugins/puzzles/src/keen.R deleted file mode 100644 index 46bd09a33d..0000000000 --- a/apps/plugins/puzzles/src/keen.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -KEEN_EXTRA = dsf LATIN -KEEN_EXTRA_SOLVER = dsf LATIN_SOLVER - -keen : [X] GTK COMMON keen KEEN_EXTRA keen-icon|no-icon - -keen : [G] WINDOWS COMMON keen KEEN_EXTRA keen.res|noicon.res - -keensolver : [U] keen[STANDALONE_SOLVER] KEEN_EXTRA_SOLVER STANDALONE -keensolver : [C] keen[STANDALONE_SOLVER] KEEN_EXTRA_SOLVER STANDALONE - -ALL += keen[COMBINED] KEEN_EXTRA - -!begin am gtk -GAMES += keen -!end - -!begin >list.c - A(keen) \ -!end - -!begin >gamedesc.txt -keen:keen.exe:Keen:Arithmetic Latin square puzzle:Complete the latin square in accordance with the arithmetic clues. -!end diff --git a/apps/plugins/puzzles/src/keen.c b/apps/plugins/puzzles/src/keen.c index 6b9610dbcd..7e2f71c8f9 100644 --- a/apps/plugins/puzzles/src/keen.c +++ b/apps/plugins/puzzles/src/keen.c @@ -8,7 +8,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "latin.h" @@ -69,7 +73,7 @@ struct game_params { struct clues { int refcount; int w; - int *dsf; + DSF *dsf; long *clues; }; @@ -677,7 +681,7 @@ static bool keen_valid(struct latin_solver *solver, void *vctx) return true; } -static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff) +static int solver(int w, DSF *dsf, long *clues, digit *soln, int maxdiff) { int a = w*w; struct solver_ctx ctx; @@ -704,11 +708,11 @@ static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff) ctx.clues = snewn(ctx.nboxes, long); ctx.whichbox = snewn(a, int); for (n = m = i = 0; i < a; i++) - if (dsf_canonify(dsf, i) == i) { + if (dsf_minimal(dsf, i) == i) { ctx.clues[n] = clues[i]; ctx.boxes[n] = m; for (j = 0; j < a; j++) - if (dsf_canonify(dsf, j) == i) { + if (dsf_minimal(dsf, j) == i) { ctx.boxlist[m++] = (j % w) * w + (j / w); /* transpose */ ctx.whichbox[ctx.boxlist[m-1]] = n; } @@ -740,7 +744,7 @@ static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff) * Grid generation. */ -static char *encode_block_structure(char *p, int w, int *dsf) +static char *encode_block_structure(char *p, int w, DSF *dsf) { int i, currrun = 0; char *orig, *q, *r, c; @@ -777,7 +781,7 @@ static char *encode_block_structure(char *p, int w, int *dsf) p0 = y*w+x; p1 = (y+1)*w+x; } - edge = (dsf_canonify(dsf, p0) != dsf_canonify(dsf, p1)); + edge = !dsf_equivalent(dsf, p0, p1); } if (edge) { @@ -815,13 +819,12 @@ static char *encode_block_structure(char *p, int w, int *dsf) return q; } -static const char *parse_block_structure(const char **p, int w, int *dsf) +static const char *parse_block_structure(const char **p, int w, DSF *dsf) { - int a = w*w; int pos = 0; int repc = 0, repn = 0; - dsf_init(dsf, a); + dsf_reinit(dsf); while (**p && (repn > 0 || **p != ',')) { int c; @@ -890,7 +893,8 @@ static char *new_game_desc(const game_params *params, random_state *rs, { int w = params->w, a = w*w; digit *grid, *soln; - int *order, *revorder, *singletons, *dsf; + int *order, *revorder, *singletons; + DSF *dsf; long *clues, *cluevals; int i, j, k, n, x, y, ret; int diff = params->diff; @@ -927,7 +931,7 @@ done order = snewn(a, int); revorder = snewn(a, int); singletons = snewn(a, int); - dsf = snew_dsf(a); + dsf = dsf_new_min(a); clues = snewn(a, long); cluevals = snewn(a, long); soln = snewn(a, digit); @@ -955,7 +959,7 @@ done for (i = 0; i < a; i++) singletons[i] = true; - dsf_init(dsf, a); + dsf_reinit(dsf); /* Place dominoes. */ for (i = 0; i < a; i++) { @@ -1037,11 +1041,10 @@ done * integer quotient, of course), but we rule out (or try to * avoid) some clues because they're of low quality. * - * Hence, we iterate once over the grid, stopping at the - * canonical element of every >2 block and the _non_- - * canonical element of every 2-block; the latter means that - * we can make our decision about a 2-block in the knowledge - * of both numbers in it. + * Hence, we iterate once over the grid, stopping at the first + * element in every >2 block and the _last_ element of every + * 2-block; the latter means that we can make our decision + * about a 2-block in the knowledge of both numbers in it. * * We reuse the 'singletons' array (finished with in the * above loop) to hold information about which blocks are @@ -1055,7 +1058,7 @@ done for (i = 0; i < a; i++) { singletons[i] = 0; - j = dsf_canonify(dsf, i); + j = dsf_minimal(dsf, i); k = dsf_size(dsf, j); if (params->multiplication_only) singletons[j] = F_MUL; @@ -1178,7 +1181,7 @@ done * Having chosen the clue types, calculate the clue values. */ for (i = 0; i < a; i++) { - j = dsf_canonify(dsf, i); + j = dsf_minimal(dsf, i); if (j == i) { cluevals[j] = grid[i]; } else { @@ -1206,7 +1209,7 @@ done } for (i = 0; i < a; i++) { - j = dsf_canonify(dsf, i); + j = dsf_minimal(dsf, i); if (j == i) { clues[j] |= cluevals[j]; } @@ -1252,7 +1255,7 @@ done p = encode_block_structure(p, w, dsf); *p++ = ','; for (i = 0; i < a; i++) { - j = dsf_canonify(dsf, i); + j = dsf_minimal(dsf, i); if (j == i) { switch (clues[j] & CMASK) { case C_ADD: *p++ = 'a'; break; @@ -1280,7 +1283,7 @@ done sfree(order); sfree(revorder); sfree(singletons); - sfree(dsf); + dsf_free(dsf); sfree(clues); sfree(cluevals); sfree(soln); @@ -1295,7 +1298,7 @@ done static const char *validate_desc(const game_params *params, const char *desc) { int w = params->w, a = w*w; - int *dsf; + DSF *dsf; const char *ret; const char *p = desc; int i; @@ -1303,15 +1306,17 @@ static const char *validate_desc(const game_params *params, const char *desc) /* * Verify that the block structure makes sense. */ - dsf = snew_dsf(a); + dsf = dsf_new_min(a); ret = parse_block_structure(&p, w, dsf); if (ret) { - sfree(dsf); + dsf_free(dsf); return ret; } - if (*p != ',') + if (*p != ',') { + dsf_free(dsf); return "Expected ',' after block structure description"; + } p++; /* @@ -1319,21 +1324,26 @@ static const char *validate_desc(const game_params *params, const char *desc) * and DIV clues don't apply to blocks of the wrong size. */ for (i = 0; i < a; i++) { - if (dsf_canonify(dsf, i) == i) { + if (dsf_minimal(dsf, i) == i) { if (*p == 'a' || *p == 'm') { /* these clues need no validation */ } else if (*p == 'd' || *p == 's') { - if (dsf_size(dsf, i) != 2) + if (dsf_size(dsf, i) != 2) { + dsf_free(dsf); return "Subtraction and division blocks must have area 2"; + } } else if (!*p) { + dsf_free(dsf); return "Too few clues for block structure"; } else { + dsf_free(dsf); return "Unrecognised clue type"; } p++; while (*p && isdigit((unsigned char)*p)) p++; } } + dsf_free(dsf); if (*p) return "Too many clues for block structure"; @@ -1373,7 +1383,7 @@ static game_state *new_game(midend *me, const game_params *params, state->clues = snew(struct clues); state->clues->refcount = 1; state->clues->w = w; - state->clues->dsf = snew_dsf(a); + state->clues->dsf = dsf_new_min(a); parse_block_structure(&p, w, state->clues->dsf); assert(*p == ','); @@ -1381,7 +1391,7 @@ static game_state *new_game(midend *me, const game_params *params, state->clues->clues = snewn(a, long); for (i = 0; i < a; i++) { - if (dsf_canonify(state->clues->dsf, i) == i) { + if (dsf_minimal(state->clues->dsf, i) == i) { long clue = 0; switch (*p) { case 'a': @@ -1448,7 +1458,7 @@ static void free_game(game_state *state) sfree(state->grid); sfree(state->pencil); if (--state->clues->refcount <= 0) { - sfree(state->clues->dsf); + dsf_free(state->clues->dsf); sfree(state->clues->clues); sfree(state->clues); } @@ -1490,16 +1500,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return out; } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - struct game_ui { /* * These are the coordinates of the currently highlighted @@ -1525,6 +1525,17 @@ struct game_ui { * allowed on immutable squares. */ bool hcursor; + + /* + * User preference option: if the user right-clicks in a square + * and presses a number key to add/remove a pencil mark, do we + * hide the mouse highlight again afterwards? + * + * Historically our answer was yes. The Android port prefers no. + * There are advantages both ways, depending how much you dislike + * the highlight cluttering your view. So it's a preference. + */ + bool pencil_keep_highlight; }; static game_ui *new_ui(const game_state *state) @@ -1533,8 +1544,9 @@ static game_ui *new_ui(const game_state *state) ui->hx = ui->hy = 0; ui->hpencil = false; - ui->hshow = false; - ui->hcursor = false; + ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->pencil_keep_highlight = false; return ui; } @@ -1544,13 +1556,26 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Keep mouse highlight after changing a pencil mark"; + ret[0].kw = "pencil-keep-highlight"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->pencil_keep_highlight; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->pencil_keep_highlight = cfg[0].u.boolean.bval; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1569,6 +1594,14 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (ui->hshow && (button == CURSOR_SELECT)) + return ui->hpencil ? "Ink" : "Pencil"; + return ""; +} + #define PREFERRED_TILESIZE 48 #define TILESIZE (ds->tilesize) #define BORDER (TILESIZE / 2) @@ -1613,7 +1646,7 @@ static bool check_errors(const game_state *state, long *errors) for (i = 0; i < a; i++) { long clue; - j = dsf_canonify(state->clues->dsf, i); + j = dsf_minimal(state->clues->dsf, i); if (j == i) { cluevals[i] = state->grid[i]; } else { @@ -1647,7 +1680,7 @@ static bool check_errors(const game_state *state, long *errors) } for (i = 0; i < a; i++) { - j = dsf_canonify(state->clues->dsf, i); + j = dsf_minimal(state->clues->dsf, i); if (j == i) { if ((state->clues->clues[j] & ~CMASK) != cluevals[i]) { errs = true; @@ -1709,7 +1742,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int tx, ty; char buf[80]; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); tx = FROMCOORD(x); ty = FROMCOORD(y); @@ -1726,7 +1759,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == RIGHT_BUTTON) { /* @@ -1746,20 +1779,18 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hshow = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->hx, &ui->hy, w, w, false); - ui->hshow = true; ui->hcursor = true; - return UI_UPDATE; + return move_cursor(button, &ui->hx, &ui->hy, w, w, false, &ui->hshow); } if (ui->hshow && (button == CURSOR_SELECT)) { ui->hpencil ^= 1; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->hshow && @@ -1776,10 +1807,31 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->hpencil && state->grid[ui->hy*w+ui->hx]) return NULL; + /* + * If you ask to fill a square with what it already contains, + * or blank it when it's already empty, that has no effect... + */ + if ((!ui->hpencil || n == 0) && state->grid[ui->hy*w+ui->hx] == n && + state->pencil[ui->hy*w+ui->hx] == 0) { + /* ... expect to remove the cursor in mouse mode. */ + if (!ui->hcursor) { + ui->hshow = false; + return MOVE_UI_UPDATE; + } + return NULL; + } + sprintf(buf, "%c%d,%d,%d", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); - if (!ui->hcursor) ui->hshow = false; + /* + * Hide the highlight after a keypress, if it was mouse- + * generated. Also, don't hide it if this move has changed + * pencil marks and the user preference says not to hide the + * highlight in that situation. + */ + if (!ui->hcursor && !(ui->hpencil && ui->pencil_keep_highlight)) + ui->hshow = false; return dupstr(buf); } @@ -1854,7 +1906,7 @@ static game_state *execute_move(const game_state *from, const char *move) #define SIZE(w) ((w) * TILESIZE + 2*BORDER) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1939,6 +1991,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, int tx, ty, tw, th; int cx, cy, cw, ch; char str[64]; + bool draw_clue = dsf_minimal(clues->dsf, y*w+x) == y*w+x; tx = BORDER + x * TILESIZE + 1 + GRIDEXTRA; ty = BORDER + y * TILESIZE + 1 + GRIDEXTRA; @@ -1948,13 +2001,13 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, cw = tw = TILESIZE-1-2*GRIDEXTRA; ch = th = TILESIZE-1-2*GRIDEXTRA; - if (x > 0 && dsf_canonify(clues->dsf, y*w+x) == dsf_canonify(clues->dsf, y*w+x-1)) + if (x > 0 && dsf_equivalent(clues->dsf, y*w+x, y*w+x-1)) cx -= GRIDEXTRA, cw += GRIDEXTRA; - if (x+1 < w && dsf_canonify(clues->dsf, y*w+x) == dsf_canonify(clues->dsf, y*w+x+1)) + if (x+1 < w && dsf_equivalent(clues->dsf, y*w+x, y*w+x+1)) cw += GRIDEXTRA; - if (y > 0 && dsf_canonify(clues->dsf, y*w+x) == dsf_canonify(clues->dsf, (y-1)*w+x)) + if (y > 0 && dsf_equivalent(clues->dsf, y*w+x, (y-1)*w+x)) cy -= GRIDEXTRA, ch += GRIDEXTRA; - if (y+1 < w && dsf_canonify(clues->dsf, y*w+x) == dsf_canonify(clues->dsf, (y+1)*w+x)) + if (y+1 < w && dsf_equivalent(clues->dsf, y*w+x, (y+1)*w+x)) ch += GRIDEXTRA; clip(dr, cx, cy, cw, ch); @@ -1979,17 +2032,21 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, * Draw the corners of thick lines in corner-adjacent squares, * which jut into this square by one pixel. */ - if (x > 0 && y > 0 && dsf_canonify(clues->dsf, y*w+x) != dsf_canonify(clues->dsf, (y-1)*w+x-1)) - draw_rect(dr, tx-GRIDEXTRA, ty-GRIDEXTRA, GRIDEXTRA, GRIDEXTRA, COL_GRID); - if (x+1 < w && y > 0 && dsf_canonify(clues->dsf, y*w+x) != dsf_canonify(clues->dsf, (y-1)*w+x+1)) - draw_rect(dr, tx+TILESIZE-1-2*GRIDEXTRA, ty-GRIDEXTRA, GRIDEXTRA, GRIDEXTRA, COL_GRID); - if (x > 0 && y+1 < w && dsf_canonify(clues->dsf, y*w+x) != dsf_canonify(clues->dsf, (y+1)*w+x-1)) - draw_rect(dr, tx-GRIDEXTRA, ty+TILESIZE-1-2*GRIDEXTRA, GRIDEXTRA, GRIDEXTRA, COL_GRID); - if (x+1 < w && y+1 < w && dsf_canonify(clues->dsf, y*w+x) != dsf_canonify(clues->dsf, (y+1)*w+x+1)) - draw_rect(dr, tx+TILESIZE-1-2*GRIDEXTRA, ty+TILESIZE-1-2*GRIDEXTRA, GRIDEXTRA, GRIDEXTRA, COL_GRID); + if (x > 0 && y > 0 && !dsf_equivalent(clues->dsf, y*w+x, (y-1)*w+x-1)) + draw_rect(dr, tx-GRIDEXTRA, ty-GRIDEXTRA, + GRIDEXTRA, GRIDEXTRA, COL_GRID); + if (x+1 < w && y > 0 && !dsf_equivalent(clues->dsf, y*w+x, (y-1)*w+x+1)) + draw_rect(dr, tx+TILESIZE-1-2*GRIDEXTRA, ty-GRIDEXTRA, + GRIDEXTRA, GRIDEXTRA, COL_GRID); + if (x > 0 && y+1 < w && !dsf_equivalent(clues->dsf, y*w+x, (y+1)*w+x-1)) + draw_rect(dr, tx-GRIDEXTRA, ty+TILESIZE-1-2*GRIDEXTRA, + GRIDEXTRA, GRIDEXTRA, COL_GRID); + if (x+1 < w && y+1 < w && !dsf_equivalent(clues->dsf, y*w+x, (y+1)*w+x+1)) + draw_rect(dr, tx+TILESIZE-1-2*GRIDEXTRA, ty+TILESIZE-1-2*GRIDEXTRA, + GRIDEXTRA, GRIDEXTRA, COL_GRID); /* Draw the box clue. */ - if (dsf_canonify(clues->dsf, y*w+x) == y*w+x) { + if (draw_clue) { long clue = clues->clues[y*w+x]; long cluetype = clue & CMASK, clueval = clue & ~CMASK; int size = dsf_size(clues->dsf, y*w+x); @@ -2043,7 +2100,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, pr = pl + TILESIZE - GRIDEXTRA; pt = ty + GRIDEXTRA; pb = pt + TILESIZE - GRIDEXTRA; - if (dsf_canonify(clues->dsf, y*w+x) == y*w+x) { + if (draw_clue) { /* * Make space for the clue text. */ @@ -2097,7 +2154,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, * And move it down a bit if it's collided with some * clue text. */ - if (dsf_canonify(clues->dsf, y*w+x) == y*w+x) { + if (draw_clue) { pt = max(pt, ty + GRIDEXTRA * 3 + TILESIZE/4); } @@ -2133,14 +2190,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int x, y; if (!ds->started) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all - * games should start by drawing a big background-colour - * rectangle covering the whole window. - */ - draw_rect(dr, 0, 0, SIZE(w), SIZE(w), COL_BACKGROUND); - /* * Big containing rectangle. */ @@ -2217,21 +2266,15 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - if (state->completed) - return false; - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * We use 9mm squares by default, like Solo. */ - game_compute_size(params, 900, &pw, &ph); + game_compute_size(params, 900, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } @@ -2245,7 +2288,7 @@ static void game_print_size(const game_params *params, float *x, float *y) * single polygon. */ static void outline_block_structure(drawing *dr, game_drawstate *ds, - int w, int *dsf, int ink) + int w, DSF *dsf, int ink) { int a = w*w; int *coords; @@ -2258,7 +2301,7 @@ static void outline_block_structure(drawing *dr, game_drawstate *ds, * Iterate over all the blocks. */ for (i = 0; i < a; i++) { - if (dsf_canonify(dsf, i) != i) + if (dsf_minimal(dsf, i) != i) continue; /* @@ -2297,11 +2340,11 @@ static void outline_block_structure(drawing *dr, game_drawstate *ds, tx = x - dy + dx; ty = y + dx + dy; nin += (tx >= 0 && tx < w && ty >= 0 && ty < w && - dsf_canonify(dsf, ty*w+tx) == i); + dsf_minimal(dsf, ty*w+tx) == i); tx = x - dy; ty = y + dx; nin += (tx >= 0 && tx < w && ty >= 0 && ty < w && - dsf_canonify(dsf, ty*w+tx) == i); + dsf_minimal(dsf, ty*w+tx) == i); if (nin == 0) { /* * Turn right. @@ -2338,9 +2381,9 @@ static void outline_block_structure(drawing *dr, game_drawstate *ds, * somewhere sensible. */ assert(x >= 0 && x < w && y >= 0 && y < w && - dsf_canonify(dsf, y*w+x) == i); + dsf_minimal(dsf, y*w+x) == i); assert(x+dx < 0 || x+dx >= w || y+dy < 0 || y+dy >= w || - dsf_canonify(dsf, (y+dy)*w+(x+dx)) != i); + dsf_minimal(dsf, (y+dy)*w+(x+dx)) != i); /* * Record the point we just went past at one end of the @@ -2367,7 +2410,8 @@ static void outline_block_structure(drawing *dr, game_drawstate *ds, sfree(coords); } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->par.w; int ink = print_mono_colour(dr, 0); @@ -2413,7 +2457,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) */ for (y = 0; y < w; y++) for (x = 0; x < w; x++) - if (dsf_canonify(state->clues->dsf, y*w+x) == y*w+x) { + if (dsf_minimal(state->clues->dsf, y*w+x) == y*w+x) { long clue = state->clues->clues[y*w+x]; long cluetype = clue & CMASK, clueval = clue & ~CMASK; int size = dsf_size(state->clues->dsf, y*w+x); @@ -2478,13 +2522,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -2498,7 +2544,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ }; diff --git a/apps/plugins/puzzles/src/latin.c b/apps/plugins/puzzles/src/latin.c index 39930166e7..a2d5713b30 100644 --- a/apps/plugins/puzzles/src/latin.c +++ b/apps/plugins/puzzles/src/latin.c @@ -563,7 +563,7 @@ void latin_solver_free_scratch(struct latin_solver_scratch *scratch) sfree(scratch); } -void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) +bool latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) { int x, y; @@ -577,14 +577,23 @@ void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) memset(solver->row, 0, o*o); memset(solver->col, 0, o*o); - for (x = 0; x < o; x++) - for (y = 0; y < o; y++) - if (grid[y*o+x]) - latin_solver_place(solver, x, y, grid[y*o+x]); - #ifdef STANDALONE_SOLVER solver->names = NULL; #endif + + for (x = 0; x < o; x++) { + for (y = 0; y < o; y++) { + int n = grid[y*o+x]; + if (n) { + if (cube(x, y, n)) + latin_solver_place(solver, x, y, n); + else + return false; /* puzzle is already inconsistent */ + } + } + } + + return true; } void latin_solver_free(struct latin_solver *solver) @@ -810,15 +819,17 @@ static int latin_solver_recurse } else { newctx = ctx; } - latin_solver_alloc(&subsolver, outgrid, o); #ifdef STANDALONE_SOLVER subsolver.names = solver->names; #endif - ret = latin_solver_top(&subsolver, diff_recursive, - diff_simple, diff_set_0, diff_set_1, - diff_forcing, diff_recursive, - usersolvers, valid, newctx, - ctxnew, ctxfree); + if (latin_solver_alloc(&subsolver, outgrid, o)) + ret = latin_solver_top(&subsolver, diff_recursive, + diff_simple, diff_set_0, diff_set_1, + diff_forcing, diff_recursive, + usersolvers, valid, newctx, + ctxnew, ctxfree); + else + ret = diff_impossible; latin_solver_free(&subsolver); if (ctxnew) ctxfree(newctx); @@ -1059,11 +1070,13 @@ int latin_solver(digit *grid, int o, int maxdiff, struct latin_solver solver; int diff; - latin_solver_alloc(&solver, grid, o); - diff = latin_solver_main(&solver, maxdiff, - diff_simple, diff_set_0, diff_set_1, - diff_forcing, diff_recursive, - usersolvers, valid, ctx, ctxnew, ctxfree); + if (latin_solver_alloc(&solver, grid, o)) + diff = latin_solver_main(&solver, maxdiff, + diff_simple, diff_set_0, diff_set_1, + diff_forcing, diff_recursive, + usersolvers, valid, ctx, ctxnew, ctxfree); + else + diff = diff_impossible; latin_solver_free(&solver); return diff; } @@ -1298,121 +1311,4 @@ bool latin_check(digit *sq, int order) return ret; } - -/* -------------------------------------------------------- - * Testing (and printing). - */ - -#ifdef STANDALONE_LATIN_TEST - -#include -#include - -const char *quis; - -static void latin_print(digit *sq, int order) -{ - int x, y; - - for (y = 0; y < order; y++) { - for (x = 0; x < order; x++) { - printf("%2u ", ELT(sq, x, y)); - } - printf("\n"); - } - printf("\n"); -} - -static void gen(int order, random_state *rs, int debug) -{ - digit *sq; - - solver_show_working = debug; - - sq = latin_generate(order, rs); - latin_print(sq, order); - if (latin_check(sq, order)) { - fprintf(stderr, "Square is not a latin square!"); - exit(1); - } - - sfree(sq); -} - -void test_soak(int order, random_state *rs) -{ - digit *sq; - int n = 0; - time_t tt_start, tt_now, tt_last; - - solver_show_working = 0; - tt_now = tt_start = time(NULL); - - while(1) { - sq = latin_generate(order, rs); - sfree(sq); - n++; - - tt_last = time(NULL); - if (tt_last > tt_now) { - tt_now = tt_last; - printf("%d total, %3.1f/s\n", n, - (double)n / (double)(tt_now - tt_start)); - } - } -} - -void usage_exit(const char *msg) -{ - if (msg) - fprintf(stderr, "%s: %s\n", quis, msg); - fprintf(stderr, "Usage: %s [--seed SEED] --soak | [game_id [game_id ...]]\n", quis); - exit(1); -} - -int main(int argc, char *argv[]) -{ - int i, soak = 0; - random_state *rs; - time_t seed = time(NULL); - - quis = argv[0]; - while (--argc > 0) { - const char *p = *++argv; - if (!strcmp(p, "--soak")) - soak = 1; - else if (!strcmp(p, "--seed")) { - if (argc == 0) - usage_exit("--seed needs an argument"); - seed = (time_t)atoi(*++argv); - argc--; - } else if (*p == '-') - usage_exit("unrecognised option"); - else - break; /* finished options */ - } - - rs = random_new((void*)&seed, sizeof(time_t)); - - if (soak == 1) { - if (argc != 1) usage_exit("only one argument for --soak"); - test_soak(atoi(*argv), rs); - } else { - if (argc > 0) { - for (i = 0; i < argc; i++) { - gen(atoi(*argv++), rs, 1); - } - } else { - while (1) { - i = random_upto(rs, 20) + 1; - gen(i, rs, 0); - } - } - } - random_free(rs); - return 0; -} - -#endif - /* vim: set shiftwidth=4 tabstop=8: */ diff --git a/apps/plugins/puzzles/src/latin.h b/apps/plugins/puzzles/src/latin.h index bb172ec3c7..96a0480491 100644 --- a/apps/plugins/puzzles/src/latin.h +++ b/apps/plugins/puzzles/src/latin.h @@ -61,10 +61,13 @@ int latin_solver_forcing(struct latin_solver *solver, /* --- Solver allocation --- */ /* Fills in (and allocates members for) a latin_solver struct. - * Will allocate members of snew, but not snew itself + * Will allocate members of solver, but not solver itself * (allowing 'struct latin_solver' to be the first element in a larger - * struct, for example). */ -void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o); + * struct, for example). + * + * latin_solver_alloc returns false if the digits already in the grid + * could not be legally placed. */ +bool latin_solver_alloc(struct latin_solver *solver, digit *grid, int o); void latin_solver_free(struct latin_solver *solver); /* Allocates scratch space (for _set and _forcing) */ diff --git a/apps/plugins/puzzles/src/lightup.R b/apps/plugins/puzzles/src/lightup.R deleted file mode 100644 index a474de815d..0000000000 --- a/apps/plugins/puzzles/src/lightup.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -LIGHTUP_EXTRA = combi - -lightup : [X] GTK COMMON lightup LIGHTUP_EXTRA lightup-icon|no-icon - -lightup : [G] WINDOWS COMMON lightup LIGHTUP_EXTRA lightup.res|noicon.res - -lightupsolver : [U] lightup[STANDALONE_SOLVER] LIGHTUP_EXTRA STANDALONE -lightupsolver : [C] lightup[STANDALONE_SOLVER] LIGHTUP_EXTRA STANDALONE - -ALL += lightup[COMBINED] LIGHTUP_EXTRA - -!begin am gtk -GAMES += lightup -!end - -!begin >list.c - A(lightup) \ -!end - -!begin >gamedesc.txt -lightup:lightup.exe:Light Up:Light-bulb placing puzzle:Place bulbs to light up all the squares. -!end diff --git a/apps/plugins/puzzles/src/lightup.c b/apps/plugins/puzzles/src/lightup.c index ab4be9ec87..e779663e01 100644 --- a/apps/plugins/puzzles/src/lightup.c +++ b/apps/plugins/puzzles/src/lightup.c @@ -47,7 +47,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -58,7 +63,7 @@ */ #if defined STANDALONE_SOLVER #define SOLVER_DIAGNOSTICS -int verbose = 0; +static int verbose = 0; #undef debug #define debug(x) printf x #elif defined SOLVER_DIAGNOSTICS @@ -346,6 +351,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 2 || params->h < 2) return "Width and height must be at least 2"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (full) { if (params->blackpc < 5 || params->blackpc > 100) return "Percentage of black squares must be between 5% and 100%"; @@ -353,6 +360,8 @@ static const char *validate_params(const game_params *params, bool full) if (params->symm == SYMM_ROT4) return "4-fold symmetry is only available with square grids"; } + if ((params->symm == SYMM_ROT4 || params->symm == SYMM_REF4) && params->w < 3 && params->h < 3) + return "Width or height must be at least 3 for 4-way symmetry"; if (params->symm < 0 || params->symm >= SYMM_MAX) return "Unknown symmetry type"; if (params->difficulty < 0 || params->difficulty > DIFFCOUNT) @@ -411,6 +420,8 @@ static void debug_state(game_state *state) int x, y; char c = '?'; + (void)c; /* placate -Wunused-but-set-variable if debug() does nothing */ + for (y = 0; y < state->h; y++) { for (x = 0; x < state->w; x++) { c = '.'; @@ -1822,30 +1833,65 @@ static char *game_text_format(const game_state *state) struct game_ui { int cur_x, cur_y; bool cur_visible; + + /* + * User preference: when a square contains both a black blob for + * 'user is convinced this isn't a light' and a yellow highlight + * for 'this square is lit by a light', both of which rule out it + * being a light, should we still bother to show the blob? + */ + bool draw_blobs_when_lit; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int draw_blobs_when_lit = -1; + + if (!initialised) { + initialised = true; + draw_blobs_when_lit = getenv_bool("LIGHTUP_LIT_BLOBS", -1); + } + + if (draw_blobs_when_lit != -1) + ui_out->draw_blobs_when_lit = draw_blobs_when_lit; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); + ui->draw_blobs_when_lit = true; + legacy_prefs_override(ui); return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Draw non-light marks even when lit"; + ret[0].kw = "show-lit-blobs"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->draw_blobs_when_lit; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - /* nothing to encode. */ - return NULL; + ui->draw_blobs_when_lit = cfg[0].u.boolean.bval; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { - /* nothing to decode. */ + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1855,6 +1901,26 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cur_visible = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int cx = ui->cur_x, cy = ui->cur_y; + unsigned int flags = GRID(state, flags, cx, cy); + + if (!ui->cur_visible) return ""; + if (button == CURSOR_SELECT) { + if (flags & (F_BLACK | F_IMPOSSIBLE)) return ""; + if (flags & F_LIGHT) return "Clear"; + return "Light"; + } + if (button == CURSOR_SELECT2) { + if (flags & (F_BLACK | F_LIGHT)) return ""; + if (flags & F_IMPOSSIBLE) return "Clear"; + return "Mark"; + } + return ""; +} + #define DF_BLACK 1 /* black square */ #define DF_NUMBERED 2 /* black square with number */ #define DF_LIT 4 /* display (white) square lit up */ @@ -1888,7 +1954,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, enum { NONE, FLIP_LIGHT, FLIP_IMPOSSIBLE } action = NONE; int cx = -1, cy = -1; unsigned int flags; - char buf[80], *nullret = UI_UPDATE, *empty = UI_UPDATE, c; + char buf[80], *nullret = MOVE_NO_EFFECT, *empty = MOVE_UI_UPDATE, c; if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { if (ui->cur_visible) @@ -1898,8 +1964,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, cy = FROMCOORD(y); action = (button == LEFT_BUTTON) ? FLIP_LIGHT : FLIP_IMPOSSIBLE; } else if (IS_CURSOR_SELECT(button) || - button == 'i' || button == 'I' || - button == ' ' || button == '\r' || button == '\n') { + button == 'i' || button == 'I') { if (ui->cur_visible) { /* Only allow cursor-effect operations if the cursor is visible * (otherwise you have no idea which square it might be affecting) */ @@ -1910,11 +1975,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->cur_visible = true; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false); - ui->cur_visible = true; - nullret = empty; + nullret = move_cursor(button, &ui->cur_x, &ui->cur_y, + state->w, state->h, false, &ui->cur_visible); } else - return NULL; + return MOVE_UNUSED; switch (action) { case FLIP_LIGHT: @@ -2002,7 +2066,7 @@ badmove: /* XXX entirely cloned from fifteen.c; separate out? */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2111,7 +2175,7 @@ static unsigned int tile_flags(game_drawstate *ds, const game_state *state, return ret; } -static void tile_redraw(drawing *dr, game_drawstate *ds, +static void tile_redraw(drawing *dr, game_drawstate *ds, const game_ui *ui, const game_state *state, int x, int y) { unsigned int ds_flags = GRID(ds, flags, x, y); @@ -2141,13 +2205,7 @@ static void tile_redraw(drawing *dr, game_drawstate *ds, draw_circle(dr, dx + TILE_SIZE/2, dy + TILE_SIZE/2, TILE_RADIUS, lcol, COL_BLACK); } else if ((ds_flags & DF_IMPOSSIBLE)) { - static int draw_blobs_when_lit = -1; - if (draw_blobs_when_lit < 0) { - char *env = getenv("LIGHTUP_LIT_BLOBS"); - draw_blobs_when_lit = (!env || (env[0] == 'y' || - env[0] == 'Y')); - } - if (!(ds_flags & DF_LIT) || draw_blobs_when_lit) { + if (!(ds_flags & DF_LIT) || ui->draw_blobs_when_lit) { int rlen = TILE_SIZE / 4; draw_rect(dr, dx + TILE_SIZE/2 - rlen/2, dy + TILE_SIZE/2 - rlen/2, @@ -2176,10 +2234,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (flashtime) flashing = (int)(flashtime * 3 / FLASH_TIME) != 1; if (!ds->started) { - draw_rect(dr, 0, 0, - TILE_SIZE * ds->w + 2 * BORDER, - TILE_SIZE * ds->h + 2 * BORDER, COL_BACKGROUND); - draw_rect_outline(dr, COORD(0)-1, COORD(0)-1, TILE_SIZE * ds->w + 2, TILE_SIZE * ds->h + 2, @@ -2196,7 +2250,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, unsigned int ds_flags = tile_flags(ds, state, ui, x, y, flashing); if (ds_flags != GRID(ds, flags, x, y)) { GRID(ds, flags, x, y) = ds_flags; - tile_redraw(dr, ds, state, x, y); + tile_redraw(dr, ds, ui, state, x, y); } } } @@ -2235,24 +2289,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->w, h = state->h; int ink = print_mono_colour(dr, 0); @@ -2323,12 +2374,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2342,7 +2395,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/list.c b/apps/plugins/puzzles/src/list.c new file mode 100644 index 0000000000..28cefca017 --- /dev/null +++ b/apps/plugins/puzzles/src/list.c @@ -0,0 +1,17 @@ +/* + * list.c: List of pointers to puzzle structures, for monolithic + * platforms. + * + * This file depends on the header "generated-games.h", which is + * constructed by CMakeLists.txt. + */ + +#include "puzzles.h" + +#define GAME(x) &x, +const game *gamelist[] = { +#include "generated-games.h" +}; +#undef GAME + +const int gamecount = lenof(gamelist); diff --git a/apps/plugins/puzzles/src/loopgen.c b/apps/plugins/puzzles/src/loopgen.c index e738d4a26d..05097fe304 100644 --- a/apps/plugins/puzzles/src/loopgen.c +++ b/apps/plugins/puzzles/src/loopgen.c @@ -8,7 +8,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -79,7 +83,7 @@ static bool can_colour_face(grid *g, char* board, int face_index, enum face_colour colour) { int i, j; - grid_face *test_face = g->faces + face_index; + grid_face *test_face = g->faces[face_index]; grid_face *starting_face, *current_face; grid_dot *starting_dot; int transitions; @@ -344,7 +348,7 @@ void generate_loop(grid *g, char *board, random_state *rs, * to check every face of the board (the grid structure does not keep a * list of the infinite face's neighbours). */ for (i = 0; i < num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; struct face_score *fs = face_scores + i; if (board[i] != FACE_GREY) continue; /* We need the full colourability check here, it's not enough simply @@ -426,7 +430,7 @@ void generate_loop(grid *g, char *board, random_state *rs, del234(darkable_faces_sorted, fs); /* Remember which face we've just coloured */ - cur_face = g->faces + i; + cur_face = g->faces[i]; /* The face we've just coloured potentially affects the colourability * and the scores of any neighbouring faces (touching at a corner or @@ -452,7 +456,7 @@ void generate_loop(grid *g, char *board, random_state *rs, if (FACE_COLOUR(f) != FACE_GREY) continue; /* Find the face index and face_score* corresponding to f */ - fi = f - g->faces; + fi = f->index; fs = face_scores + fi; /* Remove from lightable list if it's in there. We do this, @@ -513,7 +517,7 @@ void generate_loop(grid *g, char *board, random_state *rs, enum face_colour opp = (board[j] == FACE_WHITE) ? FACE_BLACK : FACE_WHITE; if (can_colour_face(g, board, j, opp)) { - grid_face *face = g->faces +j; + grid_face *face = g->faces[j]; if (do_random_pass) { /* final random pass */ if (!random_upto(rs, 10)) diff --git a/apps/plugins/puzzles/src/loopgen.h b/apps/plugins/puzzles/src/loopgen.h index 079c87c576..bab95814d2 100644 --- a/apps/plugins/puzzles/src/loopgen.h +++ b/apps/plugins/puzzles/src/loopgen.h @@ -2,8 +2,8 @@ * loopgen.h: interface file for loop generation functions for grid.[ch]. */ -#ifndef _LOOPGEN_H -#define _LOOPGEN_H +#ifndef PUZZLES_LOOPGEN_H +#define PUZZLES_LOOPGEN_H #include "puzzles.h" #include "grid.h" @@ -13,7 +13,7 @@ enum face_colour { FACE_WHITE, FACE_GREY, FACE_BLACK }; /* face should be of type grid_face* here. */ #define FACE_COLOUR(face) \ ( (face) == NULL ? FACE_BLACK : \ - board[(face) - g->faces] ) + board[(face)->index] ) typedef int (*loopgen_bias_fn_t)(void *ctx, char *board, int face); diff --git a/apps/plugins/puzzles/src/loopy.R b/apps/plugins/puzzles/src/loopy.R deleted file mode 100644 index f44560095d..0000000000 --- a/apps/plugins/puzzles/src/loopy.R +++ /dev/null @@ -1,31 +0,0 @@ -# -*- makefile -*- - -LOOPY_EXTRA = tree234 dsf grid penrose loopgen - -loopy : [X] GTK COMMON loopy LOOPY_EXTRA loopy-icon|no-icon - -loopy : [G] WINDOWS COMMON loopy LOOPY_EXTRA loopy.res|noicon.res - -loopysolver : [U] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE m.lib -loopysolver : [C] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE - -#penrose : [U] penrose[TEST_PENROSE] STANDALONE m.lib -#penrose : [C] penrose[TEST_PENROSE] STANDALONE - -#test-basis : [U] penrose[TEST_VECTORS] tree234 STANDALONE m.lib -#test-basis : [C] penrose[TEST_VECTORS] tree234 STANDALONE - - -ALL += loopy[COMBINED] LOOPY_EXTRA - -!begin am gtk -GAMES += loopy -!end - -!begin >list.c - A(loopy) \ -!end - -!begin >gamedesc.txt -loopy:loopy.exe:Loopy:Loop-drawing puzzle:Draw a single closed loop, given clues about number of adjacent edges. -!end diff --git a/apps/plugins/puzzles/src/loopy.c b/apps/plugins/puzzles/src/loopy.c index 176b56285c..b30dd68f4d 100644 --- a/apps/plugins/puzzles/src/loopy.c +++ b/apps/plugins/puzzles/src/loopy.c @@ -25,28 +25,28 @@ * outside respectively. So if you can track this for all * faces, you figure out the state of the line between a pair * once their relative insideness is known. - * + The way I envisage this working is simply to keep an edsf + * + The way I envisage this working is simply to keep a flip dsf * of all _faces_, which indicates whether they're on * opposite sides of the loop from one another. We also - * include a special entry in the edsf for the infinite + * include a special entry in the dsf for the infinite * exterior "face". * + So, the simple way to do this is to just go through the * edges: every time we see an edge in a state other than * LINE_UNKNOWN which separates two faces that aren't in the - * same edsf class, we can rectify that by merging the + * same dsf class, we can rectify that by merging the * classes. Then, conversely, an edge in LINE_UNKNOWN state - * which separates two faces that _are_ in the same edsf + * which separates two faces that _are_ in the same dsf * class can immediately have its state determined. * + But you can go one better, if you're prepared to loop * over all _pairs_ of edges. Suppose we have edges A and B, * which respectively separate faces A1,A2 and B1,B2. - * Suppose that A,B are in the same edge-edsf class and that - * A1,B1 (wlog) are in the same face-edsf class; then we can - * immediately place A2,B2 into the same face-edsf class (as + * Suppose that A,B are in the same edge-dsf class and that + * A1,B1 (wlog) are in the same face-dsf class; then we can + * immediately place A2,B2 into the same face-dsf class (as * each other, not as A1 and A2) one way round or the other. - * And conversely again, if A1,B1 are in the same face-edsf + * And conversely again, if A1,B1 are in the same face-dsf * class and so are A2,B2, then we can put A,B into the same - * face-edsf class. + * face-dsf class. * * Of course, this deduction requires a quadratic-time * loop over all pairs of edges in the grid, so it should * be reserved until there's nothing easier left to be @@ -77,7 +77,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -153,7 +157,7 @@ typedef struct solver_state { char *face_yes_count; char *face_no_count; bool *dot_solved, *face_solved; - int *dotdsf; + DSF *dotdsf; /* Information for Normal level deductions: * For each dline, store a bitmask for whether we know: @@ -162,7 +166,7 @@ typedef struct solver_state { char *dlines; /* Hard level information */ - int *linedsf; + DSF *linedsf; } solver_state; /* @@ -279,6 +283,9 @@ static void check_caches(const solver_state* sstate); A("Penrose (rhombs)",PENROSE_P3,3,3) \ A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \ A("Kagome",KAGOME,3,3) \ + A("Compass-Dodecagonal",COMPASSDODECAGONAL,2,2) \ + A("Hats",HATS,6,6) \ + A("Spectres",SPECTRES,6,6) \ /* end of list */ #define GRID_NAME(title,type,amin,omin) title, @@ -380,7 +387,7 @@ static solver_state *new_solver_state(const game_state *state, int diff) { ret->solver_status = SOLVER_INCOMPLETE; ret->diff = diff; - ret->dotdsf = snew_dsf(num_dots); + ret->dotdsf = dsf_new(num_dots); ret->looplen = snewn(num_dots, int); for (i = 0; i < num_dots; i++) { @@ -411,7 +418,7 @@ static solver_state *new_solver_state(const game_state *state, int diff) { if (diff < DIFF_HARD) { ret->linedsf = NULL; } else { - ret->linedsf = snew_dsf(state->game_grid->num_edges); + ret->linedsf = dsf_new_flip(state->game_grid->num_edges); } return ret; @@ -420,7 +427,7 @@ static solver_state *new_solver_state(const game_state *state, int diff) { static void free_solver_state(solver_state *sstate) { if (sstate) { free_game(sstate->state); - sfree(sstate->dotdsf); + dsf_free(sstate->dotdsf); sfree(sstate->looplen); sfree(sstate->dot_solved); sfree(sstate->face_solved); @@ -431,7 +438,7 @@ static void free_solver_state(solver_state *sstate) { /* OK, because sfree(NULL) is a no-op */ sfree(sstate->dlines); - sfree(sstate->linedsf); + dsf_free(sstate->linedsf); sfree(sstate); } @@ -449,10 +456,9 @@ static solver_state *dup_solver_state(const solver_state *sstate) { ret->solver_status = sstate->solver_status; ret->diff = sstate->diff; - ret->dotdsf = snewn(num_dots, int); + ret->dotdsf = dsf_new(num_dots); ret->looplen = snewn(num_dots, int); - memcpy(ret->dotdsf, sstate->dotdsf, - num_dots * sizeof(int)); + dsf_copy(ret->dotdsf, sstate->dotdsf); memcpy(ret->looplen, sstate->looplen, num_dots * sizeof(int)); @@ -480,9 +486,8 @@ static solver_state *dup_solver_state(const solver_state *sstate) { } if (sstate->linedsf) { - ret->linedsf = snewn(num_edges, int); - memcpy(ret->linedsf, sstate->linedsf, - num_edges * sizeof(int)); + ret->linedsf = dsf_new_flip(num_edges); + dsf_copy(ret->linedsf, sstate->linedsf); } else { ret->linedsf = NULL; } @@ -552,6 +557,9 @@ static const game_params loopy_presets_more[] = { { 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, { 3, 3, DIFF_HARD, LOOPY_GRID_GREATDODECAGONAL }, { 3, 2, DIFF_HARD, LOOPY_GRID_GREATGREATDODECAGONAL }, + { 3, 3, DIFF_HARD, LOOPY_GRID_COMPASSDODECAGONAL }, + { 6, 6, DIFF_HARD, LOOPY_GRID_HATS }, + { 6, 6, DIFF_HARD, LOOPY_GRID_SPECTRES }, #else { 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, @@ -561,6 +569,9 @@ static const game_params loopy_presets_more[] = { { 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, { 5, 4, DIFF_HARD, LOOPY_GRID_GREATDODECAGONAL }, { 5, 3, DIFF_HARD, LOOPY_GRID_GREATGREATDODECAGONAL }, + { 5, 4, DIFF_HARD, LOOPY_GRID_COMPASSDODECAGONAL }, + { 10, 10, DIFF_HARD, LOOPY_GRID_HATS }, + { 10, 10, DIFF_HARD, LOOPY_GRID_SPECTRES }, #endif }; @@ -681,6 +692,7 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { + const char *err; if (params->type < 0 || params->type >= NUM_GRID_TYPES) return "Illegal grid type"; if (params->w < grid_size_limits[params->type].amin || @@ -689,6 +701,8 @@ static const char *validate_params(const game_params *params, bool full) if (params->w < grid_size_limits[params->type].omin && params->h < grid_size_limits[params->type].omin) return grid_size_limits[params->type].oerr; + err = grid_validate_params(grid_types[params->type], params->w, params->h); + if (err != NULL) return err; /* * This shouldn't be able to happen at all, since decode_params @@ -771,10 +785,13 @@ static const char *validate_desc(const game_params *params, const char *desc) * know is the precise number of faces. */ grid_desc = extract_grid_desc(&desc); ret = grid_validate_desc(grid_types[params->type], params->w, params->h, grid_desc); - if (ret) return ret; + if (ret) { + sfree(grid_desc); + return ret; + } g = loopy_generate_grid(params, grid_desc); - if (grid_desc) sfree(grid_desc); + sfree(grid_desc); for (; *desc; ++desc) { if ((*desc >= '0' && *desc <= '9') || (*desc >= 'A' && *desc <= 'Z')) { @@ -785,13 +802,18 @@ static const char *validate_desc(const game_params *params, const char *desc) count += *desc - 'a' + 1; continue; } + grid_free(g); return "Unknown character in description"; } - if (count < g->num_faces) + if (count < g->num_faces) { + grid_free(g); return "Description too short for board size"; - if (count > g->num_faces) + } + if (count > g->num_faces) { + grid_free(g); return "Description too long for board size"; + } grid_free(g); @@ -850,22 +872,98 @@ static char *encode_solve_move(const game_state *state) return ret; } +struct game_ui { + /* + * User preference: should grid lines in LINE_NO state be drawn + * very faintly so users can still see where they are, or should + * they be completely invisible? + */ + bool draw_faint_lines; + + /* + * User preference: when clicking an edge that has only one + * possible edge connecting to one (or both) of its ends, should + * that edge also change to the same state as the edge we just + * clicked? + */ + enum { + AF_OFF, /* no, all grid edges are independent in the UI */ + AF_FIXED, /* yes, but only based on the grid itself */ + AF_ADAPTIVE /* yes, and consider edges user has already set to NO */ + } autofollow; +}; + +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int draw_faint_lines = -1; + static int autofollow = -1; + + if (!initialised) { + char *env; + + initialised = true; + draw_faint_lines = getenv_bool("LOOPY_FAINT_LINES", -1); + + if ((env = getenv("LOOPY_AUTOFOLLOW")) != NULL) { + if (!strcmp(env, "off")) + autofollow = AF_OFF; + else if (!strcmp(env, "fixed")) + autofollow = AF_FIXED; + else if (!strcmp(env, "adaptive")) + autofollow = AF_ADAPTIVE; + } + } + + if (draw_faint_lines != -1) + ui_out->draw_faint_lines = draw_faint_lines; + if (autofollow != -1) + ui_out->autofollow = autofollow; +} + static game_ui *new_ui(const game_state *state) { - return NULL; + game_ui *ui = snew(game_ui); + ui->draw_faint_lines = true; + ui->autofollow = AF_OFF; + legacy_prefs_override(ui); + return ui; } static void free_ui(game_ui *ui) { + sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(3, config_item); + + ret[0].name = "Draw excluded grid lines faintly"; + ret[0].kw = "draw-faint-lines"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->draw_faint_lines; + + ret[1].name = "Auto-follow unique paths of edges"; + ret[1].kw = "auto-follow"; + ret[1].type = C_CHOICES; + ret[1].u.choices.choicenames = + ":No:Based on grid only:Based on grid and game state"; + ret[1].u.choices.choicekws = ":off:fixed:adaptive"; + ret[1].u.choices.selected = ui->autofollow; + + ret[2].name = NULL; + ret[2].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->draw_faint_lines = cfg[0].u.boolean.bval; + ui->autofollow = cfg[1].u.choices.selected; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -874,7 +972,7 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { int grid_width, grid_height, rendered_width, rendered_height; int g_tilesize; @@ -974,11 +1072,6 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) sfree(ds); } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - static float game_anim_length(const game_state *oldstate, const game_state *newstate, int dir, game_ui *ui) { @@ -1004,7 +1097,7 @@ static char *game_text_format(const game_state *state) assert(state->grid_type == 0); /* Work out the basic size unit */ - f = g->faces; /* first face */ + f = g->faces[0]; /* first face */ assert(f->order == 4); /* The dots are ordered clockwise, so the two opposite * corners are guaranteed to span the square */ @@ -1027,7 +1120,7 @@ static char *game_text_format(const game_state *state) /* Fill in edge info */ for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; /* Cell coordinates, from (0,0) to (w-1,h-1) */ int x1 = (e->dot1->x - g->lowest_x) / cell_size; int x2 = (e->dot2->x - g->lowest_x) / cell_size; @@ -1055,7 +1148,7 @@ static char *game_text_format(const game_state *state) for (i = 0; i < g->num_faces; i++) { int x1, x2, y1, y2; - f = g->faces + i; + f = g->faces[i]; assert(f->order == 4); /* Cell coordinates, from (0,0) to (w-1,h-1) */ x1 = (f->dots[0]->x - g->lowest_x) / cell_size; @@ -1135,26 +1228,26 @@ static bool solver_set_line(solver_state *sstate, int i, #endif g = state->game_grid; - e = g->edges + i; + e = g->edges[i]; /* Update the cache for both dots and both faces affected by this. */ if (line_new == LINE_YES) { - sstate->dot_yes_count[e->dot1 - g->dots]++; - sstate->dot_yes_count[e->dot2 - g->dots]++; + sstate->dot_yes_count[e->dot1->index]++; + sstate->dot_yes_count[e->dot2->index]++; if (e->face1) { - sstate->face_yes_count[e->face1 - g->faces]++; + sstate->face_yes_count[e->face1->index]++; } if (e->face2) { - sstate->face_yes_count[e->face2 - g->faces]++; + sstate->face_yes_count[e->face2->index]++; } } else { - sstate->dot_no_count[e->dot1 - g->dots]++; - sstate->dot_no_count[e->dot2 - g->dots]++; + sstate->dot_no_count[e->dot1->index]++; + sstate->dot_no_count[e->dot2->index]++; if (e->face1) { - sstate->face_no_count[e->face1 - g->faces]++; + sstate->face_no_count[e->face1->index]++; } if (e->face2) { - sstate->face_no_count[e->face2 - g->faces]++; + sstate->face_no_count[e->face2->index]++; } } @@ -1178,10 +1271,10 @@ static bool merge_dots(solver_state *sstate, int edge_index) { int i, j, len; grid *g = sstate->state->game_grid; - grid_edge *e = g->edges + edge_index; + grid_edge *e = g->edges[edge_index]; - i = e->dot1 - g->dots; - j = e->dot2 - g->dots; + i = e->dot1->index; + j = e->dot2->index; i = dsf_canonify(sstate->dotdsf, i); j = dsf_canonify(sstate->dotdsf, j); @@ -1211,12 +1304,12 @@ static bool merge_lines(solver_state *sstate, int i, int j, bool inverse assert(i < sstate->state->game_grid->num_edges); assert(j < sstate->state->game_grid->num_edges); - i = edsf_canonify(sstate->linedsf, i, &inv_tmp); + i = dsf_canonify_flip(sstate->linedsf, i, &inv_tmp); inverse ^= inv_tmp; - j = edsf_canonify(sstate->linedsf, j, &inv_tmp); + j = dsf_canonify_flip(sstate->linedsf, j, &inv_tmp); inverse ^= inv_tmp; - edsf_merge(sstate->linedsf, i, j, inverse); + dsf_merge_flip(sstate->linedsf, i, j, inverse); #ifdef SHOW_WORKING if (i != j) { @@ -1239,12 +1332,12 @@ static int dot_order(const game_state* state, int dot, char line_type) { int n = 0; grid *g = state->game_grid; - grid_dot *d = g->dots + dot; + grid_dot *d = g->dots[dot]; int i; for (i = 0; i < d->order; i++) { grid_edge *e = d->edges[i]; - if (state->lines[e - g->edges] == line_type) + if (state->lines[e->index] == line_type) ++n; } return n; @@ -1256,12 +1349,12 @@ static int face_order(const game_state* state, int face, char line_type) { int n = 0; grid *g = state->game_grid; - grid_face *f = g->faces + face; + grid_face *f = g->faces[face]; int i; for (i = 0; i < f->order; i++) { grid_edge *e = f->edges[i]; - if (state->lines[e - g->edges] == line_type) + if (state->lines[e->index] == line_type) ++n; } return n; @@ -1282,10 +1375,10 @@ static bool dot_setall(solver_state *sstate, int dot, return false; g = state->game_grid; - d = g->dots + dot; + d = g->dots[dot]; for (i = 0; i < d->order; i++) { - int line_index = d->edges[i] - g->edges; + int line_index = d->edges[i]->index; if (state->lines[line_index] == old_type) { r = solver_set_line(sstate, line_index, new_type); assert(r); @@ -1309,10 +1402,10 @@ static bool face_setall(solver_state *sstate, int face, return false; g = state->game_grid; - f = g->faces + face; + f = g->faces[face]; for (i = 0; i < f->order; i++) { - int line_index = f->edges[i] - g->edges; + int line_index = f->edges[i]->index; if (state->lines[line_index] == old_type) { r = solver_set_line(sstate, line_index, new_type); assert(r); @@ -1341,7 +1434,7 @@ static void add_full_clues(game_state *state, random_state *rs) * algorithm does work, and there aren't any GREY faces still there. */ memset(clues, 0, g->num_faces); for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; grid_face *f1 = e->face1; grid_face *f2 = e->face2; enum face_colour c1 = FACE_COLOUR(f1); @@ -1349,8 +1442,8 @@ static void add_full_clues(game_state *state, random_state *rs) assert(c1 != FACE_GREY); assert(c2 != FACE_GREY); if (c1 != c2) { - if (f1) clues[f1 - g->faces]++; - if (f2) clues[f2 - g->faces]++; + if (f1) clues[f1->index]++; + if (f2) clues[f2->index]++; } } sfree(board); @@ -1361,7 +1454,7 @@ static bool game_has_unique_soln(const game_state *state, int diff) { bool ret; solver_state *sstate_new; - solver_state *sstate = new_solver_state((game_state *)state, diff); + solver_state *sstate = new_solver_state(state, diff); sstate_new = solve_game_rec(sstate); @@ -1541,7 +1634,8 @@ static bool check_completion(game_state *state) grid *g = state->game_grid; int i; bool ret; - int *dsf, *component_state; + DSF *dsf; + int *component_state; int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize; enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY }; @@ -1626,13 +1720,13 @@ static bool check_completion(game_state *state) * leave that one unhighlighted, and light the rest up in red. */ - dsf = snew_dsf(g->num_dots); + dsf = dsf_new(g->num_dots); /* Build the dsf. */ for (i = 0; i < g->num_edges; i++) { if (state->lines[i] == LINE_YES) { - grid_edge *e = g->edges + i; - int d1 = e->dot1 - g->dots, d2 = e->dot2 - g->dots; + grid_edge *e = g->edges[i]; + int d1 = e->dot1->index, d2 = e->dot2->index; dsf_merge(dsf, d1, d2); } } @@ -1657,10 +1751,10 @@ static bool check_completion(game_state *state) int unknown = dot_order(state, i, LINE_UNKNOWN); if ((yes == 1 && unknown == 0) || (yes >= 3)) { /* violation, so mark all YES edges as errors */ - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int j; for (j = 0; j < d->order; j++) { - int e = d->edges[j] - g->edges; + int e = d->edges[j]->index; if (state->lines[e] == LINE_YES) state->line_errors[e] = true; } @@ -1723,8 +1817,8 @@ static bool check_completion(game_state *state) */ for (i = 0; i < g->num_edges; i++) { if (state->lines[i] == LINE_YES) { - grid_edge *e = g->edges + i; - int d1 = e->dot1 - g->dots; /* either endpoint is good enough */ + grid_edge *e = g->edges[i]; + int d1 = e->dot1->index; /* either endpoint is good enough */ int comp = dsf_canonify(dsf, d1); if ((component_state[comp] == COMP_PATH && -1 != largest_comp) || @@ -1763,7 +1857,7 @@ static bool check_completion(game_state *state) } sfree(component_state); - sfree(dsf); + dsf_free(dsf); return ret; } @@ -1782,7 +1876,7 @@ static bool check_completion(game_state *state) * know both or neither is on that's already stored more directly.) * * Advanced Mode - * Use edsf data structure to make equivalence classes of lines that are + * Use flip dsf data structure to make equivalence classes of lines that are * known identical to or opposite to one another. */ @@ -1822,11 +1916,10 @@ static int dline_index_from_dot(grid *g, grid_dot *d, int i) if (i2 == d->order) i2 = 0; e2 = d->edges[i2]; #endif - ret = 2 * (e - g->edges) + ((e->dot1 == d) ? 1 : 0); + ret = 2 * (e->index) + ((e->dot1 == d) ? 1 : 0); #ifdef DEBUG_DLINES printf("dline_index_from_dot: d=%d,i=%d, edges [%d,%d] - %d\n", - (int)(d - g->dots), i, (int)(e - g->edges), - (int)(e2 - g->edges), ret); + (int)(d->index), i, (int)(e->index), (int)(e2 ->index), ret); #endif return ret; } @@ -1845,11 +1938,10 @@ static int dline_index_from_face(grid *g, grid_face *f, int i) if (i2 < 0) i2 += f->order; e2 = f->edges[i2]; #endif - ret = 2 * (e - g->edges) + ((e->dot1 == d) ? 1 : 0); + ret = 2 * (e->index) + ((e->dot1 == d) ? 1 : 0); #ifdef DEBUG_DLINES printf("dline_index_from_face: f=%d,i=%d, edges [%d,%d] - %d\n", - (int)(f - g->faces), i, (int)(e - g->edges), - (int)(e2 - g->edges), ret); + (int)(f->index), i, (int)(e->index), (int)(e2->index), ret); #endif return ret; } @@ -1907,9 +1999,9 @@ static bool dline_set_opp_atleastone(solver_state *sstate, opp2 = opp + 1; if (opp2 == N) opp2 = 0; /* Check if opp, opp2 point to LINE_UNKNOWNs */ - if (state->lines[d->edges[opp] - g->edges] != LINE_UNKNOWN) + if (state->lines[d->edges[opp]->index] != LINE_UNKNOWN) continue; - if (state->lines[d->edges[opp2] - g->edges] != LINE_UNKNOWN) + if (state->lines[d->edges[opp2]->index] != LINE_UNKNOWN) continue; /* Found opposite UNKNOWNS and they're next to each other */ opp_dline_index = dline_index_from_dot(g, d, opp); @@ -1931,24 +2023,24 @@ static bool face_setall_identical(solver_state *sstate, int face_index, bool retval = false; game_state *state = sstate->state; grid *g = state->game_grid; - grid_face *f = g->faces + face_index; + grid_face *f = g->faces[face_index]; int N = f->order; int i, j; int can1, can2; bool inv1, inv2; for (i = 0; i < N; i++) { - int line1_index = f->edges[i] - g->edges; + int line1_index = f->edges[i]->index; if (state->lines[line1_index] != LINE_UNKNOWN) continue; for (j = i + 1; j < N; j++) { - int line2_index = f->edges[j] - g->edges; + int line2_index = f->edges[j]->index; if (state->lines[line2_index] != LINE_UNKNOWN) continue; /* Found two UNKNOWNS */ - can1 = edsf_canonify(sstate->linedsf, line1_index, &inv1); - can2 = edsf_canonify(sstate->linedsf, line2_index, &inv2); + can1 = dsf_canonify_flip(sstate->linedsf, line1_index, &inv1); + can2 = dsf_canonify_flip(sstate->linedsf, line2_index, &inv2); if (can1 == can2 && inv1 == inv2) { solver_set_line(sstate, line1_index, line_new); solver_set_line(sstate, line2_index, line_new); @@ -1966,9 +2058,8 @@ static void find_unknowns(game_state *state, int *e /* Returned edge indices */) { int c = 0; - grid *g = state->game_grid; while (c < expected_count) { - int line_index = *edge_list - g->edges; + int line_index = (*edge_list)->index; if (state->lines[line_index] == LINE_UNKNOWN) { e[c] = line_index; c++; @@ -1989,7 +2080,7 @@ static int parity_deductions(solver_state *sstate, { game_state *state = sstate->state; int diff = DIFF_MAX; - int *linedsf = sstate->linedsf; + DSF *linedsf = sstate->linedsf; if (unknown_count == 2) { /* Lines are known alike/opposite, depending on inv. */ @@ -2002,9 +2093,9 @@ static int parity_deductions(solver_state *sstate, int can[3]; /* canonical edges */ bool inv[3]; /* whether can[x] is inverse to e[x] */ find_unknowns(state, edge_list, 3, e); - can[0] = edsf_canonify(linedsf, e[0], inv); - can[1] = edsf_canonify(linedsf, e[1], inv+1); - can[2] = edsf_canonify(linedsf, e[2], inv+2); + can[0] = dsf_canonify_flip(linedsf, e[0], inv); + can[1] = dsf_canonify_flip(linedsf, e[1], inv+1); + can[2] = dsf_canonify_flip(linedsf, e[2], inv+2); if (can[0] == can[1]) { if (solver_set_line(sstate, e[2], (total_parity^inv[0]^inv[1]) ? LINE_YES : LINE_NO)) @@ -2025,10 +2116,10 @@ static int parity_deductions(solver_state *sstate, int can[4]; /* canonical edges */ bool inv[4]; /* whether can[x] is inverse to e[x] */ find_unknowns(state, edge_list, 4, e); - can[0] = edsf_canonify(linedsf, e[0], inv); - can[1] = edsf_canonify(linedsf, e[1], inv+1); - can[2] = edsf_canonify(linedsf, e[2], inv+2); - can[3] = edsf_canonify(linedsf, e[3], inv+3); + can[0] = dsf_canonify_flip(linedsf, e[0], inv); + can[1] = dsf_canonify_flip(linedsf, e[1], inv+1); + can[2] = dsf_canonify_flip(linedsf, e[2], inv+2); + can[3] = dsf_canonify_flip(linedsf, e[3], inv+3); if (can[0] == can[1]) { if (merge_lines(sstate, e[2], e[3], total_parity^inv[0]^inv[1])) diff = min(diff, DIFF_HARD); @@ -2097,7 +2188,7 @@ static int trivial_deductions(solver_state *sstate) /* Per-face deductions */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; if (sstate->face_solved[i]) continue; @@ -2155,22 +2246,22 @@ static int trivial_deductions(solver_state *sstate) int j, k, e1, e2, e, d; for (j = 0; j < f->order; j++) { - e1 = f->edges[j] - g->edges; - e2 = f->edges[j+1 < f->order ? j+1 : 0] - g->edges; + e1 = f->edges[j]->index; + e2 = f->edges[j+1 < f->order ? j+1 : 0]->index; - if (g->edges[e1].dot1 == g->edges[e2].dot1 || - g->edges[e1].dot1 == g->edges[e2].dot2) { - d = g->edges[e1].dot1 - g->dots; + if (g->edges[e1]->dot1 == g->edges[e2]->dot1 || + g->edges[e1]->dot1 == g->edges[e2]->dot2) { + d = g->edges[e1]->dot1->index; } else { - assert(g->edges[e1].dot2 == g->edges[e2].dot1 || - g->edges[e1].dot2 == g->edges[e2].dot2); - d = g->edges[e1].dot2 - g->dots; + assert(g->edges[e1]->dot2 == g->edges[e2]->dot1 || + g->edges[e1]->dot2 == g->edges[e2]->dot2); + d = g->edges[e1]->dot2->index; } if (state->lines[e1] == LINE_UNKNOWN && state->lines[e2] == LINE_UNKNOWN) { - for (k = 0; k < g->dots[d].order; k++) { - int e = g->dots[d].edges[k] - g->edges; + for (k = 0; k < g->dots[d]->order; k++) { + int e = g->dots[d]->edges[k]->index; if (state->lines[e] == LINE_YES) goto found; /* multi-level break */ } @@ -2184,7 +2275,7 @@ static int trivial_deductions(solver_state *sstate) * they're e1 and e2. */ for (j = 0; j < f->order; j++) { - e = f->edges[j] - g->edges; + e = f->edges[j]->index; if (state->lines[e] == LINE_UNKNOWN && e != e1 && e != e2) { bool r = solver_set_line(sstate, e, LINE_YES); assert(r); @@ -2198,7 +2289,7 @@ static int trivial_deductions(solver_state *sstate) /* Per-dot deductions */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int yes, no, unknown; if (sstate->dot_solved[i]) @@ -2290,12 +2381,12 @@ static int dline_deductions(solver_state *sstate) * on that. We check this with an assertion, in case someone decides to * make a grid which has larger faces than this. Note, this algorithm * could get quite expensive if there are many large faces. */ -#define MAX_FACE_SIZE 12 +#define MAX_FACE_SIZE 14 for (i = 0; i < g->num_faces; i++) { int maxs[MAX_FACE_SIZE][MAX_FACE_SIZE]; int mins[MAX_FACE_SIZE][MAX_FACE_SIZE]; - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int N = f->order; int j,m; int clue = state->clues[i]; @@ -2306,7 +2397,7 @@ static int dline_deductions(solver_state *sstate) /* Calculate the (j,j+1) entries */ for (j = 0; j < N; j++) { - int edge_index = f->edges[j] - g->edges; + int edge_index = f->edges[j]->index; int dline_index; enum line_state line1 = state->lines[edge_index]; enum line_state line2; @@ -2317,7 +2408,7 @@ static int dline_deductions(solver_state *sstate) mins[j][k] = (line1 == LINE_YES) ? 1 : 0; /* Calculate the (j,j+2) entries */ dline_index = dline_index_from_face(g, f, k); - edge_index = f->edges[k] - g->edges; + edge_index = f->edges[k]->index; line2 = state->lines[edge_index]; k++; if (k >= N) k = 0; @@ -2362,7 +2453,7 @@ static int dline_deductions(solver_state *sstate) for (j = 0; j < N; j++) { int k; grid_edge *e = f->edges[j]; - int line_index = e - g->edges; + int line_index = e->index; int dline_index; if (state->lines[line_index] != LINE_UNKNOWN) @@ -2397,7 +2488,7 @@ static int dline_deductions(solver_state *sstate) if (sstate->diff >= DIFF_TRICKY) { /* Now see if we can make dline deduction for edges{j,j+1} */ e = f->edges[k]; - if (state->lines[e - g->edges] != LINE_UNKNOWN) + if (state->lines[e->index] != LINE_UNKNOWN) /* Only worth doing this for an UNKNOWN,UNKNOWN pair. * Dlines where one of the edges is known, are handled in the * dot-deductions */ @@ -2429,7 +2520,7 @@ static int dline_deductions(solver_state *sstate) /* ------ Dot deductions ------ */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int N = d->order; int yes, no, unknown; int j; @@ -2447,8 +2538,8 @@ static int dline_deductions(solver_state *sstate) k = j + 1; if (k >= N) k = 0; dline_index = dline_index_from_dot(g, d, j); - line1_index = d->edges[j] - g->edges; - line2_index = d->edges[k] - g->edges; + line1_index = d->edges[j]->index; + line2_index = d->edges[k] ->index; line1 = state->lines[line1_index]; line2 = state->lines[line2_index]; @@ -2545,7 +2636,7 @@ static int dline_deductions(solver_state *sstate) int opp_index; if (opp == j || opp == k) continue; - opp_index = d->edges[opp] - g->edges; + opp_index = d->edges[opp]->index; if (state->lines[opp_index] == LINE_UNKNOWN) { solver_set_line(sstate, opp_index, LINE_YES); @@ -2596,7 +2687,7 @@ static int linedsf_deductions(solver_state *sstate) if (clue < 0) continue; - N = g->faces[i].order; + N = g->faces[i]->order; yes = sstate->face_yes_count[i]; if (yes + 1 == clue) { if (face_setall_identical(sstate, i, LINE_NO)) @@ -2614,14 +2705,14 @@ static int linedsf_deductions(solver_state *sstate) /* Deductions with small number of LINE_UNKNOWNs, based on overall * parity of lines. */ - diff_tmp = parity_deductions(sstate, g->faces[i].edges, + diff_tmp = parity_deductions(sstate, g->faces[i]->edges, (clue - yes) % 2, unknown); diff = min(diff, diff_tmp); } /* ------ Dot deductions ------ */ for (i = 0; i < g->num_dots; i++) { - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int N = d->order; int j; int yes, no, unknown; @@ -2634,17 +2725,17 @@ static int linedsf_deductions(solver_state *sstate) int can1, can2; bool inv1, inv2; int j2; - line1_index = d->edges[j] - g->edges; + line1_index = d->edges[j]->index; if (state->lines[line1_index] != LINE_UNKNOWN) continue; j2 = j + 1; if (j2 == N) j2 = 0; - line2_index = d->edges[j2] - g->edges; + line2_index = d->edges[j2]->index; if (state->lines[line2_index] != LINE_UNKNOWN) continue; /* Infer dline flags from linedsf */ - can1 = edsf_canonify(sstate->linedsf, line1_index, &inv1); - can2 = edsf_canonify(sstate->linedsf, line2_index, &inv2); + can1 = dsf_canonify_flip(sstate->linedsf, line1_index, &inv1); + can2 = dsf_canonify_flip(sstate->linedsf, line2_index, &inv2); if (can1 == can2 && inv1 != inv2) { /* These are opposites, so set dline atmostone/atleastone */ if (set_atmostone(dlines, dline_index)) @@ -2679,7 +2770,7 @@ static int linedsf_deductions(solver_state *sstate) int can; bool inv; enum line_state s; - can = edsf_canonify(sstate->linedsf, i, &inv); + can = dsf_canonify_flip(sstate->linedsf, i, &inv); if (can == i) continue; s = sstate->state->lines[can]; @@ -2704,7 +2795,6 @@ static int loop_deductions(solver_state *sstate) game_state *state = sstate->state; grid *g = state->game_grid; int shortest_chainlen = g->num_dots; - bool loop_found = false; int dots_connected; bool progress = false; int i; @@ -2717,7 +2807,7 @@ static int loop_deductions(solver_state *sstate) */ for (i = 0; i < g->num_edges; i++) { if (state->lines[i] == LINE_YES) { - loop_found |= merge_dots(sstate, i); + merge_dots(sstate, i); edgecount++; } } @@ -2762,9 +2852,9 @@ static int loop_deductions(solver_state *sstate) * loop it would create is a solution. */ for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; - int d1 = e->dot1 - g->dots; - int d2 = e->dot2 - g->dots; + grid_edge *e = g->edges[i]; + int d1 = e->dot1->index; + int d2 = e->dot2->index; int eqclass, val; if (state->lines[i] != LINE_UNKNOWN) continue; @@ -2801,13 +2891,13 @@ static int loop_deductions(solver_state *sstate) */ sm1_nearby = 0; if (e->face1) { - int f = e->face1 - g->faces; + int f = e->face1->index; int c = state->clues[f]; if (c >= 0 && sstate->face_yes_count[f] == c - 1) sm1_nearby++; } if (e->face2) { - int f = e->face2 - g->faces; + int f = e->face2->index; int c = state->clues[f]; if (c >= 0 && sstate->face_yes_count[f] == c - 1) sm1_nearby++; @@ -2958,7 +3048,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char button_char = ' '; enum line_state old_state; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); /* Convert mouse-click (x,y) to grid coordinates */ x -= BORDER(ds->tilesize); @@ -2972,7 +3062,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (e == NULL) return NULL; - i = e - g->edges; + i = e->index; /* I think it's only possible to play this game with mouse clicks, sorry */ /* Maybe will add mouse drag support some time */ @@ -3020,73 +3110,58 @@ static char *interpret_move(const game_state *state, game_ui *ui, movesize = 80; movebuf = snewn(movesize, char); movelen = sprintf(movebuf, "%d%c", i, (int)button_char); - { - static enum { OFF, FIXED, ADAPTIVE, DUNNO } autofollow = DUNNO; - if (autofollow == DUNNO) { - const char *env = getenv("LOOPY_AUTOFOLLOW"); - if (env && !strcmp(env, "off")) - autofollow = OFF; - else if (env && !strcmp(env, "fixed")) - autofollow = FIXED; - else if (env && !strcmp(env, "adaptive")) - autofollow = ADAPTIVE; - else - autofollow = OFF; - } - if (autofollow != OFF) { - int dotid; - for (dotid = 0; dotid < 2; dotid++) { - grid_dot *dot = (dotid == 0 ? e->dot1 : e->dot2); - grid_edge *e_this = e; - - while (1) { - int j, n_found; - grid_edge *e_next = NULL; - - for (j = n_found = 0; j < dot->order; j++) { - grid_edge *e_candidate = dot->edges[j]; - int i_candidate = e_candidate - g->edges; - if (e_candidate != e_this && - (autofollow == FIXED || - state->lines[i] == LINE_NO || - state->lines[i_candidate] != LINE_NO)) { - e_next = e_candidate; - n_found++; - } + if (ui->autofollow != AF_OFF) { + int dotid; + for (dotid = 0; dotid < 2; dotid++) { + grid_dot *dot = (dotid == 0 ? e->dot1 : e->dot2); + grid_edge *e_this = e; + + while (1) { + int j, n_found; + grid_edge *e_next = NULL; + + for (j = n_found = 0; j < dot->order; j++) { + grid_edge *e_candidate = dot->edges[j]; + int i_candidate = e_candidate->index; + if (e_candidate != e_this && + (ui->autofollow == AF_FIXED || + state->lines[i] == LINE_NO || + state->lines[i_candidate] != LINE_NO)) { + e_next = e_candidate; + n_found++; } + } - if (n_found != 1 || - state->lines[e_next - g->edges] != state->lines[i]) - break; - - if (e_next == e) { - /* - * Special case: we might have come all the - * way round a loop and found our way back to - * the same edge we started from. In that - * situation, we must terminate not only this - * while loop, but the 'for' outside it that - * was tracing in both directions from the - * starting edge, because if we let it trace - * in the second direction then we'll only - * find ourself traversing the same loop in - * the other order and generate an encoded - * move string that mentions the same set of - * edges twice. - */ - goto autofollow_done; - } + if (n_found != 1 || + state->lines[e_next->index] != state->lines[i]) + break; + + if (e_next == e) { + /* + * Special case: we might have come all the way + * round a loop and found our way back to the same + * edge we started from. In that situation, we + * must terminate not only this while loop, but + * the 'for' outside it that was tracing in both + * directions from the starting edge, because if + * we let it trace in the second direction then + * we'll only find ourself traversing the same + * loop in the other order and generate an encoded + * move string that mentions the same set of edges + * twice. + */ + goto autofollow_done; + } - dot = (e_next->dot1 != dot ? e_next->dot1 : e_next->dot2); - if (movelen > movesize - 40) { - movesize = movesize * 5 / 4 + 128; - movebuf = sresize(movebuf, movesize, char); - } - e_this = e_next; - movelen += sprintf(movebuf+movelen, "%d%c", - (int)(e_this - g->edges), button_char); + dot = (e_next->dot1 != dot ? e_next->dot1 : e_next->dot2); + if (movelen > movesize - 40) { + movesize = movesize * 5 / 4 + 128; + movebuf = sresize(movebuf, movesize, char); } + e_this = e_next; + movelen += sprintf(movebuf+movelen, "%d%c", + (int)(e_this->index), button_char); } autofollow_done:; } @@ -3159,7 +3234,7 @@ static void grid_to_screen(const game_drawstate *ds, const grid *g, static void face_text_pos(const game_drawstate *ds, const grid *g, grid_face *f, int *xret, int *yret) { - int faceindex = f - g->faces; + int faceindex = f->index; /* * Return the cached position for this face, if we've already @@ -3192,9 +3267,9 @@ static void face_text_bbox(game_drawstate *ds, grid *g, grid_face *f, /* There seems to be a certain amount of trial-and-error involved * in working out the correct bounding-box for the text. */ - *x = xx - ds->tilesize/4 - 1; + *x = xx - ds->tilesize * 5 / 4 - 1; *y = yy - ds->tilesize/4 - 3; - *w = ds->tilesize/2 + 2; + *w = ds->tilesize * 5 / 2 + 2; *h = ds->tilesize/2 + 5; } @@ -3202,7 +3277,7 @@ static void game_redraw_clue(drawing *dr, game_drawstate *ds, const game_state *state, int i) { grid *g = state->game_grid; - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int x, y; char c[20]; @@ -3228,10 +3303,10 @@ static void edge_bbox(game_drawstate *ds, grid *g, grid_edge *e, grid_to_screen(ds, g, x1, y1, &x1, &y1); grid_to_screen(ds, g, x2, y2, &x2, &y2); /* Allow extra margin for dots, and thickness of lines */ - xmin = min(x1, x2) - 2; - xmax = max(x1, x2) + 2; - ymin = min(y1, y2) - 2; - ymax = max(y1, y2) + 2; + xmin = min(x1, x2) - (ds->tilesize + 15) / 16; + xmax = max(x1, x2) + (ds->tilesize + 15) / 16; + ymin = min(y1, y2) - (ds->tilesize + 15) / 16; + ymax = max(y1, y2) + (ds->tilesize + 15) / 16; *x = xmin; *y = ymin; @@ -3243,13 +3318,19 @@ static void dot_bbox(game_drawstate *ds, grid *g, grid_dot *d, int *x, int *y, int *w, int *h) { int x1, y1; + int xmin, xmax, ymin, ymax; grid_to_screen(ds, g, d->x, d->y, &x1, &y1); - *x = x1 - 2; - *y = y1 - 2; - *w = 5; - *h = 5; + xmin = x1 - (ds->tilesize * 5 + 63) / 64; + xmax = x1 + (ds->tilesize * 5 + 63) / 64; + ymin = y1 - (ds->tilesize * 5 + 63) / 64; + ymax = y1 + (ds->tilesize * 5 + 63) / 64; + + *x = xmin; + *y = ymin; + *w = xmax - xmin + 1; + *h = ymax - ymin + 1; } static const int loopy_line_redraw_phases[] = { @@ -3257,11 +3338,11 @@ static const int loopy_line_redraw_phases[] = { }; #define NPHASES lenof(loopy_line_redraw_phases) -static void game_redraw_line(drawing *dr, game_drawstate *ds, +static void game_redraw_line(drawing *dr, game_drawstate *ds,const game_ui *ui, const game_state *state, int i, int phase) { grid *g = state->game_grid; - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; int x1, x2, y1, y2; int line_colour; @@ -3283,16 +3364,13 @@ static void game_redraw_line(drawing *dr, game_drawstate *ds, grid_to_screen(ds, g, e->dot2->x, e->dot2->y, &x2, &y2); if (line_colour == COL_FAINT) { - static int draw_faint_lines = -1; - if (draw_faint_lines < 0) { - char *env = getenv("LOOPY_FAINT_LINES"); - draw_faint_lines = (!env || (env[0] == 'y' || - env[0] == 'Y')); - } - if (draw_faint_lines) - draw_line(dr, x1, y1, x2, y2, line_colour); + if (ui->draw_faint_lines) + draw_thick_line(dr, ds->tilesize/24.0, + x1 + 0.5, y1 + 0.5, + x2 + 0.5, y2 + 0.5, + line_colour); } else { - draw_thick_line(dr, 3.0, + draw_thick_line(dr, ds->tilesize*3/32.0, x1 + 0.5, y1 + 0.5, x2 + 0.5, y2 + 0.5, line_colour); @@ -3303,11 +3381,11 @@ static void game_redraw_dot(drawing *dr, game_drawstate *ds, const game_state *state, int i) { grid *g = state->game_grid; - grid_dot *d = g->dots + i; + grid_dot *d = g->dots[i]; int x, y; grid_to_screen(ds, g, d->x, d->y, &x, &y); - draw_circle(dr, x, y, 2, COL_FOREGROUND, COL_FOREGROUND); + draw_circle(dr, x, y, ds->tilesize*2.5/32.0, COL_FOREGROUND, COL_FOREGROUND); } static bool boxes_intersect(int x0, int y0, int w0, int h0, @@ -3322,7 +3400,7 @@ static bool boxes_intersect(int x0, int y0, int w0, int h0, } static void game_redraw_in_rect(drawing *dr, game_drawstate *ds, - const game_state *state, + const game_ui *ui, const game_state *state, int x, int y, int w, int h) { grid *g = state->game_grid; @@ -3334,20 +3412,20 @@ static void game_redraw_in_rect(drawing *dr, game_drawstate *ds, for (i = 0; i < g->num_faces; i++) { if (state->clues[i] >= 0) { - face_text_bbox(ds, g, &g->faces[i], &bx, &by, &bw, &bh); + face_text_bbox(ds, g, g->faces[i], &bx, &by, &bw, &bh); if (boxes_intersect(x, y, w, h, bx, by, bw, bh)) game_redraw_clue(dr, ds, state, i); } } for (phase = 0; phase < NPHASES; phase++) { for (i = 0; i < g->num_edges; i++) { - edge_bbox(ds, g, &g->edges[i], &bx, &by, &bw, &bh); + edge_bbox(ds, g, g->edges[i], &bx, &by, &bw, &bh); if (boxes_intersect(x, y, w, h, bx, by, bw, bh)) - game_redraw_line(dr, ds, state, i, phase); + game_redraw_line(dr, ds, ui, state, i, phase); } } for (i = 0; i < g->num_dots; i++) { - dot_bbox(ds, g, &g->dots[i], &bx, &by, &bw, &bh); + dot_bbox(ds, g, g->dots[i], &bx, &by, &bw, &bh); if (boxes_intersect(x, y, w, h, bx, by, bw, bh)) game_redraw_dot(dr, ds, state, i); } @@ -3407,7 +3485,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, /* First, trundle through the faces. */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int sides = f->order; int yes_order, no_order; bool clue_mistake; @@ -3500,26 +3578,26 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int w = grid_width * ds->tilesize / g->tilesize; int h = grid_height * ds->tilesize / g->tilesize; - game_redraw_in_rect(dr, ds, state, + game_redraw_in_rect(dr, ds, ui, state, 0, 0, w + 2*border + 1, h + 2*border + 1); } else { /* Right. Now we roll up our sleeves. */ for (i = 0; i < nfaces; i++) { - grid_face *f = g->faces + faces[i]; + grid_face *f = g->faces[faces[i]]; int x, y, w, h; face_text_bbox(ds, g, f, &x, &y, &w, &h); - game_redraw_in_rect(dr, ds, state, x, y, w, h); + game_redraw_in_rect(dr, ds, ui, state, x, y, w, h); } for (i = 0; i < nedges; i++) { - grid_edge *e = g->edges + edges[i]; + grid_edge *e = g->edges[edges[i]]; int x, y, w, h; edge_bbox(ds, g, e, &x, &y, &w, &h); - game_redraw_in_rect(dr, ds, state, x, y, w, h); + game_redraw_in_rect(dr, ds, ui, state, x, y, w, h); } } @@ -3550,19 +3628,21 @@ static int game_status(const game_state *state) return state->solved ? +1 : 0; } -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 7mm "squares" by default. */ - game_compute_size(params, 700, &pw, &ph); + game_compute_size(params, 700, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int ink = print_mono_colour(dr, 0); int i; @@ -3577,7 +3657,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) for (i = 0; i < g->num_dots; i++) { int x, y; - grid_to_screen(ds, g, g->dots[i].x, g->dots[i].y, &x, &y); + grid_to_screen(ds, g, g->dots[i]->x, g->dots[i]->y, &x, &y); draw_circle(dr, x, y, ds->tilesize / 15, ink, ink); } @@ -3585,7 +3665,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) * Clues. */ for (i = 0; i < g->num_faces; i++) { - grid_face *f = g->faces + i; + grid_face *f = g->faces[i]; int clue = state->clues[i]; if (clue >= 0) { char c[20]; @@ -3603,7 +3683,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) */ for (i = 0; i < g->num_edges; i++) { int thickness = (state->lines[i] == LINE_YES) ? 30 : 150; - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; int x1, y1, x2, y2; grid_to_screen(ds, g, e->dot1->x, e->dot1->y, &x1, &y1); grid_to_screen(ds, g, e->dot2->x, e->dot2->y, &x2, &y2); @@ -3666,14 +3746,16 @@ const struct game thegame = { new_game, dup_game, free_game, - 1, solve_game, + true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3687,7 +3769,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false /* wants_statusbar */, - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* mouse_priorities */ }; diff --git a/apps/plugins/puzzles/src/magnets.R b/apps/plugins/puzzles/src/magnets.R deleted file mode 100644 index e55e4746ee..0000000000 --- a/apps/plugins/puzzles/src/magnets.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MAGNETS_EXTRA = laydomino - -magnets : [X] GTK COMMON magnets MAGNETS_EXTRA magnets-icon|no-icon - -magnets : [G] WINDOWS COMMON magnets MAGNETS_EXTRA magnets.res|noicon.res - -magnetssolver : [U] magnets[STANDALONE_SOLVER] MAGNETS_EXTRA STANDALONE m.lib -magnetssolver : [C] magnets[STANDALONE_SOLVER] MAGNETS_EXTRA STANDALONE - -ALL += magnets[COMBINED] MAGNETS_EXTRA - -!begin am gtk -GAMES += magnets -!end - -!begin >list.c - A(magnets) \ -!end - -!begin >gamedesc.txt -magnets:magnets.exe:Magnets:Magnet-placing puzzle:Place magnets to satisfy the clues and avoid like poles touching. -!end diff --git a/apps/plugins/puzzles/src/magnets.c b/apps/plugins/puzzles/src/magnets.c index edbb8490ad..7cb5fbc919 100644 --- a/apps/plugins/puzzles/src/magnets.c +++ b/apps/plugins/puzzles/src/magnets.c @@ -36,12 +36,17 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #ifdef STANDALONE_SOLVER -bool verbose = 0; +static bool verbose = false; #endif enum { @@ -230,8 +235,17 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { - if (params->w < 2) return "Width must be at least one"; - if (params->h < 2) return "Height must be at least one"; + if (params->w < 2) return "Width must be at least two"; + if (params->h < 2) return "Height must be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; + if (params->diff >= DIFF_TRICKY) { + if (params->w < 5 && params->h < 5) + return "Either width or height must be at least five for Tricky"; + } else { + if (params->w < 3 && params->h < 3) + return "Either width or height must be at least three"; + } if (params->diff < 0 || params->diff >= DIFFCOUNT) return "Unknown difficulty level"; @@ -510,7 +524,9 @@ nextchar: * (i.e. each end points to the other) */ for (idx = 0; idx < state->wh; idx++) { if (state->common->dominoes[idx] < 0 || - state->common->dominoes[idx] > state->wh || + state->common->dominoes[idx] >= state->wh || + (state->common->dominoes[idx] % state->w != idx % state->w && + state->common->dominoes[idx] / state->w != idx / state->w) || state->common->dominoes[state->common->dominoes[idx]] != idx) { *prob = "Domino descriptions inconsistent"; goto done; @@ -541,7 +557,7 @@ static const char *validate_desc(const game_params *params, const char *desc) { const char *prob; game_state *st = new_game_int(params, desc, &prob); - if (!st) return (char*)prob; + if (!st) return prob; free_game(st); return NULL; } @@ -1574,6 +1590,7 @@ static int lay_dominoes(game_state *state, random_state *rs, int *scratch) } debug(("Laid %d dominoes, total %d dominoes.\n", nlaid, state->wh/2)); + (void)nlaid; game_debug(state, "Final layout"); return ret; } @@ -1720,7 +1737,7 @@ static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -1729,15 +1746,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -1745,6 +1753,36 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cur_visible = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int idx; + + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) return ""; + idx = ui->cur_y * state->w + ui->cur_x; + if (button == CURSOR_SELECT) { + if (state->grid[idx] == NEUTRAL && state->flags[idx] & GS_SET) + return ""; + switch (state->grid[idx]) { + case EMPTY: return "+"; + case POSITIVE: return "-"; + case NEGATIVE: return "Clear"; + } + } + if (button == CURSOR_SELECT2) { + if (state->grid[idx] != NEUTRAL) return ""; + if (state->flags[idx] & GS_SET) /* neutral */ + return "?"; + if (state->flags[idx] & GS_NOTNEUTRAL) /* !neutral */ + return "Clear"; + else + return "X"; + } + } + return ""; +} + struct game_drawstate { int tilesize; bool started, solved; @@ -1805,14 +1843,13 @@ static char *interpret_move(const game_state *state, game_ui *ui, char *nullret = NULL, buf[80], movech; enum { CYCLE_MAGNET, CYCLE_NEUTRAL } action; - if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false); - ui->cur_visible = true; - return UI_UPDATE; - } else if (IS_CURSOR_SELECT(button)) { + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, + false, &ui->cur_visible); + else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } action = (button == CURSOR_SELECT) ? CYCLE_MAGNET : CYCLE_NEUTRAL; gx = ui->cur_x; @@ -1821,7 +1858,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, (button == LEFT_BUTTON || button == RIGHT_BUTTON)) { if (ui->cur_visible) { ui->cur_visible = false; - nullret = UI_UPDATE; + nullret = MOVE_UI_UPDATE; } action = (button == LEFT_BUTTON) ? CYCLE_MAGNET : CYCLE_NEUTRAL; } else if (button == LEFT_BUTTON && is_clue(state, gx, gy)) { @@ -1928,7 +1965,7 @@ badmove: */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2205,12 +2242,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, flash = (int)(flashtime * 5 / FLASH_TIME) % 2; if (!ds->started) { - /* draw background, corner +-. */ - draw_rect(dr, 0, 0, - TILE_SIZE * (w+2) + 2 * BORDER, - TILE_SIZE * (h+2) + 2 * BORDER, - COL_BACKGROUND); - + /* draw corner +-. */ draw_sym(dr, ds, -1, -1, POSITIVE, COL_TEXT); draw_sym(dr, ds, state->w, state->h, NEGATIVE, COL_TEXT); @@ -2309,24 +2341,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->w, h = state->h; int ink = print_mono_colour(dr, 0); @@ -2430,12 +2459,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2449,7 +2480,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; @@ -2458,14 +2489,14 @@ const struct game thegame = { #include #include -const char *quis = NULL; -bool csv = false; +static const char *quis = NULL; +static bool csv = false; -void usage(FILE *out) { +static void usage(FILE *out) { fprintf(out, "usage: %s [-v] [--print] |\n", quis); } -void doprint(game_state *state) +static void doprint(game_state *state) { char *fmt = game_text_format(state); printf("%s", fmt); @@ -2559,7 +2590,7 @@ static void start_soak(game_params *p, random_state *rs) sfree(aux); } -int main(int argc, const char *argv[]) +int main(int argc, char *argv[]) { bool print = false, soak = false, solved = false; int ret; @@ -2608,7 +2639,7 @@ int main(int argc, const char *argv[]) decode_params(p, id); err = validate_params(p, true); if (err) { - fprintf(stderr, "%s: %s", argv[0], err); + fprintf(stderr, "%s: %s\n", argv[0], err); goto done; } diff --git a/apps/plugins/puzzles/src/malloc.c b/apps/plugins/puzzles/src/malloc.c index a7fa7c5adc..39bcfac25b 100644 --- a/apps/plugins/puzzles/src/malloc.c +++ b/apps/plugins/puzzles/src/malloc.c @@ -2,16 +2,23 @@ * malloc.c: safe wrappers around malloc, realloc, free, strdup */ +#ifndef NO_STDINT_H +#include +#endif #include #include #include "puzzles.h" /* - * smalloc should guarantee to return a useful pointer - Halibut + * smalloc should guarantee to return a useful pointer - we * can do nothing except die when it's out of memory anyway. */ void *smalloc(size_t size) { void *p; +#ifdef PTRDIFF_MAX + if (size > PTRDIFF_MAX) + fatal("allocation too large"); +#endif p = malloc(size); if (!p) fatal("out of memory"); @@ -32,6 +39,10 @@ void sfree(void *p) { */ void *srealloc(void *p, size_t size) { void *q; +#ifdef PTRDIFF_MAX + if (size > PTRDIFF_MAX) + fatal("allocation too large"); +#endif if (p) { q = realloc(p, size); } else { diff --git a/apps/plugins/puzzles/src/map.R b/apps/plugins/puzzles/src/map.R deleted file mode 100644 index 1e702aa19d..0000000000 --- a/apps/plugins/puzzles/src/map.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MAP_EXTRA = dsf - -map : [X] GTK COMMON map MAP_EXTRA map-icon|no-icon - -map : [G] WINDOWS COMMON map MAP_EXTRA map.res|noicon.res - -mapsolver : [U] map[STANDALONE_SOLVER] MAP_EXTRA STANDALONE m.lib -mapsolver : [C] map[STANDALONE_SOLVER] MAP_EXTRA STANDALONE - -ALL += map[COMBINED] MAP_EXTRA - -!begin am gtk -GAMES += map -!end - -!begin >list.c - A(map) \ -!end - -!begin >gamedesc.txt -map:map.exe:Map:Map-colouring puzzle:Colour the map so that adjacent regions are never the same colour. -!end diff --git a/apps/plugins/puzzles/src/map.c b/apps/plugins/puzzles/src/map.c index 9df2d22b52..9cea0d4647 100644 --- a/apps/plugins/puzzles/src/map.c +++ b/apps/plugins/puzzles/src/map.c @@ -14,7 +14,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -25,7 +30,7 @@ */ #if defined STANDALONE_SOLVER #define SOLVER_DIAGNOSTICS -bool verbose = false; +static bool verbose = false; #elif defined SOLVER_DIAGNOSTICS #define verbose true #endif @@ -40,12 +45,6 @@ bool verbose = false; #define FIVE (FOUR+1) #define SIX (FOUR+2) -/* - * Ghastly run-time configuration option, just for Gareth (again). - */ -static int flash_type = -1; -static float flash_length; - /* * Difficulty levels. I do some macro ickery here to ensure that my * enum and the various forms of my name list always match up. @@ -180,7 +179,9 @@ static void decode_params(game_params *params, char const *string) params->n = atoi(p); while (*p && (*p == '.' || isdigit((unsigned char)*p))) p++; } else { - params->n = params->w * params->h / 8; + if (params->h > 0 && params->w > 0 && + params->w <= INT_MAX / params->h) + params->n = params->w * params->h / 8; } if (*p == 'd') { int i; @@ -252,6 +253,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 2 || params->h < 2) return "Width and height must be at least two"; + if (params->w > INT_MAX / 2 / params->h) + return "Width times height must not be unreasonably large"; if (params->n < 5) return "Must have at least five regions"; if (params->n > params->w * params->h) @@ -1659,6 +1662,10 @@ static char *new_game_desc(const game_params *params, random_state *rs, } } + if (retlen + 10 >= retsize) { + retsize = retlen + 256; + ret = sresize(ret, retsize, char); + } ret[retlen++] = 'a'-1 + run; ret[retlen++] = ','; @@ -1711,8 +1718,8 @@ static const char *parse_edge_list(const game_params *params, int i, k, pos; bool state; const char *p = *desc; - - dsf_init(map+wh, wh); + const char *err = NULL; + DSF *dsf = dsf_new(wh); pos = -1; state = false; @@ -1723,8 +1730,10 @@ static const char *parse_edge_list(const game_params *params, * pairs of squares whenever the edge list shows a non-edge). */ while (*p && *p != ',') { - if (*p < 'a' || *p > 'z') - return "Unexpected character in edge list"; + if (*p < 'a' || *p > 'z') { + err = "Unexpected character in edge list"; + goto out; + } if (*p == 'z') k = 25; else @@ -1747,10 +1756,12 @@ static const char *parse_edge_list(const game_params *params, y = (pos - w*(h-1)) % h; dx = 1; dy = 0; - } else - return "Too much data in edge list"; + } else { + err = "Too much data in edge list"; + goto out; + } if (!state) - dsf_merge(map+wh, y*w+x, (y+dy)*w+(x+dx)); + dsf_merge(dsf, y*w+x, (y+dy)*w+(x+dx)); pos++; } @@ -1759,8 +1770,10 @@ static const char *parse_edge_list(const game_params *params, p++; } assert(pos <= 2*wh-w-h); - if (pos < 2*wh-w-h) - return "Too little data in edge list"; + if (pos < 2*wh-w-h) { + err = "Too little data in edge list"; + goto out; + } /* * Now go through again and allocate region numbers. @@ -1769,17 +1782,22 @@ static const char *parse_edge_list(const game_params *params, for (i = 0; i < wh; i++) map[i] = -1; for (i = 0; i < wh; i++) { - k = dsf_canonify(map+wh, i); + k = dsf_canonify(dsf, i); if (map[k] < 0) map[k] = pos++; map[i] = map[k]; } - if (pos != n) - return "Edge list defines the wrong number of regions"; + if (pos != n) { + err = "Edge list defines the wrong number of regions"; + goto out; + } *desc = p; + err = NULL; /* no error */ - return NULL; + out: + dsf_free(dsf); + return err; } static const char *validate_desc(const game_params *params, const char *desc) @@ -1789,7 +1807,7 @@ static const char *validate_desc(const game_params *params, const char *desc) int *map; const char *ret; - map = snewn(2*wh, int); + map = snewn(wh, int); ret = parse_edge_list(params, &desc, map); sfree(map); if (ret) @@ -2252,16 +2270,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return dupstr(aux); } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - struct game_ui { /* * drag_colour: @@ -2275,11 +2283,41 @@ struct game_ui { int drag_pencil; int dragx, dragy; bool show_numbers; + bool large_stipples; int cur_x, cur_y, cur_lastmove; bool cur_visible, cur_moved; + + /* + * User preference to enable alternative versions of the + * completion flash. Some users have found the colour-cycling + * default version to be a bit eye-twisting. + */ + enum { + FLASH_CYCLIC, /* cycle the four colours of the map */ + FLASH_EACH_TO_WHITE, /* turn each colour white in turn */ + FLASH_ALL_TO_WHITE /* flash the whole map to white in one go */ + } flash_type; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int flash_type = -1; + + if (!initialised) { + char *env; + + initialised = true; + + if ((env = getenv("MAP_ALTERNATIVE_FLASH")) != NULL) + flash_type = FLASH_EACH_TO_WHITE; + } + + if (flash_type != -1) + ui_out->flash_type = flash_type; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); @@ -2288,24 +2326,55 @@ static game_ui *new_ui(const game_state *state) ui->drag_pencil = 0; ui->show_numbers = false; ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->cur_moved = false; ui->cur_lastmove = 0; + ui->flash_type = FLASH_CYCLIC; + legacy_prefs_override(ui); return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(4, config_item); + + ret[0].name = "Victory flash effect"; + ret[0].kw = "flash-type"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = ":Cyclic:Each to white:All to white"; + ret[0].u.choices.choicekws = ":cyclic:each-white:all-white"; + ret[0].u.choices.selected = ui->flash_type; + + ret[1].name = "Number regions"; + ret[1].kw = "show-numbers"; + ret[1].type = C_BOOLEAN; + ret[1].u.boolean.bval = ui->show_numbers; + + ret[2].name = "Display style for stipple marks"; + ret[2].kw = "stipple-style"; + ret[2].type = C_CHOICES; + ret[2].u.choices.choicenames = ":Small:Large"; + ret[2].u.choices.choicekws = ":small:large"; + ret[2].u.choices.selected = ui->large_stipples; + + ret[3].name = NULL; + ret[3].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->flash_type = cfg[0].u.choices.selected; + ui->show_numbers = cfg[1].u.boolean.bval; + ui->large_stipples = cfg[2].u.choices.selected; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -2388,6 +2457,26 @@ static int region_from_ui_cursor(const game_state *state, const game_ui *ui) EPSILON_Y(ui->cur_lastmove)); } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int r; + + if (IS_CURSOR_SELECT(button) && ui->cur_visible) { + if (ui->drag_colour == -2) return "Pick"; + r = region_from_ui_cursor(state, ui); + if (state->map->immutable[r]) return "Cancel"; + if (!ui->cur_moved) return ui->drag_pencil ? "Cancel" : "Clear"; + if (button == CURSOR_SELECT2) { + if (state->colouring[r] >= 0) return "Cancel"; + if (ui->drag_colour >= 0) return "Stipple"; + } + if (ui->drag_pencil) return "Stipple"; + return ui->drag_colour >= 0 ? "Fill" : "Clear"; + } + return ""; +} + static char *interpret_move(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) @@ -2401,21 +2490,21 @@ static char *interpret_move(const game_state *state, game_ui *ui, */ if (button == 'l' || button == 'L') { ui->show_numbers = !ui->show_numbers; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_MOVE(button)) { move_cursor(button, &ui->cur_x, &ui->cur_y, state->p.w, state->p.h, - false); + false, NULL); ui->cur_visible = true; ui->cur_moved = true; ui->cur_lastmove = button; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->drag_colour == -2) { /* not currently cursor-dragging, start. */ int r = region_from_ui_cursor(state, ui); @@ -2427,7 +2516,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->drag_pencil = 0; } ui->cur_moved = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { /* currently cursor-dragging; drop the colour in the new region. */ alt_button = (button == CURSOR_SELECT2); /* Double-select removes current colour. */ @@ -2452,14 +2541,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->dragx = x; ui->dragy = y; ui->cur_visible = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if ((button == LEFT_DRAG || button == RIGHT_DRAG) && ui->drag_colour > -2) { ui->dragx = x; ui->dragy = y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if ((button == LEFT_RELEASE || button == RIGHT_RELEASE) && @@ -2484,18 +2573,18 @@ drag_dropped: ui->drag_colour = -2; if (r < 0) - return UI_UPDATE; /* drag into border; do nothing else */ + return MOVE_UI_UPDATE; /* drag into border; do nothing else */ if (state->map->immutable[r]) - return UI_UPDATE; /* can't change this region */ + return MOVE_UI_UPDATE; /* can't change this region */ if (state->colouring[r] == c && state->pencil[r] == p) - return UI_UPDATE; /* don't _need_ to change this region */ + return MOVE_UI_UPDATE; /* don't _need_ to change this region */ if (alt_button) { if (state->colouring[r] >= 0) { /* Can't pencil on a coloured region */ - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (c >= 0) { /* Right-dragging from colour to blank toggles one pencil */ p = state->pencil[r] ^ (1 << c); @@ -2605,7 +2694,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2729,7 +2818,7 @@ static void draw_error(drawing *dr, game_drawstate *ds, int x, int y) static void draw_square(drawing *dr, game_drawstate *ds, const game_params *params, struct map *map, - int x, int y, unsigned long v) + int x, int y, unsigned long v, bool large_stipples) { int w = params->w, h = params->h, wh = w*h; int tv, bv, xo, yo, i, j, oldj; @@ -2802,7 +2891,8 @@ static void draw_square(drawing *dr, game_drawstate *ds, draw_circle(dr, COORD(x) + (xo+1)*TILESIZE/5, COORD(y) + (yo+1)*TILESIZE/5, - TILESIZE/4, COL_0 + c, COL_0 + c); + large_stipples ? TILESIZE/4 : TILESIZE/7, + COL_0 + c, COL_0 + c); } /* @@ -2857,6 +2947,11 @@ static void draw_square(drawing *dr, game_drawstate *ds, draw_update(dr, COORD(x), COORD(y), TILESIZE, TILESIZE); } +static float flash_length(const game_ui *ui) +{ + return (ui->flash_type == FLASH_EACH_TO_WHITE ? 0.50F : 0.30F); +} + static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldstate, const game_state *state, int dir, const game_ui *ui, @@ -2872,29 +2967,18 @@ static void game_redraw(drawing *dr, game_drawstate *ds, ds->drag_visible = false; } - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all games - * should start by drawing a big background-colour rectangle - * covering the whole window. - */ if (!ds->started) { - int ww, wh; - - game_compute_size(&state->p, TILESIZE, &ww, &wh); - draw_rect(dr, 0, 0, ww, wh, COL_BACKGROUND); draw_rect(dr, COORD(0), COORD(0), w*TILESIZE+1, h*TILESIZE+1, COL_GRID); - - draw_update(dr, 0, 0, ww, wh); + draw_update(dr, COORD(0), COORD(0), w*TILESIZE+1, h*TILESIZE+1); ds->started = true; } if (flashtime) { - if (flash_type == 1) - flash = (int)(flashtime * FOUR / flash_length); + if (ui->flash_type == FLASH_EACH_TO_WHITE) + flash = (int)(flashtime * FOUR / flash_length(ui)); else - flash = 1 + (int)(flashtime * THREE / flash_length); + flash = 1 + (int)(flashtime * THREE / flash_length(ui)); } else flash = -1; @@ -2913,12 +2997,12 @@ static void game_redraw(drawing *dr, game_drawstate *ds, bv = FOUR; if (flash >= 0) { - if (flash_type == 1) { + if (ui->flash_type == FLASH_EACH_TO_WHITE) { if (tv == flash) tv = FOUR; if (bv == flash) bv = FOUR; - } else if (flash_type == 2) { + } else if (ui->flash_type == FLASH_ALL_TO_WHITE) { if (flash % 2) tv = bv = FOUR; } else { @@ -2990,7 +3074,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, for (x = 0; x < w; x++) { unsigned long v = ds->todraw[y*w+x]; if (ds->drawn[y*w+x] != v) { - draw_square(dr, ds, &state->p, state->map, x, y, v); + draw_square(dr, ds, &state->p, state->map, x, y, v, ui->large_stipples); ds->drawn[y*w+x] = v; } } @@ -3048,15 +3132,7 @@ static float game_flash_length(const game_state *oldstate, { if (!oldstate->completed && newstate->completed && !oldstate->cheated && !newstate->cheated) { - if (flash_type < 0) { - char *env = getenv("MAP_ALTERNATIVE_FLASH"); - if (env) - flash_type = atoi(env); - else - flash_type = 0; - flash_length = (flash_type == 1 ? 0.50F : 0.30F); - } - return flash_length; + return flash_length(ui); } else return 0.0F; } @@ -3079,12 +3155,8 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; @@ -3093,12 +3165,13 @@ static void game_print_size(const game_params *params, float *x, float *y) * compute this size is to compute the pixel puzzle size at a * given tile size and then scale. */ - game_compute_size(params, 400, &pw, &ph); + game_compute_size(params, 400, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->p.w, h = state->p.h, wh = w*h, n = state->p.n; int ink, c[FOUR], i; @@ -3257,13 +3330,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, 20, game_compute_size, game_set_size, @@ -3277,7 +3352,7 @@ const struct game thegame = { game_status, true, true, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/matching.c b/apps/plugins/puzzles/src/matching.c index 9078f6c36a..aabdae0846 100644 --- a/apps/plugins/puzzles/src/matching.c +++ b/apps/plugins/puzzles/src/matching.c @@ -319,35 +319,7 @@ int matching(int nl, int nr, int **adjlists, int *adjsizes, return ret; } -#ifdef STANDALONE_MATCHING_TEST - -/* - * Diagnostic routine used in testing this algorithm. It is passed a - * pointer to a piece of scratch space that's just been used by - * matching_with_scratch, and extracts from it a labelling of the - * input graph that acts as a 'witness' to the maximality of the - * returned matching. - * - * The output parameter 'witness' should be an array of (nl+nr) - * integers, indexed such that witness[L] corresponds to an L-vertex (for - * L=0,1,...,nl-1) and witness[nl+R] corresponds to an R-vertex (for - * R=0,1,...,nr-1). On return, this array will assign each vertex a - * label which is either 0 or 1, and the following properties will - * hold: - * - * + all vertices not paired up by the matching are type L0 or R1 - * + every L0->R1 edge is used by the matching - * + no L1->R0 edge is used by the matching. - * - * The mere existence of such a labelling is enough to prove the - * maximality of the matching, because if there is any larger matching - * then its symmetric difference with this one must include at least - * one 'augmenting path', which starts at a free L-vertex and ends at - * a free R-vertex, traversing only unused L->R edges and only used - * R->L edges. But that would mean it starts at an L0, ends at an R1, - * and never follows an edge that can get from an 0 to a 1. - */ -static void matching_witness(void *scratchv, int nl, int nr, int *witness) +void matching_witness(void *scratchv, int nl, int nr, int *witness) { struct scratch *s = (struct scratch *)scratchv; int i, j; @@ -357,397 +329,3 @@ static void matching_witness(void *scratchv, int nl, int nr, int *witness) for (j = 0; j < nr; j++) witness[nl + j] = s->Rlayer[j] == -1; } - -/* - * Standalone tool to run the matching algorithm. - */ - -#include -#include -#include - -#include "tree234.h" - -int nl, nr, count; -int **adjlists, *adjsizes; -int *adjdata, *outl, *outr, *witness; -void *scratch; -random_state *rs; - -void allocate(int nl_, int nr_, int maxedges) -{ - nl = nl_; - nr = nr_; - adjdata = snewn(maxedges, int); - adjlists = snewn(nl, int *); - adjsizes = snewn(nl, int); - outl = snewn(nl, int); - outr = snewn(nr, int); - witness = snewn(nl+nr, int); - scratch = smalloc(matching_scratch_size(nl, nr)); -} - -void deallocate(void) -{ - sfree(adjlists); - sfree(adjsizes); - sfree(adjdata); - sfree(outl); - sfree(outr); - sfree(witness); - sfree(scratch); -} - -void find_and_check_matching(void) -{ - int i, j, k; - - count = matching_with_scratch(scratch, nl, nr, adjlists, adjsizes, - rs, outl, outr); - matching_witness(scratch, nl, nr, witness); - - for (i = j = 0; i < nl; i++) { - if (outl[i] != -1) { - assert(0 <= outl[i] && outl[i] < nr); - assert(outr[outl[i]] == i); - j++; - - for (k = 0; k < adjsizes[i]; k++) - if (adjlists[i][k] == outl[i]) - break; - assert(k < adjsizes[i]); - } - } - assert(j == count); - - for (i = j = 0; i < nr; i++) { - if (outr[i] != -1) { - assert(0 <= outr[i] && outr[i] < nl); - assert(outl[outr[i]] == i); - j++; - } - } - assert(j == count); - - for (i = 0; i < nl; i++) { - if (outl[i] == -1) - assert(witness[i] == 0); - } - for (i = 0; i < nr; i++) { - if (outr[i] == -1) - assert(witness[nl+i] == 1); - } - for (i = 0; i < nl; i++) { - for (j = 0; j < adjsizes[i]; j++) { - k = adjlists[i][j]; - - if (outl[i] == k) - assert(!(witness[i] == 1 && witness[nl+k] == 0)); - else - assert(!(witness[i] == 0 && witness[nl+k] == 1)); - } - } -} - -struct nodename { - const char *name; - int index; -}; - -int compare_nodes(void *av, void *bv) -{ - const struct nodename *a = (const struct nodename *)av; - const struct nodename *b = (const struct nodename *)bv; - return strcmp(a->name, b->name); -} - -int node_index(tree234 *n2i, tree234 *i2n, const char *name) -{ - struct nodename *nn, *nn_prev; - char *namedup = dupstr(name); - - nn = snew(struct nodename); - nn->name = namedup; - nn->index = count234(n2i); - - nn_prev = add234(n2i, nn); - if (nn_prev != nn) { - sfree(nn); - sfree(namedup); - } else { - addpos234(i2n, nn, nn->index); - } - - return nn_prev->index; -} - -struct edge { - int L, R; -}; - -int compare_edges(void *av, void *bv) -{ - const struct edge *a = (const struct edge *)av; - const struct edge *b = (const struct edge *)bv; - if (a->L < b->L) return -1; - if (a->L > b->L) return +1; - if (a->R < b->R) return -1; - if (a->R > b->R) return +1; - return 0; -} - -void matching_from_user_input(FILE *fp, const char *filename) -{ - tree234 *Ln2i, *Li2n, *Rn2i, *Ri2n, *edges; - char *line = NULL; - struct edge *e; - int i, lineno = 0; - int *adjptr; - - Ln2i = newtree234(compare_nodes); - Rn2i = newtree234(compare_nodes); - Li2n = newtree234(NULL); - Ri2n = newtree234(NULL); - edges = newtree234(compare_edges); - - while (sfree(line), lineno++, (line = fgetline(fp)) != NULL) { - char *p, *Lname, *Rname; - - p = line; - while (*p && isspace((unsigned char)*p)) p++; - if (!*p) - continue; - - Lname = p; - while (*p && !isspace((unsigned char)*p)) p++; - if (*p) - *p++ = '\0'; - while (*p && isspace((unsigned char)*p)) p++; - - if (!*p) { - fprintf(stderr, "%s:%d: expected 2 words, found 1\n", - filename, lineno); - exit(1); - } - - Rname = p; - while (*p && !isspace((unsigned char)*p)) p++; - if (*p) - *p++ = '\0'; - while (*p && isspace((unsigned char)*p)) p++; - - if (*p) { - fprintf(stderr, "%s:%d: expected 2 words, found more\n", - filename, lineno); - exit(1); - } - - e = snew(struct edge); - e->L = node_index(Ln2i, Li2n, Lname); - e->R = node_index(Rn2i, Ri2n, Rname); - if (add234(edges, e) != e) { - fprintf(stderr, "%s:%d: duplicate edge\n", - filename, lineno); - exit(1); - } - } - - allocate(count234(Ln2i), count234(Rn2i), count234(edges)); - - adjptr = adjdata; - for (i = 0; i < nl; i++) - adjlists[i] = NULL; - for (i = 0; (e = index234(edges, i)) != NULL; i++) { - if (!adjlists[e->L]) - adjlists[e->L] = adjptr; - *adjptr++ = e->R; - adjsizes[e->L] = adjptr - adjlists[e->L]; - } - - find_and_check_matching(); - - for (i = 0; i < nl; i++) { - if (outl[i] != -1) { - struct nodename *Lnn = index234(Li2n, i); - struct nodename *Rnn = index234(Ri2n, outl[i]); - printf("%s %s\n", Lnn->name, Rnn->name); - } - } -} - -void test_subsets(void) -{ - int b = 8; - int n = 1 << b; - int i, j, nruns, expected_size; - int *adjptr; - int *edgecounts; - struct stats { - int min, max; - double n, sx, sxx; - } *stats; - static const char seed[] = "fixed random seed for repeatability"; - - /* - * Generate a graph in which every subset of [b] = {1,...,b} - * (represented as a b-bit integer 0 <= i < n) has an edge going - * to every subset obtained by removing exactly one element. - * - * This graph is the disjoint union of the corresponding graph for - * each layer (collection of same-sized subset) of the power set - * of [b]. Each of those graphs has a matching of size equal to - * the smaller of its vertex sets. So we expect the overall size - * of the output matching to be less than n by the size of the - * largest layer, that is, to be n - binomial(n, floor(n/2)). - * - * We run the generation repeatedly, randomising it every time, - * and we expect to see every possible edge appear sooner or - * later. - */ - - rs = random_new(seed, strlen(seed)); - - allocate(n, n, n*b); - adjptr = adjdata; - expected_size = 0; - for (i = 0; i < n; i++) { - adjlists[i] = adjptr; - for (j = 0; j < b; j++) { - if (i & (1 << j)) - *adjptr++ = i & ~(1 << j); - } - adjsizes[i] = adjptr - adjlists[i]; - if (adjsizes[i] != b/2) - expected_size++; - } - - edgecounts = snewn(n*b, int); - for (i = 0; i < n*b; i++) - edgecounts[i] = 0; - - stats = snewn(b, struct stats); - - nruns = 0; - while (nruns < 10000) { - nruns++; - find_and_check_matching(); - assert(count == expected_size); - - for (i = 0; i < n; i++) - for (j = 0; j < b; j++) - if ((i ^ outl[i]) == (1 << j)) - edgecounts[b*i+j]++; - - if (nruns % 1000 == 0) { - for (i = 0; i < b; i++) { - struct stats *st = &stats[i]; - st->min = st->max = -1; - st->n = st->sx = st->sxx = 0; - } - - for (i = 0; i < n; i++) { - int pop = 0; - for (j = 0; j < b; j++) - if (i & (1 << j)) - pop++; - pop--; - - for (j = 0; j < b; j++) { - if (i & (1 << j)) { - struct stats *st = &stats[pop]; - int x = edgecounts[b*i+j]; - if (st->max == -1 || st->max < x) - st->max = x; - if (st->min == -1 || st->min > x) - st->min = x; - st->n++; - st->sx += x; - st->sxx += (double)x*x; - } else { - assert(edgecounts[b*i+j] == 0); - } - } - } - } - } - - printf("after %d runs:\n", nruns); - for (j = 0; j < b; j++) { - struct stats *st = &stats[j]; - printf("edges between layers %d,%d:" - " min=%d max=%d mean=%f variance=%f\n", - j, j+1, st->min, st->max, st->sx/st->n, - (st->sxx - st->sx*st->sx/st->n) / st->n); - } -} - -int main(int argc, char **argv) -{ - static const char stdin_identifier[] = ""; - const char *infile = NULL; - bool doing_opts = true; - enum { USER_INPUT, AUTOTEST } mode = USER_INPUT; - - while (--argc > 0) { - const char *arg = *++argv; - - if (doing_opts && arg[0] == '-' && arg[1]) { - if (!strcmp(arg, "--")) { - doing_opts = false; - } else if (!strcmp(arg, "--random")) { - char buf[64]; - int len = sprintf(buf, "%lu", (unsigned long)time(NULL)); - rs = random_new(buf, len); - } else if (!strcmp(arg, "--autotest")) { - mode = AUTOTEST; - } else { - fprintf(stderr, "matching: unrecognised option '%s'\n", arg); - return 1; - } - } else { - if (!infile) { - infile = (!strcmp(arg, "-") ? stdin_identifier : arg); - } else { - fprintf(stderr, "matching: too many arguments\n"); - return 1; - } - } - } - - if (mode == USER_INPUT) { - FILE *fp; - - if (!infile) - infile = stdin_identifier; - - if (infile != stdin_identifier) { - fp = fopen(infile, "r"); - if (!fp) { - fprintf(stderr, "matching: could not open input file '%s'\n", - infile); - return 1; - } - } else { - fp = stdin; - } - - matching_from_user_input(fp, infile); - - if (infile != stdin_identifier) - fclose(fp); - } - - if (mode == AUTOTEST) { - if (infile) { - fprintf(stderr, "matching: expected no filename argument " - "with --autotest\n"); - return 1; - } - - test_subsets(); - } - - return 0; -} - -#endif /* STANDALONE_MATCHING_TEST */ diff --git a/apps/plugins/puzzles/src/matching.h b/apps/plugins/puzzles/src/matching.h index a4d3098efa..dbf424d044 100644 --- a/apps/plugins/puzzles/src/matching.h +++ b/apps/plugins/puzzles/src/matching.h @@ -77,4 +77,32 @@ size_t matching_scratch_size(int nl, int nr); int matching(int nl, int nr, int **adjlists, int *adjsizes, random_state *rs, int *outl, int *outr); +/* + * Diagnostic routine used in testing this algorithm. It is passed a + * pointer to a piece of scratch space that's just been used by + * matching_with_scratch, and extracts from it a labelling of the + * input graph that acts as a 'witness' to the maximality of the + * returned matching. + * + * The output parameter 'witness' should be an array of (nl+nr) + * integers, indexed such that witness[L] corresponds to an L-vertex (for + * L=0,1,...,nl-1) and witness[nl+R] corresponds to an R-vertex (for + * R=0,1,...,nr-1). On return, this array will assign each vertex a + * label which is either 0 or 1, and the following properties will + * hold: + * + * + all vertices not paired up by the matching are type L0 or R1 + * + every L0->R1 edge is used by the matching + * + no L1->R0 edge is used by the matching. + * + * The mere existence of such a labelling is enough to prove the + * maximality of the matching, because if there is any larger matching + * then its symmetric difference with this one must include at least + * one 'augmenting path', which starts at a free L-vertex and ends at + * a free R-vertex, traversing only unused L->R edges and only used + * R->L edges. But that would mean it starts at an L0, ends at an R1, + * and never follows an edge that can get from an 0 to a 1. + */ +void matching_witness(void *scratch, int nl, int nr, int *witness); + #endif /* MATCHING_MATCHING_H */ diff --git a/apps/plugins/puzzles/src/midend.c b/apps/plugins/puzzles/src/midend.c index f2d27d3e31..30fdf1b830 100644 --- a/apps/plugins/puzzles/src/midend.c +++ b/apps/plugins/puzzles/src/midend.c @@ -30,6 +30,11 @@ struct midend_serialise_buf { int len, size; }; +struct midend_serialise_buf_read_ctx { + struct midend_serialise_buf *ser; + int len, pos; +}; + struct midend { frontend *frontend; random_state *random; @@ -73,6 +78,7 @@ struct midend { game_params *params, *curparams; game_drawstate *drawstate; + bool first_draw; game_ui *ui; game_state *oldstate; @@ -88,10 +94,15 @@ struct midend { int pressed_mouse_button; - int preferred_tilesize, tilesize, winwidth, winheight; + struct midend_serialise_buf be_prefs; + + int preferred_tilesize, preferred_tilesize_dpr, tilesize; + int winwidth, winheight; void (*game_id_change_notify_function)(void *); void *game_id_change_notify_ctx; + + bool one_key_shortcuts; }; #define ensure(me) do { \ @@ -119,21 +130,33 @@ struct deserialise_data { }; /* - * Forward reference. + * Forward references. */ static const char *midend_deserialise_internal( midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx, const char *(*check)(void *ctx, midend *, const struct deserialise_data *), void *cctx); +static void midend_serialise_prefs( + midend *me, game_ui *ui, + void (*write)(void *ctx, const void *buf, int len), void *wctx); +static const char *midend_deserialise_prefs( + midend *me, game_ui *ui, + bool (*read)(void *ctx, void *buf, int len), void *rctx); +static config_item *midend_get_prefs(midend *me, game_ui *ui); +static void midend_set_prefs(midend *me, game_ui *ui, config_item *all_prefs); +static void midend_apply_prefs(midend *me, game_ui *ui); void midend_reset_tilesize(midend *me) { me->preferred_tilesize = me->ourgame->preferred_tilesize; + me->preferred_tilesize_dpr = 1.0; { /* * Allow an environment-based override for the default tile * size by defining a variable along the lines of * `NET_TILESIZE=15'. + * + * XXX How should this interact with DPR? */ char buf[80], *e; @@ -196,6 +219,7 @@ midend *midend_new(frontend *fe, const game *ourgame, me->aux_info = NULL; me->genmode = GOT_NOTHING; me->drawstate = NULL; + me->first_draw = true; me->oldstate = NULL; me->preset_menu = NULL; me->anim_time = me->anim_pos = 0.0F; @@ -212,6 +236,11 @@ midend *midend_new(frontend *fe, const game *ourgame, else me->drawing = NULL; + me->be_prefs.buf = NULL; + me->be_prefs.size = me->be_prefs.len = 0; + + me->one_key_shortcuts = true; + midend_reset_tilesize(me); sfree(randseed); @@ -280,6 +309,7 @@ void midend_free(midend *me) sfree(me->privdesc); sfree(me->seedstr); sfree(me->aux_info); + sfree(me->be_prefs.buf); me->ourgame->free_params(me->params); midend_free_preset_menu(me, me->preset_menu); if (me->ui) @@ -297,14 +327,56 @@ static void midend_size_new_drawstate(midend *me) * anyway yet. */ if (me->tilesize > 0) { - me->ourgame->compute_size(me->params, me->tilesize, + me->ourgame->compute_size(me->params, me->tilesize, me->ui, &me->winwidth, &me->winheight); me->ourgame->set_size(me->drawing, me->drawstate, me->params, me->tilesize); } } -void midend_size(midend *me, int *x, int *y, bool user_size) +/* + * There is no one correct way to convert tilesizes between device + * pixel ratios, because there's only a loosely-defined relationship + * between tilesize and the actual size of a puzzle. We define this + * function as the canonical conversion function so everything in the + * midend will be consistent. + */ +static int convert_tilesize(midend *me, int old_tilesize, + double old_dpr, double new_dpr) +{ + int x, y, rx, ry, min, max; + game_params *defaults; + + if (new_dpr == old_dpr) + return old_tilesize; + + defaults = me->ourgame->default_params(); + + me->ourgame->compute_size(defaults, old_tilesize, me->ui, &x, &y); + x *= new_dpr / old_dpr; + y *= new_dpr / old_dpr; + + min = max = 1; + do { + max *= 2; + me->ourgame->compute_size(defaults, max, me->ui, &rx, &ry); + } while (rx <= x && ry <= y); + + while (max - min > 1) { + int mid = (max + min) / 2; + me->ourgame->compute_size(defaults, mid, me->ui, &rx, &ry); + if (rx <= x && ry <= y) + min = mid; + else + max = mid; + } + + me->ourgame->free_params(defaults); + return min; +} + +void midend_size(midend *me, int *x, int *y, bool user_size, + double device_pixel_ratio) { int min, max; int rx, ry; @@ -318,6 +390,7 @@ void midend_size(midend *me, int *x, int *y, bool user_size) me->ourgame->free_drawstate(me->drawing, me->drawstate); me->drawstate = me->ourgame->new_drawstate(me->drawing, me->states[0].state); + me->first_draw = true; } /* @@ -333,10 +406,12 @@ void midend_size(midend *me, int *x, int *y, bool user_size) max = 1; do { max *= 2; - me->ourgame->compute_size(me->params, max, &rx, &ry); + me->ourgame->compute_size(me->params, max, me->ui, &rx, &ry); } while (rx <= *x && ry <= *y); } else - max = me->preferred_tilesize + 1; + max = convert_tilesize(me, me->preferred_tilesize, + me->preferred_tilesize_dpr, + device_pixel_ratio) + 1; min = 1; /* @@ -347,7 +422,7 @@ void midend_size(midend *me, int *x, int *y, bool user_size) */ while (max - min > 1) { int mid = (max + min) / 2; - me->ourgame->compute_size(me->params, mid, &rx, &ry); + me->ourgame->compute_size(me->params, mid, me->ui, &rx, &ry); if (rx <= *x && ry <= *y) min = mid; else @@ -359,9 +434,11 @@ void midend_size(midend *me, int *x, int *y, bool user_size) */ me->tilesize = min; - if (user_size) + if (user_size) { /* If the user requested a change in size, make it permanent. */ me->preferred_tilesize = me->tilesize; + me->preferred_tilesize_dpr = device_pixel_ratio; + } midend_size_new_drawstate(me); *x = me->winwidth; *y = me->winheight; @@ -380,6 +457,28 @@ game_params *midend_get_params(midend *me) return me->ourgame->dup_params(me->params); } +static char *encode_params(midend *me, const game_params *params, bool full) +{ + char *encoded = me->ourgame->encode_params(params, full); + int i; + + /* Assert that the params consist of printable ASCII containing + * neither '#' nor ':'. */ + for (i = 0; encoded[i]; i++) + assert(encoded[i] >= 32 && encoded[i] < 127 && + encoded[i] != '#' && encoded[i] != ':'); + return encoded; +} + +static void assert_printable_ascii(char const *s) +{ + /* Assert that s is entirely printable ASCII, and hence safe for + * writing in a save file. */ + int i; + for (i = 0; s[i]; i++) + assert(s[i] >= 32 && s[i] < 127); +} + static void midend_set_timer(midend *me) { me->timing = (me->ourgame->is_timed && @@ -397,11 +496,12 @@ void midend_force_redraw(midend *me) me->ourgame->free_drawstate(me->drawing, me->drawstate); me->drawstate = me->ourgame->new_drawstate(me->drawing, me->states[0].state); + me->first_draw = true; midend_size_new_drawstate(me); midend_redraw(me); } -static void newgame_serialise_write(void *ctx, const void *buf, int len) +static void midend_serialise_buf_write(void *ctx, const void *buf, int len) { struct midend_serialise_buf *ser = (struct midend_serialise_buf *)ctx; int new_len; @@ -416,6 +516,18 @@ static void newgame_serialise_write(void *ctx, const void *buf, int len) ser->len = new_len; } +static bool midend_serialise_buf_read(void *ctx, void *buf, int len) +{ + struct midend_serialise_buf_read_ctx *const rctx = ctx; + + if (len > rctx->len - rctx->pos) + return false; + + memcpy(buf, rctx->ser->buf + rctx->pos, len); + rctx->pos += len; + return true; +} + void midend_new_game(midend *me) { me->newgame_undo.len = 0; @@ -435,7 +547,7 @@ void midend_new_game(midend *me) * worse, valid but wrong. */ midend_purge_states(me); - midend_serialise(me, newgame_serialise_write, &me->newgame_undo); + midend_serialise(me, midend_serialise_buf_write, &me->newgame_undo); } midend_stop_anim(me); @@ -487,6 +599,7 @@ void midend_new_game(midend *me) */ me->desc = me->ourgame->new_desc(me->curparams, rs, &me->aux_info, (me->drawing != NULL)); + assert_printable_ascii(me->desc); me->privdesc = NULL; random_free(rs); } @@ -536,6 +649,7 @@ void midend_new_game(midend *me) me->statepos = 1; me->drawstate = me->ourgame->new_drawstate(me->drawing, me->states[0].state); + me->first_draw = true; midend_size_new_drawstate(me); me->elapsed = 0.0F; me->flash_pos = me->flash_time = 0.0F; @@ -543,6 +657,7 @@ void midend_new_game(midend *me) if (me->ui) me->ourgame->free_ui(me->ui); me->ui = me->ourgame->new_ui(me->states[0].state); + midend_apply_prefs(me, me->ui); midend_set_timer(me); me->pressed_mouse_button = 0; @@ -552,31 +667,28 @@ void midend_new_game(midend *me) me->newgame_can_store_undo = true; } -bool midend_can_undo(midend *me) +const char *midend_load_prefs( + midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx) { - return (me->statepos > 1 || me->newgame_undo.len); + const char *err = midend_deserialise_prefs(me, NULL, read, rctx); + return err; } -bool midend_can_redo(midend *me) +void midend_save_prefs(midend *me, + void (*write)(void *ctx, const void *buf, int len), + void *wctx) { - return (me->statepos < me->nstates || me->newgame_redo.len); + midend_serialise_prefs(me, NULL, write, wctx); } -struct newgame_undo_deserialise_read_ctx { - struct midend_serialise_buf *ser; - int len, pos; -}; - -static bool newgame_undo_deserialise_read(void *ctx, void *buf, int len) +bool midend_can_undo(midend *me) { - struct newgame_undo_deserialise_read_ctx *const rctx = ctx; - - if (len > rctx->len - rctx->pos) - return false; + return (me->statepos > 1 || me->newgame_undo.len); +} - memcpy(buf, rctx->ser->buf + rctx->pos, len); - rctx->pos += len; - return true; +bool midend_can_redo(midend *me) +{ + return (me->statepos < me->nstates || me->newgame_redo.len); } struct newgame_undo_deserialise_check_ctx { @@ -613,8 +725,8 @@ static const char *newgame_undo_deserialise_check( * We check both params and cparams, to be as safe as possible. */ - old = me->ourgame->encode_params(me->params, true); - new = me->ourgame->encode_params(data->params, true); + old = encode_params(me, me->params, true); + new = encode_params(me, data->params, true); if (strcmp(old, new)) { /* Set a flag to distinguish this deserialise failure * from one due to faulty decoding */ @@ -622,8 +734,8 @@ static const char *newgame_undo_deserialise_check( return "Undoing this new-game operation would change params"; } - old = me->ourgame->encode_params(me->curparams, true); - new = me->ourgame->encode_params(data->cparams, true); + old = encode_params(me, me->curparams, true); + new = encode_params(me, data->cparams, true); if (strcmp(old, new)) { ctx->refused = true; return "Undoing this new-game operation would change params"; @@ -648,7 +760,7 @@ static bool midend_undo(midend *me) me->dir = -1; return true; } else if (me->newgame_undo.len) { - struct newgame_undo_deserialise_read_ctx rctx; + struct midend_serialise_buf_read_ctx rctx; struct newgame_undo_deserialise_check_ctx cctx; struct midend_serialise_buf serbuf; @@ -659,14 +771,14 @@ static bool midend_undo(midend *me) */ serbuf.buf = NULL; serbuf.len = serbuf.size = 0; - midend_serialise(me, newgame_serialise_write, &serbuf); + midend_serialise(me, midend_serialise_buf_write, &serbuf); rctx.ser = &me->newgame_undo; rctx.len = me->newgame_undo.len; /* copy for reentrancy safety */ rctx.pos = 0; cctx.refused = false; deserialise_error = midend_deserialise_internal( - me, newgame_undo_deserialise_read, &rctx, + me, midend_serialise_buf_read, &rctx, newgame_undo_deserialise_check, &cctx); if (cctx.refused) { /* @@ -699,7 +811,8 @@ static bool midend_undo(midend *me) * the midend so that we can redo back into it later. */ me->newgame_redo.len = 0; - newgame_serialise_write(&me->newgame_redo, serbuf.buf, serbuf.len); + midend_serialise_buf_write(&me->newgame_redo, + serbuf.buf, serbuf.len); sfree(serbuf.buf); return true; @@ -721,7 +834,7 @@ static bool midend_redo(midend *me) me->dir = +1; return true; } else if (me->newgame_redo.len) { - struct newgame_undo_deserialise_read_ctx rctx; + struct midend_serialise_buf_read_ctx rctx; struct newgame_undo_deserialise_check_ctx cctx; struct midend_serialise_buf serbuf; @@ -732,14 +845,14 @@ static bool midend_redo(midend *me) */ serbuf.buf = NULL; serbuf.len = serbuf.size = 0; - midend_serialise(me, newgame_serialise_write, &serbuf); + midend_serialise(me, midend_serialise_buf_write, &serbuf); rctx.ser = &me->newgame_redo; rctx.len = me->newgame_redo.len; /* copy for reentrancy safety */ rctx.pos = 0; cctx.refused = false; deserialise_error = midend_deserialise_internal( - me, newgame_undo_deserialise_read, &rctx, + me, midend_serialise_buf_read, &rctx, newgame_undo_deserialise_check, &cctx); if (cctx.refused) { /* @@ -772,7 +885,8 @@ static bool midend_redo(midend *me) * the midend so that we can undo back into it later. */ me->newgame_undo.len = 0; - newgame_serialise_write(&me->newgame_undo, serbuf.buf, serbuf.len); + midend_serialise_buf_write(&me->newgame_undo, + serbuf.buf, serbuf.len); sfree(serbuf.buf); return true; @@ -859,12 +973,13 @@ void midend_restart_game(midend *me) midend_set_timer(me); } -static bool midend_really_process_key(midend *me, int x, int y, int button) +static int midend_really_process_key(midend *me, int x, int y, int button) { game_state *oldstate = me->ourgame->dup_game(me->states[me->statepos - 1].state); int type = MOVE; - bool gottype = false, ret = true; + bool gottype = false; + int ret = PKR_NO_EFFECT; float anim_time; game_state *s; char *movestr = NULL; @@ -875,40 +990,51 @@ static bool midend_really_process_key(midend *me, int x, int y, int button) me->ui, me->drawstate, x, y, button); } - if (!movestr) { - if (button == 'n' || button == 'N' || button == '\x0E' || - button == UI_NEWGAME) { + if (movestr == NULL || movestr == MOVE_UNUSED) { + if ((me->one_key_shortcuts && (button == 'n' || button == 'N')) || + button == '\x0E' || button == UI_NEWGAME) { midend_new_game(me); midend_redraw(me); + ret = PKR_SOME_EFFECT; goto done; /* never animate */ - } else if (button == 'u' || button == 'U' || - button == '\x1A' || button == '\x1F' || + } else if ((me->one_key_shortcuts && (button=='u' || button=='U')) || + button == '*' || button == '\x1A' || button == '\x1F' || button == UI_UNDO) { midend_stop_anim(me); type = me->states[me->statepos-1].movetype; gottype = true; if (!midend_undo(me)) goto done; - } else if (button == 'r' || button == 'R' || - button == '\x12' || button == '\x19' || + ret = PKR_SOME_EFFECT; + } else if ((me->one_key_shortcuts && (button=='r' || button=='R')) || + button == '#' || button == '\x12' || button == '\x19' || button == UI_REDO) { midend_stop_anim(me); if (!midend_redo(me)) goto done; + ret = PKR_SOME_EFFECT; } else if ((button == '\x13' || button == UI_SOLVE) && me->ourgame->can_solve) { + ret = PKR_SOME_EFFECT; if (midend_solve(me)) goto done; - } else if (button == 'q' || button == 'Q' || button == '\x11' || - button == UI_QUIT) { - ret = false; + } else if ((me->one_key_shortcuts && (button=='q' || button=='Q')) || + button == '\x11' || button == UI_QUIT) { + ret = PKR_QUIT; goto done; - } else + } else { + ret = PKR_UNUSED; goto done; + } + } else if (movestr == MOVE_NO_EFFECT) { + ret = PKR_NO_EFFECT; + goto done; } else { - if (movestr == UI_UPDATE) + ret = PKR_SOME_EFFECT; + if (movestr == MOVE_UI_UPDATE) s = me->states[me->statepos-1].state; else { + assert_printable_ascii(movestr); s = me->ourgame->execute_move(me->states[me->statepos-1].state, movestr); assert(s != NULL); @@ -975,9 +1101,9 @@ static bool midend_really_process_key(midend *me, int x, int y, int button) return ret; } -bool midend_process_key(midend *me, int x, int y, int button) +int midend_process_key(midend *me, int x, int y, int button) { - bool ret = true; + int ret = PKR_UNUSED, ret2; /* * Harmonise mouse drag and release messages. @@ -1052,6 +1178,10 @@ bool midend_process_key(midend *me, int x, int y, int button) * of '\n' etc for keyboard-based cursors. The choice of buttons * here could eventually be controlled by a runtime configuration * option. + * + * We also handle converting MOD_CTRL|'a' etc into '\x01' etc, + * specially recognising Ctrl+Shift+Z, and stripping modifier + * flags off keys that aren't meant to have them. */ if (IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) { if (me->pressed_mouse_button) { @@ -1076,11 +1206,34 @@ bool midend_process_key(midend *me, int x, int y, int button) /* * Fabricate a button-up for the previously pressed button. */ - ret = ret && midend_really_process_key + ret2 = midend_really_process_key (me, x, y, (me->pressed_mouse_button + (LEFT_RELEASE - LEFT_BUTTON))); - } - + ret = min(ret, ret2); + } + + /* Canonicalise CTRL+ASCII. */ + if ((button & MOD_CTRL) && + STRIP_BUTTON_MODIFIERS(button) >= 0x40 && + STRIP_BUTTON_MODIFIERS(button) < 0x80) + button = button & (0x1f | (MOD_MASK & ~MOD_CTRL)); + /* Special handling to make CTRL+SHFT+Z into REDO. */ + if ((button & (~MOD_MASK | MOD_SHFT)) == (MOD_SHFT | '\x1A')) + button = UI_REDO; + /* interpret_move() expects CTRL and SHFT only on cursor keys, and + * TAB (added as of 7/2024 to support Untangle). */ + if (!IS_CURSOR_MOVE(STRIP_BUTTON_MODIFIERS(button))) { + /* reject CTRL+anything odd */ + if ((button & MOD_CTRL) && STRIP_BUTTON_MODIFIERS(button) >= 0x20) + return PKR_UNUSED; + /* otherwise strip them, except for tab */ + if (STRIP_BUTTON_MODIFIERS(button) != '\t') + button &= ~(MOD_CTRL | MOD_SHFT); + } + /* interpret_move() expects NUM_KEYPAD only on numbers. */ + if (STRIP_BUTTON_MODIFIERS(button) < '0' || + STRIP_BUTTON_MODIFIERS(button) > '9') + button &= ~MOD_NUM_KEYPAD; /* * Translate keyboard presses to cursor selection. */ @@ -1101,7 +1254,8 @@ bool midend_process_key(midend *me, int x, int y, int button) /* * Now send on the event we originally received. */ - ret = ret && midend_really_process_key(me, x, y, button); + ret2 = midend_really_process_key(me, x, y, button); + ret = min(ret, ret2); /* * And update the currently pressed button. @@ -1121,7 +1275,7 @@ key_label *midend_request_keys(midend *me, int *n) if(me->ourgame->request_keys) { - keys = me->ourgame->request_keys(midend_get_params(me), &nkeys); + keys = me->ourgame->request_keys(me->params, &nkeys); for(i = 0; i < nkeys; ++i) { if(!keys[i].label) @@ -1135,12 +1289,38 @@ key_label *midend_request_keys(midend *me, int *n) return keys; } +/* Return a good label to show next to a key right now. */ +const char *midend_current_key_label(midend *me, int button) +{ + assert(IS_CURSOR_SELECT(button)); + if (!me->ourgame->current_key_label) return ""; + return me->ourgame->current_key_label( + me->ui, me->states[me->statepos-1].state, button); +} + void midend_redraw(midend *me) { assert(me->drawing); if (me->statepos > 0 && me->drawstate) { + bool first_draw = me->first_draw; + me->first_draw = false; + start_draw(me->drawing); + + if (first_draw) { + /* + * The initial contents of the window are not guaranteed + * by the front end. But we also don't want to require + * every single game to go to the effort of clearing the + * window on setup. So we centralise here the operation of + * covering the whole window with colour 0 (assumed to be + * the puzzle's background colour) the first time we do a + * redraw operation with a new drawstate. + */ + draw_rect(me->drawing, 0, 0, me->winwidth, me->winheight, 0); + } + if (me->oldstate && me->anim_time > 0 && me->anim_pos < me->anim_time) { assert(me->dir != 0); @@ -1152,6 +1332,15 @@ void midend_redraw(midend *me) me->states[me->statepos-1].state, +1 /*shrug*/, me->ui, 0.0, me->flash_pos); } + + if (first_draw) { + /* + * Call a big draw_update on the whole window, in case the + * game backend didn't. + */ + draw_update(me->drawing, 0, 0, me->winwidth, me->winheight); + } + end_draw(me->drawing); } } @@ -1201,6 +1390,7 @@ float *midend_colours(midend *me, int *ncolours) float *ret; ret = me->ourgame->colours(me->frontend, ncolours); + assert(*ncolours >= 1); { int i; @@ -1227,6 +1417,9 @@ float *midend_colours(midend *me, int *ncolours) ret[i*3 + 1] = g / 255.0F; ret[i*3 + 2] = b / 255.0F; } + assert(0.0F <= ret[i*3 + 0] && ret[i*3 + 0] <= 1.0F); + assert(0.0F <= ret[i*3 + 1] && ret[i*3 + 1] <= 1.0F); + assert(0.0F <= ret[i*3 + 2] && ret[i*3 + 2] <= 1.0F); } } @@ -1359,7 +1552,7 @@ static void preset_menu_encode_params(midend *me, struct preset_menu *menu) for (i = 0; i < menu->n_entries; i++) { if (menu->entries[i].params) { me->encoded_presets[menu->entries[i].id] = - me->ourgame->encode_params(menu->entries[i].params, true); + encode_params(me, menu->entries[i].params, true); } else { preset_menu_encode_params(me, menu->entries[i].submenu); } @@ -1438,7 +1631,7 @@ struct preset_menu *midend_get_presets(midend *me, int *id_limit) int midend_which_preset(midend *me) { - char *encoding = me->ourgame->encode_params(me->params, true); + char *encoding = encode_params(me, me->params, true); int i, ret; ret = -1; @@ -1496,6 +1689,10 @@ bool midend_get_cursor_location(midend *me, void midend_supersede_game_desc(midend *me, const char *desc, const char *privdesc) { + /* Assert that the descriptions consists only of printable ASCII. */ + assert_printable_ascii(desc); + if (privdesc) + assert_printable_ascii(privdesc); sfree(me->desc); sfree(me->privdesc); me->desc = dupstr(desc); @@ -1545,7 +1742,7 @@ config_item *midend_get_config(midend *me, int which, char **wintitle) * the former is likely to persist across many code * changes). */ - parstr = me->ourgame->encode_params(me->curparams, which == CFG_SEED); + parstr = encode_params(me, me->curparams, which == CFG_SEED); assert(parstr); if (which == CFG_DESC) { rest = me->desc ? me->desc : ""; @@ -1562,6 +1759,10 @@ config_item *midend_get_config(midend *me, int which, char **wintitle) ret[1].name = NULL; return ret; + case CFG_PREFS: + sprintf(titlebuf, "%s preferences", me->ourgame->name); + *wintitle = titlebuf; + return midend_get_prefs(me, NULL); } assert(!"We shouldn't be here"); @@ -1670,6 +1871,7 @@ static const char *midend_game_id_int(midend *me, const char *id, int defmode) newcurparams = me->ourgame->default_params(); } me->ourgame->decode_params(newcurparams, par); + sfree(par); error = me->ourgame->validate_params(newcurparams, desc == NULL); if (error) { me->ourgame->free_params(newcurparams); @@ -1689,7 +1891,7 @@ static const char *midend_game_id_int(midend *me, const char *id, int defmode) newparams = me->ourgame->dup_params(me->params); - tmpstr = me->ourgame->encode_params(newcurparams, false); + tmpstr = encode_params(me, newcurparams, false); me->ourgame->decode_params(newparams, tmpstr); sfree(tmpstr); @@ -1745,8 +1947,6 @@ static const char *midend_game_id_int(midend *me, const char *id, int defmode) me->genmode = GOT_SEED; } - sfree(par); - me->newgame_can_store_undo = false; return NULL; @@ -1761,7 +1961,7 @@ char *midend_get_game_id(midend *me) { char *parstr, *ret; - parstr = me->ourgame->encode_params(me->curparams, false); + parstr = encode_params(me, me->curparams, false); assert(parstr); assert(me->desc); ret = snewn(strlen(parstr) + strlen(me->desc) + 2, char); @@ -1777,7 +1977,7 @@ char *midend_get_random_seed(midend *me) if (!me->seedstr) return NULL; - parstr = me->ourgame->encode_params(me->curparams, true); + parstr = encode_params(me, me->curparams, true); assert(parstr); ret = snewn(strlen(parstr) + strlen(me->seedstr) + 2, char); sprintf(ret, "%s#%s", parstr, me->seedstr); @@ -1811,6 +2011,10 @@ const char *midend_set_config(midend *me, int which, config_item *cfg) if (error) return error; break; + + case CFG_PREFS: + midend_set_prefs(me, me->ui, cfg); + break; } return NULL; @@ -1849,12 +2053,13 @@ const char *midend_solve(midend *me) movestr = me->ourgame->solve(me->states[0].state, me->states[me->statepos-1].state, me->aux_info, &msg); - assert(movestr != UI_UPDATE); + assert(movestr != MOVE_UI_UPDATE); if (!movestr) { if (!msg) msg = "Solve operation failed"; /* _shouldn't_ happen, but can */ return msg; } + assert_printable_ascii(movestr); s = me->ourgame->execute_move(me->states[me->statepos-1].state, movestr); assert(s); @@ -1961,7 +2166,9 @@ void midend_serialise(midend *me, char lbuf[9]; \ copy_left_justified(lbuf, sizeof(lbuf), h); \ sprintf(hbuf, "%s:%d:", lbuf, (int)strlen(str)); \ + assert_printable_ascii(hbuf); \ write(wctx, hbuf, strlen(hbuf)); \ + assert_printable_ascii(str); \ write(wctx, str, strlen(str)); \ write(wctx, "\n", 1); \ } while (0) @@ -1986,7 +2193,7 @@ void midend_serialise(midend *me, * The current long-term parameters structure, in full. */ if (me->params) { - char *s = me->ourgame->encode_params(me->params, true); + char *s = encode_params(me, me->params, true); wr("PARAMS", s); sfree(s); } @@ -1995,7 +2202,7 @@ void midend_serialise(midend *me, * The current short-term parameters structure, in full. */ if (me->curparams) { - char *s = me->ourgame->encode_params(me->curparams, true); + char *s = encode_params(me, me->curparams, true); wr("CPARAMS", s); sfree(s); } @@ -2003,8 +2210,27 @@ void midend_serialise(midend *me, /* * The current game description, the privdesc, and the random seed. */ - if (me->seedstr) - wr("SEED", me->seedstr); + if (me->seedstr) { + /* + * Random seeds are not necessarily printable ASCII. + * Hex-encode the seed if necessary. Printable ASCII seeds + * are emitted unencoded for compatibility with older + * versions. + */ + int i; + + for (i = 0; me->seedstr[i]; i++) + if (me->seedstr[i] < 32 || me->seedstr[i] >= 127) + break; + if (me->seedstr[i]) { + char *hexseed = bin2hex((unsigned char *)me->seedstr, + strlen(me->seedstr)); + + wr("HEXSEED", hexseed); + sfree(hexseed); + } else + wr("SEED", me->seedstr); + } if (me->desc) wr("DESC", me->desc); if (me->privdesc) @@ -2036,7 +2262,7 @@ void midend_serialise(midend *me, /* * Any required serialisation of the game_ui. */ - if (me->ui) { + if (me->ui && me->ourgame->encode_ui) { char *s = me->ourgame->encode_ui(me->ui); if (s) { wr("UI", s); @@ -2049,7 +2275,7 @@ void midend_serialise(midend *me, */ if (me->ourgame->is_timed) { char buf[80]; - ftoa(buf, me->elapsed); + sprintf(buf, "%g", me->elapsed); wr("TIME", buf); } @@ -2060,6 +2286,7 @@ void midend_serialise(midend *me, char buf[80]; sprintf(buf, "%d", me->nstates); wr("NSTATES", buf); + assert(me->statepos >= 1 && me->statepos <= me->nstates); sprintf(buf, "%d", me->statepos); wr("STATEPOS", buf); } @@ -2159,7 +2386,7 @@ static const char *midend_deserialise_internal( if (c == ':') { break; - } else if (c >= '0' && c <= '9') { + } else if (c >= '0' && c <= '9' && len < (INT_MAX - 10) / 10) { len = (len * 10) + (c - '0'); } else { if (started) @@ -2171,10 +2398,17 @@ static const char *midend_deserialise_internal( val = snewn(len+1, char); if (!read(rctx, val, len)) { - if (started) + /* unexpected EOF */ goto cleanup; } val[len] = '\0'; + /* Validate that all values (apart from SEED) are printable ASCII. */ + if (strcmp(key, "SEED")) + for (i = 0; val[i]; i++) + if (val[i] < 32 || val[i] >= 127) { + ret = "Forbidden characters in saved game file"; + goto cleanup; + } if (!started) { if (strcmp(key, "SAVEFILE") || strcmp(val, SERIALISE_MAGIC)) { @@ -2204,6 +2438,15 @@ static const char *midend_deserialise_internal( sfree(data.cparstr); data.cparstr = val; val = NULL; + } else if (!strcmp(key, "HEXSEED")) { + unsigned char *tmp; + int len = strlen(val) / 2; /* length in bytes */ + tmp = hex2bin(val, len); + sfree(data.seed); + data.seed = snewn(len + 1, char); + memcpy(data.seed, tmp, len); + data.seed[len] = '\0'; + sfree(tmp); } else if (!strcmp(key, "SEED")) { sfree(data.seed); data.seed = val; @@ -2234,15 +2477,15 @@ static const char *midend_deserialise_internal( } else if (!strcmp(key, "TIME")) { data.elapsed = (float)atof(val); } else if (!strcmp(key, "NSTATES")) { + if (data.states) { + ret = "Two state counts provided in save file"; + goto cleanup; + } data.nstates = atoi(val); if (data.nstates <= 0) { ret = "Number of states in save file was negative"; goto cleanup; } - if (data.states) { - ret = "Two state counts provided in save file"; - goto cleanup; - } data.states = snewn(data.nstates, struct midend_state_entry); for (i = 0; i < data.nstates; i++) { data.states[i].state = NULL; @@ -2251,19 +2494,25 @@ static const char *midend_deserialise_internal( } } else if (!strcmp(key, "STATEPOS")) { data.statepos = atoi(val); - } else if (!strcmp(key, "MOVE")) { - gotstates++; - data.states[gotstates].movetype = MOVE; - data.states[gotstates].movestr = val; - val = NULL; - } else if (!strcmp(key, "SOLVE")) { - gotstates++; - data.states[gotstates].movetype = SOLVE; - data.states[gotstates].movestr = val; - val = NULL; - } else if (!strcmp(key, "RESTART")) { + } else if (!strcmp(key, "MOVE") || + !strcmp(key, "SOLVE") || + !strcmp(key, "RESTART")) { + if (!data.states) { + ret = "No state count provided in save file"; + goto cleanup; + } + if (data.statepos < 0) { + ret = "No game position provided in save file"; + goto cleanup; + } gotstates++; - data.states[gotstates].movetype = RESTART; + assert(gotstates < data.nstates); + if (!strcmp(key, "MOVE")) + data.states[gotstates].movetype = MOVE; + else if (!strcmp(key, "SOLVE")) + data.states[gotstates].movetype = SOLVE; + else + data.states[gotstates].movetype = RESTART; data.states[gotstates].movestr = val; val = NULL; } @@ -2274,12 +2523,20 @@ static const char *midend_deserialise_internal( } data.params = me->ourgame->default_params(); + if (!data.parstr) { + ret = "Long-term parameters in save file are missing"; + goto cleanup; + } me->ourgame->decode_params(data.params, data.parstr); if (me->ourgame->validate_params(data.params, true)) { ret = "Long-term parameters in save file are invalid"; goto cleanup; } data.cparams = me->ourgame->default_params(); + if (!data.cparstr) { + ret = "Short-term parameters in save file are missing"; + goto cleanup; + } me->ourgame->decode_params(data.cparams, data.cparstr); if (me->ourgame->validate_params(data.cparams, false)) { ret = "Short-term parameters in save file are invalid"; @@ -2305,12 +2562,18 @@ static const char *midend_deserialise_internal( ret = "Game private description in save file is invalid"; goto cleanup; } - if (data.statepos < 0 || data.statepos >= data.nstates) { + if (data.statepos < 1 || data.statepos > data.nstates) { ret = "Game position in save file is out of range"; + goto cleanup; } + if (!data.states) { + ret = "No state count provided in save file"; + goto cleanup; + } data.states[0].state = me->ourgame->new_game( me, data.cparams, data.privdesc ? data.privdesc : data.desc); + for (i = 1; i < data.nstates; i++) { assert(data.states[i].movetype != NEWGAME); switch (data.states[i].movetype) { @@ -2336,7 +2599,10 @@ static const char *midend_deserialise_internal( } data.ui = me->ourgame->new_ui(data.states[0].state); - me->ourgame->decode_ui(data.ui, data.uistr); + midend_apply_prefs(me, data.ui); + if (data.uistr && me->ourgame->decode_ui) + me->ourgame->decode_ui(data.ui, data.uistr, + data.states[data.statepos-1].state); /* * Run the externally provided check function, and abort if it @@ -2429,6 +2695,7 @@ static const char *midend_deserialise_internal( me->drawstate = me->ourgame->new_drawstate(me->drawing, me->states[me->statepos-1].state); + me->first_draw = true; midend_size_new_drawstate(me); if (me->game_id_change_notify_function) me->game_id_change_notify_function(me->game_id_change_notify_ctx); @@ -2528,7 +2795,7 @@ const char *identify_game(char **name, if (c == ':') { break; - } else if (c >= '0' && c <= '9') { + } else if (c >= '0' && c <= '9' && len < (INT_MAX - 10) / 10) { len = (len * 10) + (c - '0'); } else { if (started) @@ -2540,7 +2807,7 @@ const char *identify_game(char **name, val = snewn(len+1, char); if (!read(rctx, val, len)) { - if (started) + /* unexpected EOF */ goto cleanup; } val[len] = '\0'; @@ -2605,14 +2872,340 @@ const char *midend_print_puzzle(midend *me, document *doc, bool with_soln) soln = NULL; /* - * This call passes over ownership of the two game_states and - * the game_params. Hence we duplicate the ones we want to - * keep, and we don't have to bother freeing soln if it was - * non-NULL. + * This call passes over ownership of the two game_states, the + * game_params and the game_ui. Hence we duplicate the ones we + * want to keep, and we don't have to bother freeing soln if it + * was non-NULL. */ + game_ui *ui = me->ourgame->new_ui(me->states[0].state); + midend_apply_prefs(me, ui); document_add_puzzle(doc, me->ourgame, - me->ourgame->dup_params(me->curparams), + me->ourgame->dup_params(me->curparams), ui, me->ourgame->dup_game(me->states[0].state), soln); return NULL; } + +static void midend_apply_prefs(midend *me, game_ui *ui) +{ + struct midend_serialise_buf_read_ctx rctx[1]; + rctx->ser = &me->be_prefs; + rctx->len = me->be_prefs.len; + rctx->pos = 0; + const char *err = midend_deserialise_prefs( + me, ui, midend_serialise_buf_read, rctx); + /* This should have come from our own serialise function, so + * it should never be invalid. */ + assert(!err && "Bad internal serialisation of preferences"); +} + +static config_item *midend_get_prefs(midend *me, game_ui *ui) +{ + int n_be_prefs, n_me_prefs, pos, i; + config_item *all_prefs, *be_prefs; + + be_prefs = NULL; + n_be_prefs = 0; + if (me->ourgame->get_prefs) { + if (ui) { + be_prefs = me->ourgame->get_prefs(ui); + } else if (me->ui) { + be_prefs = me->ourgame->get_prefs(me->ui); + } else { + game_ui *tmp_ui = me->ourgame->new_ui(NULL); + be_prefs = me->ourgame->get_prefs(tmp_ui); + me->ourgame->free_ui(tmp_ui); + } + while (be_prefs[n_be_prefs].type != C_END) + n_be_prefs++; + } + + n_me_prefs = 1; + all_prefs = snewn(n_me_prefs + n_be_prefs + 1, config_item); + + pos = 0; + + assert(pos < n_me_prefs); + all_prefs[pos].name = "Keyboard shortcuts without Ctrl"; + all_prefs[pos].kw = "one-key-shortcuts"; + all_prefs[pos].type = C_BOOLEAN; + all_prefs[pos].u.boolean.bval = me->one_key_shortcuts; + pos++; + + for (i = 0; i < n_be_prefs; i++) { + all_prefs[pos] = be_prefs[i]; /* structure copy */ + pos++; + } + + all_prefs[pos].name = NULL; + all_prefs[pos].type = C_END; + + if (be_prefs) + /* We already copied each element, so don't free those with + free_cfg(). */ + sfree(be_prefs); + + return all_prefs; +} + +static void midend_set_prefs(midend *me, game_ui *ui, config_item *all_prefs) +{ + int pos = 0; + game_ui *tmpui = NULL; + + me->one_key_shortcuts = all_prefs[pos].u.boolean.bval; + pos++; + + if (me->ourgame->get_prefs) { + if (!ui) + ui = tmpui = me->ourgame->new_ui(NULL); + me->ourgame->set_prefs(ui, all_prefs + pos); + } + + me->be_prefs.len = 0; + midend_serialise_prefs(me, ui, midend_serialise_buf_write, &me->be_prefs); + + if (tmpui) + me->ourgame->free_ui(tmpui); +} + +static void midend_serialise_prefs( + midend *me, game_ui *ui, + void (*write)(void *ctx, const void *buf, int len), void *wctx) +{ + config_item *cfg; + int i; + + cfg = midend_get_prefs(me, ui); + + assert(cfg); + + for (i = 0; cfg[i].type != C_END; i++) { + config_item *it = &cfg[i]; + + /* Expect keywords to be made up only of simple characters */ + assert(it->kw[strspn(it->kw, "abcdefghijklmnopqrstuvwxyz-")] == '\0'); + + write(wctx, it->kw, strlen(it->kw)); + write(wctx, "=", 1); + + switch (it->type) { + case C_BOOLEAN: + if (it->u.boolean.bval) + write(wctx, "true", 4); + else + write(wctx, "false", 5); + break; + case C_STRING: { + const char *p = it->u.string.sval; + while (*p) { + char c = *p++; + write(wctx, &c, 1); + if (c == '\n') + write(wctx, " ", 1); + } + break; + } + case C_CHOICES: { + int n = it->u.choices.selected; + const char *p = it->u.choices.choicekws; + char sepstr[2]; + + sepstr[0] = *p++; + sepstr[1] = '\0'; + + while (n > 0) { + const char *q = strchr(p, sepstr[0]); + assert(q != NULL && "Value out of range in C_CHOICES"); + p = q+1; + n--; + } + + write(wctx, p, strcspn(p, sepstr)); + break; + } + } + + write(wctx, "\n", 1); + } + + free_cfg(cfg); +} + +struct buffer { + char *data; + size_t len, size; +}; + +static void buffer_append(struct buffer *buf, char c) +{ + if (buf->len + 2 > buf->size) { + size_t new_size = buf->size + buf->size / 4 + 128; + assert(new_size > buf->size); + buf->data = sresize(buf->data, new_size, char); + buf->size = new_size; + assert(buf->len < buf->size); + } + buf->data[buf->len++] = c; + assert(buf->len < buf->size); + buf->data[buf->len] = '\0'; +} + +static const char *midend_deserialise_prefs( + midend *me, game_ui *ui, + bool (*read)(void *ctx, void *buf, int len), void *rctx) +{ + config_item *cfg, *it; + int i; + struct buffer buf[1] = {{ NULL, 0, 0 }}; + const char *errmsg = NULL; + char read_char; + char ungot_char = '\0'; + bool have_ungot_a_char = false, eof = false; + + cfg = midend_get_prefs(me, ui); + + while (!eof) { + if (have_ungot_a_char) { + read_char = ungot_char; + have_ungot_a_char = false; + } else { + if (!read(rctx, &read_char, 1)) + goto out; /* EOF at line start == success */ + } + + if (read_char == '#' || read_char == '\n') { + /* Skip comment or blank line */ + while (read_char != '\n') { + if (!read(rctx, &read_char, 1)) + goto out; /* EOF during boring line == success */ + } + continue; + } + + buf->len = 0; + while (true) { + buffer_append(buf, read_char); + if (!read(rctx, &read_char, 1)) { + errmsg = "Partial line at end of preferences file"; + goto out; + } + if (read_char == '\n') { + errmsg = "Expected '=' after keyword"; + goto out; + } + if (read_char == '=') + break; + } + + it = NULL; + for (i = 0; cfg[i].type != C_END; i++) + if (!strcmp(buf->data, cfg[i].kw)) + it = &cfg[i]; + + buf->len = 0; + while (true) { + if (!read(rctx, &read_char, 1)) { + /* We tolerate missing \n at the end of the file, so + * this is taken to mean we've got a complete config + * directive. But set the eof flag so that we stop + * after processing it. */ + eof = true; + break; + } else if (read_char == '\n') { + /* Newline _might_ be the end of this config + * directive, unless it's followed by a space, in + * which case it's a space-stuffed line + * continuation. */ + if (read(rctx, &read_char, 1)) { + if (read_char == ' ') { + buffer_append(buf, '\n'); + continue; + } else { + /* But if the next character wasn't a space, + * then we must unget it so that it'll be + * available to the next iteration of our + * outer loop as the first character of the + * next keyword. */ + ungot_char = read_char; + have_ungot_a_char = true; + break; + } + } else { + /* And if the newline was followed by EOF, then we + * should finish this iteration of the outer + * loop normally, and then not go round again. */ + eof = true; + break; + } + } else { + /* Any other character is just added to the buffer. */ + buffer_append(buf, read_char); + } + } + + if (!it) { + /* + * Tolerate unknown keywords in a preferences file, on the + * assumption that they're from a different (probably + * later) version of the game. + */ + continue; + } + + switch (it->type) { + case C_BOOLEAN: + if (!strcmp(buf->data, "true")) + it->u.boolean.bval = true; + else if (!strcmp(buf->data, "false")) + it->u.boolean.bval = false; + else { + errmsg = "Value for boolean was not 'true' or 'false'"; + goto out; + } + break; + case C_STRING: + sfree(it->u.string.sval); + it->u.string.sval = buf->data; + buf->data = NULL; + buf->len = buf->size = 0; + break; + case C_CHOICES: { + int n = 0; + bool found = false; + const char *p = it->u.choices.choicekws; + char sepstr[2]; + + sepstr[0] = *p; + sepstr[1] = '\0'; + + while (*p++) { + int len = strcspn(p, sepstr); + if (buf->len == len && !memcmp(p, buf->data, len)) { + it->u.choices.selected = n; + found = true; + break; + } + p += len; + n++; + } + + if (!found) { + errmsg = "Invalid value for enumeration"; + goto out; + } + + break; + } + } + } + + out: + + if (!errmsg) + midend_set_prefs(me, ui, cfg); + + free_cfg(cfg); + sfree(buf->data); + return errmsg; +} diff --git a/apps/plugins/puzzles/src/mines.R b/apps/plugins/puzzles/src/mines.R deleted file mode 100644 index 275c76c7ad..0000000000 --- a/apps/plugins/puzzles/src/mines.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MINES_EXTRA = tree234 - -mines : [X] GTK COMMON mines MINES_EXTRA mines-icon|no-icon - -mines : [G] WINDOWS COMMON mines MINES_EXTRA mines.res|noicon.res - -mineobfusc : [U] mines[STANDALONE_OBFUSCATOR] MINES_EXTRA STANDALONE -mineobfusc : [C] mines[STANDALONE_OBFUSCATOR] MINES_EXTRA STANDALONE - -ALL += mines[COMBINED] MINES_EXTRA - -!begin am gtk -GAMES += mines -!end - -!begin >list.c - A(mines) \ -!end - -!begin >gamedesc.txt -mines:mines.exe:Mines:Mine-finding puzzle:Find all the mines without treading on any of them. -!end diff --git a/apps/plugins/puzzles/src/mines.c b/apps/plugins/puzzles/src/mines.c index 706777c4f1..e1441fae13 100644 --- a/apps/plugins/puzzles/src/mines.c +++ b/apps/plugins/puzzles/src/mines.c @@ -3,8 +3,7 @@ * * Still TODO: * - * - think about configurably supporting question marks. Once, - * that is, we've thought about configurability in general! + * - think about configurably supporting question marks. */ #include @@ -12,7 +11,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "tree234.h" #include "puzzles.h" @@ -34,8 +38,8 @@ enum { #else #define BORDER (TILE_SIZE * 3 / 2) #endif -#define HIGHLIGHT_WIDTH (TILE_SIZE / 10) -#define OUTER_HIGHLIGHT_WIDTH (BORDER / 10) +#define HIGHLIGHT_WIDTH (TILE_SIZE / 10 ? TILE_SIZE / 10 : 1) +#define OUTER_HIGHLIGHT_WIDTH (BORDER / 10 ? BORDER / 10 : 1) #define COORD(x) ( (x) * TILE_SIZE + BORDER ) #define FROMCOORD(x) ( ((x) - BORDER + TILE_SIZE) / TILE_SIZE - 1 ) @@ -162,7 +166,9 @@ static void decode_params(game_params *params, char const *string) params->n = atoi(p); while (*p && (*p == '.' || isdigit((unsigned char)*p))) p++; } else { - params->n = params->w * params->h / 10; + if (params->h > 0 && params->w > 0 && + params->w <= INT_MAX / params->h) + params->n = params->w * params->h / 10; } while (*p) { @@ -250,7 +256,7 @@ static const char *validate_params(const game_params *params, bool full) * blocking the way and no idea what's behind them, or one mine * and no way to know which of the two rows it's in. If the * mine count is even you can create a soluble grid by packing - * all the mines at one end (so what when you hit a two-mine + * all the mines at one end (so that when you hit a two-mine * wall there are only as many covered squares left as there * are mines); but if it's odd, you are doomed, because you * _have_ to have a gap somewhere which you can't determine the @@ -258,12 +264,25 @@ static const char *validate_params(const game_params *params, bool full) */ if (full && params->unique && (params->w <= 2 || params->h <= 2)) return "Width and height must both be greater than two"; + if (params->w < 1 || params->h < 1) + return "Width and height must both be at least one"; + if (params->w > SHRT_MAX || params->h > SHRT_MAX) + return "Neither width nor height may be unreasonably large"; + /* + * We use random_upto() to place mines, and its maximum limit is 2^28-1. + */ +#if (1<<28)-1 < INT_MAX + if (params->w > ((1<<28)-1) / params->h) +#else + if (params->w > INT_MAX / params->h) +#endif + return "Width times height must not be unreasonably large"; if (params->n < 0) return "Mine count may not be negative"; - if (params->n > params->w * params->h - 9) - return "Too many mines for grid size"; if (params->n < 1) return "Number of mines must be greater than zero"; + if (params->n > params->w * params->h - 9) + return "Too many mines for grid size"; /* * FIXME: Need more constraints here. Not sure what the @@ -428,7 +447,9 @@ static void ss_add(struct setstore *ss, int x, int y, int mask, int mines) * Create a set structure and add it to the tree. */ s = snew(struct set); + assert(SHRT_MIN <= x && x <= SHRT_MAX); s->x = x; + assert(SHRT_MIN <= y && y <= SHRT_MAX); s->y = y; s->mask = mask; s->mines = mines; @@ -499,7 +520,9 @@ static struct set **ss_overlap(struct setstore *ss, int x, int y, int mask) /* * Find the first set with these top left coordinates. */ + assert(SHRT_MIN <= xx && xx <= SHRT_MAX); stmp.x = xx; + assert(SHRT_MIN <= yy && yy <= SHRT_MAX); stmp.y = yy; stmp.mask = 0; @@ -1880,72 +1903,7 @@ static char *describe_layout(bool *grid, int area, int x, int y, static bool *new_mine_layout(int w, int h, int n, int x, int y, bool unique, random_state *rs, char **game_desc) { - bool *grid; - -#ifdef TEST_OBFUSCATION - static int tested_obfuscation = false; - if (!tested_obfuscation) { - /* - * A few simple test vectors for the obfuscator. - * - * First test: the 28-bit stream 1234567. This divides up - * into 1234 and 567[0]. The SHA of 56 70 30 (appending - * "0") is 15ce8ab946640340bbb99f3f48fd2c45d1a31d30. Thus, - * we XOR the 16-bit string 15CE into the input 1234 to get - * 07FA. Next, we SHA that with "0": the SHA of 07 FA 30 is - * 3370135c5e3da4fed937adc004a79533962b6391. So we XOR the - * 12-bit string 337 into the input 567 to get 650. Thus - * our output is 07FA650. - */ - { - unsigned char bmp1[] = "\x12\x34\x56\x70"; - obfuscate_bitmap(bmp1, 28, false); - printf("test 1 encode: %s\n", - memcmp(bmp1, "\x07\xfa\x65\x00", 4) ? "failed" : "passed"); - obfuscate_bitmap(bmp1, 28, true); - printf("test 1 decode: %s\n", - memcmp(bmp1, "\x12\x34\x56\x70", 4) ? "failed" : "passed"); - } - /* - * Second test: a long string to make sure we switch from - * one SHA to the next correctly. My input string this time - * is simply fifty bytes of zeroes. - */ - { - unsigned char bmp2[50]; - unsigned char bmp2a[50]; - memset(bmp2, 0, 50); - memset(bmp2a, 0, 50); - obfuscate_bitmap(bmp2, 50 * 8, false); - /* - * SHA of twenty-five zero bytes plus "0" is - * b202c07b990c01f6ff2d544707f60e506019b671. SHA of - * twenty-five zero bytes plus "1" is - * fcb1d8b5a2f6b592fe6780b36aa9d65dd7aa6db9. Thus our - * first half becomes - * b202c07b990c01f6ff2d544707f60e506019b671fcb1d8b5a2. - * - * SHA of that lot plus "0" is - * 10b0af913db85d37ca27f52a9f78bba3a80030db. SHA of the - * same string plus "1" is - * 3d01d8df78e76d382b8106f480135a1bc751d725. So the - * second half becomes - * 10b0af913db85d37ca27f52a9f78bba3a80030db3d01d8df78. - */ - printf("test 2 encode: %s\n", - memcmp(bmp2, "\xb2\x02\xc0\x7b\x99\x0c\x01\xf6\xff\x2d\x54" - "\x47\x07\xf6\x0e\x50\x60\x19\xb6\x71\xfc\xb1\xd8" - "\xb5\xa2\x10\xb0\xaf\x91\x3d\xb8\x5d\x37\xca\x27" - "\xf5\x2a\x9f\x78\xbb\xa3\xa8\x00\x30\xdb\x3d\x01" - "\xd8\xdf\x78", 50) ? "failed" : "passed"); - obfuscate_bitmap(bmp2, 50 * 8, true); - printf("test 2 decode: %s\n", - memcmp(bmp2, bmp2a, 50) ? "failed" : "passed"); - } - } -#endif - - grid = minegen(w, h, n, x, y, unique, rs); + bool *grid = minegen(w, h, n, x, y, unique, rs); if (game_desc) *game_desc = describe_layout(grid, w * h, x, y, true); @@ -2001,6 +1959,8 @@ static const char *validate_desc(const game_params *params, const char *desc) desc++; if (!*desc || !isdigit((unsigned char)*desc)) return "No initial mine count in game description"; + if (atoi(desc) > wh - 9) + return "Too many mines for grid size"; while (*desc && isdigit((unsigned char)*desc)) desc++; /* skip over mine count */ if (*desc != ',') @@ -2139,6 +2099,8 @@ static int open_square(game_state *state, int x, int y) break; } + /* If the player has already lost, don't let them win as well. */ + if (state->dead) return 0; /* * Finally, scan the grid and see if exactly as many squares * are still covered as there are mines. If so, set the `won' @@ -2365,7 +2327,7 @@ static game_ui *new_ui(const game_state *state) ui->completed = false; ui->flash_is_death = false; /* *shrug* */ ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -2387,7 +2349,8 @@ static char *encode_ui(const game_ui *ui) return dupstr(buf); } -static void decode_ui(game_ui *ui, const char *encoding) +static void decode_ui(game_ui *ui, const char *encoding, + const game_state *state) { int p= 0; sscanf(encoding, "D%d%n", &ui->deaths, &p); @@ -2402,6 +2365,35 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->completed = true; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int cx = ui->cur_x, cy = ui->cur_y; + int v = state->grid[cy * state->w + cx]; + + if (state->dead || state->won || !ui->cur_visible) return ""; + if (button == CURSOR_SELECT2) { + if (v == -2) return "Mark"; + if (v == -1) return "Unmark"; + return ""; + } + if (button == CURSOR_SELECT) { + int dy, dx, n = 0; + if (v == -2 || v == -3) return "Uncover"; + if (v == 0) return ""; + /* Count mine markers. */ + for (dy = -1; dy <= +1; dy++) + for (dx = -1; dx <= +1; dx++) + if (cx+dx >= 0 && cx+dx < state->w && + cy+dy >= 0 && cy+dy < state->h) { + if (state->grid[(cy+dy)*state->w+(cx+dx)] == -1) + n++; + } + if (n == v) return "Clear"; + } + return ""; +} + struct game_drawstate { int w, h, tilesize, bg; bool started; @@ -2432,22 +2424,20 @@ static char *interpret_move(const game_state *from, game_ui *ui, cx = FROMCOORD(x); cy = FROMCOORD(y); - if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false); - ui->cur_visible = true; - return UI_UPDATE; - } + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, + false, &ui->cur_visible); if (IS_CURSOR_SELECT(button)) { int v = from->grid[ui->cur_y * from->w + ui->cur_x]; if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == CURSOR_SELECT2) { /* As for RIGHT_BUTTON; only works on covered square. */ if (v != -2 && v != -1) - return NULL; + return MOVE_NO_EFFECT; sprintf(buf, "F%d,%d", ui->cur_x, ui->cur_y); return dupstr(buf); } @@ -2468,7 +2458,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, if (button == LEFT_BUTTON || button == LEFT_DRAG || button == MIDDLE_BUTTON || button == MIDDLE_DRAG) { if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h) - return NULL; + return MOVE_UNUSED; /* * Mouse-downs and mouse-drags just cause highlighting @@ -2482,12 +2472,12 @@ static char *interpret_move(const game_state *from, game_ui *ui, else if (button == MIDDLE_BUTTON) ui->validradius = 1; ui->cur_visible = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == RIGHT_BUTTON) { if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h) - return NULL; + return MOVE_UNUSED; /* * Right-clicking only works on a covered square, and it @@ -2498,7 +2488,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, */ if (from->grid[cy * from->w + cx] != -2 && from->grid[cy * from->w + cx] != -1) - return NULL; + return MOVE_NO_EFFECT; sprintf(buf, "F%d,%d", cx, cy); return dupstr(buf); @@ -2509,11 +2499,12 @@ static char *interpret_move(const game_state *from, game_ui *ui, ui->hradius = 0; /* - * At this stage we must never return NULL: we have adjusted - * the ui, so at worst we return UI_UPDATE. + * At this stage we must never return MOVE_UNUSED or + * MOVE_NO_EFFECT: we have adjusted the ui, so at worst we + * return MOVE_UI_UPDATE. */ if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h) - return UI_UPDATE; + return MOVE_UI_UPDATE; /* * Left-clicking on a covered square opens a tile. Not @@ -2533,7 +2524,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, } goto uncover; } - return NULL; + return MOVE_UNUSED; uncover: { @@ -2591,7 +2582,7 @@ uncover: } } - return UI_UPDATE; + return MOVE_UI_UPDATE; } } @@ -2603,6 +2594,7 @@ static game_state *execute_move(const game_state *from, const char *move) if (!strcmp(move, "S")) { int yy, xx; + if (!from->layout->mines) return NULL; /* Game not started. */ ret = dup_game(from); if (!ret->dead) { /* @@ -2656,12 +2648,17 @@ static game_state *execute_move(const game_state *from, const char *move) return ret; } else { + /* Dead players should stop trying to move. */ + if (from->dead) + return NULL; ret = dup_game(from); while (*move) { if (move[0] == 'F' && sscanf(move+1, "%d,%d", &cx, &cy) == 2 && - cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) { + cx >= 0 && cx < from->w && cy >= 0 && cy < from->h && + (ret->grid[cy * from->w + cx] == -1 || + ret->grid[cy * from->w + cx] == -2)) { ret->grid[cy * from->w + cx] ^= (-2 ^ -1); } else if (move[0] == 'O' && sscanf(move+1, "%d,%d", &cx, &cy) == 2 && @@ -2697,7 +2694,7 @@ static game_state *execute_move(const game_state *from, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2870,12 +2867,12 @@ static void draw_tile(drawing *dr, game_drawstate *ds, coords[(n)*2+0] = x + (int)(TILE_SIZE * (dx)); \ coords[(n)*2+1] = y + (int)(TILE_SIZE * (dy)); \ } while (0) - SETCOORD(0, 0.6F, 0.7F); - SETCOORD(1, 0.8F, 0.8F); - SETCOORD(2, 0.25F, 0.8F); - SETCOORD(3, 0.55F, 0.7F); - SETCOORD(4, 0.55F, 0.35F); - SETCOORD(5, 0.6F, 0.35F); + SETCOORD(0, 0.6F, 0.35F); + SETCOORD(1, 0.6F, 0.7F); + SETCOORD(2, 0.8F, 0.8F); + SETCOORD(3, 0.25F, 0.8F); + SETCOORD(4, 0.55F, 0.7F); + SETCOORD(5, 0.55F, 0.35F); draw_polygon(dr, coords, 6, COL_FLAGBASE, COL_FLAGBASE); SETCOORD(0, 0.6F, 0.2F); @@ -2980,13 +2977,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -3182,14 +3172,6 @@ static bool game_timing_state(const game_state *state, game_ui *ui) return true; } -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame mines #endif @@ -3211,12 +3193,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, encode_ui, decode_ui, NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3228,7 +3212,7 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ true, game_timing_state, BUTTON_BEATS(LEFT_BUTTON, RIGHT_BUTTON) | REQUIRE_RBUTTON, diff --git a/apps/plugins/puzzles/src/misc.c b/apps/plugins/puzzles/src/misc.c index ed31acbbe4..f9eaf5d9b8 100644 --- a/apps/plugins/puzzles/src/misc.c +++ b/apps/plugins/puzzles/src/misc.c @@ -3,13 +3,21 @@ */ #include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include #include #include #include "puzzles.h" -char UI_UPDATE[] = ""; +char MOVE_UI_UPDATE[] = ""; +char MOVE_NO_EFFECT[] = ""; +char MOVE_UNUSED[] = ""; void free_cfg(config_item *cfg) { @@ -197,30 +205,85 @@ char *fgetline(FILE *fp) return ret; } +int getenv_bool(const char *name, int dflt) +{ + char *env = getenv(name); + if (env == NULL) return dflt; + if (strchr("yYtT", env[0])) return true; + return false; +} + +/* Utility functions for colour manipulation. */ + +static float colour_distance(const float a[3], const float b[3]) +{ + return (float)sqrt((a[0]-b[0]) * (a[0]-b[0]) + + (a[1]-b[1]) * (a[1]-b[1]) + + (a[2]-b[2]) * (a[2]-b[2])); +} + +void colour_mix(const float src1[3], const float src2[3], float p, float dst[3]) +{ + int i; + for (i = 0; i < 3; i++) + dst[i] = src1[i] * (1.0F - p) + src2[i] * p; +} + void game_mkhighlight_specific(frontend *fe, float *ret, int background, int highlight, int lowlight) { - float max; + static const float black[3] = { 0.0F, 0.0F, 0.0F }; + static const float white[3] = { 1.0F, 1.0F, 1.0F }; + float db, dw; int i; - /* - * Drop the background colour so that the highlight is - * noticeably brighter than it while still being under 1. + * New geometric highlight-generation algorithm: Draw a line from + * the base colour to white. The point K distance along this line + * from the base colour is the highlight colour. Similarly, draw + * a line from the base colour to black. The point on this line + * at a distance K from the base colour is the shadow. If either + * of these colours is imaginary (for reasonable K at most one + * will be), _extrapolate_ the base colour along the same line + * until it's a distance K from white (or black) and start again + * with that as the base colour. + * + * This preserves the hue of the base colour, ensures that of the + * three the base colour is the most saturated, and only ever + * flattens the highlight and shadow to pure white or pure black. + * + * K must be at most sqrt(3)/2, or mid grey would be too close to + * both white and black. Here K is set to sqrt(3)/6 so that this + * code produces the same results as the former code in the common + * case where the background is grey and the highlight saturates + * to white. */ - max = ret[background*3]; - for (i = 1; i < 3; i++) - if (ret[background*3+i] > max) - max = ret[background*3+i]; - if (max * 1.2F > 1.0F) { - for (i = 0; i < 3; i++) - ret[background*3+i] /= (max * 1.2F); + const float k = sqrt(3)/6.0F; + if (lowlight >= 0) { + db = colour_distance(&ret[background*3], black); + if (db < k) { + for (i = 0; i < 3; i++) ret[lowlight*3+i] = black[i]; + if (db == 0.0F) + colour_mix(black, white, k/sqrt(3), &ret[background*3]); + else + colour_mix(black, &ret[background*3], k/db, &ret[background*3]); + } else { + colour_mix(&ret[background*3], black, k/db, &ret[lowlight*3]); + } } - - for (i = 0; i < 3; i++) { - if (highlight >= 0) - ret[highlight * 3 + i] = ret[background * 3 + i] * 1.2F; - if (lowlight >= 0) - ret[lowlight * 3 + i] = ret[background * 3 + i] * 0.8F; + if (highlight >= 0) { + dw = colour_distance(&ret[background*3], white); + if (dw < k) { + for (i = 0; i < 3; i++) ret[highlight*3+i] = white[i]; + if (dw == 0.0F) + colour_mix(white, black, k/sqrt(3), &ret[background*3]); + else + colour_mix(white, &ret[background*3], k/dw, &ret[background*3]); + /* Background has changed; recalculate lowlight. */ + if (lowlight >= 0) + colour_mix(&ret[background*3], black, k/db, &ret[lowlight*3]); + } else { + colour_mix(&ret[background*3], white, k/dw, &ret[highlight*3]); + } } } @@ -231,7 +294,7 @@ void game_mkhighlight(frontend *fe, float *ret, game_mkhighlight_specific(fe, ret, background, highlight, lowlight); } -static void swap_regions(void *av, void *bv, int size) +void swap_regions(void *av, void *bv, size_t size) { char tmpbuf[512]; char *a = av, *b = bv; @@ -288,15 +351,16 @@ void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col) draw_line(dr, cx + r, cy + r, cx + r/2, cy + r, col); } -void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap) +char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap, + bool *visible) { - int dx = 0, dy = 0; + int dx = 0, dy = 0, ox = *x, oy = *y; switch (button) { case CURSOR_UP: dy = -1; break; case CURSOR_DOWN: dy = 1; break; case CURSOR_RIGHT: dx = 1; break; case CURSOR_LEFT: dx = -1; break; - default: return; + default: return MOVE_UNUSED; } if (wrap) { *x = (*x + dx + maxw) % maxw; @@ -305,6 +369,13 @@ void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap) *x = min(max(*x+dx, 0), maxw - 1); *y = min(max(*y+dy, 0), maxh - 1); } + if (visible != NULL && !*visible) { + *visible = true; + return MOVE_UI_UPDATE; + } + if (*x != ox || *y != oy) + return MOVE_UI_UPDATE; + return MOVE_NO_EFFECT; } /* Used in netslide.c and sixteen.c for cursor movement around edge. */ @@ -402,12 +473,6 @@ void copy_left_justified(char *buf, size_t sz, const char *str) buf[sz - 1] = 0; } -/* another kludge for platforms without %g support in *printf() */ -int ftoa(char *buf, float f) -{ - return sprintf(buf, "%d.%06d", (int)f, abs((int)((f - (int)f)*1e6))); -} - /* Returns a dynamically allocated label for a generic button. * Game-specific buttons should go into the `label' field of key_label * instead. */ @@ -446,4 +511,161 @@ char *button2label(int button) return NULL; } +char *make_prefs_path(const char *dir, const char *sep, + const game *game, const char *suffix) +{ + size_t dirlen = strlen(dir); + size_t seplen = strlen(sep); + size_t gamelen = strlen(game->name); + size_t suffixlen = strlen(suffix); + char *path, *p; + const char *q; + + if (!dir || !sep || !game || !suffix) + return NULL; + + path = snewn(dirlen + seplen + gamelen + suffixlen + 1, char); + p = path; + + memcpy(p, dir, dirlen); + p += dirlen; + + memcpy(p, sep, seplen); + p += seplen; + + for (q = game->name; *q; q++) + if (*q != ' ') + *p++ = tolower((unsigned char)*q); + + memcpy(p, suffix, suffixlen); + p += suffixlen; + + *p = '\0'; + return path; +} + +/* + * Calculate the nearest integer to n*sqrt(k), via a bitwise algorithm + * that avoids floating point. + * + * (It would probably be OK in practice to use floating point, but I + * felt like overengineering it for fun. With FP, there's at least a + * theoretical risk of rounding the wrong way, due to the three + * successive roundings involved - rounding sqrt(k), rounding its + * product with n, and then rounding to the nearest integer. This + * approach avoids that: it's exact.) + */ +int n_times_root_k(int n_signed, int k) +{ + unsigned x, r, m; + int sign = n_signed < 0 ? -1 : +1; + unsigned n = n_signed * sign; + unsigned bitpos; + + /* + * Method: + * + * We transform m gradually from zero into n, by multiplying it by + * 2 in each step and optionally adding 1, so that it's always + * floor(n/2^something). + * + * At the start of each step, x is the largest integer less than + * or equal to m*sqrt(k). We transform m to 2m+bit, and therefore + * we must transform x to 2x+something to match. The 'something' + * we add to 2x is at most floor(sqrt(k))+2. (Worst case is if m + * sqrt(k) was equal to x + 1-eps for some tiny eps, and then the + * incoming bit of m is 1, so that (2m+1)sqrt(k) = + * 2x+2+sqrt(k)-2eps.) + * + * To compute this, we also track the residual value r such that + * x^2+r = km^2. + * + * The algorithm below is very similar to the usual approach for + * taking the square root of an integer in binary. The wrinkle is + * that we have an integer multiplier, i.e. we're computing + * n*sqrt(k) rather than just sqrt(k). Of course in principle we + * could just take sqrt(n^2k), but we'd need an integer twice the + * width to hold n^2. Pulling out n and treating it specially + * makes overflow less likely. + */ + + x = r = m = 0; + + for (bitpos = UINT_MAX & ~(UINT_MAX >> 1); bitpos; bitpos >>= 1) { + unsigned a, b = (n & bitpos) ? 1 : 0; + + /* + * Check invariants. We expect that x^2 + r = km^2 (i.e. our + * residual term is correct), and also that r < 2x+1 (because + * if not, then we could replace x with x+1 and still get a + * value that made r non-negative, i.e. x would not be the + * _largest_ integer less than m sqrt(k)). + */ + assert(x*x + r == k*m*m); + assert(r < 2*x+1); + + /* + * We're going to replace m with 2m+b, and x with 2x+a for + * some a we haven't decided on yet. + * + * The new value of the residual will therefore be + * + * k (2m+b)^2 - (2x+a)^2 + * = (4km^2 + 4kmb + kb^2) - (4x^2 + 4xa + a^2) + * = 4 (km^2 - x^2) + 4kmb + kb^2 - 4xa - a^2 + * = 4r + 4kmb + kb^2 - 4xa - a^2 (because r = km^2 - x^2) + * = 4r + (4m + 1)kb - 4xa - a^2 (b is 0 or 1, so b = b^2) + */ + for (a = 0;; a++) { + /* If we made this routine handle square roots of numbers + * significantly bigger than 3 or 5 then it would be + * sensible to make this a binary search. Here, it hardly + * seems important. */ + unsigned pos = 4*r + k*b*(4*m + 1); + unsigned neg = 4*a*x + a*a; + if (pos < neg) + break; /* this value of a is too big */ + } + + /* The above loop will have terminated with a one too big. So + * now decrementing a will give us the right value to add. */ + a--; + + r = 4*r + b*k*(4*m + 1) - (4*a*x + a*a); + m = 2*m+b; + x = 2*x+a; + } + + /* + * Finally, round to the nearest integer. At present, x is the + * largest integer that is _at most_ m sqrt(k). But we want the + * _nearest_ integer, whether that's rounded up or down. So check + * whether (x + 1/2) is still less than m sqrt(k), i.e. whether + * (x + 1/2)^2 < km^2; if it is, then we increment x. + * + * We have km^2 - (x + 1/2)^2 = km^2 - x^2 - x - 1/4 + * = r - x - 1/4 + * + * and since r and x are integers, this is greater than 0 if and + * only if r > x. + * + * (There's no need to worry about tie-breaking exact halfway + * rounding cases. sqrt(k) is irrational, so none such exist.) + */ + if (r > x) + x++; + + /* + * Put the sign back on, and convert back from unsigned to int. + */ + if (sign == +1) { + return x; + } else { + /* Be a little careful to avoid compilers deciding I've just + * perpetrated signed-integer overflow. This should optimise + * down to no actual code. */ + return INT_MIN + (int)(-x - (unsigned)INT_MIN); + } +} + /* vim: set shiftwidth=4 tabstop=8: */ diff --git a/apps/plugins/puzzles/src/mosaic.c b/apps/plugins/puzzles/src/mosaic.c new file mode 100644 index 0000000000..05a339ded5 --- /dev/null +++ b/apps/plugins/puzzles/src/mosaic.c @@ -0,0 +1,1626 @@ +/* + * mosaic.c: A puzzle based on a square grid, with some of the tiles + * having clues as to how many black squares are around them. + * the purpose of the game is to find what should be on all tiles (black or + * unmarked) + * + * The game is also known as: ArtMosaico, Count and Darken, Cuenta Y Sombrea, + * Fill-a-Pix, Fill-In, Komsu Karala, Magipic, Majipiku, Mosaico, Mosaik, + * Mozaiek, Nampre Puzzle, Nurie-Puzzle, Oekaki-Pix, Voisimage. + * + * Implementation is loosely based on https://github.com/mordechaim/Mosaic, UI + * interaction is based on the range puzzle in the collection. + */ + +#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif +#include +#include +#include + +#include "puzzles.h" + +#define DEFAULT_SIZE 10 +#define DEFAULT_AGGRESSIVENESS true +#define MAX_TILES 10000 +#define MAX_TILES_ERROR "Maximum size is 10000 tiles" +#define DEFAULT_TILE_SIZE 32 +#define DEBUG_IMAGE 1 +#undef DEBUG_IMAGE +#define FLASH_TIME 0.5F +/* To enable debug prints define DEBUG_PRINTS */ + +/* Getting the coordinates and returning NULL when out of scope + * The parentheses are needed to avoid order of operations issues + */ +#define get_coords(params, array, x, y) \ + (((x) >= 0 && (y) >= 0) && ((x) < params->width && (y) < params->height)) \ + ? array + ((y)*params->width) + x \ + : NULL + +#define COORD_FROM_CELL(d) ((d * ds->tilesize) + ds->tilesize / 2) - 1 + +enum { + COL_BACKGROUND = 0, + COL_UNMARKED, + COL_GRID, + COL_MARKED, + COL_BLANK, + COL_TEXT_SOLVED, + COL_ERROR, + COL_CURSOR, + NCOLOURS, + COL_TEXT_DARK = COL_MARKED, + COL_TEXT_LIGHT = COL_BLANK +}; + +enum cell_state { + STATE_UNMARKED = 0, + STATE_MARKED = 1, + STATE_BLANK = 2, + STATE_SOLVED = 4, + STATE_ERROR = 8, + STATE_UNMARKED_ERROR = STATE_ERROR | STATE_UNMARKED, + STATE_MARKED_ERROR = STATE_ERROR | STATE_MARKED, + STATE_BLANK_ERROR = STATE_ERROR | STATE_BLANK, + STATE_BLANK_SOLVED = STATE_SOLVED | STATE_BLANK, + STATE_MARKED_SOLVED = STATE_MARKED | STATE_SOLVED, + STATE_OK_NUM = STATE_BLANK | STATE_MARKED +}; + +struct game_params { + int width; + int height; + bool aggressive; +}; + +typedef struct board_state board_state; + +typedef struct needed_list_item needed_list_item; + +struct needed_list_item { + int x, y; + needed_list_item *next; +}; + +struct game_state { + bool cheating; + int not_completed_clues; + int width; + int height; + char *cells_contents; + board_state *board; +}; + +struct board_state { + unsigned int references; + struct board_cell *actual_board; +}; + +struct board_cell { + signed char clue; + bool shown; +}; + +struct solution_cell { + signed char cell; + bool solved; + bool needed; +}; + +struct desc_cell { + char clue; + bool shown; + bool value; + bool full; + bool empty; +}; + +struct game_ui { + bool solved; + bool in_progress; + int last_x, last_y, last_state; + int cur_x, cur_y; + bool cur_visible; +}; + +struct game_drawstate { + int tilesize; + int *state; +}; + +static game_params *default_params(void) +{ + game_params *ret = snew(game_params); + + ret->width = DEFAULT_SIZE; + ret->height = DEFAULT_SIZE; + ret->aggressive = DEFAULT_AGGRESSIVENESS; + + return ret; +} + +static bool game_fetch_preset(int i, char **name, game_params **params) +{ + const int sizes[6] = { 3, 5, 10, 15, 25, 50 }; + const bool aggressiveness[6] = { true, true, true, true, true, false }; + if (i < 0 || i > 5) { + return false; + } + game_params *res = snew(game_params); + res->height = sizes[i]; + res->width = sizes[i]; + res->aggressive = aggressiveness[i]; + *params = res; + + char value[80]; + sprintf(value, "Size: %dx%d", sizes[i], sizes[i]); + *name = dupstr(value); + return true; +} + +static void free_params(game_params *params) +{ + sfree(params); +} + +static game_params *dup_params(const game_params *params) +{ + game_params *ret = snew(game_params); + *ret = *params; /* structure copy */ + return ret; +} + +static void decode_params(game_params *params, char const *string) +{ + params->width = params->height = atoi(string); + while (*string && isdigit((unsigned char)*string)) string++; + if (*string == 'x') { + string++; + params->height = atoi(string); + while (*string && isdigit((unsigned char)*string)) string++; + } + if (*string == 'h') { + string++; + params->aggressive = atoi(string); + while (*string && isdigit((unsigned char)*string)) string++; + } +} + +static char *encode_params(const game_params *params, bool full) +{ + char encoded[128]; + int pos = 0; + pos += sprintf(encoded + pos, "%dx%d", params->width, params->height); + if (full) { + if (params->aggressive != DEFAULT_AGGRESSIVENESS) + pos += sprintf(encoded + pos, "h%d", params->aggressive); + } + return dupstr(encoded); +} + +static config_item *game_configure(const game_params *params) +{ + config_item *config = snewn(4, config_item); + char value[80]; + + config[0].type = C_STRING; + config[0].name = "Height"; + sprintf(value, "%d", params->height); + config[0].u.string.sval = dupstr(value); + + config[1].type = C_STRING; + config[1].name = "Width"; + sprintf(value, "%d", params->width); + config[1].u.string.sval = dupstr(value); + + config[2].name = "Aggressive generation (longer)"; + config[2].type = C_BOOLEAN; + config[2].u.boolean.bval = params->aggressive; + + config[3].type = C_END; + + return config; +} + +static game_params *custom_params(const config_item *cfg) +{ + game_params *res = snew(game_params); + res->height = atol(cfg[0].u.string.sval); + res->width = atol(cfg[1].u.string.sval); + res->aggressive = cfg[2].u.boolean.bval; + return res; +} + +static const char *validate_params(const game_params *params, bool full) +{ + if (params->height < 3 || params->width < 3) { + return "Minimal size is 3x3"; + } + if (params->height > MAX_TILES / params->width) { + return MAX_TILES_ERROR; + } + return NULL; +} + +static bool get_pixel(const game_params *params, const bool *image, + const int x, const int y) +{ + const bool *pixel; + pixel = get_coords(params, image, x, y); + if (pixel) { + return *pixel; + } + return 0; +} + +static void populate_cell(const game_params *params, const bool *image, + const int x, const int y, bool edge, + struct desc_cell *desc) +{ + int clue = 0; + bool xEdge = false; + bool yEdge = false; + if (edge) { + if (x > 0) { + clue += get_pixel(params, image, x - 1, y); + if (y > 0) { + clue += get_pixel(params, image, x - 1, y - 1); + } + if (y < params->height - 1) { + clue += get_pixel(params, image, x - 1, y + 1); + } + } else { + xEdge = true; + } + + if (y > 0) { + clue += get_pixel(params, image, x, y - 1); + } else { + yEdge = true; + } + if (x < params->width - 1) { + clue += get_pixel(params, image, x + 1, y); + if (y > 0) { + clue += get_pixel(params, image, x + 1, y - 1); + } + if (y < params->height - 1) { + clue += get_pixel(params, image, x + 1, y + 1); + } + } else { + xEdge = true; + } + if (y < params->height - 1) { + clue += get_pixel(params, image, x, y + 1); + } else { + yEdge = true; + } + } else { + clue += get_pixel(params, image, x - 1, y - 1); + clue += get_pixel(params, image, x - 1, y); + clue += get_pixel(params, image, x - 1, y + 1); + clue += get_pixel(params, image, x, y - 1); + clue += get_pixel(params, image, x, y + 1); + clue += get_pixel(params, image, x + 1, y - 1); + clue += get_pixel(params, image, x + 1, y); + clue += get_pixel(params, image, x + 1, y + 1); + } + + desc->value = get_pixel(params, image, x, y); + clue += desc->value; + if (clue == 0) { + desc->empty = true; + desc->full = false; + } else { + desc->empty = false; + /* setting the default */ + desc->full = false; + if (clue == 9) { + desc->full = true; + } else if (edge && ((xEdge && yEdge && clue == 4) || + ((xEdge || yEdge) && clue == 6))) { + + desc->full = true; + } + } + desc->shown = true; + desc->clue = clue; +} + +static void count_around(const game_params *params, + struct solution_cell *sol, int x, int y, + int *marked, int *blank, int *total) +{ + int i, j; + struct solution_cell *curr = NULL; + (*total) = 0; + (*blank) = 0; + (*marked) = 0; + + for (i = -1; i < 2; i++) { + for (j = -1; j < 2; j++) { + curr = get_coords(params, sol, x + i, y + j); + if (curr) { + (*total)++; + if ((curr->cell & STATE_BLANK) != 0) { + (*blank)++; + } else if ((curr->cell & STATE_MARKED) != 0) { + (*marked)++; + } + } + } + } +} + +static void count_around_state(const game_state *state, int x, int y, + int *marked, int *blank, int *total) +{ + int i, j; + char *curr = NULL; + (*total) = 0; + (*blank) = 0; + (*marked) = 0; + + for (i = -1; i < 2; i++) { + for (j = -1; j < 2; j++) { + curr = get_coords(state, state->cells_contents, x + i, y + j); + if (curr) { + (*total)++; + if ((*curr & STATE_BLANK) != 0) { + (*blank)++; + } else if ((*curr & STATE_MARKED) != 0) { + (*marked)++; + } + } + } + } +} + +static void count_clues_around(const game_params *params, + struct desc_cell *desc, int x, int y, + int *clues, int *total) +{ + int i, j; + struct desc_cell *curr = NULL; + (*total) = 0; + (*clues) = 0; + + for (i = -1; i < 2; i++) { + for (j = -1; j < 2; j++) { + curr = get_coords(params, desc, x + i, y + j); + if (curr) { + (*total)++; + if (curr->shown) { + (*clues)++; + } + } + } + } +} + +static void mark_around(const game_params *params, + struct solution_cell *sol, int x, int y, int mark) +{ + int i, j; + struct solution_cell *curr; + + for (i = -1; i < 2; i++) { + for (j = -1; j < 2; j++) { + curr = get_coords(params, sol, x + i, y + j); + if (curr) { + if (curr->cell == STATE_UNMARKED) { + curr->cell = mark; + } + } + } + } +} + +static char solve_cell(const game_params *params, struct desc_cell *desc, + struct board_cell *board, struct solution_cell *sol, + int x, int y) +{ + struct desc_cell curr; + + if (desc) { + curr.shown = desc[(y * params->width) + x].shown; + curr.clue = desc[(y * params->width) + x].clue; + curr.full = desc[(y * params->width) + x].full; + curr.empty = desc[(y * params->width) + x].empty; + } else { + curr.shown = board[(y * params->width) + x].shown; + curr.clue = board[(y * params->width) + x].clue; + curr.full = false; + curr.empty = false; + } + int marked = 0, total = 0, blank = 0; + + if (sol[(y * params->width) + x].solved) { + return 0; + } + count_around(params, sol, x, y, &marked, &blank, &total); + if (curr.full && curr.shown) { + sol[(y * params->width) + x].solved = true; + if (marked + blank < total) { + sol[(y * params->width) + x].needed = true; + } + mark_around(params, sol, x, y, STATE_MARKED); + return 1; + } + if (curr.empty && curr.shown) { + sol[(y * params->width) + x].solved = true; + if (marked + blank < total) { + sol[(y * params->width) + x].needed = true; + } + mark_around(params, sol, x, y, STATE_BLANK); + return 1; + } + if (curr.shown) { + if (!sol[(y * params->width) + x].solved) { + if (marked == curr.clue) { + sol[(y * params->width) + x].solved = true; + if (total != marked + blank) { + sol[(y * params->width) + x].needed = true; + } + mark_around(params, sol, x, y, STATE_BLANK); + } else if (curr.clue == (total - blank)) { + sol[(y * params->width) + x].solved = true; + if (total != marked + blank) { + sol[(y * params->width) + x].needed = true; + } + mark_around(params, sol, x, y, STATE_MARKED); + } else if (total == marked + blank) { + return -1; + } else { + return 0; + } + return 1; + } + return 0; + } else if (total == marked + blank) { + sol[(y * params->width) + x].solved = true; + return 1; + } else { + return 0; + } +} + +static bool solve_check(const game_params *params, struct desc_cell *desc, + random_state *rs, struct solution_cell **sol_return) +{ + int x, y, i; + int board_size = params->height * params->width; + struct solution_cell *sol = snewn(board_size, struct solution_cell), + *curr_sol; + bool made_progress = true, error = false; + int solved = 0, curr = 0, shown = 0; + needed_list_item *head = NULL, *curr_needed, **needed_array; + struct desc_cell *curr_desc; + + memset(sol, 0, board_size * sizeof(*sol)); + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + curr_desc = get_coords(params, desc, x, y); + if (curr_desc->shown) { + curr_needed = snew(needed_list_item); + curr_needed->next = head; + head = curr_needed; + curr_needed->x = x; + curr_needed->y = y; + shown++; + } + } + } + needed_array = snewn(shown, needed_list_item *); + curr_needed = head; + i = 0; + while (curr_needed) { + needed_array[i] = curr_needed; + curr_needed = curr_needed->next; + i++; + } + if (rs) { + shuffle(needed_array, shown, sizeof(*needed_array), rs); + } + solved = 0; + while (solved < shown && made_progress && !error) { + made_progress = false; + for (i = 0; i < shown; i++) { + curr = solve_cell(params, desc, NULL, sol, needed_array[i]->x, + needed_array[i]->y); + if (curr < 0) { + error = true; +#ifdef DEBUG_PRINTS + printf("error in cell x=%d, y=%d\n", needed_array[i]->x, + needed_array[i]->y); +#endif + break; + } + if (curr > 0) { + solved++; + made_progress = true; + } + } + } + while (head) { + curr_needed = head; + head = curr_needed->next; + sfree(curr_needed); + } + sfree(needed_array); + solved = 0; + /* verifying all the board is solved */ + if (made_progress) { + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + curr_sol = get_coords(params, sol, x, y); + if ((curr_sol->cell & (STATE_MARKED | STATE_BLANK)) > 0) { + solved++; + } + } + } + } + if (sol_return) { + *sol_return = sol; + } else { + sfree(sol); + } + return solved == board_size; +} + +static bool solve_game_actual(const game_params *params, + struct board_cell *desc, + struct solution_cell **sol_return) +{ + int x, y; + int board_size = params->height * params->width; + struct solution_cell *sol = snewn(board_size, struct solution_cell); + bool made_progress = true, error = false; + int solved = 0, curr = 0; + + memset(sol, 0, params->height * params->width * sizeof(*sol)); + solved = 0; + while (solved < params->height * params->width && made_progress + && !error) { + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + curr = solve_cell(params, NULL, desc, sol, x, y); + if (curr < 0) { + error = true; +#ifdef DEBUG_PRINTS + printf("error in cell x=%d, y=%d\n", x, y); +#endif + break; + } + if (curr > 0) { + made_progress = true; + } + solved += curr; + } + } + } + if (sol_return) { + *sol_return = sol; + } else { + sfree(sol); + } + return solved == params->height * params->width; +} + +static void hide_clues(const game_params *params, struct desc_cell *desc, + random_state *rs) +{ + int shown, total, x, y, i; + int needed = 0; + struct desc_cell *curr; + struct solution_cell *sol = NULL, *curr_sol = NULL; + needed_list_item *head = NULL, *curr_needed, **needed_array; + +#ifdef DEBUG_PRINTS + printf("Hiding clues\n"); +#endif + solve_check(params, desc, rs, &sol); + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + count_clues_around(params, desc, x, y, &shown, &total); + curr = get_coords(params, desc, x, y); + curr_sol = get_coords(params, sol, x, y); + if (curr_sol->needed && params->aggressive) { + curr_needed = snew(needed_list_item); + curr_needed->x = x; + curr_needed->y = y; + curr_needed->next = head; + head = curr_needed; + needed++; + } else if (!curr_sol->needed) { + curr->shown = false; + } + } + } + if (params->aggressive) { + curr_needed = head; + needed_array = snewn(needed, needed_list_item *); + memset(needed_array, 0, needed * sizeof(*needed_array)); + i = 0; + while (curr_needed) { + needed_array[i] = curr_needed; + curr_needed = curr_needed->next; + i++; + } + shuffle(needed_array, needed, sizeof(*needed_array), rs); + for (i = 0; i < needed; i++) { + curr_needed = needed_array[i]; + curr = + get_coords(params, desc, curr_needed->x, curr_needed->y); + if (curr) { + curr->shown = false; + if (!solve_check(params, desc, NULL, NULL)) { +#ifdef DEBUG_PRINTS + printf("Hiding cell %d, %d not possible.\n", + curr_needed->x, curr_needed->y); +#endif + curr->shown = true; + } + sfree(curr_needed); + needed_array[i] = NULL; + } + curr_needed = NULL; + } + sfree(needed_array); + } +#ifdef DEBUG_PRINTS + printf("needed %d\n", needed); +#endif + sfree(sol); +} + +static bool start_point_check(size_t size, struct desc_cell *desc) +{ + int i; + for (i = 0; i < size; i++) { + if (desc[i].empty || desc[i].full) { + return true; + } + } + return false; +} + +static void game_get_cursor_location(const game_ui *ui, + const game_drawstate *ds, + const game_state *state, + const game_params *params, int *x, + int *y, int *w, int *h) +{ + if (ui->cur_visible) { + *x = COORD_FROM_CELL(ui->cur_x); + *y = COORD_FROM_CELL(ui->cur_y); + *w = *h = ds->tilesize; + } +} + +static void generate_image(const game_params *params, random_state *rs, + bool *image) +{ + int x, y; + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + image[(y * params->width) + x] = random_bits(rs, 1); + } + } +} + +static char *new_game_desc(const game_params *params, random_state *rs, + char **aux, bool interactive) +{ + bool *image = snewn(params->height * params->width, bool); + bool valid = false; + char *desc_string = snewn((params->height * params->width) + 1, char); + char *compressed_desc = + snewn((params->height * params->width) + 1, char); + char space_count; + + struct desc_cell *desc = + snewn(params->height * params->width, struct desc_cell); + int x, y, location_in_str; + + while (!valid) { + generate_image(params, rs, image); +#ifdef DEBUG_IMAGE + image[0] = 1; + image[1] = 1; + image[2] = 0; + image[3] = 1; + image[4] = 1; + image[5] = 0; + image[6] = 0; + image[7] = 0; + image[8] = 0; +#endif + + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + populate_cell(params, image, x, y, + x * y == 0 || y == params->height - 1 || + x == params->width - 1, + &desc[(y * params->width) + x]); + } + } + valid = + start_point_check((params->height - 1) * (params->width - 1), + desc); + if (!valid) { +#ifdef DEBUG_PRINTS + printf("Not valid, regenerating.\n"); +#endif + } else { + valid = solve_check(params, desc, rs, NULL); + if (!valid) { +#ifdef DEBUG_PRINTS + printf("Couldn't solve, regenerating."); +#endif + } else { + hide_clues(params, desc, rs); + } + } + } + location_in_str = 0; + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + if (desc[(y * params->width) + x].shown) { +#ifdef DEBUG_PRINTS + printf("%d(%d)", desc[(y * params->width) + x].value, + desc[(y * params->width) + x].clue); +#endif + sprintf(desc_string + location_in_str, "%d", + desc[(y * params->width) + x].clue); + } else { +#ifdef DEBUG_PRINTS + printf("%d( )", desc[(y * params->width) + x].value); +#endif + sprintf(desc_string + location_in_str, " "); + } + location_in_str += 1; + } +#ifdef DEBUG_PRINTS + printf("\n"); +#endif + } + location_in_str = 0; + space_count = 'a' - 1; + for (y = 0; y < params->height; y++) { + for (x = 0; x < params->width; x++) { + if (desc[(y * params->width) + x].shown) { + if (space_count >= 'a') { + sprintf(compressed_desc + location_in_str, "%c", + space_count); + location_in_str++; + space_count = 'a' - 1; + } + sprintf(compressed_desc + location_in_str, "%d", + desc[(y * params->width) + x].clue); + location_in_str++; + } else { + if (space_count <= 'z') { + space_count++; + } else { + sprintf(compressed_desc + location_in_str, "%c", + space_count); + location_in_str++; + space_count = 'a' - 1; + } + } + } + } + if (space_count >= 'a') { + sprintf(compressed_desc + location_in_str, "%c", space_count); + location_in_str++; + } + compressed_desc[location_in_str] = '\0'; +#ifdef DEBUG_PRINTS + printf("compressed_desc: %s\n", compressed_desc); +#endif + return compressed_desc; +} + +static const char *validate_desc(const game_params *params, + const char *desc) +{ + int size_dest = params->height * params->width; + int length; + length = 0; + + while (*desc != '\0') { + if (*desc >= 'a' && *desc <= 'z') { + length += *desc - 'a'; + } else if (*desc < '0' || *desc > '9') + return "Invalid character in game description"; + length++; + desc++; + } + + if (length != size_dest) { + return "Desc size mismatch"; + } + return NULL; +} + +static game_state *new_game(midend *me, const game_params *params, + const char *desc) +{ + game_state *state = snew(game_state); + char *curr_desc = dupstr(desc); + char *desc_base = curr_desc; + int dest_loc; + int spaces, total_spaces; + + state->cheating = false; + state->not_completed_clues = 0; + dest_loc = 0; + state->height = params->height; + state->width = params->width; + state->cells_contents = snewn(params->height * params->width, char); + memset(state->cells_contents, 0, params->height * params->width); + state->board = snew(board_state); + state->board->references = 1; + state->board->actual_board = + snewn(params->height * params->width, struct board_cell); + + while (*curr_desc != '\0') { + if (*curr_desc >= '0' && *curr_desc <= '9') { + state->board->actual_board[dest_loc].shown = true; + state->not_completed_clues++; + state->board->actual_board[dest_loc].clue = *curr_desc - '0'; + } else { + if (*curr_desc != ' ') { + total_spaces = *curr_desc - 'a' + 1; + } else { + total_spaces = 1; + } + spaces = 0; + while (spaces < total_spaces) { + state->board->actual_board[dest_loc].shown = false; + state->board->actual_board[dest_loc].clue = -1; + spaces++; + if (spaces < total_spaces) { + dest_loc++; + } + } + } + curr_desc++; + dest_loc++; + } + + sfree(desc_base); + return state; +} + +static game_state *dup_game(const game_state *state) +{ + game_state *ret = snew(game_state); + + ret->cheating = state->cheating; + ret->not_completed_clues = state->not_completed_clues; + ret->width = state->width; + ret->height = state->height; + ret->cells_contents = snewn(state->height * state->width, char); + memcpy(ret->cells_contents, state->cells_contents, + state->height * state->width); + ret->board = state->board; + ret->board->references++; + + return ret; +} + +static void free_game(game_state *state) +{ + sfree(state->cells_contents); + state->cells_contents = NULL; + if (state->board->references <= 1) { + sfree(state->board->actual_board); + sfree(state->board); + state->board = NULL; + } else { + state->board->references--; + } + sfree(state); +} + +static char *solve_game(const game_state *state, + const game_state *currstate, const char *aux, + const char **error) +{ + struct solution_cell *sol = NULL; + game_params param; + bool solved; + char *ret = NULL; + unsigned int curr_ret; + int i, bits, ret_loc = 1; + int size = state->width * state->height; + + param.width = state->width; + param.height = state->height; + solved = solve_game_actual(¶m, state->board->actual_board, &sol); + if (!solved) { + *error = dupstr("Could not solve this board"); + sfree(sol); + return NULL; + } + + ret = snewn((size / 4) + 3, char); + + ret[0] = 's'; + i = 0; + while (i < size) { + curr_ret = 0; + bits = 0; + while (bits < 8 && i < size) { + curr_ret <<= 1; + curr_ret |= sol[i].cell == STATE_MARKED; + i++; + bits++; + } + curr_ret <<= 8 - bits; + sprintf(ret + ret_loc, "%02x", curr_ret); + ret_loc += 2; + } + + sfree(sol); + return ret; +} + +static bool game_can_format_as_text_now(const game_params *params) +{ + return true; +} + +static char *game_text_format(const game_state *state) +{ + char *desc_string = + snewn((state->height * state->width) * 3 + 1, char); + int location_in_str = 0, x, y; + for (y = 0; y < state->height; y++) { + for (x = 0; x < state->width; x++) { + if (state->board->actual_board[(y * state->width) + x].shown) { + sprintf(desc_string + location_in_str, "|%d|", + state->board->actual_board[(y * state->width) + + x].clue); + } else { + sprintf(desc_string + location_in_str, "| |"); + } + location_in_str += 3; + } + sprintf(desc_string + location_in_str, "\n"); + location_in_str += 1; + } + return desc_string; +} + +static game_ui *new_ui(const game_state *state) +{ + game_ui *ui = snew(game_ui); + ui->last_x = -1; + ui->last_y = -1; + ui->last_state = 0; + ui->solved = false; + ui->cur_x = ui->cur_y = 0; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); + return ui; +} + +static void free_ui(game_ui *ui) +{ + sfree(ui); +} + +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) +{ +} + +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + char *cell; + + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible || state->not_completed_clues == 0) return ""; + cell = get_coords(state, state->cells_contents, ui->cur_x, ui->cur_y); + switch (*cell & STATE_OK_NUM) { + case STATE_UNMARKED: + return button == CURSOR_SELECT ? "Black" : "White"; + case STATE_MARKED: + return button == CURSOR_SELECT ? "White" : "Empty"; + case STATE_BLANK: + return button == CURSOR_SELECT ? "Empty" : "Black"; + } + } + return ""; +} + +static char *interpret_move(const game_state *state, game_ui *ui, + const game_drawstate *ds, int x, int y, + int button) +{ + int srcX = ui->last_x, srcY = ui->last_y; + int offsetX, offsetY, gameX, gameY, i; + int dirX, dirY, diff; + char move_type; + char move_desc[80]; + char *ret = NULL; + const char *cell_state; + bool changed = false; + if (state->not_completed_clues == 0 && !IS_CURSOR_MOVE(button)) { + return NULL; + } + offsetX = x - (ds->tilesize / 2); + offsetY = y - (ds->tilesize / 2); + gameX = offsetX / ds->tilesize; + gameY = offsetY / ds->tilesize; + if ((IS_MOUSE_DOWN(button) || IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) + && ((offsetX < 0) || (offsetY < 0))) + return NULL; + if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { + cell_state = + get_coords(state, state->cells_contents, gameX, gameY); + if (cell_state) { + ui->last_state = *cell_state & (STATE_BLANK | STATE_MARKED); + ui->last_state = + (ui->last_state + + ((button == + RIGHT_BUTTON) ? 2 : 1)) % (STATE_BLANK | STATE_MARKED); + } + if (button == RIGHT_BUTTON) { + /* Right button toggles twice */ + move_type = 'T'; + } else { + move_type = 't'; + } + if (gameX >= 0 && gameY >= 0 && gameX < state->width && + gameY < state->height) { + sprintf(move_desc, "%c%d,%d", move_type, gameX, gameY); + ui->last_x = gameX; + ui->last_y = gameY; + ret = dupstr(move_desc); + } else { + ui->last_x = -1; + ui->last_y = -1; + } + changed = true; + ui->cur_visible = false; + } else if (button == LEFT_DRAG || button == RIGHT_DRAG) { + move_type = 'd'; + /* allowing only drags in straight lines */ + if (gameX >= 0 && gameY >= 0 && gameX < state->width && + gameY < state->height && ui->last_x >= 0 && ui->last_y >= 0 && + (gameY == ui->last_y || gameX == ui->last_x)) { + sprintf(move_desc, "%c%d,%d,%d,%d,%d", move_type, gameX, gameY, + ui->last_x, ui->last_y, ui->last_state); + if (srcX == gameX && srcY != gameY) { + dirX = 0; + diff = srcY - gameY; + if (diff < 0) { + dirY = -1; + diff *= -1; + } else { + dirY = 1; + } + } else { + diff = srcX - gameX; + dirY = 0; + if (diff < 0) { + dirX = -1; + diff *= -1; + } else { + dirX = 1; + } + } + for (i = 0; i < diff; i++) { + cell_state = get_coords(state, state->cells_contents, + gameX + (dirX * i), + gameY + (dirY * i)); + if (cell_state && (*cell_state & STATE_OK_NUM) == 0 + && ui->last_state > 0) { + changed = true; + break; + } + } + ui->last_x = gameX; + ui->last_y = gameY; + if (changed) { + ret = dupstr(move_desc); + } + } else { + ui->last_x = -1; + ui->last_y = -1; + } + ui->cur_visible = false; + } else if (button == LEFT_RELEASE || button == RIGHT_RELEASE) { + move_type = 'e'; + if (gameX >= 0 && gameY >= 0 && gameX < state->width && + gameY < state->height && ui->last_x >= 0 && ui->last_y >= 0 && + (gameY == ui->last_y || gameX == ui->last_x)) { + sprintf(move_desc, "%c%d,%d,%d,%d,%d", move_type, gameX, gameY, + ui->last_x, ui->last_y, ui->last_state); + if (srcX == gameX && srcY != gameY) { + dirX = 0; + diff = srcY - gameY; + if (diff < 0) { + dirY = -1; + diff *= -1; + } else { + dirY = 1; + } + } else { + diff = srcX - gameX; + dirY = 0; + if (diff < 0) { + dirX = -1; + diff *= -1; + } else { + dirX = 1; + } + } + for (i = 0; i < diff; i++) { + cell_state = get_coords(state, state->cells_contents, + gameX + (dirX * i), + gameY + (dirY * i)); + if (cell_state && (*cell_state & STATE_OK_NUM) == 0 + && ui->last_state > 0) { + changed = true; + break; + } + } + if (changed) { + ret = dupstr(move_desc); + } + } else { + ui->last_x = -1; + ui->last_y = -1; + } + ui->cur_visible = false; + } else if (IS_CURSOR_MOVE(button)) { + return move_cursor(button, &ui->cur_x, &ui->cur_y, state->width, + state->height, false, &ui->cur_visible); + } else if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) { + ui->cur_x = 0; + ui->cur_y = 0; + ui->cur_visible = true; + return MOVE_UI_UPDATE; + } + + if (button == CURSOR_SELECT2) { + sprintf(move_desc, "T%d,%d", ui->cur_x, ui->cur_y); + ret = dupstr(move_desc); + } else { + /* Otherwise, treat as LEFT_BUTTON, for a single square. */ + sprintf(move_desc, "t%d,%d", ui->cur_x, ui->cur_y); + ret = dupstr(move_desc); + } + } + return ret; +} + +static void update_board_state_around(game_state *state, int x, int y) +{ + int i, j; + struct board_cell *curr; + char *curr_state; + int total; + int blank; + int marked; + + for (i = -1; i < 2; i++) { + for (j = -1; j < 2; j++) { + curr = + get_coords(state, state->board->actual_board, x + i, + y + j); + if (curr && curr->shown) { + curr_state = + get_coords(state, state->cells_contents, x + i, y + j); + count_around_state(state, x + i, y + j, &marked, &blank, + &total); + if (curr->clue == marked && (total - marked - blank) == 0) { + *curr_state &= STATE_MARKED | STATE_BLANK; + *curr_state |= STATE_SOLVED; + } else if (curr->clue < marked + || curr->clue > (total - blank)) { + *curr_state &= STATE_MARKED | STATE_BLANK; + *curr_state |= STATE_ERROR; + } else { + *curr_state &= STATE_MARKED | STATE_BLANK; + } + } + } + } +} + +static game_state *execute_move(const game_state *state, const char *move) +{ + game_state *new_state = dup_game(state); + int i = 0, x = -1, y = -1, clues_left = 0; + int srcX = -1, srcY = -1, size = state->height * state->width; + const char *p; + char *cell, sol_char; + int steps = 1, bits, sol_location, dirX, dirY, diff, + last_state = STATE_UNMARKED; + unsigned int sol_value; + struct board_cell *curr_cell; + char move_type; + int nparams = 0, move_params[5]; + + p = move; + move_type = *p++; + switch (move_type) { + case 't': + case 'T': + nparams = 2; + break; + case 'd': + case 'e': + nparams = 5; + break; + } + + for (i = 0; i < nparams; i++) { + move_params[i] = atoi(p); + while (*p && isdigit((unsigned char)*p)) p++; + if (i+1 < nparams) { + if (*p != ',') { + free_game(new_state); + return NULL; + } + p++; + } + } + + if (move_type == 't' || move_type == 'T') { + if (move_type == 'T') { + steps++; + } + x = move_params[0]; + y = move_params[1]; + if (x == -1 || y == -1) { + return new_state; + } + cell = get_coords(new_state, new_state->cells_contents, x, y); + if (cell == NULL) { + free_game(new_state); + return NULL; + } + if (*cell >= STATE_OK_NUM) { + *cell &= STATE_OK_NUM; + } + *cell = (*cell + steps) % STATE_OK_NUM; + update_board_state_around(new_state, x, y); + } else if (move_type == 's') { + new_state->not_completed_clues = 0; + new_state->cheating = true; + sol_location = 0; + bits = 0; + i = 1; + while (i < strlen(move)) { + sol_value = 0; + while (bits < 8) { + sol_value <<= 4; + sol_char = move[i]; + if (sol_char >= '0' && sol_char <= '9') { + sol_value |= sol_char - '0'; + } else { + sol_value |= (sol_char - 'a') + 10; + } + bits += 4; + i++; + } + while (bits > 0 && sol_location < size) { + if (sol_value & 0x80) { + new_state->cells_contents[sol_location] = + STATE_MARKED_SOLVED; + } else { + new_state->cells_contents[sol_location] = + STATE_BLANK_SOLVED; + } + sol_value <<= 1; + bits--; + sol_location++; + } + } + return new_state; + } else if (move_type == 'd' || move_type == 'e') { + x = move_params[0]; + y = move_params[1]; + srcX = move_params[2]; + srcY = move_params[3]; + last_state = move_params[4]; + if (srcX == x && srcY != y) { + dirX = 0; + diff = srcY - y; + if (diff < 0) { + dirY = -1; + diff *= -1; + } else { + dirY = 1; + } + } else { + diff = srcX - x; + dirY = 0; + if (diff < 0) { + dirX = -1; + diff *= -1; + } else { + dirX = 1; + } + } + for (i = 0; i < diff; i++) { + cell = get_coords(new_state, new_state->cells_contents, + x + (dirX * i), y + (dirY * i)); + if (cell == NULL) { + free_game(new_state); + return NULL; + } + if ((*cell & STATE_OK_NUM) == 0) { + *cell = last_state; + update_board_state_around(new_state, x + (dirX * i), + y + (dirY * i)); + } + } + } + for (y = 0; y < state->height; y++) { + for (x = 0; x < state->width; x++) { + cell = get_coords(new_state, new_state->cells_contents, x, y); + curr_cell = get_coords(new_state, new_state->board->actual_board, + x, y); + if (curr_cell->shown && ((*cell & STATE_SOLVED) == 0)) { + clues_left++; + } + } + } + new_state->not_completed_clues = clues_left; + return new_state; +} + +/* ---------------------------------------------------------------------- + * Drawing routines. + */ + +static void game_compute_size(const game_params *params, int tilesize, + const game_ui *ui, int *x, int *y) +{ + *x = (params->width + 1) * tilesize; + *y = (params->height + 1) * tilesize; +} + +static void game_set_size(drawing *dr, game_drawstate *ds, + const game_params *params, int tilesize) +{ + ds->tilesize = tilesize; +} + +#define COLOUR(ret, i, r, g, b) \ + ((ret[3 * (i) + 0] = (r)), (ret[3 * (i) + 1] = (g)), (ret[3 * (i) + 2] = (b))) + +static float *game_colours(frontend *fe, int *ncolours) +{ + float *ret = snewn(3 * NCOLOURS, float); + + frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]); + COLOUR(ret, COL_GRID, 0.0F, 102 / 255.0F, 99 / 255.0F); + COLOUR(ret, COL_ERROR, 1.0F, 0.0F, 0.0F); + COLOUR(ret, COL_BLANK, 236 / 255.0F, 236 / 255.0F, 236 / 255.0F); + COLOUR(ret, COL_MARKED, 20 / 255.0F, 20 / 255.0F, 20 / 255.0F); + COLOUR(ret, COL_UNMARKED, 148 / 255.0F, 196 / 255.0F, 190 / 255.0F); + COLOUR(ret, COL_TEXT_SOLVED, 100 / 255.0F, 100 / 255.0F, 100 / 255.0F); + COLOUR(ret, COL_CURSOR, 255 / 255.0F, 200 / 255.0F, 200 / 255.0F); + + *ncolours = NCOLOURS; + return ret; +} + +/* Extra flags in game_drawstate entries, not in main game state */ +#define DRAWFLAG_CURSOR 0x100 +#define DRAWFLAG_CURSOR_U 0x200 +#define DRAWFLAG_CURSOR_L 0x400 +#define DRAWFLAG_CURSOR_UL 0x800 +#define DRAWFLAG_MARGIN_R 0x1000 +#define DRAWFLAG_MARGIN_D 0x2000 + +static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) +{ + struct game_drawstate *ds = snew(game_drawstate); + int i; + + ds->tilesize = 0; + ds->state = NULL; + ds->state = snewn((state->width + 1) * (state->height + 1), int); + for (i = 0; i < (state->width + 1) * (state->height + 1); i++) + ds->state[i] = -1; + + return ds; +} + +static void game_free_drawstate(drawing *dr, game_drawstate *ds) +{ + sfree(ds->state); + sfree(ds); +} + +static void draw_cell(drawing *dr, int cell, int ts, signed char clue_val, + int x, int y) +{ + int startX = ((x * ts) + ts / 2) - 1, startY = ((y * ts) + ts / 2) - 1; + int color, text_color = COL_TEXT_DARK; + + clip(dr, startX - 1, startY - 1, ts, ts); + if (!(cell & DRAWFLAG_MARGIN_R)) + draw_rect(dr, startX - 1, startY - 1, ts, 1, + (cell & (DRAWFLAG_CURSOR | DRAWFLAG_CURSOR_U) ? + COL_CURSOR : COL_GRID)); + if (!(cell & DRAWFLAG_MARGIN_D)) + draw_rect(dr, startX - 1, startY - 1, 1, ts, + (cell & (DRAWFLAG_CURSOR | DRAWFLAG_CURSOR_L) ? + COL_CURSOR : COL_GRID)); + if (cell & DRAWFLAG_CURSOR_UL) + draw_rect(dr, startX - 1, startY - 1, 1, 1, COL_CURSOR); + + if (!(cell & (DRAWFLAG_MARGIN_R | DRAWFLAG_MARGIN_D))) { + if (cell & STATE_MARKED) { + color = COL_MARKED; + text_color = COL_TEXT_LIGHT; + } else if (cell & STATE_BLANK) { + text_color = COL_TEXT_DARK; + color = COL_BLANK; + } else { + text_color = COL_TEXT_DARK; + color = COL_UNMARKED; + } + if (cell & STATE_ERROR) { + text_color = COL_ERROR; + } else if (cell & STATE_SOLVED) { + text_color = COL_TEXT_SOLVED; + } + + draw_rect(dr, startX, startY, ts - 1, ts - 1, color); + if (clue_val >= 0) { + char clue[80]; + sprintf(clue, "%d", clue_val); + draw_text(dr, startX + ts / 2, startY + ts / 2, 1, ts * 3 / 5, + ALIGN_VCENTRE | ALIGN_HCENTRE, text_color, clue); + } + } + + unclip(dr); + draw_update(dr, startX - 1, startY - 1, ts, ts); +} + +static void game_redraw(drawing *dr, game_drawstate *ds, + const game_state *oldstate, + const game_state *state, int dir, + const game_ui *ui, float animtime, + float flashtime) +{ + int x, y; + char status[80]; + signed char clue_val; + bool flashing = (flashtime > 0 && (flashtime <= FLASH_TIME / 3 || + flashtime > 2*FLASH_TIME / 3)); + + for (y = 0; y <= state->height; y++) { + for (x = 0; x <= state->width; x++) { + bool inbounds = x < state->width && y < state->height; + int cell = (inbounds ? + state->cells_contents[(y * state->width) + x] : 0); + if (x == state->width) + cell |= DRAWFLAG_MARGIN_R; + if (y == state->height) + cell |= DRAWFLAG_MARGIN_D; + if (flashing) + cell ^= (STATE_BLANK | STATE_MARKED); + if (ui->cur_visible) { + if (ui->cur_x == x && ui->cur_y == y) + cell |= DRAWFLAG_CURSOR; + if (ui->cur_x == x-1 && ui->cur_y == y) + cell |= DRAWFLAG_CURSOR_L; + if (ui->cur_x == x && ui->cur_y == y-1) + cell |= DRAWFLAG_CURSOR_U; + if (ui->cur_x == x-1 && ui->cur_y == y-1) + cell |= DRAWFLAG_CURSOR_UL; + } + + if (inbounds && + state->board->actual_board[(y * state->width) + x].shown) { + clue_val = state->board->actual_board[ + (y * state->width) + x].clue; + } else { + clue_val = -1; + } + + if (ds->state[(y * (state->width+1)) + x] != cell) { + draw_cell(dr, cell, ds->tilesize, clue_val, x, y); + ds->state[(y * (state->width+1)) + x] = cell; + } + } + } + sprintf(status, "Clues left: %d", state->not_completed_clues); + if (state->not_completed_clues == 0 && !state->cheating) { + sprintf(status, "COMPLETED!"); + } else if (state->not_completed_clues == 0 && state->cheating) { + sprintf(status, "Auto solved"); + } + status_bar(dr, status); +} + +static float game_anim_length(const game_state *oldstate, + const game_state *newstate, int dir, + game_ui *ui) +{ + return 0.0F; +} + +static float game_flash_length(const game_state *oldstate, + const game_state *newstate, int dir, + game_ui *ui) +{ + if (!oldstate->cheating && oldstate->not_completed_clues > 0 && + newstate->not_completed_clues == 0) { + return FLASH_TIME; + } + return 0.0F; +} + +static int game_status(const game_state *state) +{ + if (state->not_completed_clues == 0) + return +1; + return 0; +} + +#ifdef COMBINED +#define thegame mosaic +#endif + +const struct game thegame = { + "Mosaic", "games.mosaic", "mosaic", + default_params, + game_fetch_preset, NULL, + decode_params, + encode_params, + free_params, + dup_params, + true, game_configure, custom_params, + validate_params, + new_game_desc, + validate_desc, + new_game, + dup_game, + free_game, + true, solve_game, + true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ + new_ui, + free_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ + NULL, /* game_request_keys */ + game_changed_state, + current_key_label, + interpret_move, + execute_move, + DEFAULT_TILE_SIZE, game_compute_size, game_set_size, + game_colours, + game_new_drawstate, + game_free_drawstate, + game_redraw, + game_anim_length, + game_flash_length, + game_get_cursor_location, + game_status, + false, false, NULL, NULL, /* print_size, print */ + true, /* wants_statusbar */ + false, NULL, /* timing_state */ + 0, /* flags */ +}; diff --git a/apps/plugins/puzzles/src/nestedvm.c b/apps/plugins/puzzles/src/nestedvm.c index 947abe0fae..0a9fdbcfed 100644 --- a/apps/plugins/puzzles/src/nestedvm.c +++ b/apps/plugins/puzzles/src/nestedvm.c @@ -206,7 +206,7 @@ int jcallback_key_event(int x, int y, int keyval) if (fe->ox == -1) return 1; if (keyval >= 0 && - !midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval)) + midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval) == PKR_QUIT) return 42; return 1; } @@ -217,7 +217,7 @@ int jcallback_resize(int width, int height) int x, y; x = width; y = height; - midend_size(fe->me, &x, &y, true); + midend_size(fe->me, &x, &y, true, 1.0); fe->ox = (width - x) / 2; fe->oy = (height - y) / 2; fe->w = x; @@ -323,7 +323,7 @@ static bool get_config(frontend *fe, int which) int jcallback_newgame_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME)) + if (midend_process_key(fe->me, 0, 0, UI_NEWGAME) == PKR_QUIT) return 42; return 0; } @@ -331,7 +331,7 @@ int jcallback_newgame_event(void) int jcallback_undo_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_UNDO)) + if (midend_process_key(fe->me, 0, 0, UI_UNDO) == PKR_QUIT) return 42; return 0; } @@ -339,7 +339,7 @@ int jcallback_undo_event(void) int jcallback_redo_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_REDO)) + if (midend_process_key(fe->me, 0, 0, UI_REDO) == PKR_QUIT) return 42; return 0; } @@ -347,7 +347,7 @@ int jcallback_redo_event(void) int jcallback_quit_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_QUIT)) + if (midend_process_key(fe->me, 0, 0, UI_QUIT) == PKR_QUIT) return 42; return 0; } @@ -358,7 +358,7 @@ static void resize_fe(frontend *fe) x = INT_MAX; y = INT_MAX; - midend_size(fe->me, &x, &y, false); + midend_size(fe->me, &x, &y, false, 1.0); _call_java(3, x, y, 0); } diff --git a/apps/plugins/puzzles/src/net.R b/apps/plugins/puzzles/src/net.R deleted file mode 100644 index 8e98216e03..0000000000 --- a/apps/plugins/puzzles/src/net.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -NET_EXTRA = tree234 dsf findloop - -net : [X] GTK COMMON net NET_EXTRA net-icon|no-icon - -# The Windows Net shouldn't be called `net.exe' since Windows -# already has a reasonably important utility program by that name! -netgame : [G] WINDOWS COMMON net NET_EXTRA net.res|noicon.res - -ALL += net[COMBINED] NET_EXTRA - -!begin am gtk -GAMES += net -!end - -!begin >list.c - A(net) \ -!end - -!begin >gamedesc.txt -net:netgame.exe:Net:Network jigsaw puzzle:Rotate each tile to reassemble the network. -!end diff --git a/apps/plugins/puzzles/src/net.c b/apps/plugins/puzzles/src/net.c index d3032b6fe2..3200253ef9 100644 --- a/apps/plugins/puzzles/src/net.c +++ b/apps/plugins/puzzles/src/net.c @@ -7,7 +7,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -249,10 +254,7 @@ static char *encode_params(const game_params *params, bool full) if (params->wrapping) ret[len++] = 'w'; if (full && params->barrier_probability) - { - len += sprintf(ret+len, "b"); - len += ftoa(ret + len, params->barrier_probability); - } + len += sprintf(ret+len, "b%g", params->barrier_probability); if (full && !params->unique) ret[len++] = 'a'; assert(len < lenof(ret)); @@ -284,7 +286,7 @@ static config_item *game_configure(const game_params *params) ret[3].name = "Barrier probability"; ret[3].type = C_STRING; - ftoa(buf, params->barrier_probability); + sprintf(buf, "%g", params->barrier_probability); ret[3].u.string.sval = dupstr(buf); ret[4].name = "Ensure unique solution"; @@ -316,6 +318,8 @@ static const char *validate_params(const game_params *params, bool full) return "Width and height must both be greater than zero"; if (params->width <= 1 && params->height <= 1) return "At least one of width and height must be greater than one"; + if (params->width > INT_MAX / params->height) + return "Width times height must not be unreasonably large"; if (params->barrier_probability < 0) return "Barrier probability may not be negative"; if (params->barrier_probability > 1) @@ -458,7 +462,7 @@ static int net_solver(int w, int h, unsigned char *tiles, unsigned char *tilestate; unsigned char *edgestate; int *deadends; - int *equivalence; + DSF *equivalence; struct todo *todo; int i, j, x, y; int area; @@ -543,7 +547,7 @@ static int net_solver(int w, int h, unsigned char *tiles, * classes) by finding the representative of each tile and * setting equivalence[one]=the_other. */ - equivalence = snew_dsf(w * h); + equivalence = dsf_new(w * h); /* * On a non-wrapping grid, we instantly know that all the edges @@ -828,7 +832,7 @@ static int net_solver(int w, int h, unsigned char *tiles, sfree(tilestate); sfree(edgestate); sfree(deadends); - sfree(equivalence); + dsf_free(equivalence); return j; } @@ -1131,7 +1135,8 @@ static void perturb(int w, int h, unsigned char *tiles, bool wrapping, static int *compute_loops_inner(int w, int h, bool wrapping, const unsigned char *tiles, - const unsigned char *barriers); + const unsigned char *barriers, + bool include_unlocked_squares); static char *new_game_desc(const game_params *params, random_state *rs, char **aux, bool interactive) @@ -1460,7 +1465,8 @@ static char *new_game_desc(const game_params *params, random_state *rs, */ prev_loopsquares = w*h+1; while (1) { - loops = compute_loops_inner(w, h, params->wrapping, tiles, NULL); + loops = compute_loops_inner(w, h, params->wrapping, tiles, NULL, + true); this_loopsquares = 0; for (i = 0; i < w*h; i++) { if (loops[i]) { @@ -1848,16 +1854,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return ret; } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - /* ---------------------------------------------------------------------- * Utility routine. */ @@ -1878,6 +1874,8 @@ static unsigned char *compute_active(const game_state *state, int cx, int cy) active = snewn(state->width * state->height, unsigned char); memset(active, 0, state->width * state->height); + assert(0 <= cx && cx < state->width); + assert(0 <= cy && cy < state->height); /* * We only store (x,y) pairs in todo, but it's easier to reuse * xyd_cmp and just store direction 0 every time. @@ -1923,6 +1921,7 @@ struct net_neighbour_ctx { int w, h; const unsigned char *tiles, *barriers; int i, n, neighbours[4]; + bool include_unlocked_squares; }; static int net_neighbour(int vertex, void *vctx) { @@ -1943,6 +1942,9 @@ static int net_neighbour(int vertex, void *vctx) continue; OFFSETWH(x1, y1, x, y, dir, ctx->w, ctx->h); v1 = y1 * ctx->w + x1; + if (!ctx->include_unlocked_squares && + !(tile & ctx->tiles[v1] & LOCKED)) + continue; if (ctx->tiles[v1] & F(dir)) ctx->neighbours[ctx->n++] = v1; } @@ -1956,32 +1958,39 @@ static int net_neighbour(int vertex, void *vctx) static int *compute_loops_inner(int w, int h, bool wrapping, const unsigned char *tiles, - const unsigned char *barriers) + const unsigned char *barriers, + bool include_unlocked_squares) { struct net_neighbour_ctx ctx; struct findloopstate *fls; int *loops; - int x, y; + int x, y, v; fls = findloop_new_state(w*h); ctx.w = w; ctx.h = h; ctx.tiles = tiles; ctx.barriers = barriers; + ctx.include_unlocked_squares = include_unlocked_squares; findloop_run(fls, w*h, net_neighbour, &ctx); loops = snewn(w*h, int); for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - int x1, y1, dir; + int x1, y1, v1, dir; int flags = 0; + v = y * w + x; for (dir = 1; dir < 0x10; dir <<= 1) { - if ((tiles[y*w+x] & dir) && + if ((tiles[v] & dir) && !(barriers && (barriers[y*w+x] & dir))) { OFFSETWH(x1, y1, x, y, dir, w, h); - if ((tiles[y1*w+x1] & F(dir)) && + v1 = y1 * w + x1; + if (!include_unlocked_squares && + !(tiles[v] & tiles[v1] & LOCKED)) + continue; + if ((tiles[v1] & F(dir)) && findloop_is_loop_edge(fls, y*w+x, y1*w+x1)) flags |= ERR(dir); } @@ -1994,10 +2003,12 @@ static int *compute_loops_inner(int w, int h, bool wrapping, return loops; } -static int *compute_loops(const game_state *state) +static int *compute_loops(const game_state *state, + bool include_unlocked_squares) { return compute_loops_inner(state->width, state->height, state->wrapping, - state->tiles, state->imm->barriers); + state->tiles, state->imm->barriers, + include_unlocked_squares); } struct game_ui { @@ -2010,6 +2021,8 @@ struct game_ui { int dragtilex, dragtiley, dragstartx, dragstarty; bool dragged; #endif + + bool unlocked_loops; }; static game_ui *new_ui(const game_state *state) @@ -2017,20 +2030,31 @@ static game_ui *new_ui(const game_state *state) void *seed; int seedsize; game_ui *ui = snew(game_ui); - ui->org_x = ui->org_y = 0; - ui->cur_x = ui->cx = state->width / 2; - ui->cur_y = ui->cy = state->height / 2; - ui->cur_visible = false; - get_random_seed(&seed, &seedsize); - ui->rs = random_new(seed, seedsize); - sfree(seed); + + ui->unlocked_loops = true; + + if (state) { + ui->org_x = ui->org_y = 0; + ui->cur_x = ui->cx = state->width / 2; + ui->cur_y = ui->cy = state->height / 2; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); + get_random_seed(&seed, &seedsize); + ui->rs = random_new(seed, seedsize); + sfree(seed); +#ifdef USE_DRAGGING + ui->dragstartx = ui->dragstarty = ui->dragtilex = ui->dragtiley = -1; +#endif + } else { + ui->rs = NULL; + } return ui; } static void free_ui(game_ui *ui) { - random_free(ui->rs); + if (ui->rs) + random_free(ui->rs); sfree(ui); } @@ -2045,10 +2069,45 @@ static char *encode_ui(const game_ui *ui) return dupstr(buf); } -static void decode_ui(game_ui *ui, const char *encoding) +static void decode_ui(game_ui *ui, const char *encoding, + const game_state *state) { - sscanf(encoding, "O%d,%d;C%d,%d", - &ui->org_x, &ui->org_y, &ui->cx, &ui->cy); + int org_x, org_y, cx, cy; + + if (sscanf(encoding, "O%d,%d;C%d,%d", &org_x, &org_y, &cx, &cy) == 4) { + if (0 <= org_x && org_x < state->width && + 0 <= org_y && org_y < state->height) { + ui->org_x = org_x; + ui->org_y = org_y; + } + if (0 <= cx && cx < state->width && + 0 <= cy && cy < state->height) { + ui->cx = cx; + ui->cy = cy; + } + } +} + +static config_item *get_prefs(game_ui *ui) +{ + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Highlight loops involving unlocked squares"; + ret[0].kw = "unlocked-loops"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->unlocked_loops; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; +} + +static void set_prefs(game_ui *ui, const config_item *cfg) +{ + ui->unlocked_loops = cfg[0].u.boolean.bval; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -2056,8 +2115,19 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, { } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (tile(state, ui->cur_x, ui->cur_y) & LOCKED) { + if (button == CURSOR_SELECT2) return "Unlock"; + } else { + if (button == CURSOR_SELECT) return "Rotate"; + if (button == CURSOR_SELECT2) return "Lock"; + } + return ""; +} + struct game_drawstate { - bool started; int width, height; int tilesize; unsigned long *visible, *to_draw; @@ -2078,7 +2148,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, MOVE_ORIGIN, MOVE_SOURCE, MOVE_ORIGIN_AND_SOURCE, MOVE_CURSOR } action; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); nullret = NULL; action = NONE; @@ -2094,7 +2164,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->cur_visible) { ui->cur_visible = false; - nullret = UI_UPDATE; + nullret = MOVE_UI_UPDATE; } /* @@ -2102,12 +2172,22 @@ static char *interpret_move(const game_state *state, game_ui *ui, */ x -= WINDOW_OFFSET + LINE_THICK; y -= WINDOW_OFFSET + LINE_THICK; - if (x < 0 || y < 0) - return nullret; tx = x / TILE_SIZE; ty = y / TILE_SIZE; - if (tx >= state->width || ty >= state->height) + if (x < 0 || y < 0 || tx >= state->width || ty >= state->height) { +#ifdef USE_DRAGGING + if (IS_MOUSE_DOWN(button)) { + ui->dragstartx = ui->dragstarty = ui->dragtilex = ui->dragtiley = -1; + return nullret; + } + /* + * else: Despite the mouse moving off the grid, let drags and releases + * continue to manipulate the tile they started from. + */ +#else return nullret; +#endif + } /* Transform from physical to game coords */ tx = (tx + ui->org_x) % state->width; ty = (ty + ui->org_y) % state->height; @@ -2145,6 +2225,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, || button == RIGHT_DRAG #endif ) { + if (ui->dragtilex < 0) + return nullret; + /* * Find the new drag point and see if it necessitates a * rotation. @@ -2198,7 +2281,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, || button == RIGHT_RELEASE #endif ) { - if (!ui->dragged) { + if (!ui->dragged && ui->dragtilex >= 0) { /* * There was a click but no perceptible drag: * revert to single-click behaviour. @@ -2334,7 +2417,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, OFFSET(ui->cur_x, ui->cur_y, ui->cur_x, ui->cur_y, dir, state); ui->cur_visible = true; } - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { return NULL; } @@ -2444,7 +2527,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) game_drawstate *ds = snew(game_drawstate); int i, ncells; - ds->started = false; ds->width = state->width; ds->height = state->height; ncells = (state->width+2) * (state->height+2); @@ -2464,11 +2546,12 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) static void game_free_drawstate(drawing *dr, game_drawstate *ds) { sfree(ds->visible); + sfree(ds->to_draw); sfree(ds); } static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2605,8 +2688,8 @@ static void draw_wires(drawing *dr, int cx, int cy, int radius, for (i = 0; i < npoints; i++) { rotated_coords(&xf, &yf, matrix, cx, cy, fpoints[2*i], fpoints[2*i+1]); - points[2*i] = 0.5 + xf; - points[2*i+1] = 0.5 + yf; + points[2*i] = 0.5F + xf; + points[2*i+1] = 0.5F + yf; } draw_polygon(dr, points, npoints, colour, colour); @@ -2746,8 +2829,8 @@ static void draw_tile(drawing *dr, game_drawstate *ds, int x, int y, * rotated by an arbitrary angle about that centre point. */ if (tile & TILE_ROTATING) { - matrix[0] = (float)cos(angle * PI / 180.0); - matrix[2] = (float)sin(angle * PI / 180.0); + matrix[0] = (float)cos(angle * (float)PI / 180.0F); + matrix[2] = (float)sin(angle * (float)PI / 180.0F); } else { matrix[0] = 1.0F; matrix[2] = 0.0F; @@ -2786,8 +2869,8 @@ static void draw_tile(drawing *dr, game_drawstate *ds, int x, int y, float x, y; rotated_coords(&x, &y, matrix, cx, cy, boxr * points[i], boxr * points[i+1]); - points[i] = x + 0.5; - points[i+1] = y + 0.5; + points[i] = x + 0.5F; + points[i+1] = y + 0.5F; } draw_polygon(dr, points, 4, col, COL_WIRE); @@ -2841,23 +2924,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int *loops; float angle = 0.0; - /* - * Clear the screen on our first call. - */ - if (!ds->started) { - int w, h; - game_params params; - - ds->started = true; - - params.width = ds->width; - params.height = ds->height; - game_compute_size(¶ms, TILE_SIZE, &w, &h); - - draw_rect(dr, 0, 0, w, h, COL_BACKGROUND); - draw_update(dr, 0, 0, w, h); - } - tx = ty = -1; last_rotate_dir = dir==-1 ? oldstate->last_rotate_dir : state->last_rotate_dir; @@ -2888,7 +2954,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, * of barriers. */ active = compute_active(state, ui->cx, ui->cy); - loops = compute_loops(state); + loops = compute_loops(state, ui->unlocked_loops); for (dy = -1; dy < ds->height+1; dy++) { for (dx = -1; dx < ds->width+1; dx++) { @@ -3109,19 +3175,15 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 8mm squares by default. */ - game_compute_size(params, 800, &pw, &ph); + game_compute_size(params, 800, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } @@ -3172,7 +3234,8 @@ static void draw_diagram(drawing *dr, game_drawstate *ds, int x, int y, } } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->width, h = state->height; int ink = print_mono_colour(dr, 0); @@ -3269,13 +3332,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + get_prefs, set_prefs, new_ui, free_ui, encode_ui, decode_ui, NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3289,6 +3354,6 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/netslide.R b/apps/plugins/puzzles/src/netslide.R deleted file mode 100644 index ecfe7c3df8..0000000000 --- a/apps/plugins/puzzles/src/netslide.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -NETSLIDE_EXTRA = tree234 - -netslide : [X] GTK COMMON netslide NETSLIDE_EXTRA netslide-icon|no-icon - -netslide : [G] WINDOWS COMMON netslide NETSLIDE_EXTRA netslide.res|noicon.res - -ALL += netslide[COMBINED] NETSLIDE_EXTRA - -!begin am gtk -GAMES += netslide -!end - -!begin >list.c - A(netslide) \ -!end - -!begin >gamedesc.txt -netslide:netslide.exe:Netslide:Toroidal sliding network puzzle:Slide a row at a time to reassemble the network. -!end diff --git a/apps/plugins/puzzles/src/netslide.c b/apps/plugins/puzzles/src/netslide.c index 14af2a689d..4e6e82b39f 100644 --- a/apps/plugins/puzzles/src/netslide.c +++ b/apps/plugins/puzzles/src/netslide.c @@ -8,7 +8,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -242,10 +247,7 @@ static char *encode_params(const game_params *params, bool full) if (params->wrapping) ret[len++] = 'w'; if (full && params->barrier_probability) - { - len += sprintf(ret+len, "b"); - len += ftoa(ret + len, params->barrier_probability); - } + len += sprintf(ret+len, "b%g", params->barrier_probability); /* Shuffle limit is part of the limited parameters, because we have to * provide the target move count. */ if (params->movetarget) @@ -279,7 +281,7 @@ static config_item *game_configure(const game_params *params) ret[3].name = "Barrier probability"; ret[3].type = C_STRING; - ftoa(buf, params->barrier_probability); + sprintf(buf, "%g", params->barrier_probability); ret[3].u.string.sval = dupstr(buf); ret[4].name = "Number of shuffling moves"; @@ -310,6 +312,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->width <= 1 || params->height <= 1) return "Width and height must both be greater than one"; + if (params->width > INT_MAX / params->height) + return "Width times height must not be unreasonably large"; if (params->barrier_probability < 0) return "Barrier probability may not be negative"; if (params->barrier_probability > 1) @@ -895,16 +899,6 @@ static char *solve_game(const game_state *state, const game_state *currstate, return dupstr(aux); } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - /* ---------------------------------------------------------------------- * Utility routine. */ @@ -981,7 +975,7 @@ static game_ui *new_ui(const game_state *state) game_ui *ui = snew(game_ui); ui->cur_x = 0; ui->cur_y = -1; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -991,15 +985,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - /* ---------------------------------------------------------------------- * Process a move. */ @@ -1009,7 +994,9 @@ static void slide_row_int(int w, int h, unsigned char *tiles, int dir, int row) int x = dir > 0 ? -1 : w; int tx = x + dir; int n = w - 1; - unsigned char endtile = tiles[row * w + tx]; + unsigned char endtile; + assert(0 <= tx && tx < w); + endtile = tiles[row * w + tx]; do { x = tx; tx = (x + dir + w) % w; @@ -1023,7 +1010,9 @@ static void slide_col_int(int w, int h, unsigned char *tiles, int dir, int col) int y = dir > 0 ? -1 : h; int ty = y + dir; int n = h - 1; - unsigned char endtile = tiles[ty * w + col]; + unsigned char endtile; + assert(0 <= ty && ty < h); + endtile = tiles[ty * w + col]; do { y = ty; ty = (y + dir + h) % h; @@ -1055,6 +1044,14 @@ struct game_drawstate { int cur_x, cur_y; }; +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cur_visible) + return "Slide"; + return ""; +} + static char *interpret_move(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) @@ -1063,7 +1060,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int dx, dy; char buf[80]; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (IS_CURSOR_MOVE(button)) { int cpos, diff = 0; @@ -1078,7 +1075,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { @@ -1092,7 +1089,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } else { /* 'click' when cursor is invisible just makes cursor visible. */ ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else return NULL; @@ -1136,7 +1133,9 @@ static game_state *execute_move(const game_state *from, const char *move) if ((move[0] == 'C' || move[0] == 'R') && sscanf(move+1, "%d,%d", &c, &d) == 2 && - c >= 0 && c < (move[0] == 'C' ? from->width : from->height)) { + c >= 0 && c < (move[0] == 'C' ? from->width : from->height) && + d <= (move[0] == 'C' ? from->height : from->width) && + d >= -(move[0] == 'C' ? from->height : from->width) && d != 0) { col = (move[0] == 'C'); } else if (move[0] == 'S' && strlen(move) == from->width * from->height + 1) { @@ -1226,7 +1225,7 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) } static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1490,7 +1489,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state, vx = (dy ? 1 : 0); vy = (dx ? 1 : 0); - if (xshift == 0.0 && yshift == 0.0 && (tile & dir)) { + if (xshift == 0.0F && yshift == 0.0F && (tile & dir)) { /* * If we are fully connected to the other tile, we must * draw right across the tile border. (We can use our @@ -1594,22 +1593,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int cur_x = -1, cur_y = -1; /* - * Clear the screen and draw the exterior barrier lines if this - * is our first call. + * Draw the exterior barrier lines if this is our first call. */ if (!ds->started) { int phase; ds->started = true; - draw_rect(dr, 0, 0, - BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * state->width + TILE_BORDER, - BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * state->height + TILE_BORDER, - COL_BACKGROUND); - draw_update(dr, 0, 0, - BORDER * 2 + WINDOW_OFFSET*2 + TILE_SIZE*state->width + TILE_BORDER, - BORDER * 2 + WINDOW_OFFSET*2 + TILE_SIZE*state->height + TILE_BORDER); - for (phase = 0; phase < 2; phase++) { for (x = 0; x < ds->width; x++) { @@ -1703,7 +1693,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, /* * Draw any tile which differs from the way it was last drawn. */ - if (xshift != 0.0 || yshift != 0.0) { + if (xshift != 0.0F || yshift != 0.0F) { active = compute_active(state, state->last_move_row, state->last_move_col); } else { @@ -1849,19 +1839,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return false; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame netslide #endif @@ -1882,13 +1859,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1900,9 +1879,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/no-icon.c b/apps/plugins/puzzles/src/no-icon.c index 114b2c57c7..5091dca426 100644 --- a/apps/plugins/puzzles/src/no-icon.c +++ b/apps/plugins/puzzles/src/no-icon.c @@ -4,5 +4,7 @@ * `icons' subdirectory, when they're absent. */ +#include "gtk.h" + const char *const *const xpm_icons[] = { 0 }; const int n_xpm_icons = 0; diff --git a/apps/plugins/puzzles/src/nullfe.c b/apps/plugins/puzzles/src/nullfe.c index 7cba4e0c23..9a57832b6e 100644 --- a/apps/plugins/puzzles/src/nullfe.c +++ b/apps/plugins/puzzles/src/nullfe.c @@ -9,13 +9,21 @@ #include "puzzles.h" void frontend_default_colour(frontend *fe, float *output) {} +void get_random_seed(void **randseed, int *randseedsize) +{ char *c = snewn(1, char); *c = 0; *randseed = c; *randseedsize = 1; } +void deactivate_timer(frontend *fe) {} +void activate_timer(frontend *fe) {} +struct drawing { char dummy; }; +drawing *drawing_new(const drawing_api *api, midend *me, void *handle) +{ return snew(drawing); } +void drawing_free(drawing *dr) { sfree(dr); } void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, int align, int colour, const char *text) {} void draw_rect(drawing *dr, int x, int y, int w, int h, int colour) {} void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) {} void draw_thick_line(drawing *dr, float thickness, float x1, float y1, float x2, float y2, int colour) {} -void draw_polygon(drawing *dr, int *coords, int npoints, +void draw_polygon(drawing *dr, const int *coords, int npoints, int fillcolour, int outlinecolour) {} void draw_circle(drawing *dr, int cx, int cy, int radius, int fillcolour, int outlinecolour) {} @@ -26,8 +34,9 @@ void unclip(drawing *dr) {} void start_draw(drawing *dr) {} void draw_update(drawing *dr, int x, int y, int w, int h) {} void end_draw(drawing *dr) {} -blitter *blitter_new(drawing *dr, int w, int h) {return NULL;} -void blitter_free(drawing *dr, blitter *bl) {} +struct blitter { char dummy; }; +blitter *blitter_new(drawing *dr, int w, int h) { return snew(blitter); } +void blitter_free(drawing *dr, blitter *bl) { sfree(bl); } void blitter_save(drawing *dr, blitter *bl, int x, int y) {} void blitter_load(drawing *dr, blitter *bl, int x, int y) {} int print_mono_colour(drawing *dr, int grey) { return 0; } @@ -41,14 +50,9 @@ int print_rgb_hatched_colour(drawing *dr, float r, float g, float b, int hatch) { return 0; } void print_line_width(drawing *dr, int width) {} void print_line_dotted(drawing *dr, bool dotted) {} -void midend_supersede_game_desc(midend *me, const char *desc, - const char *privdesc) {} void status_bar(drawing *dr, const char *text) {} -struct preset_menu *preset_menu_new(void) {return NULL;} -struct preset_menu *preset_menu_add_submenu(struct preset_menu *parent, - char *title) {return NULL;} -void preset_menu_add_preset(struct preset_menu *parent, - char *title, game_params *params) {} +void document_add_puzzle(document *doc, const game *game, game_params *par, + game_ui *ui, game_state *st, game_state *st2) {} void fatal(const char *fmt, ...) { diff --git a/apps/plugins/puzzles/src/nullgame.R b/apps/plugins/puzzles/src/nullgame.R deleted file mode 100644 index 41bdb85d57..0000000000 --- a/apps/plugins/puzzles/src/nullgame.R +++ /dev/null @@ -1,12 +0,0 @@ -# -*- makefile -*- - -# The `nullgame' source file is a largely blank one, which contains -# all the correct function definitions to compile and link, but -# which defines the null game in which nothing is ever drawn and -# there are no valid moves. Its main purpose is to act as a -# template for writing new game definition source files. I include -# it in the Makefile because it will be worse than useless if it -# ever fails to compile, so it's important that it should actually -# be built on a regular basis. -nullgame : [X] GTK COMMON nullgame nullgame-icon|no-icon -nullgame : [G] WINDOWS COMMON nullgame nullgame.res|noicon.res diff --git a/apps/plugins/puzzles/src/nullgame.c b/apps/plugins/puzzles/src/nullgame.c index d923bc8710..c1c2ed18fd 100644 --- a/apps/plugins/puzzles/src/nullgame.c +++ b/apps/plugins/puzzles/src/nullgame.c @@ -16,7 +16,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -68,16 +72,6 @@ static char *encode_params(const game_params *params, bool full) return dupstr("FIXME"); } -static config_item *game_configure(const game_params *params) -{ - return NULL; -} - -static game_params *custom_params(const config_item *cfg) -{ - return NULL; -} - static const char *validate_params(const game_params *params, bool full) { return NULL; @@ -118,22 +112,6 @@ static void free_game(game_state *state) sfree(state); } -static char *solve_game(const game_state *state, const game_state *currstate, - const char *aux, const char **error) -{ - return NULL; -} - -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - static game_ui *new_ui(const game_state *state) { return NULL; @@ -143,15 +121,6 @@ static void free_ui(game_ui *ui) { } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -179,7 +148,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = *y = 10 * tilesize; /* FIXME */ } @@ -220,14 +189,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int dir, const game_ui *ui, float animtime, float flashtime) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all games - * should start by drawing a big background-colour rectangle - * covering the whole window. - */ - draw_rect(dr, 0, 0, 10*ds->tilesize, 10*ds->tilesize, COL_BACKGROUND); - draw_update(dr, 0, 0, 10*ds->tilesize, 10*ds->tilesize); } static float game_anim_length(const game_state *oldstate, @@ -255,19 +216,6 @@ static int game_status(const game_state *state) return 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame nullgame #endif @@ -280,21 +228,23 @@ const struct game thegame = { encode_params, free_params, dup_params, - false, game_configure, custom_params, + false, NULL, NULL, /* configure, custom_params */ validate_params, new_game_desc, validate_desc, new_game, dup_game, free_game, - false, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, /* solve */ + false, NULL, NULL, /* can_format_as_text_now, text_format */ + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, 20 /* FIXME */, game_compute_size, game_set_size, @@ -306,8 +256,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/obfusc.c b/apps/plugins/puzzles/src/obfusc.c deleted file mode 100644 index c62189c3ad..0000000000 --- a/apps/plugins/puzzles/src/obfusc.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Stand-alone tool to access the Puzzles obfuscation algorithm. - * - * To deobfuscate, use "obfusc -d": - * - * obfusc -d reads binary data from stdin, writes to stdout - * obfusc -d works on the given hex string instead of stdin - * obfusc -d -h writes a hex string instead of binary to stdout - * - * To obfuscate, "obfusc -e": - * - * obfusc -e reads binary from stdin, writes hex to stdout - * obfusc -e works on the given hex string instead of stdin - * obfusc -e -b writes binary instead of text to stdout - * - * The default output format is hex for -e and binary for -d - * because that's the way obfuscation is generally used in - * Puzzles. Either of -b and -h can always be specified to set it - * explicitly. - * - * Data read from standard input is assumed always to be binary; - * data provided on the command line is taken to be hex. - */ - -#include -#include -#include -#include -#include - -#include "puzzles.h" - -int main(int argc, char **argv) -{ - enum { BINARY, DEFAULT, HEX } outputmode = DEFAULT; - char *inhex = NULL; - unsigned char *data; - int datalen; - enum { UNKNOWN, DECODE, ENCODE } mode = UNKNOWN; - bool doing_opts = true; - - while (--argc > 0) { - char *p = *++argv; - - if (doing_opts && *p == '-') { - if (!strcmp(p, "--")) { - doing_opts = 0; - continue; - } - p++; - while (*p) { - switch (*p) { - case 'e': - mode = ENCODE; - break; - case 'd': - mode = DECODE; - break; - case 'b': - outputmode = BINARY; - break; - case 'h': - outputmode = HEX; - break; - default: - fprintf(stderr, "obfusc: unrecognised option '-%c'\n", - *p); - return 1; - } - p++; - } - } else { - if (!inhex) { - inhex = p; - } else { - fprintf(stderr, "obfusc: expected at most one argument\n"); - return 1; - } - } - } - - if (mode == UNKNOWN) { - fprintf(stderr, "usage: obfusc < -e | -d > [ -b | -h ] [hex data]\n"); - return 0; - } - - if (outputmode == DEFAULT) - outputmode = (mode == DECODE ? BINARY : HEX); - - if (inhex) { - datalen = strlen(inhex) / 2; - data = hex2bin(inhex, datalen); - } else { - int datasize = 4096; - datalen = 0; - data = snewn(datasize, unsigned char); - while (1) { - int ret = fread(data + datalen, 1, datasize - datalen, stdin); - if (ret < 0) { - fprintf(stderr, "obfusc: read: %s\n", strerror(errno)); - return 1; - } else if (ret == 0) { - break; - } else { - datalen += ret; - if (datasize - datalen < 4096) { - datasize = datalen * 5 / 4 + 4096; - data = sresize(data, datasize, unsigned char); - } - } - } - } - - obfuscate_bitmap(data, datalen * 8, mode == DECODE); - - if (outputmode == BINARY) { - int ret = fwrite(data, 1, datalen, stdout); - if (ret < 0) { - fprintf(stderr, "obfusc: write: %s\n", strerror(errno)); - return 1; - } - } else { - int i; - for (i = 0; i < datalen; i++) - printf("%02x", data[i]); - printf("\n"); - } - - return 0; -} diff --git a/apps/plugins/puzzles/src/palisade.R b/apps/plugins/puzzles/src/palisade.R deleted file mode 100644 index de4bd83126..0000000000 --- a/apps/plugins/puzzles/src/palisade.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -PALISADE_EXTRA = divvy dsf - -palisade : [X] GTK COMMON palisade PALISADE_EXTRA palisade-icon|no-icon - -palisade : [G] WINDOWS COMMON palisade PALISADE_EXTRA palisade.res|noicon.res - -ALL += palisade[COMBINED] PALISADE_EXTRA - -!begin am gtk -GAMES += palisade -!end - -!begin >list.c - A(palisade) \ -!end - -!begin >gamedesc.txt -palisade:palisade.exe:Palisade:Grid-division puzzle:Divide the grid into equal-sized areas in accordance with the clues. -!end diff --git a/apps/plugins/puzzles/src/palisade.c b/apps/plugins/puzzles/src/palisade.c index e941661a0e..811204b1fe 100644 --- a/apps/plugins/puzzles/src/palisade.c +++ b/apps/plugins/puzzles/src/palisade.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,7 @@ struct game_params { int w, h, k; }; -typedef char clue; +typedef signed char clue; typedef unsigned char borderflag; typedef struct shared_state { @@ -156,13 +157,15 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { - int w = params->w, h = params->h, k = params->k, wh = w * h; + int w = params->w, h = params->h, k = params->k, wh; if (k < 1) return "Region size must be at least one"; if (w < 1) return "Width must be at least one"; if (h < 1) return "Height must be at least one"; + if (w > INT_MAX / h) + return "Width times height must not be unreasonably large"; + wh = w * h; if (wh % k) return "Region size must divide grid area"; - if (!full) return NULL; /* succeed partial validation */ /* MAYBE FIXME: we (just?) don't have the UI for winning these. */ @@ -183,7 +186,7 @@ typedef struct solver_ctx { const game_params *params; /* also in shared_state */ clue *clues; /* also in shared_state */ borderflag *borders; /* also in game_state */ - int *dsf; /* particular to the solver */ + DSF *dsf; /* particular to the solver */ } solver_ctx; /* Deductions: @@ -270,7 +273,7 @@ static void connect(solver_ctx *ctx, int i, int j) static bool connected(solver_ctx *ctx, int i, int j, int dir) { if (j == COMPUTE_J) j = i + dx[dir] + ctx->params->w*dy[dir]; - return dsf_canonify(ctx->dsf, i) == dsf_canonify(ctx->dsf, j); + return dsf_equivalent(ctx->dsf, i, j); } static void disconnect(solver_ctx *ctx, int i, int j, int dir) @@ -502,19 +505,20 @@ static bool solver_equivalent_edges(solver_ctx *ctx) return changed; } -#define UNVISITED 6 - /* build connected components in `dsf', along the lines of `borders'. */ -static void dfs_dsf(int i, int w, borderflag *border, int *dsf, bool black) +static void build_dsf(int w, int h, borderflag *border, DSF *dsf, bool black) { - int dir; - for (dir = 0; dir < 4; ++dir) { - int ii = i + dx[dir] + w*dy[dir], bdir = BORDER(dir); - if (black ? (border[i] & bdir) : !(border[i] & DISABLED(bdir))) - continue; - if (dsf[ii] != UNVISITED) continue; - dsf_merge(dsf, i, ii); - dfs_dsf(ii, w, border, dsf, black); + int x, y; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (x+1 < w && (black ? !(border[y*w+x] & BORDER_R) : + (border[y*w+x] & DISABLED(BORDER_R)))) + dsf_merge(dsf, y*w+x, y*w+(x+1)); + if (y+1 < h && (black ? !(border[y*w+x] & BORDER_D) : + (border[y*w+x] & DISABLED(BORDER_D)))) + dsf_merge(dsf, y*w+x, (y+1)*w+x); + } } } @@ -523,9 +527,9 @@ static bool is_solved(const game_params *params, clue *clues, { int w = params->w, h = params->h, wh = w*h, k = params->k; int i, x, y; - int *dsf = snew_dsf(wh); + DSF *dsf = dsf_new(wh); - assert (dsf[0] == UNVISITED); /* check: UNVISITED and dsf.c match up */ + build_dsf(w, h, border, dsf, true); /* * A game is solved if: @@ -536,7 +540,6 @@ static bool is_solved(const game_params *params, clue *clues, * - the borders also satisfy the clue set */ for (i = 0; i < wh; ++i) { - if (dsf[i] == UNVISITED) dfs_dsf(i, params->w, border, dsf, true); if (dsf_size(dsf, i) != k) goto error; if (clues[i] == EMPTY) continue; if (clues[i] != bitcount[border[i] & BORDER_MASK]) goto error; @@ -554,19 +557,19 @@ static bool is_solved(const game_params *params, clue *clues, for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { if (x+1 < w && (border[y*w+x] & BORDER_R) && - dsf_canonify(dsf, y*w+x) == dsf_canonify(dsf, y*w+(x+1))) + dsf_equivalent(dsf, y*w+x, y*w+(x+1))) goto error; if (y+1 < h && (border[y*w+x] & BORDER_D) && - dsf_canonify(dsf, y*w+x) == dsf_canonify(dsf, (y+1)*w+x)) + dsf_equivalent(dsf, y*w+x, (y+1)*w+x)) goto error; } } - sfree(dsf); + dsf_free(dsf); return true; error: - sfree(dsf); + dsf_free(dsf); return false; } @@ -579,7 +582,7 @@ static bool solver(const game_params *params, clue *clues, borderflag *borders) ctx.params = params; ctx.clues = clues; ctx.borders = borders; - ctx.dsf = snew_dsf(wh); + ctx.dsf = dsf_new(wh); solver_connected_clues_versus_region_size(&ctx); /* idempotent */ do { @@ -591,7 +594,7 @@ static bool solver(const game_params *params, clue *clues, borderflag *borders) changed |= solver_equivalent_edges(&ctx); } while (changed); - sfree(ctx.dsf); + dsf_free(ctx.dsf); return is_solved(params, clues, borders); } @@ -622,15 +625,14 @@ static char *new_game_desc(const game_params *params, random_state *rs, { int w = params->w, h = params->h, wh = w*h, k = params->k; - clue *numbers = snewn(wh + 1, clue), *p; + clue *numbers = snewn(wh + 1, clue); borderflag *rim = snewn(wh, borderflag); borderflag *scratch_borders = snewn(wh, borderflag); char *soln = snewa(*aux, wh + 2); int *shuf = snewn(wh, int); - int *dsf = NULL, i, r, c; - - int attempts = 0; + DSF *dsf = NULL; + int i, r, c; for (i = 0; i < wh; ++i) shuf[i] = i; xshuffle(shuf, wh, rs); @@ -642,10 +644,9 @@ static char *new_game_desc(const game_params *params, random_state *rs, soln[wh] = '\0'; do { - ++attempts; setmem(soln, '@', wh); - sfree(dsf); + dsf_free(dsf); dsf = divvy_rectangle(w, h, k, rs); for (r = 0; r < h; ++r) @@ -655,7 +656,7 @@ static char *new_game_desc(const game_params *params, random_state *rs, for (dir = 0; dir < 4; ++dir) { int rr = r + dy[dir], cc = c + dx[dir], ii = rr * w + cc; if (OUT_OF_BOUNDS(cc, rr, w, h) || - dsf_canonify(dsf, i) != dsf_canonify(dsf, ii)) { + !dsf_equivalent(dsf, i, ii)) { ++numbers[i]; soln[i] |= BORDER(dir); } @@ -680,9 +681,10 @@ static char *new_game_desc(const game_params *params, random_state *rs, sfree(scratch_borders); sfree(rim); sfree(shuf); - sfree(dsf); + dsf_free(dsf); + + char *output = snewn(wh + 1, char), *p = output; - p = numbers; r = 0; for (i = 0; i < wh; ++i) { if (numbers[i] != EMPTY) { @@ -699,7 +701,8 @@ static char *new_game_desc(const game_params *params, random_state *rs, } *p++ = '\0'; - return sresize(numbers, p - numbers, clue); + sfree(numbers); + return sresize(output, p - output, char); } static const char *validate_desc(const game_params *params, const char *desc) @@ -867,14 +870,13 @@ static char *game_text_format(const game_state *state) struct game_ui { int x, y; bool show; - bool fake_ctrl, fake_shift; }; static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->x = ui->y = 0; - ui->show = ui->fake_ctrl = ui->fake_shift = false; + ui->show = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -883,16 +885,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ - assert (encoding == NULL); -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -907,7 +899,7 @@ struct game_drawstate { #define TILESIZE (ds->tilesize) #define MARGIN (ds->tilesize / 2) -#define WIDTH (1 + (TILESIZE >= 16) + (TILESIZE >= 32) + (TILESIZE >= 64)) +#define WIDTH (3*TILESIZE/32 > 1 ? 3*TILESIZE/32 : 1) #define CENTER ((ds->tilesize / 2) + WIDTH/2) #define FROMCOORD(x) (((x) - MARGIN) / TILESIZE) @@ -918,12 +910,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) { int w = state->shared->params.w, h = state->shared->params.h; - bool control = (button & MOD_CTRL) | ui->fake_ctrl, shift = (button & MOD_SHFT) | ui->fake_shift; - - /* reset */ - ui->fake_ctrl = ui->fake_shift = false; + bool control = button & MOD_CTRL, shift = button & MOD_SHFT; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { int gx = FROMCOORD(x), gy = FROMCOORD(y), possible = BORDER_MASK; @@ -974,13 +963,13 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (IS_CURSOR_MOVE(button)) { - ui->show = true; if (control || shift) { borderflag flag = 0, newflag; int dir, i = ui->y * w + ui->x; + ui->show = true; x = ui->x; y = ui->y; - move_cursor(button, &x, &y, w, h, false); + move_cursor(button, &x, &y, w, h, false, NULL); if (OUT_OF_BOUNDS(x, y, w, h)) return NULL; for (dir = 0; dir < 4; ++dir) @@ -999,20 +988,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (shift) newflag |= DISABLED(BORDER(FLIP(dir))); return string(80, "F%d,%d,%dF%d,%d,%d", ui->x, ui->y, flag, x, y, newflag); - } else { - move_cursor(button, &ui->x, &ui->y, w, h, false); - return UI_UPDATE; - } - } - else if(IS_CURSOR_SELECT(button)) { - /* CURSOR_SELECT or CURSOR_SELECT2 tells us to toggle whether - * the button press should be interpreted as having CTRL or - * shift pressed along with it, respectively. */ - ui->show = true; - if(button == CURSOR_SELECT2) - ui->fake_shift = !ui->fake_shift; - else - ui->fake_ctrl = !ui->fake_ctrl; + } else + return move_cursor(button, &ui->x, &ui->y, w, h, false, &ui->show); } return NULL; @@ -1022,15 +999,14 @@ static game_state *execute_move(const game_state *state, const char *move) { int w = state->shared->params.w, h = state->shared->params.h, wh = w * h; game_state *ret = dup_game(state); - int nchars, x, y, flag; + int nchars, x, y, flag, i; if (*move == 'S') { - int i; ++move; for (i = 0; i < wh && move[i]; ++i) ret->borders[i] = (move[i] & BORDER_MASK) | DISABLED(~move[i] & BORDER_MASK); - if (i < wh || move[i]) return NULL; /* leaks `ret', then we die */ + if (i < wh || move[i]) goto badmove; ret->cheated = ret->completed = true; return ret; } @@ -1038,22 +1014,31 @@ static game_state *execute_move(const game_state *state, const char *move) while (sscanf(move, "F%d,%d,%d%n", &x, &y, &flag, &nchars) == 3 && !OUT_OF_BOUNDS(x, y, w, h)) { move += nchars; + for (i = 0; i < 4; i++) + if ((flag & BORDER(i)) && + OUT_OF_BOUNDS(x+dx[i], y+dy[i], w, h)) + /* No toggling the borders of the grid! */ + goto badmove; ret->borders[y*w + x] ^= flag; } - if (*move) return NULL; /* leaks `ret', then we die */ + if (*move) goto badmove; if (!ret->completed) ret->completed = is_solved(&ret->shared->params, ret->shared->clues, ret->borders); return ret; + + badmove: + free_game(ret); + return NULL; } /* --- Drawing routines --------------------------------------------- */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = (params->w + 1) * tilesize; *y = (params->h + 1) * tilesize; @@ -1181,14 +1166,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds, float animtime, float flashtime) { int w = state->shared->params.w, h = state->shared->params.h, wh = w*h; - int r, c, i, flash = ((int) (flashtime * 5 / FLASH_TIME)) % 2; - int *black_border_dsf = snew_dsf(wh), *yellow_border_dsf = snew_dsf(wh); + int r, c, flash = ((int) (flashtime * 5 / FLASH_TIME)) % 2; + DSF *black_border_dsf = dsf_new(wh), *yellow_border_dsf = dsf_new(wh); int k = state->shared->params.k; if (!ds->grid) { char buf[40]; int bgw = (w+1) * ds->tilesize, bgh = (h+1) * ds->tilesize; - draw_rect(dr, 0, 0, bgw, bgh, COL_BACKGROUND); for (r = 0; r <= h; ++r) for (c = 0; c <= w; ++c) @@ -1203,12 +1187,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds, status_bar(dr, buf); } - for (i = 0; i < wh; ++i) { - if (black_border_dsf[i] == UNVISITED) - dfs_dsf(i, w, state->borders, black_border_dsf, true); - if (yellow_border_dsf[i] == UNVISITED) - dfs_dsf(i, w, state->borders, yellow_border_dsf, false); - } + build_dsf(w, h, state->borders, black_border_dsf, true); + build_dsf(w, h, state->borders, yellow_border_dsf, false); for (r = 0; r < h; ++r) for (c = 0; c < w; ++c) { @@ -1268,8 +1248,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds, draw_tile(dr, ds, r, c, ds->grid[i], clue); } - sfree(black_border_dsf); - sfree(yellow_border_dsf); + dsf_free(black_border_dsf); + dsf_free(yellow_border_dsf); } static float game_anim_length(const game_state *oldstate, @@ -1306,17 +1286,12 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - assert (!"this shouldn't get called"); - return false; /* placate optimiser */ -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; - game_compute_size(params, 700, &pw, &ph); /* 7mm, like loopy */ + game_compute_size(params, 700, ui, &pw, &ph); /* 7mm, like loopy */ *x = pw / 100.0F; *y = ph / 100.0F; @@ -1335,7 +1310,8 @@ static void print_line(drawing *dr, int x1, int y1, int x2, int y2, } else draw_line(dr, x1, y1, x2, y2, colour); } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->shared->params.w, h = state->shared->params.h; int ink = print_mono_colour(dr, 0); @@ -1399,12 +1375,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, 48, game_compute_size, game_set_size, @@ -1418,6 +1396,6 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/pattern.R b/apps/plugins/puzzles/src/pattern.R deleted file mode 100644 index d6695715f9..0000000000 --- a/apps/plugins/puzzles/src/pattern.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -pattern : [X] GTK COMMON pattern pattern-icon|no-icon - -pattern : [G] WINDOWS COMMON pattern pattern.res|noicon.res - -patternsolver : [U] pattern[STANDALONE_SOLVER] STANDALONE -patternsolver : [C] pattern[STANDALONE_SOLVER] STANDALONE - -patternpicture : [U] pattern[STANDALONE_PICTURE_GENERATOR] STANDALONE -patternpicture : [C] pattern[STANDALONE_PICTURE_GENERATOR] STANDALONE - -ALL += pattern[COMBINED] - -!begin am gtk -GAMES += pattern -!end - -!begin >list.c - A(pattern) \ -!end - -!begin >gamedesc.txt -pattern:pattern.exe:Pattern:Pattern puzzle:Fill in the pattern in the grid, given only the lengths of runs of black squares. -!end diff --git a/apps/plugins/puzzles/src/pattern.c b/apps/plugins/puzzles/src/pattern.c index df720b7d82..b370a3dc2f 100644 --- a/apps/plugins/puzzles/src/pattern.c +++ b/apps/plugins/puzzles/src/pattern.c @@ -7,7 +7,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -53,6 +58,7 @@ typedef struct game_state_common { int *rowdata, *rowlen; bool *immutable; int refcount; + enum { FS_SMALL, FS_LARGE } fontsize; } game_state_common; struct game_state { @@ -176,7 +182,10 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w <= 0 || params->h <= 0) return "Width and height must both be greater than zero"; - if (params->w * params->w < 2) + if (params->w > INT_MAX - 1 || params->h > INT_MAX - 1 || + params->w > INT_MAX / params->h) + return "Puzzle must not be unreasonably large"; + if (params->w * params->h < 2) return "Grid must contain at least two squares"; return NULL; } @@ -360,7 +369,7 @@ static int compute_rowdata(int *ret, unsigned char *start, int len, int step) #define STILL_UNKNOWN 3 #ifdef STANDALONE_SOLVER -bool verbose = false; +static bool verbose = false; #endif static bool do_recurse(unsigned char *known, unsigned char *deduced, @@ -441,6 +450,8 @@ static bool do_row(unsigned char *known, unsigned char *deduced, int rowlen, i, freespace; bool done_any; + assert(len >= 0); /* avoid compile warnings about the memsets below */ + freespace = len+1; for (rowlen = 0; data[rowlen]; rowlen++) { minpos_done[rowlen] = minpos_ok[rowlen] = len - 1; @@ -654,7 +665,7 @@ static bool solve_puzzle(const game_state *state, unsigned char *grid, #ifndef STANDALONE_PICTURE_GENERATOR static unsigned char *generate_soluble(random_state *rs, int w, int h) { - int i, j, ntries, max; + int i, j, max; bool ok; unsigned char *grid, *matrix, *workspace; unsigned int *changed_h, *changed_w; @@ -670,11 +681,7 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h) changed_w = snewn(max+1, unsigned int); rowdata = snewn(max+1, int); - ntries = 0; - do { - ntries++; - generate(rs, w, h, grid); /* @@ -719,7 +726,7 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h) #endif #ifdef STANDALONE_PICTURE_GENERATOR -unsigned char *picture; +static unsigned char *picture; #endif static char *new_game_desc(const game_params *params, random_state *rs, @@ -908,6 +915,10 @@ static const char *validate_desc(const game_params *params, const char *desc) p = desc; while (*desc && isdigit((unsigned char)*desc)) desc++; n = atoi(p); + if (n <= 0) + return "all clues must be positive"; + if (n > INT_MAX - 1) + return "at least one clue is grossly excessive"; rowspace -= n+1; if (rowspace < 0) { @@ -965,7 +976,7 @@ static const char *validate_desc(const game_params *params, const char *desc) static game_state *new_game(midend *me, const game_params *params, const char *desc) { - int i; + int i, j; const char *p; game_state *state = snew(game_state); @@ -1003,6 +1014,26 @@ static game_state *new_game(midend *me, const game_params *params, } } + /* + * Choose a font size based on the clues. If any column clue is + * more than one digit, switch to the smaller size. + */ + state->common->fontsize = FS_LARGE; + for (i = 0; i < params->w; i++) + for (j = 0; j < state->common->rowlen[i]; j++) + if (state->common->rowdata[state->common->rowsize * i + j] >= 10) + state->common->fontsize = FS_SMALL; + /* + * We might also need to use the small font if there are lots of + * row clues. We assume that all clues are one digit and that a + * single-digit clue takes up 1.5 tiles, of which the clue is 0.5 + * tiles and the space is 1.0 tiles. + */ + for (i = params->w; i < params->w + params->h; i++) + if ((state->common->rowlen[i] * 3 - 2) > + TLBORDER(state->common->w) * 2) + state->common->fontsize = FS_SMALL; + if (desc[-1] == ',') { /* * Optional extra piece of game description which fills in @@ -1217,7 +1248,7 @@ static game_ui *new_ui(const game_state *state) ret = snew(game_ui); ret->dragging = false; ret->cur_x = ret->cur_y = 0; - ret->cur_visible = false; + ret->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ret; } @@ -1227,18 +1258,26 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) return ""; + switch (state->grid[ui->cur_y * state->common->w + ui->cur_x]) { + case GRID_UNKNOWN: + return button == CURSOR_SELECT ? "Black" : "White"; + case GRID_FULL: + return button == CURSOR_SELECT ? "White" : "Grey"; + case GRID_EMPTY: + return button == CURSOR_SELECT ? "Grey" : "Black"; + } + } + return ""; } struct game_drawstate { @@ -1247,6 +1286,7 @@ struct game_drawstate { int tilesize; unsigned char *visible, *numcolours; int cur_x, cur_y; + char *strbuf; /* Used for formatting clues. */ }; static char *interpret_move(const game_state *state, game_ui *ui, @@ -1254,7 +1294,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int x, int y, int button) { bool control = button & MOD_CTRL, shift = button & MOD_SHFT; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); x = FROMCOORD(state->common->w, x); y = FROMCOORD(state->common->h, y); @@ -1294,7 +1334,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->drag_start_y = ui->drag_end_y = y; ui->cur_visible = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->dragging && button == ui->drag) { @@ -1323,7 +1363,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->drag_end_x = x; ui->drag_end_y = y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->dragging && button == ui->release) { @@ -1351,20 +1391,21 @@ static char *interpret_move(const game_state *state, game_ui *ui, x1, y1, x2-x1+1, y2-y1+1); return dupstr(buf); } else - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_MOVE(button)) { int x = ui->cur_x, y = ui->cur_y, newstate; - char buf[80]; - move_cursor(button, &ui->cur_x, &ui->cur_y, state->common->w, state->common->h, false); - ui->cur_visible = true; - if (!control && !shift) return UI_UPDATE; + char buf[80], *ret; + ret = move_cursor(button, &ui->cur_x, &ui->cur_y, + state->common->w, state->common->h, false, + &ui->cur_visible); + if (!control && !shift) return ret; newstate = control ? shift ? GRID_UNKNOWN : GRID_FULL : GRID_EMPTY; if (state->grid[y * state->common->w + x] == newstate && state->grid[ui->cur_y * state->common->w + ui->cur_x] == newstate) - return UI_UPDATE; + return ret; sprintf(buf, "%c%d,%d,%d,%d", control ? shift ? 'U' : 'F' : 'E', min(x, ui->cur_x), min(y, ui->cur_y), @@ -1379,7 +1420,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == CURSOR_SELECT2) @@ -1637,7 +1678,7 @@ static bool check_errors(const game_state *state, int i) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1692,6 +1733,8 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) ds->numcolours = snewn(ds->w + ds->h, unsigned char); memset(ds->numcolours, 255, ds->w + ds->h); ds->cur_x = ds->cur_y = 0; + ds->strbuf = snewn(state->common->rowsize * + MAX_DIGITS(*state->common->rowdata) + 1, char); return ds; } @@ -1699,6 +1742,8 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) static void game_free_drawstate(drawing *dr, game_drawstate *ds) { sfree(ds->visible); + sfree(ds->numcolours); + sfree(ds->strbuf); sfree(ds); } @@ -1743,19 +1788,43 @@ static void draw_numbers( int *rowdata = state->common->rowdata + state->common->rowsize * i; int nfit; int j; + int rx, ry, rw, rh; + int fontsize; - if (erase) { - if (i < state->common->w) { - draw_rect(dr, TOCOORD(state->common->w, i), 0, - TILE_SIZE, BORDER + TLBORDER(state->common->h) * TILE_SIZE, - COL_BACKGROUND); - } else { - draw_rect(dr, 0, TOCOORD(state->common->h, i - state->common->w), - BORDER + TLBORDER(state->common->w) * TILE_SIZE, TILE_SIZE, - COL_BACKGROUND); - } + if (i < state->common->w) { + rx = TOCOORD(state->common->w, i); + ry = 0; + rw = TILE_SIZE; + rh = BORDER + TLBORDER(state->common->h) * TILE_SIZE; + } else { + rx = 0; + ry = TOCOORD(state->common->h, i - state->common->w); + rw = BORDER + TLBORDER(state->common->w) * TILE_SIZE; + rh = TILE_SIZE; } + clip(dr, rx, ry, rw, rh); + if (erase) + draw_rect(dr, rx, ry, rw, rh, COL_BACKGROUND); + + /* + * Choose a font size that's suitable for the lengths of clue. + * Only column clues are interesting because row clues can be + * spaced out independent of the tile size. For column clues, we + * want to go as large as practical while leaving decent space + * between horizintally adjacent clues. We currently distinguish + * two cases: FS_LARGE is when all column clues are single digits, + * and FS_SMALL in all other cases. + * + * If we assume that a digit is about 0.6em wide, and we want + * about that space between clues, then FS_LARGE should be + * TILESIZE/1.2. If we also assume that clues are at most two + * digits long then the case where adjacent clues are two digits + * long requries FS_SMALL to be TILESIZE/1.8. + */ + fontsize = (TILE_SIZE + 0.5F) / + (state->common->fontsize == FS_LARGE ? 1.2F : 1.8F); + /* * Normally I space the numbers out by the same distance as the * tile size. However, if there are more numbers than available @@ -1768,32 +1837,38 @@ static void draw_numbers( nfit = max(rowlen, nfit) - 1; assert(nfit > 0); - for (j = 0; j < rowlen; j++) { - int x, y; - char str[80]; + if (i < state->common->w) { + for (j = 0; j < rowlen; j++) { + int x, y; + char str[MAX_DIGITS(*rowdata) + 1]; - if (i < state->common->w) { - x = TOCOORD(state->common->w, i); + x = rx; y = BORDER + TILE_SIZE * (TLBORDER(state->common->h)-1); y -= ((rowlen-j-1)*TILE_SIZE) * (TLBORDER(state->common->h)-1) / nfit; - } else { - y = TOCOORD(state->common->h, i - state->common->w); - x = BORDER + TILE_SIZE * (TLBORDER(state->common->w)-1); - x -= ((rowlen-j-1)*TILE_SIZE) * (TLBORDER(state->common->w)-1) / nfit; + sprintf(str, "%d", rowdata[j]); + draw_text(dr, x+TILE_SIZE/2, y+TILE_SIZE/2, FONT_VARIABLE, + fontsize, ALIGN_HCENTRE | ALIGN_VCENTRE, colour, str); } - - sprintf(str, "%d", rowdata[j]); - draw_text(dr, x+TILE_SIZE/2, y+TILE_SIZE/2, FONT_VARIABLE, - TILE_SIZE/2, ALIGN_HCENTRE | ALIGN_VCENTRE, colour, str); - } - - if (i < state->common->w) { - draw_update(dr, TOCOORD(state->common->w, i), 0, - TILE_SIZE, BORDER + TLBORDER(state->common->h) * TILE_SIZE); } else { - draw_update(dr, 0, TOCOORD(state->common->h, i - state->common->w), - BORDER + TLBORDER(state->common->w) * TILE_SIZE, TILE_SIZE); + int x, y; + size_t off = 0; + const char *spaces = " "; + + assert(rowlen <= state->common->rowsize); + *ds->strbuf = '\0'; + /* Squish up a bit if there are lots of clues. */ + if (rowlen > TLBORDER(state->common->w)) spaces++; + for (j = 0; j < rowlen; j++) + off += sprintf(ds->strbuf + off, "%s%d", + j ? spaces : "", rowdata[j]); + y = ry; + x = BORDER + TILE_SIZE * (TLBORDER(state->common->w)-1); + draw_text(dr, x+TILE_SIZE, y+TILE_SIZE/2, FONT_VARIABLE, + fontsize, ALIGN_HRIGHT | ALIGN_VCENTRE, colour, ds->strbuf); } + + unclip(dr); + draw_update(dr, rx, ry, rw, rh); } static void game_redraw(drawing *dr, game_drawstate *ds, @@ -1807,14 +1882,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, bool cmoved; if (!ds->started) { - /* - * The initial contents of the window are not guaranteed - * and can vary with front ends. To be on the safe side, - * all games should start by drawing a big background- - * colour rectangle covering the whole window. - */ - draw_rect(dr, 0, 0, SIZE(ds->w), SIZE(ds->h), COL_BACKGROUND); - /* * Draw the grid outline. */ @@ -1936,24 +2003,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 5mm squares by default. */ - game_compute_size(params, 500, &pw, &ph); + game_compute_size(params, 500, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->common->w, h = state->common->h; int ink = print_mono_colour(dr, 0); @@ -2027,12 +2091,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2046,7 +2112,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; diff --git a/apps/plugins/puzzles/src/pearl.R b/apps/plugins/puzzles/src/pearl.R deleted file mode 100644 index 79bc7325c7..0000000000 --- a/apps/plugins/puzzles/src/pearl.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -PEARL_EXTRA = dsf tree234 grid penrose loopgen tdq - -pearl : [X] GTK COMMON pearl PEARL_EXTRA pearl-icon|no-icon -pearl : [G] WINDOWS COMMON pearl PEARL_EXTRA pearl.res? - -pearlbench : [U] pearl[STANDALONE_SOLVER] PEARL_EXTRA STANDALONE m.lib -pearlbench : [C] pearl[STANDALONE_SOLVER] PEARL_EXTRA STANDALONE - -ALL += pearl[COMBINED] PEARL_EXTRA - -!begin am gtk -GAMES += pearl -!end - -!begin >list.c - A(pearl) \ -!end - -!begin >gamedesc.txt -pearl:pearl.exe:Pearl:Loop-drawing puzzle:Draw a single closed loop, given clues about corner and straight squares. -!end diff --git a/apps/plugins/puzzles/src/pearl.c b/apps/plugins/puzzles/src/pearl.c index 2657d45a67..95993172ca 100644 --- a/apps/plugins/puzzles/src/pearl.c +++ b/apps/plugins/puzzles/src/pearl.c @@ -35,7 +35,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "grid.h" @@ -272,8 +277,12 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 5) return "Width must be at least five"; if (params->h < 5) return "Height must be at least five"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->difficulty < 0 || params->difficulty >= DIFFCOUNT) return "Unknown difficulty level"; + if (params->difficulty >= DIFF_TRICKY && params->w + params->h < 11) + return "Width or height must be at least six for Tricky"; return NULL; } @@ -287,7 +296,8 @@ static int pearl_solve(int w, int h, char *clues, char *result, { int W = 2*w+1, H = 2*h+1; short *workspace; - int *dsf, *dsfsize; + DSF *dsf; + int *dsfsize; int x, y, b, d; int ret = -1; @@ -340,7 +350,7 @@ static int pearl_solve(int w, int h, char *clues, char *result, * We maintain a dsf of connected squares, together with a * count of the size of each equivalence class. */ - dsf = snewn(w*h, int); + dsf = dsf_new(w*h); dsfsize = snewn(w*h, int); /* @@ -583,7 +593,7 @@ static int pearl_solve(int w, int h, char *clues, char *result, { int nonblanks, loopclass; - dsf_init(dsf, w*h); + dsf_reinit(dsf); for (x = 0; x < w*h; x++) dsfsize[x] = 1; @@ -850,10 +860,39 @@ cleanup: if (ret == 1) assert(b < 0xD); /* we should have had a break by now */ } } + + /* + * Ensure we haven't left the _data structure_ inconsistent, + * regardless of the consistency of the _puzzle_. In + * particular, we should never have marked one square as + * linked to its neighbour if the neighbour is not + * reciprocally linked back to the original square. + * + * This can happen if we get part way through solving an + * impossible puzzle and then give up trying to make further + * progress. So here we fix it up to avoid confusing the rest + * of the game. + */ + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + for (d = 1; d <= 8; d += d) { + int nx = x + DX(d), ny = y + DY(d); + int rlink; + if (0 <= nx && nx < w && 0 <= ny && ny < h) + rlink = result[ny*w+nx] & F(d); + else + rlink = 0; /* off-board squares don't link back */ + + /* If other square doesn't link to us, don't link to it */ + if (!rlink) + result[y*w+x] &= ~d; + } + } + } } sfree(dsfsize); - sfree(dsf); + dsf_free(dsf); sfree(workspace); assert(ret >= 0); return ret; @@ -941,9 +980,9 @@ static int pearl_loopgen_bias(void *vctx, char *board, int face) * to reprocess the edges for this boundary. */ if (oldface == c || newface == c) { - grid_face *f = &g->faces[face]; + grid_face *f = g->faces[face]; for (k = 0; k < f->order; k++) - tdq_add(b->edges_todo, f->edges[k] - g->edges); + tdq_add(b->edges_todo, f->edges[k]->index); } } } @@ -959,15 +998,15 @@ static int pearl_loopgen_bias(void *vctx, char *board, int face) * the vertextypes_todo list. */ while ((j = tdq_remove(b->edges_todo)) >= 0) { - grid_edge *e = &g->edges[j]; - int fc1 = e->face1 ? board[e->face1 - g->faces] : FACE_BLACK; - int fc2 = e->face2 ? board[e->face2 - g->faces] : FACE_BLACK; + grid_edge *e = g->edges[j]; + int fc1 = e->face1 ? board[e->face1->index] : FACE_BLACK; + int fc2 = e->face2 ? board[e->face2->index] : FACE_BLACK; bool oldedge = b->edges[j]; bool newedge = (fc1==c) ^ (fc2==c); if (oldedge != newedge) { b->edges[j] = newedge; - tdq_add(b->vertextypes_todo, e->dot1 - g->dots); - tdq_add(b->vertextypes_todo, e->dot2 - g->dots); + tdq_add(b->vertextypes_todo, e->dot1->index); + tdq_add(b->vertextypes_todo, e->dot2->index); } } @@ -982,7 +1021,7 @@ static int pearl_loopgen_bias(void *vctx, char *board, int face) * old neighbours. */ while ((j = tdq_remove(b->vertextypes_todo)) >= 0) { - grid_dot *d = &g->dots[j]; + grid_dot *d = g->dots[j]; int neighbours[2], type = 0, n = 0; for (k = 0; k < d->order; k++) { @@ -990,10 +1029,10 @@ static int pearl_loopgen_bias(void *vctx, char *board, int face) grid_dot *d2 = (e->dot1 == d ? e->dot2 : e->dot1); /* dir == 0,1,2,3 for an edge going L,U,R,D */ int dir = (d->y == d2->y) + 2*(d->x+d->y > d2->x+d2->y); - int ei = e - g->edges; + int ei = e->index; if (b->edges[ei]) { type |= 1 << dir; - neighbours[n] = d2 - g->dots; + neighbours[n] = d2->index; n++; } } @@ -1048,9 +1087,8 @@ static int pearl_loopgen_bias(void *vctx, char *board, int face) return ctx->score; } -static void pearl_loopgen(int w, int h, char *lines, random_state *rs) +static void pearl_loopgen(int w, int h, char *lines, random_state *rs, grid *g) { - grid *g = grid_new(GRID_SQUARE, w-1, h-1, NULL); char *board = snewn(g->num_faces, char); int i, s = g->tilesize; struct pearl_loopgen_bias_ctx biasctx; @@ -1102,7 +1140,7 @@ static void pearl_loopgen(int w, int h, char *lines, random_state *rs) } for (i = 0; i < g->num_edges; i++) { - grid_edge *e = g->edges + i; + grid_edge *e = g->edges[i]; enum face_colour c1 = FACE_COLOUR(e->face1); enum face_colour c2 = FACE_COLOUR(e->face2); assert(c1 != FACE_GREY); @@ -1130,7 +1168,6 @@ static void pearl_loopgen(int w, int h, char *lines, random_state *rs) } } - grid_free(g); sfree(board); #if defined LOOPGEN_DIAGNOSTICS && !defined GENERATION_DIAGNOSTICS @@ -1153,11 +1190,11 @@ static void pearl_loopgen(int w, int h, char *lines, random_state *rs) } static int new_clues(const game_params *params, random_state *rs, - char *clues, char *grid) + char *clues, char *grid_out) { int w = params->w, h = params->h, diff = params->difficulty; int ngen = 0, x, y, d, ret, i; - + grid *g = grid_new(GRID_SQUARE, w-1, h-1, NULL); /* * Difficulty exception: 5x5 Tricky is not generable (the @@ -1168,13 +1205,13 @@ static int new_clues(const game_params *params, random_state *rs, while (1) { ngen++; - pearl_loopgen(w, h, grid, rs); + pearl_loopgen(w, h, grid_out, rs, g); #ifdef GENERATION_DIAGNOSTICS printf("grid array:\n"); for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - int type = grid[y*w+x]; + int type = grid_out[y*w+x]; char s[5], *p = s; if (type & L) *p++ = 'L'; if (type & R) *p++ = 'R'; @@ -1193,7 +1230,7 @@ static int new_clues(const game_params *params, random_state *rs, */ for (y = 0; y < h; y++) for (x = 0; x < w; x++) { - int type = grid[y*w+x]; + int type = grid_out[y*w+x]; clues[y*w+x] = NOCLUE; @@ -1207,7 +1244,7 @@ static int new_clues(const game_params *params, random_state *rs, for (d = 1; d <= 8; d += d) if (type & d) { int xx = x + DX(d), yy = y + DY(d); assert(xx >= 0 && xx < w && yy >= 0 && yy < h); - if ((bLU|bLD|bRU|bRD) & (1 << grid[yy*w+xx])) + if ((bLU|bLD|bRU|bRD) & (1 << grid_out[yy*w+xx])) break; } if (d <= 8) /* we found one */ @@ -1221,7 +1258,7 @@ static int new_clues(const game_params *params, random_state *rs, for (d = 1; d <= 8; d += d) if (type & d) { int xx = x + DX(d), yy = y + DY(d); assert(xx >= 0 && xx < w && yy >= 0 && yy < h); - if (!((bLR|bUD) & (1 << grid[yy*w+xx]))) + if (!((bLR|bUD) & (1 << grid_out[yy*w+xx]))) break; } if (d > 8) /* we didn't find a counterexample */ @@ -1247,7 +1284,7 @@ static int new_clues(const game_params *params, random_state *rs, /* * See if we can solve the puzzle just like this. */ - ret = pearl_solve(w, h, clues, grid, diff, false); + ret = pearl_solve(w, h, clues, grid_out, diff, false); assert(ret > 0); /* shouldn't be inconsistent! */ if (ret != 1) continue; /* go round and try again */ @@ -1256,7 +1293,7 @@ static int new_clues(const game_params *params, random_state *rs, * Check this puzzle isn't too easy. */ if (diff > DIFF_EASY) { - ret = pearl_solve(w, h, clues, grid, diff-1, false); + ret = pearl_solve(w, h, clues, grid_out, diff-1, false); assert(ret > 0); if (ret == 1) continue; /* too easy: try again */ @@ -1323,7 +1360,7 @@ static int new_clues(const game_params *params, random_state *rs, clue = clues[y*w+x]; clues[y*w+x] = 0; /* try removing this clue */ - ret = pearl_solve(w, h, clues, grid, diff, false); + ret = pearl_solve(w, h, clues, grid_out, diff, false); assert(ret > 0); if (ret != 1) clues[y*w+x] = clue; /* oops, put it back again */ @@ -1344,6 +1381,7 @@ static int new_clues(const game_params *params, random_state *rs, break; /* got it */ } + grid_free(g); debug(("%d %dx%d loops before finished puzzle.\n", ngen, w, h)); @@ -1491,29 +1529,35 @@ static char nbits[16] = { 0, 1, 1, 2, #define ERROR_CLUE 16 -static void dsf_update_completion(game_state *state, int ax, int ay, char dir, - int *dsf) +/* Returns false if the state is invalid. */ +static bool dsf_update_completion(game_state *state, int ax, int ay, char dir, + DSF *dsf) { int w = state->shared->w /*, h = state->shared->h */; int ac = ay*w+ax, bx, by, bc; - if (!(state->lines[ac] & dir)) return; /* no link */ + if (!(state->lines[ac] & dir)) return true; /* no link */ bx = ax + DX(dir); by = ay + DY(dir); - assert(INGRID(state, bx, by)); /* should not have a link off grid */ + if (!INGRID(state, bx, by)) + return false; /* should not have a link off grid */ bc = by*w+bx; - assert(state->lines[bc] & F(dir)); /* should have reciprocal link */ - if (!(state->lines[bc] & F(dir))) return; + if (!(state->lines[bc] & F(dir))) + return false; /* should have reciprocal link */ + if (!(state->lines[bc] & F(dir))) return true; dsf_merge(dsf, ac, bc); + return true; } -static void check_completion(game_state *state, bool mark) +/* Returns false if the state is invalid. */ +static bool check_completion(game_state *state, bool mark) { int w = state->shared->w, h = state->shared->h, x, y, i, d; bool had_error = false; - int *dsf, *component_state; + DSF *dsf; + int *component_state; int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize; enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY }; @@ -1532,13 +1576,16 @@ static void check_completion(game_state *state, bool mark) * same reasons, since Loopy and Pearl have basically the same * form of expected solution. */ - dsf = snew_dsf(w*h); + dsf = dsf_new(w*h); /* Build the dsf. */ for (x = 0; x < w; x++) { for (y = 0; y < h; y++) { - dsf_update_completion(state, x, y, R, dsf); - dsf_update_completion(state, x, y, D, dsf); + if (!dsf_update_completion(state, x, y, R, dsf) || + !dsf_update_completion(state, x, y, D, dsf)) { + dsf_free(dsf); + return false; + } } } @@ -1619,7 +1666,7 @@ static void check_completion(game_state *state, bool mark) * part of a single loop, for which our counter variables * nsilly,nloop,npath are enough. */ sfree(component_state); - sfree(dsf); + dsf_free(dsf); /* * Check that no clues are contradicted. This code is similar to @@ -1693,6 +1740,7 @@ static void check_completion(game_state *state, bool mark) if (!had_error) state->completed = true; } + return true; } /* completion check: @@ -1810,18 +1858,53 @@ struct game_ui { int curx, cury; /* grid position of keyboard cursor */ bool cursor_active; /* true iff cursor is shown */ + + /* + * User preference: general visual style of the GUI. GUI_MASYU is + * how this puzzle is traditionally presented, with clue dots in + * the middle of grid squares, and the solution loop connecting + * square-centres. GUI_LOOPY shifts the grid by half a square in + * each direction, so that the clue dots are at _vertices_ of the + * grid and the solution loop follows the grid edges, which you + * could argue is more logical. + */ + enum { GUI_MASYU, GUI_LOOPY } gui_style; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int gui_style = -1; + + if (!initialised) { + initialised = true; + + switch (getenv_bool("PEARL_GUI_LOOPY", -1)) { + case 0: + gui_style = GUI_MASYU; + break; + case 1: + gui_style = GUI_LOOPY; + break; + } + } + + if (gui_style != -1) + ui_out->gui_style = gui_style; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); - int sz = state->shared->sz; ui->ndragcoords = -1; - ui->dragcoords = snewn(sz, int); - ui->cursor_active = false; + ui->dragcoords = state ? snewn(state->shared->sz, int) : NULL; + ui->cursor_active = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->curx = ui->cury = 0; + ui->gui_style = GUI_MASYU; + legacy_prefs_override(ui); + return ui; } @@ -1831,13 +1914,28 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Puzzle appearance"; + ret[0].kw = "appearance"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = ":Traditional:Loopy-style"; + ret[0].u.choices.choicekws = ":traditional:loopy"; + ret[0].u.choices.selected = ui->gui_style; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->gui_style = cfg[0].u.choices.selected; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1845,11 +1943,25 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, { } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cursor_active) { + if (button == CURSOR_SELECT) { + if (ui->ndragcoords == -1) return "Start"; + return "Stop"; + } + if (button == CURSOR_SELECT2 && ui->ndragcoords >= 0) + return "Cancel"; + } + return ""; +} + #define PREFERRED_TILE_SIZE 31 #define HALFSZ (ds->halfsz) #define TILE_SIZE (ds->halfsz*2 + 1) -#define BORDER ((get_gui_style() == GUI_LOOPY) ? (TILE_SIZE/8) : (TILE_SIZE/2)) +#define BORDER ((ui->gui_style == GUI_LOOPY) ? (TILE_SIZE/8) : (TILE_SIZE/2)) #define BORDER_WIDTH (max(TILE_SIZE / 32, 1)) @@ -1865,22 +1977,6 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, #define DS_FLASH (1 << 21) #define DS_CURSOR (1 << 22) -enum { GUI_MASYU, GUI_LOOPY }; - -static int get_gui_style(void) -{ - static int gui_style = -1; - - if (gui_style == -1) { - char *env = getenv("PEARL_GUI_LOOPY"); - if (env && (env[0] == 'y' || env[0] == 'Y')) - gui_style = GUI_LOOPY; - else - gui_style = GUI_MASYU; - } - return gui_style; -} - struct game_drawstate { int halfsz; bool started; @@ -1891,6 +1987,56 @@ struct game_drawstate { char *draglines; /* size w*h; lines flipped by current drag */ }; +/* + * Routine shared between multiple callers to work out the intended + * effect of a drag path on the grid. + * + * Call it in a loop, like this: + * + * bool clearing = true; + * for (i = 0; i < ui->ndragcoords - 1; i++) { + * int sx, sy, dx, dy, dir, oldstate, newstate; + * interpret_ui_drag(state, ui, &clearing, i, &sx, &sy, &dx, &dy, + * &dir, &oldstate, &newstate); + * + * [do whatever is needed to handle the fact that the drag + * wants the edge from sx,sy to dx,dy (heading in direction + * 'dir' at the sx,sy end) to be changed from state oldstate + * to state newstate, each of which equals either 0 or dir] + * } + */ +static void interpret_ui_drag(const game_state *state, const game_ui *ui, + bool *clearing, int i, int *sx, int *sy, + int *dx, int *dy, int *dir, + int *oldstate, int *newstate) +{ + int w = state->shared->w; + int sp = ui->dragcoords[i], dp = ui->dragcoords[i+1]; + *sy = sp/w; + *sx = sp%w; + *dy = dp/w; + *dx = dp%w; + *dir = (*dy>*sy ? D : *dy<*sy ? U : *dx>*sx ? R : L); + *oldstate = state->lines[sp] & *dir; + if (*oldstate) { + /* + * The edge we've dragged over was previously + * present. Set it to absent, unless we've already + * stopped doing that. + */ + *newstate = *clearing ? 0 : *dir; + } else { + /* + * The edge we've dragged over was previously + * absent. Set it to present, and cancel the + * 'clearing' flag so that all subsequent edges in + * the drag are set rather than cleared. + */ + *newstate = *dir; + *clearing = false; + } +} + static void update_ui_drag(const game_state *state, game_ui *ui, int gx, int gy) { @@ -1919,13 +2065,42 @@ static void update_ui_drag(const game_state *state, game_ui *ui, * the drag path so far has the effect of truncating the path back * to that square, so a player can back out part of an uncommitted * drag without having to let go of the mouse. + * + * An exception is that you're allowed to drag round in a loop + * back to the very start of the drag, provided that doesn't + * create a vertex of the wrong degree. This allows a player who's + * after an extra challenge to draw the entire loop in a single + * drag, without it cancelling itself just before release. */ - for (i = 0; i < ui->ndragcoords; i++) + for (i = 1; i < ui->ndragcoords; i++) if (pos == ui->dragcoords[i]) { ui->ndragcoords = i+1; return; } + if (pos == ui->dragcoords[0]) { + /* More complex check for a loop-shaped drag, which has to go + * through interpret_ui_drag to decide on the final degree of + * the start/end vertex. */ + ui->dragcoords[ui->ndragcoords] = pos; + bool clearing = true; + int lines = state->lines[pos] & (L|R|U|D); + for (i = 0; i < ui->ndragcoords; i++) { + int sx, sy, dx, dy, dir, oldstate, newstate; + interpret_ui_drag(state, ui, &clearing, i, &sx, &sy, &dx, &dy, + &dir, &oldstate, &newstate); + if (sx == gx && sy == gy) + lines ^= (oldstate ^ newstate); + if (dx == gx && dy == gy) + lines ^= (F(oldstate) ^ F(newstate)); + } + if (NBITS(lines) > 2) { + /* Bad vertex degree: fall back to the backtracking behaviour. */ + ui->ndragcoords = 1; + return; + } + } + /* * Otherwise, dragging the mouse into a square that's a rook-move * away from the last one on the path extends the path. @@ -1958,56 +2133,6 @@ static void update_ui_drag(const game_state *state, game_ui *ui, */ } -/* - * Routine shared between interpret_move and game_redraw to work out - * the intended effect of a drag path on the grid. - * - * Call it in a loop, like this: - * - * bool clearing = true; - * for (i = 0; i < ui->ndragcoords - 1; i++) { - * int sx, sy, dx, dy, dir, oldstate, newstate; - * interpret_ui_drag(state, ui, &clearing, i, &sx, &sy, &dx, &dy, - * &dir, &oldstate, &newstate); - * - * [do whatever is needed to handle the fact that the drag - * wants the edge from sx,sy to dx,dy (heading in direction - * 'dir' at the sx,sy end) to be changed from state oldstate - * to state newstate, each of which equals either 0 or dir] - * } - */ -static void interpret_ui_drag(const game_state *state, const game_ui *ui, - bool *clearing, int i, int *sx, int *sy, - int *dx, int *dy, int *dir, - int *oldstate, int *newstate) -{ - int w = state->shared->w; - int sp = ui->dragcoords[i], dp = ui->dragcoords[i+1]; - *sy = sp/w; - *sx = sp%w; - *dy = dp/w; - *dx = dp%w; - *dir = (*dy>*sy ? D : *dy<*sy ? U : *dx>*sx ? R : L); - *oldstate = state->lines[sp] & *dir; - if (*oldstate) { - /* - * The edge we've dragged over was previously - * present. Set it to absent, unless we've already - * stopped doing that. - */ - *newstate = *clearing ? 0 : *dir; - } else { - /* - * The edge we've dragged over was previously - * absent. Set it to present, and cancel the - * 'clearing' flag so that all subsequent edges in - * the drag are set rather than cleared. - */ - *newstate = *dir; - *clearing = false; - } -} - static char *mark_in_direction(const game_state *state, int x, int y, int dir, bool primary, char *buf) { @@ -2018,11 +2143,11 @@ static char *mark_in_direction(const game_state *state, int x, int y, int dir, char ch = primary ? 'F' : 'M', *other; - if (!INGRID(state, x, y) || !INGRID(state, x2, y2)) return UI_UPDATE; + if (!INGRID(state, x, y) || !INGRID(state, x2, y2)) return MOVE_UI_UPDATE; /* disallow laying a mark over a line, or vice versa. */ other = primary ? state->marks : state->lines; - if (other[y*w+x] & dir || other[y2*w+x2] & dir2) return UI_UPDATE; + if (other[y*w+x] & dir || other[y2*w+x2] & dir2) return MOVE_UI_UPDATE; sprintf(buf, "%c%d,%d,%d;%c%d,%d,%d", ch, dir, x, y, ch, dir2, x2, y2); return dupstr(buf); @@ -2042,26 +2167,26 @@ static char *interpret_move(const game_state *state, game_ui *ui, char tmpbuf[80]; bool shift = button & MOD_SHFT, control = button & MOD_CTRL; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (IS_MOUSE_DOWN(button)) { ui->cursor_active = false; if (!INGRID(state, gx, gy)) { ui->ndragcoords = -1; - return NULL; + return MOVE_UI_UPDATE; } ui->clickx = x; ui->clicky = y; ui->dragcoords[0] = gy * w + gx; ui->ndragcoords = 0; /* will be 1 once drag is confirmed */ - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == LEFT_DRAG && ui->ndragcoords >= 0) { update_ui_drag(state, ui, gx, gy); - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_MOUSE_RELEASE(button)) release = true; @@ -2071,42 +2196,48 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->cursor_active = true; } else if (control || shift) { char *move; - if (ui->ndragcoords > 0) return NULL; + if (ui->ndragcoords > 0) return MOVE_NO_EFFECT; ui->ndragcoords = -1; move = mark_in_direction(state, ui->curx, ui->cury, KEY_DIRECTION(button), control, tmpbuf); if (control && !shift && *move) - move_cursor(button, &ui->curx, &ui->cury, w, h, false); + move_cursor(button, &ui->curx, &ui->cury, w, h, false, NULL); return move; } else { - move_cursor(button, &ui->curx, &ui->cury, w, h, false); + move_cursor(button, &ui->curx, &ui->cury, w, h, false, NULL); if (ui->ndragcoords >= 0) update_ui_drag(state, ui, ui->curx, ui->cury); } - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_SELECT(button)) { if (!ui->cursor_active) { ui->cursor_active = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (button == CURSOR_SELECT) { if (ui->ndragcoords == -1) { ui->ndragcoords = 0; ui->dragcoords[0] = ui->cury * w + ui->curx; ui->clickx = CENTERED_COORD(ui->curx); ui->clicky = CENTERED_COORD(ui->cury); - return UI_UPDATE; + return MOVE_UI_UPDATE; } else release = true; - } else if (button == CURSOR_SELECT2 && ui->ndragcoords >= 0) { - ui->ndragcoords = -1; - return UI_UPDATE; - } + } else if (button == CURSOR_SELECT2) { + if (ui->ndragcoords >= 0) { + ui->ndragcoords = -1; + return MOVE_UI_UPDATE; + } + return MOVE_NO_EFFECT; + } } if (button == 27 || button == '\b') { - ui->ndragcoords = -1; - return UI_UPDATE; + if (ui->ndragcoords >= 0) { + ui->ndragcoords = -1; + return MOVE_UI_UPDATE; + } + return MOVE_NO_EFFECT; } if (release) { @@ -2138,7 +2269,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->ndragcoords = -1; - return buf ? buf : UI_UPDATE; + return buf ? buf : MOVE_UI_UPDATE; } else if (ui->ndragcoords == 0) { /* Click (or tiny drag). Work out which edge we were * closest to. */ @@ -2159,12 +2290,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, cx = CENTERED_COORD(gx); cy = CENTERED_COORD(gy); - if (!INGRID(state, gx, gy)) return UI_UPDATE; + if (!INGRID(state, gx, gy)) return MOVE_UI_UPDATE; if (max(abs(x-cx),abs(y-cy)) < TILE_SIZE/4) { /* TODO closer to centre of grid: process as a cell click not an edge click. */ - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { int direction; if (abs(x-cx) < abs(y-cy)) { @@ -2183,7 +2314,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (button == 'H' || button == 'h') return dupstr("H"); - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -2246,7 +2377,7 @@ static game_state *execute_move(const game_state *state, const char *move) goto badmove; } - check_completion(ret, true); + if (!check_completion(ret, true)) goto badmove; return ret; @@ -2262,7 +2393,7 @@ badmove: #define FLASH_TIME 0.5F static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int halfsz; } ads, *ds = &ads; @@ -2340,8 +2471,8 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) } static void draw_lines_specific(drawing *dr, game_drawstate *ds, - int x, int y, unsigned int lflags, - unsigned int shift, int c) + const game_ui *ui, int x, int y, + unsigned int lflags, unsigned int shift, int c) { int ox = COORD(x), oy = COORD(y); int t2 = HALFSZ, t16 = HALFSZ/4; @@ -2390,7 +2521,7 @@ static void draw_square(drawing *dr, game_drawstate *ds, const game_ui *ui, COL_CURSOR_BACKGROUND : COL_BACKGROUND); - if (get_gui_style() == GUI_LOOPY) { + if (ui->gui_style == GUI_LOOPY) { /* Draw small dot, underneath any lines. */ draw_circle(dr, cx, cy, t16, COL_GRID, COL_GRID); } else { @@ -2417,7 +2548,7 @@ static void draw_square(drawing *dr, game_drawstate *ds, const game_ui *ui, draw_line(dr, mx-msz, my-msz, mx+msz, my+msz, COL_BLACK); draw_line(dr, mx-msz, my+msz, mx+msz, my-msz, COL_BLACK); } else { - if (get_gui_style() == GUI_LOOPY) { + if (ui->gui_style == GUI_LOOPY) { /* draw grid lines connecting centre of cells */ draw_line(dr, cx, cy, cx+xoff, cy+yoff, COL_GRID); } @@ -2427,11 +2558,11 @@ static void draw_square(drawing *dr, game_drawstate *ds, const game_ui *ui, /* Draw each of the four directions, where laid (or error, or drag, etc.) * Order is important here, specifically for the eventual colours of the * exposed end caps. */ - draw_lines_specific(dr, ds, x, y, lflags, 0, + draw_lines_specific(dr, ds, ui, x, y, lflags, 0, (lflags & DS_FLASH ? COL_FLASH : COL_BLACK)); - draw_lines_specific(dr, ds, x, y, lflags, DS_ESHIFT, COL_ERROR); - draw_lines_specific(dr, ds, x, y, lflags, DS_DSHIFT, COL_DRAGOFF); - draw_lines_specific(dr, ds, x, y, lflags, DS_DSHIFT, COL_DRAGON); + draw_lines_specific(dr, ds, ui, x, y, lflags, DS_ESHIFT, COL_ERROR); + draw_lines_specific(dr, ds, ui, x, y, lflags, DS_DSHIFT, COL_DRAGOFF); + draw_lines_specific(dr, ds, ui, x, y, lflags, DS_DSHIFT, COL_DRAGON); /* Draw a clue, if present */ if (clue != NOCLUE) { @@ -2458,18 +2589,9 @@ static void game_redraw(drawing *dr, game_drawstate *ds, bool force = false; if (!ds->started) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all games - * should start by drawing a big background-colour rectangle - * covering the whole window. - */ - draw_rect(dr, 0, 0, w*TILE_SIZE + 2*BORDER, h*TILE_SIZE + 2*BORDER, - COL_BACKGROUND); - - if (get_gui_style() == GUI_MASYU) { + if (ui->gui_style == GUI_MASYU) { /* - * Smaller black rectangle which is the main grid. + * Black rectangle which is the main grid. */ draw_rect(dr, BORDER - BORDER_WIDTH, BORDER - BORDER_WIDTH, w*TILE_SIZE + 2*BORDER_WIDTH + 1, @@ -2560,47 +2682,64 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->shared->w, h = state->shared->h, x, y; int black = print_mono_colour(dr, 0); int white = print_mono_colour(dr, 1); - /* No GUI_LOOPY here: only use the familiar masyu style. */ - /* Ick: fake up `ds->tilesize' for macro expansion purposes */ game_drawstate *ds = game_new_drawstate(dr, state); game_set_size(dr, ds, NULL, tilesize); - /* Draw grid outlines (black). */ - for (x = 0; x <= w; x++) - draw_line(dr, COORD(x), COORD(0), COORD(x), COORD(h), black); - for (y = 0; y <= h; y++) - draw_line(dr, COORD(0), COORD(y), COORD(w), COORD(y), black); + if (ui->gui_style == GUI_MASYU) { + /* Draw grid outlines (black). */ + for (x = 0; x <= w; x++) + draw_line(dr, COORD(x), COORD(0), COORD(x), COORD(h), black); + for (y = 0; y <= h; y++) + draw_line(dr, COORD(0), COORD(y), COORD(w), COORD(y), black); + } else { + /* Draw small dots, and dotted lines connecting them. For + * added clarity, try to start and end the dotted lines a + * little way away from the dots. */ + print_line_width(dr, TILE_SIZE / 40); + print_line_dotted(dr, true); + for (x = 0; x < w; x++) { + for (y = 0; y < h; y++) { + int cx = COORD(x) + HALFSZ, cy = COORD(y) + HALFSZ; + draw_circle(dr, cx, cy, tilesize/10, black, black); + if (x+1 < w) + draw_line(dr, cx+tilesize/5, cy, + cx+tilesize-tilesize/5, cy, black); + if (y+1 < h) + draw_line(dr, cx, cy+tilesize/5, + cx, cy+tilesize-tilesize/5, black); + } + } + print_line_dotted(dr, false); + } for (x = 0; x < w; x++) { for (y = 0; y < h; y++) { int cx = COORD(x) + HALFSZ, cy = COORD(y) + HALFSZ; int clue = state->shared->clues[y*w+x]; - draw_lines_specific(dr, ds, x, y, state->lines[y*w+x], 0, black); + draw_lines_specific(dr, ds, ui, x, y, + state->lines[y*w+x], 0, black); if (clue != NOCLUE) { int c = (clue == CORNER) ? black : white; @@ -2633,12 +2772,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2652,7 +2793,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; @@ -2661,7 +2802,7 @@ const struct game thegame = { #include #include -const char *quis = NULL; +static const char *quis = NULL; static void usage(FILE *out) { fprintf(out, "usage: %s \n", quis); @@ -2720,7 +2861,7 @@ static void start_soak(game_params *p, random_state *rs, int nsecs) sfree(clues); } -int main(int argc, const char *argv[]) +int main(int argc, char *argv[]) { game_params *p = NULL; random_state *rs = NULL; diff --git a/apps/plugins/puzzles/src/pegs.R b/apps/plugins/puzzles/src/pegs.R deleted file mode 100644 index 1e79e99ca0..0000000000 --- a/apps/plugins/puzzles/src/pegs.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -PEGS_EXTRA = tree234 - -pegs : [X] GTK COMMON pegs PEGS_EXTRA pegs-icon|no-icon - -pegs : [G] WINDOWS COMMON pegs PEGS_EXTRA pegs.res|noicon.res - -ALL += pegs[COMBINED] PEGS_EXTRA - -!begin am gtk -GAMES += pegs -!end - -!begin >list.c - A(pegs) \ -!end - -!begin >gamedesc.txt -pegs:pegs.exe:Pegs:Peg solitaire puzzle:Jump pegs over each other to remove all but one. -!end diff --git a/apps/plugins/puzzles/src/pegs.c b/apps/plugins/puzzles/src/pegs.c index ec12aa9552..c770bf3076 100644 --- a/apps/plugins/puzzles/src/pegs.c +++ b/apps/plugins/puzzles/src/pegs.c @@ -7,7 +7,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -70,7 +75,11 @@ static game_params *default_params(void) } static const struct game_params pegs_presets[] = { + {5, 7, TYPE_CROSS}, {7, 7, TYPE_CROSS}, + {5, 9, TYPE_CROSS}, + {7, 9, TYPE_CROSS}, + {9, 9, TYPE_CROSS}, {7, 7, TYPE_OCTAGON}, {5, 5, TYPE_RANDOM}, {7, 7, TYPE_RANDOM}, @@ -89,7 +98,7 @@ static bool game_fetch_preset(int i, char **name, game_params **params) *ret = pegs_presets[i]; strcpy(str, pegs_titletypes[ret->type]); - if (ret->type == TYPE_RANDOM) + if (ret->type == TYPE_CROSS || ret->type == TYPE_RANDOM) sprintf(str + strlen(str), " %dx%d", ret->w, ret->h); *name = dupstr(str); @@ -182,14 +191,38 @@ static const char *validate_params(const game_params *params, bool full) { if (full && (params->w <= 3 || params->h <= 3)) return "Width and height must both be greater than three"; + if (params->w < 1 || params->h < 1) + return "Width and height must both be at least one"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; + + /* + * At http://www.gibell.net/pegsolitaire/GenCross/GenCrossBoards0.html + * George I. Bell asserts that various generalised cross-shaped + * boards are soluble starting (and finishing) with the centre + * hole. We permit the symmetric ones. Bell's notation for each + * soluble board is listed. + */ + if (full && params->type == TYPE_CROSS) { + if (!((params->w == 9 && params->h == 5) || /* (3,1,3,1) */ + (params->w == 5 && params->h == 9) || /* (1,3,1,3) */ + (params->w == 9 && params->h == 9) || /* (3,3,3,3) */ + (params->w == 7 && params->h == 5) || /* (2,1,2,1) */ + (params->w == 5 && params->h == 7) || /* (1,2,1,2) */ + (params->w == 9 && params->h == 7) || /* (3,2,3,2) */ + (params->w == 7 && params->h == 9) || /* (2,3,2,3) */ + (params->w == 7 && params->h == 7))) /* (2,2,2,2) */ + return "This board type is only supported at " + "5x7, 5x9, 7x7, 7x9, and 9x9"; + } /* - * It might be possible to implement generalisations of Cross - * and Octagon, but only if I can find a proof that they're all + * It might be possible to implement generalisations of + * Octagon, but only if I can find a proof that they're all * soluble. For the moment, therefore, I'm going to disallow - * them at any size other than the standard one. + * it at any size other than the standard one. */ - if (full && (params->type == TYPE_CROSS || params->type == TYPE_OCTAGON)) { + if (full && params->type == TYPE_OCTAGON) { if (params->w != 7 || params->h != 7) return "This board type is only supported at 7x7"; } @@ -658,12 +691,23 @@ static char *new_game_desc(const game_params *params, random_state *rs, static const char *validate_desc(const game_params *params, const char *desc) { - int len = params->w * params->h; + int len, i, npeg = 0, nhole = 0; + + len = params->w * params->h; if (len != strlen(desc)) return "Game description is wrong length"; if (len != strspn(desc, "PHO")) return "Invalid character in game description"; + for (i = 0; i < len; i++) { + npeg += desc[i] == 'P'; + nhole += desc[i] == 'H'; + } + /* The minimal soluble game has two pegs and a hole: "3x1:PPH". */ + if (npeg < 2) + return "Too few pegs in game description"; + if (nhole < 1) + return "Too few holes in game description"; return NULL; } @@ -706,12 +750,6 @@ static void free_game(game_state *state) sfree(state); } -static char *solve_game(const game_state *state, const game_state *currstate, - const char *aux, const char **error) -{ - return NULL; -} - static bool game_can_format_as_text_now(const game_params *params) { return true; @@ -751,7 +789,7 @@ static game_ui *new_ui(const game_state *state) ui->sx = ui->sy = ui->dx = ui->dy = 0; ui->dragging = false; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->cur_jumping = false; /* make sure we start the cursor somewhere on the grid. */ @@ -775,15 +813,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -800,6 +829,19 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cur_jumping = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int w = state->w; + + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) return ""; + if (ui->cur_jumping) return "Cancel"; + if (state->grid[ui->cur_y*w+ui->cur_x] == GRID_PEG) return "Select"; + } + return ""; +} + #define PREFERRED_TILE_SIZE 33 #define TILESIZE (ds->tilesize) #define BORDER (TILESIZE / 2) @@ -845,16 +887,23 @@ static char *interpret_move(const game_state *state, game_ui *ui, tx = FROMCOORD(x); ty = FROMCOORD(y); - if (tx >= 0 && tx < w && ty >= 0 && ty < h && - state->grid[ty*w+tx] == GRID_PEG) { - ui->dragging = true; - ui->sx = tx; - ui->sy = ty; - ui->dx = x; - ui->dy = y; - ui->cur_visible = false; - ui->cur_jumping = false; - return UI_UPDATE; + if (tx >= 0 && tx < w && ty >= 0 && ty < h) { + switch (state->grid[ty*w+tx]) { + case GRID_PEG: + ui->dragging = true; + ui->sx = tx; + ui->sy = ty; + ui->dx = x; + ui->dy = y; + ui->cur_visible = false; + ui->cur_jumping = false; + return MOVE_UI_UPDATE; + case GRID_HOLE: + return MOVE_NO_EFFECT; + case GRID_OBST: + default: + return MOVE_UNUSED; + } } } else if (button == LEFT_DRAG && ui->dragging) { /* @@ -862,7 +911,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, */ ui->dx = x; ui->dy = y; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (button == LEFT_RELEASE && ui->dragging) { int tx, ty, dx, dy; @@ -874,18 +923,18 @@ static char *interpret_move(const game_state *state, game_ui *ui, tx = FROMCOORD(x); ty = FROMCOORD(y); if (tx < 0 || tx >= w || ty < 0 || ty >= h) - return UI_UPDATE; /* target out of range */ + return MOVE_UI_UPDATE; /* target out of range */ dx = tx - ui->sx; dy = ty - ui->sy; if (max(abs(dx),abs(dy)) != 2 || min(abs(dx),abs(dy)) != 0) - return UI_UPDATE; /* move length was wrong */ + return MOVE_UI_UPDATE; /* move length was wrong */ dx /= 2; dy /= 2; if (state->grid[ty*w+tx] != GRID_HOLE || state->grid[(ty-dy)*w+(tx-dx)] != GRID_PEG || state->grid[ui->sy*w+ui->sx] != GRID_PEG) - return UI_UPDATE; /* grid contents were invalid */ + return MOVE_UI_UPDATE; /* grid contents were invalid */ /* * We have a valid move. Encode it simply as source and @@ -898,14 +947,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, /* Not jumping; move cursor as usual, making sure we don't * leave the gameboard (which may be an irregular shape) */ int cx = ui->cur_x, cy = ui->cur_y; - move_cursor(button, &cx, &cy, w, h, false); + move_cursor(button, &cx, &cy, w, h, false, NULL); ui->cur_visible = true; if (state->grid[cy*w+cx] == GRID_HOLE || state->grid[cy*w+cx] == GRID_PEG) { ui->cur_x = cx; ui->cur_y = cy; } - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { int dx, dy, mx, my, jx, jy; @@ -928,26 +977,26 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->cur_x = jx; ui->cur_y = jy; return dupstr(buf); } - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->cur_jumping) { ui->cur_jumping = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (state->grid[ui->cur_y*w+ui->cur_x] == GRID_PEG) { - /* cursor is on peg: next arrow-move wil jump. */ + /* cursor is on peg: next arrow-move will jump. */ ui->cur_jumping = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } - return NULL; + return MOVE_NO_EFFECT; } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -1006,7 +1055,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1135,10 +1184,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } if (!ds->started) { - draw_rect(dr, 0, 0, - TILESIZE * state->w + 2 * BORDER, - TILESIZE * state->h + 2 * BORDER, COL_BACKGROUND); - /* * Draw relief marks around all the squares that aren't * GRID_OBST. @@ -1302,19 +1347,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame pegs #endif @@ -1334,14 +1366,16 @@ const struct game thegame = { new_game, dup_game, free_game, - false, solve_game, + false, NULL, /* solve */ true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1353,9 +1387,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/penrose-internal.h b/apps/plugins/puzzles/src/penrose-internal.h new file mode 100644 index 0000000000..984cd35711 --- /dev/null +++ b/apps/plugins/puzzles/src/penrose-internal.h @@ -0,0 +1,289 @@ +#include "penrose.h" + +static inline unsigned num_subtriangles(char t) +{ + return (t == 'A' || t == 'B' || t == 'X' || t == 'Y') ? 3 : 2; +} + +static inline unsigned sibling_edge(char t) +{ + switch (t) { + case 'A': case 'U': return 2; + case 'B': case 'V': return 1; + default: return 0; + } +} + +/* + * Coordinate system for tracking Penrose-tile half-triangles. + * PenroseCoords simply stores an array of triangle types. + */ +typedef struct PenroseCoords { + char *c; + size_t nc, csize; +} PenroseCoords; + +PenroseCoords *penrose_coords_new(void); +void penrose_coords_free(PenroseCoords *pc); +void penrose_coords_make_space(PenroseCoords *pc, size_t size); +PenroseCoords *penrose_coords_copy(PenroseCoords *pc_in); + +/* + * Coordinate system for locating Penrose tiles in the plane. + * + * The 'Point' structure represents a single point by means of an + * integer linear combination of {1, t, t^2, t^3}, where t is the + * complex number exp(i pi/5) representing 1/10 of a turn about the + * origin. + * + * The 'PenroseTriangle' structure represents a half-tile triangle, + * giving both the locations of its vertices and its combinatorial + * coordinates. It also contains a linked-list pointer and a boolean + * flag, used during breadth-first search to generate all the tiles in + * an area and report them exactly once. + */ +typedef struct Point { + int coeffs[4]; +} Point; +typedef struct PenroseTriangle PenroseTriangle; +struct PenroseTriangle { + Point vertices[3]; + PenroseCoords *pc; + PenroseTriangle *next; /* used in breadth-first search */ + bool reported; +}; + +/* Fill in all the coordinates of a triangle starting from any single edge. + * Requires tri->pc to have been filled in, so that we know which shape of + * triangle we're placing. */ +void penrose_place(PenroseTriangle *tri, Point u, Point v, int index_of_u); + +/* Free a PenroseHalf and its contained coordinates, or a whole PenroseTile */ +void penrose_free(PenroseTriangle *tri); + +/* + * A Point is really a complex number, so we can add, subtract and + * multiply them. + */ +static inline Point point_add(Point a, Point b) +{ + Point r; + size_t i; + for (i = 0; i < 4; i++) + r.coeffs[i] = a.coeffs[i] + b.coeffs[i]; + return r; +} +static inline Point point_sub(Point a, Point b) +{ + Point r; + size_t i; + for (i = 0; i < 4; i++) + r.coeffs[i] = a.coeffs[i] - b.coeffs[i]; + return r; +} +static inline Point point_mul_by_t(Point x) +{ + Point r; + /* Multiply by t by using the identity t^4 - t^3 + t^2 - t + 1 = 0, + * so t^4 = t^3 - t^2 + t - 1 */ + r.coeffs[0] = -x.coeffs[3]; + r.coeffs[1] = x.coeffs[0] + x.coeffs[3]; + r.coeffs[2] = x.coeffs[1] - x.coeffs[3]; + r.coeffs[3] = x.coeffs[2] + x.coeffs[3]; + return r; +} +static inline Point point_mul(Point a, Point b) +{ + size_t i, j; + Point r; + + /* Initialise r to be a, scaled by b's t^3 term */ + for (j = 0; j < 4; j++) + r.coeffs[j] = a.coeffs[j] * b.coeffs[3]; + + /* Now iterate r = t*r + (next coefficient down), by Horner's rule */ + for (i = 3; i-- > 0 ;) { + r = point_mul_by_t(r); + for (j = 0; j < 4; j++) + r.coeffs[j] += a.coeffs[j] * b.coeffs[i]; + } + + return r; +} +static inline bool point_equal(Point a, Point b) +{ + size_t i; + for (i = 0; i < 4; i++) + if (a.coeffs[i] != b.coeffs[i]) + return false; + return true; +} + +/* + * Return the Point corresponding to a rotation of s steps around the + * origin, i.e. a rotation by 36*s degrees or s*pi/5 radians. + */ +static inline Point point_rot(int s) +{ + Point r = {{ 1, 0, 0, 0 }}; + Point tpower = {{ 0, 1, 0, 0 }}; + + /* Reduce to a sensible range */ + s = s % 10; + if (s < 0) + s += 10; + + while (true) { + if (s & 1) + r = point_mul(r, tpower); + s >>= 1; + if (!s) + break; + tpower = point_mul(tpower, tpower); + } + + return r; +} + +/* + * PenroseContext is the shared context of a whole run of the + * algorithm. Its 'prototype' PenroseCoords object represents the + * coordinates of the starting triangle, and is extended as necessary; + * any other PenroseCoord that needs extending will copy the + * higher-order values from ctx->prototype as needed, so that once + * each choice has been made, it remains consistent. + * + * When we're inventing a random piece of tiling in the first place, + * we append to ctx->prototype by choosing a random (but legal) + * higher-level metatile for the current topmost one to turn out to be + * part of. When we're replaying a generation whose parameters are + * already stored, we don't have a random_state, and we make fixed + * decisions if not enough coordinates were provided, as in the + * corresponding hat.c system. + * + * For a normal (non-testing) caller, penrosectx_generate() is the + * main useful function. It breadth-first searches a whole area to + * generate all the triangles in it, starting from a (typically + * central) one with the coordinates of ctx->prototype. It takes two + * callback function: one that checks whether a triangle is within the + * bounds of the target area (and therefore the search should continue + * exploring its neighbours), and another that reports a full Penrose + * tile once both of its halves have been found and determined to be + * in bounds. + */ +typedef struct PenroseContext { + random_state *rs; + bool must_free_rs; + unsigned start_vertex; /* which vertex of 'prototype' is at the origin? */ + int orientation; /* orientation to put in PenrosePatchParams */ + PenroseCoords *prototype; +} PenroseContext; + +void penrosectx_init_random(PenroseContext *ctx, random_state *rs, int which); +void penrosectx_init_from_params( + PenroseContext *ctx, const struct PenrosePatchParams *ps); +void penrosectx_cleanup(PenroseContext *ctx); +PenroseCoords *penrosectx_initial_coords(PenroseContext *ctx); +void penrosectx_extend_coords(PenroseContext *ctx, PenroseCoords *pc, + size_t n); +void penrosectx_step(PenroseContext *ctx, PenroseCoords *pc, + unsigned edge, unsigned *outedge); +void penrosectx_generate( + PenroseContext *ctx, + bool (*inbounds)(void *inboundsctx, + const PenroseTriangle *tri), void *inboundsctx, + void (*tile)(void *tilectx, const Point *vertices), void *tilectx); + +/* Subroutines that step around the tiling specified by a PenroseCtx, + * delivering both plane and combinatorial coordinates as they go */ +PenroseTriangle *penrose_initial(PenroseContext *ctx); +PenroseTriangle *penrose_adjacent(PenroseContext *ctx, + const PenroseTriangle *src_spec, + unsigned src_edge, unsigned *dst_edge); + +/* For extracting the point coordinates */ +typedef struct Coord { + int c1, cr5; /* coefficients of 1 and sqrt(5) respectively */ +} Coord; + +static inline Coord point_x(Point p) +{ + Coord x = { + 4 * p.coeffs[0] + p.coeffs[1] - p.coeffs[2] + p.coeffs[3], + p.coeffs[1] + p.coeffs[2] - p.coeffs[3], + }; + return x; +} + +static inline Coord point_y(Point p) +{ + Coord y = { + 2 * p.coeffs[1] + p.coeffs[2] + p.coeffs[3], + p.coeffs[2] + p.coeffs[3], + }; + return y; +} + +static inline int coord_sign(Coord x) +{ + if (x.c1 == 0 && x.cr5 == 0) + return 0; + if (x.c1 >= 0 && x.cr5 >= 0) + return +1; + if (x.c1 <= 0 && x.cr5 <= 0) + return -1; + + if (x.c1 * x.c1 > 5 * x.cr5 * x.cr5) + return x.c1 < 0 ? -1 : +1; + else + return x.cr5 < 0 ? -1 : +1; +} + +static inline Coord coord_construct(int c1, int cr5) +{ + Coord c = { c1, cr5 }; + return c; +} + +static inline Coord coord_integer(int c1) +{ + return coord_construct(c1, 0); +} + +static inline Coord coord_add(Coord a, Coord b) +{ + Coord sum; + sum.c1 = a.c1 + b.c1; + sum.cr5 = a.cr5 + b.cr5; + return sum; +} + +static inline Coord coord_sub(Coord a, Coord b) +{ + Coord diff; + diff.c1 = a.c1 - b.c1; + diff.cr5 = a.cr5 - b.cr5; + return diff; +} + +static inline Coord coord_mul(Coord a, Coord b) +{ + Coord prod; + prod.c1 = a.c1 * b.c1 + 5 * a.cr5 * b.cr5; + prod.cr5 = a.c1 * b.cr5 + a.cr5 * b.c1; + return prod; +} + +static inline Coord coord_abs(Coord a) +{ + int sign = coord_sign(a); + Coord abs; + abs.c1 = a.c1 * sign; + abs.cr5 = a.cr5 * sign; + return abs; +} + +static inline int coord_cmp(Coord a, Coord b) +{ + return coord_sign(coord_sub(a, b)); +} diff --git a/apps/plugins/puzzles/src/penrose-legacy.c b/apps/plugins/puzzles/src/penrose-legacy.c new file mode 100644 index 0000000000..709d68d7f5 --- /dev/null +++ b/apps/plugins/puzzles/src/penrose-legacy.c @@ -0,0 +1,506 @@ +/* penrose-legacy.c: legacy Penrose tile generator. + * + * Works by choosing a small patch from a recursively expanded large + * region of tiling, using one of the two algorithms described at + * + * https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-tilings/ + * + * This method of generating Penrose tiling fragments is superseded by + * the completely different algorithm in penrose.c, using the other + * algorithm in that article (the 'combinatorial coordinates' one). We + * keep the legacy algorithm around only for interpreting Loopy game + * IDs generated by older versions of the code. + */ + +#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif +#include + +#include "puzzles.h" /* for malloc routines, and PI */ +#include "penrose-legacy.h" + +/* ------------------------------------------------------- + * 36-degree basis vector arithmetic routines. + */ + +/* Imagine drawing a + * ten-point 'clock face' like this: + * + * -E + * -D | A + * \ | / + * -C. \ | / ,B + * `-._\|/_,-' + * ,-' /|\ `-. + * -B' / | \ `C + * / | \ + * -A | D + * E + * + * In case the ASCII art isn't clear, those are supposed to be ten + * vectors of length 1, all sticking out from the origin at equal + * angular spacing (hence 36 degrees). Our basis vectors are A,B,C,D (I + * choose them to be symmetric about the x-axis so that the final + * translation into 2d coordinates will also be symmetric, which I + * think will avoid minor rounding uglinesses), so our vector + * representation sets + * + * A = (1,0,0,0) + * B = (0,1,0,0) + * C = (0,0,1,0) + * D = (0,0,0,1) + * + * The fifth vector E looks at first glance as if it needs to be + * another basis vector, but in fact it doesn't, because it can be + * represented in terms of the other four. Imagine starting from the + * origin and following the path -A, +B, -C, +D: you'll find you've + * traced four sides of a pentagram, and ended up one E-vector away + * from the origin. So we have + * + * E = (-1,1,-1,1) + * + * This tells us that we can rotate any vector in this system by 36 + * degrees: if we start with a*A + b*B + c*C + d*D, we want to end up + * with a*B + b*C + c*D + d*E, and we substitute our identity for E to + * turn that into a*B + b*C + c*D + d*(-A+B-C+D). In other words, + * + * rotate_one_notch_clockwise(a,b,c,d) = (-d, d+a, -d+b, d+c) + * + * and you can verify for yourself that applying that operation + * repeatedly starting with (1,0,0,0) cycles round ten vectors and + * comes back to where it started. + * + * The other operation that may be required is to construct vectors + * with lengths that are multiples of phi. That can be done by + * observing that the vector C-B is parallel to E and has length 1/phi, + * and the vector D-A is parallel to E and has length phi. So this + * tells us that given any vector, we can construct one which points in + * the same direction and is 1/phi or phi times its length, like this: + * + * divide_by_phi(vector) = rotate(vector, 2) - rotate(vector, 3) + * multiply_by_phi(vector) = rotate(vector, 1) - rotate(vector, 4) + * + * where rotate(vector, n) means applying the above + * rotate_one_notch_clockwise primitive n times. Expanding out the + * applications of rotate gives the following direct representation in + * terms of the vector coordinates: + * + * divide_by_phi(a,b,c,d) = (b-d, c+d-b, a+b-c, c-a) + * multiply_by_phi(a,b,c,d) = (a+b-d, c+d, a+b, c+d-a) + * + * and you can verify for yourself that those two operations are + * inverses of each other (as you'd hope!). + * + * Having done all of this, testing for equality between two vectors is + * a trivial matter of comparing the four integer coordinates. (Which + * it _wouldn't_ have been if we'd kept E as a fifth basis vector, + * because then (-1,1,-1,1,0) and (0,0,0,0,1) would have had to be + * considered identical. So leaving E out is vital.) + */ + +struct vector { int a, b, c, d; }; + +static vector v_origin(void) +{ + vector v; + v.a = v.b = v.c = v.d = 0; + return v; +} + +/* We start with a unit vector of B: this means we can easily + * draw an isoceles triangle centred on the X axis. */ +#ifdef TEST_VECTORS + +static vector v_unit(void) +{ + vector v; + + v.b = 1; + v.a = v.c = v.d = 0; + return v; +} + +#endif + +#define COS54 0.5877852 +#define SIN54 0.8090169 +#define COS18 0.9510565 +#define SIN18 0.3090169 + +/* These two are a bit rough-and-ready for now. Note that B/C are + * 18 degrees from the x-axis, and A/D are 54 degrees. */ +double penrose_legacy_vx(vector *vs, int i) +{ + return (vs[i].a + vs[i].d) * COS54 + + (vs[i].b + vs[i].c) * COS18; +} + +double penrose_legacy_vy(vector *vs, int i) +{ + return (vs[i].a - vs[i].d) * SIN54 + + (vs[i].b - vs[i].c) * SIN18; + +} + +static vector v_trans(vector v, vector trans) +{ + v.a += trans.a; + v.b += trans.b; + v.c += trans.c; + v.d += trans.d; + return v; +} + +static vector v_rotate_36(vector v) +{ + vector vv; + vv.a = -v.d; + vv.b = v.d + v.a; + vv.c = -v.d + v.b; + vv.d = v.d + v.c; + return vv; +} + +static vector v_rotate(vector v, int ang) +{ + int i; + + assert((ang % 36) == 0); + while (ang < 0) ang += 360; + ang = 360-ang; + for (i = 0; i < (ang/36); i++) + v = v_rotate_36(v); + return v; +} + +#ifdef TEST_VECTORS + +static vector v_scale(vector v, int sc) +{ + v.a *= sc; + v.b *= sc; + v.c *= sc; + v.d *= sc; + return v; +} + +#endif + +static vector v_growphi(vector v) +{ + vector vv; + vv.a = v.a + v.b - v.d; + vv.b = v.c + v.d; + vv.c = v.a + v.b; + vv.d = v.c + v.d - v.a; + return vv; +} + +static vector v_shrinkphi(vector v) +{ + vector vv; + vv.a = v.b - v.d; + vv.b = v.c + v.d - v.b; + vv.c = v.a + v.b - v.c; + vv.d = v.c - v.a; + return vv; +} + +#ifdef TEST_VECTORS + +static const char *v_debug(vector v) +{ + static char buf[255]; + sprintf(buf, + "(%d,%d,%d,%d)[%2.2f,%2.2f]", + v.a, v.b, v.c, v.d, v_x(&v,0), v_y(&v,0)); + return buf; +} + +#endif + +/* ------------------------------------------------------- + * Tiling routines. + */ + +static vector xform_coord(vector vo, int shrink, vector vtrans, int ang) +{ + if (shrink < 0) + vo = v_shrinkphi(vo); + else if (shrink > 0) + vo = v_growphi(vo); + + vo = v_rotate(vo, ang); + vo = v_trans(vo, vtrans); + + return vo; +} + + +#define XFORM(n,o,s,a) vs[(n)] = xform_coord(v_edge, (s), vs[(o)], (a)) + +static int penrose_p2_small(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge); + +static int penrose_p2_large(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge) +{ + vector vv_orig, vv_edge; + +#ifdef DEBUG_PENROSE + { + vector vs[3]; + vs[0] = v_orig; + XFORM(1, 0, 0, 0); + XFORM(2, 0, 0, -36*flip); + + state->new_tile(state, vs, 3, depth); + } +#endif + + if (flip > 0) { + vector vs[4]; + + vs[0] = v_orig; + XFORM(1, 0, 0, -36); + XFORM(2, 0, 0, 0); + XFORM(3, 0, 0, 36); + + state->new_tile(state, vs, 4, depth); + } + if (depth >= state->max_depth) return 0; + + vv_orig = v_trans(v_orig, v_rotate(v_edge, -36*flip)); + vv_edge = v_rotate(v_edge, 108*flip); + + penrose_p2_small(state, depth+1, flip, + v_orig, v_shrinkphi(v_edge)); + + penrose_p2_large(state, depth+1, flip, + vv_orig, v_shrinkphi(vv_edge)); + penrose_p2_large(state, depth+1, -flip, + vv_orig, v_shrinkphi(vv_edge)); + + return 0; +} + +static int penrose_p2_small(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge) +{ + vector vv_orig; + +#ifdef DEBUG_PENROSE + { + vector vs[3]; + vs[0] = v_orig; + XFORM(1, 0, 0, 0); + XFORM(2, 0, -1, -36*flip); + + state->new_tile(state, vs, 3, depth); + } +#endif + + if (flip > 0) { + vector vs[4]; + + vs[0] = v_orig; + XFORM(1, 0, 0, -72); + XFORM(2, 0, -1, -36); + XFORM(3, 0, 0, 0); + + state->new_tile(state, vs, 4, depth); + } + + if (depth >= state->max_depth) return 0; + + vv_orig = v_trans(v_orig, v_edge); + + penrose_p2_large(state, depth+1, -flip, + v_orig, v_shrinkphi(v_rotate(v_edge, -36*flip))); + + penrose_p2_small(state, depth+1, flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, -144*flip))); + + return 0; +} + +static int penrose_p3_small(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge); + +static int penrose_p3_large(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge) +{ + vector vv_orig; + +#ifdef DEBUG_PENROSE + { + vector vs[3]; + vs[0] = v_orig; + XFORM(1, 0, 1, 0); + XFORM(2, 0, 0, -36*flip); + + state->new_tile(state, vs, 3, depth); + } +#endif + + if (flip > 0) { + vector vs[4]; + + vs[0] = v_orig; + XFORM(1, 0, 0, -36); + XFORM(2, 0, 1, 0); + XFORM(3, 0, 0, 36); + + state->new_tile(state, vs, 4, depth); + } + if (depth >= state->max_depth) return 0; + + vv_orig = v_trans(v_orig, v_edge); + + penrose_p3_large(state, depth+1, -flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, 180))); + + penrose_p3_small(state, depth+1, flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, -108*flip))); + + vv_orig = v_trans(v_orig, v_growphi(v_edge)); + + penrose_p3_large(state, depth+1, flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, -144*flip))); + + + return 0; +} + +static int penrose_p3_small(penrose_legacy_state *state, int depth, int flip, + vector v_orig, vector v_edge) +{ + vector vv_orig; + +#ifdef DEBUG_PENROSE + { + vector vs[3]; + vs[0] = v_orig; + XFORM(1, 0, 0, 0); + XFORM(2, 0, 0, -36*flip); + + state->new_tile(state, vs, 3, depth); + } +#endif + + if (flip > 0) { + vector vs[4]; + + vs[0] = v_orig; + XFORM(1, 0, 0, -36); + XFORM(3, 0, 0, 0); + XFORM(2, 3, 0, -36); + + state->new_tile(state, vs, 4, depth); + } + if (depth >= state->max_depth) return 0; + + /* NB these two are identical to the first two of p3_large. */ + vv_orig = v_trans(v_orig, v_edge); + + penrose_p3_large(state, depth+1, -flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, 180))); + + penrose_p3_small(state, depth+1, flip, + vv_orig, v_shrinkphi(v_rotate(v_edge, -108*flip))); + + return 0; +} + +/* ------------------------------------------------------- + * Utility routines. + */ + +double penrose_legacy_side_length(double start_size, int depth) +{ + return start_size / pow(PHI, depth); +} + +/* + * It turns out that an acute isosceles triangle with sides in ratio 1:phi:phi + * has an incentre which is conveniently 2*phi^-2 of the way from the apex to + * the base. Why's that convenient? Because: if we situate the incentre of the + * triangle at the origin, then we can place the apex at phi^-2 * (B+C), and + * the other two vertices at apex-B and apex-C respectively. So that's an acute + * triangle with its long sides of unit length, covering a circle about the + * origin of radius 1-(2*phi^-2), which is conveniently enough phi^-3. + * + * (later mail: this is an overestimate by about 5%) + */ + +int penrose_legacy(penrose_legacy_state *state, int which, int angle) +{ + vector vo = v_origin(); + vector vb = v_origin(); + + vo.b = vo.c = -state->start_size; + vo = v_shrinkphi(v_shrinkphi(vo)); + + vb.b = state->start_size; + + vo = v_rotate(vo, angle); + vb = v_rotate(vb, angle); + + if (which == PENROSE_P2) + return penrose_p2_large(state, 0, 1, vo, vb); + else + return penrose_p3_small(state, 0, 1, vo, vb); +} + +/* + * We're asked for a MxN grid, which just means a tiling fitting into roughly + * an MxN space in some kind of reasonable unit - say, the side length of the + * two-arrow edges of the tiles. By some reasoning in a previous email, that + * means we want to pick some subarea of a circle of radius 3.11*sqrt(M^2+N^2). + * To cover that circle, we need to subdivide a triangle large enough that it + * contains a circle of that radius. + * + * Hence: start with those three vectors marking triangle vertices, scale them + * all up by phi repeatedly until the radius of the inscribed circle gets + * bigger than the target, and then recurse into that triangle with the same + * recursion depth as the number of times you scaled up. That will give you + * tiles of unit side length, covering a circle big enough that if you randomly + * choose an orientation and coordinates within the circle, you'll be able to + * get any valid piece of Penrose tiling of size MxN. + */ +#define INCIRCLE_RADIUS 0.22426 /* phi^-3 less 5%: see above */ + +void penrose_legacy_calculate_size( + int which, int tilesize, int w, int h, + double *required_radius, int *start_size, int *depth) +{ + double rradius, size; + int n = 0; + + /* + * Fudge factor to scale P2 and P3 tilings differently. This + * doesn't seem to have much relevance to questions like the + * average number of tiles per unit area; it's just aesthetic. + */ + if (which == PENROSE_P2) + tilesize = tilesize * 3 / 2; + else + tilesize = tilesize * 5 / 4; + + rradius = tilesize * 3.11 * sqrt((double)(w*w + h*h)); + size = tilesize; + + while ((size * INCIRCLE_RADIUS) < rradius) { + n++; + size = size * PHI; + } + + *start_size = (int)size; + *depth = n; + *required_radius = rradius; +} diff --git a/apps/plugins/puzzles/src/penrose-legacy.h b/apps/plugins/puzzles/src/penrose-legacy.h new file mode 100644 index 0000000000..514fd8b592 --- /dev/null +++ b/apps/plugins/puzzles/src/penrose-legacy.h @@ -0,0 +1,63 @@ +/* penrose-legacy.h: legacy Penrose tiling functions. + * + * Provides an interface with which to generate Penrose tilings + * by recursive subdivision of an initial tile of choice (one of the + * four sets of two pairs kite/dart, or thin/thick rhombus). + * + * You supply a callback function and a context pointer, which is + * called with each tile in turn: you choose how many times to recurse. + * + * This method of generating Penrose tiling fragments is superseded by + * the completely different algorithm in penrose.c. We keep the legacy + * algorithm around only for interpreting Loopy game IDs generated by + * older versions of the code. + */ + +#ifndef PUZZLES_PENROSE_LEGACY_H +#define PUZZLES_PENROSE_LEGACY_H + +#ifndef PHI +#define PHI 1.6180339887 +#endif + +typedef struct vector vector; + +double penrose_legacy_vx(vector *vs, int i); +double penrose_legacy_vy(vector *vs, int i); + +typedef struct penrose_legacy_state penrose_legacy_state; + +/* Return non-zero to clip the tree here (i.e. not recurse + * below this tile). + * + * Parameters are state, vector array, npoints, depth. + * ctx is inside state. + */ +typedef int (*tile_callback)(penrose_legacy_state *, vector *, int, int); + +struct penrose_legacy_state { + int start_size; /* initial side length */ + int max_depth; /* Recursion depth */ + + tile_callback new_tile; + void *ctx; /* for callback */ +}; + +#ifndef PENROSE_ENUM_DEFINED +#define PENROSE_ENUM_DEFINED +enum { PENROSE_P2, PENROSE_P3 }; +#endif + +extern int penrose_legacy(penrose_legacy_state *state, int which, int angle); + +/* Returns the side-length of a penrose tile at recursion level + * gen, given a starting side length. */ +extern double penrose_legacy_side_length(double start_size, int depth); + +/* Calculate start size and recursion depth required to produce a + * width-by-height sized patch of penrose tiles with the given tilesize */ +extern void penrose_legacy_calculate_size( + int which, int tilesize, int w, int h, + double *required_radius, int *start_size, int *depth); + +#endif diff --git a/apps/plugins/puzzles/src/penrose.c b/apps/plugins/puzzles/src/penrose.c index ccde30d8b4..4d7dcc4347 100644 --- a/apps/plugins/puzzles/src/penrose.c +++ b/apps/plugins/puzzles/src/penrose.c @@ -1,629 +1,894 @@ -/* penrose.c - * - * Penrose tile generator. +/* + * Generate Penrose tilings via combinatorial coordinates. * - * Uses half-tile technique outlined on: + * For general explanation of the algorithm: + * https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-tilings/ * - * http://tartarus.org/simon/20110412-penrose/penrose.xhtml + * I use exactly the same indexing system here that's described in the + * article. For the P2 tiling, acute isosceles triangles (half-kites) + * are assigned letters A,B, and obtuse ones (half-darts) U,V; for P3, + * acute triangles (half of a thin rhomb) are C,D and obtuse ones + * (half a thick rhomb) are X,Y. Edges of all triangles are indexed + * anticlockwise around the triangle, with 0 being the base and 1,2 + * being the two equal legs. */ #include +#include #include -#include -#include -#include "puzzles.h" /* for malloc routines, and PI */ +#include "puzzles.h" #include "penrose.h" +#include "penrose-internal.h" +#include "tree234.h" -/* ------------------------------------------------------- - * 36-degree basis vector arithmetic routines. - */ +bool penrose_valid_letter(char c, int which) +{ + switch (c) { + case 'A': case 'B': case 'U': case 'V': + return which == PENROSE_P2; + case 'C': case 'D': case 'X': case 'Y': + return which == PENROSE_P3; + default: + return false; + } +} -/* Imagine drawing a - * ten-point 'clock face' like this: - * - * -E - * -D | A - * \ | / - * -C. \ | / ,B - * `-._\|/_,-' - * ,-' /|\ `-. - * -B' / | \ `C - * / | \ - * -A | D - * E - * - * In case the ASCII art isn't clear, those are supposed to be ten - * vectors of length 1, all sticking out from the origin at equal - * angular spacing (hence 36 degrees). Our basis vectors are A,B,C,D (I - * choose them to be symmetric about the x-axis so that the final - * translation into 2d coordinates will also be symmetric, which I - * think will avoid minor rounding uglinesses), so our vector - * representation sets - * - * A = (1,0,0,0) - * B = (0,1,0,0) - * C = (0,0,1,0) - * D = (0,0,0,1) - * - * The fifth vector E looks at first glance as if it needs to be - * another basis vector, but in fact it doesn't, because it can be - * represented in terms of the other four. Imagine starting from the - * origin and following the path -A, +B, -C, +D: you'll find you've - * traced four sides of a pentagram, and ended up one E-vector away - * from the origin. So we have - * - * E = (-1,1,-1,1) - * - * This tells us that we can rotate any vector in this system by 36 - * degrees: if we start with a*A + b*B + c*C + d*D, we want to end up - * with a*B + b*C + c*D + d*E, and we substitute our identity for E to - * turn that into a*B + b*C + c*D + d*(-A+B-C+D). In other words, - * - * rotate_one_notch_clockwise(a,b,c,d) = (-d, d+a, -d+b, d+c) - * - * and you can verify for yourself that applying that operation - * repeatedly starting with (1,0,0,0) cycles round ten vectors and - * comes back to where it started. - * - * The other operation that may be required is to construct vectors - * with lengths that are multiples of phi. That can be done by - * observing that the vector C-B is parallel to E and has length 1/phi, - * and the vector D-A is parallel to E and has length phi. So this - * tells us that given any vector, we can construct one which points in - * the same direction and is 1/phi or phi times its length, like this: - * - * divide_by_phi(vector) = rotate(vector, 2) - rotate(vector, 3) - * multiply_by_phi(vector) = rotate(vector, 1) - rotate(vector, 4) - * - * where rotate(vector, n) means applying the above - * rotate_one_notch_clockwise primitive n times. Expanding out the - * applications of rotate gives the following direct representation in - * terms of the vector coordinates: - * - * divide_by_phi(a,b,c,d) = (b-d, c+d-b, a+b-c, c-a) - * multiply_by_phi(a,b,c,d) = (a+b-d, c+d, a+b, c+d-a) - * - * and you can verify for yourself that those two operations are - * inverses of each other (as you'd hope!). +/* + * Result of attempting a transition within the coordinate system. + * INTERNAL means we've moved to a different child of the same parent, + * so the 'internal' substructure gives the type of the new triangle + * and which edge of it we came in through; EXTERNAL means we've moved + * out of the parent entirely, and the 'external' substructure tells + * us which edge of the parent triangle we left by, and if it's + * divided in two, which end of that edge (-1 for the left end or +1 + * for the right end). If the parent edge is undivided, end == 0. * - * Having done all of this, testing for equality between two vectors is - * a trivial matter of comparing the four integer coordinates. (Which - * it _wouldn't_ have been if we'd kept E as a fifth basis vector, - * because then (-1,1,-1,1,0) and (0,0,0,0,1) would have had to be - * considered identical. So leaving E out is vital.) + * The type FAIL _shouldn't_ ever come up! It occurs if you try to + * compute an incoming transition with an illegal value of 'end' (i.e. + * having the wrong idea of whether the edge is divided), or if you + * refer to a child triangle type that doesn't exist in that parent. + * If it ever happens in the production code then an assertion will + * fail. But it might be useful to other users of the same code. */ - -struct vector { int a, b, c, d; }; - -static vector v_origin(void) +typedef struct TransitionResult { + enum { INTERNAL, EXTERNAL, FAIL } type; + union { + struct { + char new_child; + unsigned char new_edge; + } internal; + struct { + unsigned char parent_edge; + signed char end; + } external; + } u; +} TransitionResult; + +/* Construction function to make an INTERNAL-type TransitionResult */ +static inline TransitionResult internal(char new_child, unsigned new_edge) { - vector v; - v.a = v.b = v.c = v.d = 0; - return v; + TransitionResult tr; + tr.type = INTERNAL; + tr.u.internal.new_child = new_child; + tr.u.internal.new_edge = new_edge; + return tr; } -/* We start with a unit vector of B: this means we can easily - * draw an isoceles triangle centred on the X axis. */ -#ifdef TEST_VECTORS +/* Construction function to make an EXTERNAL-type TransitionResult */ +static inline TransitionResult external(unsigned parent_edge, int end) +{ + TransitionResult tr; + tr.type = EXTERNAL; + tr.u.external.parent_edge = parent_edge; + tr.u.external.end = end; + return tr; +} -static vector v_unit(void) +/* Construction function to make a FAIL-type TransitionResult */ +static inline TransitionResult fail(void) { - vector v; + TransitionResult tr; + tr.type = FAIL; + return tr; +} - v.b = 1; - v.a = v.c = v.d = 0; - return v; +/* + * Compute a transition out of a triangle. Can return either INTERNAL + * or EXTERNAL types (or FAIL if it gets invalid data). + */ +static TransitionResult transition(char parent, char child, unsigned edge) +{ + switch (parent) { + case 'A': + switch (child) { + case 'A': + switch (edge) { + case 0: return external(2, -1); + case 1: return external(0, 0); + case 2: return internal('B', 1); + } + case 'B': + switch (edge) { + case 0: return internal('U', 1); + case 1: return internal('A', 2); + case 2: return external(1, +1); + } + case 'U': + switch (edge) { + case 0: return external(2, +1); + case 1: return internal('B', 0); + case 2: return external(1, -1); + } + default: + return fail(); + } + case 'B': + switch (child) { + case 'A': + switch (edge) { + case 0: return internal('V', 2); + case 1: return external(2, -1); + case 2: return internal('B', 1); + } + case 'B': + switch (edge) { + case 0: return external(1, +1); + case 1: return internal('A', 2); + case 2: return external(0, 0); + } + case 'V': + switch (edge) { + case 0: return external(1, -1); + case 1: return external(2, +1); + case 2: return internal('A', 0); + } + default: + return fail(); + } + case 'U': + switch (child) { + case 'B': + switch (edge) { + case 0: return internal('U', 1); + case 1: return external(2, 0); + case 2: return external(0, +1); + } + case 'U': + switch (edge) { + case 0: return external(1, 0); + case 1: return internal('B', 0); + case 2: return external(0, -1); + } + default: + return fail(); + } + case 'V': + switch (child) { + case 'A': + switch (edge) { + case 0: return internal('V', 2); + case 1: return external(0, -1); + case 2: return external(1, 0); + } + case 'V': + switch (edge) { + case 0: return external(2, 0); + case 1: return external(0, +1); + case 2: return internal('A', 0); + } + default: + return fail(); + } + case 'C': + switch (child) { + case 'C': + switch (edge) { + case 0: return external(1, +1); + case 1: return internal('Y', 1); + case 2: return external(0, 0); + } + case 'Y': + switch (edge) { + case 0: return external(2, 0); + case 1: return internal('C', 1); + case 2: return external(1, -1); + } + default: + return fail(); + } + case 'D': + switch (child) { + case 'D': + switch (edge) { + case 0: return external(2, -1); + case 1: return external(0, 0); + case 2: return internal('X', 2); + } + case 'X': + switch (edge) { + case 0: return external(1, 0); + case 1: return external(2, +1); + case 2: return internal('D', 2); + } + default: + return fail(); + } + case 'X': + switch (child) { + case 'C': + switch (edge) { + case 0: return external(2, +1); + case 1: return internal('Y', 1); + case 2: return internal('X', 1); + } + case 'X': + switch (edge) { + case 0: return external(1, 0); + case 1: return internal('C', 2); + case 2: return external(0, -1); + } + case 'Y': + switch (edge) { + case 0: return external(0, +1); + case 1: return internal('C', 1); + case 2: return external(2, -1); + } + default: + return fail(); + } + case 'Y': + switch (child) { + case 'D': + switch (edge) { + case 0: return external(1, -1); + case 1: return internal('Y', 2); + case 2: return internal('X', 2); + } + case 'X': + switch (edge) { + case 0: return external(0, -1); + case 1: return external(1, +1); + case 2: return internal('D', 2); + } + case 'Y': + switch (edge) { + case 0: return external(2, 0); + case 1: return external(0, +1); + case 2: return internal('D', 1); + } + default: + return fail(); + } + default: + return fail(); + } } -#endif +/* + * Compute a transition into a parent triangle, after the above + * function reported an EXTERNAL transition out of a neighbouring + * parent and we had to recurse. Because we're coming inwards, this + * should always return an INTERNAL TransitionResult (or FAIL if it + * gets invalid data). + */ +static TransitionResult transition_in(char parent, unsigned edge, int end) +{ + #define EDGEEND(edge, end) (3 * (edge) + 1 + (end)) + + switch (parent) { + case 'A': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, 0): return internal('A', 1); + case EDGEEND(1, -1): return internal('B', 2); + case EDGEEND(1, +1): return internal('U', 2); + case EDGEEND(2, -1): return internal('U', 0); + case EDGEEND(2, +1): return internal('A', 0); + default: + return fail(); + } + case 'B': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, 0): return internal('B', 2); + case EDGEEND(1, -1): return internal('B', 0); + case EDGEEND(1, +1): return internal('V', 0); + case EDGEEND(2, -1): return internal('V', 1); + case EDGEEND(2, +1): return internal('A', 1); + default: + return fail(); + } + case 'U': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, -1): return internal('B', 2); + case EDGEEND(0, +1): return internal('U', 2); + case EDGEEND(1, 0): return internal('U', 0); + case EDGEEND(2, 0): return internal('B', 1); + default: + return fail(); + } + case 'V': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, -1): return internal('V', 1); + case EDGEEND(0, +1): return internal('A', 1); + case EDGEEND(1, 0): return internal('A', 2); + case EDGEEND(2, 0): return internal('V', 0); + default: + return fail(); + } + case 'C': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, 0): return internal('C', 2); + case EDGEEND(1, -1): return internal('C', 0); + case EDGEEND(1, +1): return internal('Y', 2); + case EDGEEND(2, 0): return internal('Y', 0); + default: + return fail(); + } + case 'D': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, 0): return internal('D', 1); + case EDGEEND(1, 0): return internal('X', 0); + case EDGEEND(2, -1): return internal('X', 1); + case EDGEEND(2, +1): return internal('D', 0); + default: + return fail(); + } + case 'X': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, -1): return internal('Y', 0); + case EDGEEND(0, +1): return internal('X', 2); + case EDGEEND(1, 0): return internal('X', 0); + case EDGEEND(2, -1): return internal('C', 0); + case EDGEEND(2, +1): return internal('Y', 2); + default: + return fail(); + } + case 'Y': + switch (EDGEEND(edge, end)) { + case EDGEEND(0, +1): return internal('X', 0); + case EDGEEND(0, -1): return internal('Y', 1); + case EDGEEND(1, -1): return internal('X', 1); + case EDGEEND(1, +1): return internal('D', 0); + case EDGEEND(2, 0): return internal('Y', 0); + default: + return fail(); + } + default: + return fail(); + } -#define COS54 0.5877852 -#define SIN54 0.8090169 -#define COS18 0.9510565 -#define SIN18 0.3090169 + #undef EDGEEND +} -/* These two are a bit rough-and-ready for now. Note that B/C are - * 18 degrees from the x-axis, and A/D are 54 degrees. */ -double v_x(vector *vs, int i) +PenroseCoords *penrose_coords_new(void) { - return (vs[i].a + vs[i].d) * COS54 + - (vs[i].b + vs[i].c) * COS18; + PenroseCoords *pc = snew(PenroseCoords); + pc->nc = pc->csize = 0; + pc->c = NULL; + return pc; } -double v_y(vector *vs, int i) +void penrose_coords_free(PenroseCoords *pc) { - return (vs[i].a - vs[i].d) * SIN54 + - (vs[i].b - vs[i].c) * SIN18; - + if (pc) { + sfree(pc->c); + sfree(pc); + } } -static vector v_trans(vector v, vector trans) +void penrose_coords_make_space(PenroseCoords *pc, size_t size) { - v.a += trans.a; - v.b += trans.b; - v.c += trans.c; - v.d += trans.d; - return v; + if (pc->csize < size) { + pc->csize = pc->csize * 5 / 4 + 16; + if (pc->csize < size) + pc->csize = size; + pc->c = sresize(pc->c, pc->csize, char); + } } -static vector v_rotate_36(vector v) +PenroseCoords *penrose_coords_copy(PenroseCoords *pc_in) { - vector vv; - vv.a = -v.d; - vv.b = v.d + v.a; - vv.c = -v.d + v.b; - vv.d = v.d + v.c; - return vv; + PenroseCoords *pc_out = penrose_coords_new(); + penrose_coords_make_space(pc_out, pc_in->nc); + memcpy(pc_out->c, pc_in->c, pc_in->nc * sizeof(*pc_out->c)); + pc_out->nc = pc_in->nc; + return pc_out; } -static vector v_rotate(vector v, int ang) +/* + * The main recursive function for computing the next triangle's + * combinatorial coordinates. + */ +static void penrosectx_step_recurse( + PenroseContext *ctx, PenroseCoords *pc, size_t depth, + unsigned edge, unsigned *outedge) { - int i; + TransitionResult tr; + + penrosectx_extend_coords(ctx, pc, depth+2); + + /* Look up the transition out of the starting triangle */ + tr = transition(pc->c[depth+1], pc->c[depth], edge); + + /* If we've left the parent triangle, recurse to find out what new + * triangle we've landed in at the next size up, and then call + * transition_in to find out which child of that parent we're + * going to */ + if (tr.type == EXTERNAL) { + unsigned parent_outedge; + penrosectx_step_recurse( + ctx, pc, depth+1, tr.u.external.parent_edge, &parent_outedge); + tr = transition_in(pc->c[depth+1], parent_outedge, tr.u.external.end); + } - assert((ang % 36) == 0); - while (ang < 0) ang += 360; - ang = 360-ang; - for (i = 0; i < (ang/36); i++) - v = v_rotate_36(v); - return v; + /* Now we should definitely have ended up in a child of the + * (perhaps rewritten) parent triangle */ + assert(tr.type == INTERNAL); + pc->c[depth] = tr.u.internal.new_child; + *outedge = tr.u.internal.new_edge; } -#ifdef TEST_VECTORS - -static vector v_scale(vector v, int sc) +void penrosectx_step(PenroseContext *ctx, PenroseCoords *pc, + unsigned edge, unsigned *outedge) { - v.a *= sc; - v.b *= sc; - v.c *= sc; - v.d *= sc; - return v; -} + /* Allow outedge to be NULL harmlessly, just in case */ + unsigned dummy_outedge; + if (!outedge) + outedge = &dummy_outedge; -#endif + penrosectx_step_recurse(ctx, pc, 0, edge, outedge); +} -static vector v_growphi(vector v) +static Point penrose_triangle_post_edge(char c, unsigned edge) { - vector vv; - vv.a = v.a + v.b - v.d; - vv.b = v.c + v.d; - vv.c = v.a + v.b; - vv.d = v.c + v.d - v.a; - return vv; + static const Point acute_post_edge[3] = { + {{-1, 1, 0, 1}}, /* phi * t^3 */ + {{-1, 1, -1, 1}}, /* t^4 */ + {{-1, 1, 0, 0}}, /* 1/phi * t^3 */ + }; + static const Point obtuse_post_edge[3] = { + {{0, -1, 1, 0}}, /* 1/phi * t^4 */ + {{0, 0, 1, 0}}, /* t^2 */ + {{-1, 0, 0, 1}}, /* phi * t^4 */ + }; + + switch (c) { + case 'A': case 'B': case 'C': case 'D': + return acute_post_edge[edge]; + default: /* case 'U': case 'V': case 'X': case 'Y': */ + return obtuse_post_edge[edge]; + } } -static vector v_shrinkphi(vector v) +void penrose_place(PenroseTriangle *tri, Point u, Point v, int index_of_u) { - vector vv; - vv.a = v.b - v.d; - vv.b = v.c + v.d - v.b; - vv.c = v.a + v.b - v.c; - vv.d = v.c - v.a; - return vv; + unsigned i; + Point here = u, delta = point_sub(v, u); + + for (i = 0; i < 3; i++) { + unsigned edge = (index_of_u + i) % 3; + tri->vertices[edge] = here; + here = point_add(here, delta); + delta = point_mul(delta, penrose_triangle_post_edge( + tri->pc->c[0], edge)); + } } -#ifdef TEST_VECTORS - -static const char *v_debug(vector v) +void penrose_free(PenroseTriangle *tri) { - static char buf[255]; - sprintf(buf, - "(%d,%d,%d,%d)[%2.2f,%2.2f]", - v.a, v.b, v.c, v.d, v_x(&v,0), v_y(&v,0)); - return buf; + penrose_coords_free(tri->pc); + sfree(tri); } -#endif - -/* ------------------------------------------------------- - * Tiling routines. - */ - -static vector xform_coord(vector vo, int shrink, vector vtrans, int ang) +static bool penrose_relative_probability(char c) { - if (shrink < 0) - vo = v_shrinkphi(vo); - else if (shrink > 0) - vo = v_growphi(vo); - - vo = v_rotate(vo, ang); - vo = v_trans(vo, vtrans); - - return vo; + /* Penrose tile probability ratios are always phi, so we can + * approximate that very well using two consecutive Fibonacci + * numbers */ + switch (c) { + case 'A': case 'B': case 'X': case 'Y': + return 165580141; + case 'C': case 'D': case 'U': case 'V': + return 102334155; + default: + return 0; + } } - -#define XFORM(n,o,s,a) vs[(n)] = xform_coord(v_edge, (s), vs[(o)], (a)) - -static int penrose_p2_small(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge); - -static int penrose_p2_large(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge) +static char penrose_choose_random(const char *possibilities, random_state *rs) { - vector vv_orig, vv_edge; - -#ifdef DEBUG_PENROSE - { - vector vs[3]; - vs[0] = v_orig; - XFORM(1, 0, 0, 0); - XFORM(2, 0, 0, -36*flip); - - state->new_tile(state, vs, 3, depth); + const char *p; + unsigned long value, limit = 0; + + for (p = possibilities; *p; p++) + limit += penrose_relative_probability(*p); + value = random_upto(rs, limit); + for (p = possibilities; *p; p++) { + unsigned long curr = penrose_relative_probability(*p); + if (value < curr) + return *p; + value -= curr; } -#endif - - if (flip > 0) { - vector vs[4]; + assert(false && "Probability overflow!"); + return possibilities[0]; +} - vs[0] = v_orig; - XFORM(1, 0, 0, -36); - XFORM(2, 0, 0, 0); - XFORM(3, 0, 0, 36); +static const char *penrose_starting_tiles(int which) +{ + return which == PENROSE_P2 ? "ABUV" : "CDXY"; +} - state->new_tile(state, vs, 4, depth); +static const char *penrose_valid_parents(char tile) +{ + switch (tile) { + case 'A': return "ABV"; + case 'B': return "ABU"; + case 'U': return "AU"; + case 'V': return "BV"; + case 'C': return "CX"; + case 'D': return "DY"; + case 'X': return "DXY"; + case 'Y': return "CXY"; + default: return NULL; } - if (depth >= state->max_depth) return 0; - - vv_orig = v_trans(v_orig, v_rotate(v_edge, -36*flip)); - vv_edge = v_rotate(v_edge, 108*flip); - - penrose_p2_small(state, depth+1, flip, - v_orig, v_shrinkphi(v_edge)); +} - penrose_p2_large(state, depth+1, flip, - vv_orig, v_shrinkphi(vv_edge)); - penrose_p2_large(state, depth+1, -flip, - vv_orig, v_shrinkphi(vv_edge)); +void penrosectx_init_random(PenroseContext *ctx, random_state *rs, int which) +{ + ctx->rs = rs; + ctx->must_free_rs = false; + ctx->prototype = penrose_coords_new(); + penrose_coords_make_space(ctx->prototype, 1); + ctx->prototype->c[0] = penrose_choose_random( + penrose_starting_tiles(which), rs); + ctx->prototype->nc = 1; + ctx->start_vertex = random_upto(rs, 3); + ctx->orientation = random_upto(rs, 10); +} - return 0; +void penrosectx_init_from_params( + PenroseContext *ctx, const struct PenrosePatchParams *ps) +{ + size_t i; + + ctx->rs = NULL; + ctx->must_free_rs = false; + ctx->prototype = penrose_coords_new(); + penrose_coords_make_space(ctx->prototype, ps->ncoords); + for (i = 0; i < ps->ncoords; i++) + ctx->prototype->c[i] = ps->coords[i]; + ctx->prototype->nc = ps->ncoords; + ctx->start_vertex = ps->start_vertex; + ctx->orientation = ps->orientation; } -static int penrose_p2_small(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge) +void penrosectx_cleanup(PenroseContext *ctx) { - vector vv_orig; + if (ctx->must_free_rs) + random_free(ctx->rs); + penrose_coords_free(ctx->prototype); +} -#ifdef DEBUG_PENROSE - { - vector vs[3]; - vs[0] = v_orig; - XFORM(1, 0, 0, 0); - XFORM(2, 0, -1, -36*flip); +PenroseCoords *penrosectx_initial_coords(PenroseContext *ctx) +{ + return penrose_coords_copy(ctx->prototype); +} - state->new_tile(state, vs, 3, depth); +void penrosectx_extend_coords(PenroseContext *ctx, PenroseCoords *pc, + size_t n) +{ + if (ctx->prototype->nc < n) { + penrose_coords_make_space(ctx->prototype, n); + while (ctx->prototype->nc < n) { + if (!ctx->rs) { + /* + * For safety, similarly to spectre.c, we respond to a + * lack of available random_state by making a + * deterministic one. + */ + ctx->rs = random_new("dummy", 5); + ctx->must_free_rs = true; + } + + ctx->prototype->c[ctx->prototype->nc] = penrose_choose_random( + penrose_valid_parents(ctx->prototype->c[ctx->prototype->nc-1]), + ctx->rs); + ctx->prototype->nc++; + } } -#endif - - if (flip > 0) { - vector vs[4]; - - vs[0] = v_orig; - XFORM(1, 0, 0, -72); - XFORM(2, 0, -1, -36); - XFORM(3, 0, 0, 0); - state->new_tile(state, vs, 4, depth); + penrose_coords_make_space(pc, n); + while (pc->nc < n) { + pc->c[pc->nc] = ctx->prototype->c[pc->nc]; + pc->nc++; } - - if (depth >= state->max_depth) return 0; - - vv_orig = v_trans(v_orig, v_edge); - - penrose_p2_large(state, depth+1, -flip, - v_orig, v_shrinkphi(v_rotate(v_edge, -36*flip))); - - penrose_p2_small(state, depth+1, flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, -144*flip))); - - return 0; } -static int penrose_p3_small(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge); - -static int penrose_p3_large(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge) +static Point penrose_triangle_edge_0_length(char c) { - vector vv_orig; - -#ifdef DEBUG_PENROSE - { - vector vs[3]; - vs[0] = v_orig; - XFORM(1, 0, 1, 0); - XFORM(2, 0, 0, -36*flip); - - state->new_tile(state, vs, 3, depth); + static const Point one = {{ 1, 0, 0, 0 }}; + static const Point phi = {{ 1, 0, 1, -1 }}; + static const Point invphi = {{ 0, 0, 1, -1 }}; + + switch (c) { + /* P2 tiling: unit-length edges are the long edges, i.e. edges + * 1,2 of AB and edge 0 of UV. So AB have edge 0 short. */ + case 'A': case 'B': + return invphi; + case 'U': case 'V': + return one; + + /* P3 tiling: unit-length edges are edges 1,2 of everything, + * so CD have edge 0 short and XY have it long. */ + case 'C': case 'D': + return invphi; + default: /* case 'X': case 'Y': */ + return phi; } -#endif +} - if (flip > 0) { - vector vs[4]; +PenroseTriangle *penrose_initial(PenroseContext *ctx) +{ + char type = ctx->prototype->c[0]; + Point origin = {{ 0, 0, 0, 0 }}; + Point edge0 = penrose_triangle_edge_0_length(type); + Point negoffset; + size_t i; + PenroseTriangle *tri = snew(PenroseTriangle); + + /* Orient the triangle by deciding what vector edge #0 should traverse */ + edge0 = point_mul(edge0, point_rot(ctx->orientation)); + + /* Place the triangle at an arbitrary position, in that orientation */ + tri->pc = penrose_coords_copy(ctx->prototype); + penrose_place(tri, origin, edge0, 0); + + /* Now translate so that the appropriate vertex is at the origin */ + negoffset = tri->vertices[ctx->start_vertex]; + for (i = 0; i < 3; i++) + tri->vertices[i] = point_sub(tri->vertices[i], negoffset); + + return tri; +} - vs[0] = v_orig; - XFORM(1, 0, 0, -36); - XFORM(2, 0, 1, 0); - XFORM(3, 0, 0, 36); +PenroseTriangle *penrose_adjacent(PenroseContext *ctx, + const PenroseTriangle *src_tri, + unsigned src_edge, unsigned *dst_edge_out) +{ + unsigned dst_edge; + PenroseTriangle *dst_tri = snew(PenroseTriangle); + dst_tri->pc = penrose_coords_copy(src_tri->pc); + penrosectx_step(ctx, dst_tri->pc, src_edge, &dst_edge); + penrose_place(dst_tri, src_tri->vertices[(src_edge+1) % 3], + src_tri->vertices[src_edge], dst_edge); + if (dst_edge_out) + *dst_edge_out = dst_edge; + return dst_tri; +} - state->new_tile(state, vs, 4, depth); +static int penrose_cmp(void *av, void *bv) +{ + PenroseTriangle *a = (PenroseTriangle *)av, *b = (PenroseTriangle *)bv; + size_t i, j; + + /* We should only ever need to compare the first two vertices of + * any triangle, because those force the rest */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + int ac = a->vertices[i].coeffs[j], bc = b->vertices[i].coeffs[j]; + if (ac < bc) + return -1; + if (ac > bc) + return +1; + } } - if (depth >= state->max_depth) return 0; - - vv_orig = v_trans(v_orig, v_edge); - - penrose_p3_large(state, depth+1, -flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, 180))); - - penrose_p3_small(state, depth+1, flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, -108*flip))); - - vv_orig = v_trans(v_orig, v_growphi(v_edge)); - - penrose_p3_large(state, depth+1, flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, -144*flip))); - return 0; } -static int penrose_p3_small(penrose_state *state, int depth, int flip, - vector v_orig, vector v_edge) +static unsigned penrose_sibling_edge_index(char c) { - vector vv_orig; - -#ifdef DEBUG_PENROSE - { - vector vs[3]; - vs[0] = v_orig; - XFORM(1, 0, 0, 0); - XFORM(2, 0, 0, -36*flip); - - state->new_tile(state, vs, 3, depth); + switch (c) { + case 'A': case 'U': return 2; + case 'B': case 'V': return 1; + default: return 0; } -#endif - - if (flip > 0) { - vector vs[4]; - - vs[0] = v_orig; - XFORM(1, 0, 0, -36); - XFORM(3, 0, 0, 0); - XFORM(2, 3, 0, -36); +} - state->new_tile(state, vs, 4, depth); - } - if (depth >= state->max_depth) return 0; +void penrosectx_generate( + PenroseContext *ctx, + bool (*inbounds)(void *inboundsctx, + const PenroseTriangle *tri), void *inboundsctx, + void (*tile)(void *tilectx, const Point *vertices), void *tilectx) +{ + tree234 *placed = newtree234(penrose_cmp); + PenroseTriangle *qhead = NULL, *qtail = NULL; - /* NB these two are identical to the first two of p3_large. */ - vv_orig = v_trans(v_orig, v_edge); + { + PenroseTriangle *tri = penrose_initial(ctx); - penrose_p3_large(state, depth+1, -flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, 180))); + add234(placed, tri); - penrose_p3_small(state, depth+1, flip, - vv_orig, v_shrinkphi(v_rotate(v_edge, -108*flip))); + tri->next = NULL; + tri->reported = false; - return 0; -} + if (inbounds(inboundsctx, tri)) + qhead = qtail = tri; + } -/* ------------------------------------------------------- - * Utility routines. - */ + while (qhead) { + PenroseTriangle *tri = qhead; + unsigned edge; + unsigned sibling_edge = penrose_sibling_edge_index(tri->pc->c[0]); + + for (edge = 0; edge < 3; edge++) { + PenroseTriangle *new_tri, *found_tri; + + new_tri = penrose_adjacent(ctx, tri, edge, NULL); + + if (!inbounds(inboundsctx, new_tri)) { + penrose_free(new_tri); + continue; + } + + found_tri = find234(placed, new_tri, NULL); + if (found_tri) { + if (edge == sibling_edge && !tri->reported && + !found_tri->reported) { + /* + * found_tri and tri are opposite halves of the + * same tile; both are in the tree, and haven't + * yet been reported as a completed tile. + */ + unsigned new_sibling_edge = penrose_sibling_edge_index( + found_tri->pc->c[0]); + Point tilevertices[4] = { + tri->vertices[(sibling_edge + 1) % 3], + tri->vertices[(sibling_edge + 2) % 3], + found_tri->vertices[(new_sibling_edge + 1) % 3], + found_tri->vertices[(new_sibling_edge + 2) % 3], + }; + tile(tilectx, tilevertices); + + tri->reported = true; + found_tri->reported = true; + } + + penrose_free(new_tri); + continue; + } + + add234(placed, new_tri); + qtail->next = new_tri; + qtail = new_tri; + new_tri->next = NULL; + new_tri->reported = false; + } -double penrose_side_length(double start_size, int depth) -{ - return start_size / pow(PHI, depth); -} + qhead = qhead->next; + } -void penrose_count_tiles(int depth, int *nlarge, int *nsmall) -{ - /* Steal sgt's fibonacci thingummy. */ + { + PenroseTriangle *tri; + while ((tri = delpos234(placed, 0)) != NULL) + penrose_free(tri); + freetree234(placed); + } } -/* - * It turns out that an acute isosceles triangle with sides in ratio 1:phi:phi - * has an incentre which is conveniently 2*phi^-2 of the way from the apex to - * the base. Why's that convenient? Because: if we situate the incentre of the - * triangle at the origin, then we can place the apex at phi^-2 * (B+C), and - * the other two vertices at apex-B and apex-C respectively. So that's an acute - * triangle with its long sides of unit length, covering a circle about the - * origin of radius 1-(2*phi^-2), which is conveniently enough phi^-3. - * - * (later mail: this is an overestimate by about 5%) - */ - -int penrose(penrose_state *state, int which, int angle) +const char *penrose_tiling_params_invalid( + const struct PenrosePatchParams *params, int which) { - vector vo = v_origin(); - vector vb = v_origin(); - - vo.b = vo.c = -state->start_size; - vo = v_shrinkphi(v_shrinkphi(vo)); - - vb.b = state->start_size; + size_t i; - vo = v_rotate(vo, angle); - vb = v_rotate(vb, angle); + if (params->ncoords == 0) + return "expected at least one coordinate"; - if (which == PENROSE_P2) - return penrose_p2_large(state, 0, 1, vo, vb); - else - return penrose_p3_small(state, 0, 1, vo, vb); -} - -/* - * We're asked for a MxN grid, which just means a tiling fitting into roughly - * an MxN space in some kind of reasonable unit - say, the side length of the - * two-arrow edges of the tiles. By some reasoning in a previous email, that - * means we want to pick some subarea of a circle of radius 3.11*sqrt(M^2+N^2). - * To cover that circle, we need to subdivide a triangle large enough that it - * contains a circle of that radius. - * - * Hence: start with those three vectors marking triangle vertices, scale them - * all up by phi repeatedly until the radius of the inscribed circle gets - * bigger than the target, and then recurse into that triangle with the same - * recursion depth as the number of times you scaled up. That will give you - * tiles of unit side length, covering a circle big enough that if you randomly - * choose an orientation and coordinates within the circle, you'll be able to - * get any valid piece of Penrose tiling of size MxN. - */ -#define INCIRCLE_RADIUS 0.22426 /* phi^-3 less 5%: see above */ - -void penrose_calculate_size(int which, int tilesize, int w, int h, - double *required_radius, int *start_size, int *depth) -{ - double rradius, size; - int n = 0; - - /* - * Fudge factor to scale P2 and P3 tilings differently. This - * doesn't seem to have much relevance to questions like the - * average number of tiles per unit area; it's just aesthetic. - */ - if (which == PENROSE_P2) - tilesize = tilesize * 3 / 2; - else - tilesize = tilesize * 5 / 4; - - rradius = tilesize * 3.11 * sqrt((double)(w*w + h*h)); - size = tilesize; - - while ((size * INCIRCLE_RADIUS) < rradius) { - n++; - size = size * PHI; + for (i = 0; i < params->ncoords; i++) { + if (!penrose_valid_letter(params->coords[i], which)) + return "invalid coordinate letter"; + if (i > 0 && !strchr(penrose_valid_parents(params->coords[i-1]), + params->coords[i])) + return "invalid pair of consecutive coordinates"; } - *start_size = (int)size; - *depth = n; - *required_radius = rradius; + return NULL; } -/* ------------------------------------------------------- - * Test code. - */ - -#ifdef TEST_PENROSE - -#include -#include +struct PenroseOutputCtx { + int xoff, yoff; + Coord xmin, xmax, ymin, ymax; -int show_recursion = 0; -int ntiles, nfinal; + penrose_tile_callback_fn external_cb; + void *external_cbctx; +}; -int test_cb(penrose_state *state, vector *vs, int n, int depth) +static bool inbounds(void *vctx, const PenroseTriangle *tri) { - int i, xoff = 0, yoff = 0; - double l = penrose_side_length(state->start_size, depth); - double rball = l / 10.0; - const char *col; + struct PenroseOutputCtx *octx = (struct PenroseOutputCtx *)vctx; + size_t i; - ntiles++; - if (state->max_depth == depth) { - col = n == 4 ? "black" : "green"; - nfinal++; - } else { - if (!show_recursion) - return 0; - col = n == 4 ? "red" : "blue"; - } - if (n != 4) yoff = state->start_size; + for (i = 0; i < 3; i++) { + Coord x = point_x(tri->vertices[i]); + Coord y = point_y(tri->vertices[i]); - printf("xmin) < 0 || coord_cmp(x, octx->xmax) > 0 || + coord_cmp(y, octx->ymin) < 0 || coord_cmp(y, octx->ymax) > 0) + return false; } - printf("\" style=\"fill: %s; fill-opacity: 0.2; stroke: %s\" />\n", col, col); - printf("", - v_x(vs, 0) + xoff, v_y(vs, 0) + yoff, rball, rball, col); - return 0; + return true; } -void usage_exit(void) +static void null_output_tile(void *vctx, const Point *vertices) { - fprintf(stderr, "Usage: penrose-test [--recursion] P2|P3 SIZE DEPTH\n"); - exit(1); } -int main(int argc, char *argv[]) +static void really_output_tile(void *vctx, const Point *vertices) { - penrose_state ps; - int which = 0; - - while (--argc > 0) { - char *p = *++argv; - if (!strcmp(p, "-h") || !strcmp(p, "--help")) { - usage_exit(); - } else if (!strcmp(p, "--recursion")) { - show_recursion = 1; - } else if (*p == '-') { - fprintf(stderr, "Unrecognised option '%s'\n", p); - exit(1); - } else { - break; - } + struct PenroseOutputCtx *octx = (struct PenroseOutputCtx *)vctx; + size_t i; + int coords[16]; + + for (i = 0; i < 4; i++) { + Coord x = point_x(vertices[i]); + Coord y = point_y(vertices[i]); + + coords[4*i + 0] = x.c1 + octx->xoff; + coords[4*i + 1] = x.cr5; + coords[4*i + 2] = y.c1 + octx->yoff; + coords[4*i + 3] = y.cr5; } - if (argc < 3) usage_exit(); - - if (strcmp(argv[0], "P2") == 0) which = PENROSE_P2; - else if (strcmp(argv[0], "P3") == 0) which = PENROSE_P3; - else usage_exit(); - - ps.start_size = atoi(argv[1]); - ps.max_depth = atoi(argv[2]); - ps.new_tile = test_cb; - - ntiles = nfinal = 0; - - printf("\ -\n\ -\n\ -\n\ -\n\n"); - - printf("\n"); - penrose(&ps, which); - printf("\n"); + octx->external_cb(octx->external_cbctx, coords); +} - printf("\n", - ntiles, nfinal); +static void penrose_set_bounds(struct PenroseOutputCtx *octx, int w, int h) +{ + octx->xoff = w/2; + octx->yoff = h/2; + octx->xmin.c1 = -octx->xoff; + octx->xmax.c1 = -octx->xoff + w; + octx->ymin.c1 = octx->yoff - h; + octx->ymax.c1 = octx->yoff; + octx->xmin.cr5 = 0; + octx->xmax.cr5 = 0; + octx->ymin.cr5 = 0; + octx->ymax.cr5 = 0; +} - printf(""); +void penrose_tiling_randomise(struct PenrosePatchParams *params, int which, + int w, int h, random_state *rs) +{ + PenroseContext ctx[1]; + struct PenroseOutputCtx octx[1]; - return 0; -} + penrose_set_bounds(octx, w, h); -#endif + penrosectx_init_random(ctx, rs, which); + penrosectx_generate(ctx, inbounds, octx, null_output_tile, NULL); -#ifdef TEST_VECTORS + params->orientation = ctx->orientation; + params->start_vertex = ctx->start_vertex; + params->ncoords = ctx->prototype->nc; + params->coords = snewn(params->ncoords, char); + memcpy(params->coords, ctx->prototype->c, params->ncoords); -static void dbgv(const char *msg, vector v) -{ - printf("%s: %s\n", msg, v_debug(v)); + penrosectx_cleanup(ctx); } -int main(int argc, const char *argv[]) +void penrose_tiling_generate( + const struct PenrosePatchParams *params, int w, int h, + penrose_tile_callback_fn cb, void *cbctx) { - vector v = v_unit(); + PenroseContext ctx[1]; + struct PenroseOutputCtx octx[1]; - dbgv("unit vector", v); - v = v_rotate(v, 36); - dbgv("rotated 36", v); - v = v_scale(v, 2); - dbgv("scaled x2", v); - v = v_shrinkphi(v); - dbgv("shrunk phi", v); - v = v_rotate(v, -36); - dbgv("rotated -36", v); + penrose_set_bounds(octx, w, h); + octx->external_cb = cb; + octx->external_cbctx = cbctx; - return 0; + penrosectx_init_from_params(ctx, params); + penrosectx_generate(ctx, inbounds, octx, really_output_tile, octx); + penrosectx_cleanup(ctx); } - -#endif -/* vim: set shiftwidth=4 tabstop=8: */ diff --git a/apps/plugins/puzzles/src/penrose.h b/apps/plugins/puzzles/src/penrose.h index ba5ae16f2c..e6e927d618 100644 --- a/apps/plugins/puzzles/src/penrose.h +++ b/apps/plugins/puzzles/src/penrose.h @@ -1,59 +1,86 @@ -/* penrose.h - * - * Penrose tiling functions. - * - * Provides an interface with which to generate Penrose tilings - * by recursive subdivision of an initial tile of choice (one of the - * four sets of two pairs kite/dart, or thin/thick rhombus). - * - * You supply a callback function and a context pointer, which is - * called with each tile in turn: you choose how many times to recurse. - */ +#ifndef PUZZLES_PENROSE_H +#define PUZZLES_PENROSE_H -#ifndef _PENROSE_H -#define _PENROSE_H +struct PenrosePatchParams { + /* + * A patch of Penrose tiling is identified by giving + * + * - the coordinates of the starting triangle, using a + * combinatorial coordinate system + * + * - which vertex of that triangle is at the centre point of the + * tiling + * + * - the orientation of the triangle's base edge, as a number + * from 0 to 9, measured in tenths of a turn + * + * Coordinates are a sequence of letters. For a P2 tiling all + * letters are from the set {A,B,U,V}; for P3, {C,D,X,Y}. + */ + unsigned start_vertex; + int orientation; + size_t ncoords; + char *coords; +}; -#ifndef PHI -#define PHI 1.6180339887 +#ifndef PENROSE_ENUM_DEFINED +#define PENROSE_ENUM_DEFINED +enum { PENROSE_P2, PENROSE_P3 }; #endif -typedef struct vector vector; - -double v_x(vector *vs, int i); -double v_y(vector *vs, int i); +bool penrose_valid_letter(char c, int which); -typedef struct penrose_state penrose_state; - -/* Return non-zero to clip the tree here (i.e. not recurse - * below this tile). +/* + * Fill in PenrosePatchParams with a randomly selected set of + * coordinates, in enough detail to generate a patch of tiling filling + * a w x h area. + * + * Units of measurement: the tiling will be oriented such that + * horizontal tile edges are possible (and therefore vertical ones are + * not). Therefore, all x-coordinates will be rational linear + * combinations of 1 and sqrt(5), and all y-coordinates will be + * sin(pi/5) times such a rational linear combination. By scaling up + * appropriately we can turn those rational combinations into + * _integer_ combinations, so we do. Therefore, w is measured in units + * of 1/4, and h is measured in units of sin(pi/5)/2, on a scale where + * a length of 1 corresponds to the legs of the acute isosceles + * triangles in the tiling (hence, the long edges of P2 kites and + * darts, or all edges of P3 rhombs). * - * Parameters are state, vector array, npoints, depth. - * ctx is inside state. + * (In case it's useful, the y scale factor sin(pi/5)/2 is an + * algebraic number. Its minimal polynomial is 256x^4 - 80x^2 + 5.) + * + * The 'coords' field of the structure will be filled in with a new + * dynamically allocated array. Any previous pointer in that field + * will be overwritten. */ -typedef int (*tile_callback)(penrose_state *, vector *, int, int); - -struct penrose_state { - int start_size; /* initial side length */ - int max_depth; /* Recursion depth */ - - tile_callback new_tile; - void *ctx; /* for callback */ -}; +void penrose_tiling_randomise(struct PenrosePatchParams *params, int which, + int w, int h, random_state *rs); -enum { PENROSE_P2, PENROSE_P3 }; - -extern int penrose(penrose_state *state, int which, int angle); +/* + * Validate a PenrosePatchParams to ensure it contains no illegal + * coordinates. Returns NULL if it's acceptable, or an error string if + * not. + */ +const char *penrose_tiling_params_invalid( + const struct PenrosePatchParams *params, int which); -/* Returns the side-length of a penrose tile at recursion level - * gen, given a starting side length. */ -extern double penrose_side_length(double start_size, int depth); +/* + * Generate the actual set of Penrose tiles from a PenrosePatchParams, + * passing each one to a callback. The callback receives the vertices + * of each point, in the form of an array of 4*4 integers. Each vertex + * is represented by four consecutive integers in this array, with the + * first two giving the x coordinate and the last two the y + * coordinate. Each pair of integers a,b represent a single coordinate + * whose value is a + b*sqrt(5). The units of measurement for x and y + * are as described above. + */ +typedef void (*penrose_tile_callback_fn)(void *ctx, const int *coords); -/* Returns the count of each type of tile at a given recursion depth. */ -extern void penrose_count_tiles(int gen, int *nlarge, int *nsmall); +#define PENROSE_NVERTICES 4 -/* Calculate start size and recursion depth required to produce a - * width-by-height sized patch of penrose tiles with the given tilesize */ -extern void penrose_calculate_size(int which, int tilesize, int w, int h, - double *required_radius, int *start_size, int *depth); +void penrose_tiling_generate( + const struct PenrosePatchParams *params, int w, int h, + penrose_tile_callback_fn cb, void *cbctx); #endif diff --git a/apps/plugins/puzzles/src/printing.c b/apps/plugins/puzzles/src/printing.c index d1a3badaaa..0a911949a7 100644 --- a/apps/plugins/puzzles/src/printing.c +++ b/apps/plugins/puzzles/src/printing.c @@ -10,6 +10,7 @@ struct puzzle { const game *game; game_params *par; + game_ui *ui; game_state *st; game_state *st2; }; @@ -56,6 +57,7 @@ void document_free(document *doc) for (i = 0; i < doc->npuzzles; i++) { doc->puzzles[i].game->free_params(doc->puzzles[i].par); + doc->puzzles[i].game->free_ui(doc->puzzles[i].ui); doc->puzzles[i].game->free_game(doc->puzzles[i].st); if (doc->puzzles[i].st2) doc->puzzles[i].game->free_game(doc->puzzles[i].st2); @@ -75,7 +77,7 @@ void document_free(document *doc) * another sheet (typically the solution to the first game_state). */ void document_add_puzzle(document *doc, const game *game, game_params *par, - game_state *st, game_state *st2) + game_ui *ui, game_state *st, game_state *st2) { if (doc->npuzzles >= doc->puzzlesize) { doc->puzzlesize += 32; @@ -83,6 +85,7 @@ void document_add_puzzle(document *doc, const game *game, game_params *par, } doc->puzzles[doc->npuzzles].game = game; doc->puzzles[doc->npuzzles].par = par; + doc->puzzles[doc->npuzzles].ui = ui; doc->puzzles[doc->npuzzles].st = st; doc->puzzles[doc->npuzzles].st2 = st2; doc->npuzzles++; @@ -96,7 +99,11 @@ static void get_puzzle_size(const document *doc, struct puzzle *pz, float ww, hh, ourscale; /* Get the preferred size of the game, in mm. */ - pz->game->print_size(pz->par, &ww, &hh); + { + game_ui *ui = pz->game->new_ui(pz->st); + pz->game->print_size(pz->par, ui, &ww, &hh); + pz->game->free_ui(ui); + } /* Adjust for user-supplied scale factor. */ ourscale = doc->userscale; @@ -270,9 +277,9 @@ void document_print_page(const document *doc, drawing *dr, int page_nr) * permit each game to choose its own?) */ tilesize = 512; - pz->game->compute_size(pz->par, tilesize, &pixw, &pixh); + pz->game->compute_size(pz->par, tilesize, pz->ui, &pixw, &pixh); print_begin_puzzle(dr, xm, xc, ym, yc, pixw, pixh, w, scale); - pz->game->print(dr, pass == 0 ? pz->st : pz->st2, tilesize); + pz->game->print(dr, pass == 0 ? pz->st : pz->st2, pz->ui, tilesize); print_end_puzzle(dr); } diff --git a/apps/plugins/puzzles/src/ps.c b/apps/plugins/puzzles/src/ps.c index ab8a1589f4..d0ea0ff2b5 100644 --- a/apps/plugins/puzzles/src/ps.c +++ b/apps/plugins/puzzles/src/ps.c @@ -157,7 +157,7 @@ static void ps_draw_line(void *handle, int x1, int y1, int x2, int y2, ps_stroke(ps, colour); } -static void ps_draw_polygon(void *handle, int *coords, int npoints, +static void ps_draw_polygon(void *handle, const int *coords, int npoints, int fillcolour, int outlinecolour) { psdata *ps = (psdata *)handle; diff --git a/apps/plugins/puzzles/src/puzzles.but b/apps/plugins/puzzles/src/puzzles.but index ee519b8aa1..fb94155eed 100644 --- a/apps/plugins/puzzles/src/puzzles.but +++ b/apps/plugins/puzzles/src/puzzles.but @@ -36,7 +36,7 @@ This is a collection of small one-player puzzle games. -\copyright This manual is copyright 2004-2014 Simon Tatham. All rights +\copyright This manual is copyright 2004-2024 Simon Tatham. All rights reserved. You may distribute this documentation under the MIT licence. See \k{licence} for the licence text in full. @@ -130,12 +130,12 @@ current puzzle. (Only for puzzles which make sense to print, of course \dash it's hard to think of a sensible printable representation of Fifteen!) -\dt \ii\e{Undo} (\q{U}, Ctrl+\q{Z}, Ctrl+\q{_}) +\dt \ii\e{Undo} (\q{U}, Ctrl+\q{Z}, Ctrl+\q{_}, \q{*}) \dd Undoes a single move. (You can undo moves back to the start of the session.) -\dt \ii\e{Redo} (\q{R}, Ctrl+\q{R}) +\dt \ii\e{Redo} (\q{R}, Ctrl+\q{R}, \q{#}) \dd Redoes a previously undone move. @@ -177,6 +177,22 @@ solving it yourself after seeing the answer, you can just press Undo. \dd Closes the application entirely. +\dt \i\e{Preferences} + +\dd Where supported, brings up a dialog allowing you to configure +personal preferences about a particular game. Some of these +preferences will be specific to a particular game; others will be +common to all games. + +\lcont{ + +One option common to all games allows you to turn off the one-key +shortcuts like \q{N} for new game or \q{Q} for quit, so that there's +less chance of hitting them by accident. You can still access the same +shortcuts with the Ctrl key. + +} + \H{common-id} Specifying games with the \ii{game ID} There are two ways to save a game specification out of a puzzle and @@ -348,6 +364,11 @@ in which case its behaviour is slightly different; see below. } +\dt \cw{--delete-prefs} + +\dd This option causes the puzzle to delete the configuration file in +which its user preferences were stored, if there is one. + \dt \I{printing, on Unix}\cw{--print }\e{w}\cw{x}\e{h} \dd If this option is specified, instead of a puzzle being displayed, @@ -535,6 +556,16 @@ feature and risk having ambiguous puzzles. (Also, finding \e{all} the possible solutions can be an additional challenge for an advanced player.) +\H{net-prefs} \I{preferences, for Net}Net user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure when loops are highlighted +as errors. By default, they're always highlighted; by changing this +option, you can ask for a loop to be highlighted only if every tile +forming part of the loop is locked. This avoids the loop highlighting +acting as a spoiler for available deductions about squares you haven't +even looked at yet. + \C{cube} \i{Cube} @@ -601,7 +632,8 @@ respectively. \cfg{winhelp-topic}{games.fifteen} The old ones are the best: this is the good old \q{\i{15-puzzle}} -with sliding tiles. You have a 4\by\.4 square grid; 15 squares +with sliding tiles, which dates from the 1870s. +You have a 4\by\.4 square grid; 15 squares contain numbered tiles, and the sixteenth is empty. Your move is to choose a tile next to the empty space, and slide it into the space. The aim is to end up with the tiles in numerical order, with the @@ -620,8 +652,9 @@ A left-click with the mouse in the row or column containing the empty space will move as many tiles as necessary to move the space to the mouse pointer. -The arrow keys will move a tile adjacent to the space in the direction -indicated (moving the space in the \e{opposite} direction). +By default, the arrow keys will move a tile adjacent to the space in +the direction indicated (moving the space in the \e{opposite} +direction). Pressing \q{h} will make a suggested move. Pressing \q{h} enough times will solve the game, but it may scramble your progress while @@ -635,6 +668,18 @@ The only options available from the \q{Custom...} option on the \q{Type} menu are \e{Width} and \e{Height}, which are self-explanatory. (Once you've changed these, it's not a \q{15-puzzle} any more, of course!) +\H{fifteen-prefs} \I{preferences, for Fifteen}Fifteen user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the sense of the arrow +keys. With the default setting, \q{Move the tile}, the arrow key you +press indicates the direction that you want a tile to move, so that +(for example) if you want to move the tile left of the gap rightwards +into the gap, you'd press Right. With the opposite setting, \q{Move +the gap}, the behaviour of the arrow keys is reversed, and you would +press Left to move the tile left of the gap into the gap, so that the +\e{gap} ends up one square left of where it was. + \C{sixteen} \i{Sixteen} @@ -785,8 +830,7 @@ quite as good as hand-crafted puzzles would be, but on the plus side you get an inexhaustible supply of puzzles tailored to your own specification. -\B{nikoli-rect} \W{http://www.nikoli.co.jp/en/puzzles/shikaku.html}\cw{http://www.nikoli.co.jp/en/puzzles/shikaku.html} -(beware of Flash) +\B{nikoli-rect} \W{https://www.nikoli.co.jp/en/puzzles/shikaku/}\cw{https://www.nikoli.co.jp/en/puzzles/shikaku/} \B{puzzle-palace-rect} \W{https://web.archive.org/web/20041024001459/http://www.puzzle.gr.jp/puzzle/sikaku/palm/index.html.en}\cw{https://web.archive.org/web/20041024001459/http://www.puzzle.gr.jp/puzzle/sikaku/palm/index.html.en} @@ -880,10 +924,10 @@ Netslide was contributed to this collection by Richard Boulton. \cfg{winhelp-topic}{games.pattern} You have a grid of squares, which must all be filled in either black -or white. Beside each row of the grid are listed the lengths of the -runs of black squares on that row; above each column are listed the -lengths of the runs of black squares in that column. Your aim is to -fill in the entire grid black or white. +or white. Beside each row of the grid are listed, in order, the +lengths of the runs of black squares on that row; above each column +are listed, in order, the lengths of the runs of black squares in that +column. Your aim is to fill in the entire grid black or white. I first saw this puzzle form around 1995, under the name \q{\i{nonograms}}. I've seen it in various places since then, under @@ -977,8 +1021,7 @@ of the modern form of the puzzle, and it was first published in of the history of the puzzle can be found on Wikipedia \k{wikipedia-solo}. -\B{nikoli-solo} \W{http://www.nikoli.co.jp/en/puzzles/sudoku.html}\cw{http://www.nikoli.co.jp/en/puzzles/sudoku.html} -(beware of Flash) +\B{nikoli-solo} \W{https://www.nikoli.co.jp/en/puzzles/sudoku/}\cw{https://www.nikoli.co.jp/en/puzzles/sudoku/} \B{wikipedia-solo} \W{http://en.wikipedia.org/wiki/Sudoku}\cw{http://en.wikipedia.org/wiki/Sudoku} @@ -1337,10 +1380,15 @@ after marking. Alternatively, with the keyboard, the up and down cursor keys can be used to select a peg colour, the left and right keys to select a -peg position, and the space bar or Enter key to place a peg of the +peg position, and the Enter key to place a peg of the selected colour in the chosen position. \q{D} or Backspace removes a peg, and Space adds a hold marker. +The number keys can also be used to insert pegs: \q{1} inserts the +top-most colour, \q{2} the second one, and so forth. These also +move the peg cursor to the right. Pressing \q{L} will label the +pegs with their numbers. + Pressing \q{h} or \q{?} will fill the current guess with a suggested guess. Using this is not recommended for 10 or more pegs as it is slow. @@ -1395,6 +1443,13 @@ that, use one extra colour. this increases the search space (making things harder), and is turned on by default. +\H{guess-prefs} \I{preferences, for Guess}Guess user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure whether pegs are labelled +with their numbers. Unlike the \q{L} key, this will persist between +games. + \C{pegs} \i{Pegs} @@ -1442,8 +1497,9 @@ These parameters are available from the \q{Custom...} option on the \dd Controls whether you are given a board of a standard shape or a randomly generated shape. The two standard shapes currently -supported are \q{Cross} and \q{Octagon} (also commonly known as the -English and European traditional board layouts respectively). +supported are \q{Cross} (in various sizes) and \q{Octagon}. +The 7\by\.7 Cross is the traditional English board layout. +The Octagon is the traditional French one. Selecting \q{Random} will give you a different board shape every time (but always one that is known to have a solution). @@ -1530,6 +1586,11 @@ I originally saw this in the form of a Flash game called \i{Planarity} To move a point, click on it with the left mouse button and drag it into a new position. +The cursor keys may also be used to navigate amongst the +points. Pressing the Enter key will toggle dragging the +currently-highlighted point. Pressing Tab or Space will cycle through +all the points. + (All the actions described in \k{common-actions} are also available.) \H{untangle-parameters} \I{parameters, for Untangle}Untangle parameters @@ -1714,7 +1775,7 @@ grid because that would immediately cause a loop.) Credit for this puzzle goes to \i{Nikoli} \k{nikoli-slant}. \B{nikoli-slant} -\W{http://www.nikoli.co.jp/ja/puzzles/gokigen_naname}\cw{http://www.nikoli.co.jp/ja/puzzles/gokigen_naname} +\W{https://www.nikoli.co.jp/ja/puzzles/gokigen_naname/}\cw{https://www.nikoli.co.jp/ja/puzzles/gokigen_naname/} (in Japanese) \H{slant-controls} \i{Slant controls} @@ -1763,6 +1824,12 @@ don't yet know what that direction is, and this might enable you to deduce something about still other squares.) Even at Hard level, guesswork and backtracking should never be necessary. +\H{slant-prefs} \I{preferences, for Slant}Slant user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure which way round the mouse +buttons work. + \C{lightup} \i{Light Up} @@ -1792,8 +1859,7 @@ Credit for this puzzle goes to \i{Nikoli} \k{nikoli-lightup}. Light Up was contributed to this collection by James Harvey. \B{nikoli-lightup} -\W{http://www.nikoli.co.jp/en/puzzles/akari.html}\cw{http://www.nikoli.co.jp/en/puzzles/akari.html} -(beware of Flash) +\W{https://www.nikoli.co.jp/en/puzzles/akari/}\cw{https://www.nikoli.co.jp/en/puzzles/akari/} \H{lightup-controls} \i{Light Up controls} @@ -1847,6 +1913,12 @@ noticeably.) backtracking or guessing, \q{Hard} means that some guesses will probably be necessary. +\H{lightup-prefs} \I{preferences, for Light Up}Light Up user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure whether \q{this is not a +light} marks are shown when the square is also lit. + \C{map} \i{Map} @@ -1856,7 +1928,7 @@ You are given a map consisting of a number of regions. Your task is to colour each region with one of four colours, in such a way that no two regions sharing a boundary have the same colour. You are provided with some regions already coloured, sufficient to make the -remainder of the solution unique. +remainder of the solution unique, and these cannot be changed. Only regions which share a length of border are required to be different colours. Two regions which meet at only one \e{point} @@ -1864,9 +1936,9 @@ different colours. Two regions which meet at only one \e{point} I believe this puzzle is original; I've never seen an implementation of it anywhere else. The concept of a \i{four-colouring} puzzle was -suggested by Owen Dunn; credit must also go to Nikoli and to Verity +suggested by Alexandra Lanes; credit must also go to Nikoli and to Verity Allan for inspiring the train of thought that led to me realising -Owen's suggestion was a viable puzzle. Thanks also to Gareth Taylor +Alex's suggestion was a viable puzzle. Thanks also to Gareth Taylor for many detailed suggestions. \H{map-controls} \i{Map controls} @@ -1940,6 +2012,12 @@ Unreasonable puzzles may require guessing and backtracking. } +\H{map-prefs} \I{preferences, for Map}Map user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the style of the victory +flash and also whether the regions start out labelled with numbers. + \C{loopy} \i{Loopy} @@ -1967,8 +2045,7 @@ and subsequently enhanced to handle various types of non-square grid by Lambros Lambrou. \B{nikoli-loopy} -\W{http://www.nikoli.co.jp/en/puzzles/slitherlink.html}\cw{http://www.nikoli.co.jp/en/puzzles/slitherlink.html} -(beware of Flash) +\W{https://www.nikoli.co.jp/en/puzzles/slitherlink/}\cw{https://www.nikoli.co.jp/en/puzzles/slitherlink/} \H{loopy-controls} \i{Loopy controls} @@ -2013,6 +2090,34 @@ same; this makes them the least confusing to play. \#{FIXME: what distinguishes Easy, Medium, and Hard? In particular, when are backtracking/guesswork required, if ever?} +\H{loopy-prefs} \I{preferences, for Loopy}Loopy user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the following things: + +\q{Draw excluded grid lines faintly}. This is on by default: when a +line of the grid has been explicitly excluded from the solution by +right-clicking it, the line is still drawn, just in a faint grey +colour. If you turn this option off, excluded lines are not drawn at +all. + +\q{Auto-follow unique paths of edges}. This is off by default. When +it's on, clicking to change the status of a single grid line will +potentially propagate the change along multiple lines, if one or both +ends of the line you clicked connect to only one other line. (The idea +is that if two lines meet at a vertex and no other lines do at all, +then those lines are either both part of the loop or neither, so +there's no reason you should have to click separately to toggle each +one.) + +In the mode \q{Based on grid only}, the effects of a click will only +propagate across vertices that have degree 2 in the underlying grid. +For example, in the square grid, the effect will \e{only} occur at the +four grid corners. + +In the mode \q{Based on grid and game state}, the propagation will +also take account of edges you've already excluded from the solution, +so that it will do even more work for you. \C{inertia} \i{Inertia} @@ -2171,8 +2276,7 @@ Credit for this puzzle goes to \i{Nikoli} \k{nikoli-bridges}. Bridges was contributed to this collection by James Harvey. \B{nikoli-bridges} -\W{http://www.nikoli.co.jp/en/puzzles/hashiwokakero.html}\cw{http://www.nikoli.co.jp/en/puzzles/hashiwokakero.html} -(beware of Flash) +\W{https://www.nikoli.co.jp/en/puzzles/Hashiwokakero/}\cw{https://www.nikoli.co.jp/en/puzzles/Hashiwokakero/} \H{bridges-controls} \i{Bridges controls} @@ -2217,6 +2321,9 @@ By pressing a number key, you can jump to the nearest island with that number. Letters \q{a}, ..., \q{f} count as 10, ..., 15 and \q{0} as 16. +The \q{G} key will draw a grey line between each pair of islands that +could be connected with a bridge or non-bridge but are currently not. + Violations of the puzzle rules will be marked in red: \b An island with too many bridges will be highlighted in red. @@ -2288,6 +2395,13 @@ tightly-packed islands. } +\H{bridges-prefs} \I{preferences, for Bridges}Bridges user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure whether possible bridge +locations are shown. Unlike the \q{G} key, this will persist between +games. + \C{unequal} \i{Unequal} @@ -2416,7 +2530,7 @@ English as \q{Spiral Galaxies}. Galaxies was contributed to this collection by James Harvey. -\B{nikoli-galaxies} \W{http://www.nikoli.co.jp/en/puzzles/astronomical_show.html}\cw{http://www.nikoli.co.jp/en/puzzles/astronomical_show.html} +\B{nikoli-galaxies} \W{https://www.nikoli.co.jp/en/puzzles/tentai_show/}\cw{https://www.nikoli.co.jp/en/puzzles/tentai_show/} \H{galaxies-controls} \i{Galaxies controls} @@ -2489,7 +2603,7 @@ Credit for this puzzle goes to \i{Nikoli} \k{nikoli-fillomino}. Filling was contributed to this collection by Jonas K\u00F6{oe}lker. \B{nikoli-fillomino} -\W{http://www.nikoli.co.jp/en/puzzles/fillomino.html}\cw{http://www.nikoli.co.jp/en/puzzles/fillomino.html} +\W{https://www.nikoli.co.jp/en/puzzles/fillomino/}\cw{https://www.nikoli.co.jp/en/puzzles/fillomino/} \H{filling-controls} \I{controls, for Filling}Filling controls @@ -2718,6 +2832,14 @@ level, some backtracking will be required, but the solution should still be unique. The remaining levels require increasingly complex reasoning to avoid having to backtrack. +\H{towers-prefs} \I{preferences, for Towers}Towers user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the style of the game +display. If you don't like the three-dimensional mode, selecting +\q{2D} will switch to a simpler display style in which towers are +shown by just writing their height in the square. + \C{singles} \i{Singles} @@ -2741,8 +2863,7 @@ Credit for this puzzle goes to \i{Nikoli} \k{nikoli-hitori} who call it Singles was contributed to this collection by James Harvey. \B{nikoli-hitori} -\W{http://www.nikoli.com/en/puzzles/hitori.html}\cw{http://www.nikoli.com/en/puzzles/hitori.html} -(beware of Flash) +\W{https://www.nikoli.co.jp/en/puzzles/hitori/}\cw{https://www.nikoli.co.jp/en/puzzles/hitori/} \H{singles-controls} \i{Singles controls} @@ -2750,7 +2871,9 @@ Singles was contributed to this collection by James Harvey. Left-clicking on an empty square will colour it black; left-clicking again will restore the number. Right-clicking will add a circle (useful for -indicating that a cell is definitely not black). +indicating that a cell is definitely not black). Clicking outside the +grid will toggle whether black squares completely hide the numbers on +them, or display them in dark grey. You can also use the cursor keys to move around the grid. Pressing the return or space keys will turn a square black or add a circle respectively, @@ -2771,6 +2894,12 @@ These parameters are available from the \q{Custom...} option on the \dd Controls the difficulty of the generated puzzle. +\H{Singles-prefs} \I{preferences, for Singles}Singles user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure whether numbers on black +squares are visible. Unlike clicking outside the grid, this will +persist between games. \C{magnets} \i{Magnets} @@ -2925,6 +3054,13 @@ These parameters are available from the \q{Custom...} option on the (the start at the top left, and the end at the bottom right). If false the start and end squares are placed randomly (although always both shown). +\H{signpost-prefs} \I{preferences, for Signpost}Signpost user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the style of the victory +effect. + + \C{range} \i{Range} \cfg{winhelp-topic}{games.range} @@ -2959,7 +3095,7 @@ it \q{Kurodoko}, \q{Kuromasu} or \q{Where is Black Cells}. Range was contributed to this collection by Jonas K\u00F6{oe}lker. \B{nikoli-range} -\W{http://www.nikoli.co.jp/en/puzzles/where_is_black_cells.html}\cw{http://www.nikoli.co.jp/en/puzzles/where_is_black_cells.html} +\W{https://www.nikoli.co.jp/en/puzzles/kurodoko/}\cw{https://www.nikoli.co.jp/en/puzzles/kurodoko/} \H{range-controls} \I{controls, for Range}Range controls @@ -2987,6 +3123,13 @@ These parameters are available from the \q{Custom...} option on the \dd Size of grid in squares. +\H{range-prefs} \I{preferences, for Range}Range user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure which way round the mouse +buttons work. + + \C{pearl} \i{Pearl} \cfg{winhelp-topic}{games.pearl} @@ -3019,8 +3162,7 @@ Credit for this puzzle goes to \i{Nikoli}, who call it \q{Masyu}. Thanks to James Harvey for assistance with the implementation. \B{nikoli-pearl} -\W{http://www.nikoli.co.jp/en/puzzles/masyu.html}\cw{http://www.nikoli.co.jp/en/puzzles/masyu.html} -(beware of Flash) +\W{https://www.nikoli.co.jp/en/puzzles/masyu/}\cw{https://www.nikoli.co.jp/en/puzzles/masyu/} \H{pearl-controls} \I{controls, for Pearl}Pearl controls @@ -3054,6 +3196,41 @@ right click, respectively, on the edge in the direction of the key. These parameters are available from the \q{Custom...} option on the \q{Type} menu. +\dt \e{Width}, \e{Height} + +\dd Size of grid in squares. + +\dt \e{Difficulty} + +\dd Controls the difficulty of the generated puzzle. + +\dt \e{Allow unsoluble} + +\dd If this is set, then the game will be generated in the simplest +way: every clue square that can possibly be provided will be shown, +and the generator will not check whether the puzzle can be uniquely +solved. + +\lcont{ + +This speeds up game generation, and allows much larger grids to be +played. At least one possible solution will still always exist, but +there's no guarantee that it will be unique, or that it will be +possible to deduce it step by step. + +} + +\H{pearl-prefs} \I{preferences, for Pearl}Pearl user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure the style of the game +display. \q{Traditional} is the default mode, in which the loop runs +between centres of grid squares, and each clue occupies a square. +\q{Loopy-style} is an alternative mode that looks more like Loopy +(\k{loopy}), in which the loop runs between grid \e{vertices}, and the +clues also occupy vertices. + + \C{undead} \i{Undead} \cfg{winhelp-topic}{games.undead} @@ -3088,12 +3265,13 @@ Undead was contributed to this collection by Steffen Bauer. Undead has a similar control system to Solo, Unequal and Keen. To play Undead, click the mouse in any empty square and then type a -letter on the keyboard indicating the type of monster: \q{G} for a -ghost, \q{V} for a vampire, or \q{Z} for a zombie. If you make a +letter or number on the keyboard indicating the type of monster: +\q{G} or \q{1} for a ghost, \q{V} or \q{2} for a vampire, +or \q{Z} or \q{3} for a zombie. If you make a mistake, click the mouse in the incorrect square and press Space to clear it again (or use the Undo feature). -If you \e{right}-click in a square and then type a letter, the +If you \e{right}-click in a square and then type a letter or number, the corresponding monster will be shown in reduced size in that square, as a \q{pencil mark}. You can have pencil marks for multiple monsters in the same square. A square containing a full-size monster cannot also @@ -3106,7 +3284,7 @@ monster, or you can use them as lists of the possible monster in a given square, or anything else you feel like. To erase a single pencil mark, right-click in the square and type -the same letter again. +the same letter or number again. All pencil marks in a square are erased when you left-click and type a monster letter, or when you left-click and press Space. Right-clicking @@ -3114,7 +3292,7 @@ and pressing space will also erase pencil marks. As for Solo, the cursor keys can be used in conjunction with the letter keys to place monsters or pencil marks. Use the cursor keys to move a -highlight around the grid, and type a monster letter to enter it in +highlight around the grid, and type a monster letter or number to enter it in the highlighted square. Pressing return toggles the highlight into a mode in which you can enter or remove pencil marks. @@ -3140,6 +3318,13 @@ These parameters are available from the \q{Custom...} option on the \dd Controls the difficulty of the generated puzzle. +\H{undead-prefs} \I{preferences, for Undead}Undead user preferences + +On platforms that support user preferences, the \q{Preferences} option +on the \q{Game} menu will let you configure whether Undead uses letters +or pictures to represent monsters. + + \C{unruly} \i{Unruly} \cfg{winhelp-topic}{games.unruly} @@ -3257,7 +3442,7 @@ real challenge, set this value to 0 and then try to solve a grid in } -\C{tracks} \i{Tracks} +\C{tracks} \i{Train Tracks} \cfg{winhelp-topic}{games.tracks} @@ -3269,9 +3454,9 @@ clues to the top and right of the grid. There are only straight and 90 degree curved rails, and the track may not cross itself. -Tracks was contributed to this collection by James Harvey. +Train Tracks was contributed to this collection by James Harvey. -\H{tracks-controls} \I{controls, for Tracks}Tracks controls +\H{tracks-controls} \I{controls, for Tracks}Train Tracks controls Left-clicking on an edge between two squares adds a track segment between the two squares. Right-clicking on an edge adds a cross on the edge, @@ -3288,7 +3473,7 @@ columns to match the clue. (All the actions described in \k{common-actions} are also available.) -\H{tracks-parameters} \I{parameters, for Tracks}Tracks parameters +\H{tracks-parameters} \I{parameters, for Tracks}Train Tracks parameters These parameters are available from the \q{Custom...} option on the \q{Type} menu. @@ -3305,12 +3490,12 @@ that would lead to impossible crossings later. \dt \e{Disallow consecutive 1 clues} -\dd Controls whether the Tracks game generation permits two adjacent -rows or columns to have a 1 clue, or permits the row or column of the -track's endpoint to have a 1 clue. By default this is not permitted, -to avoid long straight boring segments of track and make the games -more twiddly and interesting. If you want to restore the possibility, -turn this option off. +\dd Controls whether the Train Tracks game generation permits two +adjacent rows or columns to have a 1 clue, or permits the row or +column of the track's endpoint to have a 1 clue. By default this is +not permitted, to avoid long straight boring segments of track and +make the games more twiddly and interesting. If you want to restore +the possibility, turn this option off. \C{palisade} \i{Palisade} @@ -3329,7 +3514,7 @@ Credit for this puzzle goes to \i{Nikoli}, who call it \q{Five Cells}. Palisade was contributed to this collection by Jonas K\u00F6{oe}lker. \B{nikoli-palisade} -\W{http://nikoli.co.jp/en/puzzles/five_cells.html}\cw{http://nikoli.co.jp/en/puzzles/five_cells.html} +\W{https://www.nikoli.co.jp/en/puzzles/five_cells/}\cw{https://www.nikoli.co.jp/en/puzzles/five_cells/} \H{palisade-controls} \I{controls, for Palisade}Palisade controls @@ -3354,14 +3539,64 @@ These parameters are available from the \q{Custom...} option on the \dd The size of the regions into which the grid must be subdivided. +\C{mosaic} \i{Mosaic} + +\cfg{winhelp-topic}{games.mosaic} + +You are given a grid of squares, which you must colour either black or +white. + +Some squares contain clue numbers. Each clue tells you the number of +black squares in the 3\times\.3 region surrounding the clue \dash +\e{including} the clue square itself. + +This game is variously known in other locations as: ArtMosaico, Count +and Darken, Cuenta Y Sombrea, Fill-a-Pix, Fill-In, Komsu Karala, +Magipic, Majipiku, Mosaico, Mosaik, Mozaiek, Nampre Puzzle, +Nurie-Puzzle, Oekaki-Pix, Voisimage. + +Mosaic was contributed to this collection by Didi Kohen. Colour design +by Michal Shomer. The implementation is loosely based on +\W{https://github.com/mordechaim/Mosaic}\cw{github.com/mordechaim/Mosaic}. + +\H{mosaic-controls} \I{controls, for Mosaic}Mosaic controls + +To play Mosaic, click the mouse in a square to change its colour. +Left-clicking an empty square will turn it black, and right-clicking +will turn it white. Keep clicking the same button to cycle through the +three possible states for the square. + +If you hold down the mouse button and drag, you can colour multiple +cells in a single action. + +You can also use the cursor keys to move around the grid. Pressing the +return or space keys will turn an empty square black or white +respectively (and then cycle the colours in the same way as the mouse +buttons), and pressing Backspace will reset a square to empty. + +\H{Mosaic-parameters} \I{parameters, for Mosaic}Mosaic parameters + +These parameters are available from the \q{Custom...} option on the +\q{Type} menu. + +\dt \e{Width}, \e{Height} + +\dd Size of grid in squares. + +\dt \e{Aggressive generation} + +\dd With this option set, the game generator will try harder to +eliminate unnecessary clues on the board. This slows down generation, +so it's not recommended for boards larger than, say, 30\times\.30. + \A{licence} \I{MIT licence}\ii{Licence} -This software is \i{copyright} 2004-2014 Simon Tatham. +This software is \i{copyright} 2004-2024 Simon Tatham. Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas K\u00F6{oe}lker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens, Michael -Quevillon and Asher Gordon. +Quevillon, Asher Gordon, Didi Kohen, and Ben Harris. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h index 29b00ddaf0..2c52bc6cde 100644 --- a/apps/plugins/puzzles/src/puzzles.h +++ b/apps/plugins/puzzles/src/puzzles.h @@ -18,6 +18,9 @@ #define STR_INT(x) #x #define STR(x) STR_INT(x) +/* An upper bound on the length of sprintf'ed integers (signed or unsigned). */ +#define MAX_DIGITS(x) (sizeof(x) * CHAR_BIT / 3 + 2) + /* NB not perfect because they evaluate arguments multiple times. */ #ifndef max #define max(x,y) ( (x)>(y) ? (x) : (y) ) @@ -69,6 +72,7 @@ enum { (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) #define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) #define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND ) +#define STRIP_BUTTON_MODIFIERS(m) ( (unsigned)(m) & ~MOD_MASK ) /* * Flags in the back end's `flags' word. @@ -83,14 +87,6 @@ enum { #define REQUIRE_NUMPAD ( 1 << 11 ) /* end of `flags' word definitions */ -#ifdef _WIN32_WCE - /* Pocket PC devices have small, portrait screen that requires more vivid colours */ - #define SMALL_SCREEN - #define PORTRAIT_SCREEN - #define VIVID_COLOURS - #define STYLUS_BASED -#endif - #define IGNOREARG(x) ( (x) = (x) ) typedef struct frontend frontend; @@ -132,8 +128,13 @@ typedef struct psdata psdata; */ enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END }; struct config_item { - /* Not dynamically allocated */ + /* Not dynamically allocated: the GUI display name for the option */ const char *name; + /* Not dynamically allocated: the keyword identifier for the + * option. Only examined in the case where this structure is being + * used for options that appear in config files, i.e. the + * get_prefs method fills this in but configure does not. */ + const char *kw; /* Value from the above C_* enum */ int type; union { @@ -150,6 +151,13 @@ struct config_item { * options `Foo', `Bar' and `Baz'. */ const char *choicenames; + /* + * choicekws is non-NULL, not dynamically allocated, and + * contains a parallel list of keyword strings used to + * represent the enumeration in config files. As with 'kw' + * above, this is only expected to be set by get_prefs. + */ + const char *choicekws; /* * Indicates the chosen index from the options in * choicenames. In the above example, 0==Foo, 1==Bar and @@ -256,7 +264,7 @@ void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, int align, int colour, const char *text); void draw_rect(drawing *dr, int x, int y, int w, int h, int colour); void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour); -void draw_polygon(drawing *dr, int *coords, int npoints, +void draw_polygon(drawing *dr, const int *coords, int npoints, int fillcolour, int outlinecolour); void draw_circle(drawing *dr, int cx, int cy, int radius, int fillcolour, int outlinecolour); @@ -307,13 +315,16 @@ void midend_free(midend *me); const game *midend_which_game(midend *me); void midend_set_params(midend *me, game_params *params); game_params *midend_get_params(midend *me); -void midend_size(midend *me, int *x, int *y, bool user_size); +void midend_size(midend *me, int *x, int *y, bool user_size, + double device_pixel_ratio); void midend_reset_tilesize(midend *me); void midend_new_game(midend *me); void midend_restart_game(midend *me); void midend_stop_anim(midend *me); -bool midend_process_key(midend *me, int x, int y, int button); +enum { PKR_QUIT = 0, PKR_SOME_EFFECT, PKR_NO_EFFECT, PKR_UNUSED }; +int midend_process_key(midend *me, int x, int y, int button); key_label *midend_request_keys(midend *me, int *nkeys); +const char *midend_current_key_label(midend *me, int button); void midend_force_redraw(midend *me); void midend_redraw(midend *me); float *midend_colours(midend *me, int *ncolours); @@ -322,7 +333,7 @@ void midend_timer(midend *me, float tplus); struct preset_menu *midend_get_presets(midend *me, int *id_limit); int midend_which_preset(midend *me); bool midend_wants_statusbar(midend *me); -enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC }; +enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_PREFS, CFG_FRONTEND_SPECIFIC }; config_item *midend_get_config(midend *me, int which, char **wintitle); const char *midend_set_config(midend *me, int which, config_item *cfg); const char *midend_game_id(midend *me, const char *id); @@ -343,6 +354,11 @@ void midend_serialise(midend *me, const char *midend_deserialise(midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx); +const char *midend_load_prefs( + midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx); +void midend_save_prefs(midend *me, + void (*write)(void *ctx, const void *buf, int len), + void *wctx); const char *identify_game(char **name, bool (*read)(void *ctx, void *buf, int len), void *rctx); @@ -374,12 +390,22 @@ void free_cfg(config_item *cfg); void free_keys(key_label *keys, int nkeys); void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); char *fgetline(FILE *fp); +char *make_prefs_path(const char *dir, const char *sep, + const game *game, const char *suffix); +int n_times_root_k(int n, int k); /* allocates output each time. len is always in bytes of binary data. * May assert (or just go wrong) if lengths are unchecked. */ char *bin2hex(const unsigned char *in, int inlen); unsigned char *hex2bin(const char *in, int outlen); +/* Returns 0 or 1 if the environment variable is set, or dflt if not. + * dflt may be a third value if it needs to be. */ +int getenv_bool(const char *name, int dflt); + +/* Mixes two colours in specified proportions. */ +void colour_mix(const float src1[3], const float src2[3], float p, + float dst[3]); /* Sets (and possibly dims) background from frontend default colour, * and auto-generates highlight and lowlight colours too. */ void game_mkhighlight(frontend *fe, float *ret, @@ -392,14 +418,15 @@ void game_mkhighlight_specific(frontend *fe, float *ret, /* Randomly shuffles an array of items. */ void shuffle(void *array, int nelts, int eltsize, random_state *rs); -/* Draw a rectangle outline, using the drawing API's draw_line. */ +/* Draw a rectangle outline, using the drawing API's draw_polygon. */ void draw_rect_outline(drawing *dr, int x, int y, int w, int h, int colour); /* Draw a set of rectangle corners (e.g. for a cursor display). */ void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); -void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap); +char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap, + bool *visible); /* Used in netslide.c and sixteen.c for cursor movement around edge. */ int c2pos(int w, int h, int cx, int cy); @@ -416,37 +443,52 @@ void draw_text_outline(drawing *dr, int x, int y, int fonttype, * less than buffer size. */ void copy_left_justified(char *buf, size_t sz, const char *str); -/* An ugly, but working float-to-string implementation for platforms - * that don't have one */ -int ftoa(char *buf, float f); - /* Returns a generic label based on the value of `button.' To be used whenever a `label' field returned by the request_keys() game function is NULL. Dynamically allocated, to be freed by caller. */ char *button2label(int button); +/* Swap two regions of memory. The two regions must not + * overlap. (Note: the natural name for this might be "memswap", but + * the mem* namespace is reserved for future expansion by the C99 + * standard per clause 7.26.11.1.) */ +void swap_regions(void *av, void *bv, size_t size); + /* * dsf.c */ -int *snew_dsf(int size); - -void print_dsf(int *dsf, int size); - -/* Return the canonical element of the equivalence class containing element - * val. If 'inverse' is non-NULL, this function will put into it a flag - * indicating whether the canonical element is inverse to val. */ -int edsf_canonify(int *dsf, int val, bool *inverse); -int dsf_canonify(int *dsf, int val); -int dsf_size(int *dsf, int val); - -/* Allow the caller to specify that two elements should be in the same - * equivalence class. If 'inverse' is true, the elements are actually opposite - * to one another in some sense. This function will fail an assertion if the - * caller gives it self-contradictory data, ie if two elements are claimed to - * be both opposite and non-opposite. */ -void edsf_merge(int *dsf, int v1, int v2, bool inverse); -void dsf_merge(int *dsf, int v1, int v2); -void dsf_init(int *dsf, int len); +typedef struct DSF DSF; +DSF *dsf_new(int size); +void dsf_free(DSF *dsf); + +void dsf_copy(DSF *to, DSF *from); + +/* Basic dsf operations, return the canonical element of a class, + * check if two elements are in the same class, and return the size of + * a class. These work on all types of dsf. */ +int dsf_canonify(DSF *dsf, int n); +bool dsf_equivalent(DSF *dsf, int n1, int n2); +int dsf_size(DSF *dsf, int n); + +/* Merge two elements and their classes. Not legal on a flip dsf. */ +void dsf_merge(DSF *dsf, int n1, int n2); + +/* Special dsf that tracks the minimal element of every equivalence + * class, and a function to query it. */ +DSF *dsf_new_min(int size); +int dsf_minimal(DSF *dsf, int n); + +/* Special dsf that tracks whether pairs of elements in the same class + * have flipped sense relative to each other. Merge function takes an + * argument saying whether n1 and n2 are opposite to each other; + * canonify function will report whether n is opposite to the returned + * element. */ +DSF *dsf_new_flip(int size); +void dsf_merge_flip(DSF *dsf, int n1, int n2, bool flip); +int dsf_canonify_flip(DSF *dsf, int n, bool *flip); + +/* Reinitialise a dsf to the starting 'all elements distinct' state. */ +void dsf_reinit(DSF *dsf); /* * tdq.c @@ -507,7 +549,7 @@ void random_free(random_state *state); char *random_state_encode(random_state *state); random_state *random_state_decode(const char *input); /* random.c also exports SHA, which occasionally comes in useful. */ -#if __STDC_VERSION__ >= 199901L +#if HAVE_STDINT_H #include typedef uint32_t uint32; #elif UINT_MAX >= 4294967295L @@ -532,7 +574,7 @@ void SHA_Simple(const void *p, int len, unsigned char *output); document *document_new(int pw, int ph, float userscale); void document_free(document *doc); void document_add_puzzle(document *doc, const game *game, game_params *par, - game_state *st, game_state *st2); + game_ui *ui, game_state *st, game_state *st2); int document_npages(const document *doc); void document_begin(const document *doc, drawing *dr); void document_end(const document *doc, drawing *dr); @@ -564,7 +606,9 @@ void free_combi(combi_ctx *combi); * divvy.c */ /* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ -int *divvy_rectangle(int w, int h, int k, random_state *rs); +DSF *divvy_rectangle(int w, int h, int k, random_state *rs); +/* Same, but only tries once, and may fail. (Exposed for test program.) */ +DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs); /* * findloop.c @@ -661,19 +705,24 @@ struct game { bool can_format_as_text_ever; bool (*can_format_as_text_now)(const game_params *params); char *(*text_format)(const game_state *state); + config_item *(*get_prefs)(game_ui *ui); + void (*set_prefs)(game_ui *ui, const config_item *cfg); game_ui *(*new_ui)(const game_state *state); void (*free_ui)(game_ui *ui); char *(*encode_ui)(const game_ui *ui); - void (*decode_ui)(game_ui *ui, const char *encoding); + void (*decode_ui)(game_ui *ui, const char *encoding, + const game_state *state); key_label *(*request_keys)(const game_params *params, int *nkeys); void (*changed_state)(game_ui *ui, const game_state *oldstate, const game_state *newstate); + const char *(*current_key_label)(const game_ui *ui, + const game_state *state, int button); char *(*interpret_move)(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button); game_state *(*execute_move)(const game_state *state, const char *move); int preferred_tilesize; void (*compute_size)(const game_params *params, int tilesize, - int *x, int *y); + const game_ui *ui, int *x, int *y); void (*set_size)(drawing *dr, game_drawstate *ds, const game_params *params, int tilesize); float *(*colours)(frontend *fe, int *ncolours); @@ -693,8 +742,10 @@ struct game { int *x, int *y, int *w, int *h); int (*status)(const game_state *state); bool can_print, can_print_in_colour; - void (*print_size)(const game_params *params, float *x, float *y); - void (*print)(drawing *dr, const game_state *state, int tilesize); + void (*print_size)(const game_params *params, const game_ui *ui, + float *x, float *y); + void (*print)(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize); bool wants_statusbar; bool is_timed; bool (*timing_state)(const game_state *state, game_ui *ui); @@ -712,7 +763,7 @@ struct drawing_api { void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour); void (*draw_line)(void *handle, int x1, int y1, int x2, int y2, int colour); - void (*draw_polygon)(void *handle, int *coords, int npoints, + void (*draw_polygon)(void *handle, const int *coords, int npoints, int fillcolour, int outlinecolour); void (*draw_circle)(void *handle, int cx, int cy, int radius, int fillcolour, int outlinecolour); @@ -750,17 +801,29 @@ struct drawing_api { #ifdef COMBINED extern const game *gamelist[]; extern const int gamecount; +/* Also pre-declare every individual 'struct game' we expect */ +#define GAME(x) extern const game x; +#include "generated-games.h" +#undef GAME #else extern const game thegame; #endif /* - * Special string value to return from interpret_move in the case - * where the game UI has been updated but no actual move is being - * appended to the undo chain. Must be declared as a non-const char, - * but should never actually be modified by anyone. + * Special string values to return from interpret_move. + * + * MOVE_UI_UPDATE is for the case where the game UI has been updated + * but no actual move is being appended to the undo chain. + * + * MOVE_NO_EFFECT is for when the key was understood by the puzzle, + * but it happens that there isn't effect, not even a UI change. + * + * MOVE_UNUSED is for keys that the puzzle has no use for at all. + * + * Each must be declared as a non-const char, but should never + * actually be modified by anyone. */ -extern char UI_UPDATE[]; +extern char MOVE_UI_UPDATE[], MOVE_NO_EFFECT[], MOVE_UNUSED[]; /* A little bit of help to lazy developers */ #define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." diff --git a/apps/plugins/puzzles/src/random.c b/apps/plugins/puzzles/src/random.c index fb54560c95..bd11f16601 100644 --- a/apps/plugins/puzzles/src/random.c +++ b/apps/plugins/puzzles/src/random.c @@ -109,7 +109,7 @@ void SHA_Init(SHA_State * s) void SHA_Bytes(SHA_State * s, const void *p, int len) { - unsigned char *q = (unsigned char *) p; + const unsigned char *q = (const unsigned char *) p; uint32 wordblock[16]; uint32 lenw = len; int i; @@ -254,12 +254,12 @@ unsigned long random_bits(random_state *state, int bits) } /* - * `(1 << bits) - 1' is not good enough, since if bits==32 on a + * `(1UL << bits) - 1' is not good enough, since if bits==32 on a * 32-bit machine, behaviour is undefined and Intel has a nasty * habit of shifting left by zero instead. We'll shift by * bits-1 and then separately shift by one. */ - ret &= (1 << (bits-1)) * 2 - 1; + ret &= (1UL << (bits-1)) * 2 - 1; return ret; } diff --git a/apps/plugins/puzzles/src/range.R b/apps/plugins/puzzles/src/range.R deleted file mode 100644 index f1256efd1e..0000000000 --- a/apps/plugins/puzzles/src/range.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -RANGE_EXTRA = dsf - -range : [X] GTK COMMON range RANGE_EXTRA range-icon|no-icon - -range : [G] WINDOWS COMMON range RANGE_EXTRA range.res|noicon.res - -ALL += range[COMBINED] RANGE_EXTRA - -!begin am gtk -GAMES += range -!end - -!begin >list.c - A(range) \ -!end - -!begin >gamedesc.txt -range:range.exe:Range:Visible-distance puzzle:Place black squares to limit the visible distance from each numbered cell. -!end diff --git a/apps/plugins/puzzles/src/range.c b/apps/plugins/puzzles/src/range.c index fc0a5405f1..bc29f7604b 100644 --- a/apps/plugins/puzzles/src/range.c +++ b/apps/plugins/puzzles/src/range.c @@ -58,7 +58,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -911,8 +915,8 @@ static const char *validate_params(const game_params *params, bool full) int const w = params->w, h = params->h; if (w < 1) return "Error: width is less than 1"; if (h < 1) return "Error: height is less than 1"; + if (w > SCHAR_MAX - (h - 1)) return "Error: w + h is too big"; if (w * h < 1) return "Error: size is less than 1"; - if (w + h - 1 > SCHAR_MAX) return "Error: w + h is too big"; /* I might be unable to store clues in my puzzle_size *grid; */ if (full) { if (w == 2 && h == 2) return "Error: can't create 2x2 puzzles"; @@ -1221,28 +1225,101 @@ static char *game_text_format(const game_state *state) struct game_ui { puzzle_size r, c; /* cursor position */ bool cursor_show; + + /* + * User preference option to swap the left and right mouse + * buttons. + * + * The original puzzle submitter thought it would be more useful + * to have the left button turn an empty square into a dotted one, + * on the grounds that that was what you did most often; I (SGT) + * felt instinctively that the left button ought to place black + * squares and the right button place dots, on the grounds that + * that was consistent with many other puzzles in which the left + * button fills in the data used by the solution checker while the + * right button places pencil marks for the user's convenience. + * + * My first beta-player wasn't sure either, so I thought I'd + * pre-emptively put in a 'configuration' mechanism just in case. + */ + bool swap_buttons; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static int initialised = false; + static int swap_buttons = -1; + + if (!initialised) { + initialised = true; + swap_buttons = getenv_bool("RANGE_SWAP_BUTTONS", -1); + } + + if (swap_buttons != -1) + ui_out->swap_buttons = swap_buttons; +} + static game_ui *new_ui(const game_state *state) { struct game_ui *ui = snew(game_ui); ui->r = ui->c = 0; - ui->cursor_show = false; + ui->cursor_show = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->swap_buttons = false; + legacy_prefs_override(ui); + return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Mouse button order"; + ret[0].kw = "left-mouse-button"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = + ":Left to fill, right to dot:Left to dot, right to fill"; + ret[0].u.choices.choicekws = ":fill:dot"; + ret[0].u.choices.selected = ui->swap_buttons; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->swap_buttons = cfg[0].u.choices.selected; +} + +static void free_ui(game_ui *ui) +{ + sfree(ui); } -static void decode_ui(game_ui *ui, const char *encoding) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + int cell; + + if (IS_CURSOR_SELECT(button)) { + cell = state->grid[idx(ui->r, ui->c, state->params.w)]; + if (!ui->cursor_show || cell > 0) return ""; + switch (cell) { + case EMPTY: + return button == CURSOR_SELECT ? "Fill" : "Dot"; + case WHITE: + return button == CURSOR_SELECT ? "Empty" : "Fill"; + case BLACK: + return button == CURSOR_SELECT ? "Dot" : "Empty"; + } + } + return ""; + } typedef struct drawcell { @@ -1253,7 +1330,6 @@ typedef struct drawcell { struct game_drawstate { int tilesize; drawcell *grid; - bool started; }; #define TILESIZE (ds->tilesize) @@ -1283,38 +1359,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { - /* - * Utterly awful hack, exactly analogous to the one in Slant, - * to configure the left and right mouse buttons the opposite - * way round. - * - * The original puzzle submitter thought it would be more - * useful to have the left button turn an empty square into a - * dotted one, on the grounds that that was what you did most - * often; I (SGT) felt instinctively that the left button - * ought to place black squares and the right button place - * dots, on the grounds that that was consistent with many - * other puzzles in which the left button fills in the data - * used by the solution checker while the right button places - * pencil marks for the user's convenience. - * - * My first beta-player wasn't sure either, so I thought I'd - * pre-emptively put in a 'configuration' mechanism just in - * case. - */ - { - static int swap_buttons = -1; - if (swap_buttons < 0) { - char *env = getenv("RANGE_SWAP_BUTTONS"); - swap_buttons = (env && (env[0] == 'y' || env[0] == 'Y')); - } - if (swap_buttons) { - if (button == LEFT_BUTTON) - button = RIGHT_BUTTON; - else - button = LEFT_BUTTON; - } - } + if (ui->swap_buttons) { + if (button == LEFT_BUTTON) + button = RIGHT_BUTTON; + else + button = LEFT_BUTTON; + } } switch (button) { @@ -1355,14 +1405,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, else if (do_post) return nfmtstr(40, "W,%d,%d", ui->r, ui->c); else - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (!out_of_bounds(ui->r + dr[i], ui->c + dc[i], w, h)) { ui->r += dr[i]; ui->c += dc[i]; } } else ui->cursor_show = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (action == hint) { @@ -1408,7 +1458,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, static bool find_errors(const game_state *state, bool *report) { int const w = state->params.w, h = state->params.h, n = w * h; - int *dsf; + DSF *dsf; int r, c, i; @@ -1463,7 +1513,7 @@ static bool find_errors(const game_state *state, bool *report) /* * Check that all the white cells form a single connected component. */ - dsf = snew_dsf(n); + dsf = dsf_new(n); for (r = 0; r < h-1; ++r) for (c = 0; c < w; ++c) if (state->grid[r*w+c] != BLACK && @@ -1474,11 +1524,12 @@ static bool find_errors(const game_state *state, bool *report) if (state->grid[r*w+c] != BLACK && state->grid[r*w+(c+1)] != BLACK) dsf_merge(dsf, r*w+c, r*w+(c+1)); - if (nblack + dsf_size(dsf, any_white_cell) < n) { + if (any_white_cell != -1 && + nblack + dsf_size(dsf, any_white_cell) < n) { int biggest, canonical; if (!report) { - sfree(dsf); + dsf_free(dsf); goto found_error; } @@ -1503,7 +1554,7 @@ static bool find_errors(const game_state *state, bool *report) if (state->grid[i] != BLACK && dsf_canonify(dsf, i) != canonical) report[i] = true; } - sfree(dsf); + dsf_free(dsf); free_game(dup); return false; /* if report != NULL, this is ignored */ @@ -1604,13 +1655,12 @@ enum { COL_USER = COL_GRID, COL_ERROR, COL_LOWLIGHT, - COL_HIGHLIGHT = COL_ERROR, /* mkhighlight needs it, I don't */ COL_CURSOR = COL_LOWLIGHT, NCOLOURS }; static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = (1 + params->w) * tilesize; *y = (1 + params->h) * tilesize; @@ -1629,7 +1679,7 @@ static float *game_colours(frontend *fe, int *ncolours) { float *ret = snewn(3 * NCOLOURS, float); - game_mkhighlight(fe, ret, COL_BACKGROUND, COL_HIGHLIGHT, COL_LOWLIGHT); + game_mkhighlight(fe, ret, COL_BACKGROUND, -1, COL_LOWLIGHT); COLOUR(ret, COL_GRID, 0.0F, 0.0F, 0.0F); COLOUR(ret, COL_ERROR, 1.0F, 0.0F, 0.0F); @@ -1655,7 +1705,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) int i; ds->tilesize = 0; - ds->started = false; ds->grid = snewn(n, drawcell); for (i = 0; i < n; ++i) @@ -1690,7 +1739,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, float animtime, float flashtime) { int const w = state->params.w, h = state->params.h, n = w * h; - int const wpx = (w+1) * ds->tilesize, hpx = (h+1) * ds->tilesize; int const flash = ((int) (flashtime * 5 / FLASH_TIME)) % 2; int r, c, i; @@ -1701,12 +1749,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, assert (oldstate == NULL); /* only happens if animating moves */ - if (!ds->started) { - ds->started = true; - draw_rect(dr, 0, 0, wpx, hpx, COL_BACKGROUND); - draw_update(dr, 0, 0, wpx, hpx); - } - for (i = r = 0; r < h; ++r) { for (c = 0; c < w; ++c, ++i) { drawcell cell = makecell(state->grid[i], errors[i], false, flash); @@ -1757,25 +1799,21 @@ static void draw_cell(drawing *draw, game_drawstate *ds, int r, int c, draw_update(draw, x, y, ts + 1, ts + 1); } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - puts("warning: game_timing_state was called (this shouldn't happen)"); - return false; /* the (non-existing) timer should not be running */ -} - /* ---------------------------------------------------------------------- * User interface: print */ -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int print_width, print_height; - game_compute_size(params, 800, &print_width, &print_height); + game_compute_size(params, 800, ui, &print_width, &print_height); *x = print_width / 100.0F; *y = print_height / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int const w = state->params.w, h = state->params.h; game_drawstate ds_obj, *ds = &ds_obj; @@ -1821,12 +1859,14 @@ struct game const thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1840,6 +1880,6 @@ struct game const thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/rect.R b/apps/plugins/puzzles/src/rect.R deleted file mode 100644 index 1448c0fa63..0000000000 --- a/apps/plugins/puzzles/src/rect.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -rect : [X] GTK COMMON rect rect-icon|no-icon - -rect : [G] WINDOWS COMMON rect rect.res|noicon.res - -ALL += rect[COMBINED] - -!begin am gtk -GAMES += rect -!end - -!begin >list.c - A(rect) \ -!end - -!begin >gamedesc.txt -rect:rect.exe:Rectangles:Rectangles puzzle:Divide the grid into rectangles with areas equal to the numbers. -!end diff --git a/apps/plugins/puzzles/src/rect.c b/apps/plugins/puzzles/src/rect.c index b13de75fd4..c3ee1ab478 100644 --- a/apps/plugins/puzzles/src/rect.c +++ b/apps/plugins/puzzles/src/rect.c @@ -26,7 +26,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -163,10 +167,7 @@ static char *encode_params(const game_params *params, bool full) sprintf(data, "%dx%d", params->w, params->h); if (full && params->expandfactor) - { - sprintf(data + strlen(data), "e"); - ftoa(data + strlen(data), params->expandfactor); - } + sprintf(data + strlen(data), "e%g", params->expandfactor); if (full && !params->unique) strcat(data, "a"); @@ -192,7 +193,7 @@ static config_item *game_configure(const game_params *params) ret[2].name = "Expansion factor"; ret[2].type = C_STRING; - ftoa(buf, params->expandfactor); + sprintf(buf, "%g", params->expandfactor); ret[2].u.string.sval = dupstr(buf); ret[3].name = "Ensure unique solution"; @@ -221,6 +222,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w <= 0 || params->h <= 0) return "Width and height must both be greater than zero"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->w*params->h < 2) return "Grid area must be greater than one"; if (params->expandfactor < 0.0F) @@ -2207,7 +2210,7 @@ static game_ui *new_ui(const game_state *state) reset_ui(ui); ui->erasing = false; ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->cur_dragging = false; return ui; } @@ -2217,15 +2220,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void coord_round(float x, float y, int *xr, int *yr) { float xs, ys, xv, yv, dx, dy, dist; @@ -2377,6 +2371,21 @@ struct game_drawstate { unsigned long *visible; }; +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cur_visible && + !(ui->drag_start_x >= 0 && !ui->cur_dragging)) { + if (ui->cur_dragging) { + if (!ui->dragged) return "Cancel"; + if ((button == CURSOR_SELECT2) == ui->erasing) return "Done"; + return "Cancel"; + } + return button == CURSOR_SELECT ? "Mark" : "Erase"; + } + return ""; +} + static char *interpret_move(const game_state *from, game_ui *ui, const game_drawstate *ds, int x, int y, int button) @@ -2385,7 +2394,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, bool startdrag = false, enddrag = false, active = false, erasing = false; char buf[80], *ret; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); coord_round(FROMCOORD((float)x), FROMCOORD((float)y), &xc, &yc); @@ -2406,10 +2415,11 @@ static char *interpret_move(const game_state *from, game_ui *ui, enddrag = true; erasing = (button == RIGHT_RELEASE); } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false); - ui->cur_visible = true; + char *ret; + ret = move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, + false, &ui->cur_visible); active = true; - if (!ui->cur_dragging) return UI_UPDATE; + if (!ui->cur_dragging || ret != MOVE_UI_UPDATE) return ret; coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); } else if (IS_CURSOR_SELECT(button)) { if (ui->drag_start_x >= 0 && !ui->cur_dragging) { @@ -2422,7 +2432,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, if (!ui->cur_visible) { assert(!ui->cur_dragging); ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); erasing = (button == CURSOR_SELECT2); @@ -2443,7 +2453,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, reset_ui(ui); /* cancel keyboard dragging */ ui->cur_dragging = false; } - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (button != LEFT_DRAG && button != RIGHT_DRAG) { return NULL; } @@ -2527,7 +2537,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, if (ret) return ret; /* a move has been made */ else if (active) - return UI_UPDATE; + return MOVE_UI_UPDATE; else return NULL; } @@ -2621,7 +2631,7 @@ static game_state *execute_move(const game_state *from, const char *move) #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) ) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2796,9 +2806,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } if (!ds->started) { - draw_rect(dr, 0, 0, - state->w * TILE_SIZE + 2*BORDER + 1, - state->h * TILE_SIZE + 2*BORDER + 1, COL_BACKGROUND); draw_rect(dr, COORD(0)-1, COORD(0)-1, ds->w*TILE_SIZE+3, ds->h*TILE_SIZE+3, COL_LINE); ds->started = true; @@ -2901,24 +2908,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 5mm squares by default. */ - game_compute_size(params, 500, &pw, &ph); + game_compute_size(params, 500, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->w, h = state->h; int ink = print_mono_colour(dr, 0); @@ -2992,12 +2996,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -3011,7 +3017,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/resource.h b/apps/plugins/puzzles/src/resource.h deleted file mode 100644 index f0bfa16d6d..0000000000 --- a/apps/plugins/puzzles/src/resource.h +++ /dev/null @@ -1,20 +0,0 @@ - -#define IDR_MENUBAR1 101 - -#define ID_GAME 40005 -#define ID_TYPE 40006 - -#define IDS_CAP_GAME 40105 -#define IDS_CAP_TYPE 40106 - -#define IDD_ABOUT 2000 -#define IDC_ABOUT_CAPTION 2001 -#define IDC_ABOUT_LINE 2002 -#define IDC_ABOUT_GAME 2003 -#define IDC_ABOUT_VERSION 2004 - -#define IDD_CONFIG 2100 -#define IDC_CONFIG_CAPTION 2101 -#define IDC_CONFIG_LINE 2102 - -#define IDR_PADTOOLBAR 4000 diff --git a/apps/plugins/puzzles/src/samegame.R b/apps/plugins/puzzles/src/samegame.R deleted file mode 100644 index cc0d350041..0000000000 --- a/apps/plugins/puzzles/src/samegame.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -samegame : [X] GTK COMMON samegame samegame-icon|no-icon - -samegame : [G] WINDOWS COMMON samegame samegame.res|noicon.res - -ALL += samegame[COMBINED] - -!begin am gtk -GAMES += samegame -!end - -!begin >list.c - A(samegame) \ -!end - -!begin >gamedesc.txt -samegame:samegame.exe:Same Game:Block-clearing puzzle:Clear the grid by removing touching groups of the same colour squares. -!end diff --git a/apps/plugins/puzzles/src/samegame.c b/apps/plugins/puzzles/src/samegame.c index 615c60e0a5..30550e1f1c 100644 --- a/apps/plugins/puzzles/src/samegame.c +++ b/apps/plugins/puzzles/src/samegame.c @@ -67,7 +67,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -285,6 +290,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 1 || params->h < 1) return "Width and height must both be positive"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->ncols > 9) return "Maximum of 9 colours"; @@ -858,6 +865,8 @@ static void gen_grid(int w, int h, int nc, int *grid, random_state *rs) #if defined GENERATION_DIAGNOSTICS || defined COUNT_FAILURES printf("%d failures\n", failures); +#else + (void)failures; #endif #ifdef GENERATION_DIAGNOSTICS { @@ -1013,12 +1022,6 @@ static void free_game(game_state *state) sfree(state); } -static char *solve_game(const game_state *state, const game_state *currstate, - const char *aux, const char **error) -{ - return NULL; -} - static bool game_can_format_as_text_now(const game_params *params) { return true; @@ -1065,7 +1068,7 @@ static game_ui *new_ui(const game_state *state) ui->nselected = 0; ui->xsel = ui->ysel = 0; - ui->displaysel = false; + ui->displaysel = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -1076,15 +1079,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void sel_clear(game_ui *ui, const game_state *state) { int i; @@ -1099,14 +1093,25 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { sel_clear(ui, newstate); +} - /* - * If the game state has just changed into an unplayable one - * (either completed or impossible), we vanish the keyboard- - * control cursor. - */ - if (newstate->complete || newstate->impossible) - ui->displaysel = false; +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button)) { + int x = ui->xsel, y = ui->ysel, c = COL(state,x,y); + if (c == 0) return ""; + if (ISSEL(ui, x, y)) + return button == CURSOR_SELECT2 ? "Unselect" : "Remove"; + if ((x > 0 && COL(state,x-1,y) == c) || + (x+1 < state->params.w && COL(state,x+1,y) == c) || + (y > 0 && COL(state,x,y-1) == c) || + (y+1 < state->params.h && COL(state,x,y+1) == c)) + return "Select"; + /* Cursor is over a lone square, so we can't select it. */ + if (ui->nselected) return "Unselect"; + } + return ""; } static char *sel_movedesc(game_ui *ui, const game_state *state) @@ -1274,30 +1279,25 @@ static char *interpret_move(const game_state *state, game_ui *ui, int x, int y, int button) { int tx, ty; - char *ret = UI_UPDATE; - - ui->displaysel = false; + char *ret = MOVE_UI_UPDATE; if (button == RIGHT_BUTTON || button == LEFT_BUTTON) { + ui->displaysel = false; tx = FROMCOORD(x); ty= FROMCOORD(y); } else if (IS_CURSOR_MOVE(button)) { - int dx = 0, dy = 0; - ui->displaysel = true; - dx = (button == CURSOR_LEFT) ? -1 : ((button == CURSOR_RIGHT) ? +1 : 0); - dy = (button == CURSOR_DOWN) ? +1 : ((button == CURSOR_UP) ? -1 : 0); - ui->xsel = (ui->xsel + state->params.w + dx) % state->params.w; - ui->ysel = (ui->ysel + state->params.h + dy) % state->params.h; - return ret; + return move_cursor(button, &ui->xsel, &ui->ysel, + state->params.w, state->params.h, + true, &ui->displaysel); } else if (IS_CURSOR_SELECT(button)) { ui->displaysel = true; tx = ui->xsel; ty = ui->ysel; } else - return NULL; + return MOVE_UNUSED; if (tx < 0 || tx >= state->params.w || ty < 0 || ty >= state->params.h) - return NULL; - if (COL(state, tx, ty) == 0) return NULL; + return MOVE_UNUSED; + if (COL(state, tx, ty) == 0) return MOVE_NO_EFFECT; if (ISSEL(ui,tx,ty)) { if (button == RIGHT_BUTTON || button == CURSOR_SELECT2) @@ -1324,6 +1324,10 @@ static game_state *execute_move(const game_state *from, const char *move) move++; while (*move) { + if (!isdigit((unsigned char)*move)) { + free_game(ret); + return NULL; + } i = atoi(move); if (i < 0 || i >= ret->n) { free_game(ret); @@ -1353,12 +1357,12 @@ static game_state *execute_move(const game_state *from, const char *move) static void game_set_size(drawing *dr, game_drawstate *ds, const game_params *params, int tilesize) { - ds->tilegap = 2; + ds->tilegap = (tilesize + 8) / 16; ds->tileinner = tilesize - ds->tilegap; } static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up tile size variables for macro expansion purposes */ game_drawstate ads, *ds = &ads; @@ -1372,7 +1376,7 @@ static float *game_colours(frontend *fe, int *ncolours) { float *ret = snewn(3 * NCOLOURS, float); - frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]); + game_mkhighlight(fe, ret, COL_BACKGROUND, COL_HIGHLIGHT, COL_LOWLIGHT); ret[COL_1 * 3 + 0] = 0.0F; ret[COL_1 * 3 + 1] = 0.0F; @@ -1386,8 +1390,8 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_3 * 3 + 1] = 0.0F; ret[COL_3 * 3 + 2] = 0.0F; - ret[COL_4 * 3 + 0] = 1.0F; - ret[COL_4 * 3 + 1] = 1.0F; + ret[COL_4 * 3 + 0] = 0.7F; + ret[COL_4 * 3 + 1] = 0.7F; ret[COL_4 * 3 + 2] = 0.0F; ret[COL_5 * 3 + 0] = 1.0F; @@ -1395,16 +1399,16 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_5 * 3 + 2] = 1.0F; ret[COL_6 * 3 + 0] = 0.0F; - ret[COL_6 * 3 + 1] = 1.0F; - ret[COL_6 * 3 + 2] = 1.0F; + ret[COL_6 * 3 + 1] = 0.8F; + ret[COL_6 * 3 + 2] = 0.8F; ret[COL_7 * 3 + 0] = 0.5F; ret[COL_7 * 3 + 1] = 0.5F; ret[COL_7 * 3 + 2] = 1.0F; - ret[COL_8 * 3 + 0] = 0.5F; - ret[COL_8 * 3 + 1] = 1.0F; - ret[COL_8 * 3 + 2] = 0.5F; + ret[COL_8 * 3 + 0] = 0.2F; + ret[COL_8 * 3 + 1] = 0.8F; + ret[COL_8 * 3 + 2] = 0.2F; ret[COL_9 * 3 + 0] = 1.0F; ret[COL_9 * 3 + 1] = 0.5F; @@ -1418,14 +1422,6 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_SEL * 3 + 1] = 1.0F; ret[COL_SEL * 3 + 2] = 1.0F; - ret[COL_HIGHLIGHT * 3 + 0] = 1.0F; - ret[COL_HIGHLIGHT * 3 + 1] = 1.0F; - ret[COL_HIGHLIGHT * 3 + 2] = 1.0F; - - ret[COL_LOWLIGHT * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 2.0F / 3.0F; - ret[COL_LOWLIGHT * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 2.0F / 3.0F; - ret[COL_LOWLIGHT * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 2.0F / 3.0F; - *ncolours = NCOLOURS; return ret; } @@ -1462,6 +1458,7 @@ static void tile_redraw(drawing *dr, game_drawstate *ds, int tile, int bgcolour) { int outer = bgcolour, inner = outer, col = tile & TILE_COLMASK; + int tile_w, tile_h, outer_w, outer_h; if (col) { if (tile & TILE_IMPOSSIBLE) { @@ -1474,19 +1471,25 @@ static void tile_redraw(drawing *dr, game_drawstate *ds, outer = inner = col; } } - draw_rect(dr, COORD(x), COORD(y), TILE_INNER, TILE_INNER, outer); - draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4, - TILE_INNER/2, TILE_INNER/2, inner); - - if (dright) - draw_rect(dr, COORD(x)+TILE_INNER, COORD(y), TILE_GAP, TILE_INNER, - (tile & TILE_JOINRIGHT) ? outer : bgcolour); - if (dbelow) - draw_rect(dr, COORD(x), COORD(y)+TILE_INNER, TILE_INNER, TILE_GAP, - (tile & TILE_JOINDOWN) ? outer : bgcolour); - if (dright && dbelow) - draw_rect(dr, COORD(x)+TILE_INNER, COORD(y)+TILE_INNER, TILE_GAP, TILE_GAP, - (tile & TILE_JOINDIAG) ? outer : bgcolour); + tile_w = dright ? TILE_SIZE : TILE_INNER; + tile_h = dbelow ? TILE_SIZE : TILE_INNER; + outer_w = (tile & TILE_JOINRIGHT) ? tile_w : TILE_INNER; + outer_h = (tile & TILE_JOINDOWN) ? tile_h : TILE_INNER; + /* Draw the background if any of it will be visible. */ + if (outer_w != tile_w || outer_h != tile_h || outer == bgcolour) + draw_rect(dr, COORD(x), COORD(y), tile_w, tile_h, bgcolour); + /* Draw the piece. */ + if (outer != bgcolour) + draw_rect(dr, COORD(x), COORD(y), outer_w, outer_h, outer); + if (inner != outer) + draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4, + TILE_INNER/2, TILE_INNER/2, inner); + /* Reset bottom-right corner if necessary. */ + if ((tile & (TILE_JOINRIGHT | TILE_JOINDOWN | TILE_JOINDIAG)) == + (TILE_JOINRIGHT | TILE_JOINDOWN) && outer != bgcolour && + TILE_GAP != 0) + draw_rect(dr, COORD(x)+TILE_INNER, COORD(y)+TILE_INNER, + TILE_GAP, TILE_GAP, bgcolour); if (tile & TILE_HASSEL) { int sx = COORD(x)+2, sy = COORD(y)+2, ssz = TILE_INNER-5; @@ -1512,13 +1515,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILE_SIZE * state->params.w + 2 * BORDER, - TILE_SIZE * state->params.h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILE_SIZE * state->params.w + 2 * BORDER, - TILE_SIZE * state->params.h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -1541,7 +1537,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, ds->started = true; } - if (flashtime > 0.0) { + if (flashtime > 0.0F) { int frame = (int)(flashtime / FLASH_FRAME); bgcolour = (frame % 2 ? COL_LOWLIGHT : COL_HIGHLIGHT); } else @@ -1564,8 +1560,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if ((tile & TILE_JOINRIGHT) && (tile & TILE_JOINDOWN) && COL(state,x+1,y+1) == col) tile |= TILE_JOINDIAG; - - if (ui->displaysel && ui->xsel == x && ui->ysel == y) + /* + * If the game state is an unplayable one (either + * completed or impossible), we hide the keyboard-control + * cursor. + */ + if (ui->displaysel && ui->xsel == x && ui->ysel == y && + !(state->complete || state->impossible)) tile |= TILE_HASSEL; /* For now we're never expecting oldstate at all (because we have @@ -1637,19 +1638,6 @@ static int game_status(const game_state *state) return state->complete ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame samegame #endif @@ -1669,14 +1657,16 @@ const struct game thegame = { new_game, dup_game, free_game, - false, solve_game, + false, NULL, /* solve */ true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1688,8 +1678,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/signpost.R b/apps/plugins/puzzles/src/signpost.R deleted file mode 100644 index 09ea367d57..0000000000 --- a/apps/plugins/puzzles/src/signpost.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -SIGNPOST_EXTRA = dsf - -signpost : [X] GTK COMMON signpost SIGNPOST_EXTRA signpost-icon|no-icon -signpost : [G] WINDOWS COMMON signpost SIGNPOST_EXTRA signpost.res|noicon.res - -signpostsolver : [U] signpost[STANDALONE_SOLVER] SIGNPOST_EXTRA STANDALONE m.lib -signpostsolver : [C] signpost[STANDALONE_SOLVER] SIGNPOST_EXTRA STANDALONE - -ALL += signpost[COMBINED] SIGNPOST_EXTRA - -!begin am gtk -GAMES += signpost -!end - -!begin >list.c - A(signpost) \ -!end - -!begin >gamedesc.txt -signpost:signpost.exe:Signpost:Square-connecting puzzle:Connect the squares into a path following the arrows. -!end diff --git a/apps/plugins/puzzles/src/signpost.c b/apps/plugins/puzzles/src/signpost.c index 9aee255ebe..9aed67bb4a 100644 --- a/apps/plugins/puzzles/src/signpost.c +++ b/apps/plugins/puzzles/src/signpost.c @@ -7,7 +7,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -57,7 +62,7 @@ struct game_state { int *nums; /* numbers, size n */ unsigned int *flags; /* flags, size n */ int *next, *prev; /* links to other cell indexes, size n (-1 absent) */ - int *dsf; /* connects regions with a dsf. */ + DSF *dsf; /* connects regions with a dsf. */ int *numsi; /* for each number, which index is it in? (-1 absent) */ }; @@ -168,7 +173,7 @@ static bool isvalidmove(const game_state *state, bool clever, /* can't create a new connection between cells in the same region * as that would create a loop. */ - if (dsf_canonify(state->dsf, from) == dsf_canonify(state->dsf, to)) + if (dsf_equivalent(state->dsf, from, to)) return false; /* if both cells are actual numbers, can't drag if we're not @@ -277,7 +282,7 @@ static void strip_nums(game_state *state) { memset(state->next, -1, state->n*sizeof(int)); memset(state->prev, -1, state->n*sizeof(int)); memset(state->numsi, -1, (state->n+1)*sizeof(int)); - dsf_init(state->dsf, state->n); + dsf_reinit(state->dsf); } static bool check_nums(game_state *orig, game_state *copy, bool only_immutable) @@ -421,6 +426,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 1) return "Width must be at least one"; if (params->h < 1) return "Height must be at least one"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (full && params->w == 1 && params->h == 1) /* The UI doesn't let us move these from unsolved to solved, * so we disallow generating (but not playing) them. */ @@ -454,7 +461,7 @@ static game_state *blank_game(int w, int h) state->flags = snewn(state->n, unsigned int); state->next = snewn(state->n, int); state->prev = snewn(state->n, int); - state->dsf = snew_dsf(state->n); + state->dsf = dsf_new(state->n); state->numsi = snewn(state->n+1, int); blank_game_into(state); @@ -475,7 +482,7 @@ static void dup_game_to(game_state *to, const game_state *from) memcpy(to->next, from->next, to->n*sizeof(int)); memcpy(to->prev, from->prev, to->n*sizeof(int)); - memcpy(to->dsf, from->dsf, to->n*sizeof(int)); + dsf_copy(to->dsf, from->dsf); memcpy(to->numsi, from->numsi, (to->n+1)*sizeof(int)); } @@ -493,7 +500,7 @@ static void free_game(game_state *state) sfree(state->flags); sfree(state->next); sfree(state->prev); - sfree(state->dsf); + dsf_free(state->dsf); sfree(state->numsi); sfree(state); } @@ -1011,7 +1018,7 @@ static void connect_numbers(game_state *state) { int i, di, dni; - dsf_init(state->dsf, state->n); + dsf_reinit(state->dsf); for (i = 0; i < state->n; i++) { if (state->next[i] != -1) { assert(state->prev[state->next[i]] == i); @@ -1028,8 +1035,8 @@ static void connect_numbers(game_state *state) static int compare_heads(const void *a, const void *b) { - struct head_meta *ha = (struct head_meta *)a; - struct head_meta *hb = (struct head_meta *)b; + const struct head_meta *ha = (const struct head_meta *)a; + const struct head_meta *hb = (const struct head_meta *)b; /* Heads with preferred colours first... */ if (ha->preference && !hb->preference) return -1; @@ -1380,8 +1387,32 @@ struct game_ui { bool dragging, drag_is_from; int sx, sy; /* grid coords of start cell */ int dx, dy; /* pixel coords of drag posn */ + + /* + * Trivial and foolish configurable option done on purest whim. + * With this option enabled, the victory flash is done by rotating + * each square in the opposite direction from its immediate + * neighbours, so that they behave like a field of interlocking + * gears. With it disabled, they all rotate in the same direction. + * Choose for yourself which is more brain-twisting :-) + */ + bool gear_mode; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int gear_mode = -1; + + if (!initialised) { + initialised = true; + gear_mode = getenv_bool("SIGNPOST_GEARS", -1); + } + + if (gear_mode != -1) + ui_out->gear_mode = gear_mode; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); @@ -1390,11 +1421,14 @@ static game_ui *new_ui(const game_state *state) * copy to clone, there's code that needs fixing in game_redraw too. */ ui->cx = ui->cy = 0; - ui->cshow = false; + ui->cshow = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->dragging = false; ui->sx = ui->sy = ui->dx = ui->dy = 0; + ui->gear_mode = false; + legacy_prefs_override(ui); + return ui; } @@ -1403,13 +1437,28 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Victory rotation effect"; + ret[0].kw = "flash-type"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = ":Unidirectional:Meshing gears"; + ret[0].u.choices.choicekws = ":unidirectional:gears"; + ret[0].u.choices.selected = ui->gear_mode; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->gear_mode = cfg[0].u.choices.selected; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1421,6 +1470,26 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cshow) { + if (ui->dragging) { + if (ui->drag_is_from) { + if (isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy)) + return "To here"; + } else { + if (isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy)) + return "From here"; + } + return "Cancel"; + } else { + return button == CURSOR_SELECT ? "From here" : "To here"; + } + } + return ""; +} + struct game_drawstate { int tilesize; bool started, solved; @@ -1442,26 +1511,27 @@ static char *interpret_move(const game_state *state, game_ui *ui, char buf[80]; if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false); - ui->cshow = true; + char *ret; + ret = move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false, + &ui->cshow); if (ui->dragging) { ui->dx = COORD(ui->cx) + TILE_SIZE/2; ui->dy = COORD(ui->cy) + TILE_SIZE/2; } - return UI_UPDATE; + return ret; } else if (IS_CURSOR_SELECT(button)) { if (!ui->cshow) ui->cshow = true; else if (ui->dragging) { ui->dragging = false; - if (ui->sx == ui->cx && ui->sy == ui->cy) return UI_UPDATE; + if (ui->sx == ui->cx && ui->sy == ui->cy) return MOVE_UI_UPDATE; if (ui->drag_is_from) { if (!isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy)) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, ui->cx, ui->cy); } else { if (!isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy)) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "L%d,%d-%d,%d", ui->cx, ui->cy, ui->sx, ui->sy); } return dupstr(buf); @@ -1473,7 +1543,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->dy = COORD(ui->cy) + TILE_SIZE/2; ui->drag_is_from = (button == CURSOR_SELECT); } - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_MOUSE_DOWN(button)) { if (ui->cshow) { @@ -1502,19 +1572,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->dx = mx; ui->dy = my; ui->cshow = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (IS_MOUSE_DRAG(button) && ui->dragging) { ui->dx = mx; ui->dy = my; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (IS_MOUSE_RELEASE(button) && ui->dragging) { ui->dragging = false; - if (ui->sx == x && ui->sy == y) return UI_UPDATE; /* single click */ + if (ui->sx == x && ui->sy == y) return MOVE_UI_UPDATE; /* single click */ if (!INGRID(state, x, y)) { int si = ui->sy*w+ui->sx; if (state->prev[si] == -1 && state->next[si] == -1) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "%c%d,%d", (int)(ui->drag_is_from ? 'C' : 'X'), ui->sx, ui->sy); return dupstr(buf); @@ -1522,11 +1592,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->drag_is_from) { if (!isvalidmove(state, false, ui->sx, ui->sy, x, y)) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, x, y); } else { if (!isvalidmove(state, false, x, y, ui->sx, ui->sy)) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "L%d,%d-%d,%d", x, y, ui->sx, ui->sy); } return dupstr(buf); @@ -1535,7 +1605,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, else if ((button == 'x' || button == 'X') && ui->cshow) { int si = ui->cy*w + ui->cx; if (state->prev[si] == -1 && state->next[si] == -1) - return UI_UPDATE; + return MOVE_UI_UPDATE; sprintf(buf, "%c%d,%d", (int)((button == 'x') ? 'C' : 'X'), ui->cx, ui->cy); return dupstr(buf); @@ -1641,7 +1711,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize, order; } ads, *ds = &ads; @@ -1825,9 +1895,8 @@ static void draw_star(drawing *dr, int cx, int cy, int rad, int npoints, coords = snewn(npoints * 2 * 2, int); for (n = 0; n < npoints * 2; n++) { - /* hack to accomodate rockbox's concave polygon drawing */ - a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset - PI / npoints; - r = (n % 2 == 0) ? (double)rad/2.0 : (double)rad; + a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset; + r = (n % 2) ? (double)rad/2.0 : (double)rad; /* We're rotating the point at (0, -r) by a degrees */ coords[2*n+0] = cx + (int)( r * sin(a)); @@ -2082,7 +2151,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int aw = TILE_SIZE * state->w; int ah = TILE_SIZE * state->h; - draw_rect(dr, 0, 0, aw + 2 * BORDER, ah + 2 * BORDER, COL_BACKGROUND); draw_rect_outline(dr, BORDER - 1, BORDER - 1, aw + 2, ah + 2, COL_GRID); draw_update(dr, 0, 0, aw + 2 * BORDER, ah + 2 * BORDER); } @@ -2127,28 +2195,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (state->nums[i] != ds->nums[i] || f != ds->f[i] || dirp != ds->dirp[i] || force || !ds->started) { - int sign; - { - /* - * Trivial and foolish configurable option done on - * purest whim. With this option enabled, the - * victory flash is done by rotating each square - * in the opposite direction from its immediate - * neighbours, so that they behave like a field of - * interlocking gears. With it disabled, they all - * rotate in the same direction. Choose for - * yourself which is more brain-twisting :-) - */ - static int gear_mode = -1; - if (gear_mode < 0) { - char *env = getenv("SIGNPOST_GEARS"); - gear_mode = (env && (env[0] == 'y' || env[0] == 'Y')); - } - if (gear_mode) - sign = 1 - 2 * ((x ^ y) & 1); - else - sign = 1; - } + int sign = (ui->gear_mode ? 1 - 2 * ((x ^ y) & 1) : 1); tile_redraw(dr, ds, BORDER + x * TILE_SIZE, BORDER + y * TILE_SIZE, @@ -2206,21 +2253,18 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; - game_compute_size(params, 1300, &pw, &ph); + game_compute_size(params, 1300, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int ink = print_mono_colour(dr, 0); int x, y; @@ -2273,12 +2317,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2292,7 +2338,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; @@ -2301,10 +2347,9 @@ const struct game thegame = { #include #include -const char *quis = NULL; -int verbose = 0; +static const char *quis = NULL; -void usage(FILE *out) { +static void usage(FILE *out) { fprintf(out, "usage: %s [--stdin] [--soak] [--seed SEED] |\n", quis); } @@ -2405,7 +2450,7 @@ static void process_desc(char *id) thegame.free_params(p); } -int main(int argc, const char *argv[]) +int main(int argc, char *argv[]) { char *id = NULL, *desc, *aux = NULL; const char *err; diff --git a/apps/plugins/puzzles/src/singles.R b/apps/plugins/puzzles/src/singles.R deleted file mode 100644 index a67aed2fbc..0000000000 --- a/apps/plugins/puzzles/src/singles.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -SINGLES_EXTRA = dsf LATIN - -singles : [X] GTK COMMON singles SINGLES_EXTRA singles-icon|no-icon -singles : [G] WINDOWS COMMON singles SINGLES_EXTRA singles.res|noicon.res - -ALL += singles[COMBINED] SINGLES_EXTRA - -singlessolver : [U] singles[STANDALONE_SOLVER] SINGLES_EXTRA STANDALONE -singlessolver : [C] singles[STANDALONE_SOLVER] SINGLES_EXTRA STANDALONE - -!begin am gtk -GAMES += singles -!end - -!begin >list.c - A(singles) \ -!end - -!begin >gamedesc.txt -singles:singles.exe:Singles:Number-removing puzzle:Black out the right set of duplicate numbers. -!end diff --git a/apps/plugins/puzzles/src/singles.c b/apps/plugins/puzzles/src/singles.c index 202ce08b20..07db8361ae 100644 --- a/apps/plugins/puzzles/src/singles.c +++ b/apps/plugins/puzzles/src/singles.c @@ -58,13 +58,17 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "latin.h" #ifdef STANDALONE_SOLVER -bool verbose = false; +static bool verbose = false; #endif #define PREFERRED_TILE_SIZE 32 @@ -82,7 +86,7 @@ bool verbose = false; #define FLASH_TIME 0.7F enum { - COL_BACKGROUND, COL_HIGHLIGHT, COL_LOWLIGHT, + COL_BACKGROUND, COL_UNUSED1, COL_LOWLIGHT, COL_BLACK, COL_WHITE, COL_BLACKNUM, COL_GRID, COL_CURSOR, COL_ERROR, NCOLOURS @@ -254,7 +258,7 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { if (params->w < 2 || params->h < 2) - return "Width and neight must be at least two"; + return "Width and height must be at least two"; if (params->w > 10+26+26 || params->h > 10+26+26) return "Puzzle is too large"; if (full) { @@ -417,7 +421,7 @@ static void debug_state(const char *desc, game_state *state) { sfree(dbg); } -static void connect_if_same(game_state *state, int *dsf, int i1, int i2) +static void connect_if_same(game_state *state, DSF *dsf, int i1, int i2) { int c1, c2; @@ -429,13 +433,13 @@ static void connect_if_same(game_state *state, int *dsf, int i1, int i2) dsf_merge(dsf, c1, c2); } -static void connect_dsf(game_state *state, int *dsf) +static void connect_dsf(game_state *state, DSF *dsf) { int x, y, i; /* Construct a dsf array for connected blocks; connections * tracked to right and down. */ - dsf_init(dsf, state->n); + dsf_reinit(dsf); for (x = 0; x < state->w; x++) { for (y = 0; y < state->h; y++) { i = y*state->w + x; @@ -494,7 +498,7 @@ static int check_rowcol(game_state *state, int starti, int di, int sz, unsigned static bool check_complete(game_state *state, unsigned flags) { - int *dsf = snewn(state->n, int); + DSF *dsf = dsf_new(state->n); int x, y, i, error = 0, nwhite, w = state->w, h = state->h; if (flags & CC_MARK_ERRORS) { @@ -543,7 +547,7 @@ static bool check_complete(game_state *state, unsigned flags) int size = dsf_size(dsf, i); if (largest < size) { largest = size; - canonical = i; + canonical = dsf_canonify(dsf, i); } } @@ -558,7 +562,7 @@ static bool check_complete(game_state *state, unsigned flags) } } - sfree(dsf); + dsf_free(dsf); return !(error > 0); } @@ -1304,9 +1308,10 @@ found: return j; } -static char *new_game_desc(const game_params *params, random_state *rs, +static char *new_game_desc(const game_params *params_orig, random_state *rs, char **aux, bool interactive) { + game_params *params = dup_params(params_orig); game_state *state = blank_game(params->w, params->h); game_state *tosolve = blank_game(params->w, params->h); int i, j, *scratch, *rownums, *colnums, x, y, ntries; @@ -1315,6 +1320,12 @@ static char *new_game_desc(const game_params *params, random_state *rs, digit *latin; struct solver_state *ss = solver_state_new(state); + /* Downgrade difficulty to Easy for puzzles so tiny that they aren't + * possible to generate at Tricky. These are 2x2, 2x3 and 3x3, i.e. + * any puzzle that doesn't have one dimension at least 4. */ + if ((w < 4 || h < 4) && params->diff > DIFF_EASY) + params->diff = DIFF_EASY; + scratch = snewn(state->n, int); rownums = snewn(h*o, int); colnums = snewn(w*o, int); @@ -1408,6 +1419,7 @@ randomise: free_game(tosolve); free_game(state); + free_params(params); solver_state_free(ss); sfree(scratch); sfree(rownums); @@ -1446,24 +1458,37 @@ static game_ui *new_ui(const game_state *state) game_ui *ui = snew(game_ui); ui->cx = ui->cy = 0; - ui->cshow = false; + ui->cshow = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->show_black_nums = false; return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Show numbers on black squares"; + ret[0].kw = "show-black-nums"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->show_black_nums; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->show_black_nums = cfg[0].u.boolean.bval; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1473,6 +1498,18 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cshow = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cshow) { + unsigned int f = state->flags[ui->cy * state->w + ui->cx]; + if (f & F_BLACK) return "Restore"; + if (f & F_CIRCLE) return "Remove"; + return button == CURSOR_SELECT ? "Black" : "Circle"; + } + return ""; +} + #define DS_BLACK 0x1 #define DS_CIRCLE 0x2 #define DS_CURSOR 0x4 @@ -1497,11 +1534,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, int i, x = FROMCOORD(mx), y = FROMCOORD(my); enum { NONE, TOGGLE_BLACK, TOGGLE_CIRCLE, UI } action = NONE; - if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true); - ui->cshow = true; - action = UI; - } else if (IS_CURSOR_SELECT(button)) { + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true, + &ui->cshow); + else if (IS_CURSOR_SELECT(button)) { x = ui->cx; y = ui->cy; if (!ui->cshow) { action = UI; @@ -1519,14 +1555,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (!INGRID(state, x, y)) { ui->show_black_nums = !ui->show_black_nums; - action = UI; /* this wants to be a per-game option. */ + action = UI; } else if (button == LEFT_BUTTON) { action = TOGGLE_BLACK; } else if (button == RIGHT_BUTTON) { action = TOGGLE_CIRCLE; } } - if (action == UI) return UI_UPDATE; + if (action == UI) return MOVE_UI_UPDATE; if (action == TOGGLE_BLACK || action == TOGGLE_CIRCLE) { i = y * state->w + x; @@ -1587,7 +1623,7 @@ badmove: */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1608,12 +1644,13 @@ static float *game_colours(frontend *fe, int *ncolours) float *ret = snewn(3 * NCOLOURS, float); int i; - game_mkhighlight(fe, ret, COL_BACKGROUND, COL_HIGHLIGHT, COL_LOWLIGHT); + game_mkhighlight(fe, ret, COL_BACKGROUND, -1, COL_LOWLIGHT); for (i = 0; i < 3; i++) { ret[COL_BLACK * 3 + i] = 0.0F; ret[COL_BLACKNUM * 3 + i] = 0.4F; ret[COL_WHITE * 3 + i] = 1.0F; ret[COL_GRID * 3 + i] = ret[COL_LOWLIGHT * 3 + i]; + ret[COL_UNUSED1 * 3 + i] = 0.0F; /* To placate an assertion. */ } ret[COL_CURSOR * 3 + 0] = 0.2F; ret[COL_CURSOR * 3 + 1] = 0.8F; @@ -1708,7 +1745,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int wsz = TILE_SIZE * state->w + 2 * BORDER; int hsz = TILE_SIZE * state->h + 2 * BORDER; - draw_rect(dr, 0, 0, wsz, hsz, COL_BACKGROUND); draw_rect_outline(dr, COORD(0)-1, COORD(0)-1, TILE_SIZE * state->w + 2, TILE_SIZE * state->h + 2, COL_GRID); @@ -1776,22 +1812,19 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* 8mm squares by default. */ - game_compute_size(params, 800, &pw, &ph); + game_compute_size(params, 800, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int ink = print_mono_colour(dr, 0); int paper = print_mono_colour(dr, 1); @@ -1848,12 +1881,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1867,7 +1902,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; diff --git a/apps/plugins/puzzles/src/sixteen.R b/apps/plugins/puzzles/src/sixteen.R deleted file mode 100644 index c63a27cef8..0000000000 --- a/apps/plugins/puzzles/src/sixteen.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -sixteen : [X] GTK COMMON sixteen sixteen-icon|no-icon - -sixteen : [G] WINDOWS COMMON sixteen sixteen.res|noicon.res - -ALL += sixteen[COMBINED] - -!begin am gtk -GAMES += sixteen -!end - -!begin >list.c - A(sixteen) \ -!end - -!begin >gamedesc.txt -sixteen:sixteen.exe:Sixteen:Toroidal sliding block puzzle:Slide a row at a time to arrange the tiles into order. -!end diff --git a/apps/plugins/puzzles/src/sixteen.c b/apps/plugins/puzzles/src/sixteen.c index 0b02038c43..38f6711a49 100644 --- a/apps/plugins/puzzles/src/sixteen.c +++ b/apps/plugins/puzzles/src/sixteen.c @@ -9,7 +9,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -173,6 +178,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->movetarget < 0) return "Number of shuffling moves may not be negative"; return NULL; @@ -567,7 +574,7 @@ static game_ui *new_ui(const game_state *state) game_ui *ui = snew(game_ui); ui->cur_x = 0; ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->cur_mode = unlocked; return ui; @@ -578,18 +585,24 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + if (IS_CURSOR_SELECT(button) && ui->cur_visible) { + if (ui->cur_x == -1 || ui->cur_x == state->w || + ui->cur_y == -1 || ui->cur_y == state->h) + return button == CURSOR_SELECT2 ? "Back" : "Slide"; + if (button == CURSOR_SELECT) + return ui->cur_mode == lock_tile ? "Unlock" : "Lock tile"; + if (button == CURSOR_SELECT2) + return ui->cur_mode == lock_position ? "Unlock" : "Lock pos"; + } + return ""; } struct game_drawstate { @@ -609,12 +622,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, bool shift = button & MOD_SHFT, control = button & MOD_CTRL; int pad = button & MOD_NUM_KEYPAD; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (IS_CURSOR_MOVE(button) || pad) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (control || shift || ui->cur_mode) { @@ -622,9 +635,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (x < 0 || x >= state->w || y < 0 || y >= state->h) return NULL; move_cursor(button | pad, &x, &y, - state->w, state->h, false); + state->w, state->h, false, NULL); move_cursor(button | pad, &xwrap, &ywrap, - state->w, state->h, true); + state->w, state->h, true, NULL); if (x != xwrap) { sprintf(buf, "R%d,%c1", y, x ? '+' : '-'); @@ -645,7 +658,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int x = ui->cur_x + 1, y = ui->cur_y + 1; move_cursor(button | pad, &x, &y, - state->w + 2, state->h + 2, false); + state->w + 2, state->h + 2, false, NULL); if (x == 0 && y == 0) { int t = ui->cur_x; @@ -669,7 +682,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } @@ -687,11 +700,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, const enum cursor_mode m = (button == CURSOR_SELECT2 ? lock_position : lock_tile); ui->cur_mode = (ui->cur_mode == m ? unlocked : m); - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else { return NULL; @@ -706,7 +719,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, else if (cy == state->h && cx >= 0 && cx < state->w) dy = +1, dx = 0; else - return UI_UPDATE; /* invalid click location */ + return MOVE_UI_UPDATE; /* invalid click location */ /* reverse direction if right hand button is pressed */ if (button == RIGHT_BUTTON || button == CURSOR_SELECT2) { @@ -748,11 +761,11 @@ static game_state *execute_move(const game_state *from, const char *move) } if (move[0] == 'R' && sscanf(move+1, "%d,%d", &cy, &dx) == 2 && - cy >= 0 && cy < from->h) { + cy >= 0 && cy < from->h && -from->h <= dx && dx <= from->w ) { cx = dy = 0; n = from->w; } else if (move[0] == 'C' && sscanf(move+1, "%d,%d", &cx, &dy) == 2 && - cx >= 0 && cx < from->w) { + cx >= 0 && cx < from->w && -from->h <= dy && dy <= from->h) { cy = dx = 0; n = from->h; } else @@ -790,7 +803,7 @@ static game_state *execute_move(const game_state *from, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -937,13 +950,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -1165,19 +1171,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame sixteen #endif @@ -1199,12 +1192,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1216,9 +1211,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/slant.R b/apps/plugins/puzzles/src/slant.R deleted file mode 100644 index ff0d21f1eb..0000000000 --- a/apps/plugins/puzzles/src/slant.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -SLANT_EXTRA = dsf findloop - -slant : [X] GTK COMMON slant SLANT_EXTRA slant-icon|no-icon - -slant : [G] WINDOWS COMMON slant SLANT_EXTRA slant.res|noicon.res - -slantsolver : [U] slant[STANDALONE_SOLVER] SLANT_EXTRA STANDALONE -slantsolver : [C] slant[STANDALONE_SOLVER] SLANT_EXTRA STANDALONE - -ALL += slant[COMBINED] SLANT_EXTRA - -!begin am gtk -GAMES += slant -!end - -!begin >list.c - A(slant) \ -!end - -!begin >gamedesc.txt -slant:slant.exe:Slant:Maze-drawing puzzle:Draw a maze of slanting lines that matches the clues. -!end diff --git a/apps/plugins/puzzles/src/slant.c b/apps/plugins/puzzles/src/slant.c index ed290fe57d..bd04b786e6 100644 --- a/apps/plugins/puzzles/src/slant.c +++ b/apps/plugins/puzzles/src/slant.c @@ -28,7 +28,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -51,7 +55,7 @@ enum { */ #if defined STANDALONE_SOLVER #define SOLVER_DIAGNOSTICS -bool verbose = false; +static bool verbose = false; #elif defined SOLVER_DIAGNOSTICS #define verbose true #endif @@ -226,6 +230,8 @@ static const char *validate_params(const game_params *params, bool full) if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; return NULL; } @@ -238,7 +244,7 @@ struct solver_scratch { * Disjoint set forest which tracks the connected sets of * points. */ - int *connected; + DSF *connected; /* * Counts the number of possible exits from each connected set @@ -259,7 +265,7 @@ struct solver_scratch { * Another disjoint set forest. This one tracks _squares_ which * are known to slant in the same direction. */ - int *equiv; + DSF *equiv; /* * Stores slash values which we know for an equivalence class. @@ -306,10 +312,10 @@ static struct solver_scratch *new_scratch(int w, int h) { int W = w+1, H = h+1; struct solver_scratch *ret = snew(struct solver_scratch); - ret->connected = snewn(W*H, int); + ret->connected = dsf_new(W*H); ret->exits = snewn(W*H, int); ret->border = snewn(W*H, bool); - ret->equiv = snewn(w*h, int); + ret->equiv = dsf_new(w*h); ret->slashval = snewn(w*h, signed char); ret->vbitmap = snewn(w*h, unsigned char); return ret; @@ -319,10 +325,10 @@ static void free_scratch(struct solver_scratch *sc) { sfree(sc->vbitmap); sfree(sc->slashval); - sfree(sc->equiv); + dsf_free(sc->equiv); sfree(sc->border); sfree(sc->exits); - sfree(sc->connected); + dsf_free(sc->connected); sfree(sc); } @@ -330,7 +336,7 @@ static void free_scratch(struct solver_scratch *sc) * Wrapper on dsf_merge() which updates the `exits' and `border' * arrays. */ -static void merge_vertices(int *connected, +static void merge_vertices(DSF *connected, struct solver_scratch *sc, int i, int j) { int exits = -1; @@ -376,7 +382,7 @@ static void decr_exits(struct solver_scratch *sc, int i) static void fill_square(int w, int h, int x, int y, int v, signed char *soln, - int *connected, struct solver_scratch *sc) + DSF *connected, struct solver_scratch *sc) { int W = w+1 /*, H = h+1 */; @@ -466,13 +472,13 @@ static int slant_solve(int w, int h, const signed char *clues, * Establish a disjoint set forest for tracking connectedness * between grid points. */ - dsf_init(sc->connected, W*H); + dsf_reinit(sc->connected); /* * Establish a disjoint set forest for tracking which squares * are known to slant in the same direction. */ - dsf_init(sc->equiv, w*h); + dsf_reinit(sc->equiv); /* * Clear the slashval array. @@ -991,7 +997,8 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) { int W = w+1, H = h+1; int x, y, i; - int *connected, *indices; + DSF *connected; + int *indices; /* * Clear the output. @@ -1002,7 +1009,7 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) * Establish a disjoint set forest for tracking connectedness * between grid points. */ - connected = snew_dsf(W*H); + connected = dsf_new(W*H); /* * Prepare a list of the squares in the grid, and fill them in @@ -1058,7 +1065,7 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) } sfree(indices); - sfree(connected); + dsf_free(connected); } static char *new_game_desc(const game_params *params, random_state *rs, @@ -1574,28 +1581,69 @@ static char *game_text_format(const game_state *state) struct game_ui { int cur_x, cur_y; bool cur_visible; + + /* + * User preference option to swap the left and right mouse + * buttons. There isn't a completely obvious mapping of left and + * right buttons to the two directions of slash, and at least one + * player turned out not to have the same intuition as me. + */ + bool swap_buttons; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int swap_buttons = -1; + + if (!initialised) { + initialised = true; + swap_buttons = getenv_bool("SLANT_SWAP_BUTTONS", -1); + } + + if (swap_buttons != -1) + ui_out->swap_buttons = swap_buttons; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->swap_buttons = false; + legacy_prefs_override(ui); + return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Mouse button order"; + ret[0].kw = "left-button"; + ret[0].type = C_CHOICES; + ret[0].u.choices.choicenames = ":Left \\, right /:Left /, right \\"; + ret[0].u.choices.choicekws = ":\\:/"; + ret[0].u.choices.selected = ui->swap_buttons; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->swap_buttons = cfg[0].u.choices.selected; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1603,6 +1651,22 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, { } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cur_visible) { + switch (state->soln[ui->cur_y*state->p.w+ui->cur_x]) { + case 0: + return button == CURSOR_SELECT ? "\\" : "/"; + case -1: + return button == CURSOR_SELECT ? "/" : "Blank"; + case +1: + return button == CURSOR_SELECT ? "Blank" : "\\"; + } + } + return ""; +} + #define PREFERRED_TILESIZE 32 #define TILESIZE (ds->tilesize) #define BORDER TILESIZE @@ -1638,7 +1702,6 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, struct game_drawstate { int tilesize; - bool started; long *grid; long *todraw; }; @@ -1653,51 +1716,34 @@ static char *interpret_move(const game_state *state, game_ui *ui, enum { CLOCKWISE, ANTICLOCKWISE, NONE } action = NONE; if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { - /* - * This is an utterly awful hack which I should really sort out - * by means of a proper configuration mechanism. One Slant - * player has observed that they prefer the mouse buttons to - * function exactly the opposite way round, so here's a - * mechanism for environment-based configuration. I cache the - * result in a global variable - yuck! - to avoid repeated - * lookups. - */ - { - static int swap_buttons = -1; - if (swap_buttons < 0) { - char *env = getenv("SLANT_SWAP_BUTTONS"); - swap_buttons = (env && (env[0] == 'y' || env[0] == 'Y')); - } - if (swap_buttons) { - if (button == LEFT_BUTTON) - button = RIGHT_BUTTON; - else - button = LEFT_BUTTON; - } - } + if (ui->swap_buttons) { + if (button == LEFT_BUTTON) + button = RIGHT_BUTTON; + else + button = LEFT_BUTTON; + } action = (button == LEFT_BUTTON) ? CLOCKWISE : ANTICLOCKWISE; x = FROMCOORD(x); y = FROMCOORD(y); if (x < 0 || y < 0 || x >= w || y >= h) - return NULL; + return MOVE_UNUSED; ui->cur_visible = false; } else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } x = ui->cur_x; y = ui->cur_y; action = (button == CURSOR_SELECT2) ? ANTICLOCKWISE : CLOCKWISE; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false); - ui->cur_visible = true; - return UI_UPDATE; + return move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false, &ui->cur_visible); } else if (button == '\\' || button == '\b' || button == '/') { int x = ui->cur_x, y = ui->cur_y; - if (button == ("\\" "\b" "/")[state->soln[y*w + x] + 1]) return NULL; + if (button == ("\\" "\b" "/")[state->soln[y*w + x] + 1]) + return MOVE_NO_EFFECT; sprintf(buf, "%c%d,%d", button == '\b' ? 'C' : button, x, y); return dupstr(buf); } @@ -1723,7 +1769,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, return dupstr(buf); } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -1774,7 +1820,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* fool the macros */ struct dummy { int tilesize; } dummy, *ds = &dummy; @@ -1832,7 +1878,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) struct game_drawstate *ds = snew(struct game_drawstate); ds->tilesize = 0; - ds->started = false; ds->grid = snewn((w+2)*(h+2), long); ds->todraw = snewn((w+2)*(h+2), long); for (i = 0; i < (w+2)*(h+2); i++) @@ -1972,14 +2017,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, else flashing = false; - if (!ds->started) { - int ww, wh; - game_compute_size(&state->p, TILESIZE, &ww, &wh); - draw_rect(dr, 0, 0, ww, wh, COL_BACKGROUND); - draw_update(dr, 0, 0, ww, wh); - ds->started = true; - } - /* * Loop over the grid and work out where all the slashes are. * We need to do this because a slash in one square affects the @@ -2082,24 +2119,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->p.w, h = state->p.h, W = w+1; int ink = print_mono_colour(dr, 0); @@ -2179,12 +2213,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -2198,7 +2234,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/solo.R b/apps/plugins/puzzles/src/solo.R deleted file mode 100644 index 081a76147e..0000000000 --- a/apps/plugins/puzzles/src/solo.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -SOLO_EXTRA = divvy dsf - -solo : [X] GTK COMMON solo SOLO_EXTRA solo-icon|no-icon - -solo : [G] WINDOWS COMMON solo SOLO_EXTRA solo.res|noicon.res - -solosolver : [U] solo[STANDALONE_SOLVER] SOLO_EXTRA STANDALONE -solosolver : [C] solo[STANDALONE_SOLVER] SOLO_EXTRA STANDALONE - -ALL += solo[COMBINED] SOLO_EXTRA - -!begin am gtk -GAMES += solo -!end - -!begin >list.c - A(solo) \ -!end - -!begin >gamedesc.txt -solo:solo.exe:Solo:Number placement puzzle:Fill in the grid so that each row, column and square block contains one of every digit. -!end diff --git a/apps/plugins/puzzles/src/solo.c b/apps/plugins/puzzles/src/solo.c index 49753f41dc..2445501f57 100644 --- a/apps/plugins/puzzles/src/solo.c +++ b/apps/plugins/puzzles/src/solo.c @@ -20,7 +20,7 @@ * + while I'm revamping this area, filling in the _last_ * number in a nearly-full row or column should certainly be * permitted even at the lowest difficulty level. - * + also Owen noticed that `Basic' grids requiring numeric + * + also Alex noticed that `Basic' grids requiring numeric * elimination are actually very hard, so I wonder if a * difficulty gradation between that and positional- * elimination-only might be in order @@ -87,11 +87,15 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #ifdef STANDALONE_SOLVER #include -int solver_show_working, solver_recurse_depth; +static int solver_show_working, solver_recurse_depth; #endif #include "puzzles.h" @@ -2638,6 +2642,7 @@ static void solver(int cr, struct block_structure *blocks, sfree(usage->row); sfree(usage->col); sfree(usage->blk); + sfree(usage->diag); if (usage->kblocks) { free_block_structure(usage->kblocks); free_block_structure(usage->extra_cages); @@ -2969,6 +2974,7 @@ static bool gridgen(int cr, struct block_structure *blocks, sfree(usage->blk); sfree(usage->col); sfree(usage->row); + sfree(usage->diag); sfree(usage); return ret; @@ -3222,7 +3228,7 @@ static char *encode_solve_move(int cr, digit *grid) return ret; } -static void dsf_to_blocks(int *dsf, struct block_structure *blocks, +static void dsf_to_blocks(DSF *dsf, struct block_structure *blocks, int min_expected, int max_expected) { int cr = blocks->c * blocks->r, area = cr * cr; @@ -3654,10 +3660,11 @@ static char *new_game_desc(const game_params *params, random_state *rs, * the puzzle size: all 2x2 puzzles appear to be Trivial * (DIFF_BLOCK) so we cannot hold out for even a Basic * (DIFF_SIMPLE) one. + * Jigsaw puzzles of size 2 and 3 are also all trivial. */ dlev.maxdiff = params->diff; dlev.maxkdiff = params->kdiff; - if (c == 2 && r == 2) + if ((c == 2 && r == 2) || (r == 1 && c < 4)) dlev.maxdiff = DIFF_BLOCK; grid = snewn(area, digit); @@ -3684,11 +3691,11 @@ static char *new_game_desc(const game_params *params, random_state *rs, * constructing the block structure. */ if (r == 1) { /* jigsaw mode */ - int *dsf = divvy_rectangle(cr, cr, cr, rs); + DSF *dsf = divvy_rectangle(cr, cr, cr, rs); dsf_to_blocks (dsf, blocks, cr, cr); - sfree(dsf); + dsf_free(dsf); } else { /* basic Sudoku mode */ for (y = 0; y < cr; y++) for (x = 0; x < cr; x++) @@ -3903,14 +3910,14 @@ static const char *spec_to_grid(const char *desc, digit *grid, int area) * end of the block spec, and return an error string or NULL if everything * is OK. The DSF is stored in *PDSF. */ -static const char *spec_to_dsf(const char **pdesc, int **pdsf, +static const char *spec_to_dsf(const char **pdesc, DSF **pdsf, int cr, int area) { const char *desc = *pdesc; int pos = 0; - int *dsf; + DSF *dsf; - *pdsf = dsf = snew_dsf(area); + *pdsf = dsf = dsf_new(area); while (*desc && *desc != ',') { int c; @@ -3921,7 +3928,7 @@ static const char *spec_to_dsf(const char **pdesc, int **pdsf, else if (*desc >= 'a' && *desc <= 'z') c = *desc - 'a' + 1; else { - sfree(dsf); + dsf_free(dsf); return "Invalid character in game description"; } desc++; @@ -3936,7 +3943,7 @@ static const char *spec_to_dsf(const char **pdesc, int **pdsf, * side of it. */ if (pos >= 2*cr*(cr-1)) { - sfree(dsf); + dsf_free(dsf); return "Too much data in block structure specification"; } @@ -3966,7 +3973,7 @@ static const char *spec_to_dsf(const char **pdesc, int **pdsf, * edge at the end. */ if (pos != 2*cr*(cr-1)+1) { - sfree(dsf); + dsf_free(dsf); return "Not enough data in block structure specification"; } @@ -4008,7 +4015,7 @@ static const char *validate_block_desc(const char **pdesc, int cr, int area, int min_nr_squares, int max_nr_squares) { const char *err; - int *dsf; + DSF *dsf; err = spec_to_dsf(pdesc, &dsf, cr, area); if (err) { @@ -4037,7 +4044,7 @@ static const char *validate_block_desc(const char **pdesc, int cr, int area, if (canons[c] == j) { counts[c]++; if (counts[c] > max_nr_squares) { - sfree(dsf); + dsf_free(dsf); sfree(canons); sfree(counts); return "A jigsaw block is too big"; @@ -4047,7 +4054,7 @@ static const char *validate_block_desc(const char **pdesc, int cr, int area, if (c == ncanons) { if (ncanons >= max_nr_blocks) { - sfree(dsf); + dsf_free(dsf); sfree(canons); sfree(counts); return "Too many distinct jigsaw blocks"; @@ -4059,14 +4066,14 @@ static const char *validate_block_desc(const char **pdesc, int cr, int area, } if (ncanons < min_nr_blocks) { - sfree(dsf); + dsf_free(dsf); sfree(canons); sfree(counts); return "Not enough distinct jigsaw blocks"; } for (c = 0; c < ncanons; c++) { if (counts[c] < min_nr_squares) { - sfree(dsf); + dsf_free(dsf); sfree(canons); sfree(counts); return "A jigsaw block is too small"; @@ -4076,7 +4083,7 @@ static const char *validate_block_desc(const char **pdesc, int cr, int area, sfree(counts); } - sfree(dsf); + dsf_free(dsf); return NULL; } @@ -4161,13 +4168,13 @@ static game_state *new_game(midend *me, const game_params *params, if (r == 1) { const char *err; - int *dsf; + DSF *dsf; assert(*desc == ','); desc++; err = spec_to_dsf(&desc, &dsf, cr, area); assert(err == NULL); dsf_to_blocks(dsf, state->blocks, cr, cr); - sfree(dsf); + dsf_free(dsf); } else { int x, y; @@ -4179,13 +4186,13 @@ static game_state *new_game(midend *me, const game_params *params, if (params->killer) { const char *err; - int *dsf; + DSF *dsf; assert(*desc == ','); desc++; err = spec_to_dsf(&desc, &dsf, cr, area); assert(err == NULL); dsf_to_blocks(dsf, state->kblocks, cr, area); - sfree(dsf); + dsf_free(dsf); make_blocks_from_whichblock(state->kblocks); assert(*desc == ','); @@ -4550,6 +4557,17 @@ struct game_ui { * allowed on immutable squares. */ bool hcursor; + + /* + * User preference option: if the user right-clicks in a square + * and presses a number or letter key to add/remove a pencil mark, + * do we hide the mouse highlight again afterwards? + * + * Historically our answer was yes. The Android port prefers no. + * There are advantages both ways, depending how much you dislike + * the highlight cluttering your view. So it's a preference. + */ + bool pencil_keep_highlight; }; static game_ui *new_ui(const game_state *state) @@ -4558,8 +4576,9 @@ static game_ui *new_ui(const game_state *state) ui->hx = ui->hy = 0; ui->hpencil = false; - ui->hshow = false; - ui->hcursor = false; + ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->pencil_keep_highlight = false; return ui; } @@ -4569,13 +4588,26 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Keep mouse highlight after changing a pencil mark"; + ret[0].kw = "pencil-keep-highlight"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->pencil_keep_highlight; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->pencil_keep_highlight = cfg[0].u.boolean.bval; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -4594,6 +4626,14 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (ui->hshow && (button == CURSOR_SELECT)) + return ui->hpencil ? "Ink" : "Pencil"; + return ""; +} + struct game_drawstate { bool started, xtype; int cr; @@ -4613,7 +4653,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int tx, ty; char buf[80]; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); tx = (x + TILE_SIZE - BORDER) / TILE_SIZE - 1; ty = (y + TILE_SIZE - BORDER) / TILE_SIZE - 1; @@ -4632,7 +4672,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == RIGHT_BUTTON) { /* @@ -4652,20 +4692,19 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hshow = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->hx, &ui->hy, cr, cr, false); - ui->hshow = true; ui->hcursor = true; - return UI_UPDATE; + return move_cursor(button, &ui->hx, &ui->hy, cr, cr, false, + &ui->hshow); } if (ui->hshow && (button == CURSOR_SELECT)) { ui->hpencil = !ui->hpencil; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->hshow && @@ -4695,10 +4734,37 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->hpencil && state->grid[ui->hy*cr+ui->hx]) return NULL; + /* + * If you ask to fill a square with what it already contains, + * or blank it when it's already empty, that has no effect... + */ + if ((!ui->hpencil || n == 0) && state->grid[ui->hy*cr+ui->hx] == n) { + bool anypencil = false; + int i; + for (i = 0; i < cr; i++) + anypencil = anypencil || + state->pencil[(ui->hy*cr+ui->hx) * cr + i]; + if (!anypencil) { + /* ... expect to remove the cursor in mouse mode. */ + if (!ui->hcursor) { + ui->hshow = false; + return MOVE_UI_UPDATE; + } + return NULL; + } + } + sprintf(buf, "%c%d,%d,%d", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); - if (!ui->hcursor) ui->hshow = false; + /* + * Hide the highlight after a keypress, if it was mouse- + * generated. Also, don't hide it if this move has changed + * pencil marks and the user preference says not to hide the + * highlight in that situation. + */ + if (!ui->hcursor && !(ui->hpencil && ui->pencil_keep_highlight)) + ui->hshow = false; return dupstr(buf); } @@ -4787,7 +4853,7 @@ static game_state *execute_move(const game_state *from, const char *move) #define GETTILESIZE(cr, w) ( (double)(w-1) / (double)(cr+1) ) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -4920,6 +4986,18 @@ static void draw_number(drawing *dr, game_drawstate *ds, (ds->xtype && (ondiag0(y*cr+x) || ondiag1(y*cr+x))) ? COL_XDIAGONALS : COL_BACKGROUND)); + /* pencil-mode highlight */ + if ((hl & 15) == 2) { + int coords[6]; + coords[0] = cx; + coords[1] = cy; + coords[2] = cx+cw/2; + coords[3] = cy; + coords[4] = cx; + coords[5] = cy+ch/2; + draw_polygon(dr, coords, 3, COL_HIGHLIGHT, COL_HIGHLIGHT); + } + /* * Draw the corners of thick lines in corner-adjacent squares, * which jut into this square by one pixel. @@ -4933,18 +5011,6 @@ static void draw_number(drawing *dr, game_drawstate *ds, if (x+1 < cr && y+1 < cr && state->blocks->whichblock[y*cr+x] != state->blocks->whichblock[(y+1)*cr+x+1]) draw_rect(dr, tx+TILE_SIZE-1-2*GRIDEXTRA, ty+TILE_SIZE-1-2*GRIDEXTRA, GRIDEXTRA, GRIDEXTRA, COL_GRID); - /* pencil-mode highlight */ - if ((hl & 15) == 2) { - int coords[6]; - coords[0] = cx; - coords[1] = cy; - coords[2] = cx+cw/2; - coords[3] = cy; - coords[4] = cx; - coords[5] = cy+ch/2; - draw_polygon(dr, coords, 3, COL_HIGHLIGHT, COL_HIGHLIGHT); - } - if (state->kblocks) { int t = GRIDEXTRA * 3; int kcx, kcy, kcw, kch; @@ -5104,7 +5170,7 @@ static void draw_number(drawing *dr, game_drawstate *ds, fw = (pr - pl) / (float)pw; fh = (pb - pt) / (float)ph; fs = min(fw, fh); - if (fs > bestsize) { + if (fs >= bestsize) { bestsize = fs; pbest = pw; } @@ -5174,14 +5240,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int x, y; if (!ds->started) { - /* - * The initial contents of the window are not guaranteed - * and can vary with front ends. To be on the safe side, - * all games should start by drawing a big - * background-colour rectangle covering the whole window. - */ - draw_rect(dr, 0, 0, SIZE(cr), SIZE(cr), COL_BACKGROUND); - /* * Draw the grid. We draw it as a big thick rectangle of * COL_GRID initially; individual calls to draw_number() @@ -5315,14 +5373,8 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - if (state->completed) - return false; - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; @@ -5331,7 +5383,7 @@ static void game_print_size(const game_params *params, float *x, float *y) * for this game, because players will want to jot down no end * of pencil marks in the squares. */ - game_compute_size(params, 900, &pw, &ph); + game_compute_size(params, 900, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } @@ -5505,7 +5557,8 @@ static void outline_block_structure(drawing *dr, game_drawstate *ds, sfree(coords); } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int cr = state->cr; int ink = print_mono_colour(dr, 0); @@ -5620,12 +5673,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -5639,7 +5694,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ }; diff --git a/apps/plugins/puzzles/src/sort.c b/apps/plugins/puzzles/src/sort.c index d1897b6fdf..e82f4ec6dc 100644 --- a/apps/plugins/puzzles/src/sort.c +++ b/apps/plugins/puzzles/src/sort.c @@ -9,26 +9,8 @@ #include "puzzles.h" -static void memswap(void *av, void *bv, size_t size) -{ - char t[4096]; - char *a = (char *)av, *b = (char *)bv; - - while (size > 0) { - size_t thissize = size < sizeof(t) ? size : sizeof(t); - - memcpy(t, a, thissize); - memcpy(a, b, thissize); - memcpy(b, t, thissize); - - size -= thissize; - a += thissize; - b += thissize; - } -} - #define PTR(i) ((char *)array + size * (i)) -#define SWAP(i,j) memswap(PTR(i), PTR(j), size) +#define SWAP(i,j) swap_regions(PTR(i), PTR(j), size) #define CMP(i,j) cmp(PTR(i), PTR(j), ctx) #define LCHILD(i) (2*(i)+1) @@ -87,74 +69,3 @@ void arraysort_fn(void *array, size_t nmemb, size_t size, downheap(array, i, size, cmp, ctx, 0); } } - -#ifdef SORT_TEST - -#include -#include - -int testcmp(const void *av, const void *bv, void *ctx) -{ - int a = *(const int *)av, b = *(const int *)bv; - const int *keys = (const int *)ctx; - return keys[a] < keys[b] ? -1 : keys[a] > keys[b] ? +1 : 0; -} - -int resetcmp(const void *av, const void *bv) -{ - int a = *(const int *)av, b = *(const int *)bv; - return a < b ? -1 : a > b ? +1 : 0; -} - -int main(int argc, char **argv) -{ - typedef int Array[3723]; - Array data, keys; - int iteration; - unsigned seed; - - seed = (argc > 1 ? strtoul(argv[1], NULL, 0) : time(NULL)); - printf("Random seed = %u\n", seed); - srand(seed); - - for (iteration = 0; iteration < 10000; iteration++) { - int j; - const char *fail = NULL; - - for (j = 0; j < lenof(data); j++) { - data[j] = j; - keys[j] = rand(); - } - - arraysort(data, lenof(data), testcmp, keys); - - for (j = 1; j < lenof(data); j++) { - if (keys[data[j]] < keys[data[j-1]]) - fail = "output misordered"; - } - if (!fail) { - Array reset; - memcpy(reset, data, sizeof(data)); - qsort(reset, lenof(reset), sizeof(*reset), resetcmp); - for (j = 0; j < lenof(reset); j++) - if (reset[j] != j) - fail = "output not permuted"; - } - - if (fail) { - printf("Failed at iteration %d: %s\n", iteration, fail); - printf("Key values:\n"); - for (j = 0; j < lenof(keys); j++) - printf(" [%2d] %10d\n", j, keys[j]); - printf("Output sorted order:\n"); - for (j = 0; j < lenof(data); j++) - printf(" [%2d] %10d\n", data[j], keys[data[j]]); - return 1; - } - } - - printf("OK\n"); - return 0; -} - -#endif /* SORT_TEST */ diff --git a/apps/plugins/puzzles/src/spectre-internal.h b/apps/plugins/puzzles/src/spectre-internal.h new file mode 100644 index 0000000000..e43d30bfef --- /dev/null +++ b/apps/plugins/puzzles/src/spectre-internal.h @@ -0,0 +1,327 @@ +#include "spectre.h" + +/* + * List macro of the names for hexagon types, which will be reused all + * over the place. + * + * (I have to call the parameter to this list macro something other + * than X, because here, X is also one of the macro arguments!) + */ +#define HEX_LETTERS(Z) Z(G) Z(D) Z(J) Z(L) Z(X) Z(P) Z(S) Z(F) Z(Y) + +typedef enum Hex { + #define HEX_ENUM_DECL(x) HEX_##x, + HEX_LETTERS(HEX_ENUM_DECL) + #undef HEX_ENUM_DECL +} Hex; + +static inline unsigned num_subhexes(Hex h) +{ + return h == HEX_G ? 7 : 8; +} + +static inline unsigned num_spectres(Hex h) +{ + return h == HEX_G ? 2 : 1; +} + +/* + * Data types used in the lookup tables. + */ +struct MapEntry { + bool internal; + unsigned char hi, lo; +}; +struct MapEdge { + unsigned char startindex, len; +}; +struct Possibility { + unsigned char hi, lo; + unsigned long prob; +}; + +/* + * Coordinate system for tracking Spectres and their hexagonal + * metatiles. + * + * SpectreCoords will store the index of a single Spectre within a + * smallest-size hexagon, plus an array of HexCoord each indexing a + * hexagon within the expansion of a larger hexagon. + * + * The last coordinate stored, sc->c[sc->nc-1], will have a hex type + * but no index (represented by index==-1). This means "we haven't + * decided yet what this level of metatile needs to be". If we need to + * refer to this level during the hatctx_step algorithm, we make it up + * at random, based on a table of what metatiles each type can + * possibly be part of, at what index. + */ +typedef struct HexCoord { + int index; /* index within that tile, or -1 if not yet known */ + Hex type; /* type of this hexagon */ +} HexCoord; + +typedef struct SpectreCoords { + int index; /* index of Spectre within the order-0 hexagon */ + HexCoord *c; + size_t nc, csize; + + /* Used by spectre-test to four-colour output tilings, and + * maintained unconditionally because it's easier than making it + * conditional */ + unsigned char hex_colour, prev_hex_colour, incoming_hex_edge; +} SpectreCoords; + +SpectreCoords *spectre_coords_new(void); +void spectre_coords_free(SpectreCoords *hc); +void spectre_coords_make_space(SpectreCoords *hc, size_t size); +SpectreCoords *spectre_coords_copy(SpectreCoords *hc_in); + +/* + * Coordinate system for locating Spectres in the plane. + * + * The 'Point' structure represents a single point by means of an + * integer linear combination of {1, d, d^2, d^3}, where d is the + * complex number exp(i pi/6) representing 1/12 of a turn about the + * origin. + * + * The 'Spectre' structure represents an entire Spectre in a tiling, + * giving both the locations of all of its vertices and its + * combinatorial coordinates. It also contains a linked-list pointer, + * used during breadth-first search to generate all the Spectres in an + * area. + */ +typedef struct Point { + int coeffs[4]; +} Point; +typedef struct Spectre Spectre; +struct Spectre { + Point vertices[14]; + SpectreCoords *sc; + Spectre *next; /* used in breadth-first search */ +}; + +/* Fill in all the coordinates of a Spectre starting from any single edge */ +void spectre_place(Spectre *spec, Point u, Point v, int index_of_u); + +/* Free a Spectre and its contained coordinates */ +void spectre_free(Spectre *spec); + +/* + * A Point is really a complex number, so we can add, subtract and + * multiply them. + */ +static inline Point point_add(Point a, Point b) +{ + Point r; + size_t i; + for (i = 0; i < 4; i++) + r.coeffs[i] = a.coeffs[i] + b.coeffs[i]; + return r; +} +static inline Point point_sub(Point a, Point b) +{ + Point r; + size_t i; + for (i = 0; i < 4; i++) + r.coeffs[i] = a.coeffs[i] - b.coeffs[i]; + return r; +} +static inline Point point_mul_by_d(Point x) +{ + Point r; + /* Multiply by d by using the identity d^4 - d^2 + 1 = 0, so d^4 = d^2+1 */ + r.coeffs[0] = -x.coeffs[3]; + r.coeffs[1] = x.coeffs[0]; + r.coeffs[2] = x.coeffs[1] + x.coeffs[3]; + r.coeffs[3] = x.coeffs[2]; + return r; +} +static inline Point point_mul(Point a, Point b) +{ + size_t i, j; + Point r; + + /* Initialise r to be a, scaled by b's d^3 term */ + for (j = 0; j < 4; j++) + r.coeffs[j] = a.coeffs[j] * b.coeffs[3]; + + /* Now iterate r = d*r + (next coefficient down), by Horner's rule */ + for (i = 3; i-- > 0 ;) { + r = point_mul_by_d(r); + for (j = 0; j < 4; j++) + r.coeffs[j] += a.coeffs[j] * b.coeffs[i]; + } + + return r; +} +static inline bool point_equal(Point a, Point b) +{ + size_t i; + for (i = 0; i < 4; i++) + if (a.coeffs[i] != b.coeffs[i]) + return false; + return true; +} + +/* + * Return the Point corresponding to a rotation of s steps around the + * origin, i.e. a rotation by 30*s degrees or s*pi/6 radians. + */ +static inline Point point_rot(int s) +{ + Point r = {{ 1, 0, 0, 0 }}; + Point dpower = {{ 0, 1, 0, 0 }}; + + /* Reduce to a sensible range */ + s = s % 12; + if (s < 0) + s += 12; + + while (true) { + if (s & 1) + r = point_mul(r, dpower); + s >>= 1; + if (!s) + break; + dpower = point_mul(dpower, dpower); + } + + return r; +} + +/* + * SpectreContext is the shared context of a whole run of the + * algorithm. Its 'prototype' SpectreCoords object represents the + * coordinates of the starting Spectre, and is extended as necessary; + * any other SpectreCoord that needs extending will copy the + * higher-order values from ctx->prototype as needed, so that once + * each choice has been made, it remains consistent. + * + * When we're inventing a random piece of tiling in the first place, + * we append to ctx->prototype by choosing a random (but legal) + * higher-level metatile for the current topmost one to turn out to be + * part of. When we're replaying a generation whose parameters are + * already stored, we don't have a random_state, and we make fixed + * decisions if not enough coordinates were provided, as in the + * corresponding hat.c system. + * + * For a normal (non-testing) caller, spectrectx_generate() is the + * main useful function. It breadth-first searches a whole area to + * generate all the Spectres in it, starting from a (typically + * central) one with the coordinates of ctx->prototype. The callback + * function processes each Spectre as it's generated, and returns true + * or false to indicate whether that Spectre is within the bounds of + * the target area (and therefore the search should continue exploring + * its neighbours). + */ +typedef struct SpectreContext { + random_state *rs; + bool must_free_rs; + Point start_vertices[2]; /* vertices 0,1 of the starting Spectre */ + int orientation; /* orientation to put in SpectrePatchParams */ + SpectreCoords *prototype; +} SpectreContext; + +void spectrectx_init_random(SpectreContext *ctx, random_state *rs); +void spectrectx_init_from_params( + SpectreContext *ctx, const struct SpectrePatchParams *ps); +void spectrectx_cleanup(SpectreContext *ctx); +SpectreCoords *spectrectx_initial_coords(SpectreContext *ctx); +void spectrectx_extend_coords(SpectreContext *ctx, SpectreCoords *hc, + size_t n); +void spectrectx_step(SpectreContext *ctx, SpectreCoords *sc, + unsigned edge, unsigned *outedge); +void spectrectx_generate(SpectreContext *ctx, + bool (*callback)(void *cbctx, const Spectre *spec), + void *cbctx); + +/* For spectre-test to directly generate a tiling of hexes */ +void spectrectx_step_hex(SpectreContext *ctx, SpectreCoords *sc, + size_t depth, unsigned edge, unsigned *outedge); + +/* Subroutines that step around the tiling specified by a SpectreCtx, + * delivering both plane and combinatorial coordinates as they go */ +Spectre *spectre_initial(SpectreContext *ctx); +Spectre *spectre_adjacent(SpectreContext *ctx, const Spectre *src_spec, + unsigned src_edge, unsigned *dst_edge); + +/* For extracting the point coordinates */ +typedef struct Coord { + int c1, cr3; /* coefficients of 1 and sqrt(3) respectively */ +} Coord; + +static inline Coord point_x(Point p) +{ + Coord x = { 2 * p.coeffs[0] + p.coeffs[2], p.coeffs[1] }; + return x; +} + +static inline Coord point_y(Point p) +{ + Coord y = { 2 * p.coeffs[3] + p.coeffs[1], p.coeffs[2] }; + return y; +} + +static inline int coord_sign(Coord x) +{ + if (x.c1 == 0 && x.cr3 == 0) + return 0; + if (x.c1 >= 0 && x.cr3 >= 0) + return +1; + if (x.c1 <= 0 && x.cr3 <= 0) + return -1; + + if (x.c1 * x.c1 > 3 * x.cr3 * x.cr3) + return x.c1 < 0 ? -1 : +1; + else + return x.cr3 < 0 ? -1 : +1; +} + +static inline Coord coord_construct(int c1, int cr3) +{ + Coord c = { c1, cr3 }; + return c; +} + +static inline Coord coord_integer(int c1) +{ + return coord_construct(c1, 0); +} + +static inline Coord coord_add(Coord a, Coord b) +{ + Coord sum; + sum.c1 = a.c1 + b.c1; + sum.cr3 = a.cr3 + b.cr3; + return sum; +} + +static inline Coord coord_sub(Coord a, Coord b) +{ + Coord diff; + diff.c1 = a.c1 - b.c1; + diff.cr3 = a.cr3 - b.cr3; + return diff; +} + +static inline Coord coord_mul(Coord a, Coord b) +{ + Coord prod; + prod.c1 = a.c1 * b.c1 + 3 * a.cr3 * b.cr3; + prod.cr3 = a.c1 * b.cr3 + a.cr3 * b.c1; + return prod; +} + +static inline Coord coord_abs(Coord a) +{ + int sign = coord_sign(a); + Coord abs; + abs.c1 = a.c1 * sign; + abs.cr3 = a.cr3 * sign; + return abs; +} + +static inline int coord_cmp(Coord a, Coord b) +{ + return coord_sign(coord_sub(a, b)); +} diff --git a/apps/plugins/puzzles/src/spectre-tables-auto.h b/apps/plugins/puzzles/src/spectre-tables-auto.h new file mode 100644 index 0000000000..a41c4e1d18 --- /dev/null +++ b/apps/plugins/puzzles/src/spectre-tables-auto.h @@ -0,0 +1,1220 @@ +/* + * Autogenerated transition tables for the Spectre tiling. + * Generated by auxiliary/spectre-gen.c. + */ + +static const struct MapEntry hexmap_G[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 2, 0 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (X) */ + { true, 3, 4 }, /* edge 1 of hex 1 (X) */ + { false, 3, 1 }, /* edge 2 of hex 1 (X) */ + { false, 3, 0 }, /* edge 3 of hex 1 (X) */ + { false, 2, 2 }, /* edge 4 of hex 1 (X) */ + { false, 2, 1 }, /* edge 5 of hex 1 (X) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 2 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (P) */ + { true, 2, 2 }, /* edge 1 of hex 4 (P) */ + { false, 0, 0 }, /* edge 2 of hex 4 (P) */ + { false, 5, 1 }, /* edge 3 of hex 4 (P) */ + { false, 5, 0 }, /* edge 4 of hex 4 (P) */ + { false, 4, 4 }, /* edge 5 of hex 4 (P) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 4, 3 }, /* edge 3 of hex 5 (D) */ + { false, 4, 2 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (J) */ + { true, 5, 5 }, /* edge 1 of hex 6 (J) */ + { false, 4, 1 }, /* edge 2 of hex 6 (J) */ + { false, 4, 0 }, /* edge 3 of hex 6 (J) */ + { false, 3, 4 }, /* edge 4 of hex 6 (J) */ + { false, 3, 3 }, /* edge 5 of hex 6 (J) */ +}; +static const struct MapEdge hexedges_G[] = { + { 0, 2 }, + { 2, 3 }, + { 5, 3 }, + { 8, 5 }, + { 13, 5 }, + { 18, 2 }, +}; +static const struct MapEntry hexin_G[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 1, 5 }, /* subedge 1 of edge 2 */ + { true, 1, 4 }, /* subedge 2 of edge 2 */ + { true, 1, 3 }, /* subedge 0 of edge 3 */ + { true, 1, 2 }, /* subedge 1 of edge 3 */ + { true, 3, 3 }, /* subedge 2 of edge 3 */ + { true, 6, 5 }, /* subedge 3 of edge 3 */ + { true, 6, 4 }, /* subedge 4 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 6, 2 }, /* subedge 1 of edge 4 */ + { true, 5, 4 }, /* subedge 2 of edge 4 */ + { true, 5, 3 }, /* subedge 3 of edge 4 */ + { true, 4, 5 }, /* subedge 4 of edge 4 */ + { true, 4, 4 }, /* subedge 0 of edge 5 */ + { true, 4, 3 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry hexmap_D[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 1, 3 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (P) */ + { true, 3, 4 }, /* edge 1 of hex 1 (P) */ + { false, 3, 0 }, /* edge 2 of hex 1 (P) */ + { false, 2, 1 }, /* edge 3 of hex 1 (P) */ + { false, 2, 0 }, /* edge 4 of hex 1 (P) */ + { false, 1, 4 }, /* edge 5 of hex 1 (P) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 2 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (X) */ + { true, 2, 2 }, /* edge 1 of hex 4 (X) */ + { false, 0, 1 }, /* edge 2 of hex 4 (X) */ + { false, 0, 0 }, /* edge 3 of hex 4 (X) */ + { false, 5, 4 }, /* edge 4 of hex 4 (X) */ + { false, 5, 3 }, /* edge 5 of hex 4 (X) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 2 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (X) */ + { true, 5, 4 }, /* edge 1 of hex 7 (X) */ + { false, 5, 1 }, /* edge 2 of hex 7 (X) */ + { false, 5, 0 }, /* edge 3 of hex 7 (X) */ + { false, 4, 2 }, /* edge 4 of hex 7 (X) */ + { false, 4, 1 }, /* edge 5 of hex 7 (X) */ +}; +static const struct MapEdge hexedges_D[] = { + { 0, 3 }, + { 3, 5 }, + { 8, 2 }, + { 10, 4 }, + { 14, 3 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_D[] = { + { true, 4, 3 }, /* subedge 0 of edge 0 */ + { true, 4, 2 }, /* subedge 1 of edge 0 */ + { true, 2, 1 }, /* subedge 2 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 3 of edge 1 */ + { true, 1, 5 }, /* subedge 4 of edge 1 */ + { true, 1, 4 }, /* subedge 0 of edge 2 */ + { true, 1, 3 }, /* subedge 1 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 0 of edge 5 */ + { true, 7, 2 }, /* subedge 1 of edge 5 */ + { true, 5, 3 }, /* subedge 2 of edge 5 */ + { true, 4, 5 }, /* subedge 3 of edge 5 */ + { true, 4, 4 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry hexmap_J[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 1, 3 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (P) */ + { true, 3, 4 }, /* edge 1 of hex 1 (P) */ + { false, 3, 0 }, /* edge 2 of hex 1 (P) */ + { false, 2, 1 }, /* edge 3 of hex 1 (P) */ + { false, 2, 0 }, /* edge 4 of hex 1 (P) */ + { false, 1, 4 }, /* edge 5 of hex 1 (P) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 2 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 1 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 3, 4 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (P) */ + { true, 5, 4 }, /* edge 1 of hex 7 (P) */ + { false, 5, 0 }, /* edge 2 of hex 7 (P) */ + { false, 4, 1 }, /* edge 3 of hex 7 (P) */ + { false, 4, 0 }, /* edge 4 of hex 7 (P) */ + { false, 3, 5 }, /* edge 5 of hex 7 (P) */ +}; +static const struct MapEdge hexedges_J[] = { + { 0, 2 }, + { 2, 5 }, + { 7, 2 }, + { 9, 6 }, + { 15, 2 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_J[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 3 of edge 1 */ + { true, 1, 5 }, /* subedge 4 of edge 1 */ + { true, 1, 4 }, /* subedge 0 of edge 2 */ + { true, 1, 3 }, /* subedge 1 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 4 of edge 3 */ + { true, 7, 5 }, /* subedge 5 of edge 3 */ + { true, 7, 4 }, /* subedge 0 of edge 4 */ + { true, 7, 3 }, /* subedge 1 of edge 4 */ + { true, 7, 2 }, /* subedge 0 of edge 5 */ + { true, 5, 3 }, /* subedge 1 of edge 5 */ + { true, 4, 5 }, /* subedge 2 of edge 5 */ + { true, 4, 4 }, /* subedge 3 of edge 5 */ + { true, 4, 3 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry hexmap_L[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 1, 3 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (P) */ + { true, 3, 4 }, /* edge 1 of hex 1 (P) */ + { false, 3, 0 }, /* edge 2 of hex 1 (P) */ + { false, 2, 1 }, /* edge 3 of hex 1 (P) */ + { false, 2, 0 }, /* edge 4 of hex 1 (P) */ + { false, 1, 4 }, /* edge 5 of hex 1 (P) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 5 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 2 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (X) */ + { true, 5, 4 }, /* edge 1 of hex 7 (X) */ + { false, 5, 1 }, /* edge 2 of hex 7 (X) */ + { false, 5, 0 }, /* edge 3 of hex 7 (X) */ + { false, 4, 2 }, /* edge 4 of hex 7 (X) */ + { false, 4, 1 }, /* edge 5 of hex 7 (X) */ +}; +static const struct MapEdge hexedges_L[] = { + { 0, 2 }, + { 2, 5 }, + { 7, 2 }, + { 9, 4 }, + { 13, 3 }, + { 16, 6 }, +}; +static const struct MapEntry hexin_L[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 3 of edge 1 */ + { true, 1, 5 }, /* subedge 4 of edge 1 */ + { true, 1, 4 }, /* subedge 0 of edge 2 */ + { true, 1, 3 }, /* subedge 1 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 0 of edge 5 */ + { true, 7, 2 }, /* subedge 1 of edge 5 */ + { true, 5, 3 }, /* subedge 2 of edge 5 */ + { true, 4, 5 }, /* subedge 3 of edge 5 */ + { true, 4, 4 }, /* subedge 4 of edge 5 */ + { true, 4, 3 }, /* subedge 5 of edge 5 */ +}; +static const struct MapEntry hexmap_X[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 2, 0 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (Y) */ + { true, 3, 4 }, /* edge 1 of hex 1 (Y) */ + { false, 3, 0 }, /* edge 2 of hex 1 (Y) */ + { false, 2, 3 }, /* edge 3 of hex 1 (Y) */ + { false, 2, 2 }, /* edge 4 of hex 1 (Y) */ + { false, 2, 1 }, /* edge 5 of hex 1 (Y) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 2 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 1 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 3, 4 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (P) */ + { true, 5, 4 }, /* edge 1 of hex 7 (P) */ + { false, 5, 0 }, /* edge 2 of hex 7 (P) */ + { false, 4, 1 }, /* edge 3 of hex 7 (P) */ + { false, 4, 0 }, /* edge 4 of hex 7 (P) */ + { false, 3, 5 }, /* edge 5 of hex 7 (P) */ +}; +static const struct MapEdge hexedges_X[] = { + { 0, 2 }, + { 2, 3 }, + { 5, 4 }, + { 9, 6 }, + { 15, 2 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_X[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 1, 5 }, /* subedge 1 of edge 2 */ + { true, 1, 4 }, /* subedge 2 of edge 2 */ + { true, 1, 3 }, /* subedge 3 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 4 of edge 3 */ + { true, 7, 5 }, /* subedge 5 of edge 3 */ + { true, 7, 4 }, /* subedge 0 of edge 4 */ + { true, 7, 3 }, /* subedge 1 of edge 4 */ + { true, 7, 2 }, /* subedge 0 of edge 5 */ + { true, 5, 3 }, /* subedge 1 of edge 5 */ + { true, 4, 5 }, /* subedge 2 of edge 5 */ + { true, 4, 4 }, /* subedge 3 of edge 5 */ + { true, 4, 3 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry hexmap_P[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 2, 0 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (Y) */ + { true, 3, 4 }, /* edge 1 of hex 1 (Y) */ + { false, 3, 0 }, /* edge 2 of hex 1 (Y) */ + { false, 2, 3 }, /* edge 3 of hex 1 (Y) */ + { false, 2, 2 }, /* edge 4 of hex 1 (Y) */ + { false, 2, 1 }, /* edge 5 of hex 1 (Y) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 5 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 2 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (X) */ + { true, 5, 4 }, /* edge 1 of hex 7 (X) */ + { false, 5, 1 }, /* edge 2 of hex 7 (X) */ + { false, 5, 0 }, /* edge 3 of hex 7 (X) */ + { false, 4, 2 }, /* edge 4 of hex 7 (X) */ + { false, 4, 1 }, /* edge 5 of hex 7 (X) */ +}; +static const struct MapEdge hexedges_P[] = { + { 0, 2 }, + { 2, 3 }, + { 5, 4 }, + { 9, 4 }, + { 13, 3 }, + { 16, 6 }, +}; +static const struct MapEntry hexin_P[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 1, 5 }, /* subedge 1 of edge 2 */ + { true, 1, 4 }, /* subedge 2 of edge 2 */ + { true, 1, 3 }, /* subedge 3 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 0 of edge 5 */ + { true, 7, 2 }, /* subedge 1 of edge 5 */ + { true, 5, 3 }, /* subedge 2 of edge 5 */ + { true, 4, 5 }, /* subedge 3 of edge 5 */ + { true, 4, 4 }, /* subedge 4 of edge 5 */ + { true, 4, 3 }, /* subedge 5 of edge 5 */ +}; +static const struct MapEntry hexmap_S[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (L) */ + { true, 3, 5 }, /* edge 1 of hex 0 (L) */ + { true, 1, 0 }, /* edge 2 of hex 0 (L) */ + { false, 1, 1 }, /* edge 3 of hex 0 (L) */ + { false, 1, 0 }, /* edge 4 of hex 0 (L) */ + { false, 0, 4 }, /* edge 5 of hex 0 (L) */ + { true, 0, 2 }, /* edge 0 of hex 1 (P) */ + { true, 3, 4 }, /* edge 1 of hex 1 (P) */ + { false, 3, 0 }, /* edge 2 of hex 1 (P) */ + { false, 2, 1 }, /* edge 3 of hex 1 (P) */ + { false, 2, 0 }, /* edge 4 of hex 1 (P) */ + { false, 1, 2 }, /* edge 5 of hex 1 (P) */ + { false, 0, 3 }, /* edge 0 of hex 2 (G) */ + { false, 0, 2 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (X) */ + { true, 2, 2 }, /* edge 1 of hex 4 (X) */ + { false, 0, 1 }, /* edge 2 of hex 4 (X) */ + { false, 0, 0 }, /* edge 3 of hex 4 (X) */ + { false, 5, 4 }, /* edge 4 of hex 4 (X) */ + { false, 5, 3 }, /* edge 5 of hex 4 (X) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 2 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (X) */ + { true, 5, 4 }, /* edge 1 of hex 7 (X) */ + { false, 5, 1 }, /* edge 2 of hex 7 (X) */ + { false, 5, 0 }, /* edge 3 of hex 7 (X) */ + { false, 4, 2 }, /* edge 4 of hex 7 (X) */ + { false, 4, 1 }, /* edge 5 of hex 7 (X) */ +}; +static const struct MapEdge hexedges_S[] = { + { 0, 5 }, + { 5, 3 }, + { 8, 2 }, + { 10, 4 }, + { 14, 3 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_S[] = { + { true, 4, 3 }, /* subedge 0 of edge 0 */ + { true, 4, 2 }, /* subedge 1 of edge 0 */ + { true, 2, 1 }, /* subedge 2 of edge 0 */ + { true, 2, 0 }, /* subedge 3 of edge 0 */ + { true, 0, 5 }, /* subedge 4 of edge 0 */ + { true, 0, 4 }, /* subedge 0 of edge 1 */ + { true, 0, 3 }, /* subedge 1 of edge 1 */ + { true, 1, 5 }, /* subedge 2 of edge 1 */ + { true, 1, 4 }, /* subedge 0 of edge 2 */ + { true, 1, 3 }, /* subedge 1 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 0 of edge 5 */ + { true, 7, 2 }, /* subedge 1 of edge 5 */ + { true, 5, 3 }, /* subedge 2 of edge 5 */ + { true, 4, 5 }, /* subedge 3 of edge 5 */ + { true, 4, 4 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry hexmap_F[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 1, 3 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (P) */ + { true, 3, 4 }, /* edge 1 of hex 1 (P) */ + { false, 3, 0 }, /* edge 2 of hex 1 (P) */ + { false, 2, 1 }, /* edge 3 of hex 1 (P) */ + { false, 2, 0 }, /* edge 4 of hex 1 (P) */ + { false, 1, 4 }, /* edge 5 of hex 1 (P) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 2 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 1 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (Y) */ + { true, 5, 4 }, /* edge 1 of hex 7 (Y) */ + { false, 5, 0 }, /* edge 2 of hex 7 (Y) */ + { false, 4, 3 }, /* edge 3 of hex 7 (Y) */ + { false, 4, 2 }, /* edge 4 of hex 7 (Y) */ + { false, 4, 1 }, /* edge 5 of hex 7 (Y) */ +}; +static const struct MapEdge hexedges_F[] = { + { 0, 2 }, + { 2, 5 }, + { 7, 2 }, + { 9, 4 }, + { 13, 4 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_F[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 3 of edge 1 */ + { true, 1, 5 }, /* subedge 4 of edge 1 */ + { true, 1, 4 }, /* subedge 0 of edge 2 */ + { true, 1, 3 }, /* subedge 1 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 3 of edge 4 */ + { true, 7, 2 }, /* subedge 0 of edge 5 */ + { true, 5, 3 }, /* subedge 1 of edge 5 */ + { true, 4, 5 }, /* subedge 2 of edge 5 */ + { true, 4, 4 }, /* subedge 3 of edge 5 */ + { true, 4, 3 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry hexmap_Y[] = { + { true, 2, 5 }, /* edge 0 of hex 0 (F) */ + { true, 3, 5 }, /* edge 1 of hex 0 (F) */ + { true, 1, 0 }, /* edge 2 of hex 0 (F) */ + { false, 2, 0 }, /* edge 3 of hex 0 (F) */ + { false, 1, 2 }, /* edge 4 of hex 0 (F) */ + { false, 1, 1 }, /* edge 5 of hex 0 (F) */ + { true, 0, 2 }, /* edge 0 of hex 1 (Y) */ + { true, 3, 4 }, /* edge 1 of hex 1 (Y) */ + { false, 3, 0 }, /* edge 2 of hex 1 (Y) */ + { false, 2, 3 }, /* edge 3 of hex 1 (Y) */ + { false, 2, 2 }, /* edge 4 of hex 1 (Y) */ + { false, 2, 1 }, /* edge 5 of hex 1 (Y) */ + { false, 1, 0 }, /* edge 0 of hex 2 (G) */ + { false, 0, 1 }, /* edge 1 of hex 2 (G) */ + { true, 4, 1 }, /* edge 2 of hex 2 (G) */ + { true, 5, 1 }, /* edge 3 of hex 2 (G) */ + { true, 3, 0 }, /* edge 4 of hex 2 (G) */ + { true, 0, 0 }, /* edge 5 of hex 2 (G) */ + { true, 2, 4 }, /* edge 0 of hex 3 (S) */ + { true, 5, 0 }, /* edge 1 of hex 3 (S) */ + { true, 6, 0 }, /* edge 2 of hex 3 (S) */ + { false, 3, 1 }, /* edge 3 of hex 3 (S) */ + { true, 1, 1 }, /* edge 4 of hex 3 (S) */ + { true, 0, 1 }, /* edge 5 of hex 3 (S) */ + { true, 5, 2 }, /* edge 0 of hex 4 (Y) */ + { true, 2, 2 }, /* edge 1 of hex 4 (Y) */ + { false, 0, 0 }, /* edge 2 of hex 4 (Y) */ + { false, 5, 4 }, /* edge 3 of hex 4 (Y) */ + { false, 5, 3 }, /* edge 4 of hex 4 (Y) */ + { false, 5, 2 }, /* edge 5 of hex 4 (Y) */ + { true, 3, 1 }, /* edge 0 of hex 5 (D) */ + { true, 2, 3 }, /* edge 1 of hex 5 (D) */ + { true, 4, 0 }, /* edge 2 of hex 5 (D) */ + { false, 5, 1 }, /* edge 3 of hex 5 (D) */ + { true, 7, 1 }, /* edge 4 of hex 5 (D) */ + { true, 6, 1 }, /* edge 5 of hex 5 (D) */ + { true, 3, 2 }, /* edge 0 of hex 6 (F) */ + { true, 5, 5 }, /* edge 1 of hex 6 (F) */ + { true, 7, 0 }, /* edge 2 of hex 6 (F) */ + { false, 4, 0 }, /* edge 3 of hex 6 (F) */ + { false, 3, 3 }, /* edge 4 of hex 6 (F) */ + { false, 3, 2 }, /* edge 5 of hex 6 (F) */ + { true, 6, 2 }, /* edge 0 of hex 7 (Y) */ + { true, 5, 4 }, /* edge 1 of hex 7 (Y) */ + { false, 5, 0 }, /* edge 2 of hex 7 (Y) */ + { false, 4, 3 }, /* edge 3 of hex 7 (Y) */ + { false, 4, 2 }, /* edge 4 of hex 7 (Y) */ + { false, 4, 1 }, /* edge 5 of hex 7 (Y) */ +}; +static const struct MapEdge hexedges_Y[] = { + { 0, 2 }, + { 2, 3 }, + { 5, 4 }, + { 9, 4 }, + { 13, 4 }, + { 17, 5 }, +}; +static const struct MapEntry hexin_Y[] = { + { true, 4, 2 }, /* subedge 0 of edge 0 */ + { true, 2, 1 }, /* subedge 1 of edge 0 */ + { true, 2, 0 }, /* subedge 0 of edge 1 */ + { true, 0, 5 }, /* subedge 1 of edge 1 */ + { true, 0, 4 }, /* subedge 2 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 1, 5 }, /* subedge 1 of edge 2 */ + { true, 1, 4 }, /* subedge 2 of edge 2 */ + { true, 1, 3 }, /* subedge 3 of edge 2 */ + { true, 1, 2 }, /* subedge 0 of edge 3 */ + { true, 3, 3 }, /* subedge 1 of edge 3 */ + { true, 6, 5 }, /* subedge 2 of edge 3 */ + { true, 6, 4 }, /* subedge 3 of edge 3 */ + { true, 6, 3 }, /* subedge 0 of edge 4 */ + { true, 7, 5 }, /* subedge 1 of edge 4 */ + { true, 7, 4 }, /* subedge 2 of edge 4 */ + { true, 7, 3 }, /* subedge 3 of edge 4 */ + { true, 7, 2 }, /* subedge 0 of edge 5 */ + { true, 5, 3 }, /* subedge 1 of edge 5 */ + { true, 4, 5 }, /* subedge 2 of edge 5 */ + { true, 4, 4 }, /* subedge 3 of edge 5 */ + { true, 4, 3 }, /* subedge 4 of edge 5 */ +}; +static const struct MapEntry specmap_G[] = { + { false, 2, 2 }, /* edge 0 of Spectre 0 */ + { false, 2, 1 }, /* edge 1 of Spectre 0 */ + { false, 2, 0 }, /* edge 2 of Spectre 0 */ + { false, 1, 2 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 2 }, /* edge 9 of Spectre 0 */ + { true, 1, 7 }, /* edge 10 of Spectre 0 */ + { true, 1, 6 }, /* edge 11 of Spectre 0 */ + { true, 1, 5 }, /* edge 12 of Spectre 0 */ + { true, 1, 4 }, /* edge 13 of Spectre 0 */ + { false, 4, 1 }, /* edge 0 of Spectre 1 */ + { false, 4, 0 }, /* edge 1 of Spectre 1 */ + { false, 3, 1 }, /* edge 2 of Spectre 1 */ + { false, 3, 0 }, /* edge 3 of Spectre 1 */ + { true, 0, 13 }, /* edge 4 of Spectre 1 */ + { true, 0, 12 }, /* edge 5 of Spectre 1 */ + { true, 0, 11 }, /* edge 6 of Spectre 1 */ + { true, 0, 10 }, /* edge 7 of Spectre 1 */ + { false, 5, 1 }, /* edge 8 of Spectre 1 */ + { false, 5, 0 }, /* edge 9 of Spectre 1 */ + { false, 4, 5 }, /* edge 10 of Spectre 1 */ + { false, 4, 4 }, /* edge 11 of Spectre 1 */ + { false, 4, 3 }, /* edge 12 of Spectre 1 */ + { false, 4, 2 }, /* edge 13 of Spectre 1 */ +}; +static const struct MapEdge specedges_G[] = { + { 0, 3 }, + { 3, 3 }, + { 6, 3 }, + { 9, 2 }, + { 11, 6 }, + { 17, 3 }, +}; +static const struct MapEntry specin_G[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 2 of edge 1 */ + { true, 0, 2 }, /* subedge 0 of edge 2 */ + { true, 0, 1 }, /* subedge 1 of edge 2 */ + { true, 0, 0 }, /* subedge 2 of edge 2 */ + { true, 1, 3 }, /* subedge 0 of edge 3 */ + { true, 1, 2 }, /* subedge 1 of edge 3 */ + { true, 1, 1 }, /* subedge 0 of edge 4 */ + { true, 1, 0 }, /* subedge 1 of edge 4 */ + { true, 1, 13 }, /* subedge 2 of edge 4 */ + { true, 1, 12 }, /* subedge 3 of edge 4 */ + { true, 1, 11 }, /* subedge 4 of edge 4 */ + { true, 1, 10 }, /* subedge 5 of edge 4 */ + { true, 1, 9 }, /* subedge 0 of edge 5 */ + { true, 1, 8 }, /* subedge 1 of edge 5 */ + { true, 0, 9 }, /* subedge 2 of edge 5 */ +}; +static const struct MapEntry specmap_D[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 2 }, /* edge 1 of Spectre 0 */ + { false, 2, 1 }, /* edge 2 of Spectre 0 */ + { false, 2, 0 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 1 }, /* edge 6 of Spectre 0 */ + { false, 0, 0 }, /* edge 7 of Spectre 0 */ + { false, 5, 1 }, /* edge 8 of Spectre 0 */ + { false, 5, 0 }, /* edge 9 of Spectre 0 */ + { false, 4, 2 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_D[] = { + { 0, 2 }, + { 2, 2 }, + { 4, 3 }, + { 7, 2 }, + { 9, 3 }, + { 12, 2 }, +}; +static const struct MapEntry specin_D[] = { + { true, 0, 7 }, /* subedge 0 of edge 0 */ + { true, 0, 6 }, /* subedge 1 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 0, 2 }, /* subedge 1 of edge 2 */ + { true, 0, 1 }, /* subedge 2 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 2 of edge 4 */ + { true, 0, 9 }, /* subedge 0 of edge 5 */ + { true, 0, 8 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry specmap_J[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 2 }, /* edge 1 of Spectre 0 */ + { false, 2, 1 }, /* edge 2 of Spectre 0 */ + { false, 2, 0 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 1 }, /* edge 9 of Spectre 0 */ + { false, 5, 0 }, /* edge 10 of Spectre 0 */ + { false, 4, 2 }, /* edge 11 of Spectre 0 */ + { false, 4, 1 }, /* edge 12 of Spectre 0 */ + { false, 4, 0 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_J[] = { + { 0, 3 }, + { 3, 2 }, + { 5, 3 }, + { 8, 1 }, + { 9, 3 }, + { 12, 2 }, +}; +static const struct MapEntry specin_J[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 0, 2 }, /* subedge 1 of edge 2 */ + { true, 0, 1 }, /* subedge 2 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 0 of edge 4 */ + { true, 0, 12 }, /* subedge 1 of edge 4 */ + { true, 0, 11 }, /* subedge 2 of edge 4 */ + { true, 0, 10 }, /* subedge 0 of edge 5 */ + { true, 0, 9 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry specmap_L[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 2 }, /* edge 1 of Spectre 0 */ + { false, 2, 1 }, /* edge 2 of Spectre 0 */ + { false, 2, 0 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 0 }, /* edge 9 of Spectre 0 */ + { false, 4, 2 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_L[] = { + { 0, 3 }, + { 3, 2 }, + { 5, 3 }, + { 8, 2 }, + { 10, 3 }, + { 13, 1 }, +}; +static const struct MapEntry specin_L[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 0, 2 }, /* subedge 1 of edge 2 */ + { true, 0, 1 }, /* subedge 2 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 2 of edge 4 */ + { true, 0, 9 }, /* subedge 0 of edge 5 */ +}; +static const struct MapEntry specmap_X[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 1 }, /* edge 1 of Spectre 0 */ + { false, 2, 0 }, /* edge 2 of Spectre 0 */ + { false, 1, 2 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 1 }, /* edge 9 of Spectre 0 */ + { false, 5, 0 }, /* edge 10 of Spectre 0 */ + { false, 4, 2 }, /* edge 11 of Spectre 0 */ + { false, 4, 1 }, /* edge 12 of Spectre 0 */ + { false, 4, 0 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_X[] = { + { 0, 3 }, + { 3, 3 }, + { 6, 2 }, + { 8, 1 }, + { 9, 3 }, + { 12, 2 }, +}; +static const struct MapEntry specin_X[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 2 of edge 1 */ + { true, 0, 2 }, /* subedge 0 of edge 2 */ + { true, 0, 1 }, /* subedge 1 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 0 of edge 4 */ + { true, 0, 12 }, /* subedge 1 of edge 4 */ + { true, 0, 11 }, /* subedge 2 of edge 4 */ + { true, 0, 10 }, /* subedge 0 of edge 5 */ + { true, 0, 9 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry specmap_P[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 1 }, /* edge 1 of Spectre 0 */ + { false, 2, 0 }, /* edge 2 of Spectre 0 */ + { false, 1, 2 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 0 }, /* edge 9 of Spectre 0 */ + { false, 4, 2 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_P[] = { + { 0, 3 }, + { 3, 3 }, + { 6, 2 }, + { 8, 2 }, + { 10, 3 }, + { 13, 1 }, +}; +static const struct MapEntry specin_P[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 2 of edge 1 */ + { true, 0, 2 }, /* subedge 0 of edge 2 */ + { true, 0, 1 }, /* subedge 1 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 2 of edge 4 */ + { true, 0, 9 }, /* subedge 0 of edge 5 */ +}; +static const struct MapEntry specmap_S[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 2 }, /* edge 1 of Spectre 0 */ + { false, 2, 1 }, /* edge 2 of Spectre 0 */ + { false, 2, 0 }, /* edge 3 of Spectre 0 */ + { false, 0, 3 }, /* edge 4 of Spectre 0 */ + { false, 0, 2 }, /* edge 5 of Spectre 0 */ + { false, 0, 1 }, /* edge 6 of Spectre 0 */ + { false, 0, 0 }, /* edge 7 of Spectre 0 */ + { false, 5, 1 }, /* edge 8 of Spectre 0 */ + { false, 5, 0 }, /* edge 9 of Spectre 0 */ + { false, 4, 2 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_S[] = { + { 0, 6 }, + { 6, 2 }, + { 8, 3 }, + { 11, 2 }, + { 13, 3 }, + { 16, 2 }, +}; +static const struct MapEntry specin_S[] = { + { true, 0, 7 }, /* subedge 0 of edge 0 */ + { true, 0, 6 }, /* subedge 1 of edge 0 */ + { true, 0, 5 }, /* subedge 2 of edge 0 */ + { true, 0, 4 }, /* subedge 3 of edge 0 */ + { false, 1, 1 }, /* subedge 4 of edge 0 */ + { false, 1, 0 }, /* subedge 5 of edge 0 */ + { false, 0, 5 }, /* subedge 0 of edge 1 */ + { false, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 0, 2 }, /* subedge 1 of edge 2 */ + { true, 0, 1 }, /* subedge 2 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 2 of edge 4 */ + { true, 0, 9 }, /* subedge 0 of edge 5 */ + { true, 0, 8 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry specmap_F[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 2 }, /* edge 1 of Spectre 0 */ + { false, 2, 1 }, /* edge 2 of Spectre 0 */ + { false, 2, 0 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 1 }, /* edge 9 of Spectre 0 */ + { false, 5, 0 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_F[] = { + { 0, 3 }, + { 3, 2 }, + { 5, 3 }, + { 8, 2 }, + { 10, 2 }, + { 12, 2 }, +}; +static const struct MapEntry specin_F[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 0 of edge 2 */ + { true, 0, 2 }, /* subedge 1 of edge 2 */ + { true, 0, 1 }, /* subedge 2 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 0 of edge 5 */ + { true, 0, 9 }, /* subedge 1 of edge 5 */ +}; +static const struct MapEntry specmap_Y[] = { + { false, 3, 0 }, /* edge 0 of Spectre 0 */ + { false, 2, 1 }, /* edge 1 of Spectre 0 */ + { false, 2, 0 }, /* edge 2 of Spectre 0 */ + { false, 1, 2 }, /* edge 3 of Spectre 0 */ + { false, 1, 1 }, /* edge 4 of Spectre 0 */ + { false, 1, 0 }, /* edge 5 of Spectre 0 */ + { false, 0, 2 }, /* edge 6 of Spectre 0 */ + { false, 0, 1 }, /* edge 7 of Spectre 0 */ + { false, 0, 0 }, /* edge 8 of Spectre 0 */ + { false, 5, 1 }, /* edge 9 of Spectre 0 */ + { false, 5, 0 }, /* edge 10 of Spectre 0 */ + { false, 4, 1 }, /* edge 11 of Spectre 0 */ + { false, 4, 0 }, /* edge 12 of Spectre 0 */ + { false, 3, 1 }, /* edge 13 of Spectre 0 */ +}; +static const struct MapEdge specedges_Y[] = { + { 0, 3 }, + { 3, 3 }, + { 6, 2 }, + { 8, 2 }, + { 10, 2 }, + { 12, 2 }, +}; +static const struct MapEntry specin_Y[] = { + { true, 0, 8 }, /* subedge 0 of edge 0 */ + { true, 0, 7 }, /* subedge 1 of edge 0 */ + { true, 0, 6 }, /* subedge 2 of edge 0 */ + { true, 0, 5 }, /* subedge 0 of edge 1 */ + { true, 0, 4 }, /* subedge 1 of edge 1 */ + { true, 0, 3 }, /* subedge 2 of edge 1 */ + { true, 0, 2 }, /* subedge 0 of edge 2 */ + { true, 0, 1 }, /* subedge 1 of edge 2 */ + { true, 0, 0 }, /* subedge 0 of edge 3 */ + { true, 0, 13 }, /* subedge 1 of edge 3 */ + { true, 0, 12 }, /* subedge 0 of edge 4 */ + { true, 0, 11 }, /* subedge 1 of edge 4 */ + { true, 0, 10 }, /* subedge 0 of edge 5 */ + { true, 0, 9 }, /* subedge 1 of edge 5 */ +}; +static const struct Possibility poss_G[] = { + { HEX_G, 2, PROB_G }, + { HEX_D, 2, PROB_D }, + { HEX_J, 2, PROB_J }, + { HEX_L, 2, PROB_L }, + { HEX_X, 2, PROB_X }, + { HEX_P, 2, PROB_P }, + { HEX_S, 2, PROB_S }, + { HEX_F, 2, PROB_F }, + { HEX_Y, 2, PROB_Y }, +}; +static const struct Possibility poss_D[] = { + { HEX_G, 5, PROB_G }, + { HEX_D, 5, PROB_D }, + { HEX_J, 5, PROB_J }, + { HEX_L, 5, PROB_L }, + { HEX_X, 5, PROB_X }, + { HEX_P, 5, PROB_P }, + { HEX_S, 5, PROB_S }, + { HEX_F, 5, PROB_F }, + { HEX_Y, 5, PROB_Y }, +}; +static const struct Possibility poss_J[] = { + { HEX_G, 6, PROB_G }, +}; +static const struct Possibility poss_L[] = { + { HEX_S, 0, PROB_S }, +}; +static const struct Possibility poss_X[] = { + { HEX_G, 1, PROB_G }, + { HEX_D, 4, PROB_D }, + { HEX_D, 7, PROB_D }, + { HEX_L, 7, PROB_L }, + { HEX_P, 7, PROB_P }, + { HEX_S, 4, PROB_S }, + { HEX_S, 7, PROB_S }, +}; +static const struct Possibility poss_P[] = { + { HEX_G, 4, PROB_G }, + { HEX_D, 1, PROB_D }, + { HEX_J, 1, PROB_J }, + { HEX_J, 7, PROB_J }, + { HEX_L, 1, PROB_L }, + { HEX_X, 7, PROB_X }, + { HEX_S, 1, PROB_S }, + { HEX_F, 1, PROB_F }, +}; +static const struct Possibility poss_S[] = { + { HEX_G, 3, PROB_G }, + { HEX_D, 3, PROB_D }, + { HEX_J, 3, PROB_J }, + { HEX_L, 3, PROB_L }, + { HEX_X, 3, PROB_X }, + { HEX_P, 3, PROB_P }, + { HEX_S, 3, PROB_S }, + { HEX_F, 3, PROB_F }, + { HEX_Y, 3, PROB_Y }, +}; +static const struct Possibility poss_F[] = { + { HEX_G, 0, PROB_G }, + { HEX_D, 0, PROB_D }, + { HEX_D, 6, PROB_D }, + { HEX_J, 0, PROB_J }, + { HEX_J, 6, PROB_J }, + { HEX_L, 0, PROB_L }, + { HEX_L, 6, PROB_L }, + { HEX_X, 0, PROB_X }, + { HEX_X, 6, PROB_X }, + { HEX_P, 0, PROB_P }, + { HEX_P, 6, PROB_P }, + { HEX_S, 6, PROB_S }, + { HEX_F, 0, PROB_F }, + { HEX_F, 6, PROB_F }, + { HEX_Y, 0, PROB_Y }, + { HEX_Y, 6, PROB_Y }, +}; +static const struct Possibility poss_Y[] = { + { HEX_J, 4, PROB_J }, + { HEX_L, 4, PROB_L }, + { HEX_X, 1, PROB_X }, + { HEX_X, 4, PROB_X }, + { HEX_P, 1, PROB_P }, + { HEX_P, 4, PROB_P }, + { HEX_F, 4, PROB_F }, + { HEX_F, 7, PROB_F }, + { HEX_Y, 1, PROB_Y }, + { HEX_Y, 4, PROB_Y }, + { HEX_Y, 7, PROB_Y }, +}; +static const struct Possibility poss_spectre[] = { + { HEX_G, 0, PROB_G }, + { HEX_G, 1, PROB_G }, + { HEX_D, 0, PROB_D }, + { HEX_J, 0, PROB_J }, + { HEX_L, 0, PROB_L }, + { HEX_X, 0, PROB_X }, + { HEX_P, 0, PROB_P }, + { HEX_S, 0, PROB_S }, + { HEX_F, 0, PROB_F }, + { HEX_Y, 0, PROB_Y }, +}; diff --git a/apps/plugins/puzzles/src/spectre-tables-manual.h b/apps/plugins/puzzles/src/spectre-tables-manual.h new file mode 100644 index 0000000000..d57e6597dd --- /dev/null +++ b/apps/plugins/puzzles/src/spectre-tables-manual.h @@ -0,0 +1,160 @@ +/* + * Handwritten data tables for the Spectre tiling. + * + * This file is used by both the final tiling generator in spectre.c, + * and by spectre-gen.c which auto-generates further tables to go with + * these. + */ + +/* + * We generate the Spectre tiling based on the substitution system of + * 9 types of marked hexagon shown in the paper. + * + * The substitution expands each hexagon into 8 others, except for the + * G hex which expands to only seven. The layout, numbered with the + * indices we use in the arrays here, is as follows: + * + * 0 1 + * 2 3 + * 4 5 6 + * 7 + * + * That is: the hexes are oriented with a pair of vertical edges. + * Hexes 0 and 1 are horizontally adjacent; 2 and 3 are adjacent on + * the next row, with 3 nestling between 0 and 1; 4,5,6 are on the + * third row with 5 between 2 and 3; and 7 is by itself on a fourth + * row, between 5 and 6. In the expansion of the G hex, #7 is the + * missing one, so its indices are still consecutive from 0. + * + * These arrays list the type of each child hex. The hexes also have + * orientations, but those aren't listed here, because only + * spectre-gen needs to know them - by the time it's finished + * autogenerating transition tables, the orientations are baked into + * those and don't need to be consulted separately. + */ + +static const Hex subhexes_G[] = { + HEX_F, + HEX_X, + HEX_G, + HEX_S, + HEX_P, + HEX_D, + HEX_J, + /* hex #7 is not present for this tile */ +}; +static const Hex subhexes_D[] = { + HEX_F, + HEX_P, + HEX_G, + HEX_S, + HEX_X, + HEX_D, + HEX_F, + HEX_X, +}; +static const Hex subhexes_J[] = { + HEX_F, + HEX_P, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_P, +}; +static const Hex subhexes_L[] = { + HEX_F, + HEX_P, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_X, +}; +static const Hex subhexes_X[] = { + HEX_F, + HEX_Y, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_P, +}; +static const Hex subhexes_P[] = { + HEX_F, + HEX_Y, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_X, +}; +static const Hex subhexes_S[] = { + HEX_L, + HEX_P, + HEX_G, + HEX_S, + HEX_X, + HEX_D, + HEX_F, + HEX_X, +}; +static const Hex subhexes_F[] = { + HEX_F, + HEX_P, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_Y, +}; +static const Hex subhexes_Y[] = { + HEX_F, + HEX_Y, + HEX_G, + HEX_S, + HEX_Y, + HEX_D, + HEX_F, + HEX_Y, +}; + +/* + * Shape of the Spectre itself. + * + * Vertex 0 is taken to be at the top of the Spectre's "head"; vertex + * 1 is the adjacent vertex, in the direction of the shorter edge of + * its "cloak". + * + * This array indicates how far to turn at each vertex, in 1/12 turns. + * All edges are the same length (counting the double-edge as two + * edges, which we do). + */ +static const int spectre_angles[14] = { + -3, -2, 3, -2, -3, 2, -3, 2, -3, -2, 0, -2, 3, -2, +}; + +/* + * The relative probabilities of the nine hex types, in the limit, as + * the expansion process is iterated more and more times. Used to + * choose the initial hex coordinates as if the segment of tiling came + * from the limiting distribution across the whole plane. + * + * This is obtained by finding the matrix that says how many hexes of + * each type are expanded from each starting hex, and taking the + * eigenvector that goes with its limiting eigenvalue. + */ +#define PROB_G 10000000 /* 1 */ +#define PROB_D 10000000 /* 1 */ +#define PROB_J 1270167 /* 4 - sqrt(15) */ +#define PROB_L 1270167 /* 4 - sqrt(15) */ +#define PROB_X 7459667 /* 2 sqrt(15) - 7 */ +#define PROB_P 7459667 /* 2 sqrt(15) - 7 */ +#define PROB_S 10000000 /* 1 */ +#define PROB_F 17459667 /* 2 sqrt(15) - 6 */ +#define PROB_Y 13810500 /* 13 - 3 sqrt(15) */ diff --git a/apps/plugins/puzzles/src/spectre.c b/apps/plugins/puzzles/src/spectre.c new file mode 100644 index 0000000000..ba72304ff2 --- /dev/null +++ b/apps/plugins/puzzles/src/spectre.c @@ -0,0 +1,599 @@ +/* + * Code to generate patches of the aperiodic 'spectre' tiling + * discovered in 2023. + * + * Resources about the tiling from its discoverers: + * https://cs.uwaterloo.ca/~csk/spectre/ + * https://arxiv.org/abs/2305.17743 + * + * Writeup of the generation algorithm: + * https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-spectre/ + */ + +#include +#include + +#include "puzzles.h" +#include "tree234.h" + +#include "spectre-internal.h" + +#include "spectre-tables-manual.h" +#include "spectre-tables-auto.h" + +static const char *const letters = + #define STRINGIFY(x) #x + HEX_LETTERS(STRINGIFY) + #undef STRINGIFY + ; + +bool spectre_valid_hex_letter(char letter) +{ + return strchr(letters, letter) != NULL; +} + +static Hex hex_from_letter(char letter) +{ + char buf[2]; + buf[0] = letter; + buf[1] = '\0'; + return strcspn(letters, buf); +} + +static Hex hex_to_letter(unsigned char letter) +{ + return letters[letter]; +} + +struct HexData { + const struct MapEntry *hexmap, *hexin, *specmap, *specin; + const struct MapEdge *hexedges, *specedges; + const Hex *subhexes; + const struct Possibility *poss; + size_t nposs; +}; + +static const struct HexData hexdata[] = { + #define HEXDATA_ENTRY(x) { hexmap_##x, hexin_##x, specmap_##x, \ + specin_##x, hexedges_##x, specedges_##x, subhexes_##x, \ + poss_##x, lenof(poss_##x) }, + HEX_LETTERS(HEXDATA_ENTRY) + #undef HEXDATA_ENTRY +}; + +static const struct Possibility *choose_poss( + random_state *rs, const struct Possibility *poss, size_t nposs) +{ + /* + * If we needed to do this _efficiently_, we'd rewrite all those + * tables above as cumulative frequency tables and use binary + * search. But this happens about log n times in a grid of area n, + * so it hardly matters, and it's easier to keep the tables + * legible. + */ + unsigned long limit = 0, value; + size_t i; + + for (i = 0; i < nposs; i++) + limit += poss[i].prob; + + value = random_upto(rs, limit); + + for (i = 0; i+1 < nposs; i++) { + if (value < poss[i].prob) + return &poss[i]; + value -= poss[i].prob; + } + + assert(i == nposs - 1); + assert(value < poss[i].prob); + return &poss[i]; +} + +SpectreCoords *spectre_coords_new(void) +{ + SpectreCoords *sc = snew(SpectreCoords); + sc->nc = sc->csize = 0; + sc->c = NULL; + return sc; +} + +void spectre_coords_free(SpectreCoords *sc) +{ + if (sc) { + sfree(sc->c); + sfree(sc); + } +} + +void spectre_coords_make_space(SpectreCoords *sc, size_t size) +{ + if (sc->csize < size) { + sc->csize = sc->csize * 5 / 4 + 16; + if (sc->csize < size) + sc->csize = size; + sc->c = sresize(sc->c, sc->csize, HexCoord); + } +} + +SpectreCoords *spectre_coords_copy(SpectreCoords *sc_in) +{ + SpectreCoords *sc_out = spectre_coords_new(); + spectre_coords_make_space(sc_out, sc_in->nc); + memcpy(sc_out->c, sc_in->c, sc_in->nc * sizeof(*sc_out->c)); + sc_out->nc = sc_in->nc; + sc_out->index = sc_in->index; + sc_out->hex_colour = sc_in->hex_colour; + sc_out->prev_hex_colour = sc_in->prev_hex_colour; + sc_out->incoming_hex_edge = sc_in->incoming_hex_edge; + return sc_out; +} + +void spectre_place(Spectre *spec, Point u, Point v, int index_of_u) +{ + size_t i; + Point disp; + + /* Vector from u to v */ + disp = point_sub(v, u); + + for (i = 0; i < 14; i++) { + spec->vertices[(i + index_of_u) % 14] = u; + u = point_add(u, disp); + disp = point_mul(disp, point_rot( + spectre_angles[(i + 1 + index_of_u) % 14])); + } +} + +Spectre *spectre_initial(SpectreContext *ctx) +{ + Spectre *spec = snew(Spectre); + spectre_place(spec, ctx->start_vertices[0], ctx->start_vertices[1], 0); + spec->sc = spectre_coords_copy(ctx->prototype); + return spec; +} + +Spectre *spectre_adjacent(SpectreContext *ctx, const Spectre *src_spec, + unsigned src_edge, unsigned *dst_edge_out) +{ + unsigned dst_edge; + Spectre *dst_spec = snew(Spectre); + dst_spec->sc = spectre_coords_copy(src_spec->sc); + spectrectx_step(ctx, dst_spec->sc, src_edge, &dst_edge); + spectre_place(dst_spec, src_spec->vertices[(src_edge+1) % 14], + src_spec->vertices[src_edge], dst_edge); + if (dst_edge_out) + *dst_edge_out = dst_edge; + return dst_spec; +} + +static int spectre_cmp(void *av, void *bv) +{ + Spectre *a = (Spectre *)av, *b = (Spectre *)bv; + size_t i, j; + + /* We should only ever need to compare the first two vertices of + * any Spectre, because those force the rest */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + int ac = a->vertices[i].coeffs[j], bc = b->vertices[i].coeffs[j]; + if (ac < bc) + return -1; + if (ac > bc) + return +1; + } + } + + return 0; +} + +void spectre_free(Spectre *spec) +{ + spectre_coords_free(spec->sc); + sfree(spec); +} + +static void spectrectx_start_vertices(SpectreContext *ctx, int orientation) +{ + Point minus_sqrt3 = point_add(point_rot(5), point_rot(-5)); + Point basicedge = point_mul(point_add(point_rot(0), point_rot(-3)), + point_rot(orientation)); + Point diagonal = point_add(basicedge, point_mul(basicedge, point_rot(-3))); + ctx->start_vertices[0] = point_mul(diagonal, minus_sqrt3); + ctx->start_vertices[1] = point_add(ctx->start_vertices[0], basicedge); + ctx->orientation = orientation; +} + +void spectrectx_init_random(SpectreContext *ctx, random_state *rs) +{ + const struct Possibility *poss; + + ctx->rs = rs; + ctx->must_free_rs = false; + ctx->prototype = spectre_coords_new(); + spectre_coords_make_space(ctx->prototype, 1); + poss = choose_poss(rs, poss_spectre, lenof(poss_spectre)); + ctx->prototype->index = poss->lo; + ctx->prototype->c[0].type = poss->hi; + ctx->prototype->c[0].index = -1; + ctx->prototype->nc = 1; + + /* + * Choose a random orientation for the starting Spectre. + * + * The obvious thing is to choose the orientation out of all 12 + * possibilities. But we do it a more complicated way. + * + * The Spectres in a tiling can be partitioned into two + * equivalence classes under the relation 'orientation differs by + * a multiple of 1/6 turn'. One class is much more common than the + * other class: the 'odd'-orientation Spectres occur rarely (very + * like the rare reflected hats in the hats tiling). + * + * I think it's nicer to arrange that there's a consistent + * orientation for the _common_ class of Spectres, so that there + * will always be plenty of them in the 'canonical' orientation + * with the head upwards. So if the starting Spectre is in the + * even class, we pick an even orientation for it, and if it's in + * the odd class, we pick an odd orientation. + * + * An odd-class Spectre is easy to identify from SpectreCoords. + * They're precisely the ones expanded from a G hex with index 1, + * which means they're the ones that have index 1 _at all_. + */ + spectrectx_start_vertices(ctx, random_upto(rs, 6) * 2 + + ctx->prototype->index); + + /* Initialiise the colouring fields deterministically but unhelpfully. + * spectre-test will set these up properly if it wants to */ + ctx->prototype->hex_colour = 0; + ctx->prototype->prev_hex_colour = 0; + ctx->prototype->incoming_hex_edge = 0; +} + +void spectrectx_init_from_params( + SpectreContext *ctx, const struct SpectrePatchParams *ps) +{ + size_t i; + + ctx->rs = NULL; + ctx->must_free_rs = false; + ctx->prototype = spectre_coords_new(); + spectre_coords_make_space(ctx->prototype, ps->ncoords); + + ctx->prototype->index = ps->coords[0]; + for (i = 1; i < ps->ncoords; i++) + ctx->prototype->c[i-1].index = ps->coords[i]; + ctx->prototype->c[ps->ncoords-1].index = -1; + ctx->prototype->nc = ps->ncoords; + + ctx->prototype->c[ps->ncoords-1].type = hex_from_letter(ps->final_hex); + for (i = ps->ncoords - 1; i-- > 0 ;) { + const struct HexData *h = &hexdata[ctx->prototype->c[i+1].type]; + ctx->prototype->c[i].type = h->subhexes[ctx->prototype->c[i].index]; + } + + spectrectx_start_vertices(ctx, ps->orientation); + + ctx->prototype->hex_colour = 0; + ctx->prototype->prev_hex_colour = 0; + ctx->prototype->incoming_hex_edge = 0; +} + +void spectrectx_cleanup(SpectreContext *ctx) +{ + if (ctx->must_free_rs) + random_free(ctx->rs); + spectre_coords_free(ctx->prototype); +} + +SpectreCoords *spectrectx_initial_coords(SpectreContext *ctx) +{ + return spectre_coords_copy(ctx->prototype); +} + +/* + * Extend sc until it has at least n coordinates in, by copying from + * ctx->prototype if needed, and extending ctx->prototype if needed in + * order to do that. + */ +void spectrectx_extend_coords(SpectreContext *ctx, SpectreCoords *sc, size_t n) +{ + if (ctx->prototype->nc < n) { + spectre_coords_make_space(ctx->prototype, n); + while (ctx->prototype->nc < n) { + const struct HexData *h = &hexdata[ + ctx->prototype->c[ctx->prototype->nc-1].type]; + const struct Possibility *poss; + + if (!ctx->rs) { + /* + * If there's no random_state available, it must be + * because we were given an explicit coordinate string + * and ran off the end of it. + * + * The obvious thing to do here would be to make up an + * answer non-randomly. But in fact there's a danger + * that this leads to endless recursion within a + * single coordinate step, if the hex edge we were + * trying to traverse turns into another copy of + * itself at the higher level. That happened in early + * testing before I put the random_state in at all. + * + * To avoid that risk, in this situation - which + * _shouldn't_ come up at all in sensibly play - we + * make up a random_state, and free it when the + * context goes away. + */ + ctx->rs = random_new("dummy", 5); + ctx->must_free_rs = true; + } + + poss = choose_poss(ctx->rs, h->poss, h->nposs); + ctx->prototype->c[ctx->prototype->nc-1].index = poss->lo; + ctx->prototype->c[ctx->prototype->nc].type = poss->hi; + ctx->prototype->c[ctx->prototype->nc].index = -1; + ctx->prototype->nc++; + } + } + + spectre_coords_make_space(sc, n); + while (sc->nc < n) { + assert(sc->c[sc->nc - 1].index == -1); + assert(sc->c[sc->nc - 1].type == ctx->prototype->c[sc->nc - 1].type); + sc->c[sc->nc - 1].index = ctx->prototype->c[sc->nc - 1].index; + sc->c[sc->nc].index = -1; + sc->c[sc->nc].type = ctx->prototype->c[sc->nc].type; + sc->nc++; + } +} + +void spectrectx_step_hex(SpectreContext *ctx, SpectreCoords *sc, + size_t depth, unsigned edge, unsigned *outedge) +{ + const struct HexData *h; + const struct MapEntry *m; + + spectrectx_extend_coords(ctx, sc, depth+2); + + assert(0 <= sc->c[depth].index); + assert(sc->c[depth].index < num_subhexes(sc->c[depth].type)); + assert(0 <= edge); + assert(edge < 6); + + h = &hexdata[sc->c[depth+1].type]; + m = &h->hexmap[6 * sc->c[depth].index + edge]; + if (!m->internal) { + unsigned recedge; + const struct MapEdge *me; + spectrectx_step_hex(ctx, sc, depth+1, m->hi, &recedge); + assert(recedge < 6); + h = &hexdata[sc->c[depth+1].type]; + me = &h->hexedges[recedge]; + assert(m->lo < me->len); + m = &h->hexin[me->startindex + me->len - 1 - m->lo]; + assert(m->internal); + } + sc->c[depth].index = m->hi; + sc->c[depth].type = h->subhexes[sc->c[depth].index]; + *outedge = m->lo; + + if (depth == 0) { + /* + * Update the colouring fields to track the colour of the new + * hexagon. + */ + unsigned char new_hex_colour; + + if (!((edge ^ sc->incoming_hex_edge) & 1)) { + /* We're going out via the same parity of edge we came in + * on, so the new hex colour is the same as the previous + * one. */ + new_hex_colour = sc->prev_hex_colour; + } else { + /* We're going out via the opposite parity of edge, so the + * new colour is the one of {0,1,2} that is neither this + * _nor_ the previous colour. */ + new_hex_colour = 0+1+2 - sc->hex_colour - sc->prev_hex_colour; + } + + sc->prev_hex_colour = sc->hex_colour; + sc->hex_colour = new_hex_colour; + sc->incoming_hex_edge = m->lo; + } +} + +void spectrectx_step(SpectreContext *ctx, SpectreCoords *sc, + unsigned edge, unsigned *outedge) +{ + const struct HexData *h; + const struct MapEntry *m; + + assert(0 <= sc->index); + assert(sc->index < num_spectres(sc->c[0].type)); + assert(0 <= edge); + assert(edge < 14); + + h = &hexdata[sc->c[0].type]; + m = &h->specmap[14 * sc->index + edge]; + + while (!m->internal) { + unsigned recedge; + const struct MapEdge *me; + spectrectx_step_hex(ctx, sc, 0, m->hi, &recedge); + assert(recedge < 6); + h = &hexdata[sc->c[0].type]; + me = &h->specedges[recedge]; + assert(m->lo < me->len); + m = &h->specin[me->startindex + me->len - 1 - m->lo]; + } + sc->index = m->hi; + *outedge = m->lo; +} + +void spectrectx_generate(SpectreContext *ctx, + bool (*callback)(void *cbctx, const Spectre *spec), + void *cbctx) +{ + tree234 *placed = newtree234(spectre_cmp); + Spectre *qhead = NULL, *qtail = NULL; + + { + Spectre *spec = spectre_initial(ctx); + + add234(placed, spec); + + spec->next = NULL; + + if (callback(cbctx, spec)) + qhead = qtail = spec; + } + + while (qhead) { + unsigned edge; + Spectre *spec = qhead; + + for (edge = 0; edge < 14; edge++) { + Spectre *new_spec; + + new_spec = spectre_adjacent(ctx, spec, edge, NULL); + + if (find234(placed, new_spec, NULL)) { + spectre_free(new_spec); + continue; + } + + if (!callback(cbctx, new_spec)) { + spectre_free(new_spec); + continue; + } + + add234(placed, new_spec); + qtail->next = new_spec; + qtail = new_spec; + new_spec->next = NULL; + } + + qhead = qhead->next; + } + + { + Spectre *spec; + while ((spec = delpos234(placed, 0)) != NULL) + spectre_free(spec); + freetree234(placed); + } +} + +const char *spectre_tiling_params_invalid( + const struct SpectrePatchParams *params) +{ + size_t i; + Hex h; + + if (params->ncoords == 0) + return "expected at least one numeric coordinate"; + if (!spectre_valid_hex_letter(params->final_hex)) + return "invalid final hexagon type"; + + h = hex_from_letter(params->final_hex); + for (i = params->ncoords; i-- > 0 ;) { + unsigned limit = (i == 0) ? num_spectres(h) : num_subhexes(h); + if (params->coords[i] >= limit) + return "coordinate out of range"; + + if (i > 0) + h = hexdata[h].subhexes[params->coords[i]]; + } + + return NULL; +} + +struct SpectreCallbackContext { + int xoff, yoff; + Coord xmin, xmax, ymin, ymax; + + spectre_tile_callback_fn external_cb; + void *external_cbctx; +}; + +static bool spectre_internal_callback(void *vctx, const Spectre *spec) +{ + struct SpectreCallbackContext *ctx = (struct SpectreCallbackContext *)vctx; + size_t i; + int output_coords[4*14]; + + for (i = 0; i < 14; i++) { + Point p = spec->vertices[i]; + Coord x = point_x(p), y = point_y(p); + if (coord_cmp(x, ctx->xmin) < 0 || coord_cmp(x, ctx->xmax) > 0 || + coord_cmp(y, ctx->ymin) < 0 || coord_cmp(y, ctx->ymax) > 0) + return false; + + output_coords[4*i + 0] = ctx->xoff + x.c1; + output_coords[4*i + 1] = x.cr3; + output_coords[4*i + 2] = ctx->yoff - y.c1; + output_coords[4*i + 3] = -y.cr3; + } + + if (ctx->external_cb) + ctx->external_cb(ctx->external_cbctx, output_coords); + + return true; +} + +static void spectre_set_bounds(struct SpectreCallbackContext *cbctx, + int w, int h) +{ + cbctx->xoff = w/2; + cbctx->yoff = h/2; + cbctx->xmin.c1 = -cbctx->xoff; + cbctx->xmax.c1 = -cbctx->xoff + w; + cbctx->ymin.c1 = cbctx->yoff - h; + cbctx->ymax.c1 = cbctx->yoff; + cbctx->xmin.cr3 = 0; + cbctx->xmax.cr3 = 0; + cbctx->ymin.cr3 = 0; + cbctx->ymax.cr3 = 0; +} + +void spectre_tiling_randomise(struct SpectrePatchParams *ps, int w, int h, + random_state *rs) +{ + SpectreContext ctx[1]; + struct SpectreCallbackContext cbctx[1]; + size_t i; + + spectre_set_bounds(cbctx, w, h); + cbctx->external_cb = NULL; + cbctx->external_cbctx = NULL; + + spectrectx_init_random(ctx, rs); + spectrectx_generate(ctx, spectre_internal_callback, cbctx); + + ps->orientation = ctx->orientation; + ps->ncoords = ctx->prototype->nc; + ps->coords = snewn(ps->ncoords, unsigned char); + ps->coords[0] = ctx->prototype->index; + for (i = 1; i < ps->ncoords; i++) + ps->coords[i] = ctx->prototype->c[i-1].index; + ps->final_hex = hex_to_letter(ctx->prototype->c[ps->ncoords-1].type); + + spectrectx_cleanup(ctx); +} + +void spectre_tiling_generate( + const struct SpectrePatchParams *params, int w, int h, + spectre_tile_callback_fn external_cb, void *external_cbctx) +{ + SpectreContext ctx[1]; + struct SpectreCallbackContext cbctx[1]; + + spectre_set_bounds(cbctx, w, h); + cbctx->external_cb = external_cb; + cbctx->external_cbctx = external_cbctx; + + spectrectx_init_from_params(ctx, params); + spectrectx_generate(ctx, spectre_internal_callback, cbctx); + spectrectx_cleanup(ctx); +} diff --git a/apps/plugins/puzzles/src/spectre.h b/apps/plugins/puzzles/src/spectre.h new file mode 100644 index 0000000000..97d7595e3a --- /dev/null +++ b/apps/plugins/puzzles/src/spectre.h @@ -0,0 +1,72 @@ +#ifndef PUZZLES_SPECTRE_H +#define PUZZLES_SPECTRE_H + +struct SpectrePatchParams { + /* + * A patch of Spectre tiling is identified by giving + * + * - the coordinates of the central Spectre, using a + * combinatorial coordinate system similar to the Hat tiling in + * hat.h + * + * - the orientation of that Spectre, as a number from 0 to 11 (a + * multiple of 30 degrees), with 0 representing the 'head' of + * the Spectre facing upwards, and numbers counting + * anticlockwise. + * + * Coordinates are a sequence of small non-negative integers. The + * valid range for each coordinate depends on the next coordinate, + * or on final_hex if it's the last one in the list. The largest + * valid range is {0,...,7}. + * + * 'final_hex' is one of the letters GDJLXPSFY. + * spectre_valid_hex_letter() will check that. + */ + int orientation; + size_t ncoords; + unsigned char *coords; + char final_hex; +}; + +bool spectre_valid_hex_letter(char c); + +/* + * Fill in SpectrePatchParams with a randomly selected set of + * coordinates, in enough detail to generate a patch of tiling filling + * a w x h area. The unit of measurement is 1/(2*sqrt(2)) of a Spectre + * edge, i.e. such that a single Spectre edge at 45 degrees would + * correspond to the vector (2,2). + * + * The 'coords' field of the structure will be filled in with a new + * dynamically allocated array. Any previous pointer in that field + * will be overwritten. + */ +void spectre_tiling_randomise(struct SpectrePatchParams *params, int w, int h, + random_state *rs); + +/* + * Validate a SpectrePatchParams to ensure it contains no illegal + * coordinates. Returns NULL if it's acceptable, or an error string if + * not. + */ +const char *spectre_tiling_params_invalid( + const struct SpectrePatchParams *params); + +/* + * Generate the actual set of Spectre tiles from a SpectrePatchParams, + * passing each one to a callback. The callback receives the vertices + * of each point, in the form of an array of 4*14 integers. Each + * vertex is represented by four consecutive integers in this array, + * with the first two giving the x coordinate and the last two the y + * coordinate. Each pair of integers a,b represent a single coordinate + * whose value is a + b*sqrt(3). The unit of measurement is as above. + */ +typedef void (*spectre_tile_callback_fn)(void *ctx, const int *coords); + +#define SPECTRE_NVERTICES 14 + +void spectre_tiling_generate( + const struct SpectrePatchParams *params, int w, int h, + spectre_tile_callback_fn cb, void *cbctx); + +#endif diff --git a/apps/plugins/puzzles/src/tents.R b/apps/plugins/puzzles/src/tents.R deleted file mode 100644 index 925661c761..0000000000 --- a/apps/plugins/puzzles/src/tents.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -TENTS_EXTRA = matching dsf - -tents : [X] GTK COMMON tents TENTS_EXTRA tents-icon|no-icon - -tents : [G] WINDOWS COMMON tents TENTS_EXTRA tents.res|noicon.res - -ALL += tents[COMBINED] TENTS_EXTRA - -tentssolver : [U] tents[STANDALONE_SOLVER] TENTS_EXTRA STANDALONE -tentssolver : [C] tents[STANDALONE_SOLVER] TENTS_EXTRA STANDALONE - -!begin am gtk -GAMES += tents -!end - -!begin >list.c - A(tents) \ -!end - -!begin >gamedesc.txt -tents:tents.exe:Tents:Tent-placing puzzle:Place a tent next to each tree. -!end diff --git a/apps/plugins/puzzles/src/tents.c b/apps/plugins/puzzles/src/tents.c index ee06172baf..0d40959d26 100644 --- a/apps/plugins/puzzles/src/tents.c +++ b/apps/plugins/puzzles/src/tents.c @@ -32,7 +32,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "matching.h" @@ -229,7 +234,7 @@ */ #if defined STANDALONE_SOLVER #define SOLVER_DIAGNOSTICS -bool verbose = false; +static bool verbose = false; #elif defined SOLVER_DIAGNOSTICS #define verbose true #endif @@ -408,6 +413,8 @@ static const char *validate_params(const game_params *params, bool full) */ if (params->w < 4 || params->h < 4) return "Width and height must both be at least four"; + if (params->w > (INT_MAX - 1) / params->h) + return "Width times height must not be unreasonably large"; return NULL; } @@ -998,7 +1005,7 @@ static char *new_game_desc(const game_params *params_in, random_state *rs, int dy, dx; bool ok = true; - which = i + random_upto(rs, j); + which = i + random_upto(rs, w*h - i); tmp = order[which]; order[which] = order[i]; order[i] = tmp; @@ -1188,6 +1195,21 @@ static char *new_game_desc(const game_params *params_in, random_state *rs, return ret; } +/* + * Grid description format: + * + * _ = tree + * a = 1 BLANK then TREE + * ... + * y = 25 BLANKs then TREE + * z = 25 BLANKs + * ! = set previous square to TENT + * - = set previous square to NONTENT + * + * Last character must be one that would insert a tree as the first + * square after the grid. + */ + static const char *validate_desc(const game_params *params, const char *desc) { int w = params->w, h = params->h; @@ -1201,9 +1223,10 @@ static const char *validate_desc(const game_params *params, const char *desc) area += *desc - 'a' + 2; else if (*desc == 'z') area += 25; - else if (*desc == '!' || *desc == '-') - /* do nothing */; - else + else if (*desc == '!' || *desc == '-') { + if (area == 0 || area > w * h) + return "Tent or non-tent placed off the grid"; + } else return "Invalid character in grid specification"; desc++; @@ -1436,7 +1459,7 @@ static game_ui *new_ui(const game_state *state) ui->drag_button = -1; ui->drag_ok = false; ui->cx = ui->cy = 0; - ui->cdisp = false; + ui->cdisp = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -1445,18 +1468,25 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + int w = state->p.w; + int v = state->grid[ui->cy*w+ui->cx]; + + if (IS_CURSOR_SELECT(button) && ui->cdisp) { + switch (v) { + case BLANK: + return button == CURSOR_SELECT ? "Tent" : "Green"; + case TENT: case NONTENT: return "Clear"; + } + } + return ""; } struct game_drawstate { @@ -1546,7 +1576,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char tmpbuf[80]; bool shift = button & MOD_SHFT, control = button & MOD_CTRL; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { x = FROMCOORD(x); @@ -1559,7 +1589,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->dsy = ui->dey = y; ui->drag_ok = true; ui->cdisp = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if ((IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) && @@ -1591,14 +1621,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (IS_MOUSE_DRAG(button)) - return UI_UPDATE; + return MOVE_UI_UPDATE; /* * The drag has been released. Enact it. */ if (!ui->drag_ok) { ui->drag_button = -1; - return UI_UPDATE; /* drag was just cancelled */ + return MOVE_UI_UPDATE; /* drag was just cancelled */ } xmin = min(ui->dsx, ui->dex); @@ -1636,7 +1666,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (buflen == 0) { sfree(buf); - return UI_UPDATE; /* drag was terminated */ + return MOVE_UI_UPDATE; /* drag was terminated */ } else { buf[buflen] = '\0'; return buf; @@ -1644,11 +1674,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, } if (IS_CURSOR_MOVE(button)) { - ui->cdisp = true; + char *ret; if (shift || control) { int len = 0, i, indices[2]; indices[0] = ui->cx + w * ui->cy; - move_cursor(button, &ui->cx, &ui->cy, w, h, false); + ret = move_cursor(button, &ui->cx, &ui->cy, w, h, false, + &ui->cdisp); indices[1] = ui->cx + w * ui->cy; /* NONTENTify all unique traversed eligible squares */ @@ -1663,8 +1694,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, tmpbuf[len] = '\0'; if (len) return dupstr(tmpbuf); } else - move_cursor(button, &ui->cx, &ui->cy, w, h, false); - return UI_UPDATE; + ret = move_cursor(button, &ui->cx, &ui->cy, w, h, false, + &ui->cdisp); + return ret; } if (ui->cdisp) { char rep = 0; @@ -1691,7 +1723,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } } else if (IS_CURSOR_SELECT(button)) { ui->cdisp = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } return NULL; @@ -1875,7 +1907,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* fool the macros */ struct dummy { int tilesize; } dummy, *ds = &dummy; @@ -1976,7 +2008,8 @@ static int *find_errors(const game_state *state, char *grid) { int w = state->p.w, h = state->p.h; int *ret = snewn(w*h + w + h, int); - int *tmp = snewn(w*h*2, int), *dsf = tmp + w*h; + int *tmp = snewn(w*h, int); + DSF *dsf; int x, y; /* @@ -2193,7 +2226,7 @@ static int *find_errors(const game_state *state, char *grid) * all the tents in any component which has a smaller tree * count. */ - dsf_init(dsf, w*h); + dsf = dsf_new(w*h); /* Construct the equivalence classes. */ for (y = 0; y < h; y++) { for (x = 0; x < w-1; x++) { @@ -2236,7 +2269,7 @@ static int *find_errors(const game_state *state, char *grid) * start of the game, before the user had done anything wrong!) */ #define TENT(x) ((x)==TENT || (x)==BLANK) - dsf_init(dsf, w*h); + dsf_reinit(dsf); /* Construct the equivalence classes. */ for (y = 0; y < h; y++) { for (x = 0; x < w-1; x++) { @@ -2272,6 +2305,7 @@ static int *find_errors(const game_state *state, char *grid) #undef TENT sfree(tmp); + dsf_free(dsf); return ret; } @@ -2411,14 +2445,6 @@ static void int_redraw(drawing *dr, game_drawstate *ds, } if (printing || !ds->started) { - if (!printing) { - int ww, wh; - game_compute_size(&state->p, TILESIZE, &ww, &wh); - draw_rect(dr, 0, 0, ww, wh, COL_BACKGROUND); - draw_update(dr, 0, 0, ww, wh); - ds->started = true; - } - if (printing) print_line_width(dr, TILESIZE/64); @@ -2572,24 +2598,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int c; @@ -2628,12 +2651,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -2647,7 +2672,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; diff --git a/apps/plugins/puzzles/src/towers.R b/apps/plugins/puzzles/src/towers.R deleted file mode 100644 index c2bb78a2dc..0000000000 --- a/apps/plugins/puzzles/src/towers.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -TOWERS_EXTRA = LATIN -TOWERS_EXTRA_SOLVER = LATIN_SOLVER - -towers : [X] GTK COMMON towers TOWERS_EXTRA towers-icon|no-icon - -towers : [G] WINDOWS COMMON towers TOWERS_EXTRA towers.res|noicon.res - -towerssolver : [U] towers[STANDALONE_SOLVER] TOWERS_EXTRA_SOLVER STANDALONE -towerssolver : [C] towers[STANDALONE_SOLVER] TOWERS_EXTRA_SOLVER STANDALONE - -ALL += towers[COMBINED] TOWERS_EXTRA - -!begin am gtk -GAMES += towers -!end - -!begin >list.c - A(towers) \ -!end - -!begin >gamedesc.txt -towers:towers.exe:Towers:Tower-placing Latin square puzzle:Complete the latin square of towers in accordance with the clues. -!end diff --git a/apps/plugins/puzzles/src/towers.c b/apps/plugins/puzzles/src/towers.c index 13c652b819..4dd9484ad9 100644 --- a/apps/plugins/puzzles/src/towers.c +++ b/apps/plugins/puzzles/src/towers.c @@ -23,7 +23,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "latin.h" @@ -385,12 +389,12 @@ static int solver_easy(struct latin_solver *solver, void *vctx) return ret; #ifdef STANDALONE_SOLVER - if (solver_show_working) - sprintf(prefix, "%*slower bounds for clue %s %d:\n", - solver_recurse_depth*4, "", - cluepos[c/w], c%w+1); - else - prefix[0] = '\0'; /* placate optimiser */ + if (solver_show_working) + sprintf(prefix, "%*slower bounds for clue %s %d:\n", + solver_recurse_depth*4, "", + cluepos[c/w], c%w+1); + else + prefix[0] = '\0'; /* placate optimiser */ #endif i = 0; @@ -893,6 +897,7 @@ static const char *validate_desc(const game_params *params, const char *desc) return "Too much data to fit in grid"; } + if (*p) return "Rubbish at end of game description"; return NULL; } @@ -1154,16 +1159,59 @@ struct game_ui { * allowed on immutable squares. */ bool hcursor; + + /* + * User preference option which can be set to FALSE to disable the + * 3D graphical style, and instead just display the puzzle as if + * it was a Sudoku variant, i.e. each square just has a digit in + * it. + * + * I was initially a bit uncertain about whether the 3D style + * would be the right thing, on the basis that it uses up space in + * the cells and makes it hard to use many pencil marks. Actually + * nobody seems to have complained, but having put in the option + * while I was still being uncertain, it seems silly not to leave + * it in just in case. + */ + int three_d; + + /* + * User preference option: if the user right-clicks in a square + * and presses a number key to add/remove a pencil mark, do we + * hide the mouse highlight again afterwards? + * + * Historically our answer was yes. The Android port prefers no. + * There are advantages both ways, depending how much you dislike + * the highlight cluttering your view. So it's a preference. + */ + bool pencil_keep_highlight; }; +static void legacy_prefs_override(struct game_ui *ui_out) +{ + static bool initialised = false; + static int three_d = -1; + + if (!initialised) { + initialised = true; + three_d = getenv_bool("TOWERS_2D", -1); + } + + if (three_d != -1) + ui_out->three_d = three_d; +} + static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->hx = ui->hy = 0; ui->hpencil = false; - ui->hshow = false; - ui->hcursor = false; + ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->three_d = true; + ui->pencil_keep_highlight = false; + legacy_prefs_override(ui); return ui; } @@ -1173,13 +1221,34 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(3, config_item); + + ret[0].name = "Keep mouse highlight after changing a pencil mark"; + ret[0].kw = "pencil-keep-highlight"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->pencil_keep_highlight; + + ret[1].name = "Puzzle appearance"; + ret[1].kw = "appearance"; + ret[1].type = C_CHOICES; + ret[1].u.choices.choicenames = ":2D:3D"; + ret[1].u.choices.choicekws = ":2d:3d"; + ret[1].u.choices.selected = ui->three_d; + + ret[2].name = NULL; + ret[2].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->pencil_keep_highlight = cfg[0].u.boolean.bval; + ui->three_d = cfg[1].u.choices.selected; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1198,6 +1267,14 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (ui->hshow && (button == CURSOR_SELECT)) + return ui->hpencil ? "Ink" : "Pencil"; + return ""; +} + #define PREFERRED_TILESIZE 48 #define TILESIZE (ds->tilesize) #define BORDER (TILESIZE * 9 / 8) @@ -1221,8 +1298,6 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, struct game_drawstate { int tilesize; - bool three_d; /* default 3D graphics are user-disableable */ - bool started; long *tiles; /* (w+2)*(w+2) temp space */ long *drawn; /* (w+2)*(w+2)*4: current drawn data */ bool *errtmp; @@ -1349,12 +1424,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, int tx, ty; char buf[80]; - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); tx = FROMCOORD(x); ty = FROMCOORD(y); - if (ds->three_d) { + if (ui->three_d) { /* * In 3D mode, just locating the mouse click in the natural * square grid may not be sufficient to tell which tower the @@ -1401,7 +1476,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == RIGHT_BUTTON) { /* @@ -1421,7 +1496,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hshow = false; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (button == LEFT_BUTTON) { if (is_clue(state, tx, ty)) { @@ -1444,16 +1519,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, } return NULL; } - move_cursor(button, &ui->hx, &ui->hy, w, w, false); - ui->hshow = true; ui->hcursor = true; - return UI_UPDATE; + return move_cursor(button, &ui->hx, &ui->hy, w, w, false, &ui->hshow); } if (ui->hshow && (button == CURSOR_SELECT)) { ui->hpencil = !ui->hpencil; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->hshow && @@ -1476,10 +1549,31 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (state->clues->immutable[ui->hy*w+ui->hx]) return NULL; + /* + * If you ask to fill a square with what it already contains, + * or blank it when it's already empty, that has no effect... + */ + if ((!ui->hpencil || n == 0) && state->grid[ui->hy*w+ui->hx] == n && + state->pencil[ui->hy*w+ui->hx] == 0) { + /* ... expect to remove the cursor in mouse mode. */ + if (!ui->hcursor) { + ui->hshow = false; + return MOVE_UI_UPDATE; + } + return NULL; + } + sprintf(buf, "%c%d,%d,%d", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); - if (!ui->hcursor) ui->hshow = false; + /* + * Hide the highlight after a keypress, if it was mouse- + * generated. Also, don't hide it if this move has changed + * pencil marks and the user preference says not to hide the + * highlight in that situation. + */ + if (!ui->hcursor && !(ui->hpencil && ui->pencil_keep_highlight)) + ui->hshow = false; return dupstr(buf); } @@ -1558,7 +1652,7 @@ static game_state *execute_move(const game_state *from, const char *move) #define SIZE(w) ((w) * TILESIZE + 2*BORDER) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1614,8 +1708,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) int i; ds->tilesize = 0; - ds->three_d = !getenv("TOWERS_2D"); - ds->started = false; ds->tiles = snewn((w+2)*(w+2), long); ds->drawn = snewn((w+2)*(w+2)*4, long); for (i = 0; i < (w+2)*(w+2)*4; i++) @@ -1633,8 +1725,8 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds) sfree(ds); } -static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, - int x, int y, long tile) +static void draw_tile(drawing *dr, game_drawstate *ds, const game_ui *ui, + struct clues *clues, int x, int y, long tile) { int w = clues->w /* , a = w*w */; int tx, ty, bg; @@ -1646,7 +1738,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, bg = (tile & DF_HIGHLIGHT) ? COL_HIGHLIGHT : COL_BACKGROUND; /* draw tower */ - if (ds->three_d && (tile & DF_PLAYAREA) && (tile & DF_DIGIT_MASK)) { + if (ui->three_d && (tile & DF_PLAYAREA) && (tile & DF_DIGIT_MASK)) { int coords[8]; int xoff = X_3D_DISP(tile & DF_DIGIT_MASK, w); int yoff = Y_3D_DISP(tile & DF_DIGIT_MASK, w); @@ -1747,10 +1839,10 @@ static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues, * to put the pencil marks. */ /* Start with the whole square, minus space for impinging towers */ - pl = tx + (ds->three_d ? X_3D_DISP(w,w) : 0); + pl = tx + (ui->three_d ? X_3D_DISP(w,w) : 0); pr = tx + TILESIZE; pt = ty; - pb = ty + TILESIZE - (ds->three_d ? Y_3D_DISP(w,w) : 0); + pb = ty + TILESIZE - (ui->three_d ? Y_3D_DISP(w,w) : 0); /* * We arrange our pencil marks in a grid layout, with @@ -1821,20 +1913,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int w = state->par.w /*, a = w*w */; int i, x, y; - if (!ds->started) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all - * games should start by drawing a big background-colour - * rectangle covering the whole window. - */ - draw_rect(dr, 0, 0, SIZE(w), SIZE(w), COL_BACKGROUND); - - draw_update(dr, 0, 0, SIZE(w), SIZE(w)); - - ds->started = true; - } - check_errors(state, ds->errtmp); /* @@ -1900,13 +1978,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds, ds->drawn[i*4+2] != bl || ds->drawn[i*4+3] != br) { clip(dr, COORD(x-1), COORD(y-1), TILESIZE, TILESIZE); - draw_tile(dr, ds, state->clues, x-1, y-1, tr); + draw_tile(dr, ds, ui, state->clues, x-1, y-1, tr); if (x > 0) - draw_tile(dr, ds, state->clues, x-2, y-1, tl); + draw_tile(dr, ds, ui, state->clues, x-2, y-1, tl); if (y <= w) - draw_tile(dr, ds, state->clues, x-1, y, br); + draw_tile(dr, ds, ui, state->clues, x-1, y, br); if (x > 0 && y <= w) - draw_tile(dr, ds, state->clues, x-2, y, bl); + draw_tile(dr, ds, ui, state->clues, x-2, y, bl); unclip(dr); draw_update(dr, COORD(x-1), COORD(y-1), TILESIZE, TILESIZE); @@ -1953,26 +2031,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - if (state->completed) - return false; - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * We use 9mm squares by default, like Solo. */ - game_compute_size(params, 900, &pw, &ph); + game_compute_size(params, 900, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->par.w; int ink = print_mono_colour(dr, 0); @@ -2058,12 +2131,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -2077,7 +2152,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ }; diff --git a/apps/plugins/puzzles/src/tracks.R b/apps/plugins/puzzles/src/tracks.R deleted file mode 100644 index 8b0ac97e0f..0000000000 --- a/apps/plugins/puzzles/src/tracks.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -TRACKS_EXTRA = dsf findloop - -tracks : [X] GTK COMMON tracks TRACKS_EXTRA tracks-icon|no-icon - -tracks : [G] WINDOWS COMMON tracks TRACKS_EXTRA tracks.res|noicon.res - -ALL += tracks[COMBINED] TRACKS_EXTRA - -trackssolver : [U] tracks[STANDALONE_SOLVER] TRACKS_EXTRA STANDALONE -trackssolver : [C] tracks[STANDALONE_SOLVER] TRACKS_EXTRA STANDALONE - -!begin am gtk -GAMES += tracks -!end - -!begin >list.c - A(tracks) \ -!end - -!begin >gamedesc.txt -tracks:tracks.exe:Tracks:Path-finding railway track puzzle:Fill in the railway track according to the clues. -!end diff --git a/apps/plugins/puzzles/src/tracks.c b/apps/plugins/puzzles/src/tracks.c index 3cf5df70a1..a2d4560907 100644 --- a/apps/plugins/puzzles/src/tracks.c +++ b/apps/plugins/puzzles/src/tracks.c @@ -20,7 +20,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -196,6 +201,8 @@ static const char *validate_params(const game_params *params, bool full) */ if (params->w < 4 || params->h < 4) return "Width and height must both be at least four"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; return NULL; } @@ -242,6 +249,9 @@ static const int nbits[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; #define S_CLUE 8 #define S_MARK 16 +#define S_FLASH_SHIFT 8 /* Position of tile in solved track */ +#define S_FLASH_WIDTH 8 /* Width of above sub-field */ +#define S_FLASH_MASK ((1 << S_FLASH_WIDTH) - 1) #define S_TRACK_SHIFT 16 /* U/D/L/R flags for edge track indicators */ #define S_NOTRACK_SHIFT 20 /* U/D/L/R flags for edge no-track indicators */ @@ -904,7 +914,7 @@ static game_state *new_game(midend *me, const game_params *params, const char *d } struct solver_scratch { - int *dsf; + DSF *dsf; }; static int solve_set_sflag(game_state *state, int x, int y, @@ -919,8 +929,8 @@ static int solve_set_sflag(game_state *state, int x, int y, if (state->sflags[i] & (f == S_TRACK ? S_NOTRACK : S_TRACK)) { solverdebug(("opposite flag already set there, marking IMPOSSIBLE")); state->impossible = true; - } - state->sflags[i] |= f; + } else + state->sflags[i] |= f; return 1; } @@ -937,8 +947,8 @@ static int solve_set_eflag(game_state *state, int x, int y, int d, if (sf & (f == E_TRACK ? E_NOTRACK : E_TRACK)) { solverdebug(("opposite flag already set there, marking IMPOSSIBLE")); state->impossible = true; - } - S_E_SET(state, x, y, d, f); + } else + S_E_SET(state, x, y, d, f); return 1; } @@ -1306,7 +1316,7 @@ static int solve_check_neighbours(game_state *state, bool both_ways) } static int solve_check_loop_sub(game_state *state, int x, int y, int dir, - int *dsf, int startc, int endc) + DSF *dsf, int startc, int endc) { int w = state->p.w, h = state->p.h, i = y*w+x, j, k; bool satisfied = true; @@ -1358,13 +1368,13 @@ static int solve_check_loop_sub(game_state *state, int x, int y, int dir, static int solve_check_loop(game_state *state) { int w = state->p.w, h = state->p.h, x, y, i, j, did = 0; - int *dsf, startc, endc; + DSF *dsf; + int startc, endc; /* TODO eventually we should pull this out into a solver struct and keep it updated as we connect squares. For now we recreate it every time we try this particular solver step. */ - dsf = snewn(w*h, int); - dsf_init(dsf, w*h); + dsf = dsf_new(w*h); /* Work out the connectedness of the current loop set. */ for (x = 0; x < w; x++) { @@ -1402,7 +1412,7 @@ static int solve_check_loop(game_state *state) } } - sfree(dsf); + dsf_free(dsf); return did; } @@ -1455,8 +1465,8 @@ static int solve_bridge_sub(game_state *state, int x, int y, int d, assert(d == D || d == R); if (!sc->dsf) - sc->dsf = snew_dsf(wh); - dsf_init(sc->dsf, wh); + sc->dsf = dsf_new(wh); + dsf_reinit(sc->dsf); for (xi = 0; xi < w; xi++) { for (yi = 0; yi < h; yi++) { @@ -1595,7 +1605,7 @@ static int tracks_solve(game_state *state, int diff, int *max_diff_out) break; } - sfree(sc->dsf); + dsf_free(sc->dsf); if (max_diff_out) *max_diff_out = max_diff; @@ -1775,7 +1785,7 @@ static void debug_state(game_state *state, const char *what) { } static void dsf_update_completion(game_state *state, int ax, int ay, - char dir, int *dsf) + char dir, DSF *dsf) { int w = state->p.w, ai = ay*w+ax, bx, by, bi; @@ -1820,12 +1830,37 @@ static int tracks_neighbour(int vertex, void *vctx) return -1; } +/* + * The completion flash moves along the track, so we want to label + * each tile with how far along the track it is. This is represented + * as an eight-bit field, which is more than enough when the + * completion flash is only 0.5 s long. + */ +static void set_flash_data(game_state *state) +{ + int ntrack = 0, x, y, n, d; + const int w = state->p.w; + + for (x = 0; x < w; x++) + ntrack += state->numbers->numbers[x]; + n = 0; x = 0; y = state->numbers->row_s; d = R; + do { + state->sflags[y*w + x] &= ~(S_FLASH_MASK << S_FLASH_SHIFT); + state->sflags[y*w + x] |= + n++ * (S_FLASH_MASK / (ntrack - 1)) << S_FLASH_SHIFT; + d = F(d); /* Find the direction we just arrived from. */ + d = S_E_DIRS(state, x, y, E_TRACK) & ~d; /* Other track from here. */ + x += DX(d); y += DY(d); /* Move to the next tile. */ + } while (INGRID(state, x, y)); +} + static bool check_completion(game_state *state, bool mark) { int w = state->p.w, h = state->p.h, x, y, i, target; - bool ret = true; + bool ret = true, pathret; int ntrack, nnotrack, ntrackcomplete; - int *dsf, pathclass; + DSF *dsf; + int pathclass; struct findloopstate *fls; struct tracks_neighbour_ctx ctx; @@ -1844,60 +1879,7 @@ static bool check_completion(game_state *state, bool mark) } } - /* A cell is 'complete', for the purposes of marking the game as - * finished, if it has two edges marked as TRACK. But it only has - * to have one edge marked as TRACK, or be filled in as trackful - * without any specific edges known, to count towards checking - * row/column clue errors. */ - for (x = 0; x < w; x++) { - target = state->numbers->numbers[x]; - ntrack = nnotrack = ntrackcomplete = 0; - for (y = 0; y < h; y++) { - if (S_E_COUNT(state, x, y, E_TRACK) > 0 || - state->sflags[y*w+x] & S_TRACK) - ntrack++; - if (S_E_COUNT(state, x, y, E_TRACK) == 2) - ntrackcomplete++; - if (state->sflags[y*w+x] & S_NOTRACK) - nnotrack++; - } - if (mark) { - if (ntrack > target || nnotrack > (h-target)) { - debug(("col %d error: target %d, track %d, notrack %d", - x, target, ntrack, nnotrack)); - state->num_errors[x] = 1; - ret = false; - } - } - if (ntrackcomplete != target) - ret = false; - } - for (y = 0; y < h; y++) { - target = state->numbers->numbers[w+y]; - ntrack = nnotrack = ntrackcomplete = 0; - for (x = 0; x < w; x++) { - if (S_E_COUNT(state, x, y, E_TRACK) > 0 || - state->sflags[y*w+x] & S_TRACK) - ntrack++; - if (S_E_COUNT(state, x, y, E_TRACK) == 2) - ntrackcomplete++; - if (state->sflags[y*w+x] & S_NOTRACK) - nnotrack++; - } - if (mark) { - if (ntrack > target || nnotrack > (w-target)) { - debug(("row %d error: target %d, track %d, notrack %d", - y, target, ntrack, nnotrack)); - state->num_errors[w+y] = 1; - ret = false; - } - } - if (ntrackcomplete != target) - ret = false; - } - - dsf = snewn(w*h, int); - dsf_init(dsf, w*h); + dsf = dsf_new(w*h); for (x = 0; x < w; x++) { for (y = 0; y < h; y++) { @@ -1949,9 +1931,75 @@ static bool check_completion(game_state *state, bool mark) } } - if (mark) + /* + * A cell is 'complete', for the purposes of marking the game as + * finished, if it has two edges marked as TRACK. But it only has + * to have one edge marked as TRACK, or be filled in as trackful + * without any specific edges known, to count towards checking + * row/column clue errors. + * + * This changes if we haven't found any other errors by this + * point, so the player has constructed a route from A to B. In + * that case, we highlight any row/column where the actually laid + * tracks don't match the clue. + */ + pathret = ret; /* Do we have a plausible solution so far? */ + for (x = 0; x < w; x++) { + target = state->numbers->numbers[x]; + ntrack = nnotrack = ntrackcomplete = 0; + for (y = 0; y < h; y++) { + if (S_E_COUNT(state, x, y, E_TRACK) > 0 || + state->sflags[y*w+x] & S_TRACK) + ntrack++; + if (S_E_COUNT(state, x, y, E_TRACK) == 2) + ntrackcomplete++; + if (state->sflags[y*w+x] & S_NOTRACK) + nnotrack++; + } + if (mark) { + if (ntrack > target || nnotrack > (h-target) || + (pathret && ntrackcomplete != target)) { + debug(("col %d error: target %d, track %d, notrack %d, " + "pathret %d, trackcomplete %d", + x, target, ntrack, nnotrack, pathret, ntrackcomplete)); + state->num_errors[x] = 1; + ret = false; + } + } + if (ntrackcomplete != target) + ret = false; + } + for (y = 0; y < h; y++) { + target = state->numbers->numbers[w+y]; + ntrack = nnotrack = ntrackcomplete = 0; + for (x = 0; x < w; x++) { + if (S_E_COUNT(state, x, y, E_TRACK) > 0 || + state->sflags[y*w+x] & S_TRACK) + ntrack++; + if (S_E_COUNT(state, x, y, E_TRACK) == 2) + ntrackcomplete++; + if (state->sflags[y*w+x] & S_NOTRACK) + nnotrack++; + } + if (mark) { + if (ntrack > target || nnotrack > (w-target) || + (pathret && ntrackcomplete != target)) { + debug(("row %d error: target %d, track %d, notrack %d, " + "pathret %d, trackcomplete %d", + y, target, ntrack, nnotrack, pathret, ntrackcomplete)); + state->num_errors[w+y] = 1; + ret = false; + } + } + if (ntrackcomplete != target) + ret = false; + } + + if (mark) { state->completed = ret; - sfree(dsf); + if (ret) set_flash_data(state); + } + dsf_free(dsf); return ret; } @@ -1974,7 +2022,7 @@ static game_ui *new_ui(const game_state *state) ui->notrack = false; ui->dragging = false; ui->drag_sx = ui->drag_sy = ui->drag_ex = ui->drag_ey = -1; - ui->cursor_active = false; + ui->cursor_active = getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->curx = ui->cury = 1; return ui; @@ -1985,27 +2033,19 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { } -#define PREFERRED_TILE_SIZE 30 +#define PREFERRED_TILE_SIZE 33 #define HALFSZ (ds->sz6*3) #define THIRDSZ (ds->sz6*2) #define TILE_SIZE (ds->sz6*6) -#define BORDER (TILE_SIZE/8) +#define MAX_BORDER (TILE_SIZE/8) #define LINE_THICK (TILE_SIZE/16) +#define BORDER (ds->border) #define GRID_LINE_TL (ds->grid_line_tl) #define GRID_LINE_BR (ds->grid_line_br) #define GRID_LINE_ALL (ds->grid_line_all) @@ -2028,7 +2068,7 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, #define DS_CSHIFT 20 /* R/U/L/D shift, for cursor-on-edge */ struct game_drawstate { - int sz6, grid_line_all, grid_line_tl, grid_line_br; + int sz6, border, grid_line_all, grid_line_tl, grid_line_br; bool started; int w, h, sz; @@ -2120,6 +2160,35 @@ static bool ui_can_flip_square(const game_state *state, int x, int y, bool notra return true; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (IS_CURSOR_SELECT(button) && ui->cursor_active) { + int gx = ui->curx / 2, gy = ui->cury / 2; + int w = state->p.w; + int direction = + ((ui->curx % 2) == 0) ? L : ((ui->cury % 2) == 0) ? U : 0; + if (direction && + ui_can_flip_edge(state, gx, gy, direction, + button == CURSOR_SELECT2)) { + unsigned ef = S_E_FLAGS(state, gx, gy, direction); + switch (button) { + case CURSOR_SELECT: return (ef & E_TRACK) ? "Clear" : "Track"; + case CURSOR_SELECT2: return (ef & E_NOTRACK) ? "Clear" : "X"; + } + } + if (!direction && + ui_can_flip_square(state, gx, gy, button == CURSOR_SELECT2)) { + unsigned sf = state->sflags[gy*w+gx]; + switch (button) { + case CURSOR_SELECT: return (sf & S_TRACK) ? "Clear" : "Track"; + case CURSOR_SELECT2: return (sf & S_NOTRACK) ? "Clear" : "X"; + } + } + } + return ""; +} + static char *edge_flip_str(const game_state *state, int x, int y, int dir, bool notrack, char *buf) { unsigned ef = S_E_FLAGS(state, x, y, dir); char c; @@ -2193,6 +2262,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (!INGRID(state, gx, gy)) { /* can't drag from off grid */ + ui->drag_sx = ui->drag_sy = -1; return NULL; } @@ -2209,13 +2279,13 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->drag_sx = ui->drag_ex = gx; ui->drag_sy = ui->drag_ey = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_MOUSE_DRAG(button)) { ui->cursor_active = false; update_ui_drag(state, ui, gx, gy); - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_MOUSE_RELEASE(button)) { @@ -2252,12 +2322,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, cy = CENTERED_COORD(gy); if (!INGRID(state, gx, gy) || FROMCOORD(x) != gx || FROMCOORD(y) != gy) - return UI_UPDATE; + return MOVE_UI_UPDATE; if (max(abs(x-cx),abs(y-cy)) < TILE_SIZE/4) { if (ui_can_flip_square(state, gx, gy, button == RIGHT_RELEASE)) return square_flip_str(state, gx, gy, button == RIGHT_RELEASE, tmpbuf); - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { if (abs(x-cx) < abs(y-cy)) { /* Closest to top/bottom edge. */ @@ -2271,7 +2341,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, return edge_flip_str(state, gx, gy, direction, button == RIGHT_RELEASE, tmpbuf); else - return UI_UPDATE; + return MOVE_UI_UPDATE; } } } @@ -2284,7 +2354,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (!ui->cursor_active) { ui->cursor_active = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } ui->curx = ui->curx + dx; @@ -2295,17 +2365,17 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->curx = min(max(ui->curx, 1), 2*w-1); ui->cury = min(max(ui->cury, 1), 2*h-1); - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (IS_CURSOR_SELECT(button)) { if (!ui->cursor_active) { ui->cursor_active = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } /* click on square corner does nothing (shouldn't get here) */ if ((ui->curx % 2) == 0 && (ui->cury % 2 == 0)) - return UI_UPDATE; + return MOVE_UI_UPDATE; gx = ui->curx / 2; gy = ui->cury / 2; @@ -2317,7 +2387,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, else if (!direction && ui_can_flip_square(state, gx, gy, button == CURSOR_SELECT2)) return square_flip_str(state, gx, gy, button == CURSOR_SELECT2, tmpbuf); - return UI_UPDATE; + return MOVE_UI_UPDATE; } #if 0 @@ -2334,6 +2404,7 @@ static game_state *execute_move(const game_state *state, const char *move) int w = state->p.w, x, y, n, i; char c, d; unsigned f; + bool move_is_solve = false; game_state *ret = dup_game(state); /* this is breaking the bank on GTK, which vsprintf's into a fixed-size buffer @@ -2344,6 +2415,7 @@ static game_state *execute_move(const game_state *state, const char *move) c = *move; if (c == 'S') { ret->used_solve = true; + move_is_solve = true; move++; } else if (c == 'T' || c == 't' || c == 'N' || c == 'n') { /* set track, clear track; set notrack, clear notrack */ @@ -2355,6 +2427,9 @@ static game_state *execute_move(const game_state *state, const char *move) f = (c == 'T' || c == 't') ? S_TRACK : S_NOTRACK; if (d == 'S') { + if (!ui_can_flip_square(ret, x, y, f == S_NOTRACK) && + !move_is_solve) + goto badmove; if (c == 'T' || c == 'N') ret->sflags[y*w+x] |= f; else @@ -2364,6 +2439,9 @@ static game_state *execute_move(const game_state *state, const char *move) unsigned df = 1<tilesize' for macro expansion purposes */ + /* Ick: fake up `ds->sz6' and `ds->border` for macro expansion purposes */ struct { - int sz6; + int sz6, border; } ads, *ds = &ads; ads.sz6 = tilesize/6; + ads.border = MAX_BORDER; + /* + * Allow a reduced border at small tile sizes because the steps + * are quite large and it's better to have a thin border than + * to go down to a smaller tile size. + */ + if (ads.border <= 5) + ads.border = min(tilesize % 6, MAX_BORDER); *x = (params->w+2) * TILE_SIZE + 2 * BORDER; *y = (params->h+2) * TILE_SIZE + 2 * BORDER; } @@ -2416,14 +2502,16 @@ static void game_set_size(drawing *dr, game_drawstate *ds, const game_params *params, int tilesize) { ds->sz6 = tilesize/6; + ds->border = MAX_BORDER; + if (ds->border <= 5) + ds->border = min(tilesize % 6, MAX_BORDER); ds->grid_line_all = max(LINE_THICK, 1); ds->grid_line_br = ds->grid_line_all / 2; ds->grid_line_tl = ds->grid_line_all - ds->grid_line_br; } enum { - COL_BACKGROUND, COL_LOWLIGHT, COL_HIGHLIGHT, - COL_TRACK_BACKGROUND = COL_LOWLIGHT, + COL_BACKGROUND, COL_TRACK_BACKGROUND, COL_GRID, COL_CLUE, COL_CURSOR, COL_TRACK, COL_TRACK_CLUE, COL_SLEEPER, COL_DRAGON, COL_DRAGOFF, @@ -2436,14 +2524,15 @@ static float *game_colours(frontend *fe, int *ncolours) float *ret = snewn(3 * NCOLOURS, float); int i; - game_mkhighlight(fe, ret, COL_BACKGROUND, COL_HIGHLIGHT, COL_LOWLIGHT); + game_mkhighlight(fe, ret, COL_BACKGROUND, -1, COL_TRACK_BACKGROUND); + colour_mix(&ret[COL_BACKGROUND*3], &ret[COL_TRACK_BACKGROUND*3], 0.5F, + &ret[COL_GRID*3]); for (i = 0; i < 3; i++) { ret[COL_TRACK_CLUE * 3 + i] = 0.0F; ret[COL_TRACK * 3 + i] = 0.5F; ret[COL_CLUE * 3 + i] = 0.0F; - ret[COL_GRID * 3 + i] = 0.75F; - ret[COL_CURSOR * 3 + i] = 0.6F; + ret[COL_CURSOR * 3 + i] = 0.3F; ret[COL_ERROR_BACKGROUND * 3 + i] = 1.0F; } @@ -2535,7 +2624,8 @@ static void draw_thick_circle_outline(drawing *dr, float thickness, x2 = cx + r*(float)cos(th2); y1 = cy + r*(float)sin(th); y2 = cy + r*(float)sin(th2); - debug(("circ outline: x=%.2f -> %.2f, thick=%.2f", x1, x2, thickness)); + debug(("circ outline: x=%.2f -> %.2f, thick=%.2f\n", + x1, x2, thickness)); draw_thick_line(dr, thickness, x1, y1, x2, y2, colour); } } @@ -2665,7 +2755,7 @@ static void draw_square(drawing *dr, game_drawstate *ds, curx = ox + TILE_SIZE - off; curw = 2*off + 1; } - draw_rect_outline(dr, curx, cury, curw, curh, COL_GRID); + draw_rect_outline(dr, curx, cury, curw, curh, COL_CURSOR); } /* Draw tracks themselves */ @@ -2777,20 +2867,11 @@ static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldst const game_state *state, int dir, const game_ui *ui, float animtime, float flashtime) { - int i, x, y, flashing = 0, w = ds->w, h = ds->h; + int i, x, y, flashing, w = ds->w, h = ds->h; bool force = false; game_state *drag_state = NULL; if (!ds->started) { - /* - * The initial contents of the window are not guaranteed and - * can vary with front ends. To be on the safe side, all games - * should start by drawing a big background-colour rectangle - * covering the whole window. - */ - draw_rect(dr, 0, 0, (w+2)*TILE_SIZE + 2*BORDER, (h+2)*TILE_SIZE + 2*BORDER, - COL_BACKGROUND); - draw_loop_ends(dr, ds, state, COL_CLUE); draw_rect(dr, COORD(0) - GRID_LINE_BR, COORD(0) - GRID_LINE_BR, @@ -2812,11 +2893,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldst } } - if (flashtime > 0 && - (flashtime <= FLASH_TIME/3 || - flashtime >= FLASH_TIME*2/3)) - flashing = DS_FLASH; - if (ui->dragging) drag_state = copy_and_apply_drag(state, ui); @@ -2824,6 +2900,16 @@ static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldst for (y = 0; y < h; y++) { unsigned int f, f_d; + flashing = 0; + if (flashtime > 0) { + float flashpos = + (state->sflags[y*w+x] >> S_FLASH_SHIFT & S_FLASH_MASK) / + (float)S_FLASH_MASK; + if (flashtime > FLASH_TIME / 2 * flashpos && + flashtime <= FLASH_TIME / 2 * (flashpos + 1.0F)) + flashing = DS_FLASH; + } + f = s2d_flags(state, x, y, ui) | flashing; f_d = drag_state ? s2d_flags(drag_state, x, y, ui) : f; @@ -2890,22 +2976,19 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* The Times uses 7mm squares */ - game_compute_size(params, 700, &pw, &ph); + game_compute_size(params, 700, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->p.w, h = state->p.h; int black = print_mono_colour(dr, 0), grey = print_grey_colour(dr, 0.5F); @@ -2948,7 +3031,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) #endif const struct game thegame = { - "Tracks", "games.tracks", "tracks", + "Train Tracks", "games.tracks", "tracks", default_params, game_fetch_preset, NULL, decode_params, @@ -2964,12 +3047,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2983,7 +3068,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/tree234.c b/apps/plugins/puzzles/src/tree234.c index ad8eb047cd..ef2c3ffaf7 100644 --- a/apps/plugins/puzzles/src/tree234.c +++ b/apps/plugins/puzzles/src/tree234.c @@ -29,33 +29,25 @@ #include #include +#define TREE234_INTERNALS #include "tree234.h" #include "puzzles.h" /* for smalloc/sfree */ -#ifdef TEST -#define LOG(x) (printf x) -#define smalloc malloc -#define srealloc realloc -#define sfree free +#ifdef DEBUG_TREE234 +#include +static void logprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} +#define LOG(x) (logprintf x) #else #define LOG(x) #endif -typedef struct node234_Tag node234; - -struct tree234_Tag { - node234 *root; - cmpfn234 cmp; -}; - -struct node234_Tag { - node234 *parent; - node234 *kids[4]; - int counts[4]; - void *elems[3]; -}; - /* * Create a 2-3-4 tree. */ @@ -327,7 +319,7 @@ static void *add234_internal(tree234 *t, void *e, int index) { } n = t->root; - while (n) { + do { LOG((" node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n", n, n->kids[0], n->counts[0], n->elems[0], @@ -380,7 +372,7 @@ static void *add234_internal(tree234 *t, void *e, int index) { if (!n->kids[ki]) break; n = n->kids[ki]; - } + } while (n); add234_insert(NULL, e, NULL, &t->root, n, ki); @@ -1104,7 +1096,7 @@ static node234 *join234_internal(node234 *left, void *sep, return root; } -static int height234(tree234 *t) { +int height234(tree234 *t) { int level = 0; node234 *n = t->root; while (n) { @@ -1452,749 +1444,3 @@ tree234 *copytree234(tree234 *t, copyfn234 copyfn, void *copyfnstate) { return t2; } - -#ifdef TEST - -/* - * Test code for the 2-3-4 tree. This code maintains an alternative - * representation of the data in the tree, in an array (using the - * obvious and slow insert and delete functions). After each tree - * operation, the verify() function is called, which ensures all - * the tree properties are preserved: - * - node->child->parent always equals node - * - tree->root->parent always equals NULL - * - number of kids == 0 or number of elements + 1; - * - tree has the same depth everywhere - * - every node has at least one element - * - subtree element counts are accurate - * - any NULL kid pointer is accompanied by a zero count - * - in a sorted tree: ordering property between elements of a - * node and elements of its children is preserved - * and also ensures the list represented by the tree is the same - * list it should be. (This last check also doubly verifies the - * ordering properties, because the `same list it should be' is by - * definition correctly ordered. It also ensures all nodes are - * distinct, because the enum functions would get caught in a loop - * if not.) - */ - -#include -#include - -#define srealloc realloc - -/* - * Error reporting function. - */ -void error(char *fmt, ...) { - va_list ap; - printf("ERROR: "); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - printf("\n"); -} - -/* The array representation of the data. */ -void **array; -int arraylen, arraysize; -cmpfn234 cmp; - -/* The tree representation of the same data. */ -tree234 *tree; - -/* - * Routines to provide a diagnostic printout of a tree. Currently - * relies on every element in the tree being a one-character string - * :-) - */ -typedef struct { - char **levels; -} dispctx; - -int dispnode(node234 *n, int level, dispctx *ctx) { - if (level == 0) { - int xpos = strlen(ctx->levels[0]); - int len; - - if (n->elems[2]) - len = sprintf(ctx->levels[0]+xpos, " %s%s%s", - n->elems[0], n->elems[1], n->elems[2]); - else if (n->elems[1]) - len = sprintf(ctx->levels[0]+xpos, " %s%s", - n->elems[0], n->elems[1]); - else - len = sprintf(ctx->levels[0]+xpos, " %s", - n->elems[0]); - return xpos + 1 + (len-1) / 2; - } else { - int xpos[4], nkids; - int nodelen, mypos, myleft, x, i; - - xpos[0] = dispnode(n->kids[0], level-3, ctx); - xpos[1] = dispnode(n->kids[1], level-3, ctx); - nkids = 2; - if (n->kids[2]) { - xpos[2] = dispnode(n->kids[2], level-3, ctx); - nkids = 3; - } - if (n->kids[3]) { - xpos[3] = dispnode(n->kids[3], level-3, ctx); - nkids = 4; - } - - if (nkids == 4) - mypos = (xpos[1] + xpos[2]) / 2; - else if (nkids == 3) - mypos = xpos[1]; - else - mypos = (xpos[0] + xpos[1]) / 2; - nodelen = nkids * 2 - 1; - myleft = mypos - ((nodelen-1)/2); - assert(myleft >= xpos[0]); - assert(myleft + nodelen-1 <= xpos[nkids-1]); - - x = strlen(ctx->levels[level]); - while (x <= xpos[0] && x < myleft) - ctx->levels[level][x++] = ' '; - while (x < myleft) - ctx->levels[level][x++] = '_'; - if (nkids==4) - x += sprintf(ctx->levels[level]+x, ".%s.%s.%s.", - n->elems[0], n->elems[1], n->elems[2]); - else if (nkids==3) - x += sprintf(ctx->levels[level]+x, ".%s.%s.", - n->elems[0], n->elems[1]); - else - x += sprintf(ctx->levels[level]+x, ".%s.", - n->elems[0]); - while (x < xpos[nkids-1]) - ctx->levels[level][x++] = '_'; - ctx->levels[level][x] = '\0'; - - x = strlen(ctx->levels[level-1]); - for (i = 0; i < nkids; i++) { - int rpos, pos; - rpos = xpos[i]; - if (i > 0 && i < nkids-1) - pos = myleft + 2*i; - else - pos = rpos; - if (rpos < pos) - rpos++; - while (x < pos && x < rpos) - ctx->levels[level-1][x++] = ' '; - if (x == pos) - ctx->levels[level-1][x++] = '|'; - while (x < pos || x < rpos) - ctx->levels[level-1][x++] = '_'; - if (x == pos) - ctx->levels[level-1][x++] = '|'; - } - ctx->levels[level-1][x] = '\0'; - - x = strlen(ctx->levels[level-2]); - for (i = 0; i < nkids; i++) { - int rpos = xpos[i]; - - while (x < rpos) - ctx->levels[level-2][x++] = ' '; - ctx->levels[level-2][x++] = '|'; - } - ctx->levels[level-2][x] = '\0'; - - return mypos; - } -} - -void disptree(tree234 *t) { - dispctx ctx; - char *leveldata; - int width = count234(t); - int ht = height234(t) * 3 - 2; - int i; - - if (!t->root) { - printf("[empty tree]\n"); - } - - leveldata = smalloc(ht * (width+2)); - ctx.levels = smalloc(ht * sizeof(char *)); - for (i = 0; i < ht; i++) { - ctx.levels[i] = leveldata + i * (width+2); - ctx.levels[i][0] = '\0'; - } - - (void) dispnode(t->root, ht-1, &ctx); - - for (i = ht; i-- ;) - printf("%s\n", ctx.levels[i]); - - sfree(ctx.levels); - sfree(leveldata); -} - -typedef struct { - int treedepth; - int elemcount; -} chkctx; - -int chknode(chkctx *ctx, int level, node234 *node, - void *lowbound, void *highbound) { - int nkids, nelems; - int i; - int count; - - /* Count the non-NULL kids. */ - for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++); - /* Ensure no kids beyond the first NULL are non-NULL. */ - for (i = nkids; i < 4; i++) - if (node->kids[i]) { - error("node %p: nkids=%d but kids[%d] non-NULL", - node, nkids, i); - } else if (node->counts[i]) { - error("node %p: kids[%d] NULL but count[%d]=%d nonzero", - node, i, i, node->counts[i]); - } - - /* Count the non-NULL elements. */ - for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++); - /* Ensure no elements beyond the first NULL are non-NULL. */ - for (i = nelems; i < 3; i++) - if (node->elems[i]) { - error("node %p: nelems=%d but elems[%d] non-NULL", - node, nelems, i); - } - - if (nkids == 0) { - /* - * If nkids==0, this is a leaf node; verify that the tree - * depth is the same everywhere. - */ - if (ctx->treedepth < 0) - ctx->treedepth = level; /* we didn't know the depth yet */ - else if (ctx->treedepth != level) - error("node %p: leaf at depth %d, previously seen depth %d", - node, level, ctx->treedepth); - } else { - /* - * If nkids != 0, then it should be nelems+1, unless nelems - * is 0 in which case nkids should also be 0 (and so we - * shouldn't be in this condition at all). - */ - int shouldkids = (nelems ? nelems+1 : 0); - if (nkids != shouldkids) { - error("node %p: %d elems should mean %d kids but has %d", - node, nelems, shouldkids, nkids); - } - } - - /* - * nelems should be at least 1. - */ - if (nelems == 0) { - error("node %p: no elems", node, nkids); - } - - /* - * Add nelems to the running element count of the whole tree. - */ - ctx->elemcount += nelems; - - /* - * Check ordering property: all elements should be strictly > - * lowbound, strictly < highbound, and strictly < each other in - * sequence. (lowbound and highbound are NULL at edges of tree - * - both NULL at root node - and NULL is considered to be < - * everything and > everything. IYSWIM.) - */ - if (cmp) { - for (i = -1; i < nelems; i++) { - void *lower = (i == -1 ? lowbound : node->elems[i]); - void *higher = (i+1 == nelems ? highbound : node->elems[i+1]); - if (lower && higher && cmp(lower, higher) >= 0) { - error("node %p: kid comparison [%d=%s,%d=%s] failed", - node, i, lower, i+1, higher); - } - } - } - - /* - * Check parent pointers: all non-NULL kids should have a - * parent pointer coming back to this node. - */ - for (i = 0; i < nkids; i++) - if (node->kids[i]->parent != node) { - error("node %p kid %d: parent ptr is %p not %p", - node, i, node->kids[i]->parent, node); - } - - - /* - * Now (finally!) recurse into subtrees. - */ - count = nelems; - - for (i = 0; i < nkids; i++) { - void *lower = (i == 0 ? lowbound : node->elems[i-1]); - void *higher = (i >= nelems ? highbound : node->elems[i]); - int subcount = chknode(ctx, level+1, node->kids[i], lower, higher); - if (node->counts[i] != subcount) { - error("node %p kid %d: count says %d, subtree really has %d", - node, i, node->counts[i], subcount); - } - count += subcount; - } - - return count; -} - -void verifytree(tree234 *tree, void **array, int arraylen) { - chkctx ctx; - int i; - void *p; - - ctx.treedepth = -1; /* depth unknown yet */ - ctx.elemcount = 0; /* no elements seen yet */ - /* - * Verify validity of tree properties. - */ - if (tree->root) { - if (tree->root->parent != NULL) - error("root->parent is %p should be null", tree->root->parent); - chknode(&ctx, 0, tree->root, NULL, NULL); - } - printf("tree depth: %d\n", ctx.treedepth); - /* - * Enumerate the tree and ensure it matches up to the array. - */ - for (i = 0; NULL != (p = index234(tree, i)); i++) { - if (i >= arraylen) - error("tree contains more than %d elements", arraylen); - if (array[i] != p) - error("enum at position %d: array says %s, tree says %s", - i, array[i], p); - } - if (ctx.elemcount != i) { - error("tree really contains %d elements, enum gave %d", - ctx.elemcount, i); - } - if (i < arraylen) { - error("enum gave only %d elements, array has %d", i, arraylen); - } - i = count234(tree); - if (ctx.elemcount != i) { - error("tree really contains %d elements, count234 gave %d", - ctx.elemcount, i); - } -} -void verify(void) { verifytree(tree, array, arraylen); } - -void internal_addtest(void *elem, int index, void *realret) { - int i, j; - void *retval; - - if (arraysize < arraylen+1) { - arraysize = arraylen+1+256; - array = (array == NULL ? smalloc(arraysize*sizeof(*array)) : - srealloc(array, arraysize*sizeof(*array))); - } - - i = index; - /* now i points to the first element >= elem */ - retval = elem; /* expect elem returned (success) */ - for (j = arraylen; j > i; j--) - array[j] = array[j-1]; - array[i] = elem; /* add elem to array */ - arraylen++; - - if (realret != retval) { - error("add: retval was %p expected %p", realret, retval); - } - - verify(); -} - -void addtest(void *elem) { - int i; - void *realret; - - realret = add234(tree, elem); - - i = 0; - while (i < arraylen && cmp(elem, array[i]) > 0) - i++; - if (i < arraylen && !cmp(elem, array[i])) { - void *retval = array[i]; /* expect that returned not elem */ - if (realret != retval) { - error("add: retval was %p expected %p", realret, retval); - } - } else - internal_addtest(elem, i, realret); -} - -void addpostest(void *elem, int i) { - void *realret; - - realret = addpos234(tree, elem, i); - - internal_addtest(elem, i, realret); -} - -void delpostest(int i) { - int index = i; - void *elem = array[i], *ret; - - /* i points to the right element */ - while (i < arraylen-1) { - array[i] = array[i+1]; - i++; - } - arraylen--; /* delete elem from array */ - - if (tree->cmp) - ret = del234(tree, elem); - else - ret = delpos234(tree, index); - - if (ret != elem) { - error("del returned %p, expected %p", ret, elem); - } - - verify(); -} - -void deltest(void *elem) { - int i; - - i = 0; - while (i < arraylen && cmp(elem, array[i]) > 0) - i++; - if (i >= arraylen || cmp(elem, array[i]) != 0) - return; /* don't do it! */ - delpostest(i); -} - -/* A sample data set and test utility. Designed for pseudo-randomness, - * and yet repeatability. */ - -/* - * This random number generator uses the `portable implementation' - * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits; - * change it if not. - */ -int randomnumber(unsigned *seed) { - *seed *= 1103515245; - *seed += 12345; - return ((*seed) / 65536) % 32768; -} - -int mycmp(void *av, void *bv) { - char const *a = (char const *)av; - char const *b = (char const *)bv; - return strcmp(a, b); -} - -char *strings[] = { - "0", "2", "3", "I", "K", "d", "H", "J", "Q", "N", "n", "q", "j", "i", - "7", "G", "F", "D", "b", "x", "g", "B", "e", "v", "V", "T", "f", "E", - "S", "8", "A", "k", "X", "p", "C", "R", "a", "o", "r", "O", "Z", "u", - "6", "1", "w", "L", "P", "M", "c", "U", "h", "9", "t", "5", "W", "Y", - "m", "s", "l", "4", -#if 0 - "a", "ab", "absque", "coram", "de", - "palam", "clam", "cum", "ex", "e", - "sine", "tenus", "pro", "prae", - "banana", "carrot", "cabbage", "broccoli", "onion", "zebra", - "penguin", "blancmange", "pangolin", "whale", "hedgehog", - "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux", - "murfl", "spoo", "breen", "flarn", "octothorpe", - "snail", "tiger", "elephant", "octopus", "warthog", "armadillo", - "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin", - "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper", - "wand", "ring", "amulet" -#endif -}; - -#define NSTR lenof(strings) - -void findtest(void) { - static const int rels[] = { - REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT - }; - static const char *const relnames[] = { - "EQ", "GE", "LE", "LT", "GT" - }; - int i, j, rel, index; - char *p, *ret, *realret, *realret2; - int lo, hi, mid, c; - - for (i = 0; i < (int)NSTR; i++) { - p = strings[i]; - for (j = 0; j < (int)(sizeof(rels)/sizeof(*rels)); j++) { - rel = rels[j]; - - lo = 0; hi = arraylen-1; - while (lo <= hi) { - mid = (lo + hi) / 2; - c = strcmp(p, array[mid]); - if (c < 0) - hi = mid-1; - else if (c > 0) - lo = mid+1; - else - break; - } - - if (c == 0) { - if (rel == REL234_LT) - ret = (mid > 0 ? array[--mid] : NULL); - else if (rel == REL234_GT) - ret = (mid < arraylen-1 ? array[++mid] : NULL); - else - ret = array[mid]; - } else { - assert(lo == hi+1); - if (rel == REL234_LT || rel == REL234_LE) { - mid = hi; - ret = (hi >= 0 ? array[hi] : NULL); - } else if (rel == REL234_GT || rel == REL234_GE) { - mid = lo; - ret = (lo < arraylen ? array[lo] : NULL); - } else - ret = NULL; - } - - realret = findrelpos234(tree, p, NULL, rel, &index); - if (realret != ret) { - error("find(\"%s\",%s) gave %s should be %s", - p, relnames[j], realret, ret); - } - if (realret && index != mid) { - error("find(\"%s\",%s) gave %d should be %d", - p, relnames[j], index, mid); - } - if (realret && rel == REL234_EQ) { - realret2 = index234(tree, index); - if (realret2 != realret) { - error("find(\"%s\",%s) gave %s(%d) but %d -> %s", - p, relnames[j], realret, index, index, realret2); - } - } -#if 0 - printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j], - realret, index); -#endif - } - } - - realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index); - if (arraylen && (realret != array[0] || index != 0)) { - error("find(NULL,GT) gave %s(%d) should be %s(0)", - realret, index, array[0]); - } else if (!arraylen && (realret != NULL)) { - error("find(NULL,GT) gave %s(%d) should be NULL", - realret, index); - } - - realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index); - if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) { - error("find(NULL,LT) gave %s(%d) should be %s(0)", - realret, index, array[arraylen-1]); - } else if (!arraylen && (realret != NULL)) { - error("find(NULL,LT) gave %s(%d) should be NULL", - realret, index); - } -} - -void splittest(tree234 *tree, void **array, int arraylen) { - int i; - tree234 *tree3, *tree4; - for (i = 0; i <= arraylen; i++) { - tree3 = copytree234(tree, NULL, NULL); - tree4 = splitpos234(tree3, i, false); - verifytree(tree3, array, i); - verifytree(tree4, array+i, arraylen-i); - join234(tree3, tree4); - freetree234(tree4); /* left empty by join */ - verifytree(tree3, array, arraylen); - freetree234(tree3); - } -} - -int main(void) { - int in[NSTR]; - int i, j, k; - int tworoot, tmplen; - unsigned seed = 0; - tree234 *tree2, *tree3, *tree4; - int c; - - setvbuf(stdout, NULL, _IOLBF, 0); - - for (i = 0; i < (int)NSTR; i++) in[i] = 0; - array = NULL; - arraylen = arraysize = 0; - tree = newtree234(mycmp); - cmp = mycmp; - - verify(); - for (i = 0; i < 10000; i++) { - j = randomnumber(&seed); - j %= NSTR; - printf("trial: %d\n", i); - if (in[j]) { - printf("deleting %s (%d)\n", strings[j], j); - deltest(strings[j]); - in[j] = 0; - } else { - printf("adding %s (%d)\n", strings[j], j); - addtest(strings[j]); - in[j] = 1; - } - disptree(tree); - findtest(); - } - - while (arraylen > 0) { - j = randomnumber(&seed); - j %= arraylen; - deltest(array[j]); - } - - freetree234(tree); - - /* - * Now try an unsorted tree. We don't really need to test - * delpos234 because we know del234 is based on it, so it's - * already been tested in the above sorted-tree code; but for - * completeness we'll use it to tear down our unsorted tree - * once we've built it. - */ - tree = newtree234(NULL); - cmp = NULL; - verify(); - for (i = 0; i < 1000; i++) { - printf("trial: %d\n", i); - j = randomnumber(&seed); - j %= NSTR; - k = randomnumber(&seed); - k %= count234(tree)+1; - printf("adding string %s at index %d\n", strings[j], k); - addpostest(strings[j], k); - } - - /* - * While we have this tree in its full form, we'll take a copy - * of it to use in split and join testing. - */ - tree2 = copytree234(tree, NULL, NULL); - verifytree(tree2, array, arraylen);/* check the copy is accurate */ - /* - * Split tests. Split the tree at every possible point and - * check the resulting subtrees. - */ - tworoot = (!tree2->root->elems[1]);/* see if it has a 2-root */ - splittest(tree2, array, arraylen); - /* - * Now do the split test again, but on a tree that has a 2-root - * (if the previous one didn't) or doesn't (if the previous one - * did). - */ - tmplen = arraylen; - while ((!tree2->root->elems[1]) == tworoot) { - delpos234(tree2, --tmplen); - } - printf("now trying splits on second tree\n"); - splittest(tree2, array, tmplen); - freetree234(tree2); - - /* - * Back to the main testing of uncounted trees. - */ - while (count234(tree) > 0) { - printf("cleanup: tree size %d\n", count234(tree)); - j = randomnumber(&seed); - j %= count234(tree); - printf("deleting string %s from index %d\n", (char *)array[j], j); - delpostest(j); - } - freetree234(tree); - - /* - * Finally, do some testing on split/join on _sorted_ trees. At - * the same time, we'll be testing split on very small trees. - */ - tree = newtree234(mycmp); - cmp = mycmp; - arraylen = 0; - for (i = 0; i < 17; i++) { - tree2 = copytree234(tree, NULL, NULL); - splittest(tree2, array, arraylen); - freetree234(tree2); - if (i < 16) - addtest(strings[i]); - } - freetree234(tree); - - /* - * Test silly cases of join: join(emptytree, emptytree), and - * also ensure join correctly spots when sorted trees fail the - * ordering constraint. - */ - tree = newtree234(mycmp); - tree2 = newtree234(mycmp); - tree3 = newtree234(mycmp); - tree4 = newtree234(mycmp); - assert(mycmp(strings[0], strings[1]) < 0); /* just in case :-) */ - add234(tree2, strings[1]); - add234(tree4, strings[0]); - array[0] = strings[0]; - array[1] = strings[1]; - verifytree(tree, array, 0); - verifytree(tree2, array+1, 1); - verifytree(tree3, array, 0); - verifytree(tree4, array, 1); - - /* - * So: - * - join(tree,tree3) should leave both tree and tree3 unchanged. - * - joinr(tree,tree2) should leave both tree and tree2 unchanged. - * - join(tree4,tree3) should leave both tree3 and tree4 unchanged. - * - join(tree, tree2) should move the element from tree2 to tree. - * - joinr(tree4, tree3) should move the element from tree4 to tree3. - * - join(tree,tree3) should return NULL and leave both unchanged. - * - join(tree3,tree) should work and create a bigger tree in tree3. - */ - assert(tree == join234(tree, tree3)); - verifytree(tree, array, 0); - verifytree(tree3, array, 0); - assert(tree2 == join234r(tree, tree2)); - verifytree(tree, array, 0); - verifytree(tree2, array+1, 1); - assert(tree4 == join234(tree4, tree3)); - verifytree(tree3, array, 0); - verifytree(tree4, array, 1); - assert(tree == join234(tree, tree2)); - verifytree(tree, array+1, 1); - verifytree(tree2, array, 0); - assert(tree3 == join234r(tree4, tree3)); - verifytree(tree3, array, 1); - verifytree(tree4, array, 0); - assert(NULL == join234(tree, tree3)); - verifytree(tree, array+1, 1); - verifytree(tree3, array, 1); - assert(tree3 == join234(tree3, tree)); - verifytree(tree3, array, 2); - verifytree(tree, array, 0); - - return 0; -} - -#endif - -#if 0 /* sorted list of strings might be useful */ -{ - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", -} -#endif diff --git a/apps/plugins/puzzles/src/tree234.h b/apps/plugins/puzzles/src/tree234.h index ccd943d69d..b58f939a0a 100644 --- a/apps/plugins/puzzles/src/tree234.h +++ b/apps/plugins/puzzles/src/tree234.h @@ -31,7 +31,11 @@ #include /* - * This typedef is opaque outside tree234.c itself. + * This typedef is typically opaque outside tree234.c itself. But you + * can define TREE234_INTERNALS to get a definition of it and its + * subsidiary node structure, as long as you're prepared to commit to + * responding to changes in the internals (which probably means you're + * tree234.c itself or tree234-test.c). */ typedef struct tree234_Tag tree234; @@ -39,6 +43,24 @@ typedef int (*cmpfn234)(void *, void *); typedef void *(*copyfn234)(void *state, void *element); +#ifdef TREE234_INTERNALS +typedef struct node234_Tag node234; + +struct tree234_Tag { + node234 *root; + cmpfn234 cmp; +}; + +struct node234_Tag { + node234 *parent; + node234 *kids[4]; + int counts[4]; + void *elems[3]; +}; + +int height234(tree234 *t); +#endif + /* * Create a 2-3-4 tree. If `cmp' is NULL, the tree is unsorted, and * lookups by key will fail: you can only look things up by numeric diff --git a/apps/plugins/puzzles/src/twiddle.R b/apps/plugins/puzzles/src/twiddle.R deleted file mode 100644 index 1495c33181..0000000000 --- a/apps/plugins/puzzles/src/twiddle.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -twiddle : [X] GTK COMMON twiddle twiddle-icon|no-icon - -twiddle : [G] WINDOWS COMMON twiddle twiddle.res|noicon.res - -ALL += twiddle[COMBINED] - -!begin am gtk -GAMES += twiddle -!end - -!begin >list.c - A(twiddle) \ -!end - -!begin >gamedesc.txt -twiddle:twiddle.exe:Twiddle:Rotational sliding block puzzle:Rotate the tiles around themselves to arrange them into order. -!end diff --git a/apps/plugins/puzzles/src/twiddle.c b/apps/plugins/puzzles/src/twiddle.c index a107925aee..b3aa06f1d5 100644 --- a/apps/plugins/puzzles/src/twiddle.c +++ b/apps/plugins/puzzles/src/twiddle.c @@ -10,7 +10,12 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -123,14 +128,16 @@ static void decode_params(game_params *ret, char const *string) while (*string) { if (*string == 'r') { ret->rowsonly = true; + string++; } else if (*string == 'o') { ret->orientable = true; + string++; } else if (*string == 'm') { string++; ret->movetarget = atoi(string); - while (string[1] && isdigit((unsigned char)string[1])) string++; - } - string++; + while (*string && isdigit((unsigned char)*string)) string++; + } else + string++; } } @@ -210,6 +217,8 @@ static const char *validate_params(const game_params *params, bool full) return "Width must be at least the rotating block size"; if (params->h < params->n) return "Height must be at least the rotating block size"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; if (params->movetarget < 0) return "Number of shuffling moves may not be negative"; return NULL; @@ -615,7 +624,7 @@ static game_ui *new_ui(const game_state *state) ui->cur_x = 0; ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -625,18 +634,20 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + if (!ui->cur_visible) return ""; + switch (button) { + case CURSOR_SELECT: return "Turn left"; + case CURSOR_SELECT2: return "Turn right"; + } + return ""; } struct game_drawstate { @@ -657,18 +668,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, button = button & (~MOD_MASK | MOD_NUM_KEYPAD); - if (IS_CURSOR_MOVE(button)) { - if (button == CURSOR_LEFT && ui->cur_x > 0) - ui->cur_x--; - if (button == CURSOR_RIGHT && (ui->cur_x+n) < (w)) - ui->cur_x++; - if (button == CURSOR_UP && ui->cur_y > 0) - ui->cur_y--; - if (button == CURSOR_DOWN && (ui->cur_y+n) < (h)) - ui->cur_y++; - ui->cur_visible = true; - return UI_UPDATE; - } + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cur_x, &ui->cur_y, w-n+1, h-n+1, + false, &ui->cur_visible); if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { /* @@ -691,7 +693,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, dir = (button == CURSOR_SELECT2) ? -1 : +1; } else { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (button == 'a' || button == 'A' || button==MOD_NUM_KEYPAD+'7') { x = y = 0; @@ -791,7 +793,7 @@ static game_state *execute_move(const game_state *from, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -870,8 +872,8 @@ static void rotate(int *xy, struct rotation *rot) xf2 = rot->c * xf + rot->s * yf; yf2 = - rot->s * xf + rot->c * yf; - xy[0] = (int)(xf2 + rot->ox + 0.5); /* round to nearest */ - xy[1] = (int)(yf2 + rot->oy + 0.5); /* round to nearest */ + xy[0] = (int)(xf2 + rot->ox + 0.5F); /* round to nearest */ + xy[1] = (int)(yf2 + rot->oy + 0.5F); /* round to nearest */ } } @@ -1058,7 +1060,7 @@ static int highlight_colour(float angle) COL_LOWLIGHT, }; - return colours[(int)((angle + 2*PI) / (PI/16)) & 31]; + return colours[(int)((angle + 2*(float)PI) / ((float)PI/16)) & 31]; } static float game_anim_length_real(const game_state *oldstate, @@ -1135,13 +1137,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, if (!ds->started) { int coords[10]; - draw_rect(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND); - draw_update(dr, 0, 0, - TILE_SIZE * state->w + 2 * BORDER, - TILE_SIZE * state->h + 2 * BORDER); - /* * Recessed area containing the whole puzzle. */ @@ -1189,7 +1184,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, rot->cw = rot->ch = TILE_SIZE * state->n; rot->ox = rot->cx + rot->cw/2; rot->oy = rot->cy + rot->ch/2; - angle = (float)((-PI/2 * lastr) * (1.0 - animtime / anim_max)); + angle = ((-(float)PI/2 * lastr) * (1.0F - animtime / anim_max)); rot->c = (float)cos(angle); rot->s = (float)sin(angle); @@ -1282,19 +1277,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame twiddle #endif @@ -1316,12 +1298,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -1333,9 +1317,9 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ true, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/undead.R b/apps/plugins/puzzles/src/undead.R deleted file mode 100644 index 5907ed6b74..0000000000 --- a/apps/plugins/puzzles/src/undead.R +++ /dev/null @@ -1,18 +0,0 @@ -# -*- makefile -*- - -undead : [X] GTK COMMON undead undead-icon|no-icon -undead : [G] WINDOWS COMMON undead undead.res|noicon.res - -ALL += undead[COMBINED] - -!begin am gtk -GAMES += undead -!end - -!begin >list.c - A(undead) \ -!end - -!begin >gamedesc.txt -undead:undead.exe:Undead:Monster-placing puzzle:Place ghosts, vampires and zombies so that the right numbers of them can be seen in mirrors. -!end diff --git a/apps/plugins/puzzles/src/undead.c b/apps/plugins/puzzles/src/undead.c index 4dba828d48..0213d0e2e4 100644 --- a/apps/plugins/puzzles/src/undead.c +++ b/apps/plugins/puzzles/src/undead.c @@ -35,7 +35,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" @@ -193,9 +197,9 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { - if ((params->w * params->h ) > 54) return "Grid is too big"; if (params->w < 3) return "Width must be at least 3"; if (params->h < 3) return "Height must be at least 3"; + if (params->w > 54 / params->h) return "Grid is too big"; if (params->diff >= DIFFCOUNT) return "Unknown difficulty rating"; return NULL; } @@ -972,7 +976,7 @@ static int path_cmp(const void *a, const void *b) { static char *new_game_desc(const game_params *params, random_state *rs, char **aux, bool interactive) { - int i,count,c,w,h,r,p,g; + int count,c,w,h,r,p,g; game_state *new; /* Variables for puzzle generation algorithm */ @@ -993,7 +997,6 @@ static char *new_game_desc(const game_params *params, random_state *rs, char *e; char *desc; - i = 0; while (true) { new = new_state(params); abort = false; @@ -1031,7 +1034,7 @@ static char *new_game_desc(const game_params *params, random_state *rs, /* Monsters / Mirrors ratio should be balanced */ ratio = (float)new->common->num_total / (float)(new->common->params.w * new->common->params.h); - if (ratio < 0.48 || ratio > 0.78) { + if (ratio < 0.48F || ratio > 0.78F) { free_game(new); continue; } @@ -1253,7 +1256,6 @@ static char *new_game_desc(const game_params *params, random_state *rs, * difficulty level, free memory and start from scratch */ sfree(old_guess); free_game(new); - i++; } /* We have a valid puzzle! */ @@ -1574,6 +1576,8 @@ static char *solve_game(const game_state *state_start, const game_state *currsta } /* printf("Puzzle solved at level %s, iterations %d, ambiguous %d\n", (solved_bruteforce ? "TRICKY" : "NORMAL"), iterative_depth, count_ambiguous); */ + (void)iterative_depth; + (void)count_ambiguous; move = snewn(solve_state->common->num_total * 4 +2, char); c = move; @@ -1640,31 +1644,64 @@ struct game_ui { int hx, hy; /* as for solo.c, highlight pos */ bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */ bool ascii; + + /* + * User preference option: if the user right-clicks in a square + * and presses a monster key to add/remove a pencil mark, do we + * hide the mouse highlight again afterwards? + * + * Historically our answer was yes. The Android port prefers no. + * There are advantages both ways, depending how much you dislike + * the highlight cluttering your view. So it's a preference. + */ + bool pencil_keep_highlight; }; static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); - ui->hx = ui->hy = 0; ui->hpencil = false; - ui->hshow = false; - ui->hcursor = false; + ui->hx = ui->hy = ui->hshow = ui->hcursor = + getenv_bool("PUZZLES_SHOW_CURSOR", false); ui->ascii = false; + + ui->pencil_keep_highlight = false; + return ui; } -static void free_ui(game_ui *ui) { - sfree(ui); - return; +static config_item *get_prefs(game_ui *ui) +{ + config_item *ret; + + ret = snewn(3, config_item); + + ret[0].name = "Keep mouse highlight after changing a pencil mark"; + ret[0].kw = "pencil-keep-highlight"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->pencil_keep_highlight; + + ret[1].name = "Monster representation"; + ret[1].kw = "monsters"; + ret[1].type = C_CHOICES; + ret[1].u.choices.choicenames = ":Pictures:Letters"; + ret[1].u.choices.choicekws = ":pictures:letters"; + ret[1].u.choices.selected = ui->ascii; + + ret[2].name = NULL; + ret[2].type = C_END; + + return ret; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->pencil_keep_highlight = cfg[0].u.boolean.bval; + ui->ascii = cfg[1].u.choices.selected; } -static void decode_ui(game_ui *ui, const char *encoding) -{ +static void free_ui(game_ui *ui) { + sfree(ui); return; } @@ -1681,6 +1718,20 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int xi; + + if (ui->hshow && button == CURSOR_SELECT) + return ui->hpencil ? "Ink" : "Pencil"; + if (button == CURSOR_SELECT2) { + xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)]; + if (xi >= 0 && !state->common->fixed[xi]) return "Clear"; + } + return ""; +} + struct game_drawstate { int tilesize; bool started, solved; @@ -1743,7 +1794,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (button == 'a' || button == 'A') { ui->ascii = !ui->ascii; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == 'm' || button == 'M') { @@ -1755,22 +1806,30 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (xi >= 0 && !state->common->fixed[xi]) { if (button == 'g' || button == 'G' || button == '1') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 1) + return ui->hcursor ? NULL : MOVE_UI_UPDATE; sprintf(buf,"G%d",xi); return dupstr(buf); } if (button == 'v' || button == 'V' || button == '2') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 2) + return ui->hcursor ? NULL : MOVE_UI_UPDATE; sprintf(buf,"V%d",xi); return dupstr(buf); } if (button == 'z' || button == 'Z' || button == '3') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 4) + return ui->hcursor ? NULL : MOVE_UI_UPDATE; sprintf(buf,"Z%d",xi); return dupstr(buf); } if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || button == '0' || button == '\b' ) { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 7 && state->pencils[xi] == 0) + return ui->hcursor ? NULL : MOVE_UI_UPDATE; sprintf(buf,"E%d",xi); return dupstr(buf); } @@ -1790,45 +1849,42 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->hshow = true; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->hshow && button == CURSOR_SELECT) { ui->hpencil = !ui->hpencil; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (ui->hshow && ui->hpencil) { xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)]; if (xi >= 0 && !state->common->fixed[xi]) { + buf[0] = '\0'; + if (button == 'g' || button == 'G' || button == '1') { sprintf(buf,"g%d",xi); - if (!ui->hcursor) { - ui->hpencil = false; - ui->hshow = false; - } - return dupstr(buf); - } - if (button == 'v' || button == 'V' || button == '2') { + } else if (button == 'v' || button == 'V' || button == '2') { sprintf(buf,"v%d",xi); - if (!ui->hcursor) { - ui->hpencil = false; - ui->hshow = false; - } - return dupstr(buf); - } - if (button == 'z' || button == 'Z' || button == '3') { + } else if (button == 'z' || button == 'Z' || button == '3') { sprintf(buf,"z%d",xi); - if (!ui->hcursor) { - ui->hpencil = false; - ui->hshow = false; - } - return dupstr(buf); - } - if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || - button == '0' || button == '\b') { + } else if (button == 'e' || button == 'E' || + button == CURSOR_SELECT2 || button == '0' || + button == '\b') { + if (state->pencils[xi] == 0) + return ui->hcursor ? NULL : MOVE_UI_UPDATE; sprintf(buf,"E%d",xi); - if (!ui->hcursor) { + } + + if (buf[0]) { + /* + * Hide the highlight after a keypress, if it was mouse- + * generated. Also, don't hide it if this move has changed + * pencil marks and the user preference says not to hide the + * highlight in that situation. + */ + if (!ui->hcursor && + !(ui->hpencil && ui->pencil_keep_highlight)) { ui->hpencil = false; ui->hshow = false; } @@ -1847,14 +1903,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (button == RIGHT_BUTTON && g == 7) { ui->hshow = true; ui->hpencil = true; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (ui->hshow) { @@ -1865,14 +1921,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; ui->hcursor = false; ui->hx = 0; ui->hy = 0; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { ui->hshow = true; ui->hpencil = false; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else { @@ -1880,7 +1936,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } else if (button == RIGHT_BUTTON) { @@ -1889,7 +1945,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = true; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else { if (gx == ui->hx && gy == ui->hy) { @@ -1897,14 +1953,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hpencil = false; ui->hcursor = false; ui->hx = 0; ui->hy = 0; - return UI_UPDATE; + return MOVE_UI_UPDATE; } else if (g == 7) { ui->hshow = true; ui->hpencil = true; ui->hcursor = false; ui->hx = gx; ui->hy = gy; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } } @@ -2056,11 +2112,11 @@ static game_state *execute_move(const game_state *state, const char *move) if (c == 'S') { move++; solver = true; - } - if (c == 'G' || c == 'V' || c == 'Z' || c == 'E' || - c == 'g' || c == 'v' || c == 'z') { + } else if (c == 'G' || c == 'V' || c == 'Z' || c == 'E' || + c == 'g' || c == 'v' || c == 'z') { move++; - sscanf(move, "%d%n", &x, &n); + if (sscanf(move, "%d%n", &x, &n) != 1) goto badmove; + if (x < 0 || x >= ret->common->num_total) goto badmove; if (c == 'G') ret->guess[x] = 1; if (c == 'V') ret->guess[x] = 2; if (c == 'Z') ret->guess[x] = 4; @@ -2069,23 +2125,26 @@ static game_state *execute_move(const game_state *state, const char *move) if (c == 'v') ret->pencils[x] ^= 2; if (c == 'z') ret->pencils[x] ^= 4; move += n; - } - if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 && - is_clue(ret, x, y)) { + } else if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 && + is_clue(ret, x, y)) { ret->hints_done[clue_index(ret, x, y)] ^= 1; move += n + 1; - } - if (c == 'M') { + } else if (c == 'M') { /* * Fill in absolutely all pencil marks in unfilled * squares, for those who like to play by the rigorous * approach of starting off in that state and eliminating * things. */ - for (i = 0; i < ret->common->wh; i++) + for (i = 0; i < ret->common->num_total; i++) if (ret->guess[i] == 7) ret->pencils[i] = 7; move++; + } else { + /* Unknown move type. */ + badmove: + free_game(ret); + return NULL; } if (*move == ';') move++; } @@ -2118,7 +2177,7 @@ static game_state *execute_move(const game_state *state, const char *move) #define PREFERRED_TILE_SIZE 64 static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2402,7 +2461,7 @@ static void draw_monster(drawing *dr, game_drawstate *ds, int x, int y, static void draw_monster_count(drawing *dr, game_drawstate *ds, const game_state *state, int c, bool hflash) { int dx,dy; - char buf[8]; + char buf[MAX_DIGITS(int) + 1]; char bufm[8]; dy = TILESIZE/4; @@ -2447,7 +2506,7 @@ static void draw_path_hint(drawing *dr, game_drawstate *ds, const struct game_params *params, int hint_index, bool hflash, int hint) { int x, y, color, dx, dy, text_dx, text_dy, text_size; - char buf[4]; + char buf[MAX_DIGITS(int) + 1]; if (ds->hint_errors[hint_index]) color = COL_ERROR; @@ -2605,8 +2664,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, /* Draw static grid components at startup */ if (!ds->started) { - draw_rect(dr, 0, 0, 2*BORDER+(ds->w+2)*TILESIZE, - 2*BORDER+(ds->h+3)*TILESIZE, COL_BACKGROUND); draw_rect(dr, BORDER+TILESIZE-1, BORDER+2*TILESIZE-1, (ds->w)*TILESIZE +3, (ds->h)*TILESIZE +3, COL_GRID); for (i=0;iw;i++) @@ -2745,19 +2802,6 @@ static int game_status(const game_state *state) return state->solved; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame undead #endif @@ -2779,12 +2823,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2796,8 +2842,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; diff --git a/apps/plugins/puzzles/src/unequal.R b/apps/plugins/puzzles/src/unequal.R deleted file mode 100644 index 077407ffff..0000000000 --- a/apps/plugins/puzzles/src/unequal.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -UNEQUAL_EXTRA = LATIN -UNEQUAL_EXTRA_SOLVER = LATIN_SOLVER - -unequal : [X] GTK COMMON unequal UNEQUAL_EXTRA unequal-icon|no-icon - -unequal : [G] WINDOWS COMMON unequal UNEQUAL_EXTRA unequal.res|noicon.res - -unequalsolver : [U] unequal[STANDALONE_SOLVER] UNEQUAL_EXTRA_SOLVER STANDALONE -unequalsolver : [C] unequal[STANDALONE_SOLVER] UNEQUAL_EXTRA_SOLVER STANDALONE - -ALL += unequal[COMBINED] UNEQUAL_EXTRA - -!begin am gtk -GAMES += unequal -!end - -!begin >list.c - A(unequal) \ -!end - -!begin >gamedesc.txt -unequal:unequal.exe:Unequal:Latin square puzzle:Complete the latin square in accordance with the > signs. -!end diff --git a/apps/plugins/puzzles/src/unequal.c b/apps/plugins/puzzles/src/unequal.c index 153954e510..ab32e4ab79 100644 --- a/apps/plugins/puzzles/src/unequal.c +++ b/apps/plugins/puzzles/src/unequal.c @@ -21,7 +21,11 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #include "latin.h" /* contains typedef for digit */ @@ -84,6 +88,7 @@ struct game_params { #define ADJ_TO_SPENT(x) ((x) << 9) #define F_ERROR_MASK (F_ERROR|F_ERROR_UP|F_ERROR_RIGHT|F_ERROR_DOWN|F_ERROR_LEFT) +#define F_SPENT_MASK (F_SPENT_UP|F_SPENT_RIGHT|F_SPENT_DOWN|F_SPENT_LEFT) struct game_state { int order; @@ -890,13 +895,14 @@ static int solver_state(game_state *state, int maxdiff) struct latin_solver solver; int diff; - latin_solver_alloc(&solver, state->nums, state->order); - - diff = latin_solver_main(&solver, maxdiff, - DIFF_LATIN, DIFF_SET, DIFF_EXTREME, - DIFF_EXTREME, DIFF_RECURSIVE, - unequal_solvers, unequal_valid, ctx, - clone_ctx, free_ctx); + if (latin_solver_alloc(&solver, state->nums, state->order)) + diff = latin_solver_main(&solver, maxdiff, + DIFF_LATIN, DIFF_SET, DIFF_EXTREME, + DIFF_EXTREME, DIFF_RECURSIVE, + unequal_solvers, unequal_valid, ctx, + clone_ctx, free_ctx); + else + diff = DIFF_IMPOSSIBLE; memcpy(state->hints, solver.cube, state->order*state->order*state->order); @@ -1073,7 +1079,7 @@ static int gg_best_clue(game_state *state, int *scratch, digit *latin) } #ifdef STANDALONE_SOLVER -int maxtries; +static int maxtries; #define MAXTRIES maxtries #else #define MAXTRIES 50 @@ -1430,6 +1436,17 @@ static char *solve_game(const game_state *state, const game_state *currstate, struct game_ui { int hx, hy; /* as for solo.c, highlight pos */ bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */ + + /* + * User preference option: if the user right-clicks in a square + * and presses a number key to add/remove a pencil mark, do we + * hide the mouse highlight again afterwards? + * + * Historically our answer was yes. The Android port prefers no. + * There are advantages both ways, depending how much you dislike + * the highlight cluttering your view. So it's a preference. + */ + bool pencil_keep_highlight; }; static game_ui *new_ui(const game_state *state) @@ -1438,8 +1455,9 @@ static game_ui *new_ui(const game_state *state) ui->hx = ui->hy = 0; ui->hpencil = false; - ui->hshow = false; - ui->hcursor = false; + ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); + + ui->pencil_keep_highlight = false; return ui; } @@ -1449,13 +1467,26 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - return NULL; + config_item *ret; + + ret = snewn(2, config_item); + + ret[0].name = "Keep mouse highlight after changing a pencil mark"; + ret[0].kw = "pencil-keep-highlight"; + ret[0].type = C_BOOLEAN; + ret[0].u.boolean.bval = ui->pencil_keep_highlight; + + ret[1].name = NULL; + ret[1].type = C_END; + + return ret; } -static void decode_ui(game_ui *ui, const char *encoding) +static void set_prefs(game_ui *ui, const config_item *cfg) { + ui->pencil_keep_highlight = cfg[0].u.boolean.bval; } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1470,6 +1501,14 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, } } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + if (ui->hshow && IS_CURSOR_SELECT(button)) + return ui->hpencil ? "Ink" : "Pencil"; + return ""; +} + struct game_drawstate { int tilesize, order; bool started; @@ -1491,7 +1530,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char buf[80]; bool shift_or_control = button & (MOD_SHFT | MOD_CTRL); - button &= ~MOD_MASK; + button = STRIP_BUTTON_MODIFIERS(button); if (x >= 0 && x < ds->order && y >= 0 && y < ds->order && IS_MOUSE_DOWN(button)) { if (oy - COORD(y) > TILE_SIZE && ox - COORD(x) > TILE_SIZE) @@ -1527,7 +1566,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hshow = true; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } if (button == RIGHT_BUTTON) { /* pencil highlighting for non-filled squares */ @@ -1541,7 +1580,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->hshow = true; } ui->hcursor = false; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } @@ -1549,7 +1588,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (shift_or_control) { int nx = ui->hx, ny = ui->hy, i; bool self; - move_cursor(button, &nx, &ny, ds->order, ds->order, false); + move_cursor(button, &nx, &ny, ds->order, ds->order, false, NULL); ui->hshow = true; ui->hcursor = true; @@ -1557,12 +1596,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, ny != ui->hy + adjthan[i].dy); ++i); if (i == 4) - return UI_UPDATE; /* invalid direction, i.e. out of + return MOVE_UI_UPDATE; /* invalid direction, i.e. out of * the board */ if (!(GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f || GRID(state, flags, nx, ny ) & adjthan[i].fo)) - return UI_UPDATE; /* no clue to toggle */ + return MOVE_UI_UPDATE; /* no clue to toggle */ if (state->mode == MODE_ADJACENT) self = (adjthan[i].dx >= 0 && adjthan[i].dy >= 0); @@ -1570,24 +1609,23 @@ static char *interpret_move(const game_state *state, game_ui *ui, self = (GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f); if (self) - sprintf(buf, "F%d,%d,%d", ui->hx, ui->hy, + sprintf(buf, "F%d,%d,%u", ui->hx, ui->hy, ADJ_TO_SPENT(adjthan[i].f)); else - sprintf(buf, "F%d,%d,%d", nx, ny, + sprintf(buf, "F%d,%d,%u", nx, ny, ADJ_TO_SPENT(adjthan[i].fo)); return dupstr(buf); } else { - move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, false); - ui->hshow = true; ui->hcursor = true; - return UI_UPDATE; + return move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, + false, &ui->hshow); } } if (ui->hshow && IS_CURSOR_SELECT(button)) { ui->hpencil = !ui->hpencil; ui->hcursor = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } n = c2n(button, state->order); @@ -1604,11 +1642,37 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->hpencil && GRID(state, nums, ui->hx, ui->hy) > 0) return NULL; /* can't change hints on filled square (!) */ + /* + * If you ask to fill a square with what it already contains, + * or blank it when it's already empty, that has no effect... + */ + if ((!ui->hpencil || n == 0) && + GRID(state, nums, ui->hx, ui->hy) == n) { + bool anypencil = false; + int i; + for (i = 0; i < state->order; i++) + anypencil = anypencil || HINT(state, ui->hx, ui->hy, i); + if (!anypencil) { + /* ... expect to remove the cursor in mouse mode. */ + if (!ui->hcursor) { + ui->hshow = false; + return MOVE_UI_UPDATE; + } + return NULL; + } + } sprintf(buf, "%c%d,%d,%d", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); - if (!ui->hcursor) ui->hshow = false; + /* + * Hide the highlight after a keypress, if it was mouse- + * generated. Also, don't hide it if this move has changed + * pencil marks and the user preference says not to hide the + * highlight in that situation. + */ + if (!ui->hcursor && !(ui->hpencil && ui->pencil_keep_highlight)) + ui->hshow = false; return dupstr(buf); } @@ -1624,7 +1688,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, static game_state *execute_move(const game_state *state, const char *move) { game_state *ret = NULL; - int x, y, n, i, rc; + int x, y, n, i; debug(("execute_move: %s", move)); @@ -1649,7 +1713,7 @@ static game_state *execute_move(const game_state *state, const char *move) const char *p; ret = dup_game(state); - ret->completed = ret->cheated = true; + ret->cheated = true; p = move+1; for (i = 0; i < state->order*state->order; i++) { @@ -1660,8 +1724,8 @@ static game_state *execute_move(const game_state *state, const char *move) p++; } if (*p) goto badmove; - rc = check_complete(ret->nums, ret, true); - assert(rc > 0); + if (!ret->completed && check_complete(ret->nums, ret, true) > 0) + ret->completed = true; return ret; } else if (move[0] == 'M') { ret = dup_game(state); @@ -1678,7 +1742,8 @@ static game_state *execute_move(const game_state *state, const char *move) check_complete(ret->nums, ret, true); return ret; } else if (move[0] == 'F' && sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 && - x >= 0 && x < state->order && y >= 0 && y < state->order) { + x >= 0 && x < state->order && y >= 0 && y < state->order && + (n & ~F_SPENT_MASK) == 0) { ret = dup_game(state); GRID(ret, flags, x, y) ^= n; return ret; @@ -1696,7 +1761,7 @@ badmove: #define DRAW_SIZE (TILE_SIZE*ds->order + GAP_SIZE*(ds->order-1) + BORDER*2) static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize, order; } ads, *ds = &ads; @@ -1779,18 +1844,18 @@ static void draw_gt(drawing *dr, int ox, int oy, { int coords[12]; int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0); - coords[0] = ox + xdx + dx1; - coords[1] = oy + xdy + dy1; - coords[2] = ox + xdx + dx1 + dx2; - coords[3] = oy + xdy + dy1 + dy2; - coords[4] = ox - xdx + dx1 + dx2; - coords[5] = oy - xdy + dy1 + dy2; - coords[6] = ox - xdx + dx1; - coords[7] = oy - xdy + dy1; - coords[8] = ox - xdx; - coords[9] = oy - xdy; - coords[10] = ox + xdx; - coords[11] = oy + xdy; + coords[0] = ox + xdx; + coords[1] = oy + xdy; + coords[2] = ox + xdx + dx1; + coords[3] = oy + xdy + dy1; + coords[4] = ox + xdx + dx1 + dx2; + coords[5] = oy + xdy + dy1 + dy2; + coords[6] = ox - xdx + dx1 + dx2; + coords[7] = oy - xdy + dy1 + dy2; + coords[8] = ox - xdx + dx1; + coords[9] = oy - xdy + dy1; + coords[10] = ox - xdx; + coords[11] = oy - xdy; draw_polygon(dr, coords, 6, col, col); } @@ -2059,22 +2124,19 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* 10mm squares by default, roughly the same as Grauniad. */ - game_compute_size(params, 1000, &pw, &ph); + game_compute_size(params, 1000, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int ink = print_mono_colour(dr, 0); int x, y, o = state->order, ox, oy, n; @@ -2133,12 +2195,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ game_request_keys, game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2152,7 +2216,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ }; @@ -2165,7 +2229,7 @@ const struct game thegame = { #include #include -const char *quis = NULL; +static const char *quis = NULL; #if 0 /* currently unused */ @@ -2233,13 +2297,14 @@ static int solve(game_params *p, char *desc, int debug) solver_show_working = debug; game_debug(state); - latin_solver_alloc(&solver, state->nums, state->order); - - diff = latin_solver_main(&solver, DIFF_RECURSIVE, - DIFF_LATIN, DIFF_SET, DIFF_EXTREME, - DIFF_EXTREME, DIFF_RECURSIVE, - unequal_solvers, unequal_valid, ctx, - clone_ctx, free_ctx); + if (latin_solver_alloc(&solver, state->nums, state->order)) + diff = latin_solver_main(&solver, DIFF_RECURSIVE, + DIFF_LATIN, DIFF_SET, DIFF_EXTREME, + DIFF_EXTREME, DIFF_RECURSIVE, + unequal_solvers, unequal_valid, ctx, + clone_ctx, free_ctx); + else + diff = DIFF_IMPOSSIBLE; free_ctx(ctx); diff --git a/apps/plugins/puzzles/src/unruly.R b/apps/plugins/puzzles/src/unruly.R deleted file mode 100644 index 064ccc35ba..0000000000 --- a/apps/plugins/puzzles/src/unruly.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -unruly : [X] GTK COMMON unruly unruly-icon|no-icon -unruly : [G] WINDOWS COMMON unruly unruly.res|noicon.res - -unrulysolver : [U] unruly[STANDALONE_SOLVER] STANDALONE -unrulysolver : [C] unruly[STANDALONE_SOLVER] STANDALONE - -ALL += unruly[COMBINED] - -!begin am gtk -GAMES += unruly -!end - -!begin >list.c - A(unruly) \ -!end - -!begin >gamedesc.txt -unruly:unruly.exe:Unruly:Black and white grid puzzle:Fill in the black and white grid to avoid runs of three. -!end diff --git a/apps/plugins/puzzles/src/unruly.c b/apps/plugins/puzzles/src/unruly.c index a1f06332e0..01685b7838 100644 --- a/apps/plugins/puzzles/src/unruly.c +++ b/apps/plugins/puzzles/src/unruly.c @@ -47,12 +47,16 @@ #include #include #include -#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #ifdef STANDALONE_SOLVER -bool solver_verbose = false; +static bool solver_verbose = false; #endif enum { @@ -81,6 +85,7 @@ struct game_params { int diff; }; #define DIFFLIST(A) \ + A(TRIVIAL,Trivial, t) \ A(EASY,Easy, e) \ A(NORMAL,Normal, n) \ @@ -95,6 +100,7 @@ static char const unruly_diffchars[] = DIFFLIST(ENCODE); #define DIFFCONFIG DIFFLIST(CONFIG) static const struct game_params unruly_presets[] = { + { 8, 8, false, DIFF_TRIVIAL}, { 8, 8, false, DIFF_EASY}, { 8, 8, false, DIFF_NORMAL}, {10, 10, false, DIFF_EASY}, @@ -284,6 +290,8 @@ static const char *validate_params(const game_params *params, bool full) return "Width and height must both be even"; if (params->w2 < 6 || params->h2 < 6) return "Width and height must be at least 6"; + if (params->w2 > INT_MAX / params->h2) + return "Width times height must not be unreasonably large"; if (params->unique) { static const long A177790[] = { /* @@ -349,7 +357,7 @@ static const char *validate_desc(const game_params *params, const char *desc) return NULL; } -static game_state *blank_state(int w2, int h2, bool unique) +static game_state *blank_state(int w2, int h2, bool unique, bool new_common) { game_state *state = snew(game_state); int s = w2 * h2; @@ -358,12 +366,14 @@ static game_state *blank_state(int w2, int h2, bool unique) state->h2 = h2; state->unique = unique; state->grid = snewn(s, char); - state->common = snew(unruly_common); - state->common->refcount = 1; - state->common->immutable = snewn(s, bool); - memset(state->grid, EMPTY, s); - memset(state->common->immutable, 0, s*sizeof(bool)); + + if (new_common) { + state->common = snew(unruly_common); + state->common->refcount = 1; + state->common->immutable = snewn(s, bool); + memset(state->common->immutable, 0, s*sizeof(bool)); + } state->completed = state->cheated = false; @@ -376,7 +386,7 @@ static game_state *new_game(midend *me, const game_params *params, int w2 = params->w2, h2 = params->h2; int s = w2 * h2; - game_state *state = blank_state(w2, h2, params->unique); + game_state *state = blank_state(w2, h2, params->unique, true); const char *p = desc; int pos = 0; @@ -413,7 +423,7 @@ static game_state *dup_game(const game_state *state) int w2 = state->w2, h2 = state->h2; int s = w2 * h2; - game_state *ret = blank_state(w2, h2, state->unique); + game_state *ret = blank_state(w2, h2, state->unique, false); memcpy(ret->grid, state->grid, s); ret->common = state->common; @@ -743,6 +753,61 @@ static int unruly_solver_fill_row(game_state *state, int i, bool horizontal, return ret; } +static int unruly_solver_check_single_gap(game_state *state, + int *complete, bool horizontal, + int *rowcount, int *colcount, + char fill) +{ + int w2 = state->w2, h2 = state->h2; + int count = (horizontal ? h2 : w2); /* number of rows to check */ + int target = (horizontal ? w2 : h2) / 2; /* target number of 0s/1s */ + int *other = (horizontal ? rowcount : colcount); + + int ret = 0; + + int i; + /* Check for completed rows/cols for one number, then fill in the rest */ + for (i = 0; i < count; i++) { + if (complete[i] == target && other[i] == target - 1) { +#ifdef STANDALONE_SOLVER + if (solver_verbose) { + printf("Solver: Row %i has only one square left which must be " + "%c\n", i, (fill == N_ZERO ? '0' : '1')); + } +#endif + ret += unruly_solver_fill_row(state, i, horizontal, rowcount, + colcount, fill); + } + } + + return ret; +} + +static int unruly_solver_check_all_single_gap(game_state *state, + struct unruly_scratch *scratch) +{ + int ret = 0; + + ret += + unruly_solver_check_single_gap(state, scratch->ones_rows, true, + scratch->zeros_rows, + scratch->zeros_cols, N_ZERO); + ret += + unruly_solver_check_single_gap(state, scratch->ones_cols, false, + scratch->zeros_rows, + scratch->zeros_cols, N_ZERO); + ret += + unruly_solver_check_single_gap(state, scratch->zeros_rows, true, + scratch->ones_rows, + scratch->ones_cols, N_ONE); + ret += + unruly_solver_check_single_gap(state, scratch->zeros_cols, false, + scratch->ones_rows, + scratch->ones_cols, N_ONE); + + return ret; +} + static int unruly_solver_check_complete_nums(game_state *state, int *complete, bool horizontal, int *rowcount, int *colcount, @@ -1140,11 +1205,24 @@ static int unruly_solve_game(game_state *state, /* Keep using the simpler techniques while they produce results */ if (done) { - if (maxdiff < DIFF_EASY) - maxdiff = DIFF_EASY; + if (maxdiff < DIFF_TRIVIAL) + maxdiff = DIFF_TRIVIAL; continue; } + /* Check for rows with only one unfilled square */ + done += unruly_solver_check_all_single_gap(state, scratch); + + if (done) { + if (maxdiff < DIFF_TRIVIAL) + maxdiff = DIFF_TRIVIAL; + continue; + } + + /* Easy techniques */ + if (diff < DIFF_EASY) + break; + /* Check for completed rows */ done += unruly_solver_check_all_complete_nums(state, scratch); @@ -1302,7 +1380,7 @@ static char *new_game_desc(const game_params *params, random_state *rs, while (true) { attempts++; - state = blank_state(w2, h2, params->unique); + state = blank_state(w2, h2, params->unique, true); scratch = unruly_new_scratch(state); if (unruly_fill_game(state, scratch, rs)) break; @@ -1320,6 +1398,8 @@ static char *new_game_desc(const game_params *params, random_state *rs, temp_verbose = solver_verbose; solver_verbose = false; } +#else + (void)attempts; #endif unruly_free_scratch(scratch); @@ -1439,7 +1519,7 @@ static game_ui *new_ui(const game_state *state) game_ui *ret = snew(game_ui); ret->cx = ret->cy = 0; - ret->cursor = false; + ret->cursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ret; } @@ -1449,18 +1529,30 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { } -static void game_changed_state(game_ui *ui, const game_state *oldstate, - const game_state *newstate) +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) { + int hx = ui->cx, hy = ui->cy; + int w2 = state->w2; + char i = state->grid[hy * w2 + hx]; + + if (ui->cursor && IS_CURSOR_SELECT(button)) { + if (state->common->immutable[hy * w2 + hx]) return ""; + switch (i) { + case EMPTY: + return button == CURSOR_SELECT ? "Black" : "White"; + case N_ONE: + return button == CURSOR_SELECT ? "White" : "Empty"; + case N_ZERO: + return button == CURSOR_SELECT ? "Empty" : "Black"; + } + } + return ""; } struct game_drawstate { @@ -1520,7 +1612,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, int w2 = state->w2, h2 = state->h2; - button &= ~MOD_MASK; + char *nullret = MOVE_NO_EFFECT; + + button = STRIP_BUTTON_MODIFIERS(button); /* Mouse click */ if (button == LEFT_BUTTON || button == RIGHT_BUTTON || @@ -1529,17 +1623,18 @@ static char *interpret_move(const game_state *state, game_ui *ui, && oy >= (ds->tilesize / 2) && gy < h2) { hx = gx; hy = gy; - ui->cursor = false; + if (ui->cursor) { + ui->cursor = false; + nullret = MOVE_UI_UPDATE; + } } else - return NULL; + return MOVE_UNUSED; } /* Keyboard move */ - if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, w2, h2, false); - ui->cursor = true; - return UI_UPDATE; - } + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cx, &ui->cy, w2, h2, false, + &ui->cursor); /* Place one */ if ((ui->cursor && (button == CURSOR_SELECT || button == CURSOR_SELECT2 @@ -1551,7 +1646,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char c, i; if (state->common->immutable[hy * w2 + hx]) - return NULL; + return nullret; c = '-'; i = state->grid[hy * w2 + hx]; @@ -1571,13 +1666,13 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (state->grid[hy * w2 + hx] == (c == '0' ? N_ZERO : c == '1' ? N_ONE : EMPTY)) - return NULL; /* don't put no-ops on the undo chain */ + return nullret; /* don't put no-ops on the undo chain */ sprintf(buf, "P%c,%d,%d", c, hx, hy); return dupstr(buf); } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -1637,7 +1732,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = tilesize * (params->w2 + 1); *y = tilesize * (params->h2 + 1); @@ -1788,9 +1883,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, int x, y, i; if (!ds->started) { - /* Main window background */ - draw_rect(dr, 0, 0, TILE_SIZE * (w2+1), TILE_SIZE * (h2+1), - COL_BACKGROUND); /* Outer edge of grid */ draw_rect(dr, COORD(0)-TILE_SIZE/10, COORD(0)-TILE_SIZE/10, TILE_SIZE*w2 + 2*(TILE_SIZE/10) - 1, @@ -1878,22 +1970,19 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* Using 7mm squares */ - game_compute_size(params, 700, &pw, &ph); + game_compute_size(params, 700, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w2 = state->w2, h2 = state->h2; int x, y; @@ -1946,12 +2035,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, DEFAULT_TILE_SIZE, game_compute_size, game_set_size, @@ -1965,7 +2056,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ 0, /* flags */ }; @@ -1979,7 +2070,7 @@ const struct game thegame = { /* Most of the standalone solver code was copied from unequal.c and singles.c */ -const char *quis; +static const char *quis; static void usage_exit(const char *msg) { diff --git a/apps/plugins/puzzles/src/untangle.R b/apps/plugins/puzzles/src/untangle.R deleted file mode 100644 index a57f1e56fd..0000000000 --- a/apps/plugins/puzzles/src/untangle.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -UNTANGLE_EXTRA = tree234 - -untangle : [X] GTK COMMON untangle UNTANGLE_EXTRA untangle-icon|no-icon - -untangle : [G] WINDOWS COMMON untangle UNTANGLE_EXTRA untangle.res|noicon.res - -ALL += untangle[COMBINED] UNTANGLE_EXTRA - -!begin am gtk -GAMES += untangle -!end - -!begin >list.c - A(untangle) \ -!end - -!begin >gamedesc.txt -untangle:untangle.exe:Untangle:Planar graph layout puzzle:Reposition the points so that the lines do not cross. -!end diff --git a/apps/plugins/puzzles/src/untangle.c b/apps/plugins/puzzles/src/untangle.c index 0d3e0e6135..f0647c83e9 100644 --- a/apps/plugins/puzzles/src/untangle.c +++ b/apps/plugins/puzzles/src/untangle.c @@ -20,10 +20,6 @@ * requirements are adequately expressed by a single scalar tile * size), and probably complicate the rest of the puzzles' API as a * result. So I'm not sure I really want to do it. - * - * - It would be nice if we could somehow auto-detect a real `long - * long' type on the host platform and use it in place of my - * hand-hacked int64s. It'd be faster and more reliable. */ #include @@ -31,7 +27,15 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif +#if HAVE_STDINT_H +# include +#endif #include "puzzles.h" #include "tree234.h" @@ -39,7 +43,6 @@ #define CIRCLE_RADIUS 6 #define DRAG_THRESHOLD (CIRCLE_RADIUS * 2) #define PREFERRED_TILESIZE 64 -#define CURSOR_GRANULARITY 5 #define FLASH_TIME 0.30F #define ANIM_TIME 0.13F @@ -49,9 +52,7 @@ enum { COL_SYSBACKGROUND, COL_BACKGROUND, COL_LINE, -#ifdef SHOW_CROSSINGS COL_CROSSEDLINE, -#endif COL_OUTLINE, COL_POINT, COL_DRAGPOINT, @@ -93,9 +94,7 @@ struct game_state { game_params params; int w, h; /* extent of coordinate system only */ point *pts; -#ifdef SHOW_CROSSINGS int *crosses; /* mark edges which are crossed */ -#endif struct graph *graph; bool completed, cheated, just_solved; }; @@ -208,6 +207,8 @@ static const char *validate_params(const game_params *params, bool full) { if (params->n < 4) return "Number of points must be at least four"; + if (params->n > INT_MAX / 3) + return "Number of points must not be unreasonably large"; return NULL; } @@ -216,6 +217,9 @@ static const char *validate_params(const game_params *params, bool full) * integer overflow at the very core of cross(). */ +#if !HAVE_STDINT_H +/* For prehistoric C implementations, do this the hard way */ + typedef struct { long hi; unsigned long lo; @@ -295,6 +299,21 @@ static int64 dotprod64(long a, long b, long p, long q) return ab; } +#else /* HAVE_STDINT_H */ + +typedef int64_t int64; +#define greater64(i,j) ((i) > (j)) +#define sign64(i) ((i) < 0 ? -1 : (i)==0 ? 0 : +1) +#define mulu32to64(x,y) ((int64_t)(unsigned long)(x) * (unsigned long)(y)) +#define mul32to64(x,y) ((int64_t)(long)(x) * (long)(y)) + +static int64 dotprod64(long a, long b, long p, long q) +{ + return (int64)a * b + (int64)p * q; +} + +#endif /* HAVE_STDINT_H */ + /* * Determine whether the line segments between a1 and a2, and * between b1 and b2, intersect. We count it as an intersection if @@ -419,7 +438,9 @@ static void addedge(tree234 *edges, int a, int b) e->a = min(a, b); e->b = max(a, b); - add234(edges, e); + if (add234(edges, e) != e) + /* Duplicate edge. */ + sfree(e); } static bool isedge(tree234 *edges, int a, int b) @@ -441,8 +462,8 @@ typedef struct vertex { static int vertcmpC(const void *av, const void *bv) { - const vertex *a = (vertex *)av; - const vertex *b = (vertex *)bv; + const vertex *a = (const vertex *)av; + const vertex *b = (const vertex *)bv; if (a->param < b->param) return -1; @@ -754,6 +775,8 @@ static const char *validate_desc(const game_params *params, const char *desc) return "Expected ',' after number in game description"; desc++; /* eat comma */ } + if (a == b) + return "Node linked to itself in game description"; } return NULL; @@ -765,10 +788,8 @@ static void mark_crossings(game_state *state) int i, j; edge *e, *e2; -#ifdef SHOW_CROSSINGS for (i = 0; (e = index234(state->graph->edges, i)) != NULL; i++) state->crosses[i] = false; -#endif /* * Check correctness: for every pair of edges, see whether they @@ -782,11 +803,7 @@ static void mark_crossings(game_state *state) if (cross(state->pts[e2->a], state->pts[e2->b], state->pts[e->a], state->pts[e->b])) { ok = false; -#ifdef SHOW_CROSSINGS state->crosses[i] = state->crosses[j] = true; -#else - goto done; /* multi-level break - sorry */ -#endif } } } @@ -795,9 +812,6 @@ static void mark_crossings(game_state *state) * e == NULL if we've gone through all the edge pairs * without finding a crossing. */ -#ifndef SHOW_CROSSINGS - done: -#endif if (ok) state->completed = true; } @@ -834,10 +848,8 @@ static game_state *new_game(midend *me, const game_params *params, addedge(state->graph->edges, a, b); } -#ifdef SHOW_CROSSINGS state->crosses = snewn(count234(state->graph->edges), int); mark_crossings(state); /* sets up `crosses' and `completed' */ -#endif return state; } @@ -857,11 +869,9 @@ static game_state *dup_game(const game_state *state) ret->completed = state->completed; ret->cheated = state->cheated; ret->just_solved = state->just_solved; -#ifdef SHOW_CROSSINGS ret->crosses = snewn(count234(ret->graph->edges), int); memcpy(ret->crosses, state->crosses, count234(ret->graph->edges) * sizeof(int)); -#endif return ret; } @@ -1025,19 +1035,10 @@ static char *solve_game(const game_state *state, const game_state *currstate, return ret; } -static bool game_can_format_as_text_now(const game_params *params) -{ - return true; -} - -static char *game_text_format(const game_state *state) -{ - return NULL; -} - struct game_ui { + /* Invariant: at most one of {dragpoint, cursorpoint} may be valid + * at any time. */ int dragpoint; /* point being dragged; -1 if none */ - int cursorpoint; /* point being highlighted, but * not dragged by the cursor, * again -1 if none */ @@ -1046,6 +1047,26 @@ struct game_ui { bool just_dragged; /* reset in game_changed_state */ bool just_moved; /* _set_ in game_changed_state */ float anim_length; + + /* + * User preference option to snap dragged points to a coarse-ish + * grid. Requested by a user who otherwise found themself spending + * too much time struggling to get lines nicely horizontal or + * vertical. + */ + bool snap_to_grid; + + /* + * User preference option to highlight graph edges involved in a + * crossing. + */ + bool show_crossed_edges; + + /* + * User preference option to show vertices as numbers instead of + * circular blobs, so you can easily tell them apart. + */ + bool vertex_numbers; }; static game_ui *new_ui(const game_state *state) @@ -1054,21 +1075,51 @@ static game_ui *new_ui(const game_state *state) ui->dragpoint = -1; ui->cursorpoint = -1; ui->just_moved = ui->just_dragged = false; + ui->snap_to_grid = false; + ui->show_crossed_edges = false; + ui->vertex_numbers = false; return ui; } -static void free_ui(game_ui *ui) +static config_item *get_prefs(game_ui *ui) { - sfree(ui); + config_item *cfg; + + cfg = snewn(4, config_item); + + cfg[0].name = "Snap points to a grid"; + cfg[0].kw = "snap-to-grid"; + cfg[0].type = C_BOOLEAN; + cfg[0].u.boolean.bval = ui->snap_to_grid; + + cfg[1].name = "Show edges that cross another edge"; + cfg[1].kw = "show-crossed-edges"; + cfg[1].type = C_BOOLEAN; + cfg[1].u.boolean.bval = ui->show_crossed_edges; + + cfg[2].name = "Display style for vertices"; + cfg[2].kw = "vertex-style"; + cfg[2].type = C_CHOICES; + cfg[2].u.choices.choicenames = ":Circles:Numbers"; + cfg[2].u.choices.choicekws = ":circle:number"; + cfg[2].u.choices.selected = ui->vertex_numbers; + + cfg[3].name = NULL; + cfg[3].type = C_END; + + return cfg; } -static char *encode_ui(const game_ui *ui) +static void set_prefs(game_ui *ui, const config_item *cfg) { - return NULL; + ui->snap_to_grid = cfg[0].u.boolean.bval; + ui->show_crossed_edges = cfg[1].u.boolean.bval; + ui->vertex_numbers = cfg[2].u.choices.selected; } -static void decode_ui(game_ui *ui, const char *encoding) +static void free_ui(game_ui *ui) { + sfree(ui); } static void game_changed_state(game_ui *ui, const game_state *oldstate, @@ -1085,6 +1136,66 @@ struct game_drawstate { long *x, *y; }; +static void place_dragged_point(const game_state *state, game_ui *ui, + const game_drawstate *ds, int x, int y) +{ + if (ui->snap_to_grid) { + /* + * We snap points to a grid that has n-1 vertices on each + * side. This should be large enough to permit a straight- + * line drawing of any n-vertex planar graph, and moreover, + * any specific planar embedding of that graph. + * + * Source: David Eppstein's book 'Forbidden Configurations in + * Discrete Geometry' mentions (section 16.3, page 182) that + * the point configuration he describes as GRID(n-1,n-1) - + * that is, the vertices of a square grid with n-1 vertices on + * each side - is universal for n-vertex planar graphs. In + * other words (from definitions earlier in the chapter), if a + * graph G admits any drawing in the plane at all, then it can + * be drawn with straight lines, and with all vertices being + * vertices of that grid. + * + * That fact by itself only says that _some_ planar embedding + * of G can be drawn in this grid. We'd prefer that _all_ + * embeddings of G can be so drawn, because 'snap to grid' is + * supposed to be a UI affordance, not an extra puzzle + * challenge, so we don't want to constrain the player's + * choice of planar embedding. + * + * But it doesn't make a difference. Proof: given a specific + * planar embedding of G, triangulate it, by adding extra + * edges to every face of degree > 3. When this process + * terminates with every face a triangle, we have a new graph + * G' such that no edge can be added without it ceasing to be + * planar. Standard theorems say that a maximal planar graph + * is 3-connected, and that a 3-connected planar graph has a + * _unique_ embedding. So any drawing of G' in the plane can + * be converted into a drawing of G in the desired embedding, + * by simply removing all the extra edges that we added to + * turn G into G'. And G' is still an n-vertex planar graph, + * hence it can be drawn in GRID(n-1,n-1). [] + */ + int d = state->params.n - 1; + + /* Calculate position in terms of the snapping grid. */ + x = d * x / (state->w * ds->tilesize); + y = d * y / (state->h * ds->tilesize); + /* Convert to standard co-ordinates, applying a half-square offset. */ + ui->newpoint.x = (x * 2 + 1) * state->w; + ui->newpoint.y = (y * 2 + 1) * state->h; + ui->newpoint.d = d * 2; + } else { + ui->newpoint.x = x; + ui->newpoint.y = y; + ui->newpoint.d = ds->tilesize; + } +} + +static float normsq(point pt) { + return (pt.x * pt.x + pt.y * pt.y) / (pt.d * pt.d); +} + static char *interpret_move(const game_state *state, game_ui *ui, const game_drawstate *ds, int x, int y, int button) @@ -1119,23 +1230,20 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (bestd <= DRAG_THRESHOLD * DRAG_THRESHOLD) { ui->dragpoint = best; - ui->cursorpoint = -1; - ui->newpoint.x = x; - ui->newpoint.y = y; - ui->newpoint.d = ds->tilesize; - return UI_UPDATE; + ui->cursorpoint = -1; /* eliminate the cursor point, if any */ + place_dragged_point(state, ui, ds, x, y); + return MOVE_UI_UPDATE; } - + return MOVE_NO_EFFECT; } else if (IS_MOUSE_DRAG(button) && ui->dragpoint >= 0) { - ui->newpoint.x = x; - ui->newpoint.y = y; - ui->newpoint.d = ds->tilesize; - return UI_UPDATE; + place_dragged_point(state, ui, ds, x, y); + return MOVE_UI_UPDATE; } else if (IS_MOUSE_RELEASE(button) && ui->dragpoint >= 0) { int p = ui->dragpoint; char buf[80]; ui->dragpoint = -1; /* terminate drag, no matter what */ + ui->cursorpoint = -1; /* also eliminate the cursor point */ /* * First, see if we're within range. The user can cancel a @@ -1145,7 +1253,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->newpoint.x >= (long)state->w*ui->newpoint.d || ui->newpoint.y < 0 || ui->newpoint.y >= (long)state->h*ui->newpoint.d) - return UI_UPDATE; + return MOVE_UI_UPDATE; /* * We aren't cancelling the drag. Construct a move string @@ -1155,109 +1263,140 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->newpoint.x, ui->newpoint.y, ui->newpoint.d); ui->just_dragged = true; return dupstr(buf); + } else if (IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) { + return MOVE_NO_EFFECT; } - else if(IS_CURSOR_MOVE(button)) - { - if(ui->dragpoint < 0) - { - /* We're selecting a point here. */ - /* Search all the points and find the closest one (2-D) in - * the given direction. */ - int i, best; - long bestd; - - if(ui->cursorpoint < 0) - { + else if(IS_CURSOR_MOVE(button)) { + if(ui->dragpoint < 0) { + /* + * We're selecting a point with the cursor keys. + * + * If no point is currently highlighted, we assume the "0" + * point is highlighted to begin. Then, we search all the + * points and find the nearest one (by Euclidean distance) + * in the quadrant corresponding to the cursor key + * direction. A point is in the right quadrant if and only + * if the azimuth angle to that point from the cursor + * point is within a [-45 deg, +45 deg] interval from the + * direction vector of the cursor key. + * + * An important corner case here is if another point is in + * the exact same location as the currently highlighted + * point (which is a possibility with the "snap to grid" + * preference). In this case, we do not consider the other + * point as a candidate point, so as to prevent the cursor + * from being "stuck" on any point. The player can still + * select the overlapped point by dragging the highlighted + * point away and then navigating back. + */ + int i, best = -1; + float bestd = 0; + + if(ui->cursorpoint < 0) { ui->cursorpoint = 0; } - /* - * Begin drag. We drag the vertex _nearest_ to the pointer, - * just in case one is nearly on top of another and we want - * to drag the latter. However, we drag nothing at all if - * the nearest vertex is outside DRAG_THRESHOLD. - */ - best = -1; - bestd = 0; + point cur = state->pts[ui->cursorpoint]; for (i = 0; i < n; i++) { - long px, py, dx, dy, d; - float angle; - int right_direction; + point delta; + float distsq; + point p = state->pts[i]; + int right_direction = false; + if(i == ui->cursorpoint) continue; - px = state->pts[i].x * ds->tilesize / state->pts[i].d; - py = state->pts[i].y * ds->tilesize / state->pts[i].d; - dx = px - state->pts[ui->cursorpoint].x * ds->tilesize / state->pts[ui->cursorpoint].d; - dy = py - state->pts[ui->cursorpoint].y * ds->tilesize / state->pts[ui->cursorpoint].d; - d = dx*dx + dy*dy; + /* Compute the vector p - cur. Check that it lies in + * the correct quadrant. */ + delta.x = p.x * cur.d - cur.x * p.d; + delta.y = p.y * cur.d - cur.y * p.d; + delta.d = cur.d * p.d; - /* Figure out if this point falls into a 90 degree - * range extending from the current point */ + if(delta.x == 0 && delta.y == 0) + continue; /* overlaps cursor point - skip */ - angle = atan2(-dy, dx); /* negate y to adjust for raster coordinates */ - - /* offset to [0..2*PI] */ - if(angle < 0) - angle += 2*PI; + switch(button) { + case CURSOR_UP: + right_direction = (delta.y <= -delta.x) && (delta.y <= delta.x); + break; + case CURSOR_DOWN: + right_direction = (delta.y >= -delta.x) && (delta.y >= delta.x); + break; + case CURSOR_LEFT: + right_direction = (delta.y >= delta.x) && (delta.y <= -delta.x); + break; + case CURSOR_RIGHT: + right_direction = (delta.y <= delta.x) && (delta.y >= -delta.x); + break; + } - right_direction = false; + if(!right_direction) + continue; - if((button == CURSOR_UP && (1*PI/4 <= angle && angle <= 3*PI/4)) || - (button == CURSOR_LEFT && (3*PI/4 <= angle && angle <= 5*PI/4)) || - (button == CURSOR_DOWN && (5*PI/4 <= angle && angle <= 7*PI/4)) || - (button == CURSOR_RIGHT && (angle >= 7*PI/4 || angle <= 1*PI/4))) - right_direction = true; + /* Compute squared Euclidean distance */ + distsq = normsq(delta); - if ((best == -1 || bestd > d) && right_direction) { + if (best == -1 || distsq < bestd) { best = i; - bestd = d; + bestd = distsq; } } - if(best >= 0) - { + if(best >= 0) { ui->cursorpoint = best; - return UI_UPDATE; + return MOVE_UI_UPDATE; } } - else if(ui->dragpoint >= 0) - { - /* dragging */ - switch(button) - { + else if(ui->dragpoint >= 0) { + /* Dragging a point with the cursor keys. */ + int movement_increment = ds->tilesize / 2; + int dx = 0, dy = 0; + + switch(button) { case CURSOR_UP: - ui->newpoint.y -= ds->tilesize / CURSOR_GRANULARITY; - return UI_UPDATE; + dy = -movement_increment; + break; case CURSOR_DOWN: - ui->newpoint.y += ds->tilesize / CURSOR_GRANULARITY; - return UI_UPDATE; + dy = movement_increment; + break; case CURSOR_LEFT: - ui->newpoint.x -= ds->tilesize / CURSOR_GRANULARITY; - return UI_UPDATE; + dx = -movement_increment; + break; case CURSOR_RIGHT: - ui->newpoint.x += ds->tilesize / CURSOR_GRANULARITY; - return UI_UPDATE; + dx = movement_increment; + break; default: break; } + + /* This code has a slightly inconvenient interaction with + * the snap to grid feature: if the point being dragged + * originates on a non-grid point which is in the bottom + * half or right half (or both) of a grid cell (a 75% + * probability), then dragging point right (if it + * originates from the right half) or down (if it + * originates from the bottom half) will cause the point + * to move one more grid cell than intended in that + * direction. I (F. Wei) it wasn't worth handling this + * corner case - if anyone feels inclined, please feel + * free to do so. */ + place_dragged_point(state, ui, ds, + ui->newpoint.x * ds->tilesize / ui->newpoint.d + dx, + ui->newpoint.y * ds->tilesize / ui->newpoint.d + dy); + return MOVE_UI_UPDATE; } - } - else if(IS_CURSOR_SELECT(button)) - { - if(ui->dragpoint < 0 && ui->cursorpoint >= 0) - { + } else if(button == CURSOR_SELECT) { + if(ui->dragpoint < 0 && ui->cursorpoint >= 0) { /* begin drag */ ui->dragpoint = ui->cursorpoint; ui->cursorpoint = -1; ui->newpoint.x = state->pts[ui->dragpoint].x * ds->tilesize / state->pts[ui->dragpoint].d; ui->newpoint.y = state->pts[ui->dragpoint].y * ds->tilesize / state->pts[ui->dragpoint].d; ui->newpoint.d = ds->tilesize; - return UI_UPDATE; + return MOVE_UI_UPDATE; } - else if(ui->dragpoint >= 0) - { + else if(ui->dragpoint >= 0) { /* end drag */ int p = ui->dragpoint; char buf[80]; @@ -1273,7 +1412,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->newpoint.x >= (long)state->w*ui->newpoint.d || ui->newpoint.y < 0 || ui->newpoint.y >= (long)state->h*ui->newpoint.d) - return UI_UPDATE; + return MOVE_UI_UPDATE; /* * We aren't cancelling the drag. Construct a move string @@ -1284,14 +1423,29 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->just_dragged = true; return dupstr(buf); } - else if(ui->cursorpoint < 0) - { + else if(ui->cursorpoint < 0) { ui->cursorpoint = 0; - return UI_UPDATE; + return MOVE_UI_UPDATE; } + } else if(STRIP_BUTTON_MODIFIERS(button) == CURSOR_SELECT2 || + STRIP_BUTTON_MODIFIERS(button) == '\t') { + /* Use spacebar or tab to cycle through the points. Shift + * reverses cycle direction. */ + if(ui->dragpoint >= 0) + return MOVE_NO_EFFECT; + if(ui->cursorpoint < 0) { + ui->cursorpoint = 0; + return MOVE_UI_UPDATE; + } + assert(ui->cursorpoint >= 0); + + /* cursorpoint is valid - increment it */ + int direction = (button & MOD_SHFT) ? -1 : 1; + ui->cursorpoint = (ui->cursorpoint + direction + state->params.n) % state->params.n; + return MOVE_UI_UPDATE; } - return NULL; + return MOVE_UNUSED; } static game_state *execute_move(const game_state *state, const char *move) @@ -1334,7 +1488,7 @@ static game_state *execute_move(const game_state *state, const char *move) */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { *x = *y = COORDLIMIT(params->n) * tilesize; } @@ -1363,11 +1517,9 @@ static float *game_colours(frontend *fe, int *ncolours) ret[COL_LINE * 3 + 1] = 0.0F; ret[COL_LINE * 3 + 2] = 0.0F; -#ifdef SHOW_CROSSINGS ret[COL_CROSSEDLINE * 3 + 0] = 1.0F; ret[COL_CROSSEDLINE * 3 + 1] = 0.0F; ret[COL_CROSSEDLINE * 3 + 2] = 0.0F; -#endif ret[COL_OUTLINE * 3 + 0] = 0.0F; ret[COL_OUTLINE * 3 + 1] = 0.0F; @@ -1491,15 +1643,16 @@ static void game_redraw(drawing *dr, game_drawstate *ds, ds->y[i] = y; } - if (ds->bg == bg && ds->dragpoint == ui->dragpoint && ds->cursorpoint == ui->cursorpoint && !points_moved) + if (ds->bg == bg && + ds->dragpoint == ui->dragpoint && + ds->cursorpoint == ui->cursorpoint && !points_moved) return; /* nothing to do */ ds->dragpoint = ui->dragpoint; + ds->cursorpoint = ui->cursorpoint; ds->bg = bg; - game_compute_size(&state->params, ds->tilesize, &w, &h); - - clip(dr, 0, 0, w, h); + game_compute_size(&state->params, ds->tilesize, ui, &w, &h); draw_rect(dr, 0, 0, w, h, bg); /* @@ -1508,23 +1661,28 @@ static void game_redraw(drawing *dr, game_drawstate *ds, for (i = 0; (e = index234(state->graph->edges, i)) != NULL; i++) { draw_line(dr, ds->x[e->a], ds->y[e->a], ds->x[e->b], ds->y[e->b], -#ifdef SHOW_CROSSINGS - (oldstate?oldstate:state)->crosses[i] ? - COL_CROSSEDLINE : -#endif - COL_LINE); + ui->show_crossed_edges && + (oldstate?oldstate:state)->crosses[i] ? + COL_CROSSEDLINE : COL_LINE); } /* * Draw the points. - * - * When dragging, we should not only vary the colours, but - * leave the point being dragged until last. + * + * When dragging, we vary the point colours to highlight the drag + * point and neighbour points. The draw order is defined so that + * the most relevant points (i.e., the dragged point and cursor + * point) are drawn last, so they appear on top of other points. */ + static const int draw_order[] = { + COL_POINT, + COL_NEIGHBOUR, + COL_CURSORPOINT, + COL_DRAGPOINT + }; + for (j = 0; j < 4; j++) { - int thisc = (j == 0 ? COL_POINT : - (j == 1 ? COL_NEIGHBOUR : - j == 2 ? COL_CURSORPOINT : COL_DRAGPOINT)); + int thisc = draw_order[j]; for (i = 0; i < state->params.n; i++) { int c; @@ -1540,19 +1698,17 @@ static void game_redraw(drawing *dr, game_drawstate *ds, } if (c == thisc) { -#ifdef VERTEX_NUMBERS - draw_circle(dr, ds->x[i], ds->y[i], DRAG_THRESHOLD, bg, bg); - { - char buf[80]; - sprintf(buf, "%d", i); - draw_text(dr, ds->x[i], ds->y[i], FONT_VARIABLE, + if (ui->vertex_numbers) { + char buf[80]; + draw_circle(dr, ds->x[i], ds->y[i], DRAG_THRESHOLD, bg, bg); + sprintf(buf, "%d", i); + draw_text(dr, ds->x[i], ds->y[i], FONT_VARIABLE, DRAG_THRESHOLD*3/2, - ALIGN_VCENTRE|ALIGN_HCENTRE, c, buf); - } -#else - draw_circle(dr, ds->x[i], ds->y[i], CIRCLE_RADIUS, - c, COL_OUTLINE); -#endif + ALIGN_VCENTRE|ALIGN_HCENTRE, c, buf); + } else { + draw_circle(dr, ds->x[i], ds->y[i], CIRCLE_RADIUS, + c, COL_OUTLINE); + } } } } @@ -1587,17 +1743,20 @@ static void game_get_cursor_location(const game_ui *ui, const game_params *params, int *x, int *y, int *w, int *h) { - if(ui->dragpoint >= 0 || ui->cursorpoint >= 0) { - int idx = (ui->dragpoint >= 0) ? ui->dragpoint : ui->cursorpoint; + point pt; + if(ui->dragpoint >= 0) + pt = ui->newpoint; + else if(ui->cursorpoint >= 0) + pt = state->pts[ui->cursorpoint]; + else + return; - int cx, cy; - cx = ds->x[idx]; - cy = ds->y[idx]; + int cx = ds->tilesize * pt.x / pt.d; + int cy = ds->tilesize * pt.y / pt.d; - *x = cx - CIRCLE_RADIUS; - *y = cy - CIRCLE_RADIUS; - *w = *h = 2 * CIRCLE_RADIUS + 1; - } + *x = cx - CIRCLE_RADIUS; + *y = cy - CIRCLE_RADIUS; + *w = *h = 2 * CIRCLE_RADIUS + 1; } static int game_status(const game_state *state) @@ -1605,19 +1764,6 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) -{ -} - -static void game_print(drawing *dr, const game_state *state, int tilesize) -{ -} - #ifdef COMBINED #define thegame untangle #endif @@ -1638,13 +1784,15 @@ const struct game thegame = { dup_game, free_game, true, solve_game, - false, game_can_format_as_text_now, game_text_format, + false, NULL, NULL, /* can_format_as_text_now, text_format */ + get_prefs, set_prefs, new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + NULL, /* current_key_label */ interpret_move, execute_move, PREFERRED_TILESIZE, game_compute_size, game_set_size, @@ -1656,8 +1804,8 @@ const struct game thegame = { game_flash_length, game_get_cursor_location, game_status, - false, false, game_print_size, game_print, + false, false, NULL, NULL, /* print_size, print */ false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ SOLVE_ANIMATES, /* flags */ }; diff --git a/apps/plugins/puzzles/src/version.c b/apps/plugins/puzzles/src/version.c index 1cef29feb7..73632f9b37 100644 --- a/apps/plugins/puzzles/src/version.c +++ b/apps/plugins/puzzles/src/version.c @@ -2,6 +2,7 @@ * Puzzles version numbering. */ +#include "puzzles.h" #include "version.h" char ver[] = VER; diff --git a/apps/plugins/puzzles/src/version.h b/apps/plugins/puzzles/src/version.h index 997e00592b..20d2800fee 100644 --- a/apps/plugins/puzzles/src/version.h +++ b/apps/plugins/puzzles/src/version.h @@ -9,3 +9,5 @@ */ #define VER "Unidentified build" + +#define VERSIONINFO_BINARY_VERSION 0,0,0,0 diff --git a/apps/plugins/puzzles/src/windows.c b/apps/plugins/puzzles/src/windows.c index 38559c5454..5273e17842 100644 --- a/apps/plugins/puzzles/src/windows.c +++ b/apps/plugins/puzzles/src/windows.c @@ -7,11 +7,7 @@ #ifndef NO_HTMLHELP #include #endif /* NO_HTMLHELP */ - -#ifdef _WIN32_WCE -#include -#include -#endif +#include #include #include @@ -23,10 +19,6 @@ #include "puzzles.h" -#ifdef _WIN32_WCE -#include "resource.h" -#endif - #define IDM_NEW 0x0010 #define IDM_RESTART 0x0020 #define IDM_UNDO 0x0030 @@ -43,10 +35,14 @@ #define IDM_SAVE 0x00E0 #define IDM_LOAD 0x00F0 #define IDM_PRINT 0x0100 -#define IDM_PRESETS 0x0110 -#define IDM_GAMES 0x0300 +#define IDM_PREFS 0x0110 -#define IDM_KEYEMUL 0x0400 +/* Menu items for preset game_params go up from IDM_PRESET_BASE in + * steps of MENUITEM_STEP = 0x20. Menu items for selecting different + * games (in -DCOMBINED mode) go up from IDM_GAME_BASE similarly. */ +#define IDM_PRESET_BASE 0x0120 +#define IDM_GAME_BASE 0x0130 +#define MENUITEM_STEP 0x0020 #define HELP_FILE_NAME "puzzles.hlp" #define HELP_CNT_NAME "puzzles.cnt" @@ -77,56 +73,12 @@ bool help_has_contents; #define CLASSNAME thegame.name #endif -#ifdef _WIN32_WCE - -/* - * Wrapper implementations of functions not supplied by the - * PocketPC API. - */ - -#define SHGetSubMenu(hWndMB,ID_MENU) (HMENU)SendMessage((hWndMB), SHCMBM_GETSUBMENU, (WPARAM)0, (LPARAM)ID_MENU) - -#undef MessageBox - -int MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) -{ - TCHAR wText[2048]; - TCHAR wCaption[2048]; - - MultiByteToWideChar (CP_ACP, 0, lpText, -1, wText, 2048); - MultiByteToWideChar (CP_ACP, 0, lpCaption, -1, wCaption, 2048); - - return MessageBoxW (hWnd, wText, wCaption, uType); -} - -BOOL SetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPCSTR lpString) -{ - TCHAR wText[256]; - - MultiByteToWideChar (CP_ACP, 0, lpString, -1, wText, 256); - return SetDlgItemTextW(hDlg, nIDDlgItem, wText); -} - -LPCSTR getenv(LPCSTR buf) -{ - return NULL; -} - -BOOL GetKeyboardState(PBYTE pb) -{ - return false; -} - -static TCHAR wClassName[256], wGameName[256]; - -#endif - #ifdef DEBUGGING static FILE *debug_fp = NULL; static HANDLE debug_hdl = INVALID_HANDLE_VALUE; static int debug_got_console = 0; -void dputs(char *buf) +static void dputs(char *buf) { /*DWORD dw; @@ -144,8 +96,8 @@ void dputs(char *buf) WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL); } if (debug_fp) { - fputs(buf, debug_fp); - fflush(debug_fp); + fputs(buf, debug_fp); + fflush(debug_fp); }*/ OutputDebugString(buf); } @@ -157,7 +109,7 @@ void debug_printf(const char *fmt, ...) static int debugging = -1; if (debugging == -1) - debugging = getenv("DEBUG_PUZZLES") ? 1 : 0; + debugging = getenv_bool("DEBUG_PUZZLES", false); if (debugging) { va_start(ap, fmt); @@ -168,14 +120,12 @@ void debug_printf(const char *fmt, ...) } #endif -#ifndef _WIN32_WCE #define WINFLAGS (WS_OVERLAPPEDWINDOW &~ \ (WS_MAXIMIZEBOX | WS_OVERLAPPED)) -#else -#define WINFLAGS (WS_CAPTION | WS_SYSMENU) -#endif static void new_game_size(frontend *fe, float scale); +static void load_prefs(midend *me); +static char *save_prefs(midend *me); struct font { HFONT font; @@ -204,9 +154,6 @@ struct frontend { const game *game; midend *me; HWND hwnd, statusbar, cfgbox; -#ifdef _WIN32_WCE - HWND numpad; /* window handle for the numeric pad */ -#endif HINSTANCE inst; HBITMAP bitmap, prevbm; RECT bitmapPosition; /* game bitmap position within game window */ @@ -308,19 +255,9 @@ void get_random_seed(void **randseed, int *randseedsize) static void win_status_bar(void *handle, const char *text) { -#ifdef _WIN32_WCE - TCHAR wText[255]; -#endif frontend *fe = (frontend *)handle; -#ifdef _WIN32_WCE - MultiByteToWideChar (CP_ACP, 0, text, -1, wText, 255); - SendMessage(fe->statusbar, SB_SETTEXT, - (WPARAM) 255 | SBT_NOBORDERS, - (LPARAM) wText); -#else SetWindowText(fe->statusbar, text); -#endif } static blitter *win_blitter_new(void *handle, int w, int h) @@ -464,13 +401,6 @@ static void win_set_brush(frontend *fe, int colour) if (hatch < 0) { br = CreateSolidBrush(RGB(r * 255, g * 255, b * 255)); } else { -#ifdef _WIN32_WCE - /* - * This is only ever required during printing, and the - * PocketPC port doesn't support printing. - */ - fatal("CreateHatchBrush not supported"); -#else br = CreateHatchBrush(hatch == HATCH_BACKSLASH ? HS_FDIAGONAL : hatch == HATCH_SLASH ? HS_BDIAGONAL : hatch == HATCH_HORIZ ? HS_HORIZONTAL : @@ -478,7 +408,6 @@ static void win_set_brush(frontend *fe, int colour) hatch == HATCH_PLUS ? HS_CROSS : /* hatch == HATCH_X ? */ HS_DIAGCROSS, RGB(0,0,0)); -#endif } } else { br = fe->brushes[colour]; @@ -602,9 +531,6 @@ static void win_draw_text(void *handle, int x, int y, int fonttype, lf.lfPitchAndFamily = (fonttype == FONT_FIXED ? FIXED_PITCH | FF_DONTCARE : VARIABLE_PITCH | FF_SWISS); -#ifdef _WIN32_WCE - wcscpy(lf.lfFaceName, TEXT("Tahoma")); -#endif fe->fonts[i].font = CreateFontIndirect(&lf); } @@ -708,7 +634,7 @@ static void win_draw_circle(void *handle, int cx, int cy, int radius, win_reset_pen(fe); } -static void win_draw_polygon(void *handle, int *coords, int npoints, +static void win_draw_polygon(void *handle, const int *coords, int npoints, int fillcolour, int outlinecolour) { frontend *fe = (frontend *)handle; @@ -754,9 +680,7 @@ static void win_start_draw(void *handle) fe->prevbm = SelectObject(fe->hdc, fe->bitmap); ReleaseDC(fe->hwnd, hdc_win); fe->clip = NULL; -#ifndef _WIN32_WCE SetMapMode(fe->hdc, MM_TEXT); -#endif fe->drawstatus = DRAWING; } @@ -999,7 +923,6 @@ const struct drawing_api win_drawing = { void print(frontend *fe) { -#ifndef _WIN32_WCE PRINTDLG pd; char doctitle[256]; document *doc; @@ -1019,6 +942,7 @@ void print(frontend *fe) game_params *params; nme = midend_new(NULL, fe->game, NULL, NULL); + load_prefs(nme); /* * Set the non-interactive mid-end to have the same @@ -1090,7 +1014,6 @@ void print(frontend *fe) DeleteDC(pd.hDC); document_free(doc); -#endif } void deactivate_timer(frontend *fe) @@ -1168,7 +1091,6 @@ void write_clip(HWND hwnd, char *data) */ static void init_help(void) { -#ifndef _WIN32_WCE char b[2048], *p, *q, *r; FILE *fp; @@ -1232,11 +1154,8 @@ static void init_help(void) } help_type = NONE; /* didn't find any */ -#endif } -#ifndef _WIN32_WCE - /* * Start Help. */ @@ -1257,7 +1176,7 @@ static void start_help(frontend *fe, const char *topic) } else { cmd = HELP_CONTENTS; } - WinHelp(fe->hwnd, help_path, cmd, (DWORD)str); + WinHelp(fe->hwnd, help_path, cmd, (ULONG_PTR)str); fe->help_running = true; break; case CHM: @@ -1306,8 +1225,6 @@ static void stop_help(frontend *fe) } } -#endif - /* * Terminate Help on process exit. */ @@ -1338,10 +1255,8 @@ static void adjust_statusbar(frontend *fe, RECT *r) if (!fe->statusbar) return; sy = get_statusbar_height(fe); -#ifndef _WIN32_WCE SetWindowPos(fe->statusbar, NULL, 0, r->bottom-r->top-sy, r->right-r->left, sy, SWP_NOZORDER); -#endif } static void get_menu_size(HWND wh, RECT *r) @@ -1378,7 +1293,7 @@ static bool check_window_resize(frontend *fe, int cx, int cy, * See if we actually got the window size we wanted, and adjust * the puzzle size if not. */ - midend_size(fe->me, &x, &y, true); + midend_size(fe->me, &x, &y, true, 1.0); if (x != cx || y != cy) { /* * Resize the window, now we know what size we _really_ @@ -1416,13 +1331,8 @@ static void check_window_size(frontend *fe, int *px, int *py) cx = r.right - r.left; cy = r.bottom - r.top; - if (check_window_resize(fe, cx, cy, px, py, &wx, &wy)) { -#ifdef _WIN32_WCE - SetWindowPos(fe->hwnd, NULL, 0, 0, wx, wy, - SWP_NOMOVE | SWP_NOZORDER); -#endif - ; - } + if (check_window_resize(fe, cx, cy, px, py, &wx, &wy)) + SetWindowPos(fe->hwnd, NULL, 0, 0, wx, wy, SWP_NOMOVE | SWP_NOZORDER); GetClientRect(fe->hwnd, &r); adjust_statusbar(fe, &r); @@ -1452,23 +1362,6 @@ static void get_max_puzzle_size(frontend *fe, int *x, int *y) } } -#ifdef _WIN32_WCE -/* Toolbar buttons on the numeric pad */ -static TBBUTTON tbNumpadButtons[] = -{ - {0, IDM_KEYEMUL + '1', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {1, IDM_KEYEMUL + '2', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {2, IDM_KEYEMUL + '3', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {3, IDM_KEYEMUL + '4', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {4, IDM_KEYEMUL + '5', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {5, IDM_KEYEMUL + '6', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {6, IDM_KEYEMUL + '7', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {7, IDM_KEYEMUL + '8', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {8, IDM_KEYEMUL + '9', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}, - {9, IDM_KEYEMUL + ' ', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1} -}; -#endif - /* * Allocate a new frontend structure and create its main window. */ @@ -1502,34 +1395,6 @@ static frontend *frontend_new(HINSTANCE inst) fe->puzz_scale = 1.0; - #ifdef _WIN32_WCE - MultiByteToWideChar (CP_ACP, 0, nogame, -1, wGameName, 256); - fe->hwnd = CreateWindowEx(0, wClassName, wGameName, - WS_VISIBLE, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, inst, NULL); - - { - SHMENUBARINFO mbi; - RECT rc, rcBar, rcTB, rcClient; - - memset (&mbi, 0, sizeof(SHMENUBARINFO)); - mbi.cbSize = sizeof(SHMENUBARINFO); - mbi.hwndParent = fe->hwnd; - mbi.nToolBarId = IDR_MENUBAR1; - mbi.hInstRes = inst; - - SHCreateMenuBar(&mbi); - - GetWindowRect(fe->hwnd, &rc); - GetWindowRect(mbi.hwndMB, &rcBar); - rc.bottom -= rcBar.bottom - rcBar.top; - MoveWindow(fe->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, false); - - fe->numpad = NULL; - } -#else fe->hwnd = CreateWindowEx(0, CLASSNAME, nogame, WS_OVERLAPPEDWINDOW &~ (WS_MAXIMIZEBOX), @@ -1540,7 +1405,6 @@ static frontend *frontend_new(HINSTANCE inst) DWORD lerr = GetLastError(); printf("no window: 0x%x\n", (unsigned)lerr); } -#endif fe->gamemenu = NULL; fe->preset_menu = NULL; @@ -1586,6 +1450,7 @@ static midend *midend_for_new_game(frontend *fe, const game *cgame, if (!arg) { if (me) midend_free(me); me = midend_new(fe, cgame, &win_drawing, fe); + load_prefs(me); midend_new_game(me); } else { FILE *fp; @@ -1626,6 +1491,7 @@ static midend *midend_for_new_game(frontend *fe, const game *cgame, if (!err_load) { if (me) midend_free(me); me = midend_new(fe, loadgame, &win_drawing, fe); + load_prefs(me); err_load = midend_deserialise(me, savefile_read, fp); } } else { @@ -1638,6 +1504,7 @@ static midend *midend_for_new_game(frontend *fe, const game *cgame, */ if (me) midend_free(me); me = midend_new(fe, cgame, &win_drawing, fe); + load_prefs(me); err_param = midend_game_id(me, arg); if (!err_param) { midend_new_game(me); @@ -1676,7 +1543,8 @@ static void populate_preset_menu(frontend *fe, UINT flags = MF_ENABLED; if (entry->params) { - id_or_sub = (UINT_PTR)(IDM_PRESETS + 0x10 * entry->id); + id_or_sub = (UINT_PTR)( + IDM_PRESET_BASE + MENUITEM_STEP * entry->id); fe->preset_menuitems[entry->id].which_menu = winmenu; fe->preset_menuitems[entry->id].item_index = @@ -1694,15 +1562,7 @@ static void populate_preset_menu(frontend *fe, * here. */ -#ifndef _WIN32_WCE AppendMenu(winmenu, flags, id_or_sub, entry->title); -#else - { - TCHAR wName[255]; - MultiByteToWideChar(CP_ACP, 0, entry->title, -1, wName, 255); - AppendMenu(winmenu, flags, id_or_sub, wName); - } -#endif } } @@ -1763,41 +1623,14 @@ static int fe_set_midend(frontend *fe, midend *me) fe->statusbar = NULL; get_max_puzzle_size(fe, &x, &y); - midend_size(fe->me, &x, &y, false); + midend_size(fe->me, &x, &y, false, 1.0); r.left = r.top = 0; r.right = x; r.bottom = y; AdjustWindowRectEx(&r, WINFLAGS, true, 0); -#ifdef _WIN32_WCE - if (fe->numpad) - DestroyWindow(fe->numpad); - if (fe->game->flags & REQUIRE_NUMPAD) - { - fe->numpad = CreateToolbarEx (fe->hwnd, - WS_VISIBLE | WS_CHILD | CCS_NOPARENTALIGN | TBSTYLE_FLAT, - 0, 10, fe->inst, IDR_PADTOOLBAR, - tbNumpadButtons, sizeof (tbNumpadButtons) / sizeof (TBBUTTON), - 0, 0, 14, 15, sizeof (TBBUTTON)); - GetWindowRect(fe->numpad, &rcTB); - GetClientRect(fe->hwnd, &rcClient); - MoveWindow(fe->numpad, - 0, - rcClient.bottom - (rcTB.bottom - rcTB.top) - 1, - rcClient.right, - rcTB.bottom - rcTB.top, - false); - SendMessage(fe->numpad, TB_SETINDENT, (rcClient.right - (10 * 21)) / 2, 0); - } - else { - fe->numpad = NULL; - } - MultiByteToWideChar (CP_ACP, 0, fe->game->name, -1, wGameName, 256); - SetWindowText(fe->hwnd, wGameName); -#else SetWindowText(fe->hwnd, fe->game->name); -#endif if (fe->statusbar) DestroyWindow(fe->statusbar); @@ -1807,24 +1640,15 @@ static int fe_set_midend(frontend *fe, midend *me) WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, /* status bar does these */ fe->hwnd, NULL, fe->inst, NULL); -#ifdef _WIN32_WCE - /* Flat status bar looks better on the Pocket PC */ - SendMessage(fe->statusbar, SB_SIMPLE, (WPARAM) true, 0); - SendMessage(fe->statusbar, SB_SETTEXT, - (WPARAM) 255 | SBT_NOBORDERS, - (LPARAM) L""); -#endif /* * Now resize the window to take account of the status bar. */ GetWindowRect(fe->statusbar, &sr); GetWindowRect(fe->hwnd, &r); -#ifndef _WIN32_WCE SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left, r.bottom - r.top + sr.bottom - sr.top, SWP_NOMOVE | SWP_NOZORDER); -#endif } else { fe->statusbar = NULL; } @@ -1832,24 +1656,17 @@ static int fe_set_midend(frontend *fe, midend *me) { HMENU oldmenu = GetMenu(fe->hwnd); -#ifndef _WIN32_WCE HMENU bar = CreateMenu(); HMENU menu = CreateMenu(); RECT menusize; - AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "&Game"); -#else - HMENU menu = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_GAME); - DeleteMenu(menu, 0, MF_BYPOSITION); -#endif + AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT_PTR)menu, "&Game"); fe->gamemenu = menu; AppendMenu(menu, MF_ENABLED, IDM_NEW, TEXT("&New")); AppendMenu(menu, MF_ENABLED, IDM_RESTART, TEXT("&Restart")); -#ifndef _WIN32_WCE /* ...here I run out of sensible accelerator characters. */ AppendMenu(menu, MF_ENABLED, IDM_DESC, TEXT("Speci&fic...")); AppendMenu(menu, MF_ENABLED, IDM_SEED, TEXT("Rando&m Seed...")); -#endif assert(!fe->preset_menu); @@ -1863,14 +1680,9 @@ static int fe_set_midend(frontend *fe, midend *me) fe->preset_menuitems[i].which_menu = NULL; } if (fe->preset_menu->n_entries > 0 || fe->game->can_configure) { -#ifndef _WIN32_WCE HMENU sub = CreateMenu(); - AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)sub, "&Type"); -#else - HMENU sub = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_TYPE); - DeleteMenu(sub, 0, MF_BYPOSITION); -#endif + AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT_PTR)sub, "&Type"); populate_preset_menu(fe, fe->preset_menu, sub); @@ -1884,27 +1696,25 @@ static int fe_set_midend(frontend *fe, midend *me) } #ifdef COMBINED -#ifdef _WIN32_WCE -#error Windows CE does not support COMBINED build. -#endif { HMENU games = CreateMenu(); int i; AppendMenu(menu, MF_SEPARATOR, 0, 0); - AppendMenu(menu, MF_ENABLED|MF_POPUP, (UINT)games, "&Other"); + AppendMenu(menu, MF_ENABLED|MF_POPUP, (UINT_PTR)games, "&Other"); for (i = 0; i < gamecount; i++) { if (strcmp(gamelist[i]->name, fe->game->name) != 0) { /* only include those games that aren't the same as the * game we're currently playing. */ - AppendMenu(games, MF_ENABLED, IDM_GAMES + i, gamelist[i]->name); + AppendMenu(games, MF_ENABLED, + IDM_GAME_BASE + MENUITEM_STEP * i, + gamelist[i]->name); } } } #endif AppendMenu(menu, MF_SEPARATOR, 0, 0); -#ifndef _WIN32_WCE AppendMenu(menu, MF_ENABLED, IDM_LOAD, TEXT("&Load...")); AppendMenu(menu, MF_ENABLED, IDM_SAVE, TEXT("&Save...")); AppendMenu(menu, MF_SEPARATOR, 0, 0); @@ -1912,27 +1722,23 @@ static int fe_set_midend(frontend *fe, midend *me) AppendMenu(menu, MF_ENABLED, IDM_PRINT, TEXT("&Print...")); AppendMenu(menu, MF_SEPARATOR, 0, 0); } -#endif AppendMenu(menu, MF_ENABLED, IDM_UNDO, TEXT("Undo")); AppendMenu(menu, MF_ENABLED, IDM_REDO, TEXT("Redo")); -#ifndef _WIN32_WCE if (fe->game->can_format_as_text_ever) { AppendMenu(menu, MF_SEPARATOR, 0, 0); AppendMenu(menu, MF_ENABLED, IDM_COPY, TEXT("&Copy")); } -#endif if (fe->game->can_solve) { AppendMenu(menu, MF_SEPARATOR, 0, 0); AppendMenu(menu, MF_ENABLED, IDM_SOLVE, TEXT("Sol&ve")); } AppendMenu(menu, MF_SEPARATOR, 0, 0); -#ifndef _WIN32_WCE + AppendMenu(menu, MF_ENABLED, IDM_PREFS, TEXT("Pre&ferences")); + AppendMenu(menu, MF_SEPARATOR, 0, 0); AppendMenu(menu, MF_ENABLED, IDM_QUIT, TEXT("E&xit")); menu = CreateMenu(); - AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, TEXT("&Help")); -#endif + AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT_PTR)menu, TEXT("&Help")); AppendMenu(menu, MF_ENABLED, IDM_ABOUT, TEXT("&About")); -#ifndef _WIN32_WCE if (help_type != NONE) { char *item; AppendMenu(menu, MF_SEPARATOR, 0, 0); @@ -1947,7 +1753,6 @@ static int fe_set_midend(frontend *fe, midend *me) SetMenu(fe->hwnd, bar); get_menu_size(fe->hwnd, &menusize); fe->xmin = (menusize.right - menusize.left) + 25; -#endif } if (fe->bitmap) DeleteObject(fe->bitmap); @@ -1968,36 +1773,6 @@ static void show_window(frontend *fe) midend_redraw(fe->me); } -#ifdef _WIN32_WCE -static HFONT dialog_title_font() -{ - static HFONT hf = NULL; - LOGFONT lf; - - if (hf) - return hf; - - memset (&lf, 0, sizeof(LOGFONT)); - lf.lfHeight = -11; /* - ((8 * GetDeviceCaps(hdc, LOGPIXELSY)) / 72) */ - lf.lfWeight = FW_BOLD; - wcscpy(lf.lfFaceName, TEXT("Tahoma")); - - return hf = CreateFontIndirect(&lf); -} - -static void make_dialog_full_screen(HWND hwnd) -{ - SHINITDLGINFO shidi; - - /* Make dialog full screen */ - shidi.dwMask = SHIDIM_FLAGS; - shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN | - SHIDIF_EMPTYMENU; - shidi.hDlg = hwnd; - SHInitDialog(&shidi); -} -#endif - static int CALLBACK AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -2005,39 +1780,15 @@ static int CALLBACK AboutDlgProc(HWND hwnd, UINT msg, switch (msg) { case WM_INITDIALOG: -#ifdef _WIN32_WCE - { - char title[256]; - - make_dialog_full_screen(hwnd); - - sprintf(title, "About %.250s", fe->game->name); - SetDlgItemTextA(hwnd, IDC_ABOUT_CAPTION, title); - - SendDlgItemMessage(hwnd, IDC_ABOUT_CAPTION, WM_SETFONT, - (WPARAM) dialog_title_font(), 0); - - SetDlgItemTextA(hwnd, IDC_ABOUT_GAME, fe->game->name); - SetDlgItemTextA(hwnd, IDC_ABOUT_VERSION, ver); - } -#endif return 1; case WM_COMMAND: if (LOWORD(wParam) == IDOK) -#ifdef _WIN32_WCE - EndDialog(hwnd, 1); -#else fe->dlg_done = 1; -#endif return 0; case WM_CLOSE: -#ifdef _WIN32_WCE - EndDialog(hwnd, 1); -#else fe->dlg_done = 1; -#endif return 0; } @@ -2137,119 +1888,6 @@ static const char *frontend_set_config( } } -#ifdef _WIN32_WCE -/* Separate version of mkctrl function for the Pocket PC. */ -/* Control coordinates should be specified in dialog units. */ -HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2, - LPCTSTR wclass, int wstyle, - int exstyle, const char *wtext, INT_PTR wid) -{ - RECT rc; - TCHAR wwtext[256]; - - /* Convert dialog units into pixels */ - rc.left = x1; rc.right = x2; - rc.top = y1; rc.bottom = y2; - MapDialogRect(fe->cfgbox, &rc); - - MultiByteToWideChar (CP_ACP, 0, wtext, -1, wwtext, 256); - - return CreateWindowEx(exstyle, wclass, wwtext, - wstyle | WS_CHILD | WS_VISIBLE, - rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top, - fe->cfgbox, (HMENU) wid, fe->inst, NULL); -} - -static void create_config_controls(frontend * fe) -{ - int id, nctrls; - int col1l, col1r, col2l, col2r, y; - config_item *i; - struct cfg_aux *j; - HWND ctl; - - /* Control placement done in dialog units */ - col1l = 4; col1r = 96; /* Label column */ - col2l = 100; col2r = 154; /* Input column (edit boxes and combo boxes) */ - - /* - * Count the controls so we can allocate cfgaux. - */ - for (nctrls = 0, i = fe->cfg; i->type != C_END; i++) - nctrls++; - fe->cfgaux = snewn(nctrls, struct cfg_aux); - - id = 1000; - y = 22; /* Leave some room for the dialog title */ - for (i = fe->cfg, j = fe->cfgaux; i->type != C_END; i++, j++) { - switch (i->type) { - case C_STRING: - /* - * Edit box with a label beside it. - */ - mkctrl(fe, col1l, col1r, y + 1, y + 11, - TEXT("Static"), SS_LEFTNOWORDWRAP, 0, i->name, id++); - mkctrl(fe, col2l, col2r, y, y + 12, - TEXT("EDIT"), WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, - 0, "", (j->ctlid = id++)); - SetDlgItemTextA(fe->cfgbox, j->ctlid, i->u.string.sval); - break; - - case C_BOOLEAN: - /* - * Simple checkbox. - */ - mkctrl(fe, col1l, col2r, y + 1, y + 11, TEXT("BUTTON"), - BS_NOTIFY | BS_AUTOCHECKBOX | WS_TABSTOP, - 0, i->name, (j->ctlid = id++)); - CheckDlgButton(fe->cfgbox, j->ctlid, (i->u.boolean.bval != 0)); - break; - - case C_CHOICES: - /* - * Drop-down list with a label beside it. - */ - mkctrl(fe, col1l, col1r, y + 1, y + 11, - TEXT("STATIC"), SS_LEFTNOWORDWRAP, 0, i->name, id++); - ctl = mkctrl(fe, col2l, col2r, y, y + 48, - TEXT("COMBOBOX"), WS_BORDER | WS_TABSTOP | - CBS_DROPDOWNLIST | CBS_HASSTRINGS, - 0, "", (j->ctlid = id++)); - { - char c; - const char *p, *q; - char *str; - - p = i->u.choices.choicenames; - c = *p++; - while (*p) { - q = p; - while (*q && *q != c) q++; - str = snewn(q-p+1, char); - strncpy(str, p, q-p); - str[q-p] = '\0'; - { - TCHAR ws[50]; - MultiByteToWideChar (CP_ACP, 0, str, -1, ws, 50); - SendMessage(ctl, CB_ADDSTRING, 0, (LPARAM)ws); - } - - sfree(str); - if (*q) q++; - p = q; - } - } - SendMessage(ctl, CB_SETCURSEL, i->u.choices.selected, 0); - break; - } - - y += 15; - } - -} -#endif - static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -2259,25 +1897,6 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, switch (msg) { case WM_INITDIALOG: -#ifdef _WIN32_WCE - { - char *title; - - fe = (frontend *) lParam; - SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); - fe->cfgbox = hwnd; - - fe->cfg = frontend_get_config(fe, fe->cfg_which, &title); - - make_dialog_full_screen(hwnd); - - SetDlgItemTextA(hwnd, IDC_CONFIG_CAPTION, title); - SendDlgItemMessage(hwnd, IDC_CONFIG_CAPTION, WM_SETFONT, - (WPARAM) dialog_title_font(), 0); - - create_config_controls(fe); - } -#endif return 1; case WM_COMMAND: @@ -2293,18 +1912,10 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, MessageBox(hwnd, err, "Validation error", MB_ICONERROR | MB_OK); } else { -#ifdef _WIN32_WCE - EndDialog(hwnd, 2); -#else fe->dlg_done = 2; -#endif } } else { -#ifdef _WIN32_WCE - EndDialog(hwnd, 1); -#else fe->dlg_done = 1; -#endif } return 0; } @@ -2321,13 +1932,7 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, if (i->type == C_STRING && HIWORD(wParam) == EN_CHANGE) { char buffer[4096]; -#ifdef _WIN32_WCE - TCHAR wBuffer[4096]; - GetDlgItemText(fe->cfgbox, j->ctlid, wBuffer, 4096); - WideCharToMultiByte(CP_ACP, 0, wBuffer, -1, buffer, 4096, NULL, NULL); -#else GetDlgItemText(fe->cfgbox, j->ctlid, buffer, lenof(buffer)); -#endif buffer[lenof(buffer)-1] = '\0'; sfree(i->u.string.sval); i->u.string.sval = dupstr(buffer); @@ -2351,7 +1956,6 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, return 0; } -#ifndef _WIN32_WCE HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2, char *wclass, int wstyle, int exstyle, const char *wtext, INT_PTR wid) @@ -2363,13 +1967,9 @@ HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2, SendMessage(ret, WM_SETFONT, (WPARAM)fe->cfgfont, MAKELPARAM(true, 0)); return ret; } -#endif static void about(frontend *fe) { -#ifdef _WIN32_WCE - DialogBox(fe->inst, MAKEINTRESOURCE(IDD_ABOUT), fe->hwnd, AboutDlgProc); -#else int i; WNDCLASS wc; MSG msg; @@ -2518,19 +2118,10 @@ static void about(frontend *fe) SetForegroundWindow(fe->hwnd); DestroyWindow(fe->cfgbox); DeleteObject(fe->cfgfont); -#endif } static bool get_config(frontend *fe, int which) { -#ifdef _WIN32_WCE - fe->cfg_which = which; - - return DialogBoxParam(fe->inst, - MAKEINTRESOURCE(IDD_CONFIG), - fe->hwnd, ConfigDlgProc, - (LPARAM) fe) == 2; -#else config_item *i; struct cfg_aux *j; char *title; @@ -2770,38 +2361,8 @@ static bool get_config(frontend *fe, int which) sfree(fe->cfgaux); return (fe->dlg_done == 2); -#endif } -#ifdef _WIN32_WCE -static void calculate_bitmap_position(frontend *fe, int x, int y) -{ - /* Pocket PC - center the game in the full screen window */ - int yMargin; - RECT rcClient; - - GetClientRect(fe->hwnd, &rcClient); - fe->bitmapPosition.left = (rcClient.right - x) / 2; - yMargin = rcClient.bottom - y; - - if (fe->numpad != NULL) { - RECT rcPad; - GetWindowRect(fe->numpad, &rcPad); - yMargin -= rcPad.bottom - rcPad.top; - } - - if (fe->statusbar != NULL) { - RECT rcStatus; - GetWindowRect(fe->statusbar, &rcStatus); - yMargin -= rcStatus.bottom - rcStatus.top; - } - - fe->bitmapPosition.top = yMargin / 2; - - fe->bitmapPosition.right = fe->bitmapPosition.left + x; - fe->bitmapPosition.bottom = fe->bitmapPosition.top + y; -} -#else static void calculate_bitmap_position(frontend *fe, int x, int y) { /* Plain Windows - position the game in the upper-left corner */ @@ -2810,7 +2371,6 @@ static void calculate_bitmap_position(frontend *fe, int x, int y) fe->bitmapPosition.right = fe->bitmapPosition.left + x; fe->bitmapPosition.bottom = fe->bitmapPosition.top + y; } -#endif static void new_bitmap(frontend *fe, int x, int y) { @@ -2830,12 +2390,12 @@ static void new_game_size(frontend *fe, float scale) int x, y; get_max_puzzle_size(fe, &x, &y); - midend_size(fe->me, &x, &y, false); + midend_size(fe->me, &x, &y, false, 1.0); if (scale != 1.0) { - x = (int)((float)x * fe->puzz_scale); - y = (int)((float)y * fe->puzz_scale); - midend_size(fe->me, &x, &y, true); + x = (int)((float)x * fe->puzz_scale); + y = (int)((float)y * fe->puzz_scale); + midend_size(fe->me, &x, &y, true, 1.0); } fe->ymin = (fe->xmin * y) / x; @@ -2849,26 +2409,19 @@ static void new_game_size(frontend *fe, float scale) } else { sr.left = sr.right = sr.top = sr.bottom = 0; } -#ifndef _WIN32_WCE SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left, r.bottom - r.top + sr.bottom - sr.top, SWP_NOMOVE | SWP_NOZORDER); -#endif check_window_size(fe, &x, &y); -#ifndef _WIN32_WCE if (fe->statusbar != NULL) SetWindowPos(fe->statusbar, NULL, 0, y, x, sr.bottom - sr.top, SWP_NOZORDER); -#endif new_bitmap(fe, x, y); -#ifdef _WIN32_WCE - InvalidateRect(fe->hwnd, NULL, true); -#endif midend_redraw(fe->me); } @@ -2895,13 +2448,13 @@ static void adjust_game_size(frontend *fe, RECT *proposed, bool isedge, ydiff = (proposed->bottom - proposed->top) - (wr.bottom - wr.top); if (isedge) { - /* These next four lines work around the fact that midend_size - * is happy to shrink _but not grow_ if you change one dimension - * but not the other. */ - if (xdiff > 0 && ydiff == 0) - ydiff = (xdiff * (wr.right - wr.left)) / (wr.bottom - wr.top); - if (xdiff == 0 && ydiff > 0) - xdiff = (ydiff * (wr.bottom - wr.top)) / (wr.right - wr.left); + /* These next four lines work around the fact that midend_size + * is happy to shrink _but not grow_ if you change one dimension + * but not the other. */ + if (xdiff > 0 && ydiff == 0) + ydiff = (xdiff * (wr.right - wr.left)) / (wr.bottom - wr.top); + if (xdiff == 0 && ydiff > 0) + xdiff = (ydiff * (wr.bottom - wr.top)) / (wr.right - wr.left); } if (check_window_resize(fe, @@ -2951,6 +2504,138 @@ static void update_type_menu_tick(frontend *fe) DrawMenuBar(fe->hwnd); } +static char *prefs_dir(void) +{ + const char *var; + if ((var = getenv("APPDATA")) != NULL) { + size_t size = strlen(var) + 80; + char *dir = snewn(size, char); + sprintf(dir, "%s\\Simon Tatham's Portable Puzzle Collection", var); + return dir; + } + return NULL; +} + +static char *prefs_path_general(const game *game, const char *suffix) +{ + char *dir, *path; + + dir = prefs_dir(); + if (!dir) + return NULL; + + path = make_prefs_path(dir, "\\", game, suffix); + + sfree(dir); + return path; +} + +static char *prefs_path(const game *game) +{ + return prefs_path_general(game, ".conf"); +} + +static char *prefs_tmp_path(const game *game) +{ + return prefs_path_general(game, ".tmp"); +} + +static void load_prefs(midend *me) +{ + const game *game = midend_which_game(me); + char *path = prefs_path(game); + if (!path) + return; + FILE *fp = fopen(path, "r"); + if (!fp) + return; + const char *err = midend_load_prefs(me, savefile_read, fp); + fclose(fp); + if (err) + fprintf(stderr, "Unable to load preferences file %s:\n%s\n", + path, err); + sfree(path); +} + +static char *save_prefs(midend *me) +{ + const game *game = midend_which_game(me); + char *dir_path = prefs_dir(); + char *file_path = prefs_path(game); + char *tmp_path = prefs_tmp_path(game); + HANDLE fh; + FILE *fp; + bool cleanup_dir = false, cleanup_tmpfile = false; + char *err = NULL; + + if (!dir_path || !file_path || !tmp_path) { + sprintf(err = snewn(256, char), + "Unable to save preferences:\n" + "Could not determine pathname for configuration files"); + goto out; + } + + if (!CreateDirectory(dir_path, NULL)) { + /* Ignore errors while trying to make the directory. It may + * well already exist, and even if we got some error code + * other than EEXIST, it's still worth at least _trying_ to + * make the file inside it, and see if that goes wrong. */ + } else { + cleanup_dir = true; + } + + fh = CreateFile(tmp_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (fh == INVALID_HANDLE_VALUE) { + char *os_err = geterrstr(); + sprintf(err = snewn(256 + strlen(tmp_path) + strlen(os_err), char), + "Unable to save preferences:\n" + "Unable to create file '%s':\n%s", tmp_path, os_err); + sfree(os_err); + goto out; + } else { + cleanup_tmpfile = true; + } + + fp = _fdopen(_open_osfhandle((intptr_t)fh, 0), "w"); + SetLastError(0); + midend_save_prefs(me, savefile_write, fp); + fclose(fp); + if (GetLastError()) { + char *os_err = geterrstr(); + sprintf(err = snewn(80 + strlen(tmp_path) + strlen(os_err), char), + "Unable to write file '%s':\n%s", tmp_path, os_err); + sfree(os_err); + goto out; + } + + if (MoveFileEx(tmp_path, file_path, MOVEFILE_REPLACE_EXISTING) < 0) { + char *os_err = geterrstr(); + sprintf(err = snewn(256 + strlen(tmp_path) + strlen(file_path) + + strlen(os_err), char), + "Unable to save preferences:\n" + "Unable to rename '%s' to '%s':\n%s", tmp_path, file_path, + os_err); + sfree(os_err); + goto out; + } else { + cleanup_dir = false; + cleanup_tmpfile = false; + } + + out: + if (cleanup_tmpfile) { + if (!DeleteFile(tmp_path)) { /* can't do anything about this */ } + } + if (cleanup_dir) { + if (!RemoveDirectory(dir_path)) { /* can't do anything about this */ } + } + sfree(dir_path); + sfree(file_path); + sfree(tmp_path); + return err; +} + static void update_copy_menu_greying(frontend *fe) { UINT enable = (midend_can_format_as_text_now(fe->me) ? @@ -2990,28 +2675,21 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, DestroyWindow(hwnd); return 0; case WM_COMMAND: -#ifdef _WIN32_WCE - /* Numeric pad sends WM_COMMAND messages */ - if ((wParam >= IDM_KEYEMUL) && (wParam < IDM_KEYEMUL + 256)) - { - midend_process_key(fe->me, 0, 0, wParam - IDM_KEYEMUL); - } -#endif cmd = wParam & ~0xF; /* low 4 bits reserved to Windows */ switch (cmd) { case IDM_NEW: - if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME)) + if (midend_process_key(fe->me, 0, 0, UI_NEWGAME) == PKR_QUIT) PostQuitMessage(0); break; case IDM_RESTART: midend_restart_game(fe->me); break; case IDM_UNDO: - if (!midend_process_key(fe->me, 0, 0, UI_UNDO)) + if (midend_process_key(fe->me, 0, 0, UI_UNDO) == PKR_QUIT) PostQuitMessage(0); break; case IDM_REDO: - if (!midend_process_key(fe->me, 0, 0, UI_REDO)) + if (midend_process_key(fe->me, 0, 0, UI_REDO) == PKR_QUIT) PostQuitMessage(0); break; case IDM_COPY: @@ -3033,7 +2711,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; case IDM_QUIT: - if (!midend_process_key(fe->me, 0, 0, UI_QUIT)) + if (midend_process_key(fe->me, 0, 0, UI_QUIT) == PKR_QUIT) PostQuitMessage(0); break; case IDM_CONFIG: @@ -3052,6 +2730,16 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (get_config(fe, CFG_PRINT)) print(fe); break; + case IDM_PREFS: + if (get_config(fe, CFG_PREFS)) { + char *prefs_err = save_prefs(fe->me); + if (prefs_err) { + MessageBox(fe->hwnd, prefs_err, "Error saving preferences", + MB_ICONERROR | MB_OK); + sfree(prefs_err); + } + } + break; case IDM_ABOUT: about(fe); break; @@ -3173,7 +2861,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; -#ifndef _WIN32_WCE case IDM_HELPC: start_help(fe, NULL); break; @@ -3182,34 +2869,38 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, start_help(fe, help_type == CHM ? fe->game->htmlhelp_topic : fe->game->winhelp_topic); break; -#endif - default: + default: { + unsigned n; + #ifdef COMBINED - if (wParam >= IDM_GAMES && wParam < (IDM_GAMES + (WPARAM)gamecount)) { - int p = wParam - IDM_GAMES; + n = (wParam - IDM_GAME_BASE) / MENUITEM_STEP; + if (n < gamecount && wParam == IDM_GAME_BASE + MENUITEM_STEP * n) { char *error = NULL; - fe_set_midend(fe, midend_for_new_game(fe, gamelist[p], NULL, + fe_set_midend(fe, midend_for_new_game(fe, gamelist[n], NULL, false, false, &error)); sfree(error); - } else + break; + } #endif - { + + n = (wParam - IDM_PRESET_BASE) / MENUITEM_STEP; + if (wParam == IDM_PRESET_BASE + MENUITEM_STEP * n) { game_params *preset = preset_menu_lookup_by_id( - fe->preset_menu, - ((wParam &~ 0xF) - IDM_PRESETS) / 0x10); + fe->preset_menu, n); if (preset) { midend_set_params(fe->me, preset); new_game_type(fe); + break; } } - break; + + break; + } } break; case WM_DESTROY: -#ifndef _WIN32_WCE stop_help(fe); -#endif frontend_free(fe); PostQuitMessage(0); return 0; @@ -3223,9 +2914,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, hdc = BeginPaint(hwnd, &p); hdc2 = CreateCompatibleDC(hdc); prevbm = SelectObject(hdc2, fe->bitmap); -#ifdef _WIN32_WCE - FillRect(hdc, &(p.rcPaint), (HBRUSH) GetStockObject(WHITE_BRUSH)); -#endif IntersectRect(&rcDest, &(fe->bitmapPosition), &(p.rcPaint)); BitBlt(hdc, rcDest.left, rcDest.top, @@ -3310,7 +2998,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } if (key != -1) { - if (!midend_process_key(fe->me, 0, 0, key)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) PostQuitMessage(0); } else { MSG m; @@ -3338,32 +3026,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else if (message == WM_RBUTTONDOWN || is_alt_pressed()) button = RIGHT_BUTTON; else -#ifndef _WIN32_WCE button = LEFT_BUTTON; -#else - if ((fe->game->flags & REQUIRE_RBUTTON) == 0) - button = LEFT_BUTTON; - else - { - SHRGINFO shrgi; - - shrgi.cbSize = sizeof(SHRGINFO); - shrgi.hwndClient = hwnd; - shrgi.ptDown.x = (signed short)LOWORD(lParam); - shrgi.ptDown.y = (signed short)HIWORD(lParam); - shrgi.dwFlags = SHRG_RETURNCMD; - - if (GN_CONTEXTMENU == SHRecognizeGesture(&shrgi)) - button = RIGHT_BUTTON; - else - button = LEFT_BUTTON; - } -#endif - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); SetCapture(hwnd); @@ -3387,10 +3055,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else button = LEFT_RELEASE; - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); ReleaseCapture(); @@ -3407,10 +3075,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else button = LEFT_DRAG; - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); } break; @@ -3424,7 +3092,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, (keystate[VK_CONTROL] & 0x80)) key = UI_REDO; } - if (!midend_process_key(fe->me, 0, 0, key)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) PostQuitMessage(0); } return 0; @@ -3436,7 +3104,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, fe->timer_last_tickcount = now; } return 0; -#ifndef _WIN32_WCE case WM_SIZING: { RECT *sr = (RECT *)lParam; @@ -3468,29 +3135,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return true; } break; -#endif } return DefWindowProc(hwnd, message, wParam, lParam); } -#ifdef _WIN32_WCE -static int FindPreviousInstance() -{ - /* Check if application is running. If it's running then focus on the window */ - HWND hOtherWnd = NULL; - - hOtherWnd = FindWindow (wGameName, wGameName); - if (hOtherWnd) - { - SetForegroundWindow (hOtherWnd); - return true; - } - - return false; -} -#endif - /* * Split a complete command line into argc/argv, attempting to do it * exactly the same way the Visual Studio C library would do it (so @@ -3723,12 +3372,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) split_into_argv(cmdline, &argc, &argv, NULL); -#ifdef _WIN32_WCE - MultiByteToWideChar (CP_ACP, 0, CLASSNAME, -1, wClassName, 256); - if (FindPreviousInstance ()) - return 0; -#endif - InitCommonControls(); if (!prev) { @@ -3740,18 +3383,12 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) wndclass.cbWndExtra = 0; wndclass.hInstance = inst; wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(200)); -#ifndef _WIN32_WCE if (!wndclass.hIcon) /* in case resource file is absent */ wndclass.hIcon = LoadIcon(inst, IDI_APPLICATION); -#endif wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; -#ifdef _WIN32_WCE - wndclass.lpszClassName = wClassName; -#else wndclass.lpszClassName = CLASSNAME; -#endif RegisterClass(&wndclass); } -- cgit v1.2.3