/// GH working  on  knights  tour  20151015
#include  "..\std_lib_facilities.h"

///global variable for board width and length
int bWidth{8}, bLength{8};

/********************************************/
///prototypes
void displayBoard(vector <int>);

/// let user choose a legal move and update
void getMove(vector<int>& brd,
             int& mve,
             int& currPos,
             bool& stuck,
             vector<int>& access);

///initialize the board and set first position
void start(vector<int>&, int &, vector<int>&);

///set up the access matrix
void setup_access(vector<int>&);

int main() {
    cout << "\nEnter the width and length of your board: ";
    cin >> bWidth >> bLength;
    vector<int> board(bWidth*bLength);
    bool stuck = false;
    int mve{1};
    int currPos{0};
    vector<int> access(bWidth*bLength);
    setup_access(access);
    cout << "\nIn doubt about access: " << endl;
    displayBoard(access);
    cin.get();
    start(board , currPos, access);
    ///game loop
    while(!stuck) {
        displayBoard(board);
        getMove(board, currPos, mve, stuck, access);
    }
    return 0;
}

///initialize the board and set first position
void start(vector<int>& brd, int& cp, vector<int>& access) {
    int row , col;
    cout  << "\nWhat row and column position do you want to start ?";
    cin  >> row  >> col;
    cout << "\n That's at " << row*bWidth+col << endl;
    cp = row*bWidth+col;
    brd[cp] = 1;
    /*if(row-1>=0 && col+2<bWidth) {
        cout << "\naccess["<< (row-1)*bWidth+col+2<<"]="
             << access[(row-1)*bWidth+col+2] << endl << endl;
        --access[(row-1)*bWidth+col+2];
    }*/
    if(row-1>=0 && col+2<bWidth) --access[(row-1)*bWidth+col+2];
    if(row-2>=0 && col+1<bWidth) --access[(row-2)*bWidth+col+1];
    if(row-2>=0 && col-1>=0    ) --access[(row-2)*bWidth+col-1];
    if(row-1>=0 && col-2>=0    ) --access[(row-1)*bWidth+col-2];
    if(row+1<bLength && col-2>=0    ) --access[(row+1)*bWidth+col-2];
    if(row+2<bLength && col-1>=0    ) --access[(row+2)*bWidth+col-1];
    if(row+2<bLength && col+1<bWidth) --access[(row+2)*bWidth+col+1];
    if(row+1<bLength && col+2<bWidth) --access[(row+1)*bWidth+col+2];
    ///debugging
    displayBoard(access);
}

void displayBoard(vector<int> board)  {
    for(int i = 0; i < board.size(); ++i) {
        cout << setw(3) << board[i];
        if((i+1)%bWidth == 0)cout << endl;
    }
}

void getMove(vector<int>& brd,
             int& currPos,
             int& mve,
             bool& stuck,
             vector<int>& access) {
    int rowChange , colChange;
    cout  << "\nChange in rows and columns (-2,1) for up two-right 1):";
    do {
        cin  >> rowChange  >> colChange;
        if(abs(rowChange*colChange) != 2
           || currPos + bWidth*rowChange + colChange<0
           || currPos + bWidth*rowChange + colChange>=bWidth*bLength)
            cout << "\nThat's not legal move.  Try again: \n";
    } while(abs(rowChange*colChange) != 2
            || currPos + bWidth*rowChange + colChange<0
            || currPos + bWidth*rowChange + colChange>=bWidth*bLength);
    ///check that this is a legal move
    currPos = currPos + bWidth*rowChange + colChange;
    int row = currPos/bWidth, col = currPos%bWidth;
    if(row-1>=0 && col+2<bWidth) --access[(row-1)*bWidth+col+2];
    if(row-2>=0 && col+1<bWidth) --access[(row-2)*bWidth+col+1];
    if(row-2>=0 && col-1>=0    ) --access[(row-2)*bWidth+col-1];
    if(row-1>=0 && col-2>=0    ) --access[(row-1)*bWidth+col-2];
    if(row+1<bLength && col-2>=0    ) --access[(row+1)*bWidth+col-2];
    if(row+2<bLength && col-1>=0    ) --access[(row+2)*bWidth+col-1];
    if(row+2<bLength && col+1<bWidth) --access[(row+2)*bWidth+col+1];
    if(row+1<bLength && col+2<bWidth) --access[(row+1)*bWidth+col+2];
    ++mve;
    brd[currPos]=mve;
    ///debugging
    displayBoard(access);
}

///set up the access matrix
void setup_access(vector<int>& a) {
    int cntr{0};
    ///for each row
    for(int i = 0; i < bLength; ++i) {
        ///for each column
        for(int j = 0; j < bWidth; ++j) {
            cntr = 0;
            if(i-1>=0      && j+2<bWidth) cntr++;
            if(i-2>=0      && j+1<bWidth) cntr++;
            if(i-2>=0      && j-1>=0    ) cntr++;
            if(i-1>=0      && j-2>=0    ) cntr++;
            if(i+1<bLength && j-2>=0    ) cntr++;
            if(i+2<bLength && j-1>=0    ) cntr++;
            if(i+2<bLength && j+1<bWidth) cntr++;
            if(i+1<bLength && j+2<bWidth) cntr++;
            a[i*bWidth+j]=cntr;
        } /// end for loop
    } /// end for loop
    ///debugging for check
    for(int i = 0; i < bWidth*bLength; ++i) {
        cout << a[i];
        if((i+1)%bWidth==0) cout << endl;
    }
}
