SgHashCode SequenceHash::Hash(const PointSequence& seq)
{
    BenzeneAssert(seq.size() < (std::size_t)BITSETSIZE);
    const HashData& data = GetHashData();
    SgHashCode ret;
    for (std::size_t i = 0; i < seq.size(); ++i)
        ret.Xor(data.m_hashes[i][seq[i]]);
    return ret;
}
void GameUtil::HistoryToSequence(const MoveSequence& history, 
                                 PointSequence& sequence)
{
    sequence.clear();
    for (MoveSequence::const_iterator it = history.begin(); 
         it != history.end(); ++it)
    {    
        const Move& move = *it;
        sequence.push_back(move.Point());
    }
}
void DfpnSolver::GetPVFromHash(PointSequence& pv)
{
    // to do: SgAssertRestore r(state of search in subclass);
    int nuMoves = 0;
    for (;; ++nuMoves) 
    {
        DfpnData data;
        if (  ! TTRead(data)
           || data.m_bestMove == SG_NULLMOVE
           )
            break;
        pv.push_back(data.m_bestMove);
        PlayMove(data.m_bestMove);
    }
    while (--nuMoves >= 0)
    	UndoMove();
}
// ****************************************************************************
//  Method:  PointSequenceList::GetNextSequence
//
//  Purpose:
//    Extract another sequence from the connectivity array and return it
//    as a PointSequence.  Skip repeated adjacent points.
//
//  Returns:  true if we found another sequence; false otherwise
//
//  Programmer:  Jeremy Meredith
//  Creation:    November  1, 2002
//
//  Modifications:
//    Rich Cook and Hank Childs, Thu Oct  2 16:32:55 PDT 2008
//    Added support for loops.
//
//    Eric Brugger, Tue Dec 29 16:35:34 PST 2009
//    I modified the logic that looks for loops to only consider points
//    that have 2 neighbors.  Previously it would have considered points
//    with no neighbors, which caused it to reference uninitialized memory.
//
//    Jean Favre, Tue May  7 16:38:37 CEST 2013
//    I modified the calls to GetPoint() to use the other variant of the call
//    with two arguments. The previous version would never succeed in the test
//    to remove sequential identical points.
//    Used vtkIdType where needed
// ****************************************************************************
bool
vtkConnectedTubeFilter::PointSequenceList::GetNextSequence(PointSequence &seq)
{
    // index is already set by InitTraversal and previous calls to this fn
    for (; index < len; index++)
    {
        // if numneighbors is 1, then this is a start point
        if (((lookforloops && numneighbors[index] == 2) ||
              numneighbors[index] == 1) && !visited[index])
        {
            vtkIdType current = index;
            vtkIdType previous = -1;
            seq.Init(len);
            seq.Add(current, cellindex[current]);
            visited[current] = true;
            while (true)
            {
                vtkIdType n1       = connectivity[0][current];
                vtkIdType n2       = connectivity[1][current];
                vtkIdType next     = (n1 == previous) ? n2 : n1;
                previous = current;
                current = next;

 
                // we must skip any sequential identical points:
                // 1) they are useless, and 2) they mess up calculations
                double prePt[3];
                double curPt[3];
                pts->GetPoint(previous, prePt);
                pts->GetPoint(current, curPt);
                if (prePt[0] != curPt[0] ||
                    prePt[1] != curPt[1] ||
                    prePt[2] != curPt[2])
                {
                    seq.Add(current, cellindex[current]);
                }

                // check for a loop (AFTER adding the node again...)
                if (lookforloops && visited[current]) 
                {
                    break; 
                }
                visited[current] = true;

                bool endpoint = (numneighbors[current] == 1);
                if (endpoint)
                    break;
            }

            // We may have one duplicated cell index due to the way the
            // connectivity was built -- shift them all down by one from
            // the right spot, so the only duplicated one is the last one.
            for (int i=1; i<seq.length-1; i++)
            {
                if (seq.cellindex[i-1] == seq.cellindex[i])
                    seq.cellindex[i] = seq.cellindex[i+1];
            }

            // true ==> success; got another sequence
            return true;
        }
    }

    if (index == len && !lookforloops) 
    {
        lookforloops = true; 
        index=0; 
        return GetNextSequence(seq);
    }

    // false ==> failed; no more sequences
    return false;
}
inline void DfsSolutionSet::SetPV(HexPoint cell, const PointSequence& old)
{
    pv.clear();
    pv.push_back(cell);
    pv.insert(pv.end(), old.begin(), old.end());
}
inline void DfsSolutionSet::SetPV(HexPoint cell)
{
    pv.clear();
    pv.push_back(cell);
}
/** Does a 1-ply search.

    For each move in the consider set, if the move is a win, returns
    true and the move. If the move is a loss, prune it out of the
    consider set if there are non-losing moves in the consider set.
    If all moves are losing, perform no pruning, search will resist.

    Returns true if there is a win, false otherwise. 

    @todo Is it true that MoHex will resist in the strongest way
    possible?
*/
bool MoHexPlayer::PerformPreSearch(HexBoard& brd, HexColor color, 
                                   bitset_t& consider, double maxTime, 
                                   PointSequence& winningSequence)
{
   
    bitset_t losing;
    HexColor other = !color;
    PointSequence seq;
    bool foundWin = false;

    SgTimer elapsed;
    Resistance resist;
    resist.Evaluate(brd);
    std::vector<HexPoint> moves;
    SortConsiderSet(consider, resist, moves);
    for (std::size_t i = 0; i < moves.size() && !foundWin; ++i) 
    {
        if (elapsed.GetTime() > maxTime)
        {
            LogInfo() << "PreSearch: max time reached "
                      << '(' << i << '/' << moves.size() << ").\n";
            break;
        }
        brd.PlayMove(color, moves[i]);
        seq.push_back(moves[i]);
        if (EndgameUtil::IsLostGame(brd, other)) // Check for winning move
        {
            winningSequence = seq;
            foundWin = true;
        }	
        else if (EndgameUtil::IsWonGame(brd, other))
            losing.set(moves[i]);
        seq.pop_back();
        brd.UndoMove();
    }

    // Abort if we found a one-move win
    if (foundWin)
        return true;

    // Backing up cannot cause this to happen, right? 
    BenzeneAssert(!EndgameUtil::IsDeterminedState(brd, color));

    // Use the backed-up ice info to shrink the moves to consider
    if (m_backup_ice_info) 
    {
        bitset_t new_consider 
            = EndgameUtil::MovesToConsider(brd, color) & consider;

        if (new_consider.count() < consider.count()) 
        {
            consider = new_consider;       
            LogFine() << "$$$$$$ new moves to consider $$$$$$" 
                      << brd.Write(consider) << '\n';
        }
    }

    // Subtract any losing moves from the set we consider, unless all of them
    // are losing (in which case UCT search will find which one resists the
    // loss well).
    if (losing.any()) 
    {
	if (BitsetUtil::IsSubsetOf(consider, losing)) 
	    LogInfo() << "************************************\n"
                      << " All UCT root children are losing!!\n"
                      << "************************************\n";
        else 
        {
            LogFine() << "Removed losing moves: " << brd.Write(losing) << '\n';
	    consider = consider - losing;
	}
    }

    BenzeneAssert(consider.any());
    LogInfo() << "Moves to consider:\n" << brd.Write(consider) << '\n';
    return false;
}