2011-08-26 14:25:10 +00:00
|
|
|
#!/usr/bin/ruby
|
|
|
|
|
2011-08-28 23:39:17 +00:00
|
|
|
EMPTY = 0
|
|
|
|
TEAM_1 = 1
|
|
|
|
TEAM_2 = 2
|
2011-08-26 21:55:45 +00:00
|
|
|
TEAM_1_MAN = ' w '
|
|
|
|
TEAM_1_KING = ' W '
|
|
|
|
TEAM_2_MAN = ' b '
|
|
|
|
TEAM_2_KING = ' B '
|
|
|
|
BOARD_EMPTY = ' _ '
|
|
|
|
BOARD_SIZE = 8
|
|
|
|
|
2011-08-26 14:25:10 +00:00
|
|
|
class Board
|
2011-09-07 04:59:31 +00:00
|
|
|
attr :stats, true
|
|
|
|
|
2011-08-26 14:25:10 +00:00
|
|
|
def initialize()
|
2011-08-26 21:55:45 +00:00
|
|
|
@board = Array.new(BOARD_SIZE) {|i| Array.new(BOARD_SIZE, BOARD_EMPTY)}
|
2011-09-05 16:44:19 +00:00
|
|
|
@stats = {TEAM_1 => {}, TEAM_2 => {}}
|
2011-08-28 23:39:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def setup()
|
2011-08-26 21:55:45 +00:00
|
|
|
0.step(BOARD_SIZE) {|i|
|
|
|
|
peice = (i < 3 ? TEAM_1_MAN : TEAM_2_MAN)
|
2011-09-07 04:59:31 +00:00
|
|
|
if [0,2,6].include? i
|
2011-08-26 21:55:45 +00:00
|
|
|
start = 1
|
2011-09-07 04:59:31 +00:00
|
|
|
elsif [1,5,7].include? i
|
2011-08-26 21:55:45 +00:00
|
|
|
start = 0
|
|
|
|
else
|
|
|
|
next
|
|
|
|
end
|
2011-08-28 23:39:17 +00:00
|
|
|
start.step(BOARD_SIZE-1,2) {|j|
|
2011-08-26 21:55:45 +00:00
|
|
|
@board[i][j] = peice
|
|
|
|
}
|
|
|
|
}
|
2011-09-05 16:44:19 +00:00
|
|
|
@stats[TEAM_1]['count'] = 12
|
|
|
|
@stats[TEAM_2]['count'] = 12
|
2011-08-26 14:25:10 +00:00
|
|
|
end
|
|
|
|
|
2011-08-28 23:39:17 +00:00
|
|
|
def set(x, y, thing)
|
|
|
|
@board[y][x] = thing
|
|
|
|
end
|
|
|
|
|
|
|
|
def get(x, y)
|
|
|
|
@board[y][x]
|
|
|
|
end
|
|
|
|
|
2011-08-26 15:26:55 +00:00
|
|
|
def to_s()
|
2011-08-26 21:55:45 +00:00
|
|
|
str = ' '
|
2011-08-28 23:39:17 +00:00
|
|
|
0.step(BOARD_SIZE-1) {|i|
|
2011-08-26 21:55:45 +00:00
|
|
|
str += ' ' + i.to_s + ' '
|
|
|
|
}
|
|
|
|
str += "\n"
|
|
|
|
i = 0;
|
|
|
|
@board.each {|row|
|
|
|
|
str += ('A'.ord + i).chr + ' '
|
|
|
|
i += 1
|
2011-08-26 15:26:55 +00:00
|
|
|
row.each {|cell|
|
|
|
|
str += cell
|
|
|
|
}
|
|
|
|
str += "\n"
|
|
|
|
}
|
2011-09-07 04:59:31 +00:00
|
|
|
str += 'TEAM_1: ' + @stats[TEAM_1]['count'].to_s + ' -- TEAM_2: ' + @stats[TEAM_2]['count'].to_s + "\n"
|
2011-08-26 15:26:55 +00:00
|
|
|
return str
|
2011-08-26 14:25:10 +00:00
|
|
|
end
|
2011-08-26 15:26:55 +00:00
|
|
|
|
2011-08-28 23:39:17 +00:00
|
|
|
def piece_team(piece)
|
|
|
|
if piece == TEAM_1_MAN or piece == TEAM_1_KING
|
|
|
|
return TEAM_1
|
|
|
|
elsif piece == TEAM_2_MAN or piece == TEAM_2_KING
|
|
|
|
return TEAM_2
|
|
|
|
else
|
|
|
|
return EMPTY
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def empty?(x, y)
|
|
|
|
return @board[y][x] == BOARD_EMPTY
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid_coords(x, y)
|
2011-09-07 04:59:31 +00:00
|
|
|
return (x >= 0 and x < BOARD_SIZE and y >= 0 and y < BOARD_SIZE)
|
2011-08-28 23:39:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def gen_moves(x, y, x_mod, y_mod)
|
|
|
|
moves = []
|
|
|
|
for xm in x_mod
|
|
|
|
new_x = x + xm
|
|
|
|
for ym in y_mod
|
|
|
|
new_y = y + ym
|
|
|
|
if valid_coords(new_x, new_y) and empty?(new_x, new_y)
|
|
|
|
moves += [[new_x, new_y]]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return moves
|
|
|
|
end
|
|
|
|
|
|
|
|
# function to chart path of jumps
|
|
|
|
# merging them together
|
|
|
|
# only returns full paths
|
|
|
|
#
|
|
|
|
# base case: no jumps avail, return path
|
|
|
|
# jumps avail: do all and merge and return
|
2011-09-11 19:39:14 +00:00
|
|
|
def gen_jumps(path, x, y, team, x_mod, y_mod, taken=[])
|
2011-08-28 23:39:17 +00:00
|
|
|
jumps = []
|
|
|
|
for xm in x_mod
|
|
|
|
new_x = x + xm
|
2011-09-05 16:44:19 +00:00
|
|
|
for ym in y_mod
|
2011-08-28 23:39:17 +00:00
|
|
|
new_y = y + ym
|
2011-09-11 19:39:14 +00:00
|
|
|
if valid_coords(new_x, new_y) and piece?(new_x, new_y) and !taken.include?([new_x, new_y]) and team != team(new_x, new_y)
|
|
|
|
taken.push([new_x, new_y])
|
2011-08-28 23:39:17 +00:00
|
|
|
final_x = new_x + xm
|
|
|
|
final_y = new_y + ym
|
|
|
|
if (valid_coords(final_x, final_y) and empty?(final_x, final_y))
|
2011-09-11 19:39:14 +00:00
|
|
|
jumps += gen_jumps(path + [[final_x, final_y]], final_x, final_y, team, x_mod, y_mod, taken)
|
2011-08-28 23:39:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if jumps == []
|
2011-09-05 16:44:19 +00:00
|
|
|
if path == []
|
|
|
|
return []
|
|
|
|
else
|
|
|
|
return [path]
|
|
|
|
end
|
2011-08-28 23:39:17 +00:00
|
|
|
else
|
|
|
|
return jumps
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def piece?(x, y)
|
2011-09-05 16:44:19 +00:00
|
|
|
return !empty?(x, y)
|
2011-08-28 23:39:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def team(x, y)
|
|
|
|
if piece?(x, y)
|
|
|
|
if @board[y][x] == TEAM_1_MAN or @board[y][x] == TEAM_1_KING
|
|
|
|
return TEAM_1
|
|
|
|
else
|
|
|
|
return TEAM_2
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return EMPTY
|
|
|
|
end
|
|
|
|
|
2011-09-07 04:59:31 +00:00
|
|
|
def opposite_team(team)
|
|
|
|
return (team == TEAM_1 ? TEAM_2 : TEAM_1)
|
|
|
|
end
|
|
|
|
|
2011-08-28 23:39:17 +00:00
|
|
|
def man?(x, y)
|
|
|
|
return (@board[y][x] == TEAM_1_MAN or @board[y][x] == TEAM_2_MAN)
|
|
|
|
end
|
|
|
|
|
|
|
|
def king?(x, y)
|
|
|
|
return (@board[y][x] == TEAM_1_KING or @board[y][x] == TEAM_2_KING)
|
|
|
|
end
|
|
|
|
|
2011-09-05 16:44:19 +00:00
|
|
|
def piece_valid_moves(x, y, team)
|
2011-08-28 23:39:17 +00:00
|
|
|
moves = []
|
|
|
|
if piece_team(@board[y][x]) == team
|
|
|
|
direction = [1]
|
|
|
|
if king?(x, y)
|
|
|
|
direction = [-1, 1]
|
|
|
|
elsif team == TEAM_2
|
|
|
|
direction = [-1]
|
|
|
|
end
|
|
|
|
|
|
|
|
moves = gen_moves(x, y, [-1,1], direction)
|
|
|
|
moves += gen_jumps([], x, y, team, [-1, 1], direction)
|
|
|
|
end
|
|
|
|
return moves
|
|
|
|
end
|
|
|
|
|
|
|
|
def dup()
|
|
|
|
b = Board.new
|
|
|
|
for x in 0..(BOARD_SIZE-1)
|
|
|
|
for y in 0..(BOARD_SIZE-1)
|
|
|
|
b.set(x, y, get(x, y))
|
|
|
|
end
|
|
|
|
end
|
2011-09-07 04:59:31 +00:00
|
|
|
b.stats[TEAM_1] = @stats[TEAM_1].dup
|
|
|
|
b.stats[TEAM_2] = @stats[TEAM_2].dup
|
2011-08-28 23:39:17 +00:00
|
|
|
return b
|
|
|
|
end
|
|
|
|
|
2011-09-07 04:59:31 +00:00
|
|
|
def between(c1, c2)
|
|
|
|
return [ c2[0] + (c1[0]-c2[0])/2, c2[1] + (c1[1]-c2[1])/2 ]
|
|
|
|
end
|
|
|
|
|
2011-09-07 06:05:55 +00:00
|
|
|
def move_piece(c1, c2)
|
|
|
|
piece = get(c1[0], c1[1])
|
|
|
|
set(c1[0], c1[1], BOARD_EMPTY)
|
|
|
|
set(c2[0], c2[1], piece)
|
|
|
|
if team(c2[0], c2[1]) == TEAM_1 and c2[1] == BOARD_SIZE-1
|
|
|
|
set(c2[0], c2[1], TEAM_1_KING)
|
|
|
|
elsif (team(c2[0], c2[1]) == TEAM_2 and c2[1] == 0)
|
|
|
|
set(c2[0], c2[1], TEAM_2_KING)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-09-07 04:59:31 +00:00
|
|
|
# doesnt validate
|
|
|
|
def do_move(x, y, move, team)
|
|
|
|
if move[0].is_a?(Array)
|
|
|
|
# jump
|
|
|
|
move.each { |jump|
|
|
|
|
enemy = between([x,y], jump)
|
|
|
|
set(enemy[0], enemy[1], BOARD_EMPTY)
|
|
|
|
@stats[opposite_team(team)]['count'] -= 1
|
2011-09-07 06:05:55 +00:00
|
|
|
move_piece([x,y], jump)
|
2011-09-07 04:59:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
# move
|
2011-09-07 06:05:55 +00:00
|
|
|
move_piece([x,y], move)
|
2011-09-07 04:59:31 +00:00
|
|
|
end
|
|
|
|
end
|
2011-09-05 16:44:19 +00:00
|
|
|
|
2011-09-07 04:59:31 +00:00
|
|
|
|
|
|
|
def gen_next_move_boards(team)
|
2011-09-05 16:44:19 +00:00
|
|
|
boards = []
|
|
|
|
for x in 0..(BOARD_SIZE-1)
|
|
|
|
for y in 0..(BOARD_SIZE-1)
|
2011-09-07 04:59:31 +00:00
|
|
|
if piece?(x, y) and team(x,y) == team
|
2011-09-05 16:44:19 +00:00
|
|
|
moves = piece_valid_moves(x, y, team(x, y))
|
|
|
|
moves.each { |move|
|
|
|
|
board = dup()
|
|
|
|
board.do_move(x, y, move, team(x, y))
|
2011-09-12 20:44:19 +00:00
|
|
|
boards.push( { "board" => board, "move" => move})
|
2011-09-05 16:44:19 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return boards
|
|
|
|
end
|
|
|
|
|
2011-09-11 19:39:14 +00:00
|
|
|
def score(team)
|
|
|
|
score = 0
|
|
|
|
score += @stats[team]['count']
|
|
|
|
score += 12 - @stats[opposite_team(team)]['count']
|
|
|
|
if @stats[opposite_team(team)]['count'] == 0
|
|
|
|
score += 12
|
|
|
|
elsif @stats[team]['count'] == 0
|
|
|
|
score -= 12
|
|
|
|
end
|
|
|
|
return score
|
|
|
|
end
|
|
|
|
|
2011-09-09 06:11:19 +00:00
|
|
|
def search(team)
|
2011-09-13 01:08:23 +00:00
|
|
|
search_do(team, 0, 10, 100.0, 0.0, "R", {TEAM_1 => -100, TEAM_2 => -100})
|
2011-09-09 06:11:19 +00:00
|
|
|
end
|
|
|
|
|
2011-09-13 01:08:23 +00:00
|
|
|
# team - current player this turn
|
|
|
|
# current depth - counting up to max_depth
|
|
|
|
# max_depth - when we should stop our search
|
|
|
|
# my_percent - the percent range this work covers
|
|
|
|
# done_percent - the percent of work already done
|
|
|
|
# maxs -
|
|
|
|
def search_do(team, current_depth, max_depth, my_percent, done_percent, maxs)
|
2011-09-11 19:39:14 +00:00
|
|
|
#puts location
|
2011-09-09 06:11:19 +00:00
|
|
|
if depth == 0
|
2011-09-11 19:39:14 +00:00
|
|
|
return score(team)
|
2011-09-09 06:11:19 +00:00
|
|
|
end
|
2011-09-07 04:59:31 +00:00
|
|
|
if @stats[TEAM_1]['count'] == 0
|
|
|
|
puts "TEAM_2 WON!"
|
2011-09-11 19:39:14 +00:00
|
|
|
return score(team)
|
2011-09-07 04:59:31 +00:00
|
|
|
elsif @stats[TEAM_2]['count'] == 0
|
|
|
|
puts "TEAM_1 WON!"
|
2011-09-11 19:39:14 +00:00
|
|
|
return score(team)
|
2011-09-07 04:59:31 +00:00
|
|
|
else
|
|
|
|
moves = gen_next_move_boards(team)
|
|
|
|
if moves == []
|
|
|
|
puts "NO MOVES AVAILABLE?"
|
2011-09-11 19:39:14 +00:00
|
|
|
return score(team)
|
2011-09-07 04:59:31 +00:00
|
|
|
else
|
2011-09-12 20:44:19 +00:00
|
|
|
jumps = moves.find_all { |item| item['move'][0].is_a?(Array)}
|
|
|
|
if jumps.length > 0
|
|
|
|
moves = jumps
|
|
|
|
end
|
2011-09-11 19:39:14 +00:00
|
|
|
done = 0.0
|
2011-09-09 21:57:35 +00:00
|
|
|
item_percent = percent/moves.length
|
2011-09-11 19:39:14 +00:00
|
|
|
|
|
|
|
for i in 0..moves.length-1 do
|
|
|
|
#moves.each { |move|
|
2011-09-12 20:44:19 +00:00
|
|
|
move = moves[i]['board']
|
2011-09-11 19:39:14 +00:00
|
|
|
#puts "SEARCH"
|
2011-09-12 20:44:19 +00:00
|
|
|
sub_score = move.search_do(opposite_team(team), depth -1, item_percent, last_percent+done, location + "." +i.to_s, maxs.dup )
|
2011-09-11 19:39:14 +00:00
|
|
|
done += item_percent
|
2011-09-13 01:08:23 +00:00
|
|
|
if done >= 0.01
|
2011-09-11 19:39:14 +00:00
|
|
|
last_percent += done;
|
2011-09-12 20:44:19 +00:00
|
|
|
puts "%.5f" % last_percent + "% depth: " + depth.to_s + " max: " + maxs.to_s
|
2011-09-11 19:39:14 +00:00
|
|
|
done = 0.0
|
|
|
|
end
|
|
|
|
#puts "Score: " + sub_score.to_s
|
2011-09-12 20:44:19 +00:00
|
|
|
if sub_score > maxs[team]
|
|
|
|
maxs[team] = sub_score
|
2011-09-09 06:11:19 +00:00
|
|
|
end
|
|
|
|
end
|
2011-09-12 20:44:19 +00:00
|
|
|
return maxs[team]
|
2011-09-07 04:59:31 +00:00
|
|
|
end
|
2011-09-11 19:39:14 +00:00
|
|
|
end
|
2011-09-07 04:59:31 +00:00
|
|
|
end
|
2011-09-13 01:08:23 +00:00
|
|
|
|
2011-08-26 14:25:10 +00:00
|
|
|
end
|
|
|
|
|