引用元:https://www.ioccc.org/2005/anon/anon.c
審査員・作者による説明:https://www.ioccc.org/2005/anon/hint.text
動作
15パズルの任意サイズ化+3D対応。
次のように起動すると普通の15パズルになる。
$ gcc -o anon anon.c
$ ./anon 4 4
15 7 13 2
10 3 1 5
## 8 11 6
14 9 4 12
##
が空きマス。jとlで空きマスを左右に動かし、iとkで上下に動かす。
次のように起動すると3次元化する。
$ ./anon 3 3 3
7 11 1
12 9 22
25 23 4
18 17 8
6 14 26
2 20 13
10 24 21
15 19 5
## 16 3
操作方法は2D版に加え、oで奥方向に動かし、nで手前方向に動かす。
解説
難読化の一番のポイントとされているのは、変数宣言もmalloc
もせずに動いていること。
argc
とargv
だけでどうにかしているわけでもない。
どうしているかというと、main
を再帰させることでスタックを伸ばし、その連続領域をメモリとして使っている。
スタックが伸びる方向は環境によって違いがあるが、検出して適切に扱っているとのこと。
確保された領域は、フレームポインタやリターンアドレスも遠慮なく書き潰されるので、スタックは破壊される。
そのためmain
関数は正常にreturn
はできないので、終了するときはexit()
を使っている。
生成されるパズルは解けないこともある。
初期版はパリティチェックしていたが、IOCCCのサイズ制限のために除去したとのこと。
ゲーム中毒防止のため(?)、また、解けないパズルに無限の時間を使ってしまわないようにするため、長く操作をしているとそのうち異常終了するとのこと。
操作のたびにmain
を再帰することにより、そのうちスタックオーバーフローするという仕様になっている。
ia64でポインタを格納するためにint
ではなくlong
にした、という記述があり、近代になってきた感がある。
マクロを使った難読化もいろいろ行われている。
多くのマクロはサブルーチン的に使われているので、単純にプリプロセスで展開してもわかりやすくならない。
main
関数が1つの巨大なreturn
文になっているので、indentコマンドをかけるのもほとんど無力。
hint.textに各マクロやデータ構造の詳細な解説があるので、興味があれば参照するとよい。