// File: kobanium[P]Ray/src/mcts/UctSearch.cpp
// Function: ParallelUctSearch(thread_arg_t*)
static void
ParallelUctSearch( thread_arg_t *arg )
{
  const thread_arg_t *targ = (thread_arg_t *)arg;
  const int color = targ->color;
  bool interruption = false, enough_size = true;
  bool use_analysis = targ->lz_analysis_cs > 0 ? true : false;
  int winner = 0, interval = CRITICALITY_INTERVAL;
  game_info_t *game = AllocateGame();
  ray_clock::time_point analysis_timer;

  // スレッドIDが0のスレッドだけ別の処理をする
  // 探索回数が閾値を超える, または探索が打ち切られたらループを抜ける
  if (targ->thread_id == 0) {
    analysis_timer = ray_clock::now();

    do {
      // 探索回数を1回増やす
      IncrementPoCount();
      // 盤面のコピー
      CopyGame(game, targ->game);
      // 1回プレイアウトする
      UctSearch(game, color, mt[targ->thread_id], current_root, winner);
      // 探索を打ち切るか確認
      interruption = CheckInterruption(uct_node[current_root]);
      //interruption = InterruptionCheck();
      // ハッシュに余裕があるか確認
      enough_size = CheckRemainingHashSize();
      // OwnerとCriticalityを計算する
      if (GetPoCount() > interval) {
        CalculateOwner(color);
        CalculateCriticality(color);
        interval += CRITICALITY_INTERVAL;
      }

      if (use_analysis &&
          static_cast<int>(100 * GetSpendTime(analysis_timer)) > targ->lz_analysis_cs) {
        analysis_timer = ray_clock::now();
        PrintLeelaZeroAnalyze(&uct_node[current_root]);
      }

      if (IsTimeOver()) break;
    } while (IsSearchContinue() && !interruption && enough_size);
  } else {
    do {
      // 探索回数を1回増やす
      IncrementPoCount();
      // 盤面のコピー
      CopyGame(game, targ->game);
      // 1回プレイアウトする
      UctSearch(game, color, mt[targ->thread_id], current_root, winner);
      // 探索を打ち切るか確認
      interruption = CheckInterruption(uct_node[current_root]);
      //interruption = InterruptionCheck();
      // ハッシュに余裕があるか確認
      enough_size = CheckRemainingHashSize();

      if (IsTimeOver()) break;
    } while (IsSearchContinue() && !interruption && enough_size);
  }

  // メモリの解放
  FreeGame(game);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x14(%rbp)
movb $0x0, -0x15(%rbp)
movb $0x1, -0x16(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
testl %eax, %eax
setg %al
negb %al
andb $0x1, %al
movb %al, -0x17(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x64, -0x20(%rbp)
callq 0x9bce0
movq %rax, -0x28(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x8e6e0
movq -0x10(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x89fb7
callq 0x7090
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
callq 0x8f930
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x9c660
movq -0x28(%rbp), %rdi
movl -0x14(%rbp), %esi
movq -0x10(%rbp), %rax
movslq 0x8(%rax), %rax
leaq 0x1aac2c0d(%rip), %rdx  # 0x1ab4cac0
imulq $0x9c8, %rax, %rax      # imm = 0x9C8
addq %rax, %rdx
movl 0x1aac2bf5(%rip), %ecx  # 0x1ab4cab8
leaq -0x1c(%rbp), %r8
callq 0x8b610
movq 0x1aac2bdd(%rip), %rdi  # 0x1ab4cab0
movslq 0x1aac2bde(%rip), %rax  # 0x1ab4cab8
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
callq 0x8f950
andb $0x1, %al
movb %al, -0x15(%rbp)
callq 0x9fd70
andb $0x1, %al
movb %al, -0x16(%rbp)
callq 0x8f8a0
cmpl -0x20(%rbp), %eax
jle 0x89f1b
movl -0x14(%rbp), %edi
callq 0x8b9d0
movl -0x14(%rbp), %edi
callq 0x8bbc0
movl -0x20(%rbp), %eax
addl $0x64, %eax
movl %eax, -0x20(%rbp)
testb $0x1, -0x17(%rbp)
je 0x89f74
leaq -0x30(%rbp), %rdi
callq 0x8e710
movaps %xmm0, %xmm1
movsd 0x220e3(%rip), %xmm0    # 0xac018
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movq -0x10(%rbp), %rcx
cmpl 0x10(%rcx), %eax
jle 0x89f74
callq 0x7090
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x30(%rbp)
movq 0x1aac2b52(%rip), %rdi  # 0x1ab4cab0
movslq 0x1aac2b53(%rip), %rax  # 0x1ab4cab8
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
callq 0x22680
callq 0x8f820
testb $0x1, %al
jne 0x89f7f
jmp 0x89f81
jmp 0x89fb2
jmp 0x89f83
callq 0x8f850
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x41(%rbp)
jne 0x89f96
jmp 0x89fa7
xorl %eax, %eax
testb $0x1, -0x15(%rbp)
movb %al, -0x41(%rbp)
jne 0x89fa7
movb -0x16(%rbp), %al
movb %al, -0x41(%rbp)
movb -0x41(%rbp), %al
testb $0x1, %al
jne 0x89e88
jmp 0x8a069
jmp 0x89fb9
callq 0x8f930
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x9c660
movq -0x28(%rbp), %rdi
movl -0x14(%rbp), %esi
movq -0x10(%rbp), %rax
movslq 0x8(%rax), %rax
leaq 0x1aac2adc(%rip), %rdx  # 0x1ab4cac0
imulq $0x9c8, %rax, %rax      # imm = 0x9C8
addq %rax, %rdx
movl 0x1aac2ac4(%rip), %ecx  # 0x1ab4cab8
leaq -0x1c(%rbp), %r8
callq 0x8b610
movq 0x1aac2aac(%rip), %rdi  # 0x1ab4cab0
movslq 0x1aac2aad(%rip), %rax  # 0x1ab4cab8
imulq $0x4548, %rax, %rax     # imm = 0x4548
addq %rax, %rdi
callq 0x8f950
andb $0x1, %al
movb %al, -0x15(%rbp)
callq 0x9fd70
andb $0x1, %al
movb %al, -0x16(%rbp)
callq 0x8f820
testb $0x1, %al
jne 0x8a034
jmp 0x8a036
jmp 0x8a067
jmp 0x8a038
callq 0x8f850
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x42(%rbp)
jne 0x8a04b
jmp 0x8a05c
xorl %eax, %eax
testb $0x1, -0x15(%rbp)
movb %al, -0x42(%rbp)
jne 0x8a05c
movb -0x16(%rbp), %al
movb %al, -0x42(%rbp)
movb -0x42(%rbp), %al
testb $0x1, %al
jne 0x89fb9
jmp 0x8a069
movq -0x28(%rbp), %rdi
callq 0x9bd30
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax,%rax)