Browse Source

Plan 9 from Bell Labs 2004-09-22

David du Colombier 19 years ago
parent
commit
2a35dbc91e

+ 41 - 1
dist/replica/_plan9.db

@@ -3328,6 +3328,30 @@ sys/doc/venti/venti.ps - 664 sys sys 1019852320 2012620
 sys/games - 20000000775 sys sys 952648872 0
 sys/games - 20000000775 sys sys 952648872 0
 sys/games/lib - 20000000775 sys sys 952648879 0
 sys/games/lib - 20000000775 sys sys 952648879 0
 sys/games/lib/fortunes - 664 sys sys 1095732976 249846
 sys/games/lib/fortunes - 664 sys sys 1095732976 249846
+sys/games/lib/mahjongg - 20000000775 sys sys 1095792278 0
+sys/games/lib/mahjongg/backgrounds - 20000000775 sys sys 1095792293 0
+sys/games/lib/mahjongg/backgrounds/default.bit - 664 sys sys 1095792293 346803
+sys/games/lib/mahjongg/images - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/images/border.bit - 664 sys sys 1095792293 4057
+sys/games/lib/mahjongg/images/gameover.bit - 664 sys sys 1095792294 50228
+sys/games/lib/mahjongg/images/mask.bit - 644 sys sys 1095792294 429
+sys/games/lib/mahjongg/layouts - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/layouts/default.layout - 644 sys sys 1095792294 2662
+sys/games/lib/mahjongg/tilesets - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/tilesets/default.tileset - 644 sys sys 1095792294 484942
+sys/games/lib/sokoban - 20000000775 sys sys 1095792014 0
+sys/games/lib/sokoban/images - 20000000775 sys sys 1095792098 0
+sys/games/lib/sokoban/images/cargo.bit - 664 sys sys 1095792097 3827
+sys/games/lib/sokoban/images/empty.bit - 664 sys sys 1095792098 658
+sys/games/lib/sokoban/images/goal.bit - 664 sys sys 1095792098 1879
+sys/games/lib/sokoban/images/goalcargo.bit - 664 sys sys 1095792098 4286
+sys/games/lib/sokoban/images/left.bit - 664 sys sys 1095792098 2707
+sys/games/lib/sokoban/images/right.bit - 664 sys sys 1095792098 2726
+sys/games/lib/sokoban/images/wall.bit - 664 sys sys 1095792098 5335
+sys/games/lib/sokoban/images/win.bit - 664 sys sys 1095792098 572
+sys/games/lib/sokoban/levels - 20000000775 sys sys 1095792098 0
+sys/games/lib/sokoban/levels/easy.slc - 644 sys sys 1095792098 19839
+sys/games/lib/sokoban/levels/hard.slc - 644 sys sys 1095792098 17051
 sys/include - 20000000775 sys sys 1016902416 0
 sys/include - 20000000775 sys sys 1016902416 0
 sys/include/9p.h - 664 sys sys 1091904420 4392
 sys/include/9p.h - 664 sys sys 1091904420 4392
 sys/include/String.h - 664 sys sys 1091904425 1319
 sys/include/String.h - 664 sys sys 1091904425 1319
@@ -4661,6 +4685,7 @@ sys/man/1/filter - 664 sys sys 1041108741 4403
 sys/man/1/fmt - 664 sys sys 1070032221 1557
 sys/man/1/fmt - 664 sys sys 1070032221 1557
 sys/man/1/fortune - 664 sys sys 944959673 449
 sys/man/1/fortune - 664 sys sys 944959673 449
 sys/man/1/freq - 664 sys sys 944959673 735
 sys/man/1/freq - 664 sys sys 944959673 735
+sys/man/1/games - 664 sys sys 1095792424 1853
 sys/man/1/grap - 664 sys sys 944959675 6417
 sys/man/1/grap - 664 sys sys 944959675 6417
 sys/man/1/graph - 664 sys sys 944959673 2858
 sys/man/1/graph - 664 sys sys 944959673 2858
 sys/man/1/grep - 664 sys sys 969512677 2224
 sys/man/1/grep - 664 sys sys 969512677 2224
@@ -9452,7 +9477,7 @@ sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
 sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
 sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
-sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1072729353 59503
+sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1095775907 59692
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
@@ -11245,6 +11270,20 @@ sys/src/fs/sony/io.h - 664 sys sys 1037805175 6576
 sys/src/fs/sony/mem.h - 664 sys sys 1015110103 2865
 sys/src/fs/sony/mem.h - 664 sys sys 1015110103 2865
 sys/src/fs/sony/mkfile - 664 sys sys 1091803623 1594
 sys/src/fs/sony/mkfile - 664 sys sys 1091803623 1594
 sys/src/fs/worms - 664 sys sys 1015110031 2806
 sys/src/fs/worms - 664 sys sys 1015110031 2806
+sys/src/games - 20000000775 sys sys 1095792091 0
+sys/src/games/mahjongg - 20000000775 sys sys 1095792293 0
+sys/src/games/mahjongg/graphics.c - 644 sys sys 1095792293 5794
+sys/src/games/mahjongg/level.c - 644 sys sys 1095792293 2522
+sys/src/games/mahjongg/mahjongg.c - 644 sys sys 1095792293 3452
+sys/src/games/mahjongg/mahjongg.h - 644 sys sys 1095792293 1606
+sys/src/games/mahjongg/mkfile - 644 sys sys 1095792293 230
+sys/src/games/sokoban - 20000000775 sys sys 1095792097 0
+sys/src/games/sokoban/graphics.c - 664 sys sys 1095792097 1846
+sys/src/games/sokoban/level.c - 664 sys sys 1095792097 1654
+sys/src/games/sokoban/mkfile - 664 sys sys 1095792097 236
+sys/src/games/sokoban/move.c - 664 sys sys 1095792097 2671
+sys/src/games/sokoban/sokoban.c - 664 sys sys 1095792097 4760
+sys/src/games/sokoban/sokoban.h - 664 sys sys 1095792097 1197
 sys/src/lib9p - 20000000775 sys sys 1015023311 0
 sys/src/lib9p - 20000000775 sys sys 1015023311 0
 sys/src/lib9p/_post.c - 664 sys sys 1044836326 1641
 sys/src/lib9p/_post.c - 664 sys sys 1044836326 1641
 sys/src/lib9p/dirread.c - 664 sys sys 1015023310 641
 sys/src/lib9p/dirread.c - 664 sys sys 1015023310 641
@@ -12338,3 +12377,4 @@ usr/glenda/lib/profile - 664 glenda glenda 1021580005 847
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
+386/bin/ip/ppp - 775 sys sys 1095822523 216624

+ 41 - 2
dist/replica/plan9.db

@@ -279,7 +279,7 @@
 386/bin/ip/imap4d - 775 sys sys 1085077070 234217
 386/bin/ip/imap4d - 775 sys sys 1085077070 234217
 386/bin/ip/ipconfig - 775 sys sys 1089257533 135811
 386/bin/ip/ipconfig - 775 sys sys 1089257533 135811
 386/bin/ip/ping - 775 sys sys 1089257533 75000
 386/bin/ip/ping - 775 sys sys 1089257533 75000
-386/bin/ip/ppp - 775 sys sys 1089257534 216401
+386/bin/ip/ppp - 775 sys sys 1095822523 216624
 386/bin/ip/pppoe - 775 sys sys 1089257534 75540
 386/bin/ip/pppoe - 775 sys sys 1089257534 75540
 386/bin/ip/pptp - 775 sys sys 1089257534 124731
 386/bin/ip/pptp - 775 sys sys 1089257534 124731
 386/bin/ip/pptpd - 775 sys sys 1089257535 123832
 386/bin/ip/pptpd - 775 sys sys 1089257535 123832
@@ -3328,6 +3328,30 @@ sys/doc/venti/venti.ps - 664 sys sys 1019852320 2012620
 sys/games - 20000000775 sys sys 952648872 0
 sys/games - 20000000775 sys sys 952648872 0
 sys/games/lib - 20000000775 sys sys 952648879 0
 sys/games/lib - 20000000775 sys sys 952648879 0
 sys/games/lib/fortunes - 664 sys sys 1095732976 249846
 sys/games/lib/fortunes - 664 sys sys 1095732976 249846
+sys/games/lib/mahjongg - 20000000775 sys sys 1095792278 0
+sys/games/lib/mahjongg/backgrounds - 20000000775 sys sys 1095792293 0
+sys/games/lib/mahjongg/backgrounds/default.bit - 664 sys sys 1095792293 346803
+sys/games/lib/mahjongg/images - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/images/border.bit - 664 sys sys 1095792293 4057
+sys/games/lib/mahjongg/images/gameover.bit - 664 sys sys 1095792294 50228
+sys/games/lib/mahjongg/images/mask.bit - 644 sys sys 1095792294 429
+sys/games/lib/mahjongg/layouts - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/layouts/default.layout - 644 sys sys 1095792294 2662
+sys/games/lib/mahjongg/tilesets - 20000000775 sys sys 1095792294 0
+sys/games/lib/mahjongg/tilesets/default.tileset - 644 sys sys 1095792294 484942
+sys/games/lib/sokoban - 20000000775 sys sys 1095792014 0
+sys/games/lib/sokoban/images - 20000000775 sys sys 1095792098 0
+sys/games/lib/sokoban/images/cargo.bit - 664 sys sys 1095792097 3827
+sys/games/lib/sokoban/images/empty.bit - 664 sys sys 1095792098 658
+sys/games/lib/sokoban/images/goal.bit - 664 sys sys 1095792098 1879
+sys/games/lib/sokoban/images/goalcargo.bit - 664 sys sys 1095792098 4286
+sys/games/lib/sokoban/images/left.bit - 664 sys sys 1095792098 2707
+sys/games/lib/sokoban/images/right.bit - 664 sys sys 1095792098 2726
+sys/games/lib/sokoban/images/wall.bit - 664 sys sys 1095792098 5335
+sys/games/lib/sokoban/images/win.bit - 664 sys sys 1095792098 572
+sys/games/lib/sokoban/levels - 20000000775 sys sys 1095792098 0
+sys/games/lib/sokoban/levels/easy.slc - 644 sys sys 1095792098 19839
+sys/games/lib/sokoban/levels/hard.slc - 644 sys sys 1095792098 17051
 sys/include - 20000000775 sys sys 1016902416 0
 sys/include - 20000000775 sys sys 1016902416 0
 sys/include/9p.h - 664 sys sys 1091904420 4392
 sys/include/9p.h - 664 sys sys 1091904420 4392
 sys/include/String.h - 664 sys sys 1091904425 1319
 sys/include/String.h - 664 sys sys 1091904425 1319
@@ -4661,6 +4685,7 @@ sys/man/1/filter - 664 sys sys 1041108741 4403
 sys/man/1/fmt - 664 sys sys 1070032221 1557
 sys/man/1/fmt - 664 sys sys 1070032221 1557
 sys/man/1/fortune - 664 sys sys 944959673 449
 sys/man/1/fortune - 664 sys sys 944959673 449
 sys/man/1/freq - 664 sys sys 944959673 735
 sys/man/1/freq - 664 sys sys 944959673 735
+sys/man/1/games - 664 sys sys 1095792424 1853
 sys/man/1/grap - 664 sys sys 944959675 6417
 sys/man/1/grap - 664 sys sys 944959675 6417
 sys/man/1/graph - 664 sys sys 944959673 2858
 sys/man/1/graph - 664 sys sys 944959673 2858
 sys/man/1/grep - 664 sys sys 969512677 2224
 sys/man/1/grep - 664 sys sys 969512677 2224
@@ -9452,7 +9477,7 @@ sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
 sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
 sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
-sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1072729353 59503
+sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1095775907 59692
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
@@ -11245,6 +11270,20 @@ sys/src/fs/sony/io.h - 664 sys sys 1037805175 6576
 sys/src/fs/sony/mem.h - 664 sys sys 1015110103 2865
 sys/src/fs/sony/mem.h - 664 sys sys 1015110103 2865
 sys/src/fs/sony/mkfile - 664 sys sys 1091803623 1594
 sys/src/fs/sony/mkfile - 664 sys sys 1091803623 1594
 sys/src/fs/worms - 664 sys sys 1015110031 2806
 sys/src/fs/worms - 664 sys sys 1015110031 2806
+sys/src/games - 20000000775 sys sys 1095792091 0
+sys/src/games/mahjongg - 20000000775 sys sys 1095792293 0
+sys/src/games/mahjongg/graphics.c - 644 sys sys 1095792293 5794
+sys/src/games/mahjongg/level.c - 644 sys sys 1095792293 2522
+sys/src/games/mahjongg/mahjongg.c - 644 sys sys 1095792293 3452
+sys/src/games/mahjongg/mahjongg.h - 644 sys sys 1095792293 1606
+sys/src/games/mahjongg/mkfile - 644 sys sys 1095792293 230
+sys/src/games/sokoban - 20000000775 sys sys 1095792097 0
+sys/src/games/sokoban/graphics.c - 664 sys sys 1095792097 1846
+sys/src/games/sokoban/level.c - 664 sys sys 1095792097 1654
+sys/src/games/sokoban/mkfile - 664 sys sys 1095792097 236
+sys/src/games/sokoban/move.c - 664 sys sys 1095792097 2671
+sys/src/games/sokoban/sokoban.c - 664 sys sys 1095792097 4760
+sys/src/games/sokoban/sokoban.h - 664 sys sys 1095792097 1197
 sys/src/lib9p - 20000000775 sys sys 1015023311 0
 sys/src/lib9p - 20000000775 sys sys 1015023311 0
 sys/src/lib9p/_post.c - 664 sys sys 1044836326 1641
 sys/src/lib9p/_post.c - 664 sys sys 1044836326 1641
 sys/src/lib9p/dirread.c - 664 sys sys 1015023310 641
 sys/src/lib9p/dirread.c - 664 sys sys 1015023310 641

+ 41 - 0
dist/replica/plan9.log

@@ -16711,3 +16711,44 @@
 1095539491 0 c 386/bin/aux/vmwarefs - 775 sys sys 1095539498 99117
 1095539491 0 c 386/bin/aux/vmwarefs - 775 sys sys 1095539498 99117
 1095564695 0 c 386/bin/aux/vmwarefs - 775 sys sys 1095563640 99117
 1095564695 0 c 386/bin/aux/vmwarefs - 775 sys sys 1095563640 99117
 1095733808 0 c sys/games/lib/fortunes - 664 sys sys 1095732976 249846
 1095733808 0 c sys/games/lib/fortunes - 664 sys sys 1095732976 249846
