📄 boardhandler.cpp
字号:
bool BoardHandler::importASCII(const QString &fileName, bool fromClipboard){ QString filenameORstring = fromClipboard ? QApplication::clipboard()->text() : fileName; if (gameMode == modeScore) return false; clearNode(setting->addImportAsBrother); if (!sgfParser->parseASCII(filenameORstring, setting->charset, !fromClipboard)) return false; updateMove(tree->getCurrent()); board->setModified(); return true;}bool BoardHandler::importSGFClipboard(){ QString sgfString = QApplication::clipboard()->text(); // qDebug("Text in clipboard:\n%s", sgfString.latin1()); if (sgfString.isNull() || sgfString.isEmpty() || !sgfParser->parseString(sgfString)) return false; prepareBoard(); return true;}bool BoardHandler::exportSGFtoClipB(){ QString str = ""; if (!sgfParser->exportSGFtoClipB(&str, tree)) return false; QApplication::clipboard()->setText(str); return true;}void BoardHandler::setHandicap(int handicap){ GameMode store = getGameMode(); //qDebug("set Handicap " + QString::number(handicap) + ", stored mode == " + QString::number(store)); setMode(modeEdit); int size = getGameData()->size; int edge_dist = (size > 12 ? 4 : 3); int low = edge_dist; int middle = (size + 1) / 2; int high = size + 1 - edge_dist; if (size > 25 || size < 7) { qWarning("*** BoardHandler::setHandicap() - can't set handicap for this board size"); setMode(store); return; } // change: handicap is first move if (handicap > 1) { createNode(*tree->getCurrent()->getMatrix(), false, false); /* Move should already be set to 0 by board handler and the placement * of handicap stones won't change that */ //currentMove++; //tree->getCurrent()->setMoveNumber(1); } // extra: if (size == 19 && handicap > 9) switch (handicap) { case 13: // Hehe, this is nuts... :) addStone(stoneBlack, 17, 17); case 12: addStone(stoneBlack, 3, 3); case 11: addStone(stoneBlack, 3, 17); case 10: addStone(stoneBlack, 17, 3); default: handicap = 9; break; } switch (size % 2) { // odd board size case 1: switch (handicap) { case 9: addStone(stoneBlack, middle, middle); case 8: case 7: if (handicap >= 8) { addStone(stoneBlack, middle, low); addStone(stoneBlack, middle, high); } else addStone(stoneBlack, middle, middle); case 6: case 5: if (handicap >= 6) { addStone(stoneBlack, low, middle); addStone(stoneBlack, high, middle); } else addStone(stoneBlack, middle, middle); case 4: addStone(stoneBlack, high, high); case 3: addStone(stoneBlack, low, low); case 2: addStone(stoneBlack, high, low); addStone(stoneBlack, low, high); case 1: if (store != modeObserve && store != modeMatch && store != modeTeach) gameData->komi = 0.5; break; default: qWarning("*** BoardHandler::setHandicap() - Invalid handicap given: %d", handicap); } break; // even board size case 0: switch (handicap) { case 4: addStone(stoneBlack, high, high); case 3: addStone(stoneBlack, low, low); case 2: addStone(stoneBlack, high, low); addStone(stoneBlack, low, high); case 1: if (store != modeObserve && store != modeMatch && store != modeTeach) gameData->komi = 0.5; break; default: qWarning("*** BoardHandler::setHandicap() - Invalid handicap given: %d", handicap); } break; default: qWarning("*** BoardHandler::setHandicap() - can't set handicap for this board size"); } // Change cursor stone color board->setCurStoneColor(); gameData->handicap = handicap; setMode(store); board->getInterfaceHandler()->disableToolbarButtons();}bool BoardHandler::hasParent(){ return tree->getCurrent()->parent != NULL;}void BoardHandler::setCaptures(StoneColor c, int n){ if (c == stoneBlack) capturesBlack += n; else capturesWhite += n;}void BoardHandler::countScore(){ tree->getCurrent()->getMatrix()->clearTerritoryMarks(); // capturesBlack -= caps_black; // capturesWhite -= caps_white; // Copy the current matrix Matrix *m = new Matrix(*(tree->getCurrent()->getMatrix())); CHECK_PTR(m); // Do some cleanups, we only need stones m->absMatrix(); m->clearAllMarks(); // Mark all dead stones in the matrix with negative number int i=0, j=0; for (i=0; i<board->getBoardSize(); i++) for (j=0; j<board->getBoardSize(); j++) if (stoneHandler->hasStone(i+1, j+1) == 1) if (stoneHandler->getStoneAt(i+1, j+1)->isDead()) m->set(i, j, m->at(i, j) * -1); else if (stoneHandler->getStoneAt(i+1, j+1)->isSeki()) m->set(i, j, m->at(i, j) * MARK_SEKI); int terrWhite = 0, terrBlack = 0; while (m != NULL) { bool found = false; for (i=0; i<board->getBoardSize(); i++) { for (j=0; j<board->getBoardSize(); j++) { if (m->at(i, j) <= 0) { found = true; break; } } if (found) break; } if (!found) break; // Traverse the enclosed territory. Resulting color is in col afterwards StoneColor col = stoneNone; traverseTerritory(m, i, j, col); // Now turn the result into real territory or dame points for (i=0; i<board->getBoardSize(); i++) { for (j=0; j<board->getBoardSize(); j++) { if (m->at(i, j) == MARK_TERRITORY_VISITED) { // Black territory if (col == stoneBlack) { tree->getCurrent()->getMatrix()->removeMark(i+1, j+1); tree->getCurrent()->getMatrix()->insertMark(i+1, j+1, markTerrBlack); terrBlack ++; m->set(i, j, MARK_TERRITORY_DONE_BLACK); } // White territory else if (col == stoneWhite) { tree->getCurrent()->getMatrix()->removeMark(i+1, j+1); tree->getCurrent()->getMatrix()->insertMark(i+1, j+1, markTerrWhite); terrWhite ++; m->set(i, j, MARK_TERRITORY_DONE_WHITE); } // Dame else m->set(i, j, MARK_TERRITORY_DAME); } } } } // Finally, remove all false eyes that have been marked as territory. This // has to be here, as in the above loop we did not find all dame points yet. for (i = 0; i < board->getBoardSize(); i++) { for (j = 0; j < board->getBoardSize(); j++) { if (m->at(i, j) == MARK_TERRITORY_DONE_BLACK || m->at(i, j) == MARK_TERRITORY_DONE_WHITE) { int col = (m->at(i, j) == MARK_TERRITORY_DONE_BLACK ? stoneBlack : stoneWhite); if (stoneHandler->checkFalseEye(m, i, j, col)) { tree->getCurrent()->getMatrix()->removeMark(i + 1, j + 1); if (col == stoneBlack) terrBlack--; else terrWhite--; } } } } // Mark the move having territory marks tree->getCurrent()->setTerritoryMarked(true); // Paint the territory on the board stoneHandler->updateAll(tree->getCurrent()->getMatrix()); board->updateCanvas(); // Update Interface board->getInterfaceHandler()->setScore(terrBlack, capturesBlack + caps_black, terrWhite, capturesWhite+ caps_white, gameData->komi); delete m;}void BoardHandler::traverseTerritory(Matrix *m, int x, int y, StoneColor &col){ // Mark visited m->set(x, y, MARK_TERRITORY_VISITED); // North if (checkNeighbourTerritory(m, x, y-1, col)) traverseTerritory(m, x, y-1, col); // East if (checkNeighbourTerritory(m, x+1, y, col)) traverseTerritory(m, x+1, y, col); // South if (checkNeighbourTerritory(m, x, y+1, col)) traverseTerritory(m, x, y+1, col); // West if (checkNeighbourTerritory(m, x-1, y, col)) traverseTerritory(m, x-1, y, col);}bool BoardHandler::checkNeighbourTerritory(Matrix *m, const int &x, const int &y, StoneColor &col){ // Off the board? Dont continue if (x < 0 || x >= board->getBoardSize() || y < 0 || y >= board->getBoardSize()) return false; // No stone? Continue if (m->at(x, y) <= 0) return true; // A stone, but no color found yet? Then set this color and dont continue // The stone must not be marked as alive in seki. if (col == stoneNone && m->at(x, y) > 0 && m->at(x, y) < MARK_SEKI) { col = (StoneColor)m->at(x, y); return false; } // A stone, but wrong color? Set abort flag but continue to mark the rest of the dame points StoneColor tmpCol = stoneNone; if (col == stoneBlack) tmpCol = stoneWhite; else if (col == stoneWhite) tmpCol = stoneBlack; if ((tmpCol == stoneBlack || tmpCol == stoneWhite) && m->at(x, y) == tmpCol) { col = stoneErase; return false; } // A stone, correct color, or already visited, or seki. Dont continue return false;}void BoardHandler::enterScoreMode(int cb, int cw){ capturesBlack = tree->getCurrent()->getCapturesBlack(); capturesWhite = tree->getCurrent()->getCapturesWhite(); caps_black = cb; caps_white = cw; tree->getCurrent()->setScored(true);}void BoardHandler::leaveScoreMode(){ // Remove territory marks if (tree->getCurrent()->isTerritoryMarked()) { tree->getCurrent()->getMatrix()->clearTerritoryMarks(); tree->getCurrent()->setTerritoryMarked(false); tree->getCurrent()->setScored(false); } // Unshade dead stones stoneHandler->removeDeadMarks(); markedDead = false; updateMove(tree->getCurrent()); caps_black = caps_white = 0;}void BoardHandler::markDeadStone(int x, int y){ int caps = 0; StoneColor col; bool dead = false; if (stoneHandler->removeDeadGroup(x, y, caps, col, dead)) { // Mark we have dead stones in this move if (dead) markedDead = true; // Add captures for opponent if (!dead) caps *= -1; setCaptures(col == stoneBlack ? stoneWhite : stoneBlack, caps); countScore(); }}void BoardHandler::markSeki(int x, int y){ int caps = 0; StoneColor col; bool seki = false; if (stoneHandler->markSekiGroup(x, y, caps, col, seki)) { // Mark we have seki stones in this move if (seki) markedDead = true; // Remove captures if seki brought dead stones back to life if (caps) setCaptures(col == stoneBlack ? stoneWhite : stoneBlack, -caps); countScore(); }}void BoardHandler::findMoveByPos(int x, int y){ Move *m = tree->findMoveInMainBranch(x, y); if (m != NULL) gotoMove(m); else QApplication::beep();}void BoardHandler::findMoveByPosInVar(int x, int y){ Move *m = tree->findMoveInBranch(x, y); if (m != NULL) gotoMove(m); else QApplication::beep();}void BoardHandler::gotoMove(Move *m){ CHECK_PTR(m); tree->setCurrent(m); updateMove(m);}bool BoardHandler::findMoveInVar(int x, int y){ // Init stack if not yet done if (nodeResults == NULL) { nodeResults = new QPtrStack<Move>; nodeResults->setAutoDelete(FALSE); } CHECK_PTR(nodeResults); nodeResults->clear(); tree->traverseFind(tree->getCurrent(), x, y, *nodeResults); if (nodeResults->isEmpty()) { QApplication::beep(); return false; } return true;}void BoardHandler::numberMoves(){ if (gameMode == modeScore) return; CHECK_PTR(tree); // Move from current upwards to root and set a number mark Move *m = tree->getCurrent(); if (m == NULL || m->getMoveNumber() == 0) return; do { board->setMark(m->getX(), m->getY(), markNumber, true, QString::number(m->getMoveNumber())); } while ((m = m->parent) != NULL && m->getMoveNumber() != 0); board->updateCanvas();}void BoardHandler::markVariations(bool sons){ if (gameMode == modeScore) return; CHECK_PTR(tree); Move *m = tree->getCurrent(); if (m == NULL) return; // Mark all sons of current move if (sons && m->son != NULL) { m = m->son; do { board->setMark(m->getX(), m->getY(), markText); } while ((m = m->brother) != NULL); } // Mark all brothers of current move else if (!sons && m->parent != NULL) { Move *tmp = m->parent->son; if (tmp == NULL) return; do { if (tmp != m) board->setMark(tmp->getX(), tmp->getY(), markText); } while ((tmp = tmp->brother) != NULL); } board->updateCanvas();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -