#include "Board.h" #include "Space.h" #include "Piece.h" #include #include using namespace std; bool Board::ReconfigureThenTryInserting(Piece* piece, int icol, int irow){ if (piece->RotateCounterClockwise()!=0){ // we have tried all rotations at this centerpoint. Try recentering if (piece->RecenterAtNextBlackSquare()!=0){ // that's it. We have tried everything. It does not fit at all return false; // means doesn't fit } } return this->SucceedInserting(piece,icol,irow); } bool Board::SucceedInserting(Piece* piece,int icol,int irow){ while (this->InsertPiece(piece,icol,irow)!=0){ // doesnt fit in this configuration. Try rotating if (piece->RotateCounterClockwise()!=0){ // we have tried all rotations at this centerpoint. Try recentering if (piece->RecenterAtNextBlackSquare()!=0){ // that's it. We have tried everything. It does not fit at all return false; // means doesn't fit } } } return true; // that means there was no problem. The Piece was inserted at the next available Space on the Board } int Board::InsertPiece(Piece* piece, int col, int row){ assert (!(piece->IsOnBoard())); // can't insert it AGAIN piece->SetOnBoardOrNot(true); piece->SetColumnOfPieceOnBoard(col); piece->SetRowOfPieceOnBoard(row); for (int is=0; is < piece->NumberOfSquares(); is++){ int boardSpaceColumn = col + (*(piece->TheSpaces())[is]).Column(); // piece Spaces has RELATIVE positions int boardSpaceRow = row + (*(piece->TheSpaces())[is]).Row(); // piece Spaces has RELATIVE positions // if this space is off of the Board // then we have to UNDO ALL WHAT WE'VE DONE and return "error" code if ((boardSpaceColumn>7)||(boardSpaceColumn<0)||(boardSpaceRow>7)||(boardSpaceRow<0)){ for (int jjj=is-1; jjj > -1; jjj--){ int jjjCol = col + (*(piece->TheSpaces())[jjj]).Column(); int jjjRow = row + (*(piece->TheSpaces())[jjj]).Row(); spaces[jjjCol][jjjRow].ResetSpace(); } piece->SetOnBoardOrNot(false); return 1; // 1 is the error code } // Likewise, if this space is already occupied // then we have to UNDO ALL WHAT WE'VE DONE and return "error" code if (spaces[boardSpaceColumn][boardSpaceRow].IsOccupied()){ for (int jjj=is-1; jjj > -1; jjj--){ int jjjCol = col + (*(piece->TheSpaces())[jjj]).Column(); int jjjRow = row + (*(piece->TheSpaces())[jjj]).Row(); spaces[jjjCol][jjjRow].ResetSpace(); } piece->SetOnBoardOrNot(false); return 1; // 1 is the error code } // the assertion below checks that red square is going on red and black on black... // (yes, it's a bit wasteful timewise to ALWAYS check. Probably I comment it out // when I am sure all is working) assert( (*(piece->TheSpaces())[is]).Color() == this->spaces[boardSpaceColumn][boardSpaceRow].Color()); spaces[boardSpaceColumn][boardSpaceRow].SetOccupied(); for (int iside=0; iside<4; iside++){ if ((*(piece->TheSpaces())[is]).IsBorderOn(iside)) { (this->spaces[boardSpaceColumn][boardSpaceRow]).SetBorder(iside); } } } return 0; // 0 is the "normal" code } bool Board::AnyRedOrphans(){ for (int ired=0; ired<32; ired++){ if ( !(redSpaces[ired]->IsOccupied()) ){ int icol=redSpaces[ired]->Column(); int irow=redSpaces[ired]->Row(); // assume trapped and look around for a "way out" (i.e. a non-occupied black neighbor) // (it's actually the easiest way - recall taking an AND of many bits is same as taking NOT of the OR of the NOT bits bool trapped=true; if (icol > 0){if (!(spaces[icol-1][irow].IsOccupied())) trapped=false;} // checking to left if (icol < 7){if (!(spaces[icol+1][irow].IsOccupied())) trapped=false;} // checking to right if (irow > 0){if (!(spaces[icol][irow-1].IsOccupied())) trapped=false;} // checking above if (irow < 7){if (!(spaces[icol][irow+1].IsOccupied())) trapped=false;} // checking below if (trapped) return true; } } return false; } // this is just the same as AnyRedOrphans, except it looks for black ones, since I see that happen in the movie bool Board::AnyBlackOrphans(){ for (int ired=0; ired<32; ired++){ if ( !(blackSpaces[ired]->IsOccupied()) ){ int icol=blackSpaces[ired]->Column(); int irow=blackSpaces[ired]->Row(); // assume trapped and look around for a "way out" (i.e. a non-occupied black neighbor) // (it's actually the easiest way - recall taking an AND of many bits is same as taking NOT of the OR of the NOT bits bool trapped=true; if (icol > 0){if (!(spaces[icol-1][irow].IsOccupied())) trapped=false;} // checking to left if (icol < 7){if (!(spaces[icol+1][irow].IsOccupied())) trapped=false;} // checking to right if (irow > 0){if (!(spaces[icol][irow-1].IsOccupied())) trapped=false;} // checking above if (irow < 7){if (!(spaces[icol][irow+1].IsOccupied())) trapped=false;} // checking below if (trapped) return true; } } return false; } Board::Board(){ bool SetItBlack=true; // lower left hand corner is black, then it alternates int iBlackSpace=0; int iRedSpace=0; for (int row=0; row<8; row++){ for (int col=0; col<8; col++){ this->spaces[col][row].ResetSpace(); if (SetItBlack){ ((*this).spaces[col][row]).SetColor(black); blackSpaces[iBlackSpace] = &(spaces[col][row]); iBlackSpace++; } else { ((*this).spaces[col][row]).SetColor(red); redSpaces[iRedSpace] = &(spaces[col][row]); iRedSpace++; } SetItBlack = (!SetItBlack); ((*this).spaces[col][row]).SetColumnRow(col,row); } SetItBlack = (!SetItBlack); } } Space Board::NextAvailableBlackSpace(){ for (int ibs=0; ibs < 32; ibs++){ if (!(blackSpaces[ibs]->IsOccupied())) {return (*blackSpaces[ibs]);} } assert(0); // none available. either there is an error or the game is finished!! } void Board::Clear(){ for (int icol=0; icol<8; icol++){ for (int irow=0; irow<8; irow++){ this->Clear(icol,irow); } } } void Board::Clear(int icol, int irow){ (spaces[icol][irow]).ResetSpace(); } /* Drawing of each Space takes up 9 characters horizontally and 5 rows vertically .-------. |.......| |...X...| |.......| .-------. */ // this method below draws the board for use by paw macro // Tricky! void Board::DrawForPaw(){ float FilledRed = 1.0; float EmptyRed = 0.4; float EmptyBlack = -0.4; float FilledBlack = -1.0; cout << "vec/cre c(8,8) r "; for (int irow=0; irow<8; irow++){ cout << " _\n "; for (int icol=0; icol<8; icol++){ float level; if (spaces[icol][irow].Color()==red){ level = (spaces[icol][irow].IsOccupied())?FilledRed:EmptyRed; } else{ level = (spaces[icol][irow].IsOccupied())?FilledBlack:EmptyBlack; } cout << " " << level; } } cout << endl; cout << "hi/put/con 100 c \n"; cout << "lego 100 90 0 2 \n"; // now the borders - they are blue lines float epsilon = 0.04; for (int icol=0; icol<8; icol++){ float left = double(icol) + epsilon; float right = double(icol) + 1 - epsilon; for (int irow=0; irow<8; irow++){ float bottom = double(irow) + epsilon; float top = double(irow) + 1 - epsilon; if ((spaces[icol][irow]).IsBorderOn(0)) // top border cout << "line " << left << " " << top << " " << right << " " << top << endl; if ((spaces[icol][irow]).IsBorderOn(1)) // right border cout << "line " << right << " " << top << " " << right << " " << bottom << endl; if ((spaces[icol][irow]).IsBorderOn(2)) // bottom border cout << "line " << left << " " << bottom << " " << right << " " << bottom << endl; if ((spaces[icol][irow]).IsBorderOn(3)) // left border cout << "line " << left << " " << top << " " << left << " " << bottom << endl; } } // cout << "wait -10\n"; // cout << "***************\n"; } void Board::Draw(){ cout << endl; for (int irow=7; irow>-1; irow--){ // note nesting order of loops /* first the upper border */ for (int icol=0; icol<8; icol++){ if ((spaces[icol][irow]).IsBorderOn(0)){ cout << ".=======."; } else{ // cout << "........."; cout << " . . . . "; } } cout << endl; /* next the "empty space" above the symbol */ for (int icol=0; icol<8; icol++){ if ((spaces[icol][irow]).IsBorderOn(3)){ cout << "|"; } else{ cout << "."; } cout << " "; if ((spaces[icol][irow]).IsBorderOn(1)){ cout << "|"; } else{ cout << "."; } } cout << endl; /* next the middle row (which contains the symbol) */ for (int icol=0; icol<8; icol++){ if ((spaces[icol][irow]).IsBorderOn(3)){ cout << "|"; } else{ // cout << "."; cout << " "; } cout << " "; if ((spaces[icol][irow]).IsOccupied()){ if ((spaces[icol][irow]).Color() == red ){ cout << "R"; } else{ cout << "B"; } } else{ if ((spaces[icol][irow]).Color() == red ){ cout << "r"; } else{ cout << "b"; } } cout << " "; if ((spaces[icol][irow]).IsBorderOn(1)){ cout << "|"; } else{ // cout << "."; cout << " "; } } cout << endl; /* next the "empty space" below the symbol */ for (int icol=0; icol<8; icol++){ if ((spaces[icol][irow]).IsBorderOn(3)){ cout << "|"; } else{ cout << "."; } cout << " "; if ((spaces[icol][irow]).IsBorderOn(1)){ cout << "|"; } else{ cout << "."; } } cout << endl; /* finally the lower border */ for (int icol=0; icol<8; icol++){ if ((spaces[icol][irow]).IsBorderOn(2)){ cout << ".=======."; } else{ // cout << "........."; cout << " . . . . "; } } cout << endl; } cout << endl; }