ICFP2007 (25) Steganographyの続きです。
草の乱数の初期値が分かりました。
地面の草を描くdrawGrassPatchは第一パラメータの59文字の文字列を乱数seedとして受け取ります。drawGrassPatchの一番最初の処理は文字配列seedとint24配列biomorphPerturbを要素毎に加えています。biomorphPerturbの初期値は0です。biomorphPerturbを書き換えると草が生える場所が変わります。通常のコードでbiomorphPerturbを変更するコードはpayloadBioMorphという関数にしかありません。payloadBioMorphは2つのパラメータindexとvalueをとって(名前は適当に決めました)、biomorphPerturb[index] = valueという処理を行います。
payloadBioMorphはpayloadBioMorph_adaptationから呼ばれています。そしてpayloadBiomorphはmainで一番最初に呼ばれているadaptationであるbiomorph_adaptationで呼ばれています。
さて、このbiomorph_adaptationですが壊れています。少なくともbiomorph_adaptationを修復する必要があります。関連して中で呼ばれているbioMul_adaptationも修復する必要があります。このあたりの話は
help-initial-condに書かれています。似た記法でbioMulを書いてみると次のようになるはずです。
bioMul Zero y = Zero
bioMul (Succ x) y = bioAdd (bioMul x y) y
C風に書くと次のような再帰関数になると思います。
int bioMul(int x, int y)
{
if(x == 0) return 0;
else bioMul(x - 1, y) + y;
}
今のところ、biomorph_adaptationの完全な修復はできていません。数値の形式が何種類かあるみたいで、どのadaptationにどの形式を渡せばいいのかがよく分かっていません。少なくとも、mkほにゃの形式、bioほにゃの形式、intBoxの形式があります。
biomorph_adaptationの中で一番最初に呼ばれているのはenableBioMorph_adaptationです。中身はfalseになっていますが、trueに変える必要があります。このadaptationはtrueの時にパラメータを逐次実行する機能があるようです。トレースすると実行の様子が変わります。初期値はfalseになっています。enableBioMorph_adaptationのパラメータが上にでてきたpayloadBioMorph_adaptationです。3回呼ばれています。雰囲気的に以下のようなパラメータで呼び出されているっぽいコードになっています。
payloadBioMorph_adaptation 1 * 3 -4 * 4
payloadBioMorph_adaptation 3 * 3 1 * 7
payloadBioMorph_adaptation 7 * 3 2 * 2
このパラメータがpayloadBioMorphに渡されるのだとすると、biomorphPerturbの3番目に-16、9番目に7、21番目に4が書かれるはずです。試しに書いてみたところビンゴで、草が正しい位置に表示されました。
どうせdrawGrassPatchのseedに足されるのでseedを足された値に書き換えてやってもうまくいきます。書き換えた初期値です。
El gasto ziempre se vi mas verde del otro lado de la cerca.
もしかするとbioMul_adaptationの修復だけで十分なのかもしれません。問題の切り分けができていないというか、biomorph_adaptationの他の部分も壊れているのかどうか、よく分かりません。
残っているballoon(ふきだし)ですが、2つのことが分かりました。
1つ目です。グラデーションを描くdrawGradientCornerNWの位置とサイズが分かりました。balloonを取り囲む最小の長方形にすれば、うまくいきました。
左上の座標が(198, 324)でパラメータが(101, 169)です。実際は102x170なのですが、drawGradientCornerNWに渡すときは1ずつ小さい値にしないといけないようです。
2つ目です。分かったというか、無理やり作りました。ターゲット画像からballoonの枠のドットの座標を全部拾い出して、線画で描くときの移動量をプログラムで探索してpolygonのパラメータを作りました。探索プログラムはgreedyなので、最適とは限りませんが、全ての開始地点について探索を行った中で最も線分の数が少なくなるものです。
探索アルゴリズムは基準点から別の点まで線を引いたときに途中の点を全て通る線の中で一番遠くまで引けたものを採用して、基準点を更新していきます。とりあえず一番遠くまで引けなくても、先まで考えると遠くまで引けるかもしれないといった探索は一切行っていません(というのがgreedyな所以ですね)。どうせ塗りつぶすので、途中の内側に点を作ると、もしかすると短縮できるかもしれませんが、考慮していません。
balloonのpolygonデータ
72,
55, 59,
-7, -1, -6, 2, -4, 5, -2, 2, 0,12, 5, 8, 2, 6, 5, 6, -3, 5, -2, 1,
-4, 7, -2, 1, -16, 17, -4, 3, -14,12, 0, 5, 1, 2, 2, 5, 5, 5, 5, 1,
2, 1, 4, 0, 0, 1, -2, 1, -1, 3, -3,-2, -4,-1, -4,-3, -7,-7, -1, -3,
0, -9, 7,-6, 36,-36, 1,-3, -5,-8, -4,-5, -1,-3, 0,-2, -3,-3, -1, -3,
0,-10, 7,-8, 1, 0, 5,-5, 1, 0, 1,-1, -2,-5, -2,-6, -1,-9, 2,-11,
3, -6, 3,-4, 5, -5, 8,-3, 8,-2, 8, 3, 2, 0, 5, 3, 6, 4, 5, 4,
0, 1, 4, 5, 2, 6, -2,13, -4, 5, -1, 3, -4, 4, -6, 3, -4, 3, -11 2,
-14, 0,
0, 0,
というわけで最新の修復画像です。残りはμだけです。ターゲット画像とは548ピクセル異なっています。
μですが、たぶんfontTable_Tempus-Bold-HugeというフォントのMです。ただ、この文字を描こうとするとDNAが途中で止まってしまいます。壊れているみたいです。charInfo_Tempus-Bold-Huge_Mがμの描画情報みたいです。
最後の最後まで楽しませてくれます。