Example #1
0
bool BoardGenerator::handleNakedPairs(int round){
    for (int position=0; position<BOARD_SIZE; position++){
        int possibilities = countPossibilities(position);
        if (possibilities == 2){
            int row = cellToRow(position);
            int column = cellToColumn(position);
            int section = cellToSectionStartCell(position);
            for (int position2=position; position2<BOARD_SIZE; position2++){
                if (position != position2){
                    int possibilities2 = countPossibilities(position2);
                    if (possibilities2 == 2 && arePossibilitiesSame(position, position2)){
                        if (row == cellToRow(position2)){
                            bool doneSomething = false;
                            for (int column2=0; column2<9; column2++){
                                int position3 = rowColumnToCell(row,column2);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_ROW, 0, position));
                                return true;
                            }
                        }
                        if (column == cellToColumn(position2)){
                            bool doneSomething = false;
                            for (int row2=0; row2<9; row2++){
                                int position3 = rowColumnToCell(row2,column);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_COLUMN, 0, position));
                                return true;
                            }
                        }
                        if (section == cellToSectionStartCell(position2)){
                            bool doneSomething = false;
                            int secStart = cellToSectionStartCell(position);
                            {for (int i=0; i<3; i++){
                                    for (int j=0; j<3; j++){
                                        int position3=secStart+i+(9*j);
                                        if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                            doneSomething = true;
                                        }
                                    }
                                }}
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_SECTION, 0, position));
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }
    return false;
}
Example #2
0
/**
 * Transforms the board by performing a move
 *
 * It doesn't check that the move is valid, so you should only use
 * it with moves returned by findPossibleMoves
 * \param pMove the move to perform
 */