+1095777016 0 c sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1095775907 59692
+1095793295 0 a sys/games/lib/mahjongg - 20000000775 sys sys 1095792278 0
+1095793295 1 a sys/games/lib/mahjongg/backgrounds - 20000000775 sys sys 1095792293 0
+1095793295 2 a sys/games/lib/mahjongg/backgrounds/default.bit - 664 sys sys 1095792293 346803
+1095793295 3 a sys/games/lib/mahjongg/images - 20000000775 sys sys 1095792294 0
+1095793295 4 a sys/games/lib/mahjongg/images/border.bit - 664 sys sys 1095792293 4057
+1095793295 5 a sys/games/lib/mahjongg/images/gameover.bit - 664 sys sys 1095792294 50228
+1095793295 6 a sys/games/lib/mahjongg/images/mask.bit - 644 sys sys 1095792294 429
+1095793295 7 a sys/games/lib/mahjongg/layouts - 20000000775 sys sys 1095792294 0
+1095793295 8 a sys/games/lib/mahjongg/layouts/default.layout - 644 sys sys 1095792294 2662
+1095793295 9 a sys/games/lib/mahjongg/tilesets - 20000000775 sys sys 1095792294 0
+1095793295 10 a sys/games/lib/mahjongg/tilesets/default.tileset - 644 sys sys 1095792294 484942
+1095793295 11 a sys/games/lib/sokoban - 20000000775 sys sys 1095792014 0
+1095793295 12 a sys/games/lib/sokoban/images - 20000000775 sys sys 1095792098 0
+1095793295 13 a sys/games/lib/sokoban/images/cargo.bit - 664 sys sys 1095792097 3827
+1095793295 14 a sys/games/lib/sokoban/images/empty.bit - 664 sys sys 1095792098 658
+1095793295 15 a sys/games/lib/sokoban/images/goal.bit - 664 sys sys 1095792098 1879
+1095793295 16 a sys/games/lib/sokoban/images/goalcargo.bit - 664 sys sys 1095792098 4286
+1095793295 17 a sys/games/lib/sokoban/images/left.bit - 664 sys sys 1095792098 2707
+1095793295 18 a sys/games/lib/sokoban/images/right.bit - 664 sys sys 1095792098 2726
+1095793295 19 a sys/games/lib/sokoban/images/wall.bit - 664 sys sys 1095792098 5335
+1095793295 20 a sys/games/lib/sokoban/images/win.bit - 664 sys sys 1095792098 572
+1095793295 21 a sys/games/lib/sokoban/levels - 20000000775 sys sys 1095792098 0
+1095793295 22 a sys/games/lib/sokoban/levels/easy.slc - 644 sys sys 1095792098 19839
+1095793295 23 a sys/games/lib/sokoban/levels/hard.slc - 644 sys sys 1095792098 17051
+1095793295 24 a sys/man/1/games - 664 sys sys 1095792424 1853
+1095793295 25 a sys/src/games - 20000000775 sys sys 1095792091 0
+1095793295 26 a sys/src/games/mahjongg - 20000000775 sys sys 1095792293 0
+1095793295 27 a sys/src/games/mahjongg/graphics.c - 644 sys sys 1095792293 5794
+1095793295 28 a sys/src/games/mahjongg/level.c - 644 sys sys 1095792293 2522
+1095793295 29 a sys/src/games/mahjongg/mahjongg.c - 644 sys sys 1095792293 3452
+1095793295 30 a sys/src/games/mahjongg/mahjongg.h - 644 sys sys 1095792293 1606
+1095793295 31 a sys/src/games/mahjongg/mkfile - 644 sys sys 1095792293 230
+1095793295 32 a sys/src/games/sokoban - 20000000775 sys sys 1095792097 0
+1095793295 33 a sys/src/games/sokoban/graphics.c - 664 sys sys 1095792097 1846
+1095793295 34 a sys/src/games/sokoban/level.c - 664 sys sys 1095792097 1654
+1095793295 35 a sys/src/games/sokoban/mkfile - 664 sys sys 1095792097 236
+1095793295 36 a sys/src/games/sokoban/move.c - 664 sys sys 1095792097 2671
+1095793295 37 a sys/src/games/sokoban/sokoban.c - 664 sys sys 1095792097 4760
+1095793295 38 a sys/src/games/sokoban/sokoban.h - 664 sys sys 1095792097 1197
+1095823901 0 c 386/bin/ip/ppp - 775 sys sys 1095822523 216624

BIN
sys/games/lib/mahjongg/backgrounds/default.bit


BIN
sys/games/lib/mahjongg/images/border.bit


BIN
sys/games/lib/mahjongg/images/gameover.bit


BIN
sys/games/lib/mahjongg/images/mask.bit


+ 81 - 0
sys/games/lib/mahjongg/layouts/default.layout

@@ -0,0 +1,81 @@
+kmahjongg-layout-v1.0
+...121212121212121212121212.....
+...434343434343434343434343.....
+.......1212121212121212.........
+.......4343434343434343.........
+.....12121212121212121212.......
+.....43434343434343434343.......
+...121212121212121212121212.....
+.124343434343434343434343431212.
+.431212121212121212121212124343.
+...434343434343434343434343.....
+.....12121212121212121212.......
+.....43434343434343434343.......
+.......1212121212121212.........
+.......4343434343434343.........
+...121212121212121212121212.....
+...434343434343434343434343.....
+................................
+................................
+.........121212121212...........
+.........434343434343...........
+.........121212121212...........
+.........434343434343...........
+.........121212121212...........
+.........434343434343...........
+.........121212121212...........
+.........434343434343...........
+.........121212121212...........
+.........434343434343...........
+.........121212121212...........
+.........434343434343...........
+................................
+................................
+................................
+................................
+................................
+................................
+...........12121212.............
+...........43434343.............
+...........12121212.............
+...........43434343.............
+...........12121212.............
+...........43434343.............
+...........12121212.............
+...........43434343.............
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+.............1212...............
+.............4343...............
+.............1212...............
+.............4343...............
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+................................
+..............12................
+..............43................
+................................
+................................
+................................
+................................
+................................
+................................
+................................

BIN
sys/games/lib/mahjongg/tilesets/default.tileset


BIN
sys/games/lib/sokoban/images/cargo.bit


BIN
sys/games/lib/sokoban/images/empty.bit


BIN
sys/games/lib/sokoban/images/goal.bit


BIN
sys/games/lib/sokoban/images/goalcargo.bit


BIN
sys/games/lib/sokoban/images/left.bit


BIN
sys/games/lib/sokoban/images/right.bit


BIN
sys/games/lib/sokoban/images/wall.bit


BIN
sys/games/lib/sokoban/images/win.bit


+ 1549 - 0
sys/games/lib/sokoban/levels/easy.slc

