登場人物の一般化 A to Z(3)

 P1P2は二つのC1P2に分解できる。D1D2D3は三つのC1D2D3に分解できる。

 この分解を「正規化」と呼んでいる。もちろん俺の造語だ。

 P1P2はどちらかが主人公になる。P1P2のキャラ定義を正確に書けば、自分が主人公の時相手はNPC、自分がNPCのとき相手は主人公、となる。自分がAのとき相手はBという形で、キャラ定義がキャラ数の二乗になる。

 こうなるとジャンプ可能かどうかや、分岐がキャラを尽くしているかどうかのチェックルーチンも二乗の処理になる。実際はビット演算ができるのでO(N)の処理だが、これはもったいない。

 自分は誰、相手は誰、という形で固定できるようにすれば、O(1)の処理に出来る。C1P2やC1D2D3ならばO(1)に出来る。また、自分を主人公に固定することでいくらか分かりやすくなる。

class 顔にUnkoを投げつける : P1P2Episode<顔にUnkoを投げつける>
{
  public 顔にUnkoを投げつける()
  {
    Start.Set(
      Normalize(投げつける側.Start, 投げつけられる側.Start)
    );
  }

  class 投げつける側 : C1P2Episode<投げつける側>
  {
    public 投げつける側()
    {
      Start.Set(
        JibunText("ウンコを喰らえ!!"),
        If(delegate{ //ウンコを避けるかどうかのアルゴリズム },
          TrueBlock(
            AiteText(
              CS(Yamada,"そんなウンコくらわんでゴンス!"),
              CS(Tendo,@"
手に持った排泄物、目線の動き…@
あなたの狙いは見え見えよ。そんな排泄物、私が喰らうと思って!?")
            ),
            Base("ウンコは避けられてしまった!!")
          ),
          FalseBlock(
            Base("ウンコが顔に当たった!!"),
            AiteText(
              CS(Yamada,@"
め、目が見えないでゴンス!!
猛烈な異臭がするでゴンス!!"),
              C(Tendo,
                AiteText(@"
私の顔に排泄物を投げつけるなんて!!
どうなるかわかっているの!?"),
                JibunText("さあ?&教えてもらいたいね。"),
                AiteText("演歌界の総力を結集して、あなたを潰すわ!!")
              )
            )
          )
        ))
    }
  }

  class 投げつけられる側 : C1P2Episode<投げつけられる側>
  {
    public 投げつけられる側()
    {
      Start.Set(
        AiteText(
          CS(Yamada, "おいどんのウンコを喰らうでゴンス!!"),
          CS(Tendo, "私の排泄物を味わいなさい!!")
        ),
        Select("ウンコを投げつけてきた!!", S("避ける",yokeru), S("避けない",yokenai)
      )
    }

    Act yokeru = new Act();
    Act yokenai = new Act();

    Construct Yokeru()
    {
      yokeru.Set(
        JibunText("そんなもの喰らうかよ!!"),
        Base("ウンコを避けた!!")
      )

      yokenai.Set(
        JibunText(@"
やったー!!
ウンコ大好き!!"),
        Base("時枝は思うさまウンコを味わった。")
      )
    }
  }
}