// File: kobanium[P]Ray/src/mcts/UctSearch.cpp
// Function: UctSearch(game_info_t*, int, std::mersenne_twister_engine<unsigned long, 64ul, 312ul, 156ul, 31ul, 13043109905998158313ul, 29ul, 6148914691236517205ul, 17ul, 8202884508482404352ul, 37ul, 18444473444759240704ul, 43ul, 6364136223846793005ul>&, int, int&)
static int 
UctSearch( game_info_t *game, int color, std::mt19937_64 &mt, int current, int &winner )
{
  int result = 0, next_index;
  double score;
  child_node_t *uct_child = uct_node[current].child;  

  // 現在見ているノードをロック
  mutex_nodes[current].lock();
  // UCB値最大の手を求める
  next_index = SelectMaxUcbChild(current, color, mt);
  // 選んだ手を着手
  PutStone(game, uct_child[next_index].pos, color);
  // 色を入れ替える
  color = GetOppositeColor(color);

  if ((uct_child[next_index].move_count + uct_child[next_index].virtual_loss) < GetExpandThreshold(game)) {
    AddVirtualLoss(uct_node[current], uct_child[next_index]);

    memcpy(game->seki, uct_node[current].seki, sizeof(bool) * BOARD_MAX);
    
    // 現在見ているノードのロックを解除
    mutex_nodes[current].unlock();

    // 終局まで対局のシミュレーション
    Simulation(game, color, mt);

    // 隅の曲がり四目の確認
    CheckBentFourInTheCorner(game);
    
    // コミを含めない盤面のスコアを求める
    score = static_cast<double>(CalculateScore(game));
    
    // コミを考慮した勝敗
    if (my_color == S_BLACK) {
      if (score - dynamic_komi[my_color] >= 0) {
        result = (color == S_BLACK ? 0 : 1);
        winner = S_BLACK;
      } else {
        result = (color == S_WHITE ? 0 : 1);
        winner = S_WHITE;
      }
    } else {
      if (score - dynamic_komi[my_color] > 0) {
        result = (color == S_BLACK ? 0 : 1);
        winner = S_BLACK;
      } else {
        result = (color == S_WHITE ? 0 : 1);
        winner = S_WHITE;
      }
    }
    // 統計情報の記録
    Statistic(game, winner);
  } else {
    // Virtual Lossを加算
    AddVirtualLoss(uct_node[current], uct_child[next_index]);
    // ノードの展開の確認
    if (uct_child[next_index].index == -1) {
      // ノードの展開中はロック
      mutex_expand.lock();
      // ノードの展開
      uct_child[next_index].index = ExpandNode(game, color, current);
      // ノード展開のロックの解除
      mutex_expand.unlock();
    }
    // 現在見ているノードのロックを解除
    mutex_nodes[current].unlock();
    // 手番を入れ替えて1手深く読む
    result = UctSearch(game, color, mt, uct_child[next_index].index, winner);
  }

  // 探索結果の反映
  UpdateResult(uct_node[current], uct_child[next_index], result);

  mutex_nodes[current].lock();
  UpdateOwnership(uct_node[current], game, GetOppositeColor(color));
  mutex_nodes[current].unlock();

  return 1 - result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq %r8, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movq 0x1aac1478(%rip), %rax  # 0x1ab4cab0
movslq -0x1c(%rbp), %rcx
imulq $0x4548, %rcx, %rcx     # imm = 0x4548
addq %rcx, %rax
addq $0x1c, %rax
movq %rax, -0x40(%rbp)
movq 0x1aae8c23(%rip), %rdi  # 0x1ab74278
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x66e50
movl -0x1c(%rbp), %edi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
callq 0x8bf00
movl %eax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rax
movslq -0x30(%rbp), %rcx
imulq $0x1c, %rcx, %rcx
addq %rcx, %rax
movswl (%rax), %esi
movl -0xc(%rbp), %edx
callq 0x9dbc0
movl -0xc(%rbp), %edi
callq 0x25810
movl %eax, -0xc(%rbp)
movq -0x40(%rbp), %rdi
movslq -0x30(%rbp), %rax
imulq $0x1c, %rax, %rax
addq %rax, %rdi
addq $0x4, %rdi
callq 0x25780
movl %eax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
movslq -0x30(%rbp), %rax
imulq $0x1c, %rax, %rax
addq %rax, %rdi
addq $0x8, %rdi
callq 0x25780
movl %eax, %ecx
movl -0x48(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x44(%rbp)
movq -0x8(%rbp), %rdi
callq 0x8c3a0
movl %eax, %ecx
movl -0x44(%rbp), %eax
cmpl %ecx, %eax
jge 0x8b86a
movq 0x1aac13b6(%rip), %rdi  # 0x1ab4cab0
movslq -0x1c(%rbp), %rax
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
movq -0x40(%rbp), %rsi
movslq -0x30(%rbp), %rax
imulq $0x1c, %rax, %rax
addq %rax, %rsi
callq 0x88040
movq -0x8(%rbp), %rdi
addq $0x97029, %rdi          # imm = 0x97029
movq 0x1aac1382(%rip), %rsi  # 0x1ab4cab0
movslq -0x1c(%rbp), %rax
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rsi
addq $0x27b4, %rsi           # imm = 0x27B4
movl $0x349, %edx            # imm = 0x349
callq 0x7430
movq 0x1aae8b24(%rip), %rdi  # 0x1ab74278
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x66e80
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
callq 0x85240
movq -0x8(%rbp), %rdi
callq 0x9e720
movq -0x8(%rbp), %rdi
callq 0x9ea20
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x38(%rbp)
cmpl $0x1, 0x1aaf13d2(%rip)  # 0x1ab7cb68
jne 0x8b7f7
movsd -0x38(%rbp), %xmm0
movslq 0x1aaf13c4(%rip), %rcx  # 0x1ab7cb68
leaq 0x1aaf2905(%rip), %rax  # 0x1ab7e0b0
subsd (%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x8b7d8
movl -0xc(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x1, %edx
cmovel %ecx, %eax
movl %eax, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movl $0x1, (%rax)
jmp 0x8b7f5
movl -0xc(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x2, %edx
cmovel %ecx, %eax
movl %eax, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movl $0x2, (%rax)
jmp 0x8b856
movsd -0x38(%rbp), %xmm0
movslq 0x1aaf1365(%rip), %rcx  # 0x1ab7cb68
leaq 0x1aaf28a6(%rip), %rax  # 0x1ab7e0b0
subsd (%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x8b837
movl -0xc(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x1, %edx
cmovel %ecx, %eax
movl %eax, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movl $0x1, (%rax)
jmp 0x8b854
movl -0xc(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x2, %edx
cmovel %ecx, %eax
movl %eax, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movl $0x2, (%rax)
jmp 0x8b856
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
movl (%rax), %esi
callq 0x8c410
jmp 0x8b923
movq 0x1aac123f(%rip), %rdi  # 0x1ab4cab0
movslq -0x1c(%rbp), %rax
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
movq -0x40(%rbp), %rsi
movslq -0x30(%rbp), %rax
imulq $0x1c, %rax, %rax
addq %rax, %rsi
callq 0x88040
movq -0x40(%rbp), %rax
movslq -0x30(%rbp), %rcx
imulq $0x1c, %rcx, %rcx
addq %rcx, %rax
cmpl $-0x1, 0x10(%rax)
jne 0x8b8e3
leaq 0x1aaf18c1(%rip), %rdi  # 0x1ab7d170
callq 0x66e50
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x1c(%rbp), %edx
callq 0x8c510
movl %eax, %ecx
movq -0x40(%rbp), %rax
movslq -0x30(%rbp), %rdx
imulq $0x1c, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x10(%rax)
leaq 0x1aaf1892(%rip), %rdi  # 0x1ab7d170
callq 0x66e80
movq 0x1aae898e(%rip), %rdi  # 0x1ab74278
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x66e80
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
movq -0x40(%rbp), %rax
movslq -0x30(%rbp), %rcx
imulq $0x1c, %rcx, %rcx
addq %rcx, %rax
movl 0x10(%rax), %ecx
movq -0x28(%rbp), %r8
callq 0x8b610
movl %eax, -0x2c(%rbp)
movq 0x1aac1186(%rip), %rdi  # 0x1ab4cab0
movslq -0x1c(%rbp), %rax
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
movq -0x40(%rbp), %rsi
movslq -0x30(%rbp), %rax
imulq $0x1c, %rax, %rax
addq %rax, %rsi
movl -0x2c(%rbp), %edx
callq 0x88080
movq 0x1aae8922(%rip), %rdi  # 0x1ab74278
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x66e50
movq 0x1aac1143(%rip), %rax  # 0x1ab4cab0
movslq -0x1c(%rbp), %rcx
imulq $0x4548, %rcx, %rcx     # imm = 0x4548
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
movl -0xc(%rbp), %edi
callq 0x25810
movq -0x58(%rbp), %rdi
movq -0x50(%rbp), %rsi
movl %eax, %edx
callq 0x88350
movq 0x1aae88d3(%rip), %rdi  # 0x1ab74278
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x66e80
movl $0x1, %eax
subl -0x2c(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)