@@ -0,0 +1,1549 @@
+; #1
+ #####
+ #   ####
+ #   #  #
+ ##    .#
+### ###.#
+# $ # #.#
+# $$# ###
+#@  #
+#####
+
+; #2
+  #######
+  #     #
+  # $ @ #
+##### # #
+# $     #
+#  #$## ##
+#..$  #  #
+#..      #
+##########
+
+; #3
+######
+#..*.#
+#.$  #
+## $ #
+##$ ##
+#@$ #
+##  #
+ ####
+
+; #4
+########
+#.   $ #
+#.$  # #
+#.# #  #
+### # ##
+ # $  #
+ #@ ###
+ #####
+
+; #5
+ ########
+##..#   #
+# ..# $ ##
+# @ $  $ #
+##$###   #
+ #     ###
+ #######
+
+; #6
+ #######
+ #     ####
+ # ###.   #
+##    # # #
+# .#$ $ # #
+# #  *  # #
+# # $ $#. #
+# # #    ##
+#   .### ##
+####      #
+   #####  #
+       #@ #
+       ####
+
+; #7
+#########
+#.....  #
+### $ # ##
+  # $##  #
+  #$ $ $ #
+  #   #  #
+  ##  # @#
+   #######
+
+; #8
+    #####
+#####   #
+#.. $ $ ##
+#..$ $  @#
+##. $## ##
+ ###    #
+   ######
+
+; #9
+###########
+#     # @ #
+# $  $  $ #
+## #...# ##
+ # #...# #
+ #$ ### $#
+ #   $   #
+ #  ##   #
+ #########
+
+; #10
+   ####
+####  #
+# $...##
+#@ $.. #
+###$$$ #
+  #    #
+  ######
+
+; #11
+ ##########
+##    # @ ##
+#  $.... $ #
+# $ ####$  #
+##  #  #   #
+ ####  #####
+
+; #12
+    ########
+    #      #########
+##### #### #@##  ..#
+# $  $           ..#
+#   # ### #####  ..#
+### # ### #   ######
+  #  $  $ #
+  ###  $###
+    #$  #
+    #   #
+    #####
+
+; #13
+  #####
+  #   ##
+### *$ #
+#  .$. #
+#  $. ##
+###  @#
+  #####
+
+; #14
+  ########
+  #      #   ######
+  #$ $ $ #   #  ..#
+###  $  $#####  ..##
+#  $$$   $      ...#
+# #  $ ####@##  ..##
+# #  $ #  ####  ..#
+#    ###     ######
+######
+
+; #15
+########
+#  @   #
+#  #$$ #
+## $  ##
+ #  $.#
+ ## .##
+  #..#
+  ####
+
+; #16
+#########
+#   #   ##
+# $$#$$ @#
+#    $  ##
+#   # ##############
+####  $ #     #....#
+   # $$ #$ $ $#....#
+   #  $     $ #....#
+   # $$$#$  $ #  ..#
+   #    #  $ $   ..#
+   ############  ..#
+              #  ..#
+              ######
+
+; #17
+   #######
+   #  @  #
+#### # $ #
+#...$#$ ##
+#... $   #
+### $ ## #
+  # $    #
+  #    ###
+  ######
+
+; #18
+      ####
+#######@ #
+#   #    #
+#   $  $ #
+## ##$# ##
+ #  $ #*.#
+ ##  $...#
+  #   #. #
+  ########
+
+; #19
+ ########
+ # @    #
+##  ..$ #
+#  #..###
+# $$$##
+#    #
+######
+
+; #20
+########
+#  #   #
+# $..$ #
+#@$.* ##
+# $..$ #
+#  #   #
+########
+
+; #21
+   #####
+#### @ ###
+#    #   #
+# $$  #$ #
+#  $#$ $ #
+###...$###
+ #.... #
+ #######
+
+; #22
+ ###  ####
+##.####  ##
+#...  #  @###
+##..     $  #
+#...  # $ $ #
+##.###### ######
+ ###    # $ $  #
+       ## $ $# #
+       #   $   #
+       #  $ $# #
+       # # # # #
+       #       #
+       #########
+
+; #23
+#######
+#  #@ #
+# $$$ #
+#  $  #
+# $$$ #
+#..#..#
+#..$..#
+#######
+
+; #24
+########
+#  ##  #
+#  ##$ #
+#  $   ##
+## #    ##
+ # ## #  #
+ # $ $## #  ####
+## ##    ####..#
+# $ #$ #$##  ..#
+#      $     ..#
+########@##  ..#
+       #########
+
+; #25
+  ######
+  #  @ #
+  # $  #
+#### $ #
+# .#$ ##
+#..# $#
+#..$  ##
+#.. $  #
+####$  #
+   #   #
+   #####
+
+; #26
+       #####
+      ##   #
+      #  $ #####
+      # $ $    #
+      ### #### ##
+ ######## $    @#
+##...  ## $$## ##
+#....       ## #
+##...  #### ## #
+ ######## $ $  #
+        #  $ $ #
+        #      #
+        ########
+
+; #27
+ ########
+ #  #  @#
+ #$  $  #
+ # ## $ #
+##...$ ##
+# ...# #
+# #$$  #
+#      #
+########
+
+; #28
+  ######
+  #....#
+  #  ..#
+###$$#####
+# $   $ @#
+#   $ $  #
+###   ####
+  #####
+
+; #29
+ #######
+ #     ##
+ # $  $ #
+ ## # #@#
+  #.# $ #
+###..$ ##
+#  ..# #
+# #.*# ###
+#  #.$$$ #
+##   # # #
+ ###     #
+   #######
+
+; #30
+  ####
+  #  ####   ####
+  #     #####  #
+  #  $$$       #
+  ## #  #  # # #
+   #$ $ ####$# #
+   # $####     #
+####  #  #  ## ####
+# @$$    ## # ....#
+# #  $$ ### # ....#
+# $ $  $    # ....#
+# ## $  ##  # ....#
+#    $  ###########
+######  #
+     ####
+
+; #31
+  ############
+  #    #     #
+  # $  $ $ $ #
+###### ##$ $ #
+#..  # #  $ ##
+#..    @ ##  #
+#..  #$####  #
+#..  # $  $  #
+#..  #     ###
+############
+
+; #32
+      #######
+     ##@#   #
+    ##  # $ #
+ ####  # $  #
+ #    # $ # ##
+ #   # $  #  #
+ #  # $  #   #
+ # # $  #    #
+##  $  ### # #
+#  $  ##...# #
+#   ##.....  #
+########  ####
+       ####
+
+; #33
+########
+#....  ##########
+##...    $  $   #
+#....  ## $  $  #
+######### $ # ###
+        ##$ $ #
+        # $  $#
+        # $#$ ##
+        #     @#
+        ########
+
+; #34
+############
+#...#  @#  ##
+#...#$$  $  #
+#...   ##  $#
+#   # ##    ###
+#####  $ #$$  #
+  # $ $       #
+  #   #########
+  #####
+
+; #35
+   #########
+   #  ##   #
+   # $  $  #
+   #  $# $ #
+#### $ #$  #
+#..### # $ #
+#..  # # $ #
+#..     $$ #
+#..  ###   #
+#..  # ##@##
+######  ###
+
+; #36
+          #########
+######## ##   #   #
+#...#  ###  $  $  #
+#...#    @ # ### ##
+#...    # ##  #   #
+#  ### $#$  $  $  #
+##      # #  ## ###
+ #### #$$ ## ##  #
+    #   #   $    #
+    #####  #  ####
+        #######
+
+; #37
+           #####
+ ###########   #
+ #     $    ...#
+ #$$#  #####...#
+##  #$ #   #...#
+#  $   #   #...#
+#@#$$ ##   #...#
+# $    #   #...#
+##  $$ ######.##
+ # $ $ #   #   #
+ #$ $ $ $ $    #
+ #  ## #  $$# ##
+ #     ###    #
+ ####### ######
+
+; #38
+############
+###..##    #
+##....#  $ #
+#.....# $# #
+####.. $ #@#
+#   ..# ####
+# $# $#    #
+#  #  #  $ #
+#   # # $ ##
+# $$$ # ####
+#   $ #    #
+#### ## $$ #
+##   $   $ #
+##     ##  #
+############
+
+; #39
+        ####
+        #  #
+        #  #
+        #  #
+     #### ###
+     # $    #
+###### $$ $ #####
+#@ $  $    $  $ #
+##   #$ $   #   #
+ #####  $ $ #####
+     # $$$ ##
+     ### ########
+      ## ##  ...#
+      #  ##  ...#
+      #      ...#
+      #####  ...#
+          #  ...#
+          #######
+
+; #40
+####      ####
+#..########..#
+#.*.*.....*.*#
+#$ $ $ $ $ $ #
+# $ $ $ $ $ $#
+#$ $ $@$ $ $ #
+# $ $ $ $ $ $#
+#*.*.....*.*.#
+#..########..#
+####      ####
+
+; #41
+   ####
+   #  #####
+ ###$ $   ###
+ #  $ #  $  #
+ #    ## ## ##
+ #  ###  ##  #
+ # #  $ $ ## #
+ #$  $ $ $#  #
+## ###  $    #
+#     #$ ##$ #
+# ....#  #  ##
+##....# # @##
+ #.#.#  $ ##
+ #....   ##
+ #########
+
+; #42
+    ######
+    #....####
+    #....#  #
+    #...  $ #
+#####   #   #
+#   #####$####
+#   #      # #
+## $  $#     #
+ #$ ## # $ $ #
+ #  $   ####$##
+ # # #  ####  #
+## $       $  #
+#@  ########  #
+#####      ####
+
+; #43
+######
+#    ######  ####
+# $  $ #  ####  ##
+#  $   # $$      #
+##   $$#  ### #  #
+ # $#  ## ##  #  #
+ #$ $  $@$ # ##  ##
+ #  #  #   # #....#
+ # $ $ ##$## #....#
+ ##   # #  # #....#
+  ##### #  $ #....#
+        #  # ######
+        ######
+
+; #44
+      ####
+      #  #
+      #$ ###
+      #   ###
+ ######$ $  #
+ #... # $   #
+ #....  $$ ##
+ #....#   $#
+ #....#$ $ #
+#### ##   $#
+#@$ $ # $  #
+## $  ## ###
+ ##     $#
+  #####  #
+      ####
+
+; #45
+    #########
+    #.......#
+    #.......#
+    #.......#
+    #### $###
+     #  $  ##
+     # $ $  #
+ ###### # # ###
+ #  ## $ $ $  #
+## $$         #
+#   #####$##$##
+#   $     $ $ ###
+######## $#     #
+     #  $ #  #  #
+     #   @#$  $ #
+     ## $ $   $ #
+      ########  #
+             ####
+
+; #46
+######
+#....#
+#....#
+##   ############
+ #   #  #   #   #
+ ## ## $ $ $$   #
+  #    @# # #####
+  #  ##$# $  #
+  ####   $   #
+  #  $   #####
+  #      #
+  ########
+
+; #47
+       #######
+########.....#
+# $   $ .....####
+#  $ $ #.....   #
+##  ## #.....#  #
+ #  $  ###$### ##
+ # $  $  $   $ #
+ #$####  $   $ #
+ #   #  $# #####
+ ###   $$ $ $  #
+   #### $  $   #
+     #@  #######
+     #####
+
+; #48
+   #####
+   #...#
+   #...##
+   #....####
+ ####......####
+ #  #....     #
+##  ###  ###$ #
+# $ $ #$#  #  #
+# $    $  $## ####
+#  #  # #   $$$  #
+##  $## #$ $     #
+ #$  $  # $ $#  ##
+ #  $# $ $   ####
+ ##  ## @#   #
+  #  #########
+  ####
+
+; #49
+   #####
+   #   ##
+   # #  #
+ ### $  #
+##   # ##
+# .#.#  #
+# ..*$$ #
+# *#.#  #
+##  ##$##
+ #$ @  #
+ #  ####
+ ####
+
+; #50
+      ########
+      #      ##
+ ######  ##$$@#
+##  #  $$ #   #
+##$       $ $ #
+#   # $########
+#  $#  #... .#
+# $ #$$ ...  #
+#  $#  #...  #
+##  #  #...###
+ #  #  #####
+ #######
+
+; #51
+            #####
+     ########   #
+######@#   ## # #
+#   ##   $      #
+#...   ## ### ###
+#..## ##    # #
+#..#  ##$#### ##
+#..# $$     #  #
+#..#  ## $  $  #
+#####  #  $ #  #
+    #$$ $$# ####
+    #       #
+    #########
+
+; #52
+########
+#      ######
+# ####      #
+# #  ### ## #
+#     $   # #
+# #  #    # #
+# #$ ### #  # ######
+# # #### # #### ...#
+# #   # $$ #  #  ..#
+# #   #   ##$    ..#
+#  $$ #     $ #  ..#
+###   #   ##$ ######
+  ##########@ #
+           ####
+
+; #53
+#####
+#@  #######
+# #$#  #  #
+# $    $$ #
+### ##$#  #
+ #  # .# ##
+ #  $..   #
+ #  #..## #
+ #####.   #
+     ######
+
+; #54
+      #####
+     ##   #####
+ ##### $  #...#
+ #   # # ##...#
+ # #   # #.. .#
+ #   ##   ....#
+####  $$$ $#  #
+#  # ##  $ ####
+#  # ## $  #
+# $$$ $  $$#
+## #@##    #
+## #### #  #
+#       ####
+#       #
+#########
+
+; #55
+            ########
+        #####   #  #
+      ###   #$ $ $ #
+     ## #     $ $  #
+ #####    # #$ # $ #
+ #  #  # ## #   #  #
+ #    ##### ### #$ #
+ # $## ...# ##  $  #
+ ## ## ...#  #    ##
+ #  ###...   ######
+ #  $ ....####
+ #  #######
+### $ #
+#@$   #
+##  ###
+ ####
+
+; #56
+   ######
+ ###    ###
+ #        ####
+ # #$$$## #  #
+ # #    # #  #######
+ # #    # # $   ...#
+ # #$#$## #$    ...#
+##         $$###...#
+#  #$$$## #$   #...#
+# #     # #    #...#
+# #  $  # # ## #...#
+#  #$#$##  #   #...#
+##       $   $ #...#
+ # #$$$# ####$##.###
+ # # @ #  #  $   #
+ #  ###   # $$ ###
+ ##     ###    #
+  ####### ######
+
+; #57
+####
+# @#
+# $#####
+#  $   ##    #####
+#   $#  #    #   #
+##   $  #    # $ #
+ ##$# $ #######  #
+  #   #$    #  ..#
+  # # # $## # #..#
+  #      $     ..#
+  ###########  ..#
+      #     #$#..#
+      # $      ..#
+      #     #   ##
+      ###########
+
+; #58
+      #####
+  #####   #######
+  #@$    $   $  #
+ #### #$#  ##$  #
+ #  #  $  $ #   #
+ #  ### ##  # ####
+ #  $ # $  #  $  #
+ #        ### $  #
+#######$ ##  $ ###
+#.....#  #  $  #
+#.....## $ #$  #
+#....     $   ##
+#...   ########
+########
+
+; #59
+#######
+#     #
+# ### ###
+# #  $  #
+# # $ $ ##
+# #@ #$  #######
+# # $# $$#  ...#
+# #$ #   #  ...#
+# #  #$     ...#
+# #$ #  $#  ...#
+#   $ $  #  ...#
+###  $  $#######
+  ### ## #
+    #    #
+    ######
+
+; #60
+    ###########
+ ####.........#
+ #   .*******.#
+ # ###.......##
+## # #.$$$$$.#
+#@ ####     ##
+# $  ## $$$ #
+# $ $  #   ##
+# $ $ $    #
+# $ $ $  ###
+# $ $  ###
+# $  ###
+#  ###
+####
+
+; #61
+ ###
+##@#########
+# $#   ##  #
+#      $   #
+# $##$###  ##
+#  ## ### ###
+#####.###   #
+    #....#  #
+    #....#  #
+    #....## ##
+   ### ####  #
+   #         #
+   #   #### ####
+   #####  $ $  #
+       # $ $   #
+       # $$$$$ #
+       #       #
+       #########
+
+; #62
+####  ####
+#  ####  #
+#   @    #
+# $$$$$$ #
+##      ##
+# $$$$$$ #
+#        #
+#  $$$$  #
+###    ###
+ # $$$$ #
+ #      #
+ #  $$  #
+ ###..###
+ #..**..#
+ #......#
+ #..##..#
+ #......#
+ ########
+
+; #63
+  ###########
+  #....   ..#
+  # .......##
+### .#....#####
+#  #$##..##   #
+#     #### $  #
+# $$  #  #  $ #
+##  $$#   $$ ##
+ #$  $   #$  #
+ # $$ #  #  $#
+ # $ $#### $ #
+ #       #  ##
+ #### $  # ##
+    ### ## #
+     # $   #
+     #@ #  #
+     #######
+
+; #64
+   ######
+   #    #
+#### ## #######
+# @$  $   #   ##
+# # $  $  # $  #
+#  $  ##### #  #
+#### ##  #### ##
+  #  #  ##  #  #
+  #            #
+  #######  #  ##
+   #..  #  ####
+   #..      #
+   #..  #   #
+   ##########
+
+; #65
+#######
+#.....#
+#...#.#
+#.. ..# ####
+#.    ###  ########
+#### ## $         #
+####    #  $$ #   #
+ #   $ #  # $ #####
+ # # $ $$ # ###
+ #  #$##     #
+ ##  $ $$## ##
+  ##   @  $  #
+   ###  ###$ #
+     #### #  #
+          ####
+
+; #66
+       #########
+       #  ##   #
+     ### $     #
+  #### @$  ##$##
+###  #### ### #
+#  $ # #.*..# #
+# #   $ ....# #
+#    # #....$ #
+###  # #####  #
+  ####    $   #
+     ###$  $ ##
+       # $$ ##
+       #   ##
+       #  ##
+       ####
+
+; #67
+##################
+#   ##       $...#
+# $ $ $#$ ####  .#
+# $$#$       @...#
+# $   #$##$$ #...#
+# $ $$#    $ #...#
+#         ## #...#
+##################
+
+; #68
+ #######
+ #     #
+ # $ $ #
+ # $ ####
+## $##  #########
+#   #  $  ......#
+# *##  #$ #  $  #
+#.....*.  ## $  #
+#.###   ##  ##$ #
+### ######      #
+      #@$  $ $$ #
+      ###   #   #
+        #########
+
+; #69
+              ####
+             ##  ###
+##############  $  #
+#........... #   $ #
+#.# #######. #$ $###
+#.# ####### ##   ##
+#..           $$$@#
+#  ######## ##    #
+####   #   $$ #####
+       # $    $ #
+       ## $$  $ #
+        ##  $$  #
+         ##     #
+          ##   ##
+           #####
+
+; #70
+      #######
+  #####     #
+###   # ##$ ##
+# $   #      #
+# $# ##$# #$ #
+#@ # # $  #  #
+# $# # $###$ #
+# $  $    # ##
+## # $# #    #
+# $#  ..##. .#
+#  ### ..#.# #
+#   ## ......#
+##############
+
+; #71
+        #######
+        #     #
+    #####     ###
+#####   ## ##...#
+#     # ## ##...#
+# ###$$$ $ ##...#
+# #   $ $  ##...#
+# # #$ $ $###...#
+# #   $@$   ## ##
+# #  $ $ $ $#  #
+# # ######     #
+#              #
+################
+
+; #72
+             ####
+      ########  #
+      #     #   #
+    ### ###   # #
+#####     $   # #
+#   $ $ ###$$ # #
+#  $ $$$  # $## #
+#  #$   #  $  # #
+##   #### ### #$##
+ # ###......     #
+ #   $......## # #
+ # ###......##   #
+ #$$ #   #########
+ #     # $@$ #
+ #######     #
+       #######
+
+; #73
+    ####     ####
+  ###  #######  ##
+  #  ........... #
+  # $ ##### ### $##
+ ####  $ $ #   $  #
+ #  #  # # #$# @# ##
+ #         #   $ $ #
+ #   ##   # $$$#   #
+##  #     #      ###
+#    # ##  #  ####
+#         #   #
+########  #####
+       ####
+
+; #74
+  #####
+  #   #
+###$# ###
+# $...  ###
+# #.#*#   #
+# $.#.$   #
+#  ## ## ##
+## @ $ $ #
+ ###   ###
+   #####
+
+; #75
+          #### ####
+          #  ###  #
+          #  $    #
+          # # $ $ #
+      ##### # #  ##
+      #.....# $$$#
+      #....* $   #
+      #*..*.# #$##
+#######....*# $  #
+#     $*.*..#    #
+#  $$ # ##$###$$ #
+#    $   #      ##
+#####$ $ ####  ##
+ #@# $        ##
+ #    ######  #
+ ######    ####
+
+; #76
+      #####
+     ##   ##
+    ##  *  ##
+   ##  * *  ##
+  ##  * * *  ##
+ ##  * * * *  ####
+##  * * * * *  # ##
+#  * * * * * *    #
+# * * * . * * *@$ #
+#  * * * * * *    #
+##  * * * * *  # ##
+ ##  * * * *  ####
+  ##  * * *  ##
+   ##  * *  ##
+    ##  *  ##
+     ##   ##
+      #####
+
+; #77
+  ########
+ ##..    #
+ #...$ $ #
+###.## ###
+#   ##$ #
+#  $@$  #
+##$ ##  #
+ #  #####
+ ####
+
+; #78
+  ####
+  #  #
+  #  #########
+  # $$ #.....#
+  #    #.*...#
+ ###   $..##.#
+ #  #$##$  #.#
+ # $  ## ## .#
+ #  ##  $ $ ##
+###@ #$    ##
+#  $$ $   $#
+# $  ####  #
+#    #  ####
+#   ##
+#####
+
+; #79
+###
+# ##    ####
+#  ######  ###
+#   # $ $$ $ ###
+#  $ @ $    $  #
+# $ # #$  $    #
+#  ## # ### ####
+# ##    #  $  #
+###... ## $ $ #
+##....##   $  #
+#....## $  $###
+#...###  $  #
+#...# #  ####
+##### ####
+
+; #80
+           ####
+      ######  #
+      #   $   #
+      # $$ $  #
+      ## # $  #
+ ######   $ # #
+ #      $ $ $ ##
+ # ## #######  #
+ # $  ##...##$ #
+##   ##...#.#  #
+# $ $ #.....$$ #
+#    $$.....#  #
+##$   #..#..#$##
+ # $#$####### #
+ #    #       #
+ #### # # #####
+    #   #@#
+    #######
+
+; #81
+    ######
+    #    #
+ #### ##$###
+ #         #
+ # #....#  #
+## #....#$$#
+#   ....#  #
+# ##....   ##
+# ##....#$$ #
+#  $....#   #
+# $#### #   #
+#  $  $$$$$##
+##$    $   #
+ # $$# #   #
+ #  $ $ $$$#
+ # $   $   #
+ #@##   ####
+ ########
+
+; #82
+ ####
+ #  #######
+ #$  $    #
+ #   # #$ #
+ # #. .# ##
+ # $...  #
+##$#...# #
+#   $## $#
+#     $  #
+####### @#
+      ####
+
+; #83
+ #####
+ #   #    ##########
+ #$  ######    ##  #
+## $$  $   $  $... #
+# $ ##   #  #$#.#. #
+#    ##  ##$ $ ... #
+# $#    $ # # #.#. #
+#  ## #$  #    ... #
+# #  $#@$## # #.#. #
+#  $$ #$ #  #  ... #
+###      #  #   ####
+  ###   ##  #####
+    #########
+
+; #84
+   #####
+   #   #
+   # #$#
+####   #
+#  #.# ##
+#  *.* @#
+#  #.#  #
+## # #$##
+#  # #  #
+#    $  #
+#  ###  #
+#### ####
+
+; #85
+     #####
+######   #
+#  #     #
+# $$  #  #
+#   ### #######
+##  #.....#   #
+ #  $...*. $# ###
+ # $#.....# #   #
+ ## ####$##     #
+ #  #      $ ####
+ #  # @ $ # $#
+ #  $  ##$   #
+ ### #$   ####
+   #  $ $ #
+   ##  #  #
+    ####  #
+       ####
+
+; #86
+   ####
+   #  #####
+ ###$     #
+ #     .# #
+ # ## #.  #
+ # $  #*####
+## ####.   #
+#  #  @.#  #
+# $  #$.#$##
+###    . $ #
+  ######   #
+       #####
+
+; #87
+          #########
+          #       #
+          # ### # #
+     #### # #...# #
+######  ###  ...  #
+#         # #...# #
+#  $#  $  # ## ## #
+##  #### ##$      #
+ # ##### #  #$ ####
+ # #### $    $ #
+ # $ ##$ ###   #
+ #      $@######
+ # # ######
+ #   #
+ #####
+
+; #88
+####
+# @#   ####
+#  #####..###
+#  # $  $...#
+##   #  ... #
+ #$$  ###$# #
+##  # ### $ #
+# $   $   # #
+#    ####   #
+######  #####
+
+; #89
+    ########
+ ####  ....#
+ # #  $....######
+ # $  #....## ..####
+ #  $$## #### ....##
+####    $ @## .....#
+#    $ $$ #### #####
+# #$$$$# $$ $  #
+#       # $ ## #
+###  ## $  $  $#
+  # $   $      #
+  ####  $ ### $#
+     ###  # #  #
+       #### ####
+
+; #90
+     #####
+######   #
+#   ## # #
+#        #
+##$###*###
+## #.@.##
+#  *.#  #
+# # $ $ #
+#   ##  #
+#########
+
+; #91
+     #####
+  ####   #
+  #    #@#
+  # ###  #
+  # #  $ ###
+  # # # $$ #
+  # # $$   #
+### #   #$ #
+#   # $$ $ #
+# $ $      #
+##$#########
+# ....#
+# ....#
+# ....#
+#######
+
+; #92
+#########     #####
+#       #######   #
+# # # # #         #
+#   $ $ # ###### ##
+#####$#$# #  ..  ###
+  #  @$  $   ..# $ #
+  # #$#$# ###... $ #
+  #       ##...#   #
+  ##################
+
+; #93
+ ####
+ #  #
+ #  ###
+ # $  ###
+## ##.  #
+# $$..# #
+#  #*.$ #
+## #. ###
+ #   @#
+ #$ ###
+ #  #
+ ####
+
+; #94
+       #####
+####  ##   #######
+#  #  #  $   $   #
+#  #### $ $ $ #  #
+#... $ $  #$#$## #
+#...# $ $        #
+#..# $ $ $########
+#...$ $ $@##
+###### $ $ ###
+     # ##  ..#
+     # #  ...#
+     #    ...#
+     #########
+
+; #95
+    #####
+    #   #
+##### # #
+#   $   #
+#   #$#####
+##$## $ $ #
+ # ...#   #
+ # #..*   #
+ # @ ######
+ #####
+
+; #96
+    #######
+   ##     ##
+   #  ###  #
+ ###$##. # ###
+##    #..$   #
+#  $$ #..#   #
+# $$@ #.*# ###
+#  $#$#*.# #
+##     ..# #
+ ###$##  # #
+   #   ##  #
+   ###    ##
+     ######
+
+; #97
+ ###### ######
+ #    # #    #
+## ## ### $  #
+# $$     $$  #
+#  $ ## ## # #
+# # $ $    # #
+# $  $  # ## #######
+#  # #$   ## ##    #
+#### #  #### ## ## #
+ #  $ $##  #       #
+ # $ $     # ## ####
+## ## ###  #   ....#
+#   # ###   ## ....#
+#   $$#       .....#
+#   #    #@####....#
+############  ######
+
+; #98
+  #########
+  #.......#
+  #.......###
+  #         #
+  ##  ##### #
+   # ##   # #
+   # #   $  #
+   #  $ $ ###
+  ##$#   $ @#
+  #  ## # $##
+###$  $$#  ###
+#       #$   #
+# # $ $ $  $ #
+# ###### #  ##
+#        ####
+##########
+
+; #99
+#########
+#....   #
+#....   #
+#.#... ##
+#....#  ########
+######$$   #   #
+   #    ## $$# #
+   #  #  ##  $ #
+   ## $ $   ## #
+   #   # $   # #
+   #   $ #$  # #
+   ## ## # $ # ##
+    #$ #$#  ## @#
+    #  # #$$ $  #
+    #          ##
+    ############
+
+; #100
+  ####
+  #  #######
+###$       #######
+# $  $$  $ ##....#
+#  $# ###$$   ...#
+# #    @  #   ...#
+# #$$ $ $$#$##...#
+#   ## ##   ##...#
+##  $      $ #####
+ #########  ##
+         ####
+
+; #101
+#############
+#@$ $ $ *...#
+#  $ $ $.*..#
+# $ $ $ *...#
+#  $ $ $.*..#
+# $ $ $ *...#
+#  $ $ $.*..#
+# $ $ $ *...#
+#  $ $ $.*..#
+# $ $ $ *...#
+#  $ $ $.*..#
+#############
+
+; #102
+     #####    #####
+######   ######...##
+#   ## $ #  ##.... #
+# $$   $ #   #.. . #
+#   ### ## $ #....##
+### #     $  #....#
+ ## #   ### #####$#
+ ## ###   # ##    #
+ # $  @$$ # ##$$$ #
+ # $ ##   # ## $  #
+ #   ##### $## # ##
+ #####  #     $ $ #
+        #   #     #
+        ###########
+
+; #103
+  ####      ######
+  #  #      #    ##
+  #  ###   ##     #
+  #$   #   #   #  #
+  # $# #####      #
+  #   $   # # #####
+###$$   # # # # #
+# $   $   # #   #
+# @$ $ ###  # # ##
+#  ## #          #
+####...#  #    # #
+   #..*.# # # $  #
+   ##..*.# # #$ ##
+    ##..* $    $ #
+     ##..    #   #
+      ############
+
+; #104
+###################
+#  #   #   #   #  #
+#  $   $  $    $  #
+# $########## ##$ #
+## ## *.*..*.* # ##
+#  ## ..*..... # ##
+#  ### ######### ##
+#  #      $ #   $ #
+## #   $#$#@  #   #
+## # #       ######
+# $  #########
+#   ##
+#####
+
+; #105
+      ####
+#######  #
+#  #     #
+# $$ $#  #
+#  ##.# ####
+## ##.#  $ #
+## # . $ # #
+#   *..#   #
+#  # . # ###
+## ##.##$#
+ #     $@#
+ #  ######
+ ####
+
+; #106
+ ##########
+##  ..... #
+#  #..... #
+# $ #### ##
+# $  @   #
+## $ $ $ #
+ # $$$$$ #
+ #   #   #
+ #########
+
+; #107
+##############
+#     #      #
+# $$$    $$$ #
+##   $$$$   ##
+ #$ $    $ $#
+ #   $$$$   #
+ #$$$    $$$#
+ # $ $$$$ $ #
+ #          #
+######..######
+#..*.****.*..#
+#..*......*..#
+##.********.##
+ #..........#
+ ######@#####
+      ###
+
+; #108
+     #####
+######   #
+# $ .. $ #
+#@$$.. $##
+# $ ..  #
+#########

