zzzです。

 仕様をよくわかっていなかったせいでひどいバグに見舞われました。

 まず平面にテクスチャを張って線形フィルタを使っていたのですが、どうも面の境界部分の表示がおかしいんですよね。そこで掘木さんに相談していたところ、「上下でループしてるんじゃね?」とありがたいお言葉を頂き、まさにそのとおりでした。

 自分なりの解釈はこうです。

 線形フィルタは上下左右の最も近いテクセルについて加重平均を行い色を決定しているらしいんですけど、その際境界部分を描画する際は、境界からはみ出た部分のテクセルについても考慮するようです。はみ出た部分は一体どうなるのでしょう?
 それはアドレッシングモードによって違います。デフォルトは多分D3DTADDRESS_WRAPでこれは単純に同じ柄をタイルのように貼り付けるだけです。
 線形フィルタでは境界部分に気をつけないといけないようです。このせいで上下ループしているような画像になってしまったわけです。

 解決法は至極簡単で、アドレッシングモードを適切なものに変えてやればよいです。
 アドレッシングモードをD3DTADDRESS_BORDERにすれば、ループ部分を特定の色にすることができます。D3DSAMP_BORDERCOLORに透明色を貼り付ければ、ちゃんと表示されます。……死ぬほど悩みましたが掘木さんが即解決してました。……なんで分かるんでしょう。謎です。神です。
2012.05.25 隔絶
 いまさらながら鳥船遺跡を買ってきて視聴し終えた。

 「衛星トリフネ」「トロヤ郡の密林」「ハルトマンの妖怪少女」「宇宙に浮かぶ幻想郷」あたりが好みだ。特にトロヤ。……いかに素晴らしいかを語ろうと思ったけど、音楽関係の知識、語句に乏しく断念。とにかくベタで王道だとは思う(音楽の王道ってなんだろうね?)

 いまさらながらinfinitismを買って来て視聴し終えた。数学的な話題を出されるととても興奮する。finitism派なのがクロネッカー。infinitismに取り殺されたのはカントール。南無。

 私が刺さったのが「infinitism」「底」「崩壊の碑」だった。圧倒的にinfinitismが強い。圧倒的に。
 ……どう刺さったのかを語ろうと思ったけど、どんな刺され方をされたいのか上手く語れないので断念。
2012.05.23 遅々
 zzzです。

 現在タイトル画面を作っていますが難航中。意外にキー判定がうざい……。

title

 味気ないですがここまでに一日以上かかっています……。やばい。やばすぎです。
 zzzです。

 ポケモン界の最強3種、「ラブカス」「アンノーン」「ミツハニー」について考察してみました。

 まずアンノーンですが、なんと威力70のめざめるパワー電気を使うことができます。これでラブカスとミツハニーに対応することが出来ます。

 ダメージ計算を行ってみると、C252補正有り拘りメガネアンノーンで防御補正なしラブカス、ミツハニーを確1にすることができ、きっちり最強2種を抑えることが出来ます。

 しかしミツハニーはアンノーンよりすばやさが速いため、先制でむしくいを打つことが出来ます。

 A252補正有りこだわりハチマキミツハニーで防御補正なしアンノーンを確1、HP252防御補正なしアンノーンを乱数1発(25%)で倒すことが出来ます。これでミツハニーはアンノーンに圧倒的有利と言えるでしょう。

 ここでラブカスの登場です。ラブカスはれいとうビームを覚えることが出来ます。

 C252補正有り持ち物なしラブカスで防御補正なしミツハニーを確1です。ミツハニーに対してラブカスは非常に有利と言えるでしょう。

 よってラブカス、アンノーン、ミツハニーの三角関係が出来ました。ポケモン界最強三種と言われる所以はこのせいです。
 無限の可能性溢れる3種なのでほかにもいろいろな使い方、役割がありますが、基本はこれですので、皆さん覚えておきましょう。
 zzzです。

 さて、今度は配列の中からいくつかの要素を引っ張りだして、何か作業がしたいとします。しかも考えられるすべての要素を抽出するとします。まさに組み合わせの話ですね。

 そしてこれが予想外に難しかったです……。あまりよいアルゴリズムを思いつけませんでした。
 
 簡単のために、要素の数が5個の配列から、2個の要素を抽出したいと考えます。どういう意味かと言うとこんな感じです。

combination5

 グループとして選ぶので、2つの配列番号を1つと見て選んでいます。
 こうしてみるとかなり簡単に見えるのですが、実際は同一視する配列が可変で結構なややこしかったです。特にもとに戻した後の挙動が困難でした。
 詳しくいうほど上手くやっていないので、とりあえず出来た光景をどうぞ。

combination5

 あとはこれで終わりです。配列の要素を抽出せずとも、配列の番号さえ取得できれば問題ありません。
 アルゴリズムに関して気になる方は追記にて書きます。

... 続きを読む
 組み合わせ、Combinationの計算が必須になったため、その計算をC言語を用いてやりたいと思います。ソースコードが短いので、紹介できると思いました。

 さて、計算は簡単にできるのですが、うまくやらないとちょっとまずいことになります。
 たとえばよく知られている公式で
