Skip to content

Commit

Permalink
refactor reporter for AI without space-taken info
Browse files Browse the repository at this point in the history
  • Loading branch information
IanDCarroll committed Jul 5, 2017
1 parent 61f3ad3 commit 65fd0cd
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 35 deletions.
21 changes: 8 additions & 13 deletions lib/ai/minimax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,30 @@

class Minimax
attr_reader :spaces
attr_accessor :recursion_depth
attr_accessor :depth

def initialize(board)
@const = GameConstants.new
@judge = Reporter.new
@board = board.dup
@spaces = @board.spaces
@recursion_depth = 0
@depth = 0
end

def choose #first available to validate integration
@board.available_spaces[0]
end

def optimum_choice(spaces = @spaces, depth = @depth, choices = {})
p @judge.report({board: spaces})
if @judge.report({board: spaces}) == @const.draw then return 0 end
end

def available_spaces
@board.available_spaces
end

# recursion dependent ==v









def appropriate_player
@recursion_depth.odd? ? @const.players[1] : @const.players[0]
@depth.odd? ? @const.players[1] : @const.players[0]
end
end
18 changes: 10 additions & 8 deletions lib/reporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,34 @@ def initialize
end

def report(status)
if win?(status[:board])
return @const.winner(status[:board][status[:space]])
winning_player = check_for_win(status[:board])
if winning_player
return @const.winner(winning_player)
elsif not empty_spaces?(status[:board])
return @const.draw
end
report_move(status)
end

def report_move(status)
if status[:space].nil? then return nil end
[ status[:board][status[:space]], status[:space] ]
end

def win?(board)
def check_for_win(board)
@const.winning_sets.each do |winning_set|
if winning_set?(board, winning_set)
return true
end
winning_mark = winning_set(board, winning_set)
if winning_mark then return winning_mark end
end
false
end

def winning_set?(board, winning_set)
def winning_set(board, winning_set)
win = []
winning_set.each { |space| win << board[space] }
unless win.uniq[0].nil? || win.uniq[0].instance_of?(Integer)
win.uniq.length == 1
if win.uniq.length == 1
return win.uniq.first end
end
end

Expand Down
36 changes: 22 additions & 14 deletions spec/ai/minimax_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,53 @@



describe 'Minimax recursion_counter' do
context 'when recursion_counter has not been called' do
describe 'Minimax depth' do
context 'when depth has not been called' do
Given(:minimax) { Minimax.new(Board.new) }
Then { 0 == minimax.recursion_depth }
Then { 0 == minimax.depth }
end

context 'when called to track a deeper recursion' do
Given(:minimax) { Minimax.new(Board.new) }
When { minimax.recursion_depth += 1 }
Then { 1 == minimax.recursion_depth }
When { minimax.depth += 1 }
Then { 1 == minimax.depth }
end

context 'when called to track a surfacing recursion' do
Given(:minimax) { Minimax.new(Board.new) }
When { minimax.recursion_depth += 1
minimax.recursion_depth -= 1 }
Then { 0 == minimax.recursion_depth }
Given { minimax.depth += 1 }
When { minimax.depth -= 1 }
Then { 0 == minimax.depth }
end
end

describe 'Minimax appropriate_player' do
context 'when recursion_depth is at the root level' do
context 'when depth is at the root level' do
Given(:const) { GameConstants.new }
Given(:minimax) { Minimax.new(Board.new) }
When { minimax.recursion_depth += 1 }
When { minimax.depth += 1 }
Then { const.players[1] = minimax.appropriate_player }
end

context 'when recurstion_depth is an even number' do
Given(:const) { GameConstants.new }
Given(:minimax) { Minimax.new(Board.new) }
When { minimax.recursion_depth += 1
minimax.recursion_depth += 1 }
When { minimax.depth += 1
minimax.depth += 1 }
Then { const.players[0] = minimax.appropriate_player }
end
end



describe "Minimax optimum_choice" do
context 'when the method can be called' do
Given(:board) { Board.new }
Given(:minimax) { Minimax.new(board) }
When {
board.mark(0, "X")
}
Then { nil == minimax.optimum_choice }
end
end

#describe 'Minimax choose' do
# context 'when 7 is the only square left' do
Expand Down
44 changes: 44 additions & 0 deletions spec/reporter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,48 @@
When(:action) { subject.report(status) }
Then { const.winner(status[:board][status[:space]]) == action }
end

context 'when reporter is asked to report non-win without space' do
Given(:board) { [nil,nil,"X",
nil,nil,nil,
nil,nil,nil] }
Given(:status) { { board: board } }
Given(:subject) { Reporter.new }
When(:action) { subject.report(status) }
Then { nil == action }
end

context 'when reporter is asked to report an X win without space' do
Given(:const) { GameConstants.new }
Given(:board) { ["X","X","X",
nil,nil,nil,
nil,"O","O"] }
Given(:status) { { board: board } }
Given(:subject) { Reporter.new }
When(:action) { subject.report(status) }
Then { const.winner(const.players[0]) == action }
end

context 'when reporter is asked to report an O win without space' do
Given(:const) { GameConstants.new }
Given(:board) { ["X","X",nil,
nil,"X",nil,
"O","O","O"] }
Given(:status) { { board: board } }
Given(:subject) { Reporter.new }
When(:action) { subject.report(status) }
Then { const.winner(const.players[1]) == action }
end

context 'when reporter is asked to report a draw without space' do
Given(:const) { GameConstants.new }
Given(:board) { ["X","X","O",
"O","X","X",
"X","O","O"] }
Given(:status) { { board: board } }
Given(:subject) { Reporter.new }
When(:action) { subject.report(status) }
Then { const.draw == action }
end

end

0 comments on commit 65fd0cd

Please sign in to comment.