私の小さなサッカー ゲームの AI コードは、基本的に次のように機能します。ピッチの現在の状況を説明する事実を導き出す関数があります。
deriveFacts :: GameState -> [Fact]
... 事実は次のようになります。
data Fact =
FactCanIntercept ObjId ObjId
| FactBestPosition Team Spot Spot
| FactKickOff
| FactBallCarrier ObjId
| FactBestShootingVector Velocity3
| FactBestPassingVector Velocity3
| ...
...そして、一様に次のように見えるルールがあります。
rule_shoot facts = do
FactBallCarrier ballCarrier <- checkBallCarrier facts
FactBestShootingVector goalVector <- checkBestShootingVector facts
return [message (ballCarrier, shoot goalVector)]
そして、すべてのルールを実行し、結果のメッセージを収集するルール エンジンがあります。
これまでのところ問題なく、非常にうまく機能しています。このアプローチでは、すべてのファクトに対して次のような「アクセサ」関数が必要です。
checkBestShootingVector :: [Fact] -> Maybe Fact
checkBestShootingVector facts =
listToMaybe [e | e@(FactBestShootingVector {}) <- facts]
このアプローチは、多くの見苦しいボイラープレート コードにつながります。私の質問: これらのアクセサー関数を手動で作成する必要をなくすエレガントなソリューションはありますか?