//****************************************************************// // // // Copyright (c) 1997. // // Dr. Michael A. Redmond // // // // This software may not be distributed further without permission from // // Dr Michael A. Redmond. // // // // This software is distributed WITHOUT ANY WARRANTY. No claims are made // // as to its functionality or purpose. // // // // Title: Tw_Board.cpp // Description: abstraction for twixt board, includes peg places (including // empties) and links // Author: Dr Michael A. Redmond // // Date: 3/11/97 // // // // //****************************************************************// #include // #include // #include #include "my-math.h" #include "list.h" #include "point.h" #include "tw-color.h" #include "tw-peg.h" #include "tw-link.h" #if EXCEPT_HAND_ON // #include "exceptions.h" // #include #include #include // #include #endif #include "tw-board.h" // constructor which handles 0 or 1 args // 0 args creates a 20 X 20 (plus home rows) empty board // 1 arg creates a board of specified size (plus home rows) empty board Tw_Board::Tw_Board(const int size) : board_size(size), num_black_links(0), num_white_links(0) { int col_cnt, row_cnt; // done inefficiently - create an extra peg for each and assign it // mark corner positions as not on the board //DEBUG clog << "mark corner positions as not on the board " << endl; board_arr[0][0] = Tw_Peg(0,0,illegal); board_arr[0][size + 1] = Tw_Peg(0,size + 1,illegal); board_arr[size + 1][0] = Tw_Peg(size + 1,0,illegal); board_arr[size + 1][size + 1] = Tw_Peg(size + 1,size + 1,illegal); // do first home row //DEBUG clog << "do first home row " << endl; for (col_cnt = 1; col_cnt <= size; col_cnt++) { board_arr[0][col_cnt] = Tw_Peg(0,col_cnt,empty); } // do middle part of the board (including side home rows) //DEBUG clog << "do middle part of the board (including side home rows) " << endl; for (row_cnt = 1; row_cnt <= size; row_cnt++) { for (col_cnt = 0; col_cnt <= size + 1; col_cnt++) { board_arr[row_cnt][col_cnt] = Tw_Peg(row_cnt,col_cnt,empty); } } // do last home row //DEBUG clog << "do last home row " << endl; for (col_cnt = 1; col_cnt <= size; col_cnt++) { board_arr[size + 1][col_cnt] = Tw_Peg(size + 1,col_cnt,empty); } // debug constructor //clog << "debug board constructor" << endl; //for (row_cnt = 0; row_cnt <= size+1; row_cnt++) { // for (col_cnt = 0; col_cnt <= size + 1; col_cnt++) { // clog << board_arr[row_cnt][col_cnt]; // } // clog << endl; // } } // was planning on having a second board constructor which // could be passed an array of pegs, an array of black links, // an array of white links, and a size // This could be useful for testing - allowing starting someplace // other than the beginning of the game // The values for the parameters would have to be generated by // the client program Tw_Board::Tw_Board(Tw_Peg passed_board_arr[][MaxBoardArrayCols], Tw_Link black_links[], Tw_Link white_links[], int num_black, int num_white, int size) { int col_cnt; int row_cnt; // copy peg array for (col_cnt = 0; col_cnt <= size+1; col_cnt++) { for (row_cnt = 0; row_cnt <= size+1; row_cnt++) { board_arr[row_cnt][col_cnt] = passed_board_arr[row_cnt][col_cnt]; } } // make sure illegal positions are set correctly even if they were // not in the passed array // done inefficiently - create an extra peg for each and assign it // would like to do board_arr[0][0].SetPegColor(illegal); // but SetPegColor is not public and I'm not yet sure that I // really want to make board a friend of Peg board_arr[0][0] = Tw_Peg(0,0,illegal); board_arr[0][size + 1] = Tw_Peg(0,size + 1,illegal); board_arr[size + 1][0] = Tw_Peg(size + 1,0,illegal); board_arr[size + 1][size + 1] = Tw_Peg(size + 1,size + 1,illegal); // do black links for (int black_cnt = 0;black_cnt < num_black;black_cnt++) { list_of_black_links[black_cnt] = black_links[black_cnt]; } num_black_links = num_black; // do white links for (int white_cnt = 0;white_cnt < num_white;white_cnt++) { list_of_white_links[white_cnt] = white_links[white_cnt]; } num_black_links = num_black; } // report if there is any winner // depends on separate functions for black and white // because they go different directions // (black left to right, white top to bottom) Tw_Color Tw_Board::WhoWon() const { if (BlackWon()) { return black; } if (WhiteWon()) { return white; } // neither has won return empty; } // report if black is the winner bool Tw_Board::BlackWon() const { int size = GetBoardSize(); int row_cnt; Tw_Peg curr_peg; Tw_Peg first_home_pegs[size]; int num_first_home_pegs = 0; Tw_Peg last_home_pegs[size]; int num_last_home_pegs = 0; // start out by picking out any black pegs that are in the 0th col (left // home row // loop through all elements in home row (corners are illegal) for (row_cnt = 1; row_cnt < size; row_cnt++) { curr_peg = GetSpecPosit(row_cnt,0); if (curr_peg.GetPegColor() == black) { // found a black peg // add it to the list of black pegs in the first home row first_home_pegs[num_first_home_pegs] = curr_peg; num_first_home_pegs++; } } // next - pick out any black pegs that are in the last col (right // home row // loop through all elements in home row (corners are illegal) for (row_cnt = 1; row_cnt < size; row_cnt++) { curr_peg = GetSpecPosit(row_cnt,size+1); if (curr_peg.GetPegColor() == black) { // found a black peg // add it to the list of black pegs in the last home row last_home_pegs[num_last_home_pegs] = curr_peg; num_last_home_pegs++; } } // check if there is a continuous bridge from any of the pegs in // the first home row to any of the pegs in the last home row // if there is then black won, otherwise it hasn't yet won return Linkable(first_home_pegs,num_first_home_pegs, last_home_pegs,num_last_home_pegs); } // report if white is the winner bool Tw_Board::WhiteWon() const { int size = GetBoardSize(); int col_cnt; Tw_Peg curr_peg; Tw_Peg first_home_pegs[size]; int num_first_home_pegs = 0; Tw_Peg last_home_pegs[size]; int num_last_home_pegs = 0; // start out by picking out any white pegs that are in the 0th row (top // home row // loop through all elements in home row (corners are illegal) for (col_cnt = 1; col_cnt < size; col_cnt++) { curr_peg = GetSpecPosit(0,col_cnt); if (curr_peg.GetPegColor() == white) { // found a white peg // add it to the list of white pegs in the first home row first_home_pegs[num_first_home_pegs] = curr_peg; num_first_home_pegs++; } } // next - pick out any white pegs that are in the last row (bottom // home row // loop through all elements in home row (corners are illegal) for (col_cnt = 1; col_cnt < size; col_cnt++) { curr_peg = GetSpecPosit(size+1,col_cnt); if (curr_peg.GetPegColor() == white) { // found a white peg // add it to the list of white pegs in the last home row last_home_pegs[num_last_home_pegs] = curr_peg; num_last_home_pegs++; } } // check if there is a continuous bridge from any of the pegs in // the first home row to any of the pegs in the last home row // if there is then white won, otherwise it hasn't yet won return Linkable(first_home_pegs,num_first_home_pegs, last_home_pegs,num_last_home_pegs); } // probably only a service routine for BlackWon and WhiteWon bool Tw_Board::Linkable (const Tw_Peg first_home_pegs[],const int num_first_home_pegs, const Tw_Peg last_home_pegs[],const int num_last_home_pegs) const { int size = GetBoardSize(); int home_cnt; // if either of first home row or last home row is empty then we cannot // have a winner - return false if ((num_first_home_pegs == 0) || (num_last_home_pegs == 0)) { clog << "Debug - at least one home row is empty - no winner for sure" << endl; return false; } // since we have a peg in both first and last home rows // loop through all starting points, for each find all reachable // points (via links) // if any is on the opposite home row then we have a winner int num_reachable; Tw_Peg reachable_pegs[size * size]; int num_end_pts_reached = 0; Tw_Peg end_pts_reached[size]; bool result = false; for (home_cnt = 0;home_cnt < num_first_home_pegs;home_cnt++) { // find all pegs connected to the current home row peg num_reachable = FindAllLinkedPegs(first_home_pegs[home_cnt], reachable_pegs); clog << "Debug - number of pegs reachable from " << first_home_pegs[home_cnt] << " is " << num_reachable << endl; // find if any of them are in the home row num_end_pts_reached = ListIntersect(reachable_pegs,num_reachable, last_home_pegs,num_last_home_pegs, end_pts_reached); clog << "Debug - number of end points reachable is " << num_end_pts_reached << endl; if (num_end_pts_reached > 0) { // we have a solid link from one side to the other - the color // we are investigating wins result = true; } // otherwise just keep looking - we only need to get all of the way // across from ONE starting point } return result; } // pass back all the approp links and the count of them int Tw_Board::GetAllLinksForColor(Tw_Link approp_links[], const Tw_Color& color) const { int num; if (color == black) { num = GetBlackLinks(approp_links); } else { if (color == white) { num = GetWhiteLinks(approp_links); } else { num = 0; } } return num; } // pass back all the links and the count of them int Tw_Board::GetAllLinks(Tw_Link approp_links[]) const { int numwhite,numblack,total_num; int size = GetBoardSize(); Tw_Link white_links[size * size]; numblack = GetBlackLinks(approp_links); numwhite = GetWhiteLinks(white_links); total_num = append_list_of_objects_to_list(approp_links,numblack,white_links,numwhite); return total_num; } // pass back all the black links and the count of them int Tw_Board::GetBlackLinks(Tw_Link black_links[]) const { int link_cnt; int num_links = num_black_links; //DEBUG clog << "Ready to get list of black links with " << num_links << " links " << endl; for (link_cnt = 0; link_cnt < num_links; link_cnt++) { //DEBUG clog << "."; black_links[link_cnt] = list_of_black_links[link_cnt]; } //DEBUG clog << endl; return num_links; } // pass back all the black pegs and the count of them int Tw_Board::GetBlackPegs(Tw_Peg black_pegs[]) const { int peg_cnt; int row_cnt; int col_cnt; int num_pegs = 0; Tw_Peg curr_peg; Tw_Color curr_color; // go through all pegs in board checking each to see if it is black for (row_cnt = 0; row_cnt <= GetBoardSize() + 1; row_cnt++) { for (col_cnt = 0; col_cnt <= GetBoardSize() + 1; col_cnt++) { // get peg curr_peg = GetSpecPosit(row_cnt,col_cnt); // find out color curr_color = curr_peg.WhatColor(); if (curr_color == black) { // if black add to set of black pegs and update count black_pegs[num_pegs] = curr_peg; num_pegs++; } } } return num_pegs; } // pass back all the white links and the count of them int Tw_Board::GetWhiteLinks(Tw_Link white_links[]) const { int link_cnt; int num_links = num_white_links; //DEBUG clog << "Ready to get list of white links with " << num_links << " links " << endl; for (link_cnt = 0; link_cnt < num_links; link_cnt++) { //DEBUG clog << "."; white_links[link_cnt] = list_of_white_links[link_cnt]; } //DEBUG clog << endl; return num_links; } // pass back all the white pegs and the count of them int Tw_Board::GetWhitePegs(Tw_Peg white_pegs[]) const { int row_cnt; int col_cnt; int num_pegs = 0; Tw_Peg curr_peg; Tw_Color curr_color; // go through all pegs in board checking each to see if it is white for (row_cnt = 0; row_cnt <= GetBoardSize() + 1; row_cnt++) { for (col_cnt = 0; col_cnt <= GetBoardSize() + 1; col_cnt++) { // get peg curr_peg = GetSpecPosit(row_cnt,col_cnt); // find out color curr_color = curr_peg.WhatColor(); if (curr_color == white) { // if white add to set of white pegs and update count white_pegs[num_pegs] = curr_peg; num_pegs++; } } } return num_pegs; } // pass back all the empty places and the count of them int Tw_Board::GetEmptyPlaces(Tw_Peg empty_places[]) const { int row_cnt; int col_cnt; int num_places = 0; Tw_Peg curr_peg; Tw_Color curr_color; // go through all places in board checking each to see if it is empty for (row_cnt = 0; row_cnt <= GetBoardSize() + 1; row_cnt++) { for (col_cnt = 0; col_cnt <= GetBoardSize() + 1; col_cnt++) { // get peg curr_peg = GetSpecPosit(row_cnt,col_cnt); // find out color curr_color = curr_peg.WhatColor(); if (curr_color == empty) { // if empty add to set of empty places and update count empty_places[num_places] = curr_peg; num_places++; } } } return num_places; } // report all links that exist in the board involving the given position // this code is based on the assumption that black links and white links // are kept separately. If they were kept together and we had a function // getalllinks, then the code below could be made simpler int Tw_Board::GetLinksForPosition(const Tw_Peg& peg, Tw_Link return_links[]) const { int link_cnt; int num_links = 0; bool got_one = false; int num_black; // = GetNumBlackLinks(); int num_white; // = GetNumWhiteLinks(); Tw_Peg curr_link_start; Tw_Peg curr_link_end; Tw_Link black_links[max_board_size * max_board_size]; // find out how many black links and get them // going through GetBlackLinks has a cost, because it // essentially copies the links to a different array // couldnt do in initiallization because couldn't assignwhole array num_black = GetBlackLinks(black_links); for (link_cnt = 0;link_cnt < num_black;link_cnt++) { curr_link_start = black_links[link_cnt].GetStartPeg(); curr_link_end = black_links[link_cnt].GetEndPeg(); if ((curr_link_start == peg) || (curr_link_end == peg)) { // either start or end peg in the link is the one we are looking for // mark that we found a link - important because we should // only have black OR white links for a given peg, not both got_one = true; // include current link in the list to be returned and increment // the count of number of links found return_links[num_links] = black_links[link_cnt]; num_links++; } } if (!got_one) { // if didn't find at least one black link try looking for white links Tw_Link white_links[max_board_size * max_board_size]; // find out how many white links and get them // going through GetWhiteLinks has a cost, because it // essentially copies the links to a different array // couldnt do in initiallization because couldn't assignwhole array num_white = GetWhiteLinks(white_links); for (link_cnt = 0;link_cnt < num_white;link_cnt++) { curr_link_start = white_links[link_cnt].GetStartPeg(); curr_link_end = white_links[link_cnt].GetEndPeg(); if ((curr_link_start == peg) || (curr_link_end == peg)) { // either start or end peg in the link is the one we are looking for // include current link in the list to be returned and increment // the count of number of links found return_links[num_links] = white_links[link_cnt]; num_links++; } } // end for } // end if not got_one return num_links; } // report all links that exist in the board involving the given position // this code is based on the assumption that black links and white links // are kept separately. If they were kept together and we had a function // getalllinks, then the code below could be made simpler int Tw_Board::GetLinksForPosition(const Point& pos, Tw_Link return_links[]) const { int link_cnt; int num_links = 0; bool got_one = false; int num_black; // = GetNumBlackLinks(); int num_white; // = GetNumWhiteLinks(); Point curr_link_start_pos; Point curr_link_end_pos; Tw_Link black_links[max_board_size * max_board_size]; // find out how many black links and get them // going through GetBlackLinks has a cost, because it // essentially copies the links to a different array // couldnt do in initiallization because couldn't assignwhole array num_black = GetBlackLinks(black_links); for (link_cnt = 0;link_cnt < num_black;link_cnt++) { curr_link_start_pos = black_links[link_cnt].GetStartPeg().GetPosition(); curr_link_end_pos = black_links[link_cnt].GetEndPeg().GetPosition(); if ((curr_link_start_pos == pos) || (curr_link_end_pos == pos)) { // either start or end pos in the link is the one we are looking for // mark that we found a link - important because we should // only have black OR white links for a given pos, not both got_one = true; // include current link in the list to be returned and increment // the count of number of links found return_links[num_links] = black_links[link_cnt]; num_links++; } } if (!got_one) { // if didn't find at least one black link try looking for white links Tw_Link white_links[max_board_size * max_board_size]; // find out how many white links and get them // going through GetWhiteLinks has a cost, because it // essentially copies the links to a different array // couldnt do in initiallization because couldn't assignwhole array num_white = GetWhiteLinks(white_links); for (link_cnt = 0;link_cnt < num_white;link_cnt++) { curr_link_start_pos = white_links[link_cnt].GetStartPeg().GetPosition(); curr_link_end_pos = white_links[link_cnt].GetEndPeg().GetPosition(); if ((curr_link_start_pos == pos) || (curr_link_end_pos == pos)) { // either start or end pos in the link is the one we are looking for // include current link in the list to be returned and increment // the count of number of links found return_links[num_links] = white_links[link_cnt]; num_links++; } } // end for } // end if not got_one return num_links; } bool Tw_Board::LegalPositionToPlace(const Tw_Peg& potential_peg, const Tw_Color& color) const { // if black, playing left to right and rows 0 and size+1 are illegal // if white, playing top to bottom and cols 0 and size+1 are illegal // if position is not empty then illegal // pull out coordinates of the potential new placement Point pos = potential_peg.GetPosition(); int row = pos.GetRow(); int col = pos.GetCol(); // Find the color of the potential new placement in the current board Tw_Peg curr_peg = GetSpecPosit(row,col); Tw_Color curr_color = curr_peg.GetPegColor(); // check that position is available if (curr_color != empty) { // cant put a peg in a non empty spot return false; } // check if position is legal for this color Tw_Color potential_color = potential_peg.GetPegColor(); if (potential_color == black) { if ((row == 0) || (row == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } if (potential_color == white) { if ((col == 0) || (col == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } } bool Tw_Board::LegalPositionToPlace(const Point& potential_pos, const Tw_Color& potential_color) const { // if black, playing left to right and rows 0 and size+1 are illegal // if white, playing top to bottom and cols 0 and size+1 are illegal // if position is not empty then illegal // pull out coordinates of the potential new placement int row = potential_pos.GetRow(); int col = potential_pos.GetCol(); // Find the color of the potential new placement in the current board Tw_Peg curr_peg = GetSpecPosit(row,col); Tw_Color curr_color = curr_peg.GetPegColor(); // check that position is available if (curr_color != empty) { // cant put a peg in a non empty spot return false; } // check if position is legal for this color if (potential_color == black) { if ((row == 0) || (row == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } if (potential_color == white) { if ((col == 0) || (col == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } } bool Tw_Board::LegalPositionToPlace(const int poten_row, const int poten_col, const Tw_Color& potential_color) const { // if black, playing left to right and rows 0 and size+1 are illegal // if white, playing top to bottom and cols 0 and size+1 are illegal // if position is not empty then illegal // Find the color of the potential new placement in the current board Tw_Peg curr_peg = GetSpecPosit(poten_row,poten_col); Tw_Color curr_color = curr_peg.GetPegColor(); // check that position is available if (curr_color != empty) { // cant put a peg in a non empty spot return false; } // check if position is legal for this color if (potential_color == black) { if ((poten_row == 0) || (poten_row == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } if (potential_color == white) { if ((poten_col == 0) || (poten_col == GetBoardSize()+1)) { // cant put peg in opponents home row return false; } else return true; } } // check that a peg exists as advertised on the board bool Tw_Board::PegThere (const Tw_Peg& testpeg) const { bool result = false; int row = testpeg.GetPosition().GetRow(); int col = testpeg.GetPosition().GetCol(); //Tw_Color = testpeg.GetPegColor(); Tw_Peg actualpeg = GetSpecPosit(row,col); if (testpeg == actualpeg) { return true; } else return false; } // determine if this is a legal link to add to the board // link must not be blocked by own or opponents links bool Tw_Board::LegalLink(const Tw_Link& potential_link) const { // check to make sure pegs are really such on the board // we dont take pegs implicitly from a link being specified //DEBUG3 clog << "in LegalLink" << endl; int size = GetBoardSize(); Tw_Link curr_links[size * size]; Tw_Peg startpeg = potential_link.GetStartPeg(); Tw_Peg endpeg = potential_link.GetEndPeg(); Tw_Color link_color = potential_link.GetLinkColor(); if (!PegThere(startpeg) || !PegThere(endpeg)) { //DEBUG3 clog << "Debug - LegalLink - peg(s) not there " << endl; return false; } // check to make sure link isn't blocked // if any of the current links conflict with the potential link // (even a link of the same color) // then the link is blocked // (cant even cross own links) // NOTE: also shouldn't be able to have a link that shares // a link with the opponents peg - but that should be caught // above since the peg shouldn't be able to be there int num_links = GetAllLinks(curr_links); bool blocked = false; for (int link_cnt = 0; link_cnt < num_links; link_cnt++) { if (potential_link.Conflict(curr_links[link_cnt])) { //DEBUG3 clog << "Debug - LegalLink - conflict between " << potential_link << " and " << curr_links[link_cnt] << endl; blocked = true; } } //DEBUG3 clog << "in LegalLink - blocked: " << blocked << endl; return !blocked; } bool Tw_Board::LegalLink(const Tw_Peg& startpeg, const Tw_Peg& endpeg) const { // check to make sure pegs are really such on the board // we dont take pegs implicitly from a link being specified //DEBUG3 clog << "DEBUG: checking two pegs for legal link " << endl; int size = GetBoardSize(); Tw_Link potential_link; Tw_Link curr_links[size * size]; if (!PegThere(startpeg) || !PegThere(endpeg)) { //DEBUG3 clog << "DEBUG: one of the two pegs is not on the board " << endl; return false; } #if EXCEPT_HAND_ON // set up exception handling area try { #endif Tw_Link temp_link(startpeg,endpeg); potential_link = temp_link; #if EXCEPT_HAND_ON } // respond to illegal link exceptions catch(Tw_Link::illegal_link) { clog << "DEBUG: in catch illegal_link in LegalLink method " << endl; // would use display method for illegal_link class if I'd defined it // respond: // in this case just return that the link is not legal // allows the client to go on - knowing that the link is not legal return false; } catch(...) { // catch anthing else //DEBUG3 clog << "DEBUG: wasn't supposed to get here" << endl; } #endif // check to make sure link isn't blocked // if any of the current links conflict with the potential link // (even a link of the same color) // then the link is blocked // (cant even cross own links) // NOTE: also shouldn't be able to have a link that shares // a link with the opponents peg - but that should be caught // above since the peg shouldn't be able to be there int num_links = GetAllLinks(curr_links); bool blocked = false; for (int link_cnt = 0; link_cnt < num_links; link_cnt++) { if (potential_link.Conflict(curr_links[link_cnt])) { blocked = true; } } // if not blocked then it is a legal link return !blocked; } bool Tw_Board::LegalLink(const Point& startpos, const Point& endpos, const Tw_Color& color) const { // check to make sure pegs are really such on the board // we dont take pegs implicitly from a link being specified int size = GetBoardSize(); Tw_Link curr_links[size * size]; Tw_Peg startpeg(startpos,color); Tw_Peg endpeg(endpos,color); //EH Tw_Link potential_link(startpeg,endpeg); #if EXCEPT_HAND_ON Tw_Link potential_link; // set up exception handling area try { #endif Tw_Link potential_link(startpeg,endpeg); #if EXCEPT_HAND_ON } // respond to illegal link exceptions catch(Tw_Link::illegal_link) { //DEBUG3 clog << "DEBUG: in catch illegal_link in LegalLink method " << endl; // would use display method for illegal_link class if I'd defined it // respond: // in this case just return that the link is not legal // allows the client to go on - knowing that the link is not legal return false; } catch(...) { // catch anthing else clog << "DEBUG: wasn't supposed to get here" << endl; } #endif if (!PegThere(startpeg) || !PegThere(endpeg)) { return false; } // check to make sure link isn't blocked // if any of the current links conflict with the potential link // (even a link of the same color) // then the link is blocked // (cant even cross own links) // NOTE: also shouldn't be able to have a link that shares // a link with the opponents peg - but that should be caught // above since the peg shouldn't be able to be there int num_links = GetAllLinks(curr_links); bool blocked = false; for (int link_cnt = 0; link_cnt < num_links; link_cnt++) { if (potential_link.Conflict(curr_links[link_cnt])) { blocked = true; } } return !blocked; } bool Tw_Board::LegalLink(const int startrow, const int startcol, const int endrow, const int endcol, const Tw_Color& color) const { // check to make sure pegs are really such on the board // we dont take pegs implicitly from a link being specified int size = GetBoardSize(); Tw_Link curr_links[size * size]; Tw_Peg startpeg(startrow,startcol,color); Tw_Peg endpeg(endrow,endcol,color); //EH Tw_Link potential_link(startpeg,endpeg); #if EXCEPT_HAND_ON Tw_Link potential_link; // set up exception handling area try { #endif Tw_Link potential_link(startpeg,endpeg); #if EXCEPT_HAND_ON } // respond to illegal link exceptions catch(Tw_Link::illegal_link) { clog << "DEBUG: in catch illegal_link in LegalLink method " << endl; // would use display method for illegal_link class if I'd defined it // respond: // in this case just return that the link is not legal // allows the client to go on - knowing that the link is not legal return false; } catch(...) { // catch anthing else clog << "DEBUG: wasn't supposed to get here" << endl; } #endif if (!PegThere(startpeg) || !PegThere(endpeg)) { return false; } // check to make sure link isn't blocked // if any of the current links conflict with the potential link // (even a link of the same color) // then the link is blocked // (cant even cross own links) // NOTE: also shouldn't be able to have a link that shares // a link with the opponents peg - but that should be caught // above since the peg shouldn't be able to be there int num_links = GetAllLinks(curr_links); bool blocked = false; for (int link_cnt = 0; link_cnt < num_links; link_cnt++) { if (potential_link.Conflict(curr_links[link_cnt])) { blocked = true; } } return !blocked; } // find all legal potential links for a given position int Tw_Board::FindLegalPotentialLinksForPosition(const Tw_Peg& peg, Tw_Link return_links[]) const { const int num_neighs = 8; int legal_cnt = 0; Point neighs[num_neighs]; Tw_Color curr_color = peg.GetPegColor(); // find all positions the right distance from the current peg // check if the right color peg is alraedy on the board at // that position // and if so check if they form a legal link peg.AllOffsets(neighs); for (int cnt = 0;cnt < num_neighs; cnt++) { Tw_Peg potential_peg(neighs[cnt],curr_color); if (PegThere(potential_peg)) { // if (LegalPositionToPlace(neighs[cnt],curr_color)) { if (LegalLink(potential_peg,peg)) { // a potential link // add to list and update counter clog << "potential link found between " << peg << " and " << potential_peg; return_links[legal_cnt] = Tw_Link(potential_peg,peg); clog << return_links[legal_cnt] << endl; legal_cnt++; } } } return legal_cnt; } // mutators - establish new values of attributes (data members) // if the position is free fill with specified color // and return true otherwise return false bool Tw_Board::PlacePeg(const int row, const int colm, const Tw_Color& col) { if (LegalPositionToPlace(row,colm, col)) { // construct a peg to put in the board Tw_Peg temp_peg(row,colm,col); board_arr[row][colm] = temp_peg; return true; } else { return false; } } bool Tw_Board::PlacePeg(const Point& pos, const Tw_Color& col) { if (LegalPositionToPlace(pos, col)) { int row = pos.GetRow(); int colm = pos.GetCol(); // construct a peg to put in the board Tw_Peg temp_peg(row,colm,col); board_arr[row][colm] = temp_peg; return true; } else { return false; } } bool Tw_Board::PlacePeg(const Tw_Peg& peg, const Tw_Color& col) { if (LegalPositionToPlace(peg, col)) { int row = peg.GetPosition().GetRow(); int colm = peg.GetPosition().GetCol(); // wasteful but wanted to make sure peg passed had approp color Tw_Peg temp_peg(row,colm,col); board_arr[row][colm] = temp_peg; return true; } else { return false; } } bool Tw_Board::PlacePeg(const Tw_Peg& peg) { Tw_Color col = peg.GetPegColor(); if (LegalPositionToPlace(peg, col)) { int row = peg.GetPosition().GetRow(); int colm = peg.GetPosition().GetCol(); // wasteful but wanted to make sure peg passed had approp color Tw_Peg temp_peg(row,colm,col); board_arr[row][colm] = temp_peg; return true; } else { return false; } } // if the link is legal then add link to the board // and return true otherwise return false bool Tw_Board::PlaceLink(const Tw_Link& link) { bool result; //DEBUG3 clog << "Debug - in PlaceLink " << endl; if (LegalLink(link)) { // prob need to check that it's not already there but skip that // for now //DEBUG3 clog << "Debug - PlaceLink - link is legal" << endl; Tw_Color color = link.GetLinkColor(); //DEBUG3 clog << "Debug - in PlaceLink - color: " << color << endl; result = false; // will return failure if the color is wrong if (color == black) { // add to end of black links list_of_black_links[num_black_links] = link; num_black_links++; result = true; } if (color == white) { // add to end of white links list_of_white_links[num_white_links] = link; num_white_links++; result = true; } return result; } else { // not legal to add return false; } } bool Tw_Board::PlaceLink(const Tw_Peg& peg1, const Tw_Peg& peg2) { bool result; if (LegalLink(peg1,peg2)) { // prob need to check that it's not already there but skip that // for now // create new link (link constructor checks distance and colors) Tw_Link link(peg1,peg2); // really we need a way to handle links not created here // since constructor checks things // currently if the pegs have diff colors the next statement // will have an uninitialized color Tw_Color color = link.GetLinkColor(); result = false; // will return failure if the color is wrong if (color == black) { // add to end of black links list_of_black_links[num_black_links] = link; num_black_links++; result = true; } if (color == white) { // add to end of white links list_of_white_links[num_white_links] = link; num_white_links++; result = true; } return result; } else { // not legal to add return false; } } bool Tw_Board::PlaceLink(const Point& pos1, const Point& pos2, const Tw_Color& col) { bool result; if (LegalLink(pos1,pos2,col)) { // prob need to check that it's not already there but skip that // for now // create new link (link constructor checks distance and colors) Tw_Link link(pos1,pos2,col); // really we need a way to handle links not created here // since constructor checks things // currently if the pegs have diff colors the next statement // will have an uninitialized color Tw_Color color = link.GetLinkColor(); result = false; // will return failure if the color is wrong // the code below is showing up a lot of versions of this funct // maybe should make it a protected mutator if (color == black) { // add to end of black links list_of_black_links[num_black_links] = link; num_black_links++; result = true; } if (color == white) { // add to end of white links list_of_white_links[num_white_links] = link; num_white_links++; result = true; } return result; } else { // not legal to add return false; } } bool Tw_Board::PlaceLink(const int startrow, const int startcol, const int endrow, const int endcol, const Tw_Color& col) { bool result; if (LegalLink(startrow,startcol,endrow, endcol,col)) { // prob need to check that it's not already there but skip that // for now // create new link (link constructor checks distance and colors) Tw_Link link(startrow, startcol,endrow, endcol,col); // really we need a way to handle links not created here // since constructor checks things // currently if the link is not legal it will not be created // and the following statements will be working with an uninitialized link obj result = false; // will return failure if the color is wrong // the code below is showing up a lot of versions of this funct // maybe should make it a protected mutator if (col == black) { // add to end of black links list_of_black_links[num_black_links] = link; num_black_links++; result = true; } if (col == white) { // add to end of white links list_of_white_links[num_white_links] = link; num_white_links++; result = true; } return result; } else { // not legal to add return false; } } // facilitators // find chain of linked pegs from a given peg // returns number of linked pegs in list int Tw_Board::FindAllLinkedPegs(const Tw_Peg& startpeg, Tw_Peg return_pegs[]) const { int curr_pt; int check_cnt; int link_cnt; int pt_cnt; // set up lists of checked and unchecked points int num_checked_pts = 0; int num_unchecked_pts = 1; int num_new_pts = 0; Tw_Peg checked_pts[max_board_size * max_board_size]; Tw_Peg unchecked_pts[max_board_size * max_board_size]; Tw_Peg new_pts[max_board_size * max_board_size]; unchecked_pts[0] = startpeg; // set up list of links for the appropriate color Tw_Color curr_color = startpeg.GetPegColor(); Tw_Link approp_links[max_board_size * max_board_size]; // find all links for the current color int num_links = GetAllLinksForColor(approp_links,curr_color); // loop as long as there are unchecked points while (num_unchecked_pts > 0) { // start keeping track of new points that are linked to unchecked // points num_new_pts = 0; // loop through all unchecked points looking for links for (curr_pt = 0;curr_pt < num_unchecked_pts; curr_pt++) { // make sure point really is unchecked (and not a newly generated // but already checked point bool new_point = true; for (check_cnt = 0;check_cnt < num_checked_pts;check_cnt++) { if (unchecked_pts[curr_pt] == checked_pts[check_cnt]) { // already checked new_point = false; } } // if new point has been found include it in the list of checked // points - which is the list of reachable points // and find what will be the next set of potentially unchecked // points if (new_point) { checked_pts[num_checked_pts] = unchecked_pts[curr_pt]; num_checked_pts++; // find points that are directly linked to the current point for (link_cnt = 0; link_cnt < num_links;link_cnt++) { // check each link to see if it is linked directly to // the current point if (approp_links[link_cnt].peg_part_of_link(unchecked_pts[curr_pt])) { // linked directly - so add to set of new points new_pts[num_new_pts] = approp_links[link_cnt].other_part_of_link(unchecked_pts[curr_pt]); num_new_pts++; } // end if approp links } // end for link_cnt } // end if new point } // end for curr_pt // the new_points generated are now the potential unchecked points // (the previous unchecked points have now all been checked) // but before looping again - eliminate duplicates and any points // on the checked list // 1. remove duplicates // should probably be written with template so we have // avail for removing duplicate links, etc num_new_pts = remove_dup_objects(new_pts, num_new_pts); // 2. remove pegs already checked // should probably be written with template so we have // avail for removing any kind of list from another list // of the same type num_new_pts = remove_list_objects_from_list(checked_pts, num_checked_pts,new_pts, num_new_pts); // 3. update unchecked point list for (pt_cnt = 0;pt_cnt < num_new_pts;pt_cnt++) { unchecked_pts[pt_cnt] = new_pts[pt_cnt]; } num_unchecked_pts = num_new_pts; } // end while loop // set up return for (pt_cnt = 0;pt_cnt < num_checked_pts;pt_cnt++) { return_pegs[pt_cnt] = checked_pts[pt_cnt]; } return num_checked_pts; } /// BELOW WAS MOVED TO LIST.H WHERE IT WAS MADE A TEMPLATE /// // remove duplicate pegs from a list of pegs /// //global function rather than in class /// int remove_dup_points(Tw_Peg peglist[], num_pegs) { /// bool dup_found = true; /// Tw_Peg temppeg; /// /// while (dup_found) { /// // keep looping as long as we find a duplicate /// dup_found = false; /// int peg_cnt = 0; /// while (!dup_found && (peg_cnt < num_pegs-1)) { /// // go through all the rest looking for dup for each /// int inner_cnt = peg_cnt + 1; /// while (!dup_found && (inner_cnt < num_pegs)) { /// // check any after the current one for a duplicate /// if (peglist[peg_cnt] == peglist[inner_cnt]) { /// // found a dup /// dup_found = true; /// // swap the second with the last and decrement the count /// // and force an end to the loop to go back in with correct /// // number of pegs /// temppeg = peglist[inner_cnt]; /// peglist[inner_cnt] = peglist[num_pegs - 1]; /// peglist[num_pegs - 1] = temppeg; /// num_pegs--; /// } // end if /// } // end inner while /// } // end middle while /// } // end outer while /// return num_pegs; /// } // end function /// /// /// /// // remove duplicate pegs from a list of pegs /// //global function rather than in class /// int remove_list_points_from_list(const Tw_Peg& pegs_to_rem, const int num_pegs_to_rem, Tw_Peg& startpeglist[], num_pegs) { /// bool match_found = true; /// Tw_Peg temppeg; /// /// match_found = false; /// int match_peg_cnt = 0; /// while (match_peg_cnt < num_pegs_to_rem) { /// // go through second list looking for match for each /// int source_cnt = 0; /// while (source_cnt < num_pegs) { /// // check any after the current one for a duplicate /// if (pegs_to_rem[match_peg_cnt] == startpeglist[source_cnt]) { /// // found a match /// match_found = true; /// // swap the second with the last and decrement the count /// temppeg = startpeglist[source_cnt]; /// startpeglist[source_cnt] = startpeglist[num_pegs - 1]; /// startpeglist[num_pegs - 1] = temppeg; /// num_pegs--; /// } // end if /// } // end inner while /// } // end middle while /// } // end outer while /// return num_pegs; /// } // end function // MAJOR WORK STARTS HERE // place peg on a board should go under board // some stream facilitators // draw board void Tw_Board::DrawBoard(ostream &sout) const { int size = GetBoardSize(); //DEBUG clog << "Ready to draw board with size: " << size << endl; if (size < 11) { DrawScaledPrettyBoard(sout, 4); } else { if (size < 16) { DrawScaledPrettyBoard(sout, 2); } else { if (size < 32) { DrawScaledPrettyBoard(sout, 1); } else { DrawSimpleBoardWLinks(sout); } // end far inner else } // end middle else } // end outer else } // draw nice scaled pretty board void Tw_Board::DrawSimpleBoardWLinks(ostream &sout) const { int size = GetBoardSize(); const int num_rows = size + 2; const int num_cols = size + 2; // print a representation for the color of the peg // loop through rows for (int row_cnt = 0;row_cnt < num_rows; row_cnt++) { sout << endl << "==> "; // loop through columns for (int col_cnt = 0;col_cnt < num_cols; col_cnt++) { Tw_Peg curr_peg = GetSpecPosit(row_cnt,col_cnt); Tw_Color curr_col = curr_peg.GetPegColor(); // need to put letter for the color B W . for empty blank for illegal sout << " " << curr_col.GetCharRep() << " "; } } PrintBoardLinks(sout); } // draw nice scaled pretty board void Tw_Board::DrawScaledPrettyBoard(ostream &sout, const int magnif) const { //DEBUG clog << "Ready to draw scaled pretty board with magnification: " << magnif << endl; int size = GetBoardSize() + 2; int num_rows = size * magnif; int num_cols = 2 * size * magnif; int prin_row, prin_col; //DEBUG clog << " num rows in print array: " << num_rows << endl; //char print_arr[size * magnif][2 * size * magnif]; char print_arr[MaxPrintArrayRows][MaxPrintArrayCols]; //DEBUG clog << " Print array size is " << size * magnif << " by " << 2 * size * magnif << endl; //DEBUG clog << " Print array address is " << &print_arr << endl; //DEBUG clog << " board array address is " << &board_arr << endl; // initialize the print array to all blanks // loop through rows for (prin_row = 0;prin_row < num_rows; prin_row++) { // loop through columns for (prin_col = 0;prin_col < num_cols; prin_col++) { print_arr[prin_row][prin_col] = ' '; } } // create a character representation of the board to be printed //DEBUG2 clog << "Ready to create print array for scaled pretty board" << endl; CreatePrintArray(print_arr,magnif); //DEBUG2 clog << " After CreatePrintArray PrintArray[0][0] = " << print_arr[0][0] << endl; //DEBUG2 clog << "Ready to print print array for scaled pretty board" << endl; //DEBUG2 clog << " num rows in print array: " << num_rows << endl; PrintPrintArray(sout,print_arr,num_rows); //DEBUG2 clog << "Ready to print list of links for scaled pretty board" << endl; PrintBoardLinks(sout); } // create a character representation of the board to be printed void Tw_Board::CreatePrintArray(char print_arr[][MaxPrintArrayCols], const int magnif) const { const int size = GetBoardSize(); const int num_rows = size + 2; const int num_cols = size + 2; /* const int num_rows = GetBoardSize() + 2; const int num_cols = GetBoardSize() + 2; */ Tw_Link black_links[size * size]; Tw_Link white_links[size * size]; const int new_num_rows = magnif * num_rows; const int new_num_cols = 2 * magnif * num_cols; Tw_Peg curr_peg; int prin_row, prin_col; int row_cnt, col_cnt; // debug board contents // clog << "debug board contents in Create PrintArray" << endl; // for (row_cnt = 0; row_cnt <= size+1; row_cnt++) { // for (col_cnt = 0; col_cnt <= size + 1; col_cnt++) { // clog << board_arr[row_cnt][col_cnt]; // } // clog << endl; // } // debug board contents // clog << "debug board contents in Create PrintArray" << endl; // for (row_cnt = 0; row_cnt <= size+1; row_cnt++) { // for (col_cnt = 0; col_cnt <= size + 1; col_cnt++) { // clog << GetSpecPosit(row_cnt,col_cnt); // } // clog << endl; // } // initialize the print array to all blanks // loop through rows for (prin_row = 0;prin_row < new_num_rows; prin_row++) { // loop through columns for (prin_col = 0;prin_col < new_num_cols; prin_col++) { print_arr[prin_row][prin_col] = ' '; } } //DEBUG2 clog << " In CreatePrintArray after init PrintArray[0][0] = " << print_arr[0][0] << endl; // debug print array contents // clog << "debug print array contents in Create PrintArray" << endl; // for (prin_row = 0; prin_row < new_num_rows; prin_row++) { // for (prin_col = 0; prin_col < new_num_cols; prin_col++) { // clog << print_arr[prin_row][prin_col]; // } // clog << "|" << endl; // } // debug board contents //clog << "debug board contents in Create PrintArray" << endl; //for (row_cnt = 0; row_cnt <= size+1; row_cnt++) { // for (col_cnt = 0; col_cnt <= size + 1; col_cnt++) { // clog << board_arr[row_cnt][col_cnt]; // } // clog << endl; // } // put the actual pegs in the print array (actually just a rep for their color // loop through rows for (row_cnt = 0;row_cnt < num_rows; row_cnt++) { prin_row = magnif * row_cnt; // loop through columns for (col_cnt = 0;col_cnt < num_cols; col_cnt++) { prin_col = 2 * magnif * col_cnt; // Tw_Peg curr_peg = GetSpecPosit(row_cnt,col_cnt); //DEBUG clog << "==> " << GetSpecPosit(row_cnt,col_cnt) << " "; //DEBUG clog << board_arr[row_cnt][col_cnt] << " "; curr_peg = GetSpecPosit(row_cnt,col_cnt); Tw_Color curr_col = curr_peg.GetPegColor(); // need to put letter for the color B W . for empty blank for illegal print_arr[prin_row][prin_col] = curr_col.GetCharRep(); //DEBUG clog << "DEBUG(row,col,curr_peg,prin_row,prin_col,color,color_rep): " << row_cnt << " " << col_cnt << " " << curr_peg << " " << prin_row << " " << prin_col << " " << curr_col << " " << curr_col.GetCharRep() << endl; } } //DEBUG2 clog << " In CreatePrintArray after pegs placed PrintArray[0][0] = " << print_arr[0][0] << endl; // put the links into the print array int num_black = GetBlackLinks(black_links); int num_white = GetWhiteLinks(white_links); for (int link_cnt = 0;link_cnt < num_black; link_cnt++) { AddLinkToPrintArray(print_arr, black, black_links[link_cnt], magnif); } for (int link_cnt = 0;link_cnt < num_white; link_cnt++) { AddLinkToPrintArray(print_arr, white, white_links[link_cnt], magnif); } //DEBUG2 clog << " In CreatePrintArray after links placed PrintArray[0][0] = " << print_arr[0][0] << endl; } // add a link to a character representation of the board to be printed void Tw_Board::AddLinkToPrintArray(char print_arr[][MaxPrintArrayCols], const Tw_Color curr_color, const Tw_Link& curr_link, const int magnif) const { // pull out coordinates of the link int start_row = curr_link.GetStartPeg().GetPosition().GetRow(); int start_col = curr_link.GetStartPeg().GetPosition().GetCol(); int end_row = curr_link.GetEndPeg().GetPosition().GetRow(); int end_col = curr_link.GetEndPeg().GetPosition().GetCol(); // get lower case char for link color //char color_char = curr_link.GetLinkColor().GetCharRep(); char color_char = curr_link.GetCharRep(); // convert coordinates to size based on magnification // columns get extra space int conv_start_row = start_row * magnif; int conv_start_col = start_col * magnif * 2; int conv_end_row = end_row * magnif; int conv_end_col = end_col * magnif * 2; // put mark midway between start and end points // first find mid-points float mid_row = (conv_start_row + conv_end_row) / 2.0; float mid_col = (conv_start_col + conv_end_col) / 2.0; // then check if they are close to an integer int mid_row_int = static_cast(mid_row); int mid_col_int = static_cast(mid_col); float row_diff = myabs(mid_row - mid_row_int); float col_diff = myabs(mid_col - mid_col_int); if ((row_diff < 0.01) && (col_diff < 0.01)) { // put color in this position in the print array print_arr[mid_row_int][mid_col_int] = color_char; // now see if we can show the link in greater detail // find 1/4 and 3/4 points and see if they are integer float early_row = (conv_start_row + mid_row) / 2.0; float early_col = (conv_start_col + mid_col) / 2.0; float late_row = (conv_end_row + mid_row) / 2.0; float late_col = (conv_end_col + mid_col) / 2.0; int early_row_int = static_cast(early_row); int early_col_int = static_cast(early_col); int late_row_int = static_cast(late_row); int late_col_int = static_cast(late_col); row_diff = myabs(early_row - early_row_int); col_diff = myabs(early_col - early_col_int); if ((row_diff < 0.01) && (col_diff < 0.01)) { // put color in this position in the print array print_arr[early_row_int][early_col_int] = color_char; // since symetric if 1/4 point is integer then 3/4 should be too print_arr[late_row_int][late_col_int] = color_char; // now see if we can show the link in greater detail // set up 1/8 - between start and 1/4 float early_early_row = (conv_start_row + early_row) / 2.0; float early_early_col = (conv_start_col + early_col) / 2.0; int early_early_row_int = static_cast(early_early_row); int early_early_col_int = static_cast(early_early_col); // set up 3/8 - between 1/4 and midpoint float late_early_row = (mid_row + early_row) / 2.0; float late_early_col = (mid_col + early_col) / 2.0; int late_early_row_int = static_cast(late_early_row); int late_early_col_int = static_cast(late_early_col); // set up 5/8 - between midpoint and 3/4 float early_late_row = (mid_row + late_row) / 2.0; float early_late_col = (mid_col + late_col) / 2.0; int early_late_row_int = static_cast(early_late_row); int early_late_col_int = static_cast(early_late_col); // set up 7/8 - between 3/4 and end float late_late_row = (conv_end_row + late_row) / 2.0; float late_late_col = (conv_end_col + late_col) / 2.0; int late_late_row_int = static_cast(late_late_row); int late_late_col_int = static_cast(late_late_col); // check if around integer location row_diff = myabs(early_early_row - early_early_row_int); col_diff = myabs(early_early_col - early_early_col_int); if ((row_diff < 0.01) && (col_diff < 0.01)) { // put color in this position in the print array print_arr[early_early_row_int][early_early_col_int] = color_char; // since symetric if 1/8 point is integer then 3/8 5/8 and 7/8 points should be too print_arr[late_early_row_int][late_early_col_int] = color_char; print_arr[early_late_row_int][early_late_col_int] = color_char; print_arr[late_late_row_int][late_late_col_int] = color_char; // now see if we can show the link in greater detail // go no further for now // should have done this recursively then could have gone on // indefinitely // but it was a little hard to figure out } // end if } // end if } // end if } void Tw_Board::PrintPrintArray(ostream &sout,char print_arr[][MaxPrintArrayCols], const int full_size) const { // debugging //DEBUG2 clog << "In PrintPrintArray - full size = " << full_size << endl; //DEBUG2 clog << " PrintArray[0][0] = " << print_arr[0][0] << endl; for (int row_cnt = 0; row_cnt < full_size; row_cnt++) { //DEBUG clog << "DEBUG: " << endl << " "; for (int col_cnt = 0; col_cnt < (2 * full_size); col_cnt++) { //DEBUG clog << "D: " << print_arr[row_cnt][col_cnt]; //DEBUG clog << print_arr[row_cnt][col_cnt]; } } sout << endl; //DEBUG2 clog << "In PrintPrintArray - end debugging section " << endl; for (int row_cnt = 0; row_cnt < full_size; row_cnt++) { sout << endl << " "; for (int col_cnt = 0; col_cnt < (2 * full_size); col_cnt++) { sout << print_arr[row_cnt][col_cnt]; } } sout << endl; } void Tw_Board::PrintBoardLinks(ostream &sout) const { const int size = GetBoardSize(); //DEBUG clog << "in PrintBoardLinks - board size: " << size << endl; Tw_Link black_links[size * size]; Tw_Link white_links[size * size]; // put the links into the print array //DEBUG2 clog << "Ready to get list of black links for printing board" << endl; int num_black = GetBlackLinks(black_links); //DEBUG2 clog << "Ready to get list of white links for printing board" << endl; int num_white = GetWhiteLinks(white_links); sout << endl << " Black Links: " << endl << " "; for (int link_cnt = 0;link_cnt < num_black; link_cnt++) { sout << black_links[link_cnt] << endl; } sout << endl << endl; sout << endl << " White Links: " << endl << " "; for (int link_cnt = 0;link_cnt < num_white; link_cnt++) { sout << white_links[link_cnt] << endl; } } // write to stream void Tw_Board::Insert(ostream &sout) const { } // read from stream void Tw_Board::Extract(istream &sin) { } // protected interface can be used by objects that are in class, // and objects that are in a subtype class (derived class) // inspectors // return values of attributes (data members) // geez just let them have access to the data member directly // for efficiency - this is going to cost a lot each time void Tw_Board::GetBoardArr(Tw_Peg tw_board_arr[][MaxBoardArrayCols]) const { for (int row = 0; row <= board_size + 1; row++) { for (int col = 0; col <= board_size + 1; col++) { tw_board_arr[row][col] = board_arr[row][col]; } } } // get specific position Tw_Peg Tw_Board::GetSpecPosit(int row, int col) const { return board_arr[row][col]; } // find out board size int Tw_Board::GetBoardSize() const { return board_size; } // find out number of black links currently on the board int Tw_Board::GetNumBlackLinks() const { return num_black_links; } // find out number of white links currently on the board int Tw_Board::GetNumWhiteLinks() const { return num_white_links; } // I DONT THINK WE NEED THIS HERE Point Tw_Board::GetPosition() const { } // inserting a Tw_Board // overloading built-in << so can use same syntax as with built-in object types ostream& operator<<(ostream &sout, const Tw_Board &board) { // uses member function for the class to actually carry out // the operation board.DrawBoard(sout); // return the result so that this insertion can be cascaded // with other insertions in a single expression return sout; }