// File: kobanium[P]Ray/src/board/GoBoard.cpp
// Function: IsFalseEyeConnection(game_info_t const*, int, int)
static bool
IsFalseEyeConnection( const game_info_t *game, const int pos, const int color )
{
  // +++++XOO#
  // +++++XO+#
  // +++XXXOO#
  // ++XOOXXO#
  // +++O*OO*#
  // #########
  // シミュレーション中に上の局面の*を眼と認識せずに打つように,
  // ++++XXXX#
  // +++XXOOO#
  // +++XO+XO#
  // +++XOOO*#
  // #########
  // シミュレーション中に上の局面の*を眼と認識して打たないようにする.
  //
  // 隣接する2つの自分の連の呼吸点に共通するものがなければ打ち
  // 共通するものがあれば打たないようにしている.
  // 以下の局面は誤認識して打ってしまうので要対応.
  // ++++XXXX#
  // +++XXOOO#
  // +++XOX+O#
  // +++XO+XO#
  // +++XOOO*#
  // #########
  const string_t *string = game->string;
  const int *string_id = game->string_id;
  const char *board = game->board;
  const int other = GetOppositeColor(color);
  int id, neighbor, count, lib, libs = 0, lib_sum = 0, player_ids = 0, strings = 0;
  int neighbor4[4], player_id[4] = {0}, liberty[STRING_LIB_MAX], checked_string[4] = {0}, string_liberties[4] = {0};
  bool checked, already_checked;

  // 欠け眼を構成する連のIDを取り出す
  GetNeighbor4(neighbor4, pos);
  for (int i = 0; i < 4; i++) {
    checked = false;
    for (int j = 0; j < player_ids; j++) {
      if (player_id[j] == string_id[neighbor4[i]]) {
        checked = true;
      }
    }
    if (!checked) {
      player_id[player_ids++] = string_id[neighbor4[i]];
    }
  }

  // 斜め方向に取れる, または取れそうな石があったらfalseを返す
  for (int i = 0; i < 4; i++) {
    if (board[pos + cross[i]] == other) {
      id = string_id[pos + cross[i]];
      if (IsAlreadyCaptured(game, id, player_id, player_ids)) {
        return false;
      }
    }
  }

  // 隣接する座標が自分の連なら
  // その連の呼吸点を取り出す
  for (int i = 0; i < 4; i++) {
    if (board[neighbor4[i]] == color) {
      id = string_id[neighbor4[i]];
      if (string[id].libs == 2) {
        lib = string[id].lib[0];
        if (lib == pos) lib = string[id].lib[lib];
        if (IsSelfAtari(game, color, lib)) return true;
      }
      already_checked = false;
      for (int j = 0; j < strings; j++) {
        if (checked_string[j] == id) {
          already_checked = true;
          break;
        }
      }
      if (already_checked) continue;
      lib = string[id].lib[0];
      count = 0;
      while (lib != LIBERTY_END) {
        if (lib != pos) {
          checked = false;
          for (i = 0; i < libs; i++) {
            if (liberty[i] == lib) {
              checked = true;
              break;
            }
          }
          if (!checked) {
            liberty[libs + count] = lib;
            count++;
          }
        }
        lib = string[id].lib[lib];
      }
      libs += count;
      string_liberties[strings] = string[id].libs;
      checked_string[strings++] = id;
    }
  }

  // その連が持っている呼吸点を求める
  for (int i = 0; i < strings; i++) {
    lib_sum += string_liberties[i] - 1;
  }

  neighbor = string[checked_string[0]].neighbor[0];
  while (neighbor != NEIGHBOR_END) {
    if (string[neighbor].libs == 1 &&
        string[checked_string[1]].neighbor[neighbor] != 0) {
      return false;
    }
    neighbor = string[checked_string[0]].neighbor[neighbor];
  }

  // 隣接する連が一続きなら眼なのでfalseを返す
  if (strings == 1) {
    return false;
  }

  // 2つの連が呼吸点を共有していなければtrue
  // そうでなければfalseを返す
  if (libs == lib_sum) {
    return true;
  } else {
    return false;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xba0, %rsp            # imm = 0xBA0
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq -0x10(%rbp), %rax
addq $0x9620, %rax           # imm = 0x9620
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
addq $0x95720, %rax          # imm = 0x95720
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x43f8, %rax           # imm = 0x43F8
movq %rax, -0x30(%rbp)
movl -0x18(%rbp), %edi
callq 0x25810
movl %eax, -0x34(%rbp)
movl $0x0, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x72b0
leaq -0xb70(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x72b0
leaq -0xb80(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x72b0
leaq -0x70(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x9bc90
movl $0x0, -0xb88(%rbp)
cmpl $0x4, -0xb88(%rbp)
jge 0x9d7f8
movb $0x0, -0xb81(%rbp)
movl $0x0, -0xb8c(%rbp)
movl -0xb8c(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x9d7b5
movslq -0xb8c(%rbp), %rax
movl -0x80(%rbp,%rax,4), %eax
movq -0x28(%rbp), %rcx
movslq -0xb88(%rbp), %rdx
movslq -0x70(%rbp,%rdx,4), %rdx
cmpl (%rcx,%rdx,4), %eax
jne 0x9d7a2
movb $0x1, -0xb81(%rbp)
jmp 0x9d7a4
movl -0xb8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb8c(%rbp)
jmp 0x9d770
testb $0x1, -0xb81(%rbp)
jne 0x9d7e2
movq -0x28(%rbp), %rax
movslq -0xb88(%rbp), %rcx
movslq -0x70(%rbp,%rcx,4), %rcx
movl (%rax,%rcx,4), %ecx
movl -0x50(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x50(%rbp)
cltq
movl %ecx, -0x80(%rbp,%rax,4)
jmp 0x9d7e4
movl -0xb88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb88(%rbp)
jmp 0x9d752
movl $0x0, -0xb90(%rbp)
cmpl $0x4, -0xb90(%rbp)
jge 0x9d88a
movq -0x30(%rbp), %rax
movl -0x14(%rbp), %ecx
movslq -0xb90(%rbp), %rsi
leaq 0x1ab35bb0(%rip), %rdx  # 0x1abd33d0
addl (%rdx,%rsi,4), %ecx
movslq %ecx, %rcx
movsbl (%rax,%rcx), %eax
cmpl -0x34(%rbp), %eax
jne 0x9d874
movq -0x28(%rbp), %rax
movl -0x14(%rbp), %ecx
movslq -0xb90(%rbp), %rsi
leaq 0x1ab35b8c(%rip), %rdx  # 0x1abd33d0
addl (%rdx,%rsi,4), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rdi
movl -0x38(%rbp), %esi
leaq -0x80(%rbp), %rdx
movl -0x50(%rbp), %ecx
callq 0xa96d0
testb $0x1, %al
jne 0x9d869
jmp 0x9d872
movb $0x0, -0x1(%rbp)
jmp 0x9dbb0
jmp 0x9d874
jmp 0x9d876
movl -0xb90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb90(%rbp)
jmp 0x9d802
movl $0x0, -0xb94(%rbp)
cmpl $0x4, -0xb94(%rbp)
jge 0x9dac3
movq -0x30(%rbp), %rax
movslq -0xb94(%rbp), %rcx
movslq -0x70(%rbp,%rcx,4), %rcx
movsbl (%rax,%rcx), %eax
cmpl -0x18(%rbp), %eax
jne 0x9daad
movq -0x28(%rbp), %rax
movslq -0xb94(%rbp), %rcx
movslq -0x70(%rbp,%rcx,4), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
cmpl $0x2, 0x4(%rax)
jne 0x9d94b
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movswl 0x8(%rax), %eax
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x14(%rbp), %eax
jne 0x9d92b
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movslq -0x44(%rbp), %rcx
movswl 0x8(%rax,%rcx,2), %eax
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rdi
movl -0x18(%rbp), %esi
movl -0x44(%rbp), %edx
callq 0xa8e70
testb $0x1, %al
jne 0x9d940
jmp 0x9d949
movb $0x1, -0x1(%rbp)
jmp 0x9dbb0
jmp 0x9d94b
movb $0x0, -0xb82(%rbp)
movl $0x0, -0xb98(%rbp)
movl -0xb98(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x9d996
movslq -0xb98(%rbp), %rax
movl -0xb70(%rbp,%rax,4), %eax
cmpl -0x38(%rbp), %eax
jne 0x9d983
movb $0x1, -0xb82(%rbp)
jmp 0x9d996
jmp 0x9d985
movl -0xb98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb98(%rbp)
jmp 0x9d95c
testb $0x1, -0xb82(%rbp)
je 0x9d9a4
jmp 0x9daaf
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movswl 0x8(%rax), %eax
movl %eax, -0x44(%rbp)
movl $0x0, -0x40(%rbp)
cmpl $0x2b7, -0x44(%rbp)     # imm = 0x2B7
je 0x9da6d
movl -0x44(%rbp), %eax
cmpl -0x14(%rbp), %eax
je 0x9da4a
movb $0x0, -0xb81(%rbp)
movl $0x0, -0xb94(%rbp)
movl -0xb94(%rbp), %eax
cmpl -0x48(%rbp), %eax
jge 0x9da24
movslq -0xb94(%rbp), %rax
movl -0xb60(%rbp,%rax,4), %eax
cmpl -0x44(%rbp), %eax
jne 0x9da11
movb $0x1, -0xb81(%rbp)
jmp 0x9da24
jmp 0x9da13
movl -0xb94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb94(%rbp)
jmp 0x9d9ea
testb $0x1, -0xb81(%rbp)
jne 0x9da48
movl -0x44(%rbp), %ecx
movl -0x48(%rbp), %eax
addl -0x40(%rbp), %eax
cltq
movl %ecx, -0xb60(%rbp,%rax,4)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x9da4a
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movslq -0x44(%rbp), %rcx
movswl 0x8(%rax,%rcx,2), %eax
movl %eax, -0x44(%rbp)
jmp 0x9d9c4
movl -0x40(%rbp), %eax
addl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x20(%rbp), %rax
movslq -0x38(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movl 0x4(%rax), %ecx
movslq -0x54(%rbp), %rax
movl %ecx, -0xb80(%rbp,%rax,4)
movl -0x38(%rbp), %ecx
movl -0x54(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x54(%rbp)
cltq
movl %ecx, -0xb70(%rbp,%rax,4)
jmp 0x9daaf
movl -0xb94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb94(%rbp)
jmp 0x9d894
movl $0x0, -0xb9c(%rbp)
movl -0xb9c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x9db00
movslq -0xb9c(%rbp), %rax
movl -0xb80(%rbp,%rax,4), %eax
subl $0x1, %eax
addl -0x4c(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl -0xb9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb9c(%rbp)
jmp 0x9dacd
movq -0x20(%rbp), %rax
movslq -0xb70(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movswl 0x57c(%rax), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x11f, -0x3c(%rbp)     # imm = 0x11F
je 0x9db92
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
cmpl $0x1, 0x4(%rax)
jne 0x9db6c
movq -0x20(%rbp), %rax
movslq -0xb6c(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movslq -0x3c(%rbp), %rcx
movswl 0x57c(%rax,%rcx,2), %eax
cmpl $0x0, %eax
je 0x9db6c
movb $0x0, -0x1(%rbp)
jmp 0x9dbb0
movq -0x20(%rbp), %rax
movslq -0xb70(%rbp), %rcx
imulq $0x7c8, %rcx, %rcx      # imm = 0x7C8
addq %rcx, %rax
movslq -0x3c(%rbp), %rcx
movswl 0x57c(%rax,%rcx,2), %eax
movl %eax, -0x3c(%rbp)
jmp 0x9db1f
cmpl $0x1, -0x54(%rbp)
jne 0x9db9e
movb $0x0, -0x1(%rbp)
jmp 0x9dbb0
movl -0x48(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jne 0x9dbac
movb $0x1, -0x1(%rbp)
jmp 0x9dbb0
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xba0, %rsp            # imm = 0xBA0
popq %rbp
retq
nop