void GoBoard::AddStone(int point, int color) { int boardColor = color == S_BLACK? B_BLACK : B_WHITE; // int w = West(point); // int e = East(point); // int n = North(point); // int s = South(point); State.stones[point] = boardColor; if(West(point) != -1) { --State.numNeighboursEmpty[West(point)]; ++State.numNeighbours[color][West(point)]; } if(East(point) != -1) { --State.numNeighboursEmpty[East(point)]; ++State.numNeighbours[color][East(point)]; } if(North(point) != -1) { --State.numNeighboursEmpty[North(point)]; ++State.numNeighbours[color][North(point)]; } if(South(point) != -1) { --State.numNeighboursEmpty[South(point)]; ++State.numNeighbours[color][South(point)]; } UpdateBlocks(point,color); }
void GoBoard::RemoveStone(const int pos) { int stoneColor = State.stones[pos] == B_BLACK? S_BLACK : S_WHITE; //Handling opened liberties if(IsRealPoint(North(pos)) && North(pos) != -1) { // LOG_DEBUG << "Handling renewed liberties for "<<North(pos)<< " Old libs: "<<State.blockPointers[North(pos)]->Liberties(); ++State.numNeighboursEmpty[North(pos)]; --State.numNeighbours[stoneColor][North(pos)]; if(State.stones[North(pos)] != NONE && !IsInSameBlock(pos,North(pos))) { ++State.blockPointers[North(pos)]->liberties; } } if(IsRealPoint(South(pos)) && South(pos) != -1) { ++State.numNeighboursEmpty[South(pos)]; --State.numNeighbours[stoneColor][South(pos)]; if(State.stones[South(pos)] != NONE && !IsInSameBlock(pos,South(pos)) && !IsInSameBlock(South(pos),North(pos))) { ++State.blockPointers[South(pos)]->liberties; } } if(IsRealPoint(West(pos)) && West(pos) != -1) { ++State.numNeighboursEmpty[West(pos)]; --State.numNeighbours[stoneColor][West(pos)]; if(State.stones[West(pos)] != NONE && !IsInSameBlock(pos,West(pos)) && !IsInSameBlock(West(pos),North(pos)) && !IsInSameBlock(West(pos),South(pos))) { ++State.blockPointers[West(pos)]->liberties; } } if(IsRealPoint(East(pos)) && East(pos) != -1) { ++State.numNeighboursEmpty[East(pos)]; --State.numNeighbours[stoneColor][East(pos)]; if(State.stones[East(pos)] != NONE && !IsInSameBlock(pos,East(pos)) && !IsInSameBlock(East(pos),North(pos)) && !IsInSameBlock(East(pos),South(pos)) && !IsInSameBlock(East(pos),West(pos))) { ++State.blockPointers[East(pos)]->liberties; } } int opponentColor = stoneColor == S_BLACK ? S_WHITE : S_BLACK; // LOG_VERBOSE<<opponentColor<<" now has "<<State.bw_prisoners[opponentColor]<<" prisoners"; ++State.bw_prisoners[opponentColor]; // LOG_VERBOSE<<opponentColor<<" now has "<<State.bw_prisoners[opponentColor]<<" prisoners"; //Remove the stone from the board State.blockPointers[pos] = 0; State.stones[pos] = NONE; }
Matrix CoordinateSystem::getRotFromCompass(CompassData& compassData, GravityData& gravityData) { Vector compass_vector(3); compass_vector(0) = compassData.x(); compass_vector(1) = compassData.y(); compass_vector(2) = compassData.z(); Vector gravity_vector(3); gravity_vector(0) = gravityData.x(); gravity_vector(1) = gravityData.y(); gravity_vector(2) = gravityData.z(); Vector East(3); cross_prod(compass_vector, gravity_vector, East); // East = cross(compass_vector, gravity_vector) double normEast = norm_2(East); if (normEast < 0) return IdentityMatrix(3); East /= normEast; // normalization gravity_vector /= norm_2(gravity_vector); Vector North(3); cross_prod(gravity_vector, East, North); // North = cross(gravity_vector, East) Matrix rotmat(3, 3); row(rotmat, 0) = East; row(rotmat, 1) = North; row(rotmat, 2) = gravity_vector; return Matrix(rotmat); }
bool GoBoard::IsSuicide(const int pos, const int color) const { int boardColor = color == S_BLACK? B_BLACK : B_WHITE; //Converts GoPoint-Stonecolor to board color. Should be put in function... //Test for single stone if(State.numNeighboursEmpty[pos]>0) { return false; } //Test if joins block of same color if(Occupied(North(pos)) && State.stones[North(pos)] == boardColor && State.blockPointers[North(pos)]->Liberties()>1) { return false; } if(Occupied(South(pos)) && State.stones[South(pos)] == boardColor && State.blockPointers[South(pos)]->Liberties()>1) { return false; } if(Occupied(West(pos)) && State.stones[West(pos)] == boardColor && State.blockPointers[West(pos)]->Liberties()>1) { return false; } if(Occupied(East(pos)) && State.stones[East(pos)] == boardColor && State.blockPointers[East(pos)]->Liberties()>1) { return false; } //Allow "temporary suicide" if it leads to capture. if(Occupied(North(pos)) && State.stones[North(pos)] != boardColor && State.blockPointers[North(pos)]->liberties == 1) { return false; } if (Occupied(South(pos)) && State.stones[South(pos)] != boardColor && State.blockPointers[South(pos)]->liberties == 1) { return false; } if(Occupied(West(pos)) && State.stones[West(pos)] != boardColor && State.blockPointers[West(pos)]->liberties == 1) { return false; } if(Occupied(East(pos)) && State.stones[East(pos)] != boardColor && State.blockPointers[East(pos)]->liberties == 1) { return false; } return true; }
void GoBoard::KillSurroundingDeadBlocks(const int pos) { //Reset kopoint State.koPoint = NO_KO_POINT; bool singleStoneKilledBefore = false; for(int i = 0; i<4; i++) { int blockPos = -1; if(i == 0 && IsRealPoint(North(pos)) && State.stones[North(pos)] != NONE && State.stones[North(pos)] != State.stones[pos]) blockPos = North(pos); else if(i == 1 && IsRealPoint(South(pos)) && State.stones[South(pos)] != NONE && State.stones[South(pos)] != State.stones[pos]) blockPos = South(pos); else if(i == 2 && IsRealPoint(West(pos)) && State.stones[West(pos)] != NONE && State.stones[West(pos)] != State.stones[pos]) blockPos = West(pos); else if(i == 3 && IsRealPoint(East(pos)) && State.stones[East(pos)] != NONE && State.stones[East(pos)] != State.stones[pos]) blockPos = East(pos); //if(blockPos == -1) else continue; GoBlock* p_block = State.blockPointers[blockPos]; if(p_block == 0) { LOG_VERBOSE << "Tested on 0 block"; continue; } if(p_block->Liberties() == 0) { //Create ko-point if applicable(Single stone) if(p_block->lastStone==1) { if(!singleStoneKilledBefore) { State.koPoint = blockPos; singleStoneKilledBefore = true; } else { State.koPoint = NO_KO_POINT; } } p_block->RemoveStones(); //Remove stones from board and update liberties. p_block->reset(); //Free block from memory } } }
const int GoBoard::FindUniqueLiberties(const int stone, const GoBlock* block) const { LOG_DEBUG<<"Testing "<<stone<<" against "<<block->anchor; int uniqueLiberties = 0; if(North(stone) != -1 && State.stones[North(stone)] == NONE && !IsLibertyOfBlock(North(stone),block->anchor)) { ++uniqueLiberties; } if(South(stone) != -1 && State.stones[South(stone)] == NONE && !IsLibertyOfBlock(South(stone),block->anchor)) { ++uniqueLiberties; } if(West(stone) != -1 && State.stones[West(stone)] == NONE && !IsLibertyOfBlock(West(stone),block->anchor)) { ++uniqueLiberties; } if(East(stone) != -1 && State.stones[East(stone)] == NONE && !IsLibertyOfBlock(East(stone),block->anchor)) { ++uniqueLiberties; } // int lib = 0; // for(int i = 0; i < 4; i++) // { // if(i == 0) // lib = North(stone); // else if(i == 1) // lib = South(stone); // else if(i == 2) // lib = West(stone); // else if(i == 3) // lib = East(stone); // if(State.stones[lib] == NONE) // { // if(State.blockPointers[North(lib)] != block && // State.blockPointers[South(lib)] != block && // State.blockPointers[West(lib)] != block && // State.blockPointers[East(lib)] != block) // ++uniqueLiberties; // } // } return uniqueLiberties; }
const int GoBoard::FindCommonLiberties(const int point, const int anchor) const { int commonLiberties = 0; if(North(point)!=-1 && point != anchor && IsLibertyOfBlock(North(point),anchor)) { ++commonLiberties; } if(South(point)!=-1 && point != anchor && IsLibertyOfBlock(South(point),anchor)) { ++commonLiberties; } if(West(point)!=-1 && point != anchor && IsLibertyOfBlock(West(point),anchor)) { ++commonLiberties; } if(East(point)!=-1 && point != anchor && IsLibertyOfBlock(East(point),anchor)) { ++commonLiberties; } return commonLiberties; }
const bool GoBoard::IsLibertyOfBlock(const int point, const int anchor) const { if(!Occupied(anchor)) return false; const GoBlock* block = State.blockPointers[anchor]; if(North(point) != -1 && State.blockPointers[North(point)] == block && State.blockPointers[North(point)] != State.blockPointers[point]) { return true; } if(South(point) != -1 && State.blockPointers[South(point)] == block && State.blockPointers[South(point)] != State.blockPointers[point]) { return true; } if(West(point) != -1 && State.blockPointers[West(point)] == block && State.blockPointers[West(point)] != State.blockPointers[point]) { return true; } if(East(point) != -1 && State.blockPointers[East(point)] == block && State.blockPointers[East(point)] != State.blockPointers[point]) { return true; } return false; }
const float GoBoard::GetScoreInternal() const { float score = -komi; //Positive score = black win // LOG_VERBOSE << "Post komi"<<score<<std::endl; //Count captures score += State.bw_prisoners[S_BLACK] - State.bw_prisoners[S_WHITE]; // LOG_VERBOSE << "Caps "<<State.bw_prisoners[S_BLACK]<<" "<<State.bw_prisoners[S_WHITE]<< " " << score+komi << std::endl; // LOG_VERBOSE << "Post caps"<<score<<std::endl; int bstones = 0; int wstones = 0; int bterr = 0; int wterr = 0; for(int i = 0; i<Size()*Size(); ++i) { //Count stones if(State.stones[i] == B_BLACK) ++bstones; else if(State.stones[i] == B_WHITE) ++wstones; else if(State.stones[i] == NONE) //Count empty points { if(State.stones[North(i)] == B_BLACK || State.stones[South(i)] == B_BLACK || State.stones[West(i)] == B_BLACK || State.stones[East(i)] == B_BLACK ) ++bterr; else ++wterr; } } // LOG_VERBOSE << bstones << " " <<wstones<< " "<<bterr<< " "<<wterr; score += bstones + bterr - wstones - wterr; // LOG_VERBOSE << "Finished score"<<score<<std::endl; return score; }
const bool GoBoard::IsTrueEye(const int point, const int boardColor) { if( (North(point) == -1 || (State.stones[North(point)] == boardColor)) && (South(point) == -1 || (State.stones[South(point)] == boardColor)) && (West(point) == -1 || (State.stones[West(point)] == boardColor)) && (East(point) == -1 || (State.stones[East(point)] == boardColor)) )//Results in potential eye at point. May still be false { //Get diagonal colors int NW = West(point) != -1 && North(point) != -1 ? State.stones[North(West(point))] : -1; int NE = East(point) != -1 && North(point) != -1 ? State.stones[North(East(point))] : -1; int SW = West(point) != -1 && South(point) != -1 ? State.stones[South(West(point))] : -1; int SE = East(point) != -1 && South(point) != -1 ? State.stones[South(East(point))] : -1; LOG_DEBUG << NW << NE << SW <<SE<<State.stones[point]; int numValid = 0; int numSameCol = 0; if(NW != -1) ++numValid; if(NE != -1) ++numValid; if(SW != -1) ++numValid; if(SE != -1) ++numValid; if(NW == boardColor) ++numSameCol; if(NE == boardColor) ++numSameCol; if(SW == boardColor) ++numSameCol; if(SE == boardColor) ++numSameCol; if((float)numSameCol / (float)numValid > 0.5) return true; } return false; }
int GoBoard::East(const GoPoint p) const { return East(Pos(p)); }
void GoBoard::UpdateBlocks(int pos, int color) { int boardColor = color == S_BLACK? B_BLACK : B_WHITE; //Remove blockliberties of opposite color if(North(pos) != -1 && IsLibertyOfBlock(pos,North(pos))) { State.blockPointers[North(pos)]->liberties--; // LOG_DEBUG << "Removed liberty for block at "<< North(pos); } if(South(pos) != -1 && (State.blockPointers[South(pos)] != State.blockPointers[North(pos)]) //These are in place on west and east as well, to prevent removing too several liberties from the same group && IsLibertyOfBlock(pos,South(pos))) { State.blockPointers[South(pos)]->liberties--; // LOG_DEBUG << "Removed liberty for block at "<< North(pos); } if(West(pos) != -1 && (State.blockPointers[West(pos)] != State.blockPointers[North(pos)] && State.blockPointers[West(pos)] != State.blockPointers[South(pos)]) && IsLibertyOfBlock(pos,West(pos))) State.blockPointers[West(pos)]->liberties--; if(East(pos) != -1 && (State.blockPointers[East(pos)] != State.blockPointers[North(pos)] && State.blockPointers[East(pos)] != State.blockPointers[South(pos)] && State.blockPointers[East(pos)] != State.blockPointers[West(pos)]) && IsLibertyOfBlock(pos,East(pos))) State.blockPointers[East(pos)]->liberties--; if(State.numNeighbours[color][pos] == 0) //Solo stone. Create new block { GoBlock* b = blocks[blockPointer]; ++blockPointer; b->anchor = pos; b->color = color; b->board = this; b->liberties= State.numNeighboursEmpty[pos]; State.blockPointers[pos] = b; } else //Not solo. Attach to block { int uniqueLiberties = 0; if (South(pos) != -1 && State.stones[South(pos)] == boardColor) { // commonLiberties = FindCommonLiberties(pos,South(pos)); uniqueLiberties = FindUniqueLiberties(pos, State.blockPointers[South(pos)]); State.blockPointers[pos] = State.blockPointers[South(pos)]; } else if (North(pos) != -1 && State.stones[North(pos)] == boardColor) { // commonLiberties = FindCommonLiberties(pos,North(pos)); uniqueLiberties = FindUniqueLiberties(pos, State.blockPointers[North(pos)]); State.blockPointers[pos] = State.blockPointers[North(pos)]; } else if (West(pos) != -1 && State.stones[West(pos)] == boardColor) { // commonLiberties = FindCommonLiberties(pos,West(pos)); uniqueLiberties = FindUniqueLiberties(pos, State.blockPointers[West(pos)]); State.blockPointers[pos] = State.blockPointers[West(pos)]; } else if (East(pos) != -1 && State.stones[East(pos)] == boardColor) { // commonLiberties = FindCommonLiberties(pos,East(pos)); uniqueLiberties = FindUniqueLiberties(pos, State.blockPointers[East(pos)]); State.blockPointers[pos] = State.blockPointers[East(pos)]; } else LOG_ERROR <<"Something went terribly wrong"; //Subtract one since the new stone is always placed on a liberty for the block. State.blockPointers[pos]->liberties += uniqueLiberties; //Detect neighboring blocks to perform join. //Has similar neighbor but not recently attached block if(State.stones[North(pos)] == boardColor && State.blockPointers[North(pos)] != State.blockPointers[pos]) State.blockPointers[pos]->ImportBlock(State.blockPointers[North(pos)]); if(State.stones[South(pos)] == boardColor && State.blockPointers[South(pos)] != State.blockPointers[pos]) State.blockPointers[pos]->ImportBlock(State.blockPointers[South(pos)]); if(State.stones[West(pos)] == boardColor && State.blockPointers[West(pos)] != State.blockPointers[pos]) State.blockPointers[pos]->ImportBlock(State.blockPointers[West(pos)]); if(State.stones[East(pos)] == boardColor && State.blockPointers[East(pos)] != State.blockPointers[pos]) State.blockPointers[pos]->ImportBlock(State.blockPointers[East(pos)]); // if(copyBlock != 0) // { // std::vector<int> commonLiberties; // GoBlock* curBlock = State.blockPointers[pos]; // curBlock->ImportBlock(copyBlock); // } } State.blockPointers[pos]->addStone(pos); KillSurroundingDeadBlocks(pos); }
void Interface::MainGame() { string input = ""; vector<string> parsedInput; bool quitGame = false; Look(); cout << "Type 'help' (no ' marks) for a short explanation of basic commands." << endl; cout << "Make sure to use the 'growth' command before gaining experience!" << endl; while(!quitGame) { Prompt(); getline(cin, input); for (int i = 0; i < input.size(); i++) input[i] = tolower(input[i]); parsedInput = ParseInput(input); command cmd = CommandControl::GetInstance()->GetCommand(parsedInput.front()); string target = parsedInput.back(); if (cmd == LOOK) Look(); if (cmd == GO_NORTH) North(); if (cmd == GO_SOUTH) South(); if (cmd == GO_EAST) East(); if (cmd == GO_WEST) West(); if (cmd == GO_DOWN) Down(); if (cmd == GO_UP) Up(); if (cmd == KILL) Kill(parsedInput.back()); if (cmd == SCORE) Score(); if (cmd == ABILITIES) Abilities(); if (cmd == HELP) Help(); if (cmd == GROWTH) Growth(); if (cmd == QUIT) Quit(); if (cmd == INVENTORY) Inventory(); if (cmd == EQUIPMENT) Equipment(); if (cmd == WEAR) Wear(parsedInput.back()); if (cmd == REMOVE) Remove(parsedInput.back()); if (cmd == EXAMINE) { command targetCmd = CommandControl::GetInstance()->GetCommand(parsedInput.back()); if (targetCmd == INVENTORY) ExaInv(); else if (targetCmd == EQUIPMENT) ExaEquip(); else if (targetCmd == LOOK) ExaLook(); else cout << "That is not a valid target to examine." << endl; } if (cmd == GET) Get(parsedInput.back()); if (cmd == DROP) Drop(parsedInput.back()); if (cmd == USE) Use(parsedInput.back()); if (cmd == SAVE) SavePlayer(); } }
/* compute the next generation of the world */ void NextGeneration(char **oldWorld, char **newWorld, int row, int column) { //RULES: //Live cell fewer than 2 live neighbours dies //Live Cell more than 3 live neigbours dies //Live cell 2 or 3 neigbours lives //Dead cell with 3 neigbours becomes alive. //primitives int i, j; int neigbours = 0; //loop through visible non border region //CHECK for (i = 0; i < row; i++) { for (j = 0; j < column; j++) { neigbours = 0; //sum up the neigbours neigbours += North(oldWorld, i, j, row, column); neigbours += NorthEast(oldWorld, i, j, row, column); neigbours += NorthWest(oldWorld, i, j, row, column); neigbours += South(oldWorld, i, j, row, column); neigbours += SouthEast(oldWorld, i, j, row, column); neigbours += SouthWest(oldWorld, i, j, row, column); neigbours += East(oldWorld, i, j, row, column); neigbours += West(oldWorld, i, j, row, column); //check for the rules above //check if the cell is alive if (LiveCell(oldWorld, i, j) == TRUE) { //Live cell fewer than 2 live neighbours dies if (neigbours < 2) { newWorld[i][j]=' '; //DEBUG //printf("\n\nIt's Dead\n"); } //Live Cell more than 3 live neigbours dies else if (neigbours > 3) { newWorld[i][j]=' '; //printf("\n\nIt's Dead\n"); } //Live cell 2 or 3 neigbours lives //this is redundant since it will stay alive } else //Dead cell with 3 neigbours becomes alive. if (neigbours == 3) { //It shall be reborn! newWorld[i][j]='x'; } } } }