class Scene_Riversi < Scene_MenuBase
  
  alias tako1set_init set_init
  def set_init
    tako1set_init

    @ai_board = []
    @open_space_degree_array = []
    @exact_win_degree_array = [ - 10000 ,max_gettable_stones(1),max_gettable_stones(2)]
  end
  
  #● ai_boardの作成
  def make_ai_board(x , y ,color , board = @board) 
    aiboard = board.dup
    set_board_data(x, y , color , aiboard )
    reverse_stone(x , y , color , aiboard )
    return aiboard
  end   
  
  #●boardにcolorの石をおいたとき次の色
  def next_color(x , y , color ,board)
    
    ai_board = make_ai_board(x , y ,color , board )
    if puttable_cell_exist?(op_color(color), ai_board)
      return op_color(color)
    elsif puttable_cell_exist?(color, ai_board)
      return color
    else
      return 0
    end  
  end  
    
  #● デバッグ用の数字の表示
  def show_debug_num(return_value)
    printf "********************* \n"    
    printf("turn : %d \n" ,@turn_count ) 
    printf("puttabe : %d \n" , @cpu_ai[return_value] ) 
    printf("flag : %s \n" , only_puttable_lose_corner? )  
    printf("return_value : %s \n" , return_value) 
    printf("open_degree : %s \n" ,     @open_space_degree_array[2]) 
    printf("@empty_cells : %s \n" , @empty_cells)     
  end 
  
 

  #● CPUの優先度配列の作成
  def make_cpu_ai
    
    
    last_flag = false
    cx_flag = false
    complete_array_temp = []
    if @turn_count > BOARDWIDTH * BOARDHEIGHT - 4 - 1 - 9
      last_flag = true
    end 
    cx_flag = puttable_only_xc? && !(last_flag)  
 
    make_calculate_open_space_degree if @turn_count > 8 && !last_flag #開放度理論 

    for i in 0..@ai_puttable.size - 1 
      put_value = 100000
      ix = @ai_puttable[i] % BOARDWIDTH
      iy = @ai_puttable[i] / BOARDWIDTH
      @ai_board.clear 
      @ai_board = make_ai_board(ix , iy, cpu_color)
      

#~       put_value += plus_corner(ix , iy)
      
      if @turn_count > 8 && !last_flag && !cx_flag   #開放度理論     
        unless @open_space_degree_array.empty?
          if @open_space_degree_array[0] == ix && @open_space_degree_array[1] == iy 
            put_value *= 666 
          end  
        end          
      
      end 

      put_value = restrict_put_x(ix , iy , put_value) 
      put_value = restrict_corner_lose_put(ix , iy , put_value)
      put_value = restrict_put_c_isolated(ix , iy , put_value) 
      put_value = plus_corner(ix ,iy ,put_value)
      put_value = guard_corner_lose(ix , iy , put_value)   
      put_value = put_c_edge_samecolor_disjoint(ix , iy , cpu_color ,put_value)
      put_value = contact_putting_on_edge(ix , iy , cpu_color  , @board , put_value)
      put_value = okiuchi_putting(ix , iy , cpu_color , @board ,put_value)
      put_value = attack_on_edge(ix , iy , cpu_color , @board , put_value)
      put_value = connect_edge_samecolor_disjoint(ix , iy , cpu_color , @board , put_value)
      put_value = only_puttable_around_corner(ix , iy , cpu_color , put_value) if only_puttable_lose_corner?
