乱数とチート
きっと srand(time(0)); 的なことしていて現行の計算機の時間解像度はプランク定数から見れば巨視なので状態の観測による非ユニタリ発展を操作できてもあまり意味は無いかもしれません。
ところでセガのテトリス(猿のヤツ) では time(0) 的なものが起動からの時間であったのか、電源入れて最初のプレイでは全く同じブロックが出てくるらしく、スコアラーはブロックの出現順を記録して全部テトリスになるパターンを考えて最速カンストを達成したということです。
追記: よく考えると time(0) なんて使わずに定数を srand に渡してただけか…
さて、 PC で time(0) 的なものを制御できるか、ですけど UNIX では比較的簡単にできます。
long time(long* l) { if (l != (long*)0) { /* not implemented */ return -1; } else { return 0; } }
まあこの程度。
gcc -o time.so -shared time.c export LD_PRELOAD=./time.so
などとしてから time(0) で乱数を初期化しているゲームを呼んでやると、例えば sdmkun で実験したのですが、はい同じ弾幕しか出てこなくなりました。
で、件の Moebius Syndrome は、 time は使ってなくて、 gettimeofday 使ってるのかな… strace しても少しよくわかりませんでした。
まあ、この場合乱数列の制御なんていう面倒なことはしなくて良いです。
#define _GNU_SOURCE #include <stdio.h> #include <dlfcn.h> #include <unistd.h> struct timeval { long tv_sec; long tv_usec; }; struct timezone { int tz_minuteswest; int tz_dsttime; }; int gettimeofday(struct timeval* tv, struct timezone* tz) { static int (*old_gettimeofday)(struct timeval* tv, struct timezone* tz) = NULL; static struct timeval base; static struct timeval* basep = NULL; if (old_gettimeofday == NULL) { old_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday"); } if (basep == NULL) { basep = &base; old_gettimeofday(basep, tz); } old_gettimeofday(tv, tz); tv->tv_sec = (tv->tv_sec - basep->tv_sec) >> 1; tv->tv_usec = (tv->tv_usec - basep->tv_usec) >> 1; return 0; }
なんていうものを書いて、
gcc -o time.so -shared time.c export LD_PRELOAD=/lib/libdl.so.2:./time.so gflashplayer http://flash.games.for.free.fr/moebius/swf/moebius.swf
などと。はい、スローになりました、 CPU に負荷かけるよりはるかにリーズナブル、と。ひどい。
ゲームの乱数初期化・時間取得は CPU の機能使うしかないのかな。
お前は何が言いたかったのだ、という記述でした。
ところで、ネットワークから切断して驚異的な記録を出そうとプレイしたのですが、 0.5倍速でも 400 程度のスコアで終わってしまったのでした。