void Module::set ( Log_Entry &e ) { for ( int i = 0; i < e.size(); ++i ) { const char *s, *v; e.get( i, &s, &v ); if ( ! strcmp( s, ":chain" ) ) { /* This trickiness is because we may need to know the name of our chain before we actually get added to it. */ int i; sscanf( v, "%X", &i ); Chain *t = (Chain*)Loggable::find( i ); assert( t ); chain( t ); } } for ( int i = 0; i < e.size(); ++i ) { const char *s, *v; e.get( i, &s, &v ); /* if ( ! strcmp( s, ":name" ) ) */ /* label( v ); */ if ( ! strcmp( s, ":parameter_values" ) ) { set_parameters( v ); } else if ( ! ( strcmp( s, ":is_default" ) ) ) { is_default( atoi( v ) ); } else if ( ! ( strcmp( s, ":active" ) ) ) { bypass( ! atoi( v ) ); } else if ( ! strcmp( s, ":chain" ) ) { int i; sscanf( v, "%X", &i ); Chain *t = (Chain*)Loggable::find( i ); assert( t ); t->add( this ); } } }
/* * Updates the board with a move. Assumes that the move is legal. */ void Board::doMove(Player p, Move m) { if (m == MOVE_PASS) return; int x = getX(m); int y = getY(m); assert(pieces[index(x, y)] == EMPTY); assert(chainID[index(x, y)] == 0); pieces[index(x, y)] = p; zobristKey ^= zobristTable[zobristIndex(p, x, y)]; Player victim = otherPlayer(p); Stone east = pieces[index(x+1, y)]; Stone west = pieces[index(x-1, y)]; Stone north = pieces[index(x, y+1)]; Stone south = pieces[index(x, y-1)]; int connectionCount = (east == p) + (west == p) + (north == p) + (south == p); // If the stone placed is a new chain if (connectionCount == 0) { // Record which chain this square is a part of chainID[index(x, y)] = nextID; // Add this chain to the list of chains Chain *cargo = new Chain(p, nextID); cargo->add(m); cargo->liberties = 0; if (east == EMPTY) cargo->addLiberty(coordToMove(x+1, y)); if (west == EMPTY) cargo->addLiberty(coordToMove(x-1, y)); if (north == EMPTY) cargo->addLiberty(coordToMove(x, y+1)); if (south == EMPTY) cargo->addLiberty(coordToMove(x, y-1)); chainList.add(cargo); nextID++; } // If the stone placed is added to an existing chain else if (connectionCount == 1) { // Find the ID of the chain we are adding this stone to int thisID; if (east == p) thisID = chainID[index(x+1, y)]; else if (west == p) thisID = chainID[index(x-1, y)]; else if (north == p) thisID = chainID[index(x, y+1)]; else thisID = chainID[index(x, y-1)]; chainID[index(x, y)] = thisID; Chain *node = nullptr; searchChainsByID(node, thisID); node->add(m); // The new stone occupies a previous liberty, but adds on however many // liberties it itself has node->removeLiberty(node->findLiberty(m)); updateLiberty(node, x, y); } // If the stone possibly connects two existing chains else { int eastID = (east == p) * chainID[index(x+1, y)]; int westID = (west == p) * chainID[index(x-1, y)]; int northID = (north == p) * chainID[index(x, y+1)]; int southID = (south == p) * chainID[index(x, y-1)]; Chain *node = nullptr; bool added = false; if (eastID) { chainID[index(x, y)] = eastID; searchChainsByID(node, eastID); node->add(m); node->removeLiberty(node->findLiberty(m)); updateLiberty(node, x, y); added = true; } if (westID) { if (added) { // If two stones from the same chain are adjacent, do nothing // If they are from different chains, we need to combine... if (westID != eastID) mergeChains(node, westID, m); } else { chainID[index(x, y)] = westID; searchChainsByID(node, westID); node->add(m); node->removeLiberty(node->findLiberty(m)); updateLiberty(node, x, y); added = true; } } if (northID) { if (added) { if (northID != eastID && northID != westID) mergeChains(node, northID, m); } else { chainID[index(x, y)] = northID; searchChainsByID(node, northID); node->add(m); node->removeLiberty(node->findLiberty(m)); updateLiberty(node, x, y); added = true; } } if (southID) { if (added) { if (southID != eastID && southID != westID && southID != northID) mergeChains(node, southID, m); } else { chainID[index(x, y)] = southID; searchChainsByID(node, southID); node->add(m); node->removeLiberty(node->findLiberty(m)); updateLiberty(node, x, y); added = true; } } } // Update opponent liberties int eastID = (east == victim) * chainID[index(x+1, y)]; int westID = (west == victim) * chainID[index(x-1, y)]; int northID = (north == victim) * chainID[index(x, y+1)]; int southID = (south == victim) * chainID[index(x, y-1)]; if (eastID) { Chain *node = nullptr; int nodeIndex = searchChainsByID(node, eastID); node->removeLiberty(node->findLiberty(m)); if (node->liberties == 0) captureChain(node, nodeIndex); } if (westID && westID != eastID) { Chain *node = nullptr; int nodeIndex = searchChainsByID(node, westID); node->removeLiberty(node->findLiberty(m)); if (node->liberties == 0) captureChain(node, nodeIndex); } if (northID && northID != eastID && northID != westID) { Chain *node = nullptr; int nodeIndex = searchChainsByID(node, northID); node->removeLiberty(node->findLiberty(m)); if (node->liberties == 0) captureChain(node, nodeIndex); } if (southID && southID != eastID && southID != westID && southID != northID) { Chain *node = nullptr; int nodeIndex = searchChainsByID(node, southID); node->removeLiberty(node->findLiberty(m)); if (node->liberties == 0) captureChain(node, nodeIndex); } // Check for a suicide int selfID = chainID[index(x, y)]; Chain *node = nullptr; int nodeIndex = searchChainsByID(node, selfID); if (node->liberties == 0) captureChain(node, nodeIndex); // A debugging check assert(!checkChains()); // Check if p captured any of the other player's stones with move m /* doCaptures<true>(victim, coordToMove(x+1, y)); doCaptures<true>(victim, coordToMove(x-1, y)); doCaptures<true>(victim, coordToMove(x, y+1)); doCaptures<true>(victim, coordToMove(x, y-1)); // Check if p suicided with move m doCaptures<true>(p, coordToMove(x, y)); */ }