+ 1521 - 0
sys/games/lib/sokoban/levels/hard.slc

@@ -0,0 +1,1521 @@
+; #1
+#####
+#   #####
+# $ #   #
+#   #$# #
+###$    #
+ #   ####
+ # @...#
+ #######
+
+; #2
+  ####
+  #  #
+### $####
+#@$.. $ #
+#  .*   #
+###  ####
+  #  #
+  ####
+
+; #3
+#######
+#  . ##
+# $ $ #
+#. * .#
+# $ $ #
+## . @#
+#######
+
+; #4
+#########
+#      @#
+# $.$.$ #
+# .$.$. #
+# $.*.$ #
+# .$.$. #
+# $.$.$ #
+#       #
+#########
+
+; #5
+#########
+#   @   #
+#$$$$$$$#
+#...#...#
+#.......#
+#$$$ $$$#
+#       #
+#########
+
+; #6
+##########
+#    $  .#
+#  $##$# #
+#   $    #
+### ## ###
+#  $#  ##
+#.*.  $@#
+#...##  #
+#########
+
+; #7
+#######
+#  .  #
+# $*$.#
+#  .. #
+#$$*$$#
+# ..  #
+#.$*$ #
+#  . @#
+#######
+
+; #8
+###########
+#  $  *.* #
+#  $  *.* #
+#  $  *.*@#
+#  $  *.* #
+## $  *.* #
+ ##########
+
+; #9
+   ###########
+  ##     #  .#
+  #  $#$ #...#
+###  $  $#  .#
+#  $$$   $ @.#
+# #  $ ###  .#
+#  $ $ # #...#
+#    ### #  .#
+######   #####
+
+; #10
+#### #####
+#  ### @ ###
+#..     $  #
+#..# # $ $ #
+#..#  ## ######
+#..   ## $ $  #
+#..#  ## $ $# #
+#######   $   #
+      #  $ $# #
+      # # # # #
+      #       #
+      #########
+
+; #11
+#########
+#  .#   #
+#  $ $*.#
+# $## # #
+#   #   #
+# * #  ##
+##  .@##
+ ######
+
+; #12
+  ####
+  #. # ###
+###$ ###.#
+#  .$.   #
+#   ##$$ #
+# $$.#@  #
+#  $.#####
+###   .#
+  ######
+
+; #13
+ ########
+ #......#
+ #......#
+ #......#
+ #      #
+ #      #
+ #### ##########
+##  $    $ $ $ #
+#    $ #$#   # #
+#@#$ $ $  ##   #
+### $# #  #### #
+  #  $ $  #    #
+  # $# $ #  $  #
+  #    $   $ $ #
+  #  ###########
+  ####
+
+; #14
+    #######
+    #     ##
+    #  $$  #####
+   ### #  $#...#
+ ### $ #  $ ...#
+ #     ## $#...#
+ # $ #$    #...#
+ # #  $ # $ ...#
+ #  $ $##$  #  #
+## ##$ #@ ######
+# $    ####
+#   #  #
+########
+
+; #15
+   ###########
+   #   #     #
+####   # $ $ #
+#  $  $   #$ #
+#   $  # $$  #
+# #  $$##  # #
+# $$    ##   #
+#@$  $ $   ###
+## ####$##$#
+#  #...... ##
+#   .....#  #
+####......  #
+   ##########
+
+; #16
+#####
+#...##########
+#....$ $     #
+#..*. $   #  #
+#.*..### ## ####
+#....# $  #    #
+###### #$ #$#$ #
+  #@$  $  # $  #
+  ##      #    #
+   ########$ # #
+   #     $   $ #
+   # # # # $## #
+   #   $   $ $ #
+   ########    #
+          ######
+
+; #17
+    ######
+  ###    ####
+  # $ $ $   ##
+###    $ ##  #
+# $ # ##$  $ #
+#   #$   $   #
+#  $   $  $$ #
+# $@## ### ###
+#   #  #. ...#
+#####   .....#
+    ####.....#
+       #######
+
+; #18
+       #####
+########   #
+#.....# $# #
+#.....   # #
+#...  # $# ###
+##### #  #   #
+    #   $#$# #
+    ###$ $ # ##
+      #   $@$ #
+      #   # $ #
+      #$ $$$  #
+      #       #
+      #########
+
+; #19
+ ##########
+##  #     #
+#     $...#
+# # @ #...#
+#    #....#
+# $#$$...####
+#    ###$   #
+##  #    $$$###
+ #$ $ ##   $  #
+ #  #$#  #    #
+ ###  $  ######
+   #   # #
+   ###   #
+     #####
+
+; #20
+      ######
+    ### ...##
+   ##   ....##
+   # $##$#...#
+   # $  @ ...#
+ ###  # # # $#
+## $ #  #$## #
+#    $ $   # ##
+# $ # ##   $  #
+#  #   ## # # #
+# # $$   $    #
+#     #  ##  ##
+#####   ######
+    #####
+
+; #21
+    ############
+   #......#####
+  #@..$ **.###
+  #  $ $      #
+  ####### #$#  #
+ # #  # $ $  $ #
+#  #  # #  # # #
+      #  #   $ #
+       #  $##  #
+        #     #
+         #####
+
+; #22
+     ######
+######    #####
+#   #  #  #   ##
+# $$  $#$#  $  #
+#  #.#...  $ $ #
+#   .....@# $  #
+# $#.##*#  $$$ #
+##  ....#$ #   #
+ ###.#...  #####
+  # $ $#$# #
+  # $#   $ #
+  #    #   #
+  ##########
+
+; #23
+########
+#  #.#.##
+# $.$. .#
+#   .#$##
+####   #
+   #$$$#
+   # @ #
+   #####
+
+; #24
+  ##########
+  #        #
+ ## $ ##   #
+ #@ $$$  # #
+ ##  $ $$  #
+######  $$ #
+#... #$ $  #
+#..  # $## #
+#..     #  #
+#..  # ##  #
+#... #     #
+############
+
+; #25
+   ######
+   # @  #
+####  $ #
+# *..*$ #
+# $*..* #
+# $  ####
+#    #
+######
+
+; #26
+  #######
+  #. .  #
+####$#$ #
+# $. .  #
+#@$# #$ #
+# $.$.  #
+####.  ##
+   #####
+
+; #27
+##########
+# @###...#
+# $$  .$.#
+#   #$#$ #
+##       #
+##########
+
+; #28
+######
+#    ##
+# $ * #
+##.$$.#
+#. @ .#
+#.$$.##
+# * $ #
+##    #
+ ######
+
+; #29
+#########
+#   @...#
+# #$#.*.#
+# $  $$ #
+## #$   #
+ #   ####
+ #####
+
+; #30
+     ######
+######    #
+# $ .*. $ #
+#@$.* *.$ #
+# $ .*. $ #
+#     #####
+#######
+
+; #31
+######
+# # .#
+# $ .#
+#@ $.#
+# $$.#
+#  ###
+####
+
+; #32
+####
+#  ###  #####
+# $$ #  #...#
+#    ####...#
+# $ $ $  ...#
+# $  #### ..#
+### ##  ##$###
+### ######   #
+#  $  #    $ #
+#    $  # $  #
+##@#  ###   ##
+ ###### #####
+
+; #33
+    ####
+#####  #
+#  $ $ # #######
+#   $  # #*.*.*#
+## $ $ ###.*.*.#
+ #$ $  #  *.*.*#
+ #@$ $    .*.*##
+ #$ $  #  *.*.*#
+## $ $ ###.*.*.#
+#   $  # #*.*.*#
+#  $ $ # #######
+#####  #
+    ####
+
+; #34
+     ####
+     #  #####
+ #####      #
+ #  ## ##   #
+##   $   #$$ #
+#  ####  # $ #
+#  ..##$#    #
+###... $ # # #
+  #.*.#$ #$  #
+  #...#  # $##
+  #####$    #
+     #@  ####
+     #####
+
+; #35
+ ####
+ #  ######
+ #@$  $  ####
+ #  #   $#  #
+ ## #$ $  ..####
+### # ####.....#
+#    $ # $.....#
+# $    $  #  ###
+#### #$#  ####
+   # $ $ ##
+   #    ##
+   ######
+
+; #36
+##############
+#....#       #
+#*...# $ $ $ #
+#..####  $   #
+#..#  #   $$ #
+#..$  ## #   #
+# $#  $  #####
+#  #  #      #
+## #### ## # #
+# $    $ #   #
+# #$#$#@ #####
+#       ##
+#########
+
+; #37
+  ###########
+  #.........#
+  #.........##
+##########$$ #
+#     $  $ $ #
+# @##$ $  $  #
+# $#  ## ### ##
+#    $$ $   $ #
+####$  $  #$$ #
+   #  $#      #
+   #     ######
+   #######
+
+; #38
+#########
+#....   #
+#....$# #
+#.#..  $##
+#..@ #$  #
+###### #$#####
+  ##   $   $ #
+  # $$ #$    #
+  #   $   $$ #
+  #   #$   ###
+  ###    ###
+    ######
+
+; #39
+###############
+#             #
+# # $..... ## #
+# ##.$###$. # #
+#    . # .  $ #
+# $#@$...# #  #
+# $  . # .$ # #
+# # # ... #   #
+#   ##$#$##$$ #
+# #  $ #      #
+# $ #$ # $##$ #
+#      #      #
+###############
+
+; #40
+####
+#  #####
+# $$ $ #######
+#        ##  ###
+### ####$# $ $ #
+#....        $ #
+#....####$ #   #
+#....###  ## $ #
+##.#### $ $@$# #
+ #    $   #    #
+ #  #    #######
+ #########
+
+; #41
+          ####
+###########  #
+#      $   $ #
+#  ##### ### #
+## # $...$ # ##
+ # # $...     #
+ # #@#...###$ #
+## ## ...    ##
+#  $ $$$ #####
+# $$   ###
+#      #
+########
+
+; #42
+       ####
+      ##  #
+ ###### $ #
+##    # $ #
+# $ $   # ####
+#  ##$#....#@##
+# #   #....   #
+# # $$ ....## #
+#     #....#  #
+### # ### # $ #
+ # $  $ #$ $  #
+ #   $  # $  ##
+ # $# # ##  ##
+ # $  # #  ##
+ #  ###   ##
+ #### #####
+
+; #43
+          #####
+        ###   #
+    #####   $ #
+#####   # $#$##
+#....$ $#     #
+#....$#   $ $ #
+#....@#  ###$##
+#....#   $    #
+## #$ $ $ #   #
+# $$ #$########
+#      #
+###   ##
+  #####
+
+; #44
+        ####
+     ####  ##
+ ##### $    #
+ #   #   #$ ##
+ # $$ #$#....#
+##  $    ....#
+#  ## $ #.##.#
+# #  ## #....#
+#  $ @ $  $ ##
+## $ $ #$ #$#
+ #   ###    #
+ ##### ######
+
+; #45
+  #####
+ ##   #
+ # $# ####
+##  .....##
+# $ #.....#
+# #$ # ...##
+#   $# ##  ##
+#    $$###$ ##
+# ##$#  @  $ #
+#    #$$ #   #
+### # $  $ ###
+  #   #  ###
+  ########
+
+; #46
+     ####
+ #####  ##
+##    $  ####
+#  $  #$  $ ##
+# $ #   #    #
+#  ### $@ #$ #
+######...##  #
+   ####..#####
+ ###  ... #
+## $$#... #
+#  # $ ## #
+# #    $  #
+#     #####
+##   ##
+ #####
+
+; #47
+  #########
+  #      @#
+  #$ $ $  #
+  # ##$# ##
+ ##.. .. #
+ # .. ..##
+## #$## #
+#  $ $ $#
+#       #
+#########
+
+; #48
+######
+#    ######
+# $$$#    #
+# @$ # ## #
+# $$....# #####
+#  #.#.*# #   #
+#  #.#*.$     #
+#  #.*.. ###$##
+#######$#  #  #
+      # $$    #
+      #    #  #
+      #  ######
+      ####
+
+; #49
+        #######
+        #     #
+        #$$ $ #
+   ######  $  #
+   #   ## $ $ #
+   # ....*  $ #
+   # .###.#####
+   ##.# #.#
+#####.###.#
+# $  *....#
+# $ $ #####
+#@ $  #
+# $ $$#
+#     #
+#######
+
+; #50
+ ########
+ #  @   #
+##$ $ $ #
+# $ # $ #
+#  $ # ##
+#......#
+########
+
+; #51
+   ####
+   #  ###
+####  $ ####
+#    $# #  #
+# $#  #   @##
+#    #  #  ####
+# #$ $ #..... #
+# $ # $ ..##. #
+##$  # #...*.##
+ #  $#  #..#. #
+ # $  #$$  $$ #
+ #  # $    #  #
+ ####    ######
+    ######
+
+; #52
+    ########
+    #  ....#
+ #### #....#
+##  # $...##
+#  $ #$.*. ###
+#    $ $# $$ #
+# $#  @ #    #
+##  #  #  $ ##
+ #  $ # $ ###
+ #  #  $ $#
+ #####    #
+     ######
+
+; #53
+#######
+#. . .#
+# $$$ #
+#.$@$.#
+# $$$ #
+#. . .#
+#######
+
+; #54
+##############
+#   ###      #
+# $$$     $$ #
+# $ ### $ $  #
+# $ #  ### ###
+#   #.*...$@##
+#   #.....#$ #
+## # ...#.#  #
+## # .....#  #
+##$#####  # ##
+#     $ ###  #
+# $$ $    $$ #
+#       ###  #
+##############
+
+; #55
+   #####
+####   #
+#  $.# ##
+#   $   #
+#.##.##.#
+#  $$$  #
+####.  @#
+   ######
+
+; #56
+ ##########
+ #    .   #
+## $##$## #
+# @$. . .$##
+#   ##$##  #
+###   .    #
+  ##########
+
+; #57
+########
+#   @  #
+# #$## #
+# $  $ #
+###  $##
+ #. $.#
+ #. ..#
+ ######
+
+; #58
+#######
+#  .  ####
+# $.$ $ @#
+#  .####.##
+#  $ $ $. #
+####    . #
+   ########
+
+; #59
+#####
+#   #######
+# $ * .$  #
+# #.#.#.# #
+# $ $@$ $ #
+# #.#.#.# #
+#  $. * $ #
+###   #   #
+  #########
+
+; #60
+ #####
+ #   ######
+ # $.##   #
+ ##$...$  #
+### .$. ###
+#@$ $$###
+# $ ..###
+# $  .  #
+#####   #
+   ######
+
+; #61
+  #########
+ ##.......##
+## .$$$$$. ##
+#   #   #   #
+#  #*#@#*#  #
+##  #   #  ##
+ #. $$$$$  #
+  #.$     #
+   ##   ##
+     ###
+      #
+      #
+
+; #62
+  ####
+###  ######
+#    ##   #
+# #     $ #
+# $$ #$#$##
+### $    ###
+  ##  ##.*.##
+   ##$ $... ##
+  ##  ##...  #
+  #   $ #. @ #
+  # #   $.# ##
+  #    ##   #
+  #######  ##
+        ####
+
+; #63
+ #######
+##  *  ##
+# . .@. #
+#   * $ #
+#*$$*$$*#
+# $ *   #
+# . . . #
+##  *  ##
+ #######
+
+; #64
+#######
+#     #
+# $.$ #
+# .$. #
+#*$.$*#
+# .$. #
+#  .$ #
+# @   #
+#######
+
+; #65
+ ######
+ # @  ##
+ #$##  #
+## ..  #
+# $**$ #
+#  .. ##
+#  ##$#
+##    #
+ ######
+
+; #66
+###############
+#             #
+# $.$.$.$.$.# #
+# .$.$.$.$.$  #
+# $.$.$.$.$.#@#
+# .$.$.$.$.$  #
+# $.$.$.$.$.# #
+#             #
+###############
+
+; #67
+#######
+# $.  #
+#. .$.#
+#$.*. #
+# $*$ #
+#  .  #
+# $*$ #
+#  * @#
+#######
+
+; #68
+   #######
+   # ... #
+####$##$ ##
+#    $    #
+# #$@.* # #
+#   $*. # #
+## # .* # #
+ #$ ####  #
+ #       ##
+ #########
+
+; #69
+#######
+#  .  #
+# $.$ #
+# $*$ #
+#..*..#
+#$$*$ #
+#  .  #
+# $. @#
+#######
+
+; #70
+##########
+#.     $.#
+# #### #.#
+#. $ #$  #
+#  $ # $ #
+#   $@ $##
+######...#
+     #####
+
+; #71
+    ##########
+   ##   #    ##
+####    #  #  #
+#  $.******.$ #
+#   #   @  #  #
+#####    ######
+    ######
+
+; #72
+       #
+      ###
+     ##  #
+    #  $ ##
+   #  $.$  #
+  ## $.*.$  #
+ #  $.*.*.$ ##
+## $.*.*.*.$ ##
+ ## $.*.*.$  #
+  #  $.*.$ ##
+   #  $.$  #
+    ## $  #
+     # @##
+      ###
+       #
+
+; #73
+#######
+#  *  #
+#  *  #
+# $*$ #
+#*...*#
+# $.$ #
+# $.$ #
+#  . @#
+#######
+
+; #74
+#########
+##  @  ##
+# $ $.# #
+#  $.#. #
+# $.#.$ #
+# .*.$  #
+# #.$ $ #
+##     ##
+#########
+
+; #75
+#######
+#  .  #
+# $*$ #
+# $.$ #
+# ... #
+#.$.$.#
+#$$*$ #
+#  . @#
+#######
+
+; #76
+###############
+#  .........  #
+# $.$$$$$$$$$ #
+# $.$.......$ #
+# $.$.$$$$$.$ #
+# $.$.$...$.$ #
+# $.$.$*$.$.$@#
+# $.$...$.$.$ #
+# $.$$$$$.$.$ #
+# $.......$.$ #
+# $$$$$$$$$.$ #
+#  .........  #
+###############
+
+; #77
+ ########
+##  @#  #
+#  ###$ ##
+#  * *   #
+# * * *  #
+#  * * . #
+###   ####
+  #####
+
+; #78
+#######
+#  .  #
+# $.$ #
+# $.* #
+#.$*$.#
+# *.$ #
+# $.$ #
+#  . @#
+#######
+
+; #79
+##########
+#        #
+# $#$#$#$##
+#. .$...$.#
+#. .$...$.#
+# $#$#$#$@#
+#        ##
+##########
+
+; #80
+#########
+#   #   ###
+#   $ $   #
+## ##.#   #
+#@$##.##$##
+# $.....  #
+##$##.##$ #
+#  ##.#   #
+#  $ $#  ##
+#     #  #
+##########
+
+; #81
+            ####
+ ############  #
+ #      $      #
+ #$$#  ## ###  #
+##  ## #....# ##
+#  $   #....$  #
+#@#$$ ##....#  #
+# $    #....#  #
+##  $$ ###$### #
+ # $ $ #       #
+ #$ $ $  #   # #
+ #  ## #####   #
+ #     #   #####
+ #######
+
+; #82
+ ####   ####
+##  #####  #
+# $ $   $$ #
+#    ## #  ###
+##$#.....$   #
+ # #.....#  $##
+ # #.....# $$ #
+ # ### ###    #
+ #    @    #$ #
+ #  #  $ ###  #
+ #### $ $ $ $ #
+    #####     #
+        #######
+
+; #83
+ ############
+ # @# ......#
+ #$ #...* $ #
+ #   $ ##  ##
+ # $ $  ## #
+## ### $#  #
+# $# $    $#
+#     ##   #
+####  ######
+   ####
+
+; #84
+   #########
+   #@      #
+ ### ##  # ##
+ # $$ # $#  ##
+ #    # $ #$ #
+ #  # # #    #
+ ## # $  $ $ #
+  # #   ###  ##
+  # ##...##$  #
+###$$ ..### # #
+#  $  ...##   #
+#   ##....#####
+###########
+
+; #85
+ ####
+ #  ########
+ #   $     ###
+ # ##$ ###   #
+ #    #...$  ##
+ #$ @ #...# $ ##
+##  #  ...#$   #
+# $$  $#..  #  #
+# #  $ #..$ $  #
+#  $  ##..#  ###
+### #$  $ ####
+  #    #  #
+  #########
+
+; #86
+#########
+#   ## @#
+# $  $  #
+## *.#$ ##
+ # #.*   #
+ # .. $# #
+ #####   #
+     #####
+
+; #87
+  ####
+  #  ########
+ ##    $    #
+ # $# #.# # #
+ #  ...*. $ #
+## #$##.##  #
+# $     $ @ #
+#   ###  #  #
+##### #######
+
+; #88
+#####
+#   ########
+#   # .    ##
+#  ## *$$#  #
+# @ # .   $ #
+#   # .#$#  #
+##  ##.# $ ##
+ #  ##.#   #
+ #   #. # ###
+ #   $* # $ #
+ #    . #   #
+ ############
+
+; #89
+   ###### #####
+   #    ###   #
+   # #$     $ #
+ ### $ ##### ##
+ #   #.##     #
+ # $##.##  #$ #
+ #  ..... $#  #
+##$ ##.##  ####
+#  $ #.#####
+#   $ @ #
+#####   #
+    #####
+
+; #90
+#########
+#  #    ###
+#  #  #   ###
+# .   # $ $ ###
+#..#  # $ $   #
+#..   # @$ $  #
+#..#  ##$# $  #
+#..  ##   $ ###
+#..#    $$# #
+#    ##     #
+#  ##########
+#  #
+####
+
+; #91
+############
+#    ... $ #
+# $$$*** $@#
+#    ... $ #
+############
+
+; #92
+     #####
+######   ######
+#   #  $ ##   #
+# $ $ $ #   $ ##
+#  $# @ $ $$#  #
+## $  #     $$ #
+#..#$#### #$#  #
+#....  #  #   ##
+#....   $$#####
+#...###   #
+#...# #####
+#####
+
+; #93
+  #####
+  #   #
+### . #
+#   . #####
+# ##$## @ #
+#   . $   #
+###$.$#####
+  #   #
+  #####
+
+; #94
+     #######
+     #@ #  #
+###### $   #
+#...### #  ##
+#.  #  $ #  #
+#.    $ $ $ #
+#.  #  $ #  #
+#...### #  ##
+###### $#  #
+     #  $$ #
+     #  #  #
+     #######
+
+; #95
+     #####
+   ###   ####
+ ### $ $ #  #
+##   .#     #
+# $# ..# $  #
+#@$  ...#  ##
+# $# #...#$ #
+##   $ $    #
+ #### # #####
+    #   #
+    #####
+
+; #96
+    ####
+  ### @####
+ #  #   #  #
+ #$ $ $$$ $#
+ #  #.#.#  #
+ # #.....# #
+ # #.....# #
+#   #...#   #
+# $  # #  $ #
+ #  $ $ $  #
+  #$ $ $ $#
+  #       #
+  #########
+
+; #97
+             #
+            ##
+           ###
+          #   #
+   ######## # #
+  # $ $ $ $   #
+ ## # # # #$##
+###.......   ##
+ ## #.#.#.#@$#
+  # $ $ $ $   #
+   ######## # #
+          #   #
+           ###
+            ##
+             #
+
+; #98
+    ##   ##
+   ######  #
+####  $ $  ####
+ ### *.*.* ###
+  ## .$ $. ##
+   # *.*.* #
+   #  $ $  #
+   ### @ ###
+     #####
+       #
+
+; #99
+#####       ####
+#   #########  #
+#              #
+## ##########  #
+ # # * . * ## ##
+ # #  * *  ## #
+ # # * * * ## #
+ # #  * *  ## #
+ # # * * * ## #
+ # #  * *  ## ##
+ # # * * *     #
+ #$#  * *  #   #
+ #@  * * * #  ##
+ ##############
+
+; #100
+###########
+#  #   #  #
+#  $  $   #
+#  ##.##  #
+## ...##$##
+##$#...   #
+#  #.##$# #
+# $$  $   #
+# @#  #####
+#######
+
+; #101
+##### ####
+#   ###  ######
+# $  $ @$.... #
+##$ $  #$.##. #
+ #  # $# ....##
+ #  $  #$.##. #
+ # $  #  .... #
+ #$$$ # $$  $##
+ #    #  ##  #
+ #############
+
+; #102
+   #####
+   #...######
+   #...#    #
+   #...$ $$ #
+#####.. @# ##
+#    $ ### ###
+#   #$####   #
+## $     ### #
+ #   # $  $  #
+ ######  # $ #
+     #  $#$# #
+     #       #
+     #########
+
+; #103
+    #####
+    #   #
+ ####$# ###
+ # $  @$  ###
+ #   #    $ #
+###$## $$   #
+#....#$#  $ ##
+#..... ###$  #
+##.#.  #   $ #
+ #... $#$ #  #
+ #  #   $ ####
+ ####  ####
+    ####
+
+; #104
+###########
+#   ##..  #
+# $ ....# ##
+#  #.... @ ###
+#  #.#.. #   #
+####.###  $# #
+ ##  ##  $ # ##
+##   #  #$    #
+#  $ #$$#   # #
+# # $  $ ##   #
+# ###$ $  $  ##
+# $    ##    #
+# $   ####   #
+#  ####  #####
+####
+
+; #105
+ #######
+ #...  #####
+ #...#$#   ###
+ #... $@ $   ###
+ ##$$# ##$#$   #
+ #   #     $$# #
+ # $###$## # $ #
+ # $.#.$       #
+##  ...#$$ #####
+#  $#..  ###
+#   ##.   #
+#######   #
+      #####
+
+; #106
+ ####   #####
+ #  #####   #
+##*   * #$# #
+#   #   #   #
+# * . *  ** #
+######   #@##
+# .   ###   #
+# $ *    *# #
+##*   * **  #
+ #  ####    #
+ ####  ######
+
+; #107
+      ####
+      #  #
+    ###  ####
+#####       ###
+#   $ #$###   #
+#  $@$....#$$ #
+######..*.  $ #
+   #####..#####
+   # $ $ ##
+   #     #
+   #######
+
+; #108
+         #####
+         #   #
+########## * ###
+#          .   #
+# $$$$****$...@#
+#          .   #
+########## * ###
+         #   #
+         #####
+
+; #109
+########
+#  .$  #
+# .$.$ ##
+#*$.$.@ #
+# .$.$  #
+#  .$ ###
+#######
+
+; #110
+###########
+#    .    #
+#  $.$.$  #
+###.$.$.###
+  ##.$.##
+   #$.$#
+   # $ #
+   # @ #
+   #####
+
+; #111
+       #####
+########   #
+#......... #
+#  $ #$#   #
+# $#    # ###
+#  #  # $   #
+#$### $ # # #
+#@$    $  $ #
+######  #####
+     ####
+
+; #112
+          #####
+          #   #
+########### # #
+#             #
+# # $#######$$#
+# #  *.....#  #
+# #$ #.***.*  #
+# #  #.....#  #
+# #  ####*###$##
+# #         $  #
+# $ $ $ $ $ $ @#
+##  ############
+ ####
+
+; #113
+###########
+#  .$ $.  #
+#  .$  #  #
+#.#*#..*..#
+#$ .$$$#$$#
+#  .$@$.  #
+#$$#$$$. $#
+#..*..#*#.#
+#  #  $.  #
+# $. $ .  #
+###########
+
+; #114
+   #####
+   # @ #
+   #$$$#
+#### . ####
+#   *.* $ #
+# $.....$ #
+# $ *.*   #
+#### . ####
+   # $$#
+   #   #
+   #####
+
+; #115
+#######
+# $. @#
+#  .$ #
+# **$ #
+#* .$*#
+# $*. #
+#  .$ #
+#  .  #
+#######
+
+; #116
+#######
+#  *  #
+# $.$ #
+#  .$ #
+#.*.*.#
+#$ *  #
+# $. $#
+#@ *  #
+#######
+
+; #117
+   ######
+####    ####
+#@ $.#*$   #
+# $ ...# $ #
+###$#.     #
+  #   ######
+  #####
+
+; #118
+   #####
+   #.  #
+   #...#
+   #.  #
+   #.  #
+##### #####
+#         #
+# $@$$$$$ #
+#    #    #
+###########
+
+; #119
+  #####
+  # . #
+  # * #
+  # . #
+###$*$###
+#   *   #
+# ***** #
+#   *   #
+### . ###
+  # $ #
+  # @ #
+  #####
+
+; #120
+#############
+#.          #
+#.#$#$#$#$#$#
+#.          #
+#.#########.#
+#.#.  $ ..$$#
+#.# $ $ *.$@#
+#.#.* $ ..$*##
+#.#########  #
+#.$ $ $ $ $  #
+#.           #
+##############

