Best 3D puzzle

最高の3Dパズル

受賞者:Anonymous

引用元: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

##が空きマス。jlで空きマスを左右に動かし、ikで上下に動かす。

次のように起動すると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もせずに動いていること。 argcargvだけでどうにかしているわけでもない。 どうしているかというと、mainを再帰させることでスタックを伸ばし、その連続領域をメモリとして使っている。 スタックが伸びる方向は環境によって違いがあるが、検出して適切に扱っているとのこと。

確保された領域は、フレームポインタやリターンアドレスも遠慮なく書き潰されるので、スタックは破壊される。 そのためmain関数は正常にreturnはできないので、終了するときはexit()を使っている。

生成されるパズルは解けないこともある。 初期版はパリティチェックしていたが、IOCCCのサイズ制限のために除去したとのこと。

ゲーム中毒防止のため(?)、また、解けないパズルに無限の時間を使ってしまわないようにするため、長く操作をしているとそのうち異常終了するとのこと。 操作のたびにmainを再帰することにより、そのうちスタックオーバーフローするという仕様になっている。

ia64でポインタを格納するためにintではなくlongにした、という記述があり、近代になってきた感がある。

マクロを使った難読化もいろいろ行われている。 多くのマクロはサブルーチン的に使われているので、単純にプリプロセスで展開してもわかりやすくならない。 main関数が1つの巨大なreturn文になっているので、indentコマンドをかけるのもほとんど無力。 hint.textに各マクロやデータ構造の詳細な解説があるので、興味があれば参照するとよい。