class Scene_Riversi < Scene_MenuBase alias tako1set_init set_init def set_init tako1set_init @pre_end = false @point_value_list = [] @ai_board = [] @node_list = [] @current_node_id = 0 @ai_complete_start = @current_person.ai_complete_start @ai_eval_depth_max = @current_person.pre_eval_depth @eval_fazzy = @current_person.eval_fazzy @new_puttables = [] @opening_orientation = -1 @ai_progress = 0 @inedata = [] @edata0 = [] @edata1 = [] @edata = [] @eboards = [] @eboards0 = [] @ecomps = [] @temp_puttables = [] @e_array = (0..7) @corners = [0,7,56,63] 8.times do |i| @ecomps[i] = Ecomp.new() end @temp_confirms = [] @confirms = [] @spiral_id = [0,1,2,3,4,5,6,7,15,23,31,39,47,55,63,62,61,60,59,58,57, 56,48,40,32,24,16,8,9,10,11,12,13,14,22,30,38,46,54, 53,52,51,50,49,41,33,25,17,18,19,20,21,29,37,45,44,43,42,34,26,27,28,36,35] @rspiral_id = [63,55,47,39,31,23,15,7,6,5,4,3,2,1,0,8,16,24,32,40,48,56,57,58,59,60, 61,62,54,46,38,30,22,14,13,12,11,10,9,17,25,33,41,49,50,51,52,53,45,37, 29,21,20,19,18,26,34,42,43,44,36,28,27,35] end #● ai_boardの作成 def make_ai_board2(x , y ,color , board = @board) aiboard = board.dup set_board_data(x, y , color , aiboard ) reverse_stone(x , y , color , aiboard ) return aiboard end #● ai_boardの作成 def make_ai_board(pt ,color , board = @board) x = pt % BOARDWIDTH y = pt / BOARDWIDTH aiboard = board.dup set_board_data(x, y , color , aiboard ) reverse_stone(x , y , color , aiboard ) return aiboard end #●次の色 def next_color(color ,board) if puttable_cell_exist?(op_color(color), board) return op_color(color) elsif puttable_cell_exist?(color, board) return color else return 0 end end #● CPUの優先度配列の作成 def make_cpu_ai #~ set_ai_init last_flag = false make_eboards(@board,@eboards0) complete_array_temp = [] if number_empty(@board) < @ai_complete_start last_flag = true end for i in 0..@ai_puttable.size - 1 put_value = 10000000000000 ix = @ai_puttable[i] % BOARDWIDTH iy = @ai_puttable[i] / BOARDWIDTH @ai_board.clear @ai_board = make_ai_board2(ix , iy, cpu_color) if last_flag if @ai_puttable[i] == @comp_calc_pt put_value = 1000000000 else put_value = 1 end elsif number_empty(@board) == 64 - 4 put_value = 1 elsif only_puttable_lost_corner?(cpu_color,@board) put_value = apply_value_functions_at_pre_last(@ai_puttable[i],put_value) elsif (@opening_orientation >= 0 && check_opening_tree) put_value = put_opening_tree(@ai_puttable[i]) else put_value = apply_value_functions(@ai_puttable[i],put_value) end @cpu_ai.push(put_value) end end def apply_value_functions(p,value) @current_person.ai_functions.each do |fcode| value = set_function_list(fcode,p,value) end return value end def set_function_list(fcode,p,value) case (fcode) when "value_x" return value_x(p,value) when "value_c" return value_c(p,value) when "value_eval_degree" return value_eval_degree(p,value) when "value_prevent_corner_put" return value_prevent_corner_put(p,value) when "value_corner_put" return value_corner_put(p,value) when "value_edge" return value_edge(p,value) when "value_less_number" return value_less_number(p,value) end p "No Function", fcode return value end def apply_value_functions_at_pre_last(p,value) @current_person.pre_last_functions.each do |fcode| value = set_function_list_at_pre_last(fcode,p,value) end return value end def set_function_list_at_pre_last(fcode,p,value) case (fcode) when "value_x" return value_x(p,value) when "value_c" return value_c(p,value) when "value_eval_degree" return value_eval_degree(p,value) when "value_prevent_corner_put" return value_prevent_corner_put(p,value) when "value_corner_put" return value_corner_put(p,value) when "value_edge" return value_edge(p,value) when "value_less_number" return value_less_number(p,value) when "put_in_pre_last" return put_in_pre_last(p,value) end p "No Function" return value end def value_x(p,value) return value unless is_x(p) if is_x_corner_empty(p) return value / 300000000 end return value end def is_x_corner_empty(pt) corner = near_corner(pt) eboard = @eboards0[corner] return is_x(pt) && eboard[0] == 0 end def value_c(p,value) return value unless is_c(p) px = p % BOARDWIDTH py = p / BOARDWIDTH edge = get_near_edge(px,py) eboard = @eboards0[edge] edata0 = get_edge_data0(player_color,eboard) coord = trans_coord_global_into_edge(edge,[px,py]) if (edata0 == 0) return value / 20000000 end if (coord[0] != 1) edge = get_reciprocal_edge(edge) eboard = @eboards0[edge] edata0 = get_edge_data0(player_color,eboard) end if edata0 / 10000 == 2 return value / 10000000 end if edata0 == 1000 || edata0 == 10000 || edata0 == 100 return value / 1000000 end if edata0 == 10111110 return value * 100000 end if edata0 / 100000 == 101 return value * 3 end if eboard[0] == 1 return value end return value end def value_corner_put(p,value) if (is_corner(p)) px = p % BOARDWIDTH py = p / BOARDWIDTH corner = near_corner(p) edges = get_edges_include_corner(corner) eboardds = [@eboards0[edges[0]],@eboards0[edges[1]]] 2.times do |i| aiboard2 = make_ai_board(0,cpu_color,eboardds[i]) if reverse_stone_puttable?(1, 0, player_color,aiboard2) aiboard3 = make_ai_board2(1,0,player_color,aiboard2) if reverse_stone_puttable?(7, 0, player_color,aiboard3) return value / 800 end end end return value * 100000000 end return value; end def value_prevent_corner_put(p,value) corners = get_corners_not_avoid_corner_put(cpu_color,@board) aiboard2 = make_ai_board(p,cpu_color,@board) corners2 = get_corners_not_avoid_corner_put(cpu_color,aiboard2) if only_puttable_lost_corner?(cpu_color,@board) if (corners.length > corners2.length) return value * 2 elsif (corners.length == corners2.length) return value end end if corners2.length > 0 return value / 30000000 end return value end def get_corners_not_avoid_corner_put(col,board) make_eboards(board) return [0,1,2,3].select{|corner| reverse_stone_puttable?(0, 0, op_color(col),@eboards[corner])} end def value_edge(p,value) 8.times do |edge| aiboard2 = make_ai_board(p,cpu_color, @board) make_eboards(aiboard2) eboard = @eboards[edge] value = value_edge_each(eboard,value); end return value; end def value_edge_each(eboard,value) if check_edge_form(cpu_color,eboard) == 14 return value / 800 elsif check_edge_form(cpu_color,eboard) == 15 return value / 700 elsif check_edge_form(cpu_color,eboard) == 16 return value / 700 elsif check_edge_form(cpu_color,eboard) == 1016 return value * 30 elsif check_edge_form(cpu_color,eboard) == 1020 return value * 40 elsif check_edge_form(cpu_color,eboard) == 1021 return value * 400 end return value end def check_edge_form(col,eboard) opcol = op_color(col) ecomp = get_edge_components0(eboard) ecomps_st = ecomp[1] edata0 = get_edge_data0(col,eboard) if compare_array(ecomp[0],[0,col,0,col,0] ) d_ecomps_st = ecomps_st[3] - ecomps_st[2] if (ecomps_st[1] == 1 && d_ecomps_st == 1 ) return 14 end end if compare_array(ecomp[0],[0,col,0,opcol,col,0] ) d_ecomps_st = ecomps_st[3] - ecomps_st[2] if (ecomps_st[1] == 1 && d_ecomps_st == 1 ) return 15 end end if compare_array(ecomp[0],[0,col,opcol,0,col,0] ) d_ecomps_st = ecomps_st[4] - ecomps_st[3] if (ecomps_st[1] == 1 && d_ecomps_st == 1 ) return 16 end end if compare_array(ecomp[0],[0,opcol,col,opcol,0] ) d_ecomps_st = ecomps_st[3] - ecomps_st[2] if (ecomps_st[1] == 1 && d_ecomps_st == 1 ) return 1016 end end if edata0 == 2000100 return 1020 elsif edata0 == 2010100 return 1021 end return 0 end def value_less_number(pt,value) px = pt % BOARDWIDTH py = pt / BOARDWIDTH stones = get_reverse_stones(px , py , cpu_color) l = stones.length return value / (l + 1) ** 2 end #● ひっくり返しの実行 def get_reverse_stones(x , y , color , board = @board) array = [] (-1..1).each do |i| (-1..1).each do |j| if reverse_stone_exist_d?(x , y , i, j, color , board) array = array.concat(get_reverse_stones_d(x , y , i, j, color , board)) end end end return array end #● ひっくり返しの実行 方向別 def get_reverse_stones_d(x , y , dx ,dy , color , board = @board) array = [] i = 1 # 逆石でなくなるまでひっくり返す while get_board_data2(x + dx * i , y + dy * i , board ) == op_color(color) array.push(x + dx * i + (y + dy * i) * BOARDWIDTH) i += 1 end return array end def is_corner(pt) pt == 0 || pt == 7 || pt == 56 || pt == 63 end def is_x(pt) return (pt == 9 || pt == 14 || pt == 49 || pt == 54) end def is_c(pt) return (pt == 1 || pt == 6 || pt == 8 || pt == 15 || pt == 48 || pt == 55 || pt == 57 || pt == 62) end def is_around_corner(pt) return is_corner(pt) || is_x(pt) || is_c(pt) end def ai_thinking_complete_calc(count_max) if (@current_node_id == 0) init_node_list(@board) end comp_calc_pre = complete_calc(count_max) if (comp_calc_pre >= 0) @ai_progress = 20 end return comp_calc_pre end def ai_thinking_calc_eval(count_max) if (@current_node_id == 0) init_node_eval_list(@board) end calc_eval_pre = calc_eval(count_max) if (calc_eval_pre) @ai_progress = 20 end return end def ai_pre_thinking if @ai_progress == 0 prepare_ai_thinking elsif @ai_progress == 10 cpu_pre_thinking else init_after_pre_thinking end end def cpu_pre_thinking if number_empty(@board) < @ai_complete_start @comp_calc_pt = ai_thinking_complete_calc(40000) elsif check_opening_tree @ai_progress = 20 else ai_thinking_calc_eval(1300) end end def prepare_ai_thinking @empty_cells = get_empty_cells(@board) @n_empty = @empty_cells.length check_confirm(@confirms,@board) @ai_progress = 10 end def init_after_pre_thinking @ai_phase = 2 @ai_progress = 0 end def init_node_list(board) top_node = CompCalcNode.new(0, 0,[0],1,board,0) puttables = find_puttable_cell(cpu_color , board) start_node = CompCalcNode.new(0, 0,puttables, cpu_color, board, -9999) @current_node_id = 1 @node_list = [top_node,start_node] 20.times do |i| node = CompCalcNode.new(0, 0,[], 1, [], 0) @node_list.push(node) end set_branch(1, 0) @current_node_id += 1 end def complete_calc(max_count) count = 0 while @current_node_id > 0 if (count > max_count) return -1 end update_node_list count = update_count(count) end return @node_list[1].result_pt end def update_count(count) case (@node_work) when 1 return count + 3 when 2 return count + 6 else return count + 1 end end def set_branch(cur_node_id,cid) node = @node_list[cur_node_id] dnode = @node_list[cur_node_id + 1] pt = node.puttables[cid] aiboard2 = make_ai_board(pt, node.color, node.board) nextcol = next_color(node.color, aiboard2) puttables = find_puttable_cell(nextcol, aiboard2) init_value = nextcol == cpu_color ? -3333 : 3333 dnode.set_node(p, puttables, nextcol, aiboard2, init_value) end def set_value(node,value) sign = node.color == cpu_color ? 1 : -1 if (sign * (value - node.value) > 0) node.value = value node.result_pt = node.puttables[node.current_child_id] end end def update_node_list current_node = @node_list[@current_node_id] board = current_node.board p_length = current_node.puttables.length parent_node = @node_list[@current_node_id - 1] if (p_length > 0 && current_node.current_child_id > p_length - 1) set_value(parent_node, current_node.value) parent_node.current_child_id += 1 @current_node_id -= 1 @node_work = 0 elsif (reversi_end?(board) ) set_value(parent_node, difference_stone(cpu_color,board)) parent_node.current_child_id += 1 @current_node_id -= 1 @node_work = 1 else set_branch(@current_node_id , current_node.current_child_id) @current_node_id += 1 @node_work = 2 end end def max_puttables(col,board,puttables) temp_deg = col == cpu_color ? -9333 : 9333 sign = col == cpu_color ? 1 : -1 puttables.each do |pt| aiboard2 = make_ai_board(pt, col, board) nextcol = next_color(col, aiboard2) deg = eval_degree(nextcol, aiboard2) if ((deg - temp_deg) * sign > 0 ) temp_deg = deg end end return temp_deg end ###通常 #7777 def init_node_eval_list(board = @board) top_node = CompCalcNode.new(0, 0,[0],1,board,0) puttables = find_puttable_cell(cpu_color, board) start_node = CompCalcNode.new(0, 0,puttables, cpu_color, board, -99999) @point_value_list = [] @node_list = [top_node,start_node] 8.times do |i| node = CompCalcNode.new(0, 0,[], 1, [], 0) @node_list.push(node) end @current_node_id = 1 set_branch_eval(1, 0) @current_node_id += 1 end def calc_eval(max_count) count = 0 while(@current_node_id > 0 ) if (@current_node_id == 1) child_node = @node_list[2] current_node = @node_list[@current_node_id] child_pt = current_node.puttables[current_node.current_child_id - 1] @point_value_list.push([child_pt, child_node.value]) end if (count > max_count) return false end update_node_list_eval count = update_count_eval(count) end #~ p @node_list p @point_value_list @point_value_list.sort!{|a,b| b[1] - a[1]} return true end def update_count_eval(count) case(@node_work) when 1 return count + 2; when 2 return count + 20; when 3 return count + 125; when 31 return count + 18; else return count + 1; end end def update_node_list_eval current_node = @node_list[@current_node_id] board = current_node.board p_length = current_node.puttables.length sign = current_node.color == cpu_color ? 1 : -1 parent_node = @node_list[@current_node_id - 1] if (reversi_end?(board) ) set_value_eval(parent_node, sign * 33333,@current_node_id) parent_node.current_child_id += 1 @current_node_id -= 1 @node_work = 0 elsif (p_length > 0 && current_node.current_child_id > p_length - 1) set_value_eval(parent_node, eval_deg(current_node, p_length),@current_node_id) parent_node.current_child_id += 1 @current_node_id -= 1 @node_work = 0 elsif (@current_node_id >= @ai_eval_depth_max) deg = max_puttables(current_node.color, board, current_node.puttables) set_value(parent_node, deg) parent_node.current_child_id += 1 @current_node_id -= 1 @node_work = 2 else set_branch_eval(@current_node_id , current_node.current_child_id) if (puttable_condition(current_node.current_child_id)) @node_work = 31 else @node_work = 3 end @current_node_id += 1 end end def set_branch_eval(cur_node_id,cid) node = @node_list[cur_node_id] dnode = @node_list[cur_node_id + 1] pt = node.puttables[cid] aiboard2 = make_ai_board(pt, node.color, node.board) nextcol = next_color(node.color, aiboard2) puttables = make_puttable_eval(nextcol,cur_node_id + 1, aiboard2) init_value = nextcol == cpu_color ? -13335 : 13335 dnode.set_node(pt, puttables, nextcol, aiboard2, init_value) end def set_value_eval(node,value,depth) sign = node.color == cpu_color ? 1 : -1 if (sign * (value - node.value) > 0) if depth <= @ai_eval_depth_max node.second_value = node.second_value ? node.value : value else node.second_value = 0 end node.value = value node.result_pt = node.puttables[node.current_child_id] set_root_record end end def set_root_record pnode = @node_list[@current_node_id - 1] node = @node_list[@current_node_id] pnode.root_record = node.root_record + [pnode.result_pt] ##あとで消すこと end def puttable_condition(depth) #~ return false return (depth <= 1) end def make_puttable_eval(col, depth, board) puttables = find_puttable_cell(col, board) cpt = cut_puttable(col,depth) if (puttable_condition(depth)) return puttables else i_max = puttables.length - 1 pt_list = [] sign = col == cpu_color ? 1 : -1 @new_puttables.clear puttables.each do |pt| aiboard2 = make_ai_board(pt, col, board) deg = eval_degree(col, aiboard2) @new_puttables.push([pt, deg]) end a = i_max + 1 > cpt ? cpt : i_max + 1 @new_puttables.sort!{|a,b| sign * (b[1] - a[1])} if i_max + 1 > a #~ pickup_puttable_num(@new_puttables,a) @new_puttables[0,a].each do |i| pt_list.push(i[0]) end return pt_list end end def eval_deg(node,plength) if (plength >= 2 ) return node.value #+ node.second_value / 25 end return node.value end def cut_puttable(col, depth) if depth == 2 return 11 #~ elsif depth == @ai_eval_depth_max #~ return 1 end return (col == cpu_color ? 3 : 7 ) end def value_eval_degree(p,value) ai_eval_list = @point_value_list ii = 1 if (p == ai_eval_list[0][0]) return value end while (ai_eval_list[ii] && ai_eval_list[0][1] - ai_eval_list[ii][1] < 1000) if (p == ai_eval_list[ii][0]) q = ((ai_eval_list[0][1] - ai_eval_list[ii][1]) * 0.1 + 1.0) ** @eval_fazzy return value / q end ii += 1 end return value / 1000000000 end def eval_degree(ccol,board) sum = 0 make_eboards(board) @empty_cells.each do |i| ix = i % BOARDWIDTH iy = i / BOARDWIDTH if (board[i] == 0 && !is_x(i) && !is_corner(i)) sum += eval_degree_base(cpu_color,ix,iy, board) end end #~ sum -= reduce_power(3, 3, get_puttable_except_x_or_lose_corner_length(cpu_color, board)) * 5; #~ sum += reduce_power(3, 3, get_puttable_except_x_or_lose_corner_length(player_color, board)) * 5; sum += eval_confirm(board) * 20 @e_array.each do |i| sum += eval_degree_for_each_edge(i,ccol, board) if @n_empty < 57 end if (check_win(player_color,board)) sum = -3333 end if (check_win(cpu_color,board)) sum = 3333 end return sum.ceil end def reduce_power(zero_pt, pow, x) if (x >= zero_pt) return 0 else return (zero_pt - x) ** pow end end def get_puttable_except_x_or_lose_corner_length(col,board) @temp_puttables.clear puttables2 = find_puttable_cell(col,board) puttables2.each do |pt| aiboard2 = make_ai_board(pt,col,board) if(!puttable_corner(op_color(col), aiboard2) && !is_x(pt)) @temp_puttables.push(pt) end end return @temp_puttables.length end def puttable_corner(col, board) if (reverse_stone_puttable?(0,0,col,board)) return true end if (reverse_stone_puttable?(7,0,col,board)) return true end if (reverse_stone_puttable?(7,7,col,board)) return true end if (reverse_stone_puttable?(0,7,col,board)) return true end return false end def eval_degree_for_each_edge(edge,ccol, board) value = 0 eboard = @eboards[edge] edata0p = get_edge_data0(player_color,eboard) edata0c = get_edge_data0(cpu_color,eboard) #~ value -= eval_stoner_trap_each_edge(player_color,eboard, edata0p) #~ value -= eval_degree_edge(edge,player_color,ccol,eboard, edata0p) #~ value += eval_degree_edge(edge,cpu_color,ccol,eboard, edata0c) value += eval_around_corner(cpu_color,eboard) * 8 value -= eval_around_corner(player_color,eboard) * 8 return value end def eval_around_corner(col,eboard) value = 0 if (eboard[0] == 0) if (eboard[1] == col) value -= 15 end if (eboard[9] == col) value -= 80 end if (eboard[8] == col) value -= 15 end elsif (eboard[0] == col) value += 600 end return value; end def neval_x_for_ecorner(col,eform,eboard) value = 0, opcol = op_color(col) if (eform == 1) value = 50 elsif (eform == 101) value = 40 elsif (eform == 11) value = 30 else value = 120 end end def get_edge_area(x,y) if (y <= x && y <= 7 - x) return 0 end if (y <= x && y >= 7 - x) return 1 end if (y >= x && y >= 7 - x) return 2 end if (y <= x && y >= 7 - x) return 4 end return 0 end def eval_confirm(board) value = 0 check_temp_confirm(@temp_confirms, board) (0..63).each do |i| if (@temp_confirms[i]) if (board[i] == player_color) value = value - 1 else value = value + 1 end end end return value end def check_temp_confirm(array,board) init_temp_confirm(array) update_t_confirm_array(board, array, 0) update_t_confirm_array(board, array, 1) update_t_confirm_array(board, array, 0) update_t_confirm_array(board, array, 1) end def check_confirm(array,board) init_confirm(array) update_t_confirm_array(board, array, 0) update_t_confirm_array(board, array, 1) update_t_confirm_array(board, array, 0) update_t_confirm_array(board, array, 1) end def update_t_confirm_array(board,carray,type) (0..63).each do |i| id = type == 0 ? @spiral_id[i] : @rspiral_id[i] px = id % BOARDWIDTH py = id / BOARDWIDTH col = get_board_data2(px,py,board) if get_board_data2(px,py,board) != 0 && check_confirm_line(px,py,col,board,carray) carray[id] = true; end end end def check_confirm_line(x,y,col,board,temp_confirm) if (!check_confirm_line_ds(x,y,col,1,1,board,temp_confirm)) return false end if (!check_confirm_line_ds(x,y,col,1,-1,board,temp_confirm)) return false end if (!check_confirm_line_ds(x,y,col,0,1,board,temp_confirm)) return false end if (!check_confirm_line_ds(x,y,col,1,0,board,temp_confirm)) return false end return true end def check_confirm_line_ds(px,py,col,dx,dy,board,temp_confirm) if (check_filled_d(px,py,dx,dy,board)) return true end if (check_confirm_line_d(px,py,col,dx,dy,board,temp_confirm)) return true end if (check_confirm_line_d(px,py,col,-dx,-dy,board,temp_confirm)) return true end return false end def check_confirm_line_d(px,py,col,dx,dy,board,temp_confirm) x = px + dx y = py + dy while(inside_board(x , y)) pt = y * BOARDWIDTH + x; if (!temp_confirm[pt] || get_board_data(x,y,board) == op_color(col)) return false end x = x + dx y = y + dy end return true end def check_filled_d(px,py,dx,dy,board) x = px y = py while(inside_board(x , y)) if (get_board_data2(x,y,board) == 0) return false end x = x + dx y = y + dy end x = px y = py while(inside_board(x , y)) if (get_board_data2(x,y,board) == 0) return false end x = x - dx y = y - dy end return true end def eval_degree_base(col,px,py,board) count = eval_degree_base_each_d(col,px,py,1,1,board) + eval_degree_base_each_d(col,px,py,1,0,board) + eval_degree_base_each_d(col,px,py,1,-1,board)+ eval_degree_base_each_d(col,px,py,0,1,board) + eval_degree_base_each_d(col,px,py,0,-1,board)+ eval_degree_base_each_d(col,px,py,-1,1,board) + eval_degree_base_each_d(col,px,py,-1,0,board) + eval_degree_base_each_d(col,px,py,-1,-1,board); return eval_function_on_cell(count) end def eval_degree_base_each_d(bcol,px,py,dx,dy,board) col = get_board_data((px + dx),(py + dy),board); if(col == bcol) return -1 elsif(col == op_color(bcol)) return 1 end return 0; end def eval_function_on_cell_abs(num) return num * 30 - num end def eval_function_on_cell(num) sign = num < 0 ? -1 : 1 return sign * eval_function_on_cell_abs(sign * num) end def inverse_coord_global_into_edge2(edge,x,y) case (edge) when 0 return x + y * BOARDWIDTH when 4 return (BOARDWIDTH - 1 - x) + y * BOARDWIDTH when 1 return (BOARDWIDTH - 1 - y) + x * BOARDWIDTH when 5 return (BOARDWIDTH - 1 - y) + (BOARDHEIGHT - 1 - x) * BOARDWIDTH when 6 return x + (BOARDHEIGHT - 1 - y) * BOARDWIDTH when 2 return (BOARDHEIGHT - 1 - x) + (BOARDWIDTH - 1 - y) * BOARDWIDTH when 7 return y + x * BOARDWIDTH when 3 return y + (BOARDHEIGHT - 1 - x) * BOARDWIDTH else return x + y * BOARDWIDTH end end def compare_array(array,array2) l1 = array.length l2 = array2.length if (l1 != l2) return false end for i in 0..(l1 - 1) if array[i] != array2[i] return false end end return true end def array_components(tarray) array = [] ts = tarray[0] ? null : 1 cstartpoints = [] tarray.each_index do |i| if (tarray[i] != ts) ts = tarray[i] array.push(tarray[i]) cstartpoints.push(i) end end return [array,cstartpoints] end def get_edge_array0(array,board) @e_array.each do |i| array[i] = (get_board_data2(i,0,board)) end end def get_edge_array1(array,board) @e_array.each do |i| array[i] = (get_board_data2(0,i,board)) end end def get_edge_components0(board) ts = -1 array = [] cstartpoints = [] @e_array.each do |i| s = get_board_data2(i,0,board) if (s != ts) ts = s array.push(s) cstartpoints.push(i) end end return [array,cstartpoints] end def get_line_stones(array,x, y, dx, dy, length, board) array.clear (0..(length - 1)).each do |i| array.push(get_board_data(x + dx * i, y + dy * i, board)) end end def get_edge_same_root(edge) return get_conjugate_corner(edge) end def put_in_pre_last(pt,value) edge = near_corner(pt) eboard = @eboards0[edge] if around_corner?(pt) value = eval_corner_in_pre_last(eboard) if is_x(pt) value *= 100 elsif is_corner(pt) value *= 10000 end else value = eval_nonaround_corner_in_pre_last(pt,value) end return value end def eval_nonaround_corner_in_pre_last(pt,value = 1) ai_board = make_ai_board(pt ,cpu_color, @board) corner_pt = target_corner_lost_corner_each_pt(pt) ai_board2 = make_ai_board(corner_pt ,player_color, ai_board) corner = get_corner_id(corner_pt) make_eboards(ai_board2) eboard = @eboards[corner] edata0 = get_edge_data0(player_color,eboard) edata1 = get_edge_data1(player_color,eboard) count = count_around_corner(eboard) if reverse_stone_puttable?(1,0,cpu_color,eboard) && edata0 == 10111110 if count % 2 == 1 return 10000000 else return 200000 end elsif reverse_stone_puttable?(0,1,cpu_color,eboard) && edata1 == 10111110 if count % 2 == 1 return 10000000 else return 200000 end else if count % 2 == 1 return 100000 elsif count_root_wing_at_edge(cpu_color,eboard) > 0 return 2 end end return 400 end def near_corner(pt) x = pt % BOARDWIDTH y = pt / BOARDWIDTH return 0 if x < 4 && y < 4 return 1 if x >= 4 && y < 4 return 2 if x >= 4 && y >= 4 return 3 if x < 4 && y >= 4 end def around_corner?(pt) x = pt % BOARDWIDTH y = pt / BOARDWIDTH x < 2 && y < 2 || x >= 6 && y < 2 || x >= 6 && y >= 6 || x < 2 && y >= 6 end def target_corner_lost_corner_each_pt(pt) ai_board = make_ai_board(pt ,cpu_color, @board) @corners.each do |corner| x = corner % BOARDWIDTH y = corner / BOARDWIDTH return corner if (reverse_stone_puttable?(x,y,player_color,ai_board)) end end def eval_corner_in_pre_last(eboard) value = 1 count = count_around_corner(eboard) if count == 3 if count_root_wing_at_edge(player_color,eboard) > 0 return 20000000 elsif count_root_wing_at_edge(cpu_color,eboard) > 0 return 5000 else return 300000 end elsif count == 4 if count_root_wing_at_edge(player_color,eboard) > 0 return 2000000 elsif count_root_wing_at_edge(cpu_color,eboard) > 0 return 2 else return 24000 end else if count_root_wing_at_edge(player_color,eboard) > 0 return 100000 elsif count_root_wing_at_edge(cpu_color,eboard) > 0 return 2 else return 110 end end return value end def only_puttable_lost_corner?(col,board) return false if lose_corner_board?(col,board) puttables = find_puttable_cell(col,board) puttables.select{|pt| !put_lost_corner?(pt,col,board)}.empty? end def put_lost_corner?(pt,col,board) px = pt % BOARDWIDTH py = pt / BOARDWIDTH ai_board = make_ai_board(pt, col,board) lose_corner_board?(op_color(col),ai_board) end def lose_corner_board?(col,board) reverse_stone_puttable?(0, 0,col,board) || reverse_stone_puttable?(7, 0,col,board) || reverse_stone_puttable?(0, 7,col,board) || reverse_stone_puttable?(7, 7,col,board) end def count_around_corner(eboard) v = 0 v += 1 if eboard[0] == 0 v += 1 if eboard[1] == 0 v += 1 if eboard[8] == 0 v += 1 if eboard[9] == 0 return v end def count_root_wing_at_edge(col,eboard) edata0 = get_edge_data0(col,eboard) edata1 = get_edge_data1(col,eboard) value = 0 value += 1 if edata0 == 111110 value += 1 if edata1 == 111110 return value end def get_conjugate_corner(corner) case(corner) when 0 return 7 when 1 return 4 when 2 return 5 when 3 return 6 when 4 return 1 when 5 return 2 when 6 return 3 when 7 return 0 else return end end def get_edge_same_pointa(edge) case(edge) when 0 return 5 when 1 return 6 when 2 return 7 when 3 return 4 when 4 return 3 when 5 return 0 when 6 return 1 when 7 return 2 else return end end def trans_board_global_into_edge(edge,board) new_board = [] (0..BOARDWIDTH - 1).each do |i| (0..BOARDHEIGHT - 1).each do |j| new_board[i + BOARDWIDTH * j] = board[inverse_coord_global_into_edge2(edge,i,j)] end end return new_board end def get_edges_include_corner(cid) case(cid) when 0 return [0,7] when 1 return [1,4] when 2 return [2,5] when 3 return [3,6] else return [] end end def trans_coord_global_into_edge(edge,array) x = array[0] y = array[1] case (edge) when 0 return [x, y] when 4 return [BOARDWIDTH - 1 - x, y] when 1 return [y, BOARDWIDTH - 1 - x] when 5 return [BOARDHEIGHT - 1 - y, BOARDWIDTH - 1 - x] when 6 return [x, BOARDHEIGHT - 1 - y] when 2 return [BOARDWIDTH - 1 - x, BOARDHEIGHT - 1 - y] when 7 return [y, x] when 3 return [BOARDHEIGHT - 1 - y, x] else return [x,y] end end def get_reciprocal_edge(edge) return (edge + 4) % 8 end def get_near_edge(px,py) if (px >= py && BOARDHEIGHT - 1 - px >= py) return 0 end if (px >= py && BOARDHEIGHT - 1 - px <= py) return 1 end if (px <= py && BOARDHEIGHT - 1 - px <= py) return 2 end if (px <= py && BOARDHEIGHT - 1 - px >= py) return 3 end end def get_corner_id(pt) @corners.index(pt) end def make_ecomps @ecomps.each_with_index do |ecomp,edge| get_edge_components0(ecomp,@eboards[edge]) end end def make_eboards(board,container = @eboards) 8.times{|edge| container[edge] = trans_board_global_into_edge(edge, board)} end def edge_onecolor?(edge) ecomp = @ecomps[edge] return ecomp.comp.length == 1 end def init_confirm(array) 64.times{|i| array[i] = false} end def init_temp_confirm(array) 64.times{|i| array[i] = @confirms[i]} end def get_edge_data0(col,board) @e_array.inject(0){|result, i| result + convert_color_to_turn(get_board_data2(i,0,board),col) * 10 ** (7 - i)} end def get_edge_data1(col,board) @e_array.inject(0){|result, i| result + convert_color_to_turn(get_board_data2(0,i,board),col) * 10 ** (7 - i)} end def get_inedge_data0(col,board) (0..5).inject(0){|result, i| result + convert_color_to_turn(get_board_data2(i + 1,1,board),col) * 10 ** (5 - i)} end def convert_color_to_turn(color,col) return 0 if color == 0 return color == col ? 1 : 2 end end