// 0/40
// Does not compile - trying to return after function ended (line 134)
/**************************************************************************************************/
/*                                                                                                */
/*  Name:  DarC KonQuesT                                                                          */
/*  Program:  #2                                                                                  */
/*  Date:  2005.9.27                                                                              */
/*  Purpose:                                                                                      */
/*  Application.h implementation which checks validity of positions, increments through the grid, */
/*        undoes placements, and stores positions of placed queens.                               */
/*                                                                                                */
/*                                                                                                */
/**************************************************************************************************/

#include <iostream>
#include "Application.h"

using namespace std;


int queens[8][2] = {
  {9,9},
  {9,9},
  {9,9},
  {9,9},
  {9,9},
  {9,9},
  {9,9},
  {9,9}
};
int q_it = 0;

//const short WALL = 1;

const short CORRIDOR = 0;

const short TRIED = 2;

const short PATH = 1;

const short ROWS = 8;

const short COLUMNS = 8;

short grid[ROWS][COLUMNS] =
{
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0}
}; // Chess Board


//operator overloading
ostream &operator<< (ostream &stream, Application& app)
{
  cout << endl;
  for (int row = 0; row < ROWS; row++)
  {
    for (int column = 0; column < COLUMNS; column++)
      cout << grid[row][column] << ' ';
   cout << endl;
   } // outer for
   return stream;
} // operator <<

//itrFields struct declaration
struct itrFields
{
  int row,
  column,
  move_count;
};


/*  Name:  generateInitialState()                                                                                     */
/*  Purpose:  asks user for start position, sets it                                                                   */
/*  Parameters:  none                                                                                                 */
/*  Preconditions: Position must be implemented correctly                                                             */
/*  Postconditions:  start position is initialized and returned                                                       */

Position Application::generateInitialState()
{
  Position start;
  int x, y;
  
  cout << endl << "Please enter the starting point for the first queen: ";
  cin >> x >> y;
  start.setPosition(x,y);
  return start;
}

/*  Name: valid(const Position& pos)                                                                                  */
/*  Purpose:  determine is provided Position is a valid move                                                          */
/*  Parameters:  const Position& pos                                                                                  */
/*  Preconditions:  pos must be implemented and initialized                                                           */
/*  Postconditions:  returns true if a valid position, false if invalid                                               */

bool Application::valid(const Position& pos)
{
  int irow, icol, resx, resy;
  bool q_found;
 

  // Check if its on the grid //
  if (pos.getRow() >= 0 && pos.getRow() < ROWS &&
        pos.getColumn() >= 0 && pos.getColumn() < COLUMNS  && grid[pos.getRow()][pos.getColumn()] == CORRIDOR)
  {

    //if this is our first position, it is always valid
    if(q_it == 0)
          return true;
    
    // Check if there is another queen on this row or column  //
    for(int i = 0; i <= q_it; i++)
      if(queens[i][0] == pos.getRow() || queens[i][1] == pos.getColumn())
        return false;
      
    
   // Check if there is another queen diaganolly //
   for(int i = 0; i <= q_it; i++)
   {
     resx = pos.getRow() - queens[i][0];
     resy = pos.getColumn() - queens[i][1];
     if(abs(resx) == abs(resy))
       return false;
   }  

    return true;
  } 
  return false;
}

/*  Name:  record(const Position& pos)                                                                                */
/*  Purpose:  record the position of a validated queen and increment its counter                                      */
/*  Parameters:  const Position& pos                                                                                  */
/*  Preconditions:  pos must be implemented and initialized with a validated position                                 */
/*  Postconditions:  position is stored in queens[][] and its index is incremented                                    */

void Application::record(const Position& pos)

{
   grid[pos.getRow()][pos.getColumn()] = PATH;
   queens[q_it][0] = pos.getRow();
   queens[q_it][1] = pos.getColumn();
   q_it++;
}

/*  Name:  done(const Position& pos)                                                                                  */
/*  Purpose: determine if we've completed the 8 queens problem                                                        */
/*  Parameters:  const Position& pos                                                                                  */
/*  Preconditions:  pos must be implemented and initialized with a validated position                                 */
/*  Postconditions:  returns true if 8 queens sucessfully placed, false if not                                        */

bool Application::done(const Position& pos)
{
// check if we've stored 8 queen positions //
if(q_it == 8)
  return true;
return false;
}

/*  Name:  undo(const Position& pos)                                                                                  */
/*  Purpose:  undo a queen position that has been determined to not be part of the solution                           */
/*  Parameters:  const Position& pos                                                                                  */
/*  Preconditions: pos must be implemented and initialized with a position to remove                                  */
/*  Postconditions:                                                                                                   */

void Application::undo(const Position& pos)
{ 
  queens[q_it][0] = 9;
  queens[q_it][1] = 9;
  grid[pos.getRow()][pos.getColumn()] = 0;
  q_it--;
}

//  Iterator Class
Application::Iterator::Iterator(const Position& pos)
{
  itrFields* itrPtr = new itrFields;
  itrPtr -> row = pos.getRow();
  itrPtr -> column = pos.getColumn();
  fieldPtr = itrPtr;
}

//operator overloading
Position Application::Iterator::operator++(int)
{
  itrFields* itrPtr = (itrFields*)fieldPtr;
  int nextRow = itrPtr->row, nextColumn = itrPtr->column;
  
  if(itrPtr->column == 7 && itrPtr->row == 7)
  {
     itrPtr->row = 0;
     itrPtr->column = 0;
  }  
     
  else if(itrPtr->column == 7)
  {
    itrPtr->row++;
    itrPtr->column = 0;
  }
  else if(itrPtr->column < 7)
  {
    itrPtr->column++;
  }
  
  
  Position next (nextRow, nextColumn);
  itrPtr->move_count++;
  return next;
}

/*  Name:  atEnd()                                                                                                    */
/*  Purpose:  determine if all moves have been exhausted                                                              */
/*  Parameters: none                                                                                                  */
/*  Preconditions: itrFields implemented and initialized                                                              */
/*  Postconditions:  returns true if all moves used, false if not                                                     */

bool Application::Iterator::atEnd()
{
  itrFields* itrPtr = (itrFields*)fieldPtr;
  if (itrPtr->move_count == 64)
    return true;
  return false;
}