void GameState::doMove(const Move &pMove)
{
    if (pMove.isJump())
    {
        // Row and column of source cell
        int sr = cellToRow(pMove[0]);
        int sc = cellToCol(pMove[0]);

        // Perform all jumps
        for(unsigned i=1;i<pMove.length();++i)
        {
            // Destination cell
            int dr = cellToRow(pMove[i]);
            int dc = cellToCol(pMove[i]);

            // Move the jumping piece
            at(pMove[i]) = at(pMove[i-1]);
            at(pMove[i-1]) = CELL_EMPTY;

            // Promote to king if we should
            if ((dr==7 && (at(pMove[i])&CELL_RED)) || (dr==0 && (at(pMove[i])&CELL_WHITE)))
                at(pMove[i])|=CELL_KING;

            // Remove the piece being jumped over
            at(rowColToCell((sr+dr)>>1,(sc+dc)>>1)) = CELL_EMPTY;

            // Prepare for next jump
            sr = dr;
            sc = dc;
        }

        // Reset number of moves left until draw
        mMovesUntilDraw = cMovesUntilDraw;
    }
Example #3
0
/**
 * Tries to make a move from a certain position
 *
 * \param pMoves vector where the valid moves will be inserted
 * \param pCell the cell where the move is tried from
 * \param pOther the \ref ECell code corresponding to the player
 * who is not making the move
 * \param pKing true if the piece is a king
 */
void GameState::tryMove(std::vector<Move> &pMoves, int pCell, bool pKing) const
{
    int lR=cellToRow(pCell);
    int lC=cellToCol(pCell);
    // Try moving downwards
    if(mNextPlayer==CELL_RED||pKing)
    {
        // Try moving right
        if(at(lR+1,lC-1)==CELL_EMPTY)
            pMoves.push_back(Move(pCell,rowColToCell(lR+1,lC-1)));
        //try moving left
        if(at(lR+1,lC+1)==CELL_EMPTY)
            pMoves.push_back(Move(pCell,rowColToCell(lR+1,lC+1)));
    }
    // Try moving upwards
    if(mNextPlayer==CELL_WHITE||pKing)
    {
        // Try moving right
        if(at(lR-1,lC-1)==CELL_EMPTY)
            pMoves.push_back(Move(pCell,rowColToCell(lR-1,lC-1)));
        // Try moving left
        if(at(lR-1,lC+1)==CELL_EMPTY)
            pMoves.push_back(Move(pCell,rowColToCell(lR-1,lC+1)));
    }
}
Example #4
0
/**
 * Mark the given value at the given position.  Go through
 * the row, column, and section for the position and remove
 * the value from the possibilities.
 *
 * @param position Position into the board (0-80)
 * @param round Round to mark for rollback purposes
 * @param value The value to go in the square at the given position
 */
void BoardGenerator::mark(int position, int round, int value){
    if (solution[position] != 0) throw ("Marking position that already has been marked.");
    if (solutionRound[position] !=0) throw ("Marking position that was marked another round.");
    int valIndex = value-1;
    solution[position] = value;

    int possInd = getPossibilityIndex(valIndex,position);
    if (possibilities[possInd] != 0) throw ("Marking impossible position.");

    // Take this value out of the possibilities for everything in the row
    solutionRound[position] = round;
    int rowStart = cellToRow(position)*9;
    for (int col=0; col<COL_HEIGHT; col++){
        int rowVal=rowStart+col;
        int valPos = getPossibilityIndex(valIndex,rowVal);
        if (possibilities[valPos] == 0){
            possibilities[valPos] = round;
        }
    }

    // Take this value out of the possibilities for everything in the column
    int colStart = cellToColumn(position);
    {for (int i=0; i<9; i++){
            int colVal=colStart+(9*i);
            int valPos = getPossibilityIndex(valIndex,colVal);
            if (possibilities[valPos] == 0){
                possibilities[valPos] = round;
            }
        }}

    // Take this value out of the possibilities for everything in section
    int secStart = cellToSectionStartCell(position);
    {for (int i=0; i<3; i++){
            for (int j=0; j<3; j++){
                int secVal=secStart+i+(9*j);
                int valPos = getPossibilityIndex(valIndex,secVal);
                //cout << "Sec Start: " << secStart << " Sec Value: " << secVal << " Value Position: " << valPos << endl;
                if (possibilities[valPos] == 0){
                    possibilities[valPos] = round;
                }
            }
        }}

    //This position itself is determined, it should have possibilities.
    {for (int valIndex=0; valIndex<9; valIndex++){
            int valPos = getPossibilityIndex(valIndex,position);
            if (possibilities[valPos] == 0){
                possibilities[valPos] = round;
            }
        }}

    //cout << "Col Start: " << colStart << " Row Start: " << rowStart << " Section Start: " << secStart<< " Value: " << value << endl;
    //printPossibilities();
}
Example #5
0
/**
 * Returns a list of all valid moves for \p pWho
 *
 * \param pMoves a vector where the list of moves will be appended
 * \param pWho the \ref ECell code (CELL_OWN or CELL_OTHER) of the
 * player making the move
 */
void GameState::findPossibleMoves(std::vector<GameState> &pStates) const
{
    pStates.clear();

    if (mLastMove.isEOG())
        return;

    if (mMovesUntilDraw <= 0)
    {
        pStates.push_back(GameState(*this, Move(Move::MOVE_DRAW)));
        return;
    }

    // Normal moves are forbidden if any jump is found
    bool lFound=false;
    int lPieces[cPlayerPieces];
    uint8_t lMoveBuffer[cPlayerPieces];
    std::vector<Move> lMoves;
    int lNumPieces=0;
    for (int i = 1; i <= cSquares; ++i)
    {
        // Is this a piece which belongs to the player making the move?
        if (at(i) & mNextPlayer)
        {
            bool lIsKing = at(i)&CELL_KING;

            if (tryJump(lMoves, cellToRow(i), cellToCol(i), lIsKing, lMoveBuffer))
                lFound=true;

            lPieces[lNumPieces++]=i;
        }
    }

    // Try normal moves if no jump was found
    if (!lFound)
    {
        for (int k = 0; k < lNumPieces; ++k)
        {
            int lCell = lPieces[k];
            bool lIsKing = at(lCell) & CELL_KING;
            tryMove(lMoves, lCell, lIsKing);
        }
    }

    // Convert moves to GameStates
    for (unsigned i = 0; i < lMoves.size(); ++i)
        pStates.push_back(GameState(*this, lMoves[i]));

    // Admit loss if no moves can be found
    if (pStates.size() == 0)
        pStates.push_back(GameState(*this, Move(mNextPlayer == CELL_WHITE ? Move::MOVE_RW : Move::Move::MOVE_WW)));
}
Example #6
0
bool BoardGenerator::rowBoxReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int row=0; row<9; row++){
            int rowStart = rowToFirstCell(row);
            bool inOneBox = true;
            int rowBox = -1;
            {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int column = i*3+j;
                        int position = rowColumnToCell(row, column);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if(possibilities[valPos] == 0){
                            if (rowBox == -1 || rowBox == i){
                                rowBox = i;
                            } else {
                                inOneBox = false;
                            }
                        }

                    }
                }}
            if (inOneBox && rowBox != -1){
                bool doneSomething = false;
                int column = 3*rowBox;
                int secStart = cellToSectionStartCell(rowColumnToCell(row, column));
                int secStartRow = cellToRow(secStart);
                int secStartCol = cellToColumn(secStart);
                {for (int i=0; i<3; i++){
                        for (int j=0; j<3; j++){
                            int row2 = secStartRow+i;
                            int col2 = secStartCol+j;
                            int position = rowColumnToCell(row2, col2);
                            int valPos = getPossibilityIndex(valIndex,position);
                            if (row != row2 && possibilities[valPos] == 0){
                                possibilities[valPos] = round;
                                doneSomething = true;
                            }
                        }
                    }}
                if (doneSomething){
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::ROW_BOX, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}
Example #7
0
bool BoardGenerator::pointingRowReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int section=0; section<9; section++){
            int secStart = sectionToFirstCell(section);
            bool inOneRow = true;
            int boxRow = -1;
            for (int j=0; j<3; j++){
                {for (int i=0; i<3; i++){
                        int secVal=secStart+i+(9*j);
                        int valPos = getPossibilityIndex(valIndex,secVal);
                        if(possibilities[valPos] == 0){
                            if (boxRow == -1 || boxRow == j){
                                boxRow = j;
                            } else {
                                inOneRow = false;
                            }
                        }
                    }}
            }
            if (inOneRow && boxRow != -1){
                bool doneSomething = false;
                int row = cellToRow(secStart) + boxRow;
                int rowStart = rowToFirstCell(row);

                {for (int i=0; i<9; i++){
                        int position = rowStart+i;
                        int section2 = cellToSection(position);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (section != section2 && possibilities[valPos] == 0){
                            possibilities[valPos] = round;
                            doneSomething = true;
                        }
                    }}
                if (doneSomething){
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::POINTING_PAIR_TRIPLE_ROW, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}