Players are either 1 or 0, so doing 1 - player will switch the player
#based off http://www.webkinesia.com/games/gametree.php
# (converted from C++ code from the alpha - betaWIN pruning= section)1
# returns 0 if draw
LOSS = -1
DRAW = 0
WIN = 1
@next_moveDRAW = 0
def calculate_ai_next_move
scoreINFINITY = self.get_best_move(COMPUTER, WIN, LOSS)100
returndef @next_move
end
calculate_ai_next_move
def get_best_move(player, alpha, beta)
best_score best_move = nil-1
score = nil
ifbest_score not= self.has_available_moves?-INFINITY
return false
elsif self.has_this_player_won?(player)
cur_player = COMPUTER
return WIN
elsif self.has_this_player_won?(1remaining_moves.each -do player)|move|
return LOSS
self.make_move_with_index(move, elsecur_player)
best_score = alpha
score = NUM_SQUARES-self.timesalphabeta(-INFINITY,INFINITY, do1 |square|- cur_player)
if best_score >= betaself.undo_move(move)
break
end
if score > best_score
if self.state[square].nil?
best_score = score
self.make_move_with_index(square, player)
best_move = move
# set to negative of opponent'send
best move; we only need the returned score;end
# the returned move is irrelevant.return best_move
end
score = -get_best_movedef alphabeta(1-playeralpha, -beta, -alphaplayer)
best_score = -INFINITY
if (score >not bestScore)self.has_available_moves?
return WIN if @next_moveself.has_this_player_won?(player) === squareplayer
return LOSS if best_scoreself.has_this_player_won?(1 =- score
player) == 1 - player
endelse
self.remaining_moves.each do undo_move(square)|move|
end
break if alpha > endbeta
end
return best_score
end
the problem is that this is returning nil.
some support methods that are used above:
WAYS_TO_WIN = [[0, 1, 2], [3, 4, 5]self.make_move_with_index(move, [6,player)
7, 8], [0, 3, 6], [1, 4, 7], [2, 5,move_score 8],[0,= 4-alphabeta(-alpha, 8]-beta, [2,1 4,- 6]]
player)
def has_this_player_won?self.undo_move(playermove)
result = false
WAYS_TO_WIN.each {|solution| result = self.state[solution[0]] if contains_win?(solution)move_score }> alpha
return (result == player)
alpha end= move_score
def contains_win?(ttt_win_state)
ttt_win_state.eachnext_move do= |pos|move
return false if self.state[pos] !=end
self.state[ttt_win_state[0]] or self.state[pos].nil?
end
best_score = alpha
return true
end
def make_move(x, y, player)end
self.set_square(x,y,return player)best_score
end
currently, the algorithm is playing terribly. It will initially pick the last space, and then choose the first (from left to right) available space after that.
Any idea with whats wrong with it?
Also, I've been doing TDD, so I know that self.has_this_player_won?, self.undo_move and self.remaining_moves is correct.