#include // bool #include // atoi() #include // EXIT_{FAILURE,SUCCESS} #include #include "../libsok/sok.h" #define UNUSED(a) ((void) (a)) #define CASE_DIGIT \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': typedef struct { char *pack, *name, *data; } level_t; static const level_t LEVELS[] = {{ .pack = "Tutorials", .name = "Hello World!", .data = "5#|#@$.#|5#", }, { .pack = "Tutorials", .name = "Plus", .data = "7#|3#.3#|3#$3#|#.$@$.#|3#$3#|3#.3#|7#", }, { .pack = "Microban", .name = "Level 1", .data = "4#|# .#|# 3#|#*@ #|# $ #|# 3#|4#", }, { .pack = "Microban", .name = "Level 2", .data = "6#|#4 #|# #@ #|# $* #|# .* #|#4 #|6#", }, { .pack = "Microban", .name = "Level 3", .data = " 4#|3# 4#|#5 $ #|# # #$ #|# . .#@ #|9#", }, { .pack = "Microban", .name = "Level 4", .data = "8#|#6 #|# .**$@#|#6 #|5# #|4 4#", }, { .pack = "Microban", .name = "Level 5", .data = " 7#| #5 #| # .$. #|## $@$ #|# .$. #|#6 #|8#", }, { .pack = "Microban", .name = "Level 6", .data = "6# 5#|#4 3#3 #|# $$5 #@#|# $ #3.3 #|#3 8#|5#", }, { .pack = "Microban", .name = "Level 7", .data = "7#|#5 #|# .$. #|# $.$ #|# .$. #|# $.$ #|# @ #|7#", }, { .pack = "Microban", .name = "Level 8", .data = " 6#| # ..@#| # $$ #| ## 3#|3 # #|3 # #|4# #|#4 ##|# #3 #|#3 # #|3#3 #| 5#", }, { .pack = "Microban", .name = "Level 9", .data = "5#|#. ##|#@$$ #|##3 #| ## #| ##.#|3 3#", }, { .pack = "Microban", .name = "Level 10", .data = "6 5#|6 #. #|6 #.# #|7#.# #|# @ $ $ $ #|# # # # 3#|#7 #|9#", }, { .pack = "Microban", .name = "Level 11", .data = " 6#| #4 #| # ##@##|3# # $ #|# ..# $ #|#7 #|# 6#|4#", }, { .pack = "Microban", .name = "Level 12", .data = "5#|#3 ##|# $ #|## $ 4#| 3#@. #| # .# #| #5 #| 7#", }, { .pack = "Microban", .name = "Level 13", .data = "4#|#. ##|#.@ #|#. $#|##$ 3#| # $ #| #4 #| # 3#| 4#", }, { .pack = "Microban", .name = "Level 14", .data = "7#|#5 #|# # # #|#. $*@#|#3 3#|5#", }, { .pack = "Microban", .name = "Level 15", .data = "5 3#|6#@##|#4 .* #|#3 #3 #|5#$# #|4 #3 #|4 5#", }, { .pack = "Microban", .name = "Level 16", .data = " 4#| # 4#| #5 ##|## ##3 #|#. .# @$##|#3 # $$ #|# .#4 #|10#", }, { .pack = "Microban", .name = "Level 17", .data = "5#|# @ #|#3.#|#3$##|#4 #|#4 #|6#", }, { .pack = "Microban", .name = "Level 18", .data = "7#|#5 #|#. . #|# ## ##|# $ #|3#$ #| #@ #| # #| 4#", }, { .pack = "Microban", .name = "Level 19", .data = "8#|#3 .. #|# @$$ #|5# ##|3 # #|3 # #|3 # #|3 4#", }, { .pack = "Microban", .name = "Level 20", .data = "7#|#5 3#|# @$$..#|4# ## #| #5 #| # 4#| # #| 4#", }, { .pack = "Microban", .name = "Level 21", .data = "4#|# 4#|# . . #|# $$#@#|##4 #| 6#", }, { .pack = "Microban", .name = "Level 22", .data = "5#|#3 3#|#. . #|#3 # #|## # #| #@$$ #| #4 #| # 3#| 4#", }, { .pack = "Microban", .name = "Level 23", .data = "7#|# * #|#5 #|## # ##| #$@.#| #3 #| 5#", }, { .pack = "Microban", .name = "Level 24", .data = "# 5#| #3 #|3#$$@#|#3 3#|#5 #|# . . #|7#", }, { .pack = "Microban", .name = "Level 25", .data = " 4#| # 3#| # $$ #|##3. #|# @$ #|#3 3#|5#", }, { .pack = "Microban", .name = "Level 26", .data = " 5#| # @ #| #3 #|3#$ #|# 3.#|# $$ #|3# #| 4#", }, { .pack = "Microban", .name = "Level 27", .data = "6#|#3 .#|# ## ##|# $$@#|# #3 #|#. 3#|5#", }, { .pack = "Microban", .name = "Level 28", .data = "5#|#3 #|# @ #|# $$3#|##. . #| #4 #| 6#", }, { .pack = "Microban", .name = "Level 29", .data = "5 5#|5 #3 ##|5 #4 #| 6#3 #|##5 #. #|# $ $ @ ##|# 6#.#|#8 #|10#", }, { .pack = "Microban", .name = "Level 30", .data = "4#|# 3#|# $$ #|#3. #|# @$ #|#3 ##|5#", }, { .pack = "Microban", .name = "Level 31", .data = " 4#| ## #|##@$.##|# $$ #|# . . #|3#3 #| 5#", }, { .pack = "Microban", .name = "Level 32", .data = " 4#|## 3#|#5 #|#.**$@#|#3 3#|## #| 4#", }, { .pack = "Microban", .name = "Level 33", .data = "7#|#. # #|# $ #|#. $#@#|# $ #|#. # #|7#", }, { .pack = "Microban", .name = "Level 34", .data = " 4#|3# 4#|#7 #|#@$***. #|#7 #|9#", }, { .pack = "Microban", .name = "Level 35", .data = " 4#| ## #| #. $#| #.$ #| #.$ #| #.$ #| #. $##| #3 @#| ##3 #| 5#", }, { .pack = "Microban", .name = "Level 36", .data = "4#|# 12#|# $ $ $ $ $ @ #|# 5.7 #|15#", }, { .pack = "Microban", .name = "Level 37", .data = "6 3#|5# #.#|#3 3#.#|#3 $ #.#|# $ $ #|5#@# #|4 #3 #|4 5#", }, { .pack = "Microban", .name = "Level 38", .data = "10#|#8 #|# ##.3# #|# # $$ . #|# . @$## #|5#4 #|4 6#", }, { .pack = "Microban", .name = "Level 39", .data = "5#|#3 4#|# # # .#|#4 $ 3#|3# #$. #|#3 #@3 #|# # 6#|#3 #|5#", }, { .pack = "Microban", .name = "Level 40", .data = " 5#| #3 #|##3 ##|# 3$ #|# .+. #|7#", }, { .pack = "Microban", .name = "Level 41", .data = "7#|#5 #|#@3$ ##|# #3.#|##4 ##| 6#", }, { .pack = "Microban", .name = "Level 42", .data = "3 4#|3 # #|3 #@ #|4#$.#|#3 $.#|# # $.#|#4 ##|6#", }, { .pack = "Microban", .name = "Level 43", .data = "5 4#|5 # @#|5 # #|6# .#|#3 $ .#|# $$# .#|#4 4#|3# #| 4#", }, { .pack = "Microban", .name = "Level 44: Duh!", .data = "5#|#@$.#|5#", }, { .pack = "Microban", .name = "Level 45", .data = "6#|#3. #|# $ #|# #$##|# $ #|# @ #|6#", }, { .pack = "Microban", .name = "Level 46", .data = " 6#|##4 #|# ## #|# # $ #|# * .#|## #@##| #3 #| 5#", }, { .pack = "Microban", .name = "Level 47", .data = " 7#|3#5 #|# $ $3 #|# 3# 5#|# @ . .3 #|#3 3#3 #|5# 5#", }, { .pack = "Microban", .name = "Level 48", .data = "6#|# @ #|# # ##|# .# ##|# .3$ #|# .#3 #|4#3 #|3 5#", }, { .pack = "Microban", .name = "Level 49", .data = "6#|# @ #|# $# #|# $ #|# $ ##|3# 4#| # # #| #3. #| #5 #| 7#", }, { .pack = "Microban", .name = "Level 50", .data = " 4#|3# 5#|# $ @..#|# $4 # #|3# 4# #| #6 #| 8#", }, { .pack = "Microban", .name = "Level 51", .data = "4#|# 3#|#4 3#|# $*@ #|3# .# #| #4 #| 6#", }, { .pack = "Microban", .name = "Level 52", .data = " 4#|3# @#|# $ #|# *.#|# *.#|# $ #|3# #| 4#", }, { .pack = "Microban", .name = "Level 53", .data = " 5#|##. .##|# * * #|# # #|# $ $ #|## @ ##| 5#", }, { .pack = "Microban", .name = "Level 54", .data = "6 6#|6 #4 #| 5# . #|3# 3#. #|# $ $ . ##|# @$$ # . #|##4 5#| 6#", }, { .pack = "Microban", .name = "Level 55", .data = "8#|# @ # #|#6 #|5#$ #|4 # 3#| ## #$ ..#| ## # 3#|4 4#", }, { .pack = "Microban", .name = "Level 56", .data = "5#|#3 3#|# $ #|##* . #| #3 @#| 6#", }, { .pack = "Microban", .name = "Level 57", .data = " 4#| # #| #@ #| # #|3# 4#|#4 * #|# $3 #|5#. #|4 4#", }, { .pack = "Microban", .name = "Level 58", .data = "4#|# 4#|#.*$ #|# .$# #|## @ #| #3 ##| 5#", }, { .pack = "Microban", .name = "Level 59", .data = "12#|#10 #|# 7# @##|# #9 #|# # $3 # #|# $$ 5# #|3# # # 3.#| 4# #4 #|7 6#", }, { .pack = "Microban", .name = "Level 60", .data = " 9#| #7 #|##@5# #|# #3 # #|# #3 $.#|# ##$##.#|##$## #.#|#3 $ #.#|#3 # 3#|8#", }, { .pack = "Microban", .name = "Level 61", .data = "8#|#6 #|# 4# #|# #3.@#|# 3#$3#|# #5 #|# $$ $ #|4#3 ##|3 #.3#|3 3#", }, { .pack = "Microban", .name = "Level 62", .data = "3 10#|4#4 ## #|# 3$4.$@#|#6 3# #|#3 4# 4#|5#", }, { .pack = "Microban", .name = "Level 63", .data = "5#3 4#|#3 5# .#|#7 $ 8#|3# 4# .$4 @ #| # # # 4#3 #| 4# 4# 5#", }, { .pack = "Microban", .name = "Level 64", .data = " 6#|##4 #|#3 $ #|# $$ #|3# .5#| ##.# @ #|3 #. $ #|3 #. 4#|3 4#", }, { .pack = "Microban", .name = "Level 65", .data = " 6#| #4 #| # $ #| 4#$ #|## $ $ #|#4.# ##|#5 @ #|## #3 #| 8#", }, { .pack = "Microban", .name = "Level 66", .data = "3 3#|3 #@#| 3#$3#|## . ##|# # # #|# #3 # #|# #3 # #|# #3 # #|# # # #|## $ $ ##| ##. .##| #3 #| #3 #| 5#", }, { .pack = "Microban", .name = "Level 67", .data = "5#|#3 ##|# # #|#@$*.##|## . #| # $# #| ##3 #| 5#", }, { .pack = "Microban", .name = "Level 68", .data = " 4#| # 6#|##4 $ #|# .# $3 #|# .#$5#|# .@ #|6#", }, { .pack = "Microban", .name = "Level 69", .data = "4# 4#|# 4# #|# # # #|# #4 $##|# . .#$ #|#@ ## # $ #|#3 . #3 #|11#", }, { .pack = "Microban", .name = "Level 70", .data = "5#|# @ 4#|#6 #|# $ $$ #|##$## #|#3 4#|# .. #|##.. #| 3# #|3 4#", }, { .pack = "Microban", .name = "Level 71", .data = "11#|#5 #3 3#|# $@$ # . .#|# ## 3# ## #|# #7 # #|# #3 #3 # #|# 9# #|#11 #|13#", }, { .pack = "Microban", .name = "Level 72", .data = " 4#| ## 5#| # $ @ #| # $#3 #|4# 5#|# #3 #|#4 $ #|# ..# #|# .4#|# ##|4#", }, { .pack = "Microban", .name = "Level 73", .data = "4#|# 5#|# $$ $ #|#6 #|## ## ##|#3.#@#|# 3# ##|#6 #|# #3 #|8#", }, { .pack = "Microban", .name = "Level 74", .data = " 4#| # 7#| #$ @#3 .#|## #$$3 .#|# $ ##..#|#3 # 5#|3#3 #| 5#", }, { .pack = "Microban", .name = "Level 75", .data = " 7#|## 4.##|#3 6#|#3 $ $ @#|3# $ $ #| 3#4 #|4 6#", }, { .pack = "Microban", .name = "Level 76", .data = " 5#|##3 #|#4 5#|# #.#3 #|#@ #.# $ #|# #.# ##|#4 # #|## ##$$#| ##5 #| # 4#| 4#", }, { .pack = "Microban", .name = "Level 77", .data = "10#|# @ 4. #|#3 4#$##|## # $ $ #| # $6 #| #3 6#| 5#", }, { .pack = "Microban", .name = "Level 78", .data = " 7#|##5 ##|# $ $ #|# $ $ $ #|## 3# 4#| #@ 5.#| ##5 3#| 7#", }, { .pack = "Microban", .name = "Level 79", .data = " 9#| #4 # #|## $#$# #|# .$.@ #|# .#4 #|10#", }, { .pack = "Microban", .name = "Level 80", .data = "4#|# 7#|# . ## .#|# $#4 .#|## ## # .#| #4 # #| 4# # #| # @$ 3#| # $$ #| #4 #| 6#", }, { .pack = "Microban", .name = "Level 81", .data = " 5#| #3 #| # . #|## * #|# *##|# @##|## $ #| #3 #| 5#", }, { .pack = "Microban", .name = "Level 82", .data = "5#|#3 3#|# .3 ##|##*#$ #|# .# $ #|# @## ##|#5 #|7#", }, { .pack = "Microban", .name = "Level 83", .data = "6#|#4 ##|# $ $ ##|## $$ #| # #3 #| # ## ##| # . .#| # @. .#| # 4#| 4#", }, { .pack = "Microban", .name = "Level 84", .data = "8#|# 3. #|# 3# ##|# # $ #|## #@$ #| # # $ #| # 3# 5#| #9 #| #3 3#3 #| 5# 5#", }, { .pack = "Microban", .name = "Level 85", .data = "7 4#| 7# #| # $6 #| #3 $ $ #| # 8#|## # . #|# # # #|# @ . ##|## # # #| #3 . #| 7#", }, { .pack = "Microban", .name = "Level 86", .data = "4 4#| 3# ##| ## $3 #|## $ # #|# @#$$ #|# .. 3#|# ..3#|5#", }, { .pack = "Microban", .name = "Level 87", .data = "5 4#|6# #|#7 #|# 3. .#|##$6#|# $ #|#3 $3#|## $ #| ## @ #| 6#", }, { .pack = "Microban", .name = "Level 88", .data = "5 4#| # 3# #| # #4 #| # # # #| # #$ #.#| # # # # #| # #$ #.# #|3 # # # #|4#$ #.# #|# @5 # #|#3 # ## #|8#", }, { .pack = "Microban", .name = "Level 89", .data = "10#|#3 ##3 #|# $ $@# #|4# # $ #|3 #.# ##| # #.# $#| # #.3 #| # #.3 #|3 6#", }, { .pack = "Microban", .name = "Level 90", .data = " 8#| # @3 #| # $ $ #|3# ## 3#|# $..$ #|#3 ..3 #|10#", }, { .pack = "Microban", .name = "Level 91", .data = "11#|#4 .## #|# $$@..$$ #|#3 ##.3 #|11#", }, { .pack = "Microban", .name = "Level 92", .data = " 4#| # #4 5#| # #4 #3 #| # 6#.# #|4# $4 . #|#3 $$# 3#.# #|#3 #3 # #3 #|9# #@ ##|10 # #|10 4#", }, { .pack = "Microban", .name = "Level 93", .data = " 9#|##3 #3 ##|#4 #4 #|# $ # $ #|#3 *.*3 #|4#.@.4#|#3 *.*3 #|# $ # $ #|#4 #4 #|##3 #3 ##| 9#", }, { .pack = "Microban", .name = "Level 94", .data = "9#|# @ #3 #|# $ $3 #|##$3# ##|# 3. #|#3 #3 #|6# #|5 4#", }, { .pack = "Microban", .name = "Level 95", .data = "8#|#@5 #|# .$$. #|# $..$ #|# $..$ #|# .$$. #|#6 #|8#", }, { .pack = "Microban", .name = "Level 96", .data = " 6#| #4 #| #4 #|5# #|#3 #.5#|#3 $@$3 #|5#.#3 #|3 ## ## ##|3 #3 $.#|3 #3 3#|3 5#", }, { .pack = "Microban", .name = "Level 97", .data = "3 4#|3 # 8#|4# $ $5.#|#3 $3 6#|#@3# 3#|# $ #|# $ # #|## # #| #4 #| 6#", }, { .pack = "Microban", .name = "Level 98", .data = "5#|#3 ## 4#|# $ 3# .#|# $3 $ .#|## $5#.# 4#|# $ # # .3# #|#4 # # .# @ #|3# # #7 #| 4# ##5 ##|8 7#", }, { .pack = "Microban", .name = "Level 99", .data = "15 5#|15 #3 #|7# 7# # #|#5 # # #6 #|# @ 4# #5 4#|# #4 4.## 4# #|#4 5# ## $$ $ $ #|6#3 #11 #|9 # 10#|9 4#", }, { .pack = "Microban", .name = "Level 100", .data = "7#|# @# #|#.$3 #|#. # $##|#.$#3 #|#. # $ #|# #3 #|8#", }, { .pack = "Microban", .name = "Level 101: Lockdown", .data = " 5#| #3 #| # # 7#| # * #3 #| ## ##3 # #| #5 #* #|3# # # # 3#|# *#$+3 #|# #3 ## ##|#3 # * #|7# # #|6 #3 #|6 5#", }, { .pack = "Microban", .name = "Level 102", .data = "11#|#4.#4 #|# #3 $$ #|# @ ## #|#5 ##$ #|6# $ #|5 #4 #|5 6#", }, { .pack = "Microban", .name = "Level 103", .data = " 5#| # . ##|3# $ #|# . $#@#|# #$ . #|# $ 3#|## . #| 5#", }, { .pack = "Microban", .name = "Level 104", .data = "4 5#|5#3 #|#4 $ #|# $#$#@#|3# #3 #| # 3. #| 3# ##|4 # #|4 4#", }, { .pack = "Microban", .name = "Level 105", .data = " 4# 4#|## 3# ##|#3 # #3 #|# *. .* #|3#$3 $3#| #3 @3 #|3#$3 $3#|# *. .* #|#3 # #3 #|## 3# ##| 4# 4#", }, { .pack = "Microban", .name = "Level 106", .data = " 8#| #6 #| #@3 $ #|## 3#$ #|# 5.3#|# $ $ $ #|6# # #|5 #3 #|5 5#", }, { .pack = "Microban", .name = "Level 107", .data = "8#|#6 #|# $*** #|# * * #|# * * #|# ***. #|#5 @#|8#", }, { .pack = "Microban", .name = "Level 108", .data = "4#5 5#|# 3#3 #3 ##|#4 #3 #$ $ #|#..# 5# # #|# @4 # $ $ #|#..#9 ##|##3 9#| 5#", }, { .pack = "Microban", .name = "Level 109", .data = " 7#|# #5 #|# # # # #| # @ $ #|3# 3# #|#3 3# #|# $ ##.#|## $ #.#| ## $ .#|# ## $#.#|## ## #.#|3# #3 #|3# 5#", }, { .pack = "Microban", .name = "Level 110", .data = " 4#| # #| # $4#|3#. . #|# $ # $ #|# . .3#|4#$ #|3 # @#|3 4#", }, { .pack = "Microban", .name = "Level 111", .data = "6#|#4 4#|#4 3.#|#4 3.#|6# #| # # #| # $$ ##| # @$ #| # $$ #| ## $# #|3 #4 #|3 6#", }, { .pack = "Microban", .name = "Level 112", .data = " 5#|##3 4#|# 3$ #|# #3 $ #|#3 $## ##|3# #. #| # #3 #| 5# 3#| #3 # ##| # @4.#| #6 #| #3 # #| 8#", }, { .pack = "Microban", .name = "Level 113", .data = "3 5#| ##3 #|3# # #|#4 . #|# ## 5#|# . . # ##|# # @ $3 3#|5#. # $ #|4 4# $ #|7 ## $ ##|8 # ##|8 # #|8 4#", }, { .pack = "Microban", .name = "Level 114", .data = "6#|#4 3#|# # $ #|# $ @ #|## ## 5#|# #6.#|# $ $ $ $ #|##3 6#| 5#", }, { .pack = "Microban", .name = "Level 115", .data = "4 5#|5#3 4#|#5 #4 #|# #5. #|## ## # 3#| #$$@3$ #| #5 3#| 7#", }, { .pack = "Microban", .name = "Level 116", .data = "5 5#|3 3#3 #|4#5.#|# @5$ #|#5 # ##|5#3 #|4 5#", }, { .pack = "Microban", .name = "Level 117", .data = " 4# 4#| # 3# ##| #6 @ #|##..3#3 #|#6 # #|#3.#$ # #|# ## $$ $ #|# $4 3#|4# 3#|3 4#", }, { .pack = "Microban", .name = "Level 118", .data = " 5#|##3 ##|# $ ##|# $ $ ##|3#$# . ##| # # . #| ## ##. #| # @ . ##| #3 # #| 8#", }, { .pack = "Microban", .name = "Level 119", .data = " 6#| #4 ##| ## ## #| # $$ # #| # @$ # #| #4 # #|4# # #|# 3. ##|#5 ##|7#", }, { .pack = "Microban", .name = "Level 120", .data = "6 4#|7# #|# $6 ##|# $5# #|# @# # #|## ##..3 #|# # ..4#|# $ 3#|# $3#|# #|4#", }, { .pack = "Microban", .name = "Level 121", .data = " 6#| # . #|##$.# #|# * #|# ..3#|##$ # 5#|## ## #3 #|# 4# # #|#3 @ $ $ #|## #5 #| 10#", }, { .pack = "Microban", .name = "Level 122", .data = "5#|#3 3#|# #$ #|# $3 #|# $ $ #|# $# #|# @3#|## 8#|#6 3.#|#9 #|8#..#|7 4#", }, { .pack = "Microban", .name = "Level 123", .data = "8#|#6 #|# $ $$ 8#|5# @##. . #|4 #$ # .3 #|4 #3 #. . ##|4 #$# ## # #|4 #8 #|4 # 3# ##|4 # # 4#|4 4#", }, { .pack = "Microban", .name = "Level 124", .data = "14#|#6 #5 #|# $@$$ # . ..#|## ## 3# ## #| # #7 # #| # #3 #3 # #| # 9# #| #11 #| 13#", }, { .pack = "Microban", .name = "Level 125", .data = "6 5#|6 #3 ##|6 # $ #|8# #@##|# . # $ $ #|#8 $# #|#3.5#3 #|5#3 5#", }, { .pack = "Microban", .name = "Level 126", .data = " 11#|##7. #|# 7$@ #|#3 # # # ##|# # #5 #|#3 7#|5#", }, { .pack = "Microban", .name = "Level 127", .data = "## 4#|4# 4#| # $ $. #|## # .$ #|#3 ##.3#|# $ . #|# @ #3 #|# 6#|4#", }, { .pack = "Microban", .name = "Level 128", .data = " 9#|3#3 #3 #|# * $ . . #|#3 $ ## ##|4#*#3 #| # @ 3#| #3 3#| 5#", }, { .pack = "Microban", .name = "Level 129", .data = " 9#|3# @ #3 #|# * $ *.. #|#3 $ #3 #|4#*# 3#| #5 ##| #3 3#| 5#", }, { .pack = "Microban", .name = "Level 130", .data = "5# 5#|#3 4#.. #|# 3$6 #|#3 $# .. #|3# @# ## #| # ##4 #| 10#", }, { .pack = "Microban", .name = "Level 131", .data = "5#|#3 #|# . #|#.@.3#|##.# #|# $ #|# $3 #|##$$ #| # 3#| # #| 4#", }, { .pack = "Microban", .name = "Level 132", .data = "4#|# @3#|#.* 5#|#..#$$ $ #|##7 #| # # ## #| #3 5#| 5#", }, { .pack = "Microban", .name = "Level 133", .data = " 7#| # . .3#| # . . . #|3# 4# #|# @$ $ #|# $$ $ #|4#3 3#|3 5#", }, { .pack = "Microban", .name = "Level 134", .data = "8 4#|9# #|#3 ## $3 #|# $3 ## #|3# #. .# ##| # #. .#$##| # #3 # #| # @ $4 #| # 7#| 4#", }, { .pack = "Microban", .name = "Level 135", .data = "7#|#5 5#|# $$#@##..#|# #7 #|# $ # # #|4# $ ..#|3 8#", }, { .pack = "Microban", .name = "Level 136", .data = " 7#| #5 #|## 3#$##|#.$3 @ #|# .. #$ #|#.## $ #|#4 4#|6#", }, { .pack = "Microban", .name = "Level 137", .data = "7 4#|6 ## 3#|4# # $ #|# 4# $ $ #|#3 ..# #$ #|# #3 @ 3#|## #..# 3#| # ## # #| #6 #| 8#", }, { .pack = "Microban", .name = "Level 138", .data = " 4#|3# #|#4 3#|# # . .#|# @ 3.4#|# # # #3 ##|#3 # $$3 #|5# $ $ #|4 ##$ # ##|5 #4 #|5 6#", }, { .pack = "Microban", .name = "Level 139", .data = " 4#|## 4#|#3 3.#|#3 3.#|#3 # ##|#3 #@ 4# 4#|5# $3 3# #|4 # ##$ $3 #|3 3#5 $$ #|3 # $ ##3 3#|3 #4 6#|3 6#", }, { .pack = "Microban", .name = "Level 140", .data = "8# 5#|# #3 3#3 #|#6 ## $ #|#.# @ ## $ ##|#.#3 # $ ##|#.#4 $ ##|#. ## 5#|##4 #| 6#", }, { .pack = "Microban", .name = "Level 141", .data = " 8#| # # . #| #3 .*.#| # # * #|4#$##.##|#6 $ #|# $ ## $ #|#3 @#3 #|10#", }, { .pack = "Microban", .name = "Level 142", .data = " 4#| # #| # 4#|3#$.$ #|# .@. #|# $.$3#|4# #|3 # #|3 4#", }, { .pack = "Microban", .name = "Level 143", .data = "4#|# 4#|# $3 #|# .# #|# $# ##|# . #|4# #|3 # #| 3# 3#| # $ #|## #$# ##|# $ @ $ #|# ..#.. #|3#3 3#| 5#", }, { .pack = "Microban", .name = "Level 144", .data = "3 4#| 3# 5#| # $$ #3 #| # $ . .$$##| # .. #. $ #|3# #** . #|# . **# 3#|# $ .# .. #|##$$.@. $ #| #3 # $$ #| 5# 3#|5 4#", }, { .pack = "Microban", .name = "Level 145", .data = "3 5#|3 # @ #| ##3 ##|3#.3$.3#|# $3.$ #|# $.#.$ #|# $3.$ #|3#.3$.3#| ##3 ##|3 #3 #|3 5#", }, { .pack = "Microban", .name = "Level 146", .data = " 7#|## . ##|# .3$. #|# $. .$ #|#.$ @ $.#|# $. .$ #|# .3$. #|## . ##| 7#", }, { .pack = "Microban", .name = "Level 147: reduction of (Mas Sasquatch 8)", .data = "7 5#|8#3 #|#.3 . @#.#|# 3#5 #|## $ #4 #| # $3 5#| # $# #| ## # #| #3 ##| 5#", }, { .pack = "Microban", .name = "Level 148: from (Original 18)", .data = "11#|# . #3 #|# #. @3 #|# #..# 7#|## ## $$ $ $ #| ##11 #| 13#", }, { .pack = "Microban", .name = "Level 149: from (Boxxle 43)", .data = " 4#|## 3#|#@$3 #|3# $ #| # 6#| # $4.#| # # 4#| ## # #| # $# #| #4 #| # 3#| 4#", }, { .pack = "Microban", .name = "Level 150: from (Original 47)", .data = "5 4#| 5# #| #5 $7#|## ## ..# 3.#|# $ $$#$ @3 #|#8 3# #|7# # 4#|6 4#", }, { .pack = "Microban", .name = "Level 151: from (Original 47)", .data = "3 4#|3 # #| 3# #|## $ #|#3 # #|# #$$ 6#|# #3 #3 .#|# $ @3 .#|3# 4#..#| 4# 4#", }, { .pack = "Microban", .name = "Level 152: reduced (Mas Sasquatch 23)", .data = "6# 4#|#5 #4 #|#.## #$## #|#3 #5 # #|#$ # 3# # #|# #6 # # #|# # 4# # # #|#. @4 $ * . #|15#", }, { .pack = "Microban", .name = "Level 153: reduction of (Revenge 306)", .data = "13#|#.# @# #3 #|#.#$$3 # $ #|#.# # $#3 #|#.# $# # $##|#.# # $# #|#.# $# # $#|#.. # $3 #|#.. # # #|12#", }, { .pack = "Microban", .name = "Level 154: Take the long way home.", .data = " 28#| #26 #| # 24# #| # #22 # #| # # 20# # #| # # #18 # # #| # # # 16# # # #| # # # #14 # # # #| # # # # 12# # # # #| # # # # #12 # # # #| # # # # # 12# # # #| # # # # #14 # # #| # # # # 16# # #| # # # #18 # #|##$# # 20# #|#. @ #22 #|29#", }, { .pack = "Microban", .name = "Level 155: The Dungeon", .data = "4 6#15 4#|5#*# 17# ##|#3 3#22 #|#8 8# 4# ## #|3# 4#5 # 4# 4# ##|#*# # .# # # #5 #5 #3 #|#*# # #5 # ## # ## ## #|3#4 3# 3# # ## # ## ##| #3 # #*#6 #5 # #4 #| #3 # 3# 5# 4# #4 #| 5#3 5# 7# 6#| #3 # # #**#15 #|## # #3 #**# 7# ## #|#4 9# #4 5# 3#|# #13 # $8 #*#|#3 9# 3# @5# #*#|5#7 4# 4#3 6#", }, { .pack = "", .name = "", .data = "", }}; #define NUM_LEVELS (sizeof(LEVELS) / sizeof(level_t)) static char print_buf[(SOK_LEVEL_MAX_WIDTH + 1) * SOK_LEVEL_MAX_HEIGHT + 1]; static bool on_size( const sok_ctx_t * const ctx, const sok_pos_t size, void * const data ) { UNUSED(ctx); UNUSED(data); // fprintf(stderr, "size: x = %u, y = %u\n", size.x, size.y); memset(print_buf, ' ', sizeof(print_buf)); print_buf[(size.x + 1) * size.y + 1] = '\0'; for (size_t i = 0; i < size.y; i++) { print_buf[(i + 1) * (size.x + 1) - 1] = '\n'; } return true; } static bool on_home( const sok_ctx_t * const ctx, const sok_pos_t pos, const bool has_goal, void * const data ) { UNUSED(data); print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = has_goal ? '+' : '@'; return true; } static bool on_wall( const sok_ctx_t * const ctx, const sok_pos_t pos, void * const data ) { // fprintf(stderr, "wall: x = %u, y = %u\n", pos.x, pos.y); UNUSED(data); print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = '#'; return true; } static bool on_goal( const sok_ctx_t * const ctx, const sok_pos_t pos, const bool has_player, const bool has_box, void * const data ) { UNUSED(data); const char c = has_player ? '+' : (has_box ? '*' : '.'); print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = c; return true; } static bool on_box( const sok_ctx_t * const ctx, const sok_pos_t pos, const bool has_goal, void * const data ) { UNUSED(data); print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = has_goal ? '*' : '$'; return true; } static sok_ctx_walk_cbs_t PRINT_CBS = { .on_size = on_size, .on_home = on_home, .on_wall = on_wall, .on_goal = on_goal, .on_box = on_box, }; static void print_level( const sok_ctx_t * const ctx ) { // fill buffer if (!sok_ctx_walk(ctx, &PRINT_CBS, NULL)) { fprintf(stderr, "Couldn't print level\n"); exit(EXIT_FAILURE); } // print level printf("%s\n", print_buf); } static void solve_on_error( const char * const err ) { fprintf(stderr, "Error solving level: %s\n", err); exit(EXIT_FAILURE); } static void print_moves( const sok_ctx_t * const ctx, const size_t skip_moves ) { printf("Moves (%zu): ", ctx->num_moves - skip_moves); for (size_t i = skip_moves; i < ctx->num_moves; i++) { switch (ctx->moves[i].dir) { case SOK_DIR_UP: fputs("u", stdout); break; case SOK_DIR_DOWN: fputs("d", stdout); break; case SOK_DIR_LEFT: fputs("l", stdout); break; case SOK_DIR_RIGHT: fputs("r", stdout); break; default: fprintf(stderr, "Error: invalid move: %u", ctx->moves[i].dir); exit(EXIT_FAILURE); } } printf("\n"); } int main(int argc, char *argv[]) { size_t level = (argc > 1) ? atoi(argv[1]) : 0; // init context sok_ctx_t ctx; sok_ctx_init(&ctx, NULL); if (!sok_ctx_set_level(&ctx, LEVELS[level].data)) { fprintf(stderr, "Couldn't load level %zu\n", level); return EXIT_FAILURE; } char buf[1024]; bool done = false; while (!done) { printf("%s: %s (#%zu)\n", LEVELS[level].pack, LEVELS[level].name, level); print_level(&ctx); printf("%zu%s> ", ctx.num_moves, sok_ctx_is_done(&ctx) ? " (won!)" : ""); if (!fgets(buf, sizeof(buf), stdin)) { done = true; break; } switch (buf[0]) { case EOF: case 'q': done = true; break; case 'k': if (!sok_ctx_move(&ctx, SOK_DIR_UP)) { fprintf(stderr, "W: move up failed\n"); } break; case 'h': if (!sok_ctx_move(&ctx, SOK_DIR_LEFT)) { fprintf(stderr, "W: move left failed\n"); } break; case 'j': if (!sok_ctx_move(&ctx, SOK_DIR_DOWN)) { fprintf(stderr, "W: move down failed\n"); } break; case 'l': if (!sok_ctx_move(&ctx, SOK_DIR_RIGHT)) { fprintf(stderr, "W: move right failed\n"); } break; case 'u': if (!sok_ctx_undo(&ctx)) { fprintf(stderr, "W: undo failed\n"); } break; case 'n': if (sok_ctx_is_done(&ctx)) { // advance level level = (level + 1) % NUM_LEVELS; // load next level if (!sok_ctx_set_level(&ctx, LEVELS[level].data)) { fprintf(stderr, "Couldn't load level %zu\n", level); return EXIT_FAILURE; } } else { fprintf(stderr, "W: cannot advance to next level\n"); } break; CASE_DIGIT { level = atoi(buf) % NUM_LEVELS; // load level if (!sok_ctx_set_level(&ctx, LEVELS[level].data)) { fprintf(stderr, "Couldn't load level %zu\n", level); return EXIT_FAILURE; } } break; case 's': { // get current number of moves const size_t old_num_moves = ctx.num_moves; if (sok_solve(&ctx, solve_on_error)) { // found solution, print it print_moves(&ctx, old_num_moves); } else { fprintf(stderr, "W: Couldn't solve level\n"); } } break; default: // ignore break; } } return 0; }