combination
 という式が成立します。よってあとは階乗を定義すれば組み合わせは求めることができます。階乗はとても簡単に実装できます。以下がソースです。

unsigned long Factorial(int k)
{
    unsigned long i = 1;
    for(int count = 2; count <= k; ++count) i *= count;
    return i;
}
 階乗が出来れば組み合わせも簡単です。 上の公式を用いれば組み合わせが求まります。以下がソースです。

unsigned long Combination(int n, int k)
{
    return Factorial(n) / Factorial(k) / Factorial(n - k);
}

combination2

 これは完璧ですね。Combination(10, 7) = 120は正しい結果です。

 しかしこれには実は重大な落とし穴があります。どういうことかというと

combination3

 こういうことです。Combination(15, 7) = 9となっています。これは明らかにおかしいです。
 もうちょっと実験してみると、Combination(13, 3)は計算できないのですが、Combination(12, 5)などは正しい結果がでます。これは一体何故でしょうか。

 何がおかしいのかというと、表現できる数値の限界に問題があります。
 PCによって違いますが、32bitPCの場合、int型やlong型は0~4294967295の値しか代入することが出来ません。そして階乗はとてつもなく値が大きくなるのが速いので、平然とこの値を上回る値をたたき出します。どんな感じかというと

1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600

 こんな感じです。非常に大きくなるのが速いです。
 さて、先ほどのプログラムで13!を求めましょう。大体こうなります。

13! = 1932053504

 実はこの値は嘘です。実際に電卓などを用いて12!×13を行えばわかります。

13! = 6227020800

 となります。6227020800 > 4294967295 なので、unsigned long型で表現できる数値の最大を超えてしまっています。Combination(13, 5)がきちんと計算しなかったのはこのせいです。先に階乗を計算するので、ちゃんとした値にならないのです。

 ということでどうすればいいのでしょうか。
 結論としては、上の公式を使わずにいきます。こっちを用いたほうがもう少し有効に計算できます。
Combination4
 Pは順列です。さて、これでさっきよりはマシにはなっていますが、順列もとても速く値が大きくなるので、もう少し考えます。
 順列の計算を先にするから桁が大きくなってしまうのです。だから、順列を計算する前に割り算を実行してやれば桁の増加を抑えることが出来ます。
 ということで、割り算を順々に実行するプログラムがこちらです。先ほどよりもかなり長めになっています。事前に#include<list>が必須で、cppファイルでないと動かないでしょう。
unsigned long Combination(int n,int r)
{
    unsigned long i = 1;
    int k = r > n - r ? n - r : r, count;
    if(k < 0) return 0;
    std::list<int> list;
    std::list<int>::iterator it;
    for(count = 2; count <= k; ++count) list.push_back(count);
    for(count = n; count > n - k; --count)
    {
        i *= count;
        for(it = list.begin(); it != list.end(); )
        {
            if(!(i % *it))
            {
                i /= *it;
                it = list.erase(it);
            }
            else ++it;
        }
    }
    return i;
}

 これで先ほど間違った値が出ていたCombination(15, 7)を計算してやると

combination4

 きちんと正しい結果がでました。

 ここまでやりましたが、結局大きな桁を代入すると桁あふれしてしまいます。Combination(34, 17)あたりとなるとすでに値がおかしくなります。が正確な値がそもそも2333606220とかなりunsigned longの最大値に近いため、仕方がないといえば仕方がありません。
 もっと大きな値を出したいという場合には、もはやunsigned longなどではなく、多倍長整数を定義するのが自然でしょう。がそれは筆者の力量を大きく超えるため、組み合わせの解説は以上にしたいと思います。ありがとうございました。

 もっと良い方法があるという方や、バグを発見された方はご一報をください。喜びます。

 追記:もっと効率の良い方法がありました。掘木様に感謝。
 順列、P(n, k)がk!で割り切れることを利用します。一番下の公式からこれは自明です。 ここから次のプログラムで十分であります。

unsigned long Combination(int n,int r)

    unsigned long i = 1; 
    int k = r > n - r ? n - r : r, count; 
    if(k < 0) return 0; 
    for(count = 1; count <= k; ++count) 
    { 
        i *= n - count + 1;
        i /= count;
    }
    return i;
}
2012.05.08 まとも
 やっとまともなものを作りました。いや、ただ3D空間上に浮かぶ平面を定義しただけなんですけど。

directx5

 わりとまともなものができた?ような気がします。
2012.05.06 原因不明
zzzです。

DirectXのZバッファが有効にならない……orz
 原因不明すぎてなける。とりあえず対処療法的に大丈夫なようには出来たけど、根本解決になっていない……。
 とりあえずエフェクトでZバッファを有効にしてやらせてるんだけど、前後関係がきっちりしない。

 画像はプログラム起動時。

directx3

 これは前後関係がメチャクチャになっている。そしてこのプログラムに、エフェクト生成時にデバイスのReset関数を呼ぶとこうなる。理想はプログラム起動時からこうなってほしい。

directx4

 これは前後関係がちゃんと判断できている。

 うう、何がおかしいのだろうか……。エフェクト生成時に常にReset関数を呼ばないとダメなのだろうか……。