Reputation: 4233
The AI code for my little soccer game basically works like this: There is a function that derives facts that describe the current situation on the pitch:
deriveFacts :: GameState -> [Fact]
... where the facts look kind of like this:
data Fact =
FactCanIntercept ObjId ObjId
| FactBestPosition Team Spot Spot
| FactKickOff
| FactBallCarrier ObjId
| FactBestShootingVector Velocity3
| FactBestPassingVector Velocity3
| ...
... and there are rules that look uniformly like this:
rule_shoot facts = do
FactBallCarrier ballCarrier <- checkBallCarrier facts
FactBestShootingVector goalVector <- checkBestShootingVector facts
return [message (ballCarrier, shoot goalVector)]
And then there is a rule engine that runs all the rules and gathers up the resulting messages.
That's fine so far and works quite nicely. What's kind of annoying, though: In this approach, I need an "accessor" function like this for every Fact:
checkBestShootingVector :: [Fact] -> Maybe Fact
checkBestShootingVector facts =
listToMaybe [e | e@(FactBestShootingVector {}) <- facts]
This approach leads to a lot of ugly boilerplate code. My question: Is there an elegant solution that removes the need for creating these accessor functions by hand?
Upvotes: 3
Views: 202
Reputation: 32455
You could refactor most of your Fact data as a record object
data FactRec = FR {
canIntercept :: [(ObjId,ObjId)], -- use lists for things you previously had multiple times
factBestPosition :: [(Team,Spot,Spot)], -- not sure about this one, maybe two entries not one list
kickOff :: Bool,
ballCarrier :: ObjID,
factBestShootingVector :: Velocity3,
factBestPassingVector :: Velocity3,
.....
}
Which gives you bulti-in accessor functions
if kickOff fr then something else somethingelse
So you wouldn't need to write all the check functions, but instead do
rule_shoot facts = message (ballCarrier facts, shoot $ goalVector facts)
If there are facts that genuinely might or might not be there, they could be of type Maybe something, and if there are facts that can be there an arbitrary number of times, they can be lists.
Upvotes: 4