#~       @reversi_window.get_number(@turn_count)  if only_puttable_lose_corner?
      put_value = puttable_around_nonempty_corner(ix , iy , cpu_color , @board , put_value)
      put_value = 1 if exact_lose_put?(ix , iy ) #全滅する手の制限
      put_value = exact_win_put?(put_value)
      if last_flag
        complete_array_temp = complete_calculate(cpu_color)
        if complete_array_temp[0] == ix && complete_array_temp[1] == iy
          put_value = 1000000000
        else 
          put_value = 1
        end  
      end 
  
      @cpu_ai.push(put_value)
      
    end  
  end

  #● CX角のゾーンであるか否か？
  def cxcorner?(x , y)
    if x < 2 || x > BOARDWIDTH-3
      if y < 2 || y > BOARDWIDTH-3
        return true
      end
    end  
    return false
  end  

  #● 基本的に角優先
  def plus_corner(x , y ,value)
    if corner?(x , y)
      return value * 100000000
    else
      return value
    end   
  end  
  
  #● 角であるか？
  def corner?(x , y)
    return 1 if x == 0 && y == 0   
    return 2 if x == 0 && y == (BOARDHEIGHT - 1)    
    return 3 if x == (BOARDWIDTH - 1) && y == (BOARDHEIGHT - 1)
    return 4 if x == (BOARDWIDTH - 1) && y == 0    
    return false
  end   
  
  #● 辺であるか？
  def edge?(x , y)
    (x == 0) || (y == 0 ) || (x == (BOARDWIDTH - 1)) || (y == (BOARDHEIGHT - 1))
  end
  
  #● 含む辺を返す array
  def get_edge_include_point(x , y)
    return [4 , - 4] if x == 0 
    return [1 , - 1] if y == 0 
    return [2 , - 2] if x == (BOARDWIDTH - 1) 
    return [3 , - 3] if y == (BOARDHEIGHT - 1)
  end  
  
  #● X打ちを控える
  def restrict_put_x(x , y , value) 
    if cell_x_corner_empty?(x , y) 
      unless puttable_x_or_lose_corner?
        value = ( value / 100000 >= 1 ? value / 100000 : 1) 
      end  
      
    end  

     return value
    
   end 
   
  #● Xであるか？
  def cell_x?(x , y)
    if x == 1 && y == 1
      return true
    end      
    if x == 1 && y == BOARDHEIGHT - 2
      return true
    end      
    if x == BOARDWIDTH - 2 && y == 1
      return true
    end  
    if x == BOARDWIDTH - 2 && y == BOARDHEIGHT - 2
      return true
    end    
    return false
  end  
  
  #● 打てる場所がXorCのみ?
  def puttable_only_xc?
    @ai_puttable.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      return false  unless cell_x?(ix , iy) || cell_c?(ix , iy)
      
    end  
    return true
    
  end  
  
  #● 打てる場所がXまたは角を取られるところのみであるか
  def puttable_x_or_lose_corner?
    @ai_puttable.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      return false  unless cell_x?(ix , iy) || corner_lose_put?(ix , iy)
      
    end  
    return true
    
  end    
  #● Xのとき角が空であるか？
  def cell_x_corner_empty?(x , y)
    if x == 1 && y == 1
      
      return true if get_board_data(0 , 0) == 0
    end      
    if x == 1 && y == BOARDHEIGHT - 2
      return true if get_board_data(0 , BOARDHEIGHT - 1) == 0
    end      
    if x == BOARDWIDTH - 2 && y == 1
      return true if get_board_data(BOARDWIDTH - 1 , 0) == 0
    end  
    if x == BOARDWIDTH - 2 && y == BOARDHEIGHT - 2
      return true if get_board_data(BOARDWIDTH - 1 , BOARDHEIGHT - 1) == 0
    end    
    return false
  end 
  
  #● 角を取られるような手の制限
  def restrict_corner_lose_put(x , y, value)
    if corner_lose_put?(x , y)
      return ( value / 100000 >= 1 ? value / 100000 : 1)
    end         
    return value    
  end  
  
  #● 角を取られるような手であるか?
  def corner_lose_put?(x , y, color = cpu_color , board = @board)

    ai_board = make_ai_board(x , y, color , board)
    if reverse_stone_puttable?(0 , 0 , op_color(color) , ai_board) 
      return true 
    end
    if reverse_stone_puttable?(0 , BOARDHEIGHT - 1 , op_color(color) , ai_board) 
      return true 
    end      
    if reverse_stone_puttable?(BOARDWIDTH - 1 , 0 , op_color(color) , ai_board) 
      return true 
    end
    if reverse_stone_puttable?(BOARDWIDTH - 1 , BOARDHEIGHT - 1 , op_color(color) , ai_board) 
      return true 
    end    
     
    return false
    
  end 

    
  #● 単独C打ちを控える
  def restrict_put_c_isolated(x , y , value)
    if isolated_c_putting?(x , y , cpu_color)
      return ( value / 500 >= 1 ? value / 500 : 1)      
    else
      return value
    end  
  end  
  
  #● Cであるか？
  def cell_c?(x , y)
    cell_abc?(x , y , 1)
  end  
  
  #● A打ちであるか？  
  def cell_a?(x , y)
    cell_abc?(x , y , 2)
  end
  
  #● Bであるか？
  def cell_b?(x , y)
    cell_abc?(x , y , 3)
  end  
  
  #● 辺におけるABCの判定
  def cell_abc?(x , y , a)
    all_edges.each do |edge|
       return true if transform_board_coordinate_into_edge_coordinate(edge, x , y) == [ a , 0 ]
    
    end
    return false
  end  
  
  
  #● 孤立したCとなる手であるか 
  def isolated_c_putting?(x , y, color , board = @board ) 
    return false unless cell_c?(x, y)
    edge = get_edge_near_c(x , y )
    return empty_edge?(edge , board)
  end     
    
  #● 指定した辺に孤立したCがあるか？  
  def exist_isolated_c?(edge , color , board = @board ) 
    estones = get_edge_stones(edge , board)
    return true if estones == [0,color] + [0] * (BOARDWIDTH - 2)
    return false
  end     
  
  #● 角を取られることを防ぐ
  def guard_corner_lose(x , y , value)
    return value unless some_corner_get_soon?(cpu_color)
    
    value *= 100000  unless unable_guard_corner_lose?(x , y , cpu_color)
    return value
  end  
  
  
  #● 角を取られることを防げないか?
  def unable_guard_corner_lose?(x , y , color,  board = @board)
    ai_board = make_ai_board(x , y , color, board).dup
    4.times do |i|
      return true if reverse_stone_puttable_corner?(i + 1 , 0 , 0 , op_color(color) , ai_board) 
    end    
     
    return false
    
  end  

  #● 角を取ることができる状況か?
  def corner_get_soon?(corner , color,  board = @board)
     reverse_stone_puttable_corner?(corner , 0 , 0 , color , board)

  end     
  
  #● どこかの角を取ることができる状況か?
  def some_corner_get_soon?(color,  board = @board)
    4.times do |i|
      return true if corner_get_soon?(i + 1 , color,  board)
    end  
    return false
  end     

 
  
  def difference_puttable_number(color ,board = @board)
    puttable = find_puttable_cell(color,board)
    puttable2 = find_puttable_cell(op_color(color),board)
    return puttable.size - puttable2.size
  end  
  
  #● 開放度理論による優先度の高いｘｙを取り出す
  def make_calculate_open_space_degree(board = @board , color = cpu_color)
    weight_degree = 1
    count = 1
    temp_v = 10000
    temp_x = 0
    temp_y = 0
    d_temp = 0
    weight = 1 + weight_degree * (count + 1)
    @open_space_degree_array.clear
    for i in 0..BOARDWIDTH - 1
      for j in 0..BOARDHEIGHT - 1
         
        if reverse_stone_puttable?(i , j , color ,board) && !(cxcorner?(i , j))
          a = expanded_open_space_degree(i , j , color, board, color , count , weight_degree)
          a += weight * calculate_open_space_degree_each_color(i , j , color, board)  
          if temp_v > a
            temp_v = a
            temp_x = i
            temp_y = j
          elsif temp_v == a
            if rand(3) == 1
              temp_x = i
              temp_y = j
              d_temp = temp_v
            end
          end
        end 

      end
    end
    @open_space_degree_array.push(temp_x)
    @open_space_degree_array.push(temp_y)
    @open_space_degree_array.push(temp_v)
  end 
  
  #● 開放度を測定する
  def calculate_open_space_degree_each_color(x , y , color, board = @board)
    degree = 0
    for dx in -1..1
      for dy in -1..1

        if reverse_stone_exist_d?(x , y , dx , dy , color , board)
          degree += calculate_open_space_degree_each_color_d(x , y , dx ,dy , color , board) 
        end  
      end  
    end   
    return degree
  end 
  
  #● 開放度を測定する　方向ごと
  def calculate_open_space_degree_each_color_d(x , y , dx ,dy , color, board = @board)
    i = 1
    degree = 0
    # 逆石でなくなるまで測定
    while  get_board_data(x + dx * i , y + dy * i , board ) == op_color(color) 

      degree += calculate_open_space_degree_each_point(x + dx * i ,y + dy * i, color , board)
      i += 1
    end  

    return degree
  end 
  
  #● 開放度を測定する(各点)
  def calculate_open_space_degree_each_point(x , y , color, board = @board)
    degree = 0
    for dx in -1..1
      for dy in -1..1
        if get_board_data(x + dx , y + dy , board ) == 0
          degree += 1
        end  
      end  
    end   
    return degree
  end  

  
  
  #● 重みつき開放度
  def expanded_open_space_degree(x , y , color, board, base_color,count , weight_degree = 0)
    ncolor = next_color(x , y , color ,board)
    return 0  if ncolor == 0  # 念のため
    color_sign = 1
    if ncolor == base_color
      open_degree = 10000
    else  
      open_degree = -10000
      
    end 

    ai_board = make_ai_board(x , y , color, board)