+ 86 - 0
sys/man/1/games

@@ -0,0 +1,86 @@
+.TH GAMES 1
+.SH NAME
+mahjongg, sokoban \- time wasters
+.SH SYNOPSIS
+.B games/mahjongg
+[
+.B -c
+] [
+.B -b
+.I background
+] [
+.B -t 
+.I tileset
+] [
+.B -l
+.I layout
+]
+.br
+.B games/sokoban
+[
+.B level
+]
+.SH DESCRIPTION
+There are a few games in
+.BR /bin/games :
+.TP
+.B mahjongg
+Remove all tiles
+from the board. Click on tiles with the same face that
+are not blocked by others. A blocked tile is one that is partially or
+fully covered on top or has neighbouring tiles to the left and right.
+The game finishes when either all tiles are gone or there are no
+more moves left. The arguments are for changing background
+.RB (-b),
+tile
+.RB (-t)
+and layout
+.RB (-l)
+images;
+.RB -c
+selects a true-color buffer image, use with
+drawterm or in case selecting a tile obscures it completely.
+The 
+.LR N
+key will generate a new level, 
+.LR R
+restarts the current one. 
+.LR Q
+and 
+.LR Del
+quit, 
+.LR H
+gives a hint, either trying to match the currently selected tile, or if no tile is
+selected finding out the first available tile.
+.TP
+.B sokoban
+Guide Glenda through a room full of walls, pebbles and holes to put
+the pebbles in.  Your goal is to arrange all pebbles into holes by
+pushing them around, but you can only push a pebble if there is no
+wall or another pebble blocking the way.
+Arrow keys move Glenda up-down-left-right.  
+.LR N 
+and 
+.LR P 
+keys switch between
+the next and previous levels, 
+.LR R
+restarts the current level.  
+.LR Del 
+and
+.LR Q
+quit.  The right mouse button invokes a menu to restart the current level or load different
+level sets.  The middle mouse button lets you change between levels. 
+.I Sokoban
+accepts a level file as its argument.
+.SH FILES
+.TP
+.B /sys/games/lib/mahjongg/*
+image sprites, levels and backgrounds used by
+.I mahjongg
+.TP
+.B /sys/games/lib/sokoban/*
+image sprites and levels used by
+.I sokoban
+.SH SOURCE
+.B /sys/src/games

+ 5 - 0
sys/src/cmd/ip/ppp/ppp.c

@@ -1525,6 +1525,11 @@ ipopen(PPP *ppp)
 		}
 		}
 		buf[n] = 0;
 		buf[n] = 0;
 
 
+		netlog("ppp: setting up IP interface local %I remote %I (valid %d)\n",
+			ppp->local, ppp->remote, validv4(ppp->remote));
+		if(!validv4(ppp->remote))
+			ipmove(ppp->remote, ppp->local);
+
 		snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);
 		snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);
 		fd = open(path, ORDWR);
 		fd = open(path, ORDWR);
 		if(fd < 0){
 		if(fd < 0){

+ 310 - 0
sys/src/games/mahjongg/graphics.c

@@ -0,0 +1,310 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+#include "mahjongg.h"
+
+int
+freeup(int d, Point p)
+{
+	/* are we blocked from above? */
+	if(d == Depth -1 || (level.board[d+1][p.x][p.y].which == 0 &&
+			level.board[d+1][p.x+1][p.y].which == 0 &&
+			level.board[d+1][p.x][p.y+1].which == 0 &&
+			level.board[d+1][p.x+1][p.y+1].which == 0))
+		return 1;
+	
+	return 0;
+}
+
+int
+freeleft(int d, Point p)
+{
+
+	/* blocked from the left? */
+	if(p.x == 0 || (level.board[d][p.x-1][p.y].which == 0 &&
+		level.board[d][p.x-1][p.y+1].which == 0)) 
+		return 1;
+
+	return 0;
+}
+
+int
+freeright(int d, Point p)
+{		
+	if(p.x == Lx-2 || (level.board[d][p.x+2][p.y].which == 0 &&
+		level.board[d][p.x+2][p.y+1].which == 0))
+		return 1;
+
+	return 0;
+}
+
+int
+isfree(int d, Point p)
+{
+	return (freeleft(d, p) || freeright(d, p)) && freeup(d, p);
+}
+
+void
+clearbrick(int d, Point p)
+{
+	level.board[d][p.x][p.y].which = 0;
+	level.board[d][p.x+1][p.y].which = 0;
+	level.board[d][p.x][p.y+1].which = 0;
+	level.board[d][p.x+1][p.y+1].which = 0;
+}
+
+void
+resize(Point p)
+{
+	/* resize to the size of the current level */
+
+	int fd;
+
+	fd = open("/dev/wctl", OWRITE);
+	if(fd >= 0){
+		fprint(fd, "resize -dx %d -dy %d", p.x, p.y);
+		close(fd);
+	}
+
+}
+
+void
+drawbrick(int d, int x, int y)
+{
+	Point p;
+	Rectangle r;
+
+	p = Pt(x*(Facex/2)-(d*TileDxy), y*(Facey/2)-(d*TileDxy));
+	r = Rpt(p, addpt(p, Pt(Facex, Facey)));
+	r = rectaddpt(r, Pt(Depth*TileDxy, Depth*TileDxy));
+	draw(img, r, tileset, nil, level.board[d][x][y].start);
+
+	if(level.board[d][x][y].clicked)
+		draw(img, r, selected, nil, ZP);
+
+	/* looks better without borders, uncomment to check it out with'em */
+//	r = Rpt(r.min, addpt(r.min, Pt(Tilex, Tiley)));
+//	draw(img, r, brdr, nil, ZP);
+}
+
+
+void
+drawlevel(void)
+{
+	int d, x, y;
+
+	draw(img, img->r, background, nil, ZP);
+
+	for(d = 0; d < Depth; d++)
+		for(y = 0; y < Ly; y++)
+			for(x = 0; x < Lx; x++)
+				if(level.board[d][x][y].which == 1) 
+					drawbrick(d, x, y);
+
+	draw(screen, screen->r, img, nil, ZP);
+	flushimage(display, 1);
+}
+
+Brick *
+bmatch(int d, Point p)
+{
+	int x, y;
+	int ld = d;
+
+	do {
+		for(y = 0; y < Ly; y++)
+			for(x = 0; x < Lx; x++)
+				if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) && 
+					level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
+			
+					return &level.board[ld][x][y];
+
+	} while(--ld >= 0);
+
+	return nil;
+}
+
+int
+canmove(void)
+{
+	int d, x, y;
+
+	for(d = Depth - 1; d >= 0; d--) 
+		for(y = 0; y < Ly; y++) 
+			for(x = 0; x < Lx; x++) 
+				if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
+					if(bmatch(d, Pt(x, y)) != nil)
+						return 1;
+	return 0;
+}
+
+void
+hint(void)
+{
+	Brick *b = nil;
+	int d = 0, x = 0, y = 0;
+
+	if(level.c.d != -1) {
+		if((b = bmatch(level.c.d, level.c.p)) != nil) {
+			d = level.c.d;
+			x = level.c.p.x;
+			y = level.c.p.y;
+		}
+	} else {
+		for(d = Depth - 1; d >= 0; d--) 
+			for(y = 0; y < Ly; y++) 
+				for(x = 0; x < Lx; x++) 
+					if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
+						if((b = bmatch(d, Pt(x, y))) != nil)
+							goto Matched;
+	}
+
+Matched:
+	if(b != nil) {
+		level.board[d][x][y].clicked = 1;
+		b->clicked = 1;
+		drawlevel();
+		sleep(500);
+		if(level.c.d == -1)
+			level.board[d][x][y].clicked = 0;
+		b->clicked = 0;
+		drawlevel();
+		sleep(500);
+		level.board[d][x][y].clicked = 1;
+		b->clicked = 1;
+		drawlevel();
+		sleep(500);
+		if(level.c.d == -1)
+			level.board[d][x][y].clicked = 0;
+		b->clicked = 0;
+		drawlevel();
+	}
+
+}
+
+void
+done(void)
+{
+	level.done = 1;
+	draw(screen, screen->r, selected, gameover, ZP);
+	draw(screen, screen->r, selected, gameover, ZP);
+	flushimage(display, 1);
+}
+
+
+void
+clicked(Point coord)
+{
+	Point p;
+	int d;
+
+	/* ugly on purpose */
+
+	for(d = Depth - 1; d >= 0; d--) {
+		p = Pt((coord.x + TileDxy*d)/(Facex/2), (coord.y + TileDxy*d)/(Facey/2));
+		switch(level.board[d][p.x][p.y].which) {
+		case 0:
+			break;
+		case 1:
+			goto Found;
+		case 2:
+			p = Pt(p.x-1, p.y);
+			goto Found;
+		case 3:
+			p = Pt(p.x-1, p.y-1);
+			goto Found;
+		case 4:
+			p = Pt(p.x, p.y-1);
+			goto Found;
+		}
+	}
+
+	return;
+
+Found:
+	if(freeup(d, p) && (freeleft(d, p) || freeright(d, p))) {
+		if(level.c.d == -1) {
+			level.c.d = d;
+			level.c.p = p;
+			level.board[d][p.x][p.y].clicked = 1;
+		} else if(!eqpt(p, level.c.p) && 
+			(level.board[d][p.x][p.y].type == level.board[level.c.d][level.c.p.x][level.c.p.y].type)) {
+
+			clearbrick(d, p);
+			clearbrick(level.c.d, level.c.p);
+
+			level.c.d = -1;
+			level.c.p = Pt(0, 0);
+
+			level.remaining -= 2;
+		} else {
+			level.board[d][p.x][p.y].clicked = 0;
+			level.board[level.c.d][level.c.p.x][level.c.p.y].clicked = 0;
+			level.c.d = -1;
+			level.c.p = Pt(0, 0);
+		} 
+		drawlevel();
+		if(!canmove())
+			done();
+	}
+}
+
+/* below only for testing */
+
+Point
+pmatch(int d, Point p)
+{
+	int x, y;
+	int ld = d;
+
+	do {
+		for(y = 0; y < Ly; y++)
+			for(x = 0; x < Lx; x++)
+				if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) && 
+					level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
+			
+					return Pt(x, y);
+
+	} while(--ld >= 0);
+
+	return Pt(-1, -1);
+}
+
+int
+dmatch(int d, Point p)
+{
+	int x, y;
+	int ld = d;
+
+	do {
+		for(y = 0; y < Ly; y++)
+			for(x = 0; x < Lx; x++)
+				if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) && 
+					level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
+			
+					return ld;
+
+	} while(--ld >= 0);
+
+	return -1;
+}
+
+void
+clearlevel(void)
+{
+	int d, x, y;
+
+	for(d = Depth - 1; d >= 0; d--) 
+		for(y = 0; y < Ly; y++) 
+			for(x = 0; x < Lx; x++) 
+				if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
+					if(bmatch(d, Pt(x, y)) != nil) {
+						clearbrick(dmatch(d, Pt(x, y)), pmatch(d, Pt(x, y)));
+						clearbrick(d, Pt(x, y));
+						level.remaining -= 2;
+						drawlevel();
+						clearlevel();
+					}
+}

