Logo for Tick5 Game

What's new
sf.net page

SourceForge.net Logo

Image of Lua Logo

Image for wxWidgets Logo

7. Make it less deterministic

Now, our program is able to attack and defend itself as well. However, the moves are deterministic, which makes it less fun to play with. In this section, we'll make the program less deterministic.

Let's open boora-0.6.wz with a text editor and save it as boora-0.7.wz.

Modify function makemove() of AI class to accommodate the newly-added function exploringmove(). (Listing 7-1)

   -- a method that makes a move
local function makemove( ai, board )
if board:isempty() then
return fixedmove()

local x, y, color = board:lastmove()
hotspots:log( x, y )

evalmoves( board )
if winning() then
x, y = greedymove()
elseif threatening( board, x, y ) then
x, y = defend( board, x, y )
x, y = exploringmove() greedymove()

hotspots:log( x, y )

return x, y

Listing 7-1

Instead of always choosing the move that has the biggest value, function
exploringmove() randomly picks up a move among those that have top values. (Listing 7-2) The for-loop counts the number of moves which have top values. It compares the values of moves with the biggest, and chooses these whose the relative difference is less than delta.  Variable delta takes values between 0 and 1 and determines the randomness of the program: the bigger the value, the less deterministic and the weaker the program.

   -- randomly pick up a move among those that have top values 
local function exploringmove()
assert( table.getn( movelist ) >= 1 )

local total = table.getn( movelist )
local valmax = movelist[1].val

-- count moves that have top values
local topmoves = 0
for i = 2, total, 1 do
if (valmax - movelist[i].val)/valmax > delta then
topmoves = i

-- randomly pick up one
local index = 1
if topmoves >= 2 then
index = math.random( 1, topmoves )

return hotspots:get( movelist[index].idx )

Listing 7-2

delta  as a data member and initialize it in initDelta(). (Listing 7-3)  Function initDelta() guarantees that delta gets a valid value.

-- AI class
local bound = nil
local hotspots = nil
local mystone = nil
local movelist = nil
local delta = nil

local function initDelta( delta )
local default = 0.5

if delta == nil then
return default
elseif delta < 0 or delta > 1 then
return default
return delta

Listing 7-3

Accordingly, modify initAI()to invoke initDelta() and set random number seed.

   local function initAI( board, d )
if bound == nil then
bound = board:dimension() - 1
hotspots = newHotspots( bound, 2 )
mystone = mycolor()
delta = initDelta( d )
math.randomseed( os.time() )

Listing 7-4

Modify function
newAI() in order to pass in a value to delta. (Listing 7-5)

   function newAI( board, delta )
initAI( board, delta )
return setmetatable( {}, metatbl )

Listing 7-5

Modify function
tick5think(). (Listing 7-5) We choose 0.15 for delta, because we want randomness but don't want the program too weak.

function tick5think( board )
AI = newAI( board, 0.15 )
return AI:makemove( board )

Listing 7-5

Play against the program. We notice that its moves are less deterministic. Let it play against predecessor boora-0.6.wz, it roughly has the same chance to win, no matter whether it plays black or white stone.