• Subject: Re: Tools for high level game AI
• From: Steven Johnson <temujin98007@...>
• Date: Fri, 5 Sep 2008 19:34:25 -0700 (PDT)

```Hi.

>    I'm wondering if anyone can point me towards tools or sample code for
> doing things like fuzzy logic, Bayesian reasoning or hierarchical task
> networks in Lua. Although I get the feeling that HTN just requires a
> language designed for it. I'm just trying to do a survey of what tools might
> exist that might do a good job at making decisions inside of my AI, right
> now my if-then-else clauses aren't quite going to cut it.

I don't have anything for your examples, but if you have any algorithms with relatively benign / absent / reversible side effects, I do have some basic nondeterminism code. If you don't mind Lisp, chapter 22 of this book has a good summary (#23 and 24 may be useful too):

http://paulgraham.com/onlisptext.html

A while back, for non-AI reasons, I made some resettable coroutine functionality. Once I had that, I was able to implement a limited version of the choice operator.[1]

So far, this has been mostly an interesting experiment, but the idea for my company's next game calls for a lot of character AI, and I'm thinking at the highest level it would be something like "try out tactics (virtually) until we find something that works well", where not working well would be a fail.

The Choose function is in the beginning of the attached CoroutineOps.lua and the rest is in Coroutine.lua. (These files are as is, so there are some undefined but hopefully obvious utility functions too.)

Here's a quick example of the parlor trick with sum 7 (Fig. 22.3 in the book):

local Choose = coroutineops.Choose
local Reset = coroutine_ex.Reset

local N1, N2

N1 = Choose({ 0, 1, 2, 3, 4, 5 }, function(n1)
N2 = Choose({ 0, 1, 2, 3, 4, 5 }, function(n2)
if n1 + n2 ~= 7 then
Reset()
end
end)
end)

printf("%i, %i", N1, N2) -- 2, 5

Another more hypothetical example:

local function JudgeShot (weapon, target)

-- Long block of judgment code

Reset()
end

return shot_stuff
end

Choose(ListOfWeapons, function(weapon)
Choose(ListOfTargets, function(target)
local stuff = JudgeShot(weapon, target)

FireAtTarget(weapon, target, stuff)
end)
end, function()

-- No good shots: Failure logic

end)

Anyhow, it's one way of recasting the if-then-else. :)

- Steve

[1] - For general orthogonality with some of my own code, like the other algorithms in CoroutineOps, I'll probably have to patch some of those yield calls, say with a resume and immediate reyield, since Reset itself uses yield and could get snagged on those. If there's a way to account for this with arbitary code that can yield, I haven't thought of it. :(

Caveat #2: The on_reset logic may cause troubles if you're not using CoCo. Not sure about that, though.

```

Attachment: Coroutine.lua
Description: Binary data

Attachment: CoroutineOps.lua
Description: Binary data