/* Use one of the faster functions if available */
static void probabilityFunctionDispatch(const AstronomyParameters* ap, const CLRequest* clr)
{
    int hasSSE2 = FALSE, hasSSE3 = FALSE;
    int useSSE2 = FALSE, useSSE3 = FALSE;

    getSSELevelSupport(&hasSSE2, &hasSSE3);

    if (clr->verbose)
    {
        warn("CPU features: SSE2 = %d, SSE3 = %d\n"
             "Forcing: SSE2 = %d, SSE3 = %d, x87 = %d\n",
             hasSSE2, hasSSE3,
             clr->forceSSE2, clr->forceSSE3, clr->forceX87);
    }

    if (!clr->forceSSE2 && !clr->forceSSE3 && !clr->forceX87)
    {
        /* Default to using highest capability if not forcing anything */
        useSSE3 = hasSSE3;
        useSSE2 = hasSSE2;
    }
    else if (clr->forceSSE2)
    {
        useSSE2 = TRUE;
    }
    else if (clr->forceSSE3)
    {
        useSSE3 = TRUE;
    }
    else if (clr->forceX87)
    {
      #if MW_IS_X86_32
        useSSE2 = useSSE3 = FALSE;
      #elif MW_IS_X86_64
        useSSE2 = TRUE;  /* Ignore flag */
      #endif
    }

    if (useSSE3)  /* Precedence to higher level */
    {
        warn("Using SSE3 path\n");
        probabilityFunc = initProbabilities_SSE3(ap, clr->forceNoIntrinsics);
    }
    else if (useSSE2)
    {
        warn("Using SSE2 path\n");
        probabilityFunc = initProbabilities_SSE2(ap, clr->forceNoIntrinsics);
    }
    else
    {
      #if !MW_NO_X87_EVER
        warn("Using x87 path\n");
        probabilityFunc = initProbabilities(ap, clr->forceNoIntrinsics);
      #else
        mw_unreachable();
      #endif
    }

    if (!probabilityFunc)
    {
        mw_panic("Probability function not set!:\n"
                 "  Has SSE2             = %d\n"
                 "  Has SSE3             = %d\n"
                 "  Forced SSE3          = %d\n"
                 "  Forced SSE2          = %d\n"
                 "  Forced x87           = %d\n"
                 "  Forced no intrinsics = %d\n"
                 "  Arch                 = %s\n",
                 hasSSE2, hasSSE3,
                 clr->forceSSE3, clr->forceSSE2, clr->forceX87, clr->forceNoIntrinsics,
                 ARCH_STRING);
    }
}
static void probabilityFunctionDispatch(const AstronomyParameters* ap, const CLRequest* clr)
{
    probabilityFunc = initProbabilities(ap, clr->forceNoIntrinsics);
}
  double SoftmaxPolicyPlayout::operator()(Common::Color turn_color, Go::Board *board, int depth, bool doUndo) {

    //initProbabilities(board);

    const static int playing_count_offset = 200;

    m_sequence.resize(0);
    
    int currentTurn = turn_color;
    int board_size = board->getSize();
    int max_playing = board_size*board_size + playing_count_offset;
    Common::Point prev_hand(POINT_NULL);

    // enumerate hand candidates
    int playoutHandCount = 0;

    int table_index = turn_color == BLACK ? 0 : 1;
    double *tables[] = {m_probTableBlack, m_probTableWhite};
    bool doublepass = false;

    // first 2 moves
    for (int i=0; i<2; i++)
    {
      initProbabilities(board, currentTurn, tables[table_index], currentTurn == BLACK ? m_featureTableBlack : m_featureTableWhite);
      Point selected_hand = selectOneMoveAccordingToProbabilityTable(board, tables[table_index]);
      board->put(selected_hand, currentTurn, true);

      m_sequence.push_back(selected_hand);

      if (prev_hand == PASS && selected_hand == PASS) {
        doublepass = true;
      }

      prev_hand = selected_hand;
      table_index = 1-table_index;
      currentTurn = Board::flipColor(currentTurn);
      playoutHandCount++;
    }

    //cerr << "-------------" <<  endl;
    for (; playoutHandCount<max_playing && !doublepass; playoutHandCount++) {

      // select hand according to the table
      updateProbabilitiesBeforeAction(board, currentTurn);
      // if (playoutHandCount >= 63 && playoutHandCount <= 96) {
      //   board->printToErr();
      //   printProbabilityTableToErr(board);
      // }
      
      Point selected_hand = selectOneMoveAccordingToProbabilityTable(board, tables[table_index]);
      
      Board::PutType err;
#ifdef DEBUG
      if ((err = board->checkLegalHand(selected_hand, currentTurn, Board::flipColor(currentTurn))) != Board::PUT_LEGAL) {
        board->printToErr();
        cerr << "selected move = " << board->pointToXY(selected_hand).first << "," << board->pointToXY(selected_hand).second << " turn = " << (currentTurn == BLACK ? "black" : "white") << " error = " << err << endl;
        cerr << "sequence new to old" << endl;
        for (int i=board->getHistoryCount(); i>=0; i--) {
          const Board::MoveChangeEntry *entry = board->getHistory(i);
          if (entry) {
            int killedBlocks = 0;
            for (killedBlocks=0; entry->m_killedBlocks[killedBlocks] && killedBlocks < 4; killedBlocks++) {}
            if (killedBlocks > 0) {
              int x = board->pointToXY(entry->m_putPos).first;
              int y = board->pointToXY(entry->m_putPos).second;
              cerr << "last " << i << " move = " << x << "," << y << " killed blocks = " << killedBlocks << " put color = " << entry->m_putColor << endl;
            }
          }
        }
        printProbabilityTableToErr(board);
        tables[table_index][selected_hand] = 0;
      }
#endif
      err = board->put(selected_hand, currentTurn, true);

      assert (err == Board::PUT_LEGAL);
      m_sequence.push_back(selected_hand);

      // double pass
      if (selected_hand == PASS && prev_hand == PASS) {
        // end game
        doublepass = true;
      } else {      
        prev_hand = selected_hand;
        table_index = 1-table_index;
        currentTurn = Board::flipColor(currentTurn);
      }
    }

    double score = board->countScore(turn_color);
    if (doUndo) {
      // undo changes
      for (int i=0; i<playoutHandCount; i++) {
        board->undo();
      }
    }
    //std::cerr << playoutHandCount << endl;
    return score;    
  }