tonari note

オンラインゲームエンジニアの雑記

ひとりごと

C#で稀によくenumなりで状態を返してちょっとした処理をしたいときがあります。
たとえば簡単な例として、符号を調べる関数があるとして

enum Sign { Positive, Zero, Negative }
static Sign GetSign(int value)
{
    if (value > 0) return Sign.Positive;
    if (value < 0) return Sign.Negative;
    return Sign.Zero;
}
//===
var sign = GetSign(new Random().Next(-5, 5));
switch (sign)
{
    case Sign.Positive:
        何か良い事(); break; 
    case Sign.Negative:
        何か悪い事(); break;
    case Sign.Zero:
    default:
        break;
}

みたいな。
enum作るのも面倒だし、switch書くのも面倒だし、みたいな。

で、

new Random().Next(-5, 5)
    .Pattern(x => x > 0, x => 良い事())
    .Pattern(x => x < 0, x => 悪い事());

みたいに書きたいってなって作りました。


yKimisaki/ActionPattern · GitHub

上みたいな書き方もできるんですが、

enum Element { Fire, Water, Wind, None }

みたいな属性があって、火は水に弱いみたいなジャンケンがあるとします。
すると、それは

var getWeak = ActionPattern
    .Pattern(Element.Fire, x => Element.Water)
    .Pattern(Element.Water, x => Element.Wind)
    .Pattern(Element.Wind, x => Element.Fire)
    .Default(x => Element.None);

みたいに書くことができ、

var weak = Element.Fire.Match(getWeak)();

で取得できます。
このMatchの返り値はカリー化されたデリゲートで、実際の値はMatch()()で取得できます。
返り値がデリゲートなのは将来的に引数付でアレコレしたいからです。

ココからまだ未実装ですがたとえば

var getDamageRate = ActionPattern<Magic, Character>
    .Select(magic => magic.Element, character => character.Element)
    .Pattern((magicElem, charElem) =>
        // 魔法の属性が、キャラクターの属性の弱点だったら、2倍
        magicElem == charElem.Match(getWeak)(), x => 2f)
    .Pattern((magicElem, charElem) =>
        // 逆だったら、0.5倍
        charElem == magicElem.Match(getWeak)(), x => 0.5f)
    .Default(x => 1f);

// ダメージ計算で上のレートを掛ける
damage *= usingMagic.Match(getDamageRate)(enemy);

みたいなことができたらなぁ、など。