int StoneHandler::countLibertiesOnMatrix(Group *group, Matrix *m) { CHECK_PTR(group); CHECK_PTR(m); int liberties = 0; Q3ValueList<int> libCounted; // Walk through the horizontal and vertial directions, counting the // liberties of this group. for (unsigned int i=0; i<group->count(); i++) { Stone *tmp = group->at(i); CHECK_PTR(tmp); int x = tmp->posX(), y = tmp->posY(); // North checkNeighbourLibertyOnMatrix(x, y-1, libCounted, liberties, m); // West checkNeighbourLibertyOnMatrix(x-1, y, libCounted, liberties, m); // South checkNeighbourLibertyOnMatrix(x, y+1, libCounted, liberties, m); // East checkNeighbourLibertyOnMatrix(x+1, y, libCounted, liberties, m); } return liberties; }
bool Group::isAttachedTo(Stone *s) { CHECK_PTR(s); int stoneX = s->posX(); int stoneY = s->posY(); int x, y; StoneColor col = s->getColor(), c; Stone *tmp; if (isEmpty()) return false; for (unsigned int i=0; i<size(); i++) { tmp = at(i); x = tmp->posX(); y = tmp->posY(); c = tmp->getColor(); if (((stoneX == x && (stoneY == y-1 || stoneY == y+1)) || (stoneY == y && (stoneX == x-1 || stoneX == x+1))) && c == col) return true; } return false; }
void Group::debug() { qDebug(QString("Count: %1 - Liberties: %2").arg(count()).arg(liberties)); const_iterator i; for (i = constBegin(); i != constEnd(); i++) { Stone *s = *i; qDebug(" (%d, %d) %s", s->posX(), s->posY(), s->getColor() == stoneBlack ? "B" : "W"); } }
//bool StoneHandler::checkPosition(Stone *stone) bool StoneHandler::checkPosition(Stone *stone, Matrix *m, bool koStone) { //CHECK_PTR(stone); // CHECK_PTR(m); // SL added eb 8 if (!stone->isVisible()) return true; Group *active = NULL; // No groups existing? Create one. if (groups->isEmpty()) { Group *g = assembleGroup(stone,m); CHECK_PTR(g); groups->append(g); active = g; } // We already have one or more groups. else { bool flag = false; Group *tmp; for (unsigned int i=0; i<groups->count(); i++) { tmp = groups->at(i); //CHECK_PTR(tmp); // Check if the added stone is attached to an existing group. // If yes, update this group and replace the old one. // If the stone is attached to two groups, remove the second group. // This happens if the added stone connects two groups. if (tmp->isAttachedTo(stone)) { // Group attached to stone if (!flag) { if (!groups->remove(i)) qFatal("StoneHandler::checkPosition(Stone *stone):" "Oops, removing an attached group failed."); active = assembleGroup(stone,m); groups->insert(i, active); flag = true; } // Groups connected, remove one else { if (active != NULL && active == groups->at(i)) active = tmp; if (!groups->remove(i)) qFatal("StoneHandler::checkPosition(Stone *stone): " "Oops, removing a connected group failed."); i--; } } } // The added stone isnt attached to an existing group. Create a new group. if (!flag) { Group *g = assembleGroup(stone,m); CHECK_PTR(g); groups->append(g); active = g; } } // active->debug(); // Now we have to sort the active group as last in the groups QPtrList, // so if this one is out of liberties, we beep and abort the operation. // This prevents suicide moves. groups->append(groups->take(groups->findRef(active))); // Check the liberties of every group. If a group has zero liberties, remove it. for (unsigned int i=0; i<groups->count(); i++) { Group *tmp = groups->at(i); //CHECK_PTR(tmp); tmp->setLiberties(countLiberties(tmp, m)); //SL added eb 8 // qDebug("Group #%d with %d liberties:", i, tmp->getLiberties()); // tmp->debug(); // Oops, zero liberties. if (tmp->getLiberties() == 0) { // Suicide move? if (tmp == active) { if (active->count() == 1) { groups->remove(i); removeStone(stone->posX(), stone->posY(), false); } return false; } //was it a forbidden ko move ? if ((tmp->count() == 1) && koStone && ((countLiberties(active, m) == 0))) { active->debug(); groups->remove(groups->findRef(active)); removeStone(stone->posX(), stone->posY(), false); return false ; } int stoneCounter = 0; // Erase the stones of this group from the stones table. QListIterator<Stone *> it(*tmp); while (it.hasNext()) { Stone *s = it.next(); CHECK_PTR(s); if (workingOnNewMove) boardHandler->updateCurrentMatrix(stoneNone, s->posX(), s->posY()); removeStone(s->posX(), s->posY()); stoneCounter ++; } // Remove the group from the groups list. // qDebug("Oops, a group got killed. Removing killed group #%d", i); if (tmp == active) active = NULL; if (!groups->remove(i)) qFatal("StoneHandler::checkPosition(Stone *stone): " "Oops, removing a killed group failed."); i--; // Tell the boardhandler about the captures boardHandler->setCaptures(stone->getColor(), stoneCounter); } } return true; }