#~     open_degree = 100 
    puttable2 = find_puttable_cell(ncolor,ai_board)
#~     return -1 if puttable2.empty? 
    puttable2.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
        
     
      
      base_num = 0      
      color_sign = ( ncolor == base_color ?  1 : -1 )
      if count > 0
        base_num = expanded_open_space_degree(ix , iy , ncolor, ai_board, base_color  , count - 1)  
        add_num = calculate_open_space_degree_each_color(ix , iy , ncolor, ai_board)  
      else  
        add_num = calculate_open_space_degree_each_color(ix , iy , ncolor, ai_board)
        
      end
      weight = 1 + weight_degree * count
      temp_num = color_sign * weight * add_num + base_num
      if ncolor == base_color
        open_degree = temp_num if temp_num < open_degree
      else  
        open_degree = temp_num if temp_num > open_degree
      
      end 
      
    end
      
    return open_degree
  end  
  
  ### 辺の戦略
  #● 付け手ができるかを調べる
  def check_contact_putting_on_edge(x , y , color ,edge , board)
    return false unless get_edge_components(edge) == [0 , op_color(color) , 0]
    ed = edge_direction(edge)
    nc = [x + ed[0] , y ]
    ed2 = edge_direction(- edge) 
    nc2 = [x + ed2[0] , y ] 
    t1 = 0
    t2 = 0
    t1 = 1 if get_board_data(nc[0] , nc[1] , board ) == op_color(color) 
    t2 = 1 if get_board_data(nc2[0] , nc2[1] , board ) == op_color(color) 
    return t1 * 10 + t2 
    
  end
  
  #● 付け手  
  def contact_putting_on_edge(x , y , color , board, value)
    return value if cxcorner?(x , y)
    return value unless edge?(x , y)
    edges = get_edge_include_point(x , y)
    edge = edges[0]
    return value unless exist_stone_on_edge?(edge,op_color(color) , board)
    return value if corner_lose_put?(x , y , color ,board)
    a = check_contact_putting_on_edge(x , y , color ,edge , board)
    case a 
    when 0
      return value * 10000
    when 1
      return value * 10000
    when 10
      return value * 10000 
    when 11  
      return value * 130000 
      
    end  
    return value
  end
  #● Aの上側に余裕手が発生するB打ちに対するA打ちの付けてであるか
  def check_putA_for_B_yield_remainder_over_A?(x , y , color ,edge , board)
    