+ 150 - 0
sys/src/games/mahjongg/level.c

@@ -0,0 +1,150 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+
+#include "mahjongg.h"
+
+void
+consumeline(Biobuf *b)
+{
+	while(Bgetc(b) != '\n')
+		;
+}
+
+/* parse a level file */
+int
+parse(char *layout)
+{
+	Biobuf *b;
+	int x = 0, y = 0, depth = 0;
+	char c;
+
+	b = Bopen(layout, OREAD);
+	if(b == nil) {
+		fprint(2, "could not open file %s: %r\n", layout);
+		return 0;
+	}
+
+	level.remaining = 0;
+
+	while((c = Bgetc(b)) > 0) {
+		switch(c)  {
+		case '\n':
+			x = 0;
+			y = (y+1) % Ly;
+			if(!y)
+				depth++;
+			break;
+		case '.':
+			orig.board[depth][x][y].which = 0;
+			x++;
+			break;
+		case '1':
+			orig.remaining++;
+		case '2':
+		case '3':
+		case '4':
+			orig.board[depth][x++][y].which = c-48;
+			break;
+		default:
+			consumeline(b);
+			break;
+		}
+	}
+	Bterm(b);
+
+	return 1;
+}
+
+int
+indextype(int type)
+{
+	int t;
+
+	if(type < 108) 	
+		t = (type/36)*Facey * 9 + ((type%36)/4)*Facex;
+	else if(type < 112)
+		t = Seasons;
+	else if(type < 128)
+		t = 3*Facey + (((type+12)%36)/4)*Facex;
+	else if(type < 132)
+		t = Flowers;
+	else
+		t = 4*Facey + (((type+28)%36)/4)*Facex;
+
+	return t;
+
+}
+
+Point
+indexpt(int type)
+{
+	Point p;
+	
+	/* the first 108 bricks are 4 of each, 36 per line:
+	 * 	x = (index%36)/4
+	 *	y = (index)/36
+	 * then multiply by the size of a single tile.
+	 * the next 4 are the seasons, so x = index%4...
+	 *
+	 * and so on...
+	 */
+		
+	if(type < 108) {
+		p = Pt(((type%36)/4)*Facex, (type/36)*Facey);
+	} else if(type < 112) {
+		p = Pt((type%4)*Facex, 3*Facey);
+	} else if(type < 128) {
+		p = Pt((((type+12)%36)/4)*Facex, 3*Facey);
+	} else if(type < 132) {
+		p = Pt(((type+4)%4)*Facex, 4*Facey);
+	} else {
+		p = Pt((((type+28)%36)/4)*Facex, 4*Facey);
+	}
+
+	return p;
+}
+
+/* use the seed to generate a replayable game */
+void
+generate(uint seed)
+{
+	Point p;
+	int x, y, d, n;
+	int order[144];
+
+	srand(seed);
+
+	for (x = 0; x < Tiles; x++)
+		order[x] = x;
+
+	for(x = 0; x < Tiles; x++) {
+		n = order[x];
+		y = nrand(Tiles);
+		order[x] = order[y];
+		order[y] = n;
+	}
+	
+	n = 0;
+	for(d = 0; d < Depth; d++)
+		for(y = 0; y < Ly; y++)
+			for(x = 0; x < Lx; x++)
+				if(orig.board[d][x][y].which == 1) {
+
+					orig.board[d][x][y].type = indextype(order[n]);
+					p = indexpt(order[n++]);
+					orig.board[d][x][y].start = p;
+					orig.board[d][x+1][y].start = p;
+					orig.board[d][x][y+1].start = p;
+					orig.board[d][x+1][y+1].start = p;
+				}
+
+	if(n != orig.remaining)
+		fprint(2, "level improperly generated: %d elements, should have %d\n", n, orig.remaining);
+
+	orig.c.d = -1;
+	orig.c.p = Pt(0, 0);
+	orig.done = 0;
+	level = orig;
+}

+ 203 - 0
sys/src/games/mahjongg/mahjongg.c

@@ -0,0 +1,203 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+#include "mahjongg.h"
+
+char *Border = "/sys/games/lib/mahjongg/images/border.bit";
+char *Mask = "/sys/games/lib/mahjongg/images/mask.bit";
+char *Gameover = "/sys/games/lib/mahjongg/images/gameover.bit";
+
+char *deftileset = "/sys/games/lib/mahjongg/tilesets/default.tileset";
+char *defbackgr = "/sys/games/lib/mahjongg/backgrounds/default.bit";
+char *deflayout = "/sys/games/lib/mahjongg/layouts/default.layout";
+ulong defchan;
+
+
+char *buttons[] = 
+{
+	"new",
+	"restart",
+	"resize",
+	"exit",
+	0
+};
+
+Menu menu = 
+{
+	buttons
+};
+
+void
+usage(char *progname)
+{
+	fprint(2, "usage: %s [-b background] [-l layout] [-t tileset] -c\n", progname);
+	exits("usage");
+}
+
+Image *
+eallocimage(Rectangle r, int repl, uint chan, uint color)
+{
+	Image *tmp;
+
+	tmp = allocimage(display, r, chan, repl, color);
+	if(tmp == nil)
+		sysfatal("cannot allocate buffer image: %r");
+
+	return tmp;
+}
+
+Image *
+eloadfile(char *path)
+{
+	Image *img;
+	int fd;
+
+	fd = open(path, OREAD);
+	if(fd < 0) {
+		fprint(2, "cannot open image file %s: %r\n", path);
+		exits("image");
+	}
+	img = readimage(display, fd, 0);
+	if(img == nil)
+		sysfatal("cannot load image: %r");
+	close(fd);
+	
+	return img;
+}
+
+
+void
+allocimages(void)
+{
+	Rectangle one = Rect(0, 0, 1, 1);
+	
+	selected = eallocimage(one, 1, RGBA32, setalpha(DPalebluegreen, 0x5f));
+	img = eallocimage(Rect(0, 0, Sizex, Sizey), 0, defchan ? defchan : screen->chan, DBlack);
+
+	background = eloadfile(defbackgr);
+	replclipr(background, 1, img->r);
+
+	mask = eloadfile(Mask);
+	gameover = eloadfile(Gameover);
+	tileset = eloadfile(deftileset);
+}
+
+
+void
+eresized(int new)
+{
+	if(new && getwindow(display, Refnone) < 0)
+		sysfatal("can't reattach to window");
+	
+	drawlevel();
+}
+
+void 
+main(int argc, char **argv)
+{
+	Mouse m;
+	Event e;
+	int clickety = 0;
+
+	ARGBEGIN{
+	case 'h':
+		usage(argv0);
+	case 'b':
+		defbackgr = EARGF(usage(argv0));
+		break;
+	case 'l':
+		deflayout = EARGF(usage(argv0));
+		break;
+	case 't':
+		deftileset = EARGF(usage(argv0));
+		break;
+	case 'c':
+		defchan = RGBA32;
+		break;
+	}ARGEND
+
+	if(argc > 0) 
+		usage(argv0);
+		
+	if(! parse(deflayout)) {
+		fprint(2, "usage: %s [levelfile]\n", argv[0]);
+		exits("usage");
+	}
+
+	if(initdraw(nil, nil, "mahjongg") < 0)
+		sysfatal("initdraw failed: %r");
+	einit(Emouse|Ekeyboard);
+
+	allocimages();
+	resize(img->r.max);
+
+	generate(time(0));
+	drawlevel();
+	for(;;) {
+		if(level.remaining == 0 && !level.done)
+			done();
+		switch(event(&e)) {
+		case Emouse:
+			m = e.mouse;
+			if(m.buttons&1) {
+				if(level.done)
+					break;
+				if(!clickety && level.remaining > 0) {
+					clickety = 1;
+					clicked(subpt(m.xy, addpt(screen->r.min, Pt(30, 30))));
+				}
+			} else 
+				clickety = 0;
+			if(m.buttons&2) {
+				/* nothing here for the moment */
+			}
+			if(m.buttons&4)
+				switch(emenuhit(3, &m, &menu)) {
+				case 0:
+					generate(time(0));
+					drawlevel();
+					break;
+				case 1:
+					level = orig;
+					drawlevel();
+					break;
+				case 2:
+					resize(img->r.max);
+					break;
+				case 3:
+					exits(nil);
+				}
+			break;
+		case 2:
+			switch(e.kbdc) {
+			case 127:
+			case 'q':
+			case 'Q':
+				exits(nil);
+			case 'h':
+			case 'H':
+				if(!level.done)
+					hint();
+				break;
+			case 'n':
+			case 'N':
+				/* new */
+				generate(time(0));
+				break;
+			case 'r':
+			case 'R':
+				level = orig;
+				break;
+			case 'c':
+			case 'C':
+				clearlevel();
+				break;
+			}
+			if(! level.done)
+				drawlevel();
+			break;
+		}
+	}
+}

+ 88 - 0
sys/src/games/mahjongg/mahjongg.h

@@ -0,0 +1,88 @@
+enum {
+
+	/* 
+	 * D[1-4], the seasons, appear only once
+	 * F[1-4], the flowers, appear only once
+	 * everything else appears 4 times
+	 * for a total of 144
+	 */
+	A1 = 0, A2, A3, A4, A5, A6, A7, A8, A9,
+	B1, B2, B3, B4, B5, B6, B7, B8, B9,
+	C1, C2, C3, C4, C5, C6, C7, C8, C9,	
+	D1, D2, D3, D4, E1, E2, E3, E4, 
+	F1, F2, F3, F4, G1, G2, G3,
+	Seasons,
+	Flowers,
+}; 
+
+enum {
+	/* level-specific enums */
+	Tiles = 144,
+	Depth = 5,
+	TileDxy = 6,	/* tile displacement when on a higher level */
+	Lx = 32,
+	Ly = 16,
+};
+enum {
+	/* the size of a complete tile */
+	Tilex = 60,
+	Tiley = 74,
+	
+	/* only the face part */
+	Facex = 54,
+	Facey = 68,
+
+	/* and the entire window, giving room for 5*6 = 30 pixels
+	 * that are needed for the higher tiles
+	 */
+	Sizex = 16*Facex + 2*Depth*TileDxy,
+	Sizey = 8*Facey + 2*Depth*TileDxy,
+};
+
+
+typedef struct {
+	Point start;	/* where do we draw here */
+	int clicked;
+	int which;		/* 0 ↔ 4 */
+	int type;
+} Brick;
+
+typedef struct {
+	int d;
+	Point p;
+} Click;
+
+typedef struct {
+	Brick 	board[Depth][Lx][Ly];
+	Click		c; 		/* player has a brick selected */
+	int			done;
+	int 		remaining;
+} Level;
+
+Level level;	/* the level played */
+Level orig;		/* same, sans modifications */
+
+Image *img;		/* buffer */
+
+Image *tileset;
+Image *brdr;
+Image *mask;
+Image *background;
+Image *selected;
+Image *gameover;
+
+/* graphics.c */
+void drawlevel(void);
+void resize(Point);
+void clicked(Point);
+void hint(void);
+void done(void);
+void clearlevel(void);
+
+/* mahjongg.c */
+char *genlevels(int);
+Image *eallocimage(Rectangle, int, uint, uint);
+
+/* level.c */
+int parse(char *);
+void generate(uint seed);

+ 19 - 0
sys/src/games/mahjongg/mkfile