#~     cell_a?(x, y) && check_yield_remainder_over_A?(x , y , color ,edge , board)
  end
  
  #● Aの上側に余裕手が発生するか
  def check_yield_remainder_over_A?(x , y , color ,edge , board)
    ai_board = ai_board = make_ai_board_edge(x , y ,edge , color , board)
    return true if reverse_stone_puttable_edge?(edge ,1, 0 , color ,  ai_board) 
    return false
  end
  
  #● 置き打ちできるか
  def check_okiuchi_putting(x , y , color , board)
    return false unless edge?(x , y)    
    all_edges.each do |edge|
      edi = inverse_board_coordinate_into_edge_coordinate(edge, 2 , 0 )
      if reverse_stone_puttable_edge?(edge ,2, 0 , color ,  board) 
        ai_board = make_ai_board_edge(2, 0 ,edge , color , board)
        if get_data_edge_coordinate(edge , 2 , 1 , ai_board) == op_color(color)
          return true if edi == [x , y ]
            
        end  
      end  
    end
    return false
  end
  
  #● 置き打ち
  def okiuchi_putting(x , y , color , board ,value)
    return value * 10000 if check_okiuchi_putting(x , y , color , board)
    return value  
  end  
  
  #● 単独C打ちが存在しているか？ 辺を返す。なければ 0
  def check_isolate_c_putting(color , board )
    all_edges.each do |edge|
      return edge if exist_isolated_c?(edge , color , board = @board )
      
    end  
    return 0
    
  end
  
  #● 辺の状態による戦略
  def attack_on_edge(x , y , color , board ,value)
    return value if corner?(x,y)    
    edges = edge_include_cell(x, y , 0)
    return value if edges.empty? 
    edges.each do |edge|
      return value * 100000 if next_attack_on_edge(x , y , color ,edge , board)
    end  
    return value 
  end  
  
  #● 辺の状態を調べ次の手を決める
  def next_attack_on_edge(x , y , color ,edge , board)
    estones = get_edge_stones(edge , board)
    c = color
    oc = op_color(color)    
    ei = []
    if estones == [0,oc] + [0] * (BOARDWIDTH - 2)
      ei = inverse_board_coordinate_into_edge_coordinate(edge, 3 , 0 )       
    elsif estones == [0, oc , 0 , c] + [0] * (BOARDWIDTH - 4)  
      ei = inverse_board_coordinate_into_edge_coordinate(edge, 5 , 0 )      
    elsif estones == [0, oc , 0 , c , 0 ,c] + [0] * (BOARDWIDTH - 6)   
      ei = inverse_board_coordinate_into_edge_coordinate(edge, 2 , 0 )          
    elsif estones == [0, oc , 0 , c , oc ,c] + [0] * (BOARDWIDTH - 6)   
      ei = inverse_board_coordinate_into_edge_coordinate(edge, 2 , 0 ) 
    elsif estones == [0, 0 , oc ] + [0] * (BOARDWIDTH - 3) 
      
    end  
    return false if ei.empty?
    return true if ei[0] == x && ei[1] == y   
    return false
  end    
  
  