@@ -0,0 +1,19 @@
+</$objtype/mkfile
+BIN=/$objtype/bin/games
+
+TARG=mahjongg
+OFILES=\
+	mahjongg.$O\
+	graphics.$O\
+	level.$O\
+
+
+HFILES=mahjongg.h\
+
+UPDATE=\
+	mkfile\
+	$HFILES\
+	${OFILES:%.$O=%.c}\
+	`{ls /sys/games/lib/mahjongg/*}
+
+</sys/src/cmd/mkone

+ 124 - 0
sys/src/games/sokoban/graphics.c

@@ -0,0 +1,124 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+#include "sokoban.h"
+
+void
+drawscreen(void)
+{
+	draw(screen, screen->r, img, nil, ZP);
+	flushimage(display, 1);
+}
+
+void
+drawglenda(void)
+{
+	Rectangle r;
+	Point p;
+
+	p = level.glenda;
+	p.x *= BoardX;
+	p.y *= BoardY;
+	/* leave some room from the edge of the window */
+	p = addpt(p, Pt(1, 1));
+
+	r = Rpt(p, Pt(p.x + BoardX, p.y+BoardY));
+	draw(img, r, glenda, nil, ZP);
+}
+
+void
+drawwin(void)
+{
+	Rectangle r;
+	Point p;
+
+	p = level.glenda;
+	p.x *= BoardX;
+	p.y *= BoardY;
+	p = addpt(p, Pt(6, 6));
+	p = addpt(p, Pt(1, 1));
+
+	r = Rpt(p, Pt(p.x + BoardX, p.y+BoardY));
+	draw(img, r, text, win, ZP);
+}
+
+void
+drawboard(Point p)
+{
+	Rectangle r;
+	uint square = level.board[p.x][p.y];
+
+	p.x *= BoardX;
+	p.y *= BoardY;
+
+	/* leave some room from the edge of the window */
+	p = addpt(p, Pt(1, 1));
+
+	r = Rpt(p, Pt(p.x + BoardX, p.y+BoardY));
+
+	switch(square) {
+	case Background:
+		draw(img, r, bg, nil, ZP);
+		break;
+	case Empty:
+		draw(img, r, empty, nil, ZP);
+		break;
+	case Wall:
+		draw(img, r, wall, nil, ZP);
+		break;
+	case Cargo:
+		draw(img, r, cargo, nil, ZP);
+		break;
+	case Goal:
+		draw(img, r, goal, nil, ZP);
+		break;
+	case GoalCargo:
+		draw(img, r, goalcargo, nil, ZP);
+		break;
+	}
+}
+
+void
+resize(Point p)
+{
+	/* resize to the size of the current level */
+
+	int fd;
+
+	fd = open("/dev/wctl", OWRITE);
+	if(fd >= 0){
+		fprint(fd, "resize -dx %d -dy %d", p.x*BoardX+10, p.y*BoardY+10);
+		close(fd);
+	}
+
+}
+
+Point
+boardsize(Point p)
+{
+	return Pt(p.x*BoardX+2, p.y*BoardY+2);
+}
+
+void
+drawlevel(void)
+{
+	int x, y;
+
+	resize(level.max);
+
+	if(img)
+		freeimage(img);
+	img = eallocimage(Rpt(Pt(0, 0), boardsize(level.max)), 0, 0);	
+
+	draw(img, insetrect(img->r, 1), empty, nil, ZP);
+
+	for(x = 0; x < MazeX; x++) {
+		for(y = 0; y < MazeY; y++) {
+			drawboard(Pt(x, y));
+		}
+	}
+
+	drawglenda();
+}

+ 101 - 0
sys/src/games/sokoban/level.c

@@ -0,0 +1,101 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+
+#include "sokoban.h"
+
+void
+consumeline(Biobuf *b)
+{
+	while(Bgetc(b) != '\n')
+		;
+}
+
+/* parse a level file */
+int
+loadlevels(char *path)
+{
+	Biobuf *b;
+	int x = 0, y = 0, lnum = 0;
+	char c;
+		
+	if(path == nil)
+		return 0;
+
+	b = Bopen(path, OREAD);
+	if(b == nil) {
+		fprint(2, "could not open file %s: %r\n", path);
+		return 0;
+	}
+
+	memset(levels, 0, Maxlevels*sizeof(Level));
+	
+	while((c = Bgetc(b)) > 0) {
+		switch(c)  {
+		case ';':
+			consumeline(b); 	/* no ';'-comments in the middle of a level */
+			break;
+		case '\n':
+			levels[lnum].index = lnum;
+			levels[lnum].done = 0;
+			x = 0;
+			levels[lnum].max.y = ++y;
+
+			c = Bgetc(b);
+			if(c == '\n' || c == Beof) {
+				/* end of level */
+				if(++lnum == Maxlevels)
+					goto Done;
+
+				x = 0;
+				y = 0;
+			} else
+				Bungetc(b);
+			break;
+		case '#':
+			levels[lnum].board[x][y] = Wall;
+			x++;
+			break;
+		case ' ':
+			levels[lnum].board[x][y] = Empty;
+			x++;
+			break;
+		case '$':
+			levels[lnum].board[x][y] = Cargo;
+			x++;
+			break;
+		case '*':
+			levels[lnum].board[x][y] = GoalCargo;
+			x++;
+			break;
+		case '.':
+			levels[lnum].board[x][y] = Goal;
+			x++;
+			break;
+		case '@':
+			levels[lnum].board[x][y] = Empty;
+			levels[lnum].glenda = Pt(x, y);
+			x++;
+			break;
+		case '+':
+			levels[lnum].board[x][y] = Goal;
+			levels[lnum].glenda = Pt(x, y);
+			x++;
+			break;
+		default:
+			fprint(2, "impossible character for level %d: %c\n", lnum+1, c);
+			return 0;
+		}
+		if(x > levels[lnum].max.x)
+			levels[lnum].max.x = x;
+		levels[lnum].max.y = y;
+	}
+Done:
+	Bterm(b);
+
+	level = levels[0];
+	numlevels = lnum;
+
+	return 1;
+}

+ 20 - 0
sys/src/games/sokoban/mkfile

@@ -0,0 +1,20 @@
+</$objtype/mkfile
+BIN=/$objtype/bin/games
+
+TARG=sokoban
+OFILES=\
+	sokoban.$O\
+	move.$O\
+	graphics.$O\
+	level.$O\
+
+
+HFILES=sokoban.h\
+
+UPDATE=\
+	mkfile\
+	$HFILES\
+	${OFILES:%.$O=%.c}\
+	`{ls /sys/games/lib/sokoban/*}
+
+</sys/src/cmd/mkone

+ 136 - 0
sys/src/games/sokoban/move.c

@@ -0,0 +1,136 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+#include "sokoban.h"
+
+/* pretty ghastly, if you ask me */
+void
+move(int key)
+{
+	Point g = level.glenda;
+	int moved = 0;
+
+	/* this is messy; no time for math */
+	switch(key) {
+	case Up:
+		switch(level.board[g.x][g.y-1]) {
+		case Empty:
+		case Goal:
+			moved = 1;
+			level.glenda = Pt(g.x, g.y-1);
+			break;
+		case Cargo:
+		case GoalCargo:
+			switch(level.board[g.x][g.y-2]) {
+			case Empty:
+				moved = 1;
+				level.board[g.x][g.y-2] = Cargo;
+				drawboard(Pt(g.x, g.y-2));
+				break;
+			case Goal:
+				moved = 1;
+				level.board[g.x][g.y-2] = GoalCargo;
+				drawboard(Pt(g.x, g.y-2));
+				break;
+			}
+			if(moved) {
+				level.board[g.x][g.y-1] = (level.board[g.x][g.y-1] == Cargo) ? Empty : Goal;
+				level.glenda = Pt(g.x, g.y-1);
+			}
+			break;
+		}
+		break;
+	case Down:
+		switch(level.board[g.x][g.y+1]) {
+		case Empty:
+		case Goal:
+			moved = 1;
+			level.glenda = Pt(g.x, g.y+1);
+			break;
+		case Cargo:
+		case GoalCargo:
+			switch(level.board[g.x][g.y+2]) {
+			case Empty:
+				moved = 1;
+				level.board[g.x][g.y+2] = Cargo;
+				drawboard(Pt(g.x, g.y+2));
+				break;
+			case Goal:
+				moved = 1;
+				level.board[g.x][g.y+2] = GoalCargo;
+				drawboard(Pt(g.x, g.y+2));
+				break;
+			}
+			if(moved) {
+				level.board[g.x][g.y+1] = (level.board[g.x][g.y+1] == Cargo) ? Empty : Goal;
+				level.glenda = Pt(g.x, g.y+1);
+			}
+			break;
+		}
+		break;
+	case Left:
+		glenda = gleft;
+		switch(level.board[g.x-1][g.y]) {
+		case Empty:
+		case Goal:
+			moved = 1;
+			level.glenda = Pt(g.x-1, g.y);
+			break;
+		case Cargo:
+		case GoalCargo:
+			switch(level.board[g.x-2][g.y]) {
+			case Empty:
+				moved = 1;
+				level.board[g.x-2][g.y] = Cargo;
+				drawboard(Pt(g.x-2, g.y));
+				break;
+			case Goal:
+				moved = 1;
+				level.board[g.x-2][g.y] = GoalCargo;
+				drawboard(Pt(g.x-2, g.y));
+				break;
+			}
+			if(moved) {
+				level.board[g.x-1][g.y] = (level.board[g.x-1][g.y] == Cargo) ? Empty : Goal;
+				level.glenda = Pt(g.x-1, g.y);
+			}
+			break;
+		}
+		break;
+	case Right:
+		glenda = gright;
+		switch(level.board[g.x+1][g.y]) {
+		case Empty:
+		case Goal:
+			moved = 1;
+			level.glenda = Pt(g.x+1, g.y);
+			break;
+		case Cargo:
+		case GoalCargo:
+			switch(level.board[g.x+2][g.y]) {
+			case Empty:
+				moved = 1;
+				level.board[g.x+2][g.y] = Cargo;
+				drawboard(Pt(g.x+2, g.y));
+				break;
+			case Goal:
+				moved = 1;
+				level.board[g.x+2][g.y] = GoalCargo;
+				drawboard(Pt(g.x+2, g.y));
+				break;
+			}
+			if(moved) {
+				level.board[g.x+1][g.y] = (level.board[g.x+1][g.y] == Cargo) ? Empty : Goal;
+				level.glenda = Pt(g.x+1, g.y);
+			}
+			break;
+		}
+		break;
+	}
+	if(moved)
+		drawboard(Pt(g.x, g.y));
+
+	drawglenda();
+}
+

+ 294 - 0
sys/src/games/sokoban/sokoban.c

@@ -0,0 +1,294 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+#include "sokoban.h"
+
+char *LEasy = "/sys/games/lib/sokoban/levels/easy.slc";
+char *LHard = "levels/hard.slc";
+char *levelfile;
+
+char		*GRImage = "/sys/games/lib/sokoban/images/right.bit";
+char		*GLImage = "/sys/games/lib/sokoban/images/left.bit";
+char		*WallImage = "/sys/games/lib/sokoban/images/wall.bit";
+char		*EmptyImage = "/sys/games/lib/sokoban/images/empty.bit";
+char		*CargoImage = "/sys/games/lib/sokoban/images/cargo.bit";
+char		*GoalCargoImage = "/sys/games/lib/sokoban/images/goalcargo.bit";
+char		*GoalImage = "/sys/games/lib/sokoban/images/goal.bit";
+char		*WinImage = "/sys/games/lib/sokoban/images/win.bit";
+
+
+char *buttons[] = 
+{
+	"restart",
+	"easy",
+	"hard",
+	"exit",
+	0
+};
+
+Menu menu = 
+{
+	buttons
+};
+
+Menu lmenu =
+{
+	nil,
+	genlevels,
+	0,
+};
+
+Image *
+eallocimage(Rectangle r, int repl, uint color)
+{
+	Image *tmp;
+
+	tmp = allocimage(display, r, screen->chan, repl, color);
+	if(tmp == nil)
+		sysfatal("cannot allocate buffer image: %r");
+
+	return tmp;
+}
+
+Image *
+eloadfile(char *path)
+{
+	Image *img;
+	int fd;
+
+	fd = open(path, OREAD);
+	if(fd < 0) {
+		fprint(2, "cannot open image file %s: %r\n", path);
+		exits("image");
+	}
+	img = readimage(display, fd, 0);
+	if(img == nil)
+		sysfatal("cannot load image: %r");
+	close(fd);
+	
+	return img;
+}
+
+
+void
+allocimages(void)
+{
+	Rectangle one = Rect(0, 0, 1, 1);
+	
+	bg		= eallocimage(one, 1, DDarkyellow);
+	text 		= eallocimage(one, 1, DBluegreen);
+
+	gright = eloadfile(GRImage);
+	gleft = eloadfile(GLImage);
+	wall = eloadfile(WallImage);
+	empty = eloadfile(EmptyImage);
+	empty->repl = 1;
+	goalcargo = eloadfile(GoalCargoImage);
+	cargo = eloadfile(CargoImage);
+	goal = eloadfile(GoalImage);
+	win = eloadfile(WinImage);
+}
+
+int
+key2move(int key)
+{
+	int k = 0;
+
+	switch(key) {
+	case 61454:
+		k = Up;
+		break;
+	case 63488:
+		k = Down;
+		break;
+	case 61457:
+		k = Left;
+		break;
+	case 61458:
+		k = Right;
+		break;
+	}
+
+	return k;
+}
+int
+mousemove(Mouse m)
+{
+	Point p;
+
+	p = subpt(m.xy, screen->r.min);
+	p.x /= BoardX;
+	p.y /= BoardY;
+
+	if(eqpt(p, addpt(level.glenda, Pt(0, -1))))
+		return Up;
+	if(eqpt(p, addpt(level.glenda, Pt(0, 1))))
+		return Down;
+	if(eqpt(p, addpt(level.glenda, Pt(-1, 0))))
+		return Left;
+	if(eqpt(p, addpt(level.glenda, Pt(1, 0))))
+		return Right;
+}
+
+char *
+genlevels(int i)
+{
+	
+	if(i >= numlevels)
+		return 0;
+
+	return smprint("level %d", i+1);
+}
+
+
+int
+finished(void)
+{
+	int x, y;
+	for(x = 0; x < MazeX; x++)
+		for(y = 0; y < MazeY; y++)
+			if(level.board[x][y] == Goal)
+				return 0;
+
+	return 1;
+}
+
+void
+eresized(int new)
+{
+	Point p;
+
+	if(new && getwindow(display, Refnone) < 0)
+		sysfatal("can't reattach to window");
+	
+	p = Pt(Dx(screen->r), Dy(screen->r));
+
+	if(!new || !eqpt(p, boardsize(level.max))) {
+		drawlevel();
+	}
+	drawscreen();
+}
+
+void 
+main(int argc, char **argv)
+{
+	Mouse m;
+	Event e;
+
+	if(argc == 2) 
+		levelfile = argv[1];
+	else
+		levelfile = LEasy;
+		
+	if(! loadlevels(levelfile)) {
+		fprint(2, "usage: %s [levelfile]\n", argv[0]);
+		exits("usage");
+	}
+
+	if(initdraw(nil, nil, "sokoban") < 0)
+		sysfatal("initdraw failed: %r");
+	einit(Emouse|Ekeyboard);
+
+	allocimages();
+	glenda = gright;
+	eresized(0);
+
+	for(;;) {
+		switch(event(&e)) {
+		case Emouse:
+			m = e.mouse;
+			if(m.buttons&1) {
+				move(mousemove(m));
+				drawscreen();
+			}
+			if(m.buttons&2) {
+				int l;
+				/* levels start from 1 */
+				lmenu.lasthit = level.index;
+				l=emenuhit(2, &m, &lmenu);
+				if(l>=0){
+					level = levels[l];
+					drawlevel();
+					drawscreen();
+				}
+			}
+			if(m.buttons&4)
+				switch(emenuhit(3, &m, &menu)) {
+				case 0:
+					level = levels[level.index];
+					drawlevel();
+					drawscreen();
+					break;
+				case 1:
+					loadlevels(LEasy);
+					drawlevel();
+					drawscreen();
+					break;
+				case 2:
+					loadlevels(LHard);
+					drawlevel();
+					drawscreen();
+					break;
+				case 3:
+					exits(nil);
+				}
+			break;
+
+		case Ekeyboard:
+			if(level.done)
+				break;
+
+			switch(e.kbdc) {
+			case 127:
+			case 'q':
+			case 'Q':
+				exits(nil);
+			case 'n':
+			case 'N':
+				if(level.index < numlevels - 1) {
+					level = levels[++level.index];
+					drawlevel();
+					drawscreen();
+				}
+				break;
+			case 'p':
+			case 'P':
+				if(level.index > 0) {
+					level = levels[--level.index];
+					drawlevel();
+					drawscreen();
+				}
+				break;
+			case 'r':
+			case 'R':
+				level = levels[level.index];
+				drawlevel();
+				drawscreen();
+				break;
+			case 61454:
+			case 63488:
+			case 61457:
+			case 61458:
+			case ' ':
+				move(key2move(e.kbdc));
+				drawscreen();
+				break;
+			}
+			break;
+		}
+
+		if(finished()) {
+			level.done = 1;
+			drawwin();
+			drawscreen();
+			sleep(3000);
+			if(level.index < numlevels - 1) {
+				level = levels[++level.index];
+				drawlevel();
+				drawscreen();
+			}
+		}
+	}
+}

+ 79 - 0
sys/src/games/sokoban/sokoban.h

@@ -0,0 +1,79 @@
+enum {
+	/* levels */
+	Empty		= 0,
+	Background,
+	Wall, 
+	Cargo,
+	Goal,
+	GoalCargo,
+	Glenda,
+
+	/* movements */
+	Up,
+	Down,
+	Left,
+	Right,
+};
+
+enum {
+	/* glenda faces the horizontal direction she's moving in */
+	GLeft	= 0,
+	GRight 	= 1,
+};
+
+enum {
+	MazeX = 20,
+	MazeY = 18,
+	BoardX = 49,
+	BoardY = 49,
+	SizeX = MazeX*BoardX+10,	
+	SizeY = MazeY*BoardY+10,
+
+	Maxlevels = 200,
+};
+
+typedef struct {
+	Point 	glenda;
+	Point 	max;		/* that's how much the board spans */
+	uint 	index;
+	uint	done;
+	uint 	board[MazeX][MazeY];
+} Level;
+
+Level level;		/* the current level */
+Level levels[Maxlevels];	/* all levels from this file */
+int numlevels;		/* how many levels do we have */
+
+Image *img;		/* buffer */
+Image *text;		/* for text messages */
+Image *win;
+
+Image *goal;
+Image *cargo;
+Image *goalcargo;
+Image *wall;
+Image *empty;
+Image *gleft;
+Image *gright;
+Image *glenda;
+Image *bg;
+
+/* graphics.c */
+void drawscreen(void);
+void drawlevel(void);
+void drawwin(void);
+void drawglenda(void);
+void drawboard(Point);
+void resize(Point);
+Point boardsize(Point);
+
+
+/* level.c */
+int loadlevels(char *);
+
+/* move.c */
+void move(int);
+
+/* sokoban.c */
+char *genlevels(int);
+Image *eallocimage(Rectangle, int, uint);