#~   
  ### 終盤完全読み　(再帰的に定義する)
  
  #● 完全読み  
  def complete_calculate(color , board = @board , basecolor = cpu_color)
    tcolor = 0
    tx = -1
    ty = -1
    temp2 = -2000

    puttable2 = find_puttable_cell(color , board)

    puttable2.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      
     

      a = eval_complete_caluculate(ix,iy,color , board, basecolor )

      
      if a > temp2
        temp2 = a
        tx = ix
        ty = iy
      end  

      
    end
    return [tx , ty]
  end  

  def eval_complete_caluculate(x,y,color , board, basecolor = cpu_color)
    ncolor = next_color(x , y , color ,board)
    dstone = difference_stone(basecolor , board)
    return dstone if ncolor == 0
    empty_cells_num = get_empty_cells(board).size
    return dstone if empty_cells_num <= 3 && dstone.abs >= @exact_win_degree_array[empty_cells_num - 1]
    
    if ncolor == basecolor
      temp = -2000
    else
      temp = 2000
    end  

    ai_board = make_ai_board(x , y , color, board) 
      
    puttable2 = find_puttable_cell(ncolor , ai_board)
    puttable2.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH      
      
      a = eval_complete_caluculate(ix , iy , ncolor , ai_board, basecolor)
      if ncolor == basecolor
        temp = a if temp < a
      else
        temp = a if temp > a
      end  
        
    end  
    return temp
    
  end  
  
  #● 得られる石の数の限界
  def max_gettable_stones(lturn)
    m = [BOARDWIDTH , BOARDHEIGHT].max
    return (BOARDWIDTH - 2 + BOARDHEIGHT - 2 + m - 2) * lturn - (lturn - 1) * 3 
    
  end    
  
  ###--------------------------
  
  #● 全ての辺のIDのリスト
  def all_edges
    [1 , - 1 , 2 , - 2 , 3 , - 3 , 4 , - 4 ]
  end  
  
  #● グローバルなボード座標から辺座標への変換
  def transform_board_coordinate_into_edge_coordinate(edge, x , y ) 
    array_t = []
    hogehoge if edge == 0
    case edge
    when 1
      array_t.push(x)
      array_t.push(y)
    when (- 1)
      array_t.push(BOARDWIDTH - 1 - x)
      array_t.push(y)      
      
    when 2
      array_t.push(y) 
      array_t.push(BOARDWIDTH - 1 - x)     
    when (- 2)
      array_t.push(BOARDHEIGHT - 1 - y) 
      array_t.push(BOARDWIDTH - 1 - x)        
    when 3
      array_t.push(x) 
      array_t.push(BOARDHEIGHT - 1 - y)      
    when (- 3)
      array_t.push(BOARDWIDTH - 1 - x)
      array_t.push(BOARDHEIGHT - 1 - y)        
      
    when 4  
      array_t.push(y) 
      array_t.push(x)
    when (- 4)  
      array_t.push(BOARDHEIGHT - 1 - y) 
      array_t.push(x)      
  
      
    end  
    

    return array_t
  end
  
  #● transform_board_coordinate_into_edge_coordinateの逆変換
  def inverse_board_coordinate_into_edge_coordinate(edge, x , y )
    transform_board_coordinate_into_edge_coordinate(edge, x , y )
  end  
  
  #● 辺座標を使ってデータの取得
  def get_data_edge_coordinate(edge, x , y , board = @board) 
    array = inverse_board_coordinate_into_edge_coordinate(edge, x , y )
    get_board_data(array[0] , array[1] , board)
  end  
  
  #● edgeの方向性
  def edge_direction(edge)
    edge_sign = edge > 0 ? 1 : - 1
    case edge.abs
    when 1
      return [1 * edge_sign , 1]
    when 2
      return [ - 1 , 1 * edge_sign]
    when 3
      return [ - 1 * edge_sign , - 1]
    when 4
      return [1 , - 1 * edge_sign]
    else  
      return [0 , 0]
    end  
  end   
  
  
  #● グローバルなボード座標から角座標への変換
  def transform_board_coordinate_into_corner_coordinate(corner, x , y ) 
    array_t = []
    case corner
    when 1
      array_t.push(x) 
      array_t.push(y)
    when 2
      array_t.push(BOARDWIDTH - 1 - x) 
      array_t.push(y)      
    when 3
      array_t.push(BOARDWIDTH - 1 - x) 
      array_t.push(BOARDHEIGHT - 1 - y)      
    when 4  
      array_t.push(x) 
      array_t.push(BOARDHEIGHT - 1 - y)
    end    
    return array_t 
  end     
  
  #● transform_board_coordinate_into_corner_coordinateの逆変換
  def inverse_board_coordinate_into_corner_coordinate(corner, x , y ) 
    transform_board_coordinate_into_corner_coordinate(corner, x , y )
  end  
  
  #● 角座標を使ってデータの取得
  def get_data_corner_coordinate(corner, x , y ,board = @board ) 
    array = inverse_board_coordinate_into_corner_coordinate(corner, x , y )
    get_board_data(array[0] , array[1] ,board)
  end  
  
  #● ある角を根とする辺を取得 （arrayで返す）
  def get_edge_of_corner(corner)
    case corner
    when 1
      return [1 , 4]
    when 2
      return [2, - 1]
    when 3
      return [- 2 , - 3]
    when 4
      return [3 , - 4]
    else  
      return []
    end  
  end 
  
  #● 辺の石の情報の取得
  def get_edge_stones(edge , board = @board)
    array = []
    BOARDWIDTH.times do |i|
      array.push(get_data_edge_coordinate(edge, i , 0 , board))
      
    end 
    return array
  end   
  
  #● 辺座標において石を置けるか判定
  def reverse_stone_puttable_edge?(edge , x , y , color, board = @board )
    c = inverse_board_coordinate_into_edge_coordinate(edge, x , y ) 
    reverse_stone_puttable?(c[0] , c[1] , color , board)
  end  
  
  
  #● 点座標において石を置けるか判定
  def reverse_stone_puttable_corner?(corner , x , y , color, board = @board )
    c = inverse_board_coordinate_into_corner_coordinate(corner, x , y ) 
    reverse_stone_puttable?(c[0] , c[1] , color , board )
  end  
    
  
  
  #●角をとられるところしか打てない場合
  def puttable_around_corner(x , y ,corner ,color )
    ai_board = make_ai_board(x , y , color)
    carray = corner_point(corner)
    ai_board2 = make_ai_board(carray[0] , carray[1] , op_color(color), ai_board) 
    edges = get_edge_of_corner(corner)
    edges.each do |edge|
      if reverse_stone_puttable_edge?(edge , 1 , 0 ,color,ai_board2)
        ai_board3 = make_ai_board_edge(1 , 0 ,edge, color , ai_board2 )
        return 440000 if some_corner_get_soon?(color,  ai_board3)
      end  
    end 
    return 10
  end 
  
  #● ai_boardの作成 辺座標
  def make_ai_board_edge(x , y ,edge, color , board = @board) 
    c = inverse_board_coordinate_into_edge_coordinate(edge, x , y )    
    aiboard = board.dup
#~     @reversi_window.get_number(@turn_count)
    set_board_data(c[0], c[1] , color , aiboard )
    reverse_stone(c[0], c[1] , color , aiboard )
    return aiboard
  end     
  
  #● ai_boardの作成 角座標
  def make_ai_board_corner(x , y ,corner, color , board = @board) 
    c = inverse_board_coordinate_into_corner_coordinate(corner, x , y )    
    aiboard = board.dup
#~     @reversi_window.get_number(@turn_count)
    set_board_data(c[0], c[1] , color , aiboard )
    reverse_stone(c[0], c[1] , color , aiboard )
    return aiboard
  end   
  
  #● 空の辺であるか
  def empty_edge?(edge , board = @board)
    get_edge_stones(edge , board) == [0] * BOARDWIDTH
  end  
  
  #● 辺において1マス同色dijointの場合、c内を避ける
  def put_c_edge_samecolor_disjoint(x , y , color ,value)
    return value unless cell_c?(x , y)
    edge = get_edge_near_c(x , y )
    return value / 1000 if check_edge_samecolor_disjoint?(edge, color , 1)
    return value

  end  
  
  #● 辺において1マス同色dijointをつぶせるときは潰す
  def connect_edge_samecolor_disjoint(x , y , color , board , value)    
    return value unless edge?(x , y)
    edgearray = get_edge_include_point(x , y)   
    edge = edgearray[0]
    return value unless check_edge_samecolor_disjoint?(edge, color , 1 , board)
    ai_board = make_ai_board(x , y , color)
        
    return value * 1000 unless check_edge_samecolor_disjoint?(edge, color , 1 , ai_board)
    return value
  end  
  
  
  #● 辺が同色disjoint   zero_numは間の空きの数
  def check_edge_samecolor_disjoint?(edge, color , zero_num , board = @board)
    c = color 
    earrayc = get_edge_components(edge , 0)
    
    return false unless earrayc == [0 ,c , 0 , c , 0]
    earray = get_edge_stones(edge , board)
    sarray = [c] + [0] * zero_num + [c]

    return true if exist_subarray?(earray,sarray)  
    return false
    
  end    
  
  #● arrayなかにsubarrayと同じ配列を見つける  
  def exist_subarray?(array,subarray)
    for i in 0 .. array.size - 1
      return true if array[i, subarray.size] == subarray
    end  
    return false
    
  end  
 
  
  #● 辺の石の連続する成分をチェック （Cと角を除く）
  def check_edge_component(edge)
    ecomponents = get_edge_components(edge , 2)
    c = cpu_color
    p = player_color
    return 1 if ecomponents == [c] 
    return 2 if ecomponents == [p] 
    return 3 if ecomponents == [c,p,c] 
    return 4 if ecomponents == [p,c,p]     
    return 5 if ecomponents == [c,0,p] 
    return 6 if ecomponents == [p,0,c]
    return 0
    
  end  

  #● 辺の状態をチェック
  def check_edge_contents(edge,value)  
    earray = get_edge_stones(edge)
    c1 = eaaray[1]
    c2 = eaaray[BOARDWIDTH - 2] 
    return c2 * 10 + c1    
  end   
  
  #● 辺の両cの状態をチェック
  def check_edge_cs(edge)  
    earray = get_edge_stones(edge)
    c1 = eaaray[1]
    c2 = eaaray[BOARDWIDTH - 2] 
    return c2 * 10 + c1    
  end 
  
  #● arrayの連続する成分の並び
  def get_array_components(array)
    return [] if array.empty? 
    temp = array[0] 
    array2 = [temp]
    array.each do |i|
      if temp != i
        array2.push(i)
        temp = i
        
      end
    end  
    return array2
  end      
  
  #● 辺の石の連続する成分の並び 
  def get_edge_components(edge , r = 0)
    earray = get_edge_stones(edge)
    earrayc = earray[r,BOARDWIDTH - r * 2]
    return get_array_components(earrayc)
    
  end    
  
  #● 辺に石が存在するか?
  def exist_stone_on_edge?(edge,color , board)  
    earray = get_edge_stones(edge,board)
    earray.include?(color) 
  end    
  
  #● セルを含む辺たち
  def edge_include_cell(x, y , sign = 0)
    array = []
    if x == 0
      array.push(4) unless sign < 0
      array.push(- 4) unless sign > 0
    end
    if x == BOARDWIDTH - 1
      array.push(2) unless sign < 0
      array.push(- 2) unless sign > 0
    end    
    if y == 0
      array.push(1) unless sign < 0
      array.push(- 1) unless sign > 0
    end
    if y == BOARDWIDTH - 1
      array.push(3) unless sign < 0
      array.push(- 3) unless sign > 0
    end    
    return array
  end  
  
  #● 角の近傍に含まれているか?
  def include_corner_region?(x , y , corner , distx , disty) 
    array2 = []
    array2 =  transform_board_coordinate_into_corner_coordinate(corner, x , y )
    cx = array2[0]
    cy = array2[1]
    return true if include_rect?(cx ,cy , 0 , 0 , distx , disty)
    return false
  end 
  
  #● 4分割された領域のどこに入るか(幅が奇数の場合、中線上のマスは無視される)
  def get_devided_region(x , y)
    distx = BOARDWIDTH / 4 - 1 
    disty = BOARDHEIGHT / 4 - 1
    for corner in 1..4
      return corner if include_corner_region?(x , y , corner , distx , disty) 
    end  
    return 0
  end  
  
  #● 領域に点が含まれているか
  def include_rect?( x , y , rx1 , ry1 , rx2 , ry2 ) 
    if rx1 <= x && x <= rx2
      if ry1 <= y && y <= ry2
        return true
      end  
    end
    return false
  end    

 
  
   #●　周辺に属するのか?
  def around_cell?(x , y , xbase , ybase)
    (x - xbase).abs <= 1 && (y - ybase).abs <= 1
  end  
  
   #●　どの角周辺に属するのか
  def around_corner_num(x , y) 
    return 1 if around_cell?(x , y , 0 ,0) 
    return 2 if around_cell?(x , y , BOARDWIDTH - 1 ,0)   
    return 3 if around_cell?(x , y , BOARDWIDTH - 1 ,BOARDHEIGHT - 1)   
    return 4 if around_cell?(x , y , 0 ,BOARDHEIGHT - 1) 
    return 0
  end    
   #●　角の座標を取得
  def corner_point(corner) 
    return inverse_board_coordinate_into_corner_coordinate(corner, 0 , 0 ) 
  end    
    
   #●　角周辺の空き数
  def around_corner_empty_num(corner) 
    num = 0
    case corner
    when 1
      dx = 1
      dy = 1
      bx = 0
      by = 0
    when 2
      dx = -1
      dy = 1
      bx = BOARDWIDTH - 1 
      by = 0      
    when 3
      dx = -1
      dy = -1
      bx = BOARDWIDTH - 1 
      by = BOARDHEIGHT - 1      
    when 4 
      dx = 1
      dy = -1     
      bx = 0
      by = BOARDHEIGHT - 1
    end  
    for i in 0..1
      for j in 0..1
        if get_board_data(bx + i * dx , by + j * dy) == 0
          num += 1     
        end  
      end  
    end      
    return num
  end 

  
  #●　どの辺に近いcであるか
  def get_edge_near_c(x , y )
    return 0 unless cell_c?(x , y)
    all_edges.each do |edge|  
      return edge if inverse_board_coordinate_into_edge_coordinate(edge, 1 , 0 ) == [x , y]
    end  
    return 0
  end
  

  
  #●　角をとられるところしか打てないか
  def only_puttable_lose_corner?(color = cpu_color , board = @board)
    
    puttable = find_puttable_cell(color , board)
    puttable.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      return false if !corner_lose_put?(ix , iy , color, board) #&& around_corner_num(ix , iy) > 0
    end 
    return true
  
  end

  
  #●　どの角周辺で角をとられるところしか打てないときの思考
  def only_puttable_around_corner(x , y ,color, value)
    puttable = find_puttable_cell(color)
    corner_n = around_corner_num(x , y)
    return value if corner_n == 0
    value = puttable_around_corner(x , y ,corner_n ,color)
    if around_corner_empty_num(corner_n) % 2 == 1 
      value *= 100 
    end
    value *= 100 if cell_x?(x , y) 
    return value
  end   
  
  
  #●　埋まった角周辺における思考
  def puttable_around_nonempty_corner(x , y ,color , board ,value)
    return value unless cell_c_nonempty_corner?(x , y )
    ai_board = make_ai_board(x , y, color , board)
    value *= 4000  if some_corner_get_soon?(color,  ai_board)
    return value
  end  
  
  #●　埋まった角周辺のCであるか
  def cell_c_nonempty_corner?(x , y )
    return false unless cell_c?(x , y)
    corner = around_corner_num(x , y) 
    return get_data_corner_coordinate(corner, 0 , 0 ) != 0
    
  end  

  
   #●　その石がひっくり返される手が存在するか？
  def change_color_put_exist?(x , y , ocolor , board = @board)
    ai_board = []
    puttable2 = []
    color = get_board_data(x , y , board) 
    return false if color == 0 
    
    puttable2 = find_puttable_cell(ocolor , board )
    puttable2.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      ai_board.clear
      ai_board = make_ai_board(ix , iy ,ocolor , board )
      if get_board_data(x, y , ai_board ) == ocolor 
    
        return true
      end
    end
    return false
  end    
  
   #●　全滅をまねく手であるか?
  def exact_lose_put?(x , y , color = cpu_color )
    ai_board = []
    puttable = find_puttable_cell(op_color(color) , @ai_board )
    puttable.each do |i|
      ix = i % BOARDWIDTH
      iy = i / BOARDWIDTH
      ai_board = make_ai_board(ix , iy, op_color(color) , @ai_board)
      return true if reversi_end?(ai_board)
    end  
    return false
  end  
    #●　全滅させることのできる?
  def exact_win_put?(value )
    return value * 700000 if reversi_end?(@ai_board)
    return value  
      
  end   
end  


