#include <allinc.h>
#define OMGLOLWTFBBQ 1337
#define DENY_NONZERO 1 //leave this at 1
#define SHOW_RESULT 0
#define DISPLAY_ENABLED 1
#define PAUSE_BETWEEN_MOVES 0
#define BORDER 1
#define ORIGINAL 0 //user-input data
#define USE_R4 0
#define SHOW_R4 0 //show R4's temp lists
#define SHOW_MISS 0
#define USE_MATRIX 1 //leave this at 1
#define SHOW_MATRIX 1
#define SHOW_MATRIX_STEPS 1
#define SHOW_MATRIX_COMMANDS 0
#define FORCE_MATRIX 1

//Goal: allows user to control minesweeper game played by submain, through main

//Features
//submain allows main to play a game by passing parameters, then returns
//data to be used in statistical analysis
//child of minekiller2.cpp

//v.3: Border is eliminated in this version.
//v.4: starts again from different location if it fails
//v.5: Top two (decisive) rules of R4 have been implemented.
//v.6: Allows user input
//v.7: radical changes

int BOARD_ROWS;
int BOARD_COLS;
int BOMB_COUNT;
apstring targetfilename;

struct _tile
{
	int status;//0~8 number behind marker
	bool bomb;//1 = contains a bomb
   bool flagged;//1 = marked as a bomb
   //bool hidden;//0 = uncovered, show STATUS
   bool cleared;//NEW V.7: all tiles are uncovered, but no mines are shown
   double bomb2; //NEW V.8: used when double checking field data
   double stat2; //NEW V.8: used with bomb2, since regular status is int
};

struct _parcel
//for use with returning data from submain
{
   int  moves;
   bool clear;
};

struct _movelist
{
	apvector <int> ar;
   int index;
};

_parcel submain(int,int,int);
void initialize(apmatrix <_tile> &);
void plantbombs(apmatrix <_tile> &);
void showboard(apmatrix <_tile> &);
//_movelist getmove(apmatrix <_tile> &); //no longer necessary in v.7
bool nextmove(apmatrix <_tile> &);
void clearzeroes(apmatrix <_tile> &);
void clearpalm(apmatrix <_tile> &, int, int); //changed from napalm, v.7
void flagpalm(apmatrix <_tile> &, int, int);
int  countflags(apmatrix <_tile> &, int, int);
int  countunmarked(apmatrix <_tile> &, int, int);
double gettime();
bool r4(apmatrix <_tile> &);
//inline bool r4(apmatrix <_tile> &) {return false;}; //dummy for v.7
int r4_sum(apvector <int> &, bool);
int r4_count(apvector <int> &, int);
int minesleft(apmatrix <_tile> &);
bool matrix_exe(apmatrix <_tile> &);
bool matrix_swapout(apmatrix <double> &, int);
void showmatrix (apmatrix <double> &);
void matrix_mult(apmatrix <double> &, int, double);
void matrix_add(apmatrix <double> &, int, double, int);
bool matrix_verify(apmatrix <_tile> &, apmatrix <double> &);

void main()
{
	randomize();
	int counter=0;
   int i,j,k,h;
   _parcel temp;

   if(ORIGINAL)
   {
   	cout<<"Target filename: ";
      getline(cin,targetfilename);
   }

   ofstream ouf;
   ouf.open("minekiller8results.xls");
   ouf<<"ROW\tCOL\tMINES\tWINS\tTRIES\tAVG.LENGTH\tTOTALTIMETAKEN\n";

   int stepcount;
   int CYCLECOUNT=5;
   if(!ORIGINAL)
   {
	   for(i=3; i<=100; i+=1)//number of rows
	   for(j=i; j<=i; j+=1)//number of cols
	   for(k=i*j/2; k<=i*j/2; k+=100)//number of mines
	   {
	   	counter=0;//counts up victories
	      stepcount=0;//number of moves taken by victory
	      double before=gettime();
			for(h=0; h<CYCLECOUNT; h++)
			{
	         temp=submain(i,j,k);
	         if(temp.clear)
	         {
	         	counter++;
	            stepcount+=temp.moves;
	         }
			}
	      if(counter==0) {stepcount=0; counter=-1;}//prevents div.zero
	      ouf<<i<<"\t"<<j<<"\t"<<k<<'\t'<<counter<<'\t'<<h<<'\t'<<stepcount/double(counter)<<'\t'<<(gettime()-before)<<endl;
	     cout<<i<<"\t"<<j<<"\t"<<k<<'\t'<<counter<<'\t'<<h<<'\t'<<stepcount/double(counter)<<'\t'<<(gettime()-before)<<endl;
	   }
   }
   else
   {
   	ifstream inf;
      inf.open(targetfilename.c_str());
      inf>>i>>j; k=0; char temps;
      for(int q=0; q<i*j; q++)
      {//quickly get mine count
      	inf>>temps;
         if(temps=='B' || temps=='b')
         	k++;
      }
	   counter=0;//counts up victories
	   stepcount=0;//number of moves taken by victory
	   double before=gettime();
		for(h=0; h<1; h++)
		{
	      temp=submain(i,j,k);
	      if(temp.clear)
	      {
	        	counter++;
	         stepcount+=temp.moves;
	      }
		}
	   if(counter==0) {stepcount=0; counter=-1;}//prevents div.zero

	   ouf<<i<<"x"<<j<<"m"<<k<<'\t'<<counter<<'\t'<<h<<'\t'<<stepcount/double(counter)<<'\t'<<(gettime()-before)<<endl;
      if(SHOW_RESULT)
		   cout<<i<<"x"<<j<<"m"<<k<<'\t'<<counter<<'\t'<<h<<'\t'<<stepcount/double(counter)<<'\t'<<(gettime()-before)<<endl;
   }


   cout<<"\nDone";
   getch();
}
_parcel submain(int BOARD_ROWS_, int BOARD_COLS_, int BOMB_COUNT_)
//Use: plays a game with given parameters
//Args: temp values for rows, cols, and bomb count, which are placed into globals
//Returns: _parcel type: cleared status, number of moves taken.
{
	if(DISPLAY_ENABLED)
	   clrscr();
	BOARD_ROWS=BOARD_ROWS_;
   BOARD_COLS=BOARD_COLS_;
   BOMB_COUNT=BOMB_COUNT_;
	bool repeat;
	apmatrix <_tile> board (BOARD_ROWS,BOARD_COLS);
   _movelist movelist;
   if(!ORIGINAL)
   {
	   initialize(board);
	   plantbombs(board);
		//make initial move
	   //movelist=getmove(board); //deprecated
	   /*
      if(!board[0][0].hidden && (board[0][0].status!=0 || board[0][0].bomb))
	   {//0,0 is uncovered and not zero- sign that this board fails
		   if(DISPLAY_ENABLED)
		   {
	      	cout<<"\nNo opening moves.     ";
			   getch();
		   }
		   _parcel ret;
		   ret.moves=0;
		   ret.clear=false;
		   return ret;
	   }
      *///not sure if I need any of this
   }
   else
   {
   	initialize(board);
		ifstream inf;
      inf.open(targetfilename.c_str());
      int nt;
      char ch;
      inf>>nt>>nt; //get rid of parameter data
      for(int i=0; i<BOARD_ROWS*BOARD_COLS; i++)
      {
      	inf>>ch;
         if(ch=='B' || ch=='b')//bomb
	         board[i/BOARD_COLS][i%BOARD_COLS].bomb=1;
         //increment status numbers in legal adjacent squares
         //use original temp values, 'cause I'm super lazy
         if(board[i/BOARD_COLS][i%BOARD_COLS].bomb==1)
         {
	         int a=i, c=BOARD_COLS, r=BOARD_ROWS;
		      if(BORDER)
		      {
		         if(0<=a/c-1 && 0<=a%c-1) board[a/c-1][a%c-1].status++;
		         if(0<=a/c-1            ) board[a/c-1][a%c  ].status++;
		         if(0<=a/c-1 && a%c+1< c) board[a/c-1][a%c+1].status++;
		         if(            0<=a%c-1) board[a/c  ][a%c-1].status++;
		         if(            a%c+1< c) board[a/c  ][a%c+1].status++;
		         if(a/c+1< r && 0<=a%c-1) board[a/c+1][a%c-1].status++;
		         if(a/c+1< r            ) board[a/c+1][a%c  ].status++;
		         if(a/c+1< r && a%c+1< c) board[a/c+1][a%c+1].status++;
		      }
		      else
		      {//increment status numbers in ALL adjacent squares
				   board[((a/c-1)+r)%r][((a%c-1)+c)%c].status++;
				   board[((a/c-1)+r)%r][a%c          ].status++;
				   board[((a/c-1)+r)%r][(a%c+1)%c    ].status++;
				   board[a/c          ][((a%c-1)+c)%c].status++;
				   board[a/c          ][(a%c+1)%c    ].status++;
				   board[(a/c+1)%r    ][((a%c-1)+c)%c].status++;
				   board[(a/c+1)%r    ][a%c          ].status++;
				   board[(a/c+1)%r    ][(a%c+1)%c    ].status++;
		      }
         }
      }
      /*for(int i=0; i<BOARD_ROWS*BOARD_COLS; i++)
      {
      	inf>>ch;
         if(ch!='.')//hidden
	         board[i/BOARD_COLS][i%BOARD_COLS].hidden=0;
         board[i/BOARD_COLS][i%BOARD_COLS].flagged=0;//no flags to start with
      }*///not needed in v.7
   }
   bool matrixresult=false;
	bool allcleared;
   int x=1;
   bool repeat_revival=true; //turns repeat back to true only once after a matrix is used
   								  //can be restored if more tiles are uncovered after matrix is used
   if(!FORCE_MATRIX)
   {
	   clearzeroes(board);
	   if(DISPLAY_ENABLED)
		   showboard(board);
	   do
	   {
	      x++;
	      if(PAUSE_BETWEEN_MOVES)
		   	getch();

	      //make next move
		   repeat=nextmove(board);
         if(repeat && !repeat_revival)
      		repeat_revival=1;
		   //clearzeroes(board);
	      if(DISPLAY_ENABLED)
	      {
			   showboard(board);
		      cout<<"Moves: "<<x<<" Mines left: "<<minesleft(board)<<"  ";
	      }

	      //check if cleared, if so, break loop
		   allcleared=true;
		   for(int i=0; i<board.numrows(); i++)
		   for(int j=0; j<board.numcols(); j++)
		   	if(!board[i][j].cleared && !board[i][j].flagged)
		      	allcleared=false;

	      if(!repeat && !allcleared && USE_R4) //if you're about to give up, try r4.
	         if(r4(board))
	         {//if you find something, check for clear, and then turn repeat back on.
	         	//check if cleared, if so, break loop
				   allcleared=true;
				   for(int i=0; i<board.numrows(); i++)
				   for(int j=0; j<board.numcols(); j++)
				   	if(!board[i][j].cleared && !board[i][j].flagged)
				      	allcleared=false;
	            repeat=true;
	            if(DISPLAY_ENABLED)
		            cout<<"\nR4 USED ";
	         }
	         else
	         {
	            if(DISPLAY_ENABLED)
		            cout<<"\nR4 FAILED ";
	         }

         if(!repeat && !allcleared && USE_MATRIX)
		   {
			   matrixresult=matrix_exe(board);
		      if(matrixresult)
		      	allcleared=true;
            if(DISPLAY_ENABLED)
            {
            	showboard(board);
		      	cout<<"\nUsing matrix...    ";
            }
            repeat=repeat_revival;
            repeat_revival=false;
   		}


	      /*if(!repeat && !cleared && movelist.index<movelist.ar.length() && !ORIGINAL)
		   {//try another index, NOT FOR USE WITH ORIGINAL BOARDS
	      	int aa,ii,jj;//temps
	         do
	         {
	         	aa=movelist.ar[movelist.index];
		         ii=aa/board.numcols();
		         jj=aa%board.numcols();
	            movelist.index++;
	         }while((board[ii][jj].bomb || board[ii][jj].status!=0) && movelist.index<movelist.ar.length());

	         if(!movelist.index<movelist.ar.length())
	         {
	         	for(int kk=0; kk<board.numrows(); kk++)
	            for(int ll=0; ll<board.numcols(); ll++)
	            {
	            	board[kk][ll].hidden=1;
	               board[kk][ll].flagged=0;
	            }
	            board[ii][jj].hidden=0;
	            clearzeroes(board);
	            x=1;
				   if(DISPLAY_ENABLED)
					   showboard(board);
	            repeat=true;
				   if(DISPLAY_ENABLED)
		            cout<<"Retrying.        ";
	         }
			}*///movelist has been disabled in v.7
	   }while(repeat && !allcleared);
   }
   else//FORCE_MATRIX true
   {
	   matrixresult=matrix_exe(board);
	   if(matrixresult)
	   	allcleared=true;
      if(DISPLAY_ENABLED)
      {
        	showboard(board);
	    	cout<<"\nForced matrix.    ";
      }
      repeat=repeat_revival;
      repeat_revival=false;
   }
   //verification process
   if(1)//allcleared)
   {
   	for(int p=0; p<board.numrows(); p++)
      for(int q=0; q<board.numcols(); q++)
      	if((board[p][q].cleared && board[p][q].bomb) || (!board[p][q].bomb && board[p][q].flagged))
         {
         	if(SHOW_MISS)
	         	cout<<"(p,q)=("<<p<<","<<q<<") ("<<board[p][q].cleared<<"&&"<<board[p][q].bomb<<") || (!"<<board[p][q].bomb<<"&&"<<board[p][q].flagged<<") \n";
         	allcleared=false;//deny cleared if a bomb is uncovered or a clear tile is flagged
         }
   }
   if(!DISPLAY_ENABLED && SHOW_MISS && allcleared==false)
   {
      clrscr();
   	showboard(board);
	   cout<<"\nFailed...\n";
      getch();
   }
   if(DISPLAY_ENABLED)
   {
	   if(!allcleared)
		   cout<<"\nFailed...      ";
	   else
	   	cout<<"\nCLEARED!       ";
	   getch();
   }
   _parcel ret;
   ret.moves=x;
   ret.clear=allcleared;

   return ret;
}

void initialize(apmatrix <_tile> &board)
//Use: stores initial values into undefined values in each tile
//Args: board to be initialized, of type _tile
//Notes: status=0, bomb=0, flagged=0, hidden=1
{
	for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   {
   	board[i][j].status=0;
      board[i][j].bomb=0;
      board[i][j].flagged=0;
      //board[i][j].hidden=1;
      board[i][j].cleared=0; //added in v.7
      board[i][j].bomb2=0;//added in v.8
      board[i][j].stat2=0;//added in v.8
   }
}

void plantbombs(apmatrix <_tile> &board)
//Use: determine which positions are to have bombs, then mark off
//     status values of others
//Args: board to be planted, of type _tile
{
   //creates an indepent list of tile indices- 0 to ROW*COL-1
	apvector <int> tiles(board.numrows()*board.numcols());
   for(int i=0; i<tiles.length(); i++)
   	tiles[i]=i;

   //shuffles list, double swap-pass method
   for(int h=1; h<=2; h++)
   for(int i=0; i<tiles.length(); i++)
   {
   	int target=rand()%tiles.length();
      int temp=tiles[target];
      tiles[target]=tiles[i];
      tiles[i]=temp;
   }

   //assign bombs to indicies given starting at the front of tiles[]
   for(int i=0; i<BOMB_COUNT; i++)
    	if(i<tiles.length())//make sure there are no excess bombs
      {
      	int a=tiles[i];        //symbolic temps
         int r=board.numrows();
         int c=board.numcols();
         board[a/c][a%c].bomb=1; //set up us the bomb!

         //increment status numbers in legal adjacent squares
         if(BORDER)
         {
	         if(0<=a/c-1 && 0<=a%c-1) board[a/c-1][a%c-1].status++;
	         if(0<=a/c-1            ) board[a/c-1][a%c  ].status++;
	         if(0<=a/c-1 && a%c+1< c) board[a/c-1][a%c+1].status++;
	         if(            0<=a%c-1) board[a/c  ][a%c-1].status++;
	         if(            a%c+1< c) board[a/c  ][a%c+1].status++;
	         if(a/c+1< r && 0<=a%c-1) board[a/c+1][a%c-1].status++;
	         if(a/c+1< r            ) board[a/c+1][a%c  ].status++;
	         if(a/c+1< r && a%c+1< c) board[a/c+1][a%c+1].status++;
         }
         else
         {//increment status numbers in ALL adjacent squares
			   board[((a/c-1)+r)%r][((a%c-1)+c)%c].status++;
			   board[((a/c-1)+r)%r][a%c          ].status++;
			   board[((a/c-1)+r)%r][(a%c+1)%c    ].status++;
			   board[a/c          ][((a%c-1)+c)%c].status++;
			   board[a/c          ][(a%c+1)%c    ].status++;
			   board[(a/c+1)%r    ][((a%c-1)+c)%c].status++;
			   board[(a/c+1)%r    ][a%c          ].status++;
			   board[(a/c+1)%r    ][(a%c+1)%c    ].status++;
         }
      }
}

void showboard(apmatrix <_tile> &board)
//Use: displays board so far.
{
	//clrscr();
   gotoxy(1,1);
	for(int i=0; i<board.numrows(); i++)
   {
   	for(int j=0; j<board.numcols(); j++)
         if(board[i][j].bomb && board[i][j].flagged)
           	cout<<"M";//marked bomb
         else if(!board[i][j].bomb && board[i][j].flagged)
         	cout<<"F";//false bomb
      	//else if(board[i][j].hidden)
         	//cout<<".";//hidden
         else if(board[i][j].bomb && !board[i][j].flagged)
         	if(board[i][j].cleared)
		      	cout<<board[i][j].status;//bomb
         	else
		      	cout<<char(board[i][j].status+0x60);//bomb
         else
         	if(board[i][j].cleared)
		      	cout<<board[i][j].status;//no bomb
         	else
		      	cout<<char(board[i][j].status+0x60);//no bomb
      cout<<endl;
   }
}

void clearzeroes(apmatrix <_tile> &board)
//Use: "explodes" any zero tiles, like in the game. Automatically clears
//     all 3/5/8 blocks around a zero.
{
	bool repeat;//tells loop that it has found an exploded a zero, and to go
               //back around and check if that made any more zeroes.
	do
   {
   	repeat=false;
		for(int i=0; i<board.numrows(); i++)
	   for(int j=0; j<board.numcols(); j++)
	   	if(board[i][j].status==0 && countunmarked(board,i,j)>0)
	      {//if spot shows a zero and has non-clear tiles around it...
         	repeat=true; //repeat after checking
            clearpalm(board,i,j); //bomb it
	      }
   }while(repeat);
}

void clearpalm(apmatrix <_tile> &board, int i, int j)
//Use: Unhides all tiles in vicinity that are not marked.
//Args: board, and location to napalm
//Note: Changed from napalm for v.7
{
  	int a;//temporary value for current position on board
   int r=board.numrows();
   int c=board.numcols();

  	a=i*c+j; //current location

   if(!BORDER)
   {
	   if(!board[((a/c-1)+r)%r][((a%c-1)+c)%c].flagged) {board[((a/c-1)+r)%r][((a%c-1)+c)%c].cleared=1;}
	   if(!board[((a/c-1)+r)%r][a%c          ].flagged) {board[((a/c-1)+r)%r][a%c          ].cleared=1;}
	   if(!board[((a/c-1)+r)%r][(a%c+1)%c    ].flagged) {board[((a/c-1)+r)%r][(a%c+1)%c    ].cleared=1;}
	   if(!board[a/c          ][((a%c-1)+c)%c].flagged) {board[a/c          ][((a%c-1)+c)%c].cleared=1;}
	   if(!board[a/c          ][(a%c+1)%c    ].flagged) {board[a/c          ][(a%c+1)%c    ].cleared=1;}
	   if(!board[(a/c+1)%r    ][((a%c-1)+c)%c].flagged) {board[(a/c+1)%r    ][((a%c-1)+c)%c].cleared=1;}
	   if(!board[(a/c+1)%r    ][a%c          ].flagged) {board[(a/c+1)%r    ][a%c          ].cleared=1;}
	   if(!board[(a/c+1)%r    ][(a%c+1)%c    ].flagged) {board[(a/c+1)%r    ][(a%c+1)%c    ].cleared=1;}
   }
   else
	//check nearby positions and uncover them
	{
	   if(0<=a/c-1 && 0<=a%c-1) if(!board[a/c-1][a%c-1].flagged) {board[a/c-1][a%c-1].cleared=1;}
	   if(0<=a/c-1            ) if(!board[a/c-1][a%c  ].flagged) {board[a/c-1][a%c  ].cleared=1;}
	   if(0<=a/c-1 && a%c+1< c) if(!board[a/c-1][a%c+1].flagged) {board[a/c-1][a%c+1].cleared=1;}
	   if(            0<=a%c-1) if(!board[a/c  ][a%c-1].flagged) {board[a/c  ][a%c-1].cleared=1;}
	   if(            a%c+1< c) if(!board[a/c  ][a%c+1].flagged) {board[a/c  ][a%c+1].cleared=1;}
	   if(a/c+1< r && 0<=a%c-1) if(!board[a/c+1][a%c-1].flagged) {board[a/c+1][a%c-1].cleared=1;}
	   if(a/c+1< r            ) if(!board[a/c+1][a%c  ].flagged) {board[a/c+1][a%c  ].cleared=1;}
	   if(a/c+1< r && a%c+1< c) if(!board[a/c+1][a%c+1].flagged) {board[a/c+1][a%c+1].cleared=1;}
   }
}

void flagpalm(apmatrix <_tile> &board, int i, int j)
//Use: Flags all tiles in vicinity that are hidden
//Args: board, and location to flagpalm
{
  	int a;//temporary value for current position on board
   int r=board.numrows();
   int c=board.numcols();

  	a=i*c+j; //current location

   if(!BORDER)
   {
	   if(!board[((a/c-1)+r)%r][((a%c-1)+c)%c].cleared && !board[((a/c-1)+r)%r][((a%c-1)+c)%c].flagged) {board[((a/c-1)+r)%r][((a%c-1)+c)%c].flagged=1;}
	   if(!board[((a/c-1)+r)%r][a%c          ].cleared && !board[((a/c-1)+r)%r][a%c          ].flagged) {board[((a/c-1)+r)%r][a%c          ].flagged=1;}
	   if(!board[((a/c-1)+r)%r][(a%c+1)%c    ].cleared && !board[((a/c-1)+r)%r][(a%c+1)%c    ].flagged) {board[((a/c-1)+r)%r][(a%c+1)%c    ].flagged=1;}
	   if(!board[a/c          ][((a%c-1)+c)%c].cleared && !board[a/c          ][((a%c-1)+c)%c].flagged) {board[a/c          ][((a%c-1)+c)%c].flagged=1;}
	   if(!board[a/c          ][(a%c+1)%c    ].cleared && !board[a/c          ][(a%c+1)%c    ].flagged) {board[a/c          ][(a%c+1)%c    ].flagged=1;}
	   if(!board[(a/c+1)%r    ][((a%c-1)+c)%c].cleared && !board[(a/c+1)%r    ][((a%c-1)+c)%c].flagged) {board[(a/c+1)%r    ][((a%c-1)+c)%c].flagged=1;}
	   if(!board[(a/c+1)%r    ][a%c          ].cleared && !board[(a/c+1)%r    ][a%c          ].flagged) {board[(a/c+1)%r    ][a%c          ].flagged=1;}
	   if(!board[(a/c+1)%r    ][(a%c+1)%c    ].cleared && !board[(a/c+1)%r    ][(a%c+1)%c    ].flagged) {board[(a/c+1)%r    ][(a%c+1)%c    ].flagged=1;}
   }
   //check nearby positions and flag them
   else
   {
	   if(0<=a/c-1 && 0<=a%c-1) if(!board[a/c-1][a%c-1].cleared && !board[a/c-1][a%c-1].flagged) {board[a/c-1][a%c-1].flagged=1;}
	   if(0<=a/c-1            ) if(!board[a/c-1][a%c  ].cleared && !board[a/c-1][a%c  ].flagged) {board[a/c-1][a%c  ].flagged=1;}
	   if(0<=a/c-1 && a%c+1< c) if(!board[a/c-1][a%c+1].cleared && !board[a/c-1][a%c+1].flagged) {board[a/c-1][a%c+1].flagged=1;}
	   if(            0<=a%c-1) if(!board[a/c  ][a%c-1].cleared && !board[a/c  ][a%c-1].flagged) {board[a/c  ][a%c-1].flagged=1;}
	   if(            a%c+1< c) if(!board[a/c  ][a%c+1].cleared && !board[a/c  ][a%c+1].flagged) {board[a/c  ][a%c+1].flagged=1;}
	   if(a/c+1< r && 0<=a%c-1) if(!board[a/c+1][a%c-1].cleared && !board[a/c+1][a%c-1].flagged) {board[a/c+1][a%c-1].flagged=1;}
	   if(a/c+1< r            ) if(!board[a/c+1][a%c  ].cleared && !board[a/c+1][a%c  ].flagged) {board[a/c+1][a%c  ].flagged=1;}
	   if(a/c+1< r && a%c+1< c) if(!board[a/c+1][a%c+1].cleared && !board[a/c+1][a%c+1].flagged) {board[a/c+1][a%c+1].flagged=1;}
   }
}

bool nextmove(apmatrix <_tile> &board)
//Use: sequentially checks each tile for potential moves.
{
	int unmarkedcount;
	for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   	if(1)//always check in v.7 //!board[i][j].hidden) //ignore tile if it's hidden
   	{
	   	unmarkedcount=countunmarked(board,i,j);
	      if(unmarkedcount>0) //ignore if there's nothing unmarked around it
         {
		   	int flagcount=countflags(board,i,j);
            if(flagcount+unmarkedcount==board[i][j].status &&unmarkedcount!=0)
            {
            	flagpalm(board,i,j);
               return true;
            }
	         if(flagcount==board[i][j].status && unmarkedcount!=0)
            {
            	clearpalm(board,i,j);
               return true;
            }
	      }
      }
   return false;
}

int countflags(apmatrix <_tile> &board, int i, int j)
//Use: counts marked bombs in nearby area
//Args: board, location around which to check
//Returns: number of flags in vicinity
{
	int markcount=0; //returned value
  	int a;//temporary value for current position on board
   int r=board.numrows();
   int c=board.numcols();

  	a=i*c+j; //current location

   if(!BORDER)
   {
	   if(board[((a/c-1)+r)%r][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(board[((a/c-1)+r)%r][a%c          ].flagged) {markcount++;}
	   if(board[((a/c-1)+r)%r][(a%c+1)%c    ].flagged) {markcount++;}
	   if(board[a/c          ][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(board[a/c          ][(a%c+1)%c    ].flagged) {markcount++;}
	   if(board[(a/c+1)%r    ][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(board[(a/c+1)%r    ][a%c          ].flagged) {markcount++;}
	   if(board[(a/c+1)%r    ][(a%c+1)%c    ].flagged) {markcount++;}
   }
   else
   {
	   if(0<=a/c-1 && 0<=a%c-1) if(board[a/c-1][a%c-1].flagged) {markcount++;}
	   if(0<=a/c-1            ) if(board[a/c-1][a%c  ].flagged) {markcount++;}
	   if(0<=a/c-1 && a%c+1< c) if(board[a/c-1][a%c+1].flagged) {markcount++;}
	   if(            0<=a%c-1) if(board[a/c  ][a%c-1].flagged) {markcount++;}
	   if(            a%c+1< c) if(board[a/c  ][a%c+1].flagged) {markcount++;}
	   if(a/c+1< r && 0<=a%c-1) if(board[a/c+1][a%c-1].flagged) {markcount++;}
	   if(a/c+1< r            ) if(board[a/c+1][a%c  ].flagged) {markcount++;}
	   if(a/c+1< r && a%c+1< c) if(board[a/c+1][a%c+1].flagged) {markcount++;}
   }
   return markcount;
}

int countunmarked(apmatrix <_tile> &board, int i, int j)
//Use: counts unmarked tiles in nearby area
//Args: board, location around which to check
//Returns: number of non-cleared, non-flagged tiles in vicinity
{
	int markcount=0; //returned value
  	int a;//temporary value for current position on board
   int r=board.numrows();
   int c=board.numcols();

  	a=i*c+j; //current location

   if(!BORDER)
	{
	   if(!board[((a/c-1)+r)%r][((a%c-1)+c)%c].cleared && !board[((a/c-1)+r)%r][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(!board[((a/c-1)+r)%r][a%c          ].cleared && !board[((a/c-1)+r)%r][a%c          ].flagged) {markcount++;}
	   if(!board[((a/c-1)+r)%r][(a%c+1)%c    ].cleared && !board[((a/c-1)+r)%r][(a%c+1)%c    ].flagged) {markcount++;}
	   if(!board[a/c          ][((a%c-1)+c)%c].cleared && !board[a/c          ][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(!board[a/c          ][(a%c+1)%c    ].cleared && !board[a/c          ][(a%c+1)%c    ].flagged) {markcount++;}
	   if(!board[(a/c+1)%r    ][((a%c-1)+c)%c].cleared && !board[(a/c+1)%r    ][((a%c-1)+c)%c].flagged) {markcount++;}
	   if(!board[(a/c+1)%r    ][a%c          ].cleared && !board[(a/c+1)%r    ][a%c          ].flagged) {markcount++;}
	   if(!board[(a/c+1)%r    ][(a%c+1)%c    ].cleared && !board[(a/c+1)%r    ][(a%c+1)%c    ].flagged) {markcount++;}
   }
   else
   {
	   if(0<=a/c-1 && 0<=a%c-1) if(!board[a/c-1][a%c-1].cleared && !board[a/c-1][a%c-1].flagged) {markcount++;}
	   if(0<=a/c-1            ) if(!board[a/c-1][a%c  ].cleared && !board[a/c-1][a%c  ].flagged) {markcount++;}
	   if(0<=a/c-1 && a%c+1< c) if(!board[a/c-1][a%c+1].cleared && !board[a/c-1][a%c+1].flagged) {markcount++;}
	   if(            0<=a%c-1) if(!board[a/c  ][a%c-1].cleared && !board[a/c  ][a%c-1].flagged) {markcount++;}
	   if(            a%c+1< c) if(!board[a/c  ][a%c+1].cleared && !board[a/c  ][a%c+1].flagged) {markcount++;}
	   if(a/c+1< r && 0<=a%c-1) if(!board[a/c+1][a%c-1].cleared && !board[a/c+1][a%c-1].flagged) {markcount++;}
	   if(a/c+1< r            ) if(!board[a/c+1][a%c  ].cleared && !board[a/c+1][a%c  ].flagged) {markcount++;}
	   if(a/c+1< r && a%c+1< c) if(!board[a/c+1][a%c+1].cleared && !board[a/c+1][a%c+1].flagged) {markcount++;}
   }
   return markcount;
}

double gettime()
//Use: Returns the number of seconds that have passed since midnight, 1st
//     January 1970 GMT (or 6pm, 31st December 1969 CST).
//Args: None
//Returns: current time
//Note: Is a very large number **EDITED: now uses clock() which returns ms.
{
   time_t t=clock();
 	double t1=t;
 	return t1/1000;
}

bool r4(apmatrix <_tile> &board)
//Use: tries to determine any mined/clear tiles using systems of equations
//Args: Entire board, by reference.
//Returns: TRUE if any tiles can be determined, FALSE if none can.
//Note: Does not check for Rules 3 and 4, which suggest two solutions exist.
//Procedure: automatically looks at all tiles with at least one not-clear-not-flagged,
// non-flagged neighbor and adds them to list, total = status - flagcount
{
	//make matrix, with enough space to assign values to all tiles, plus one
   //for the total
	apmatrix <int> matrix(1,board.numrows()*board.numcols()+1);
   matrix[0][matrix.numcols()-1]=0;
   for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   {	//tally for all unaccounted tiles: mark 1 if hidden, and not flagged.
   	matrix[0][i*board.numcols()+j]=(1-board[i][j].cleared)*(1-board[i][j].flagged);
      //increment unaccounted mine total by 1 if hidden, not flagged, and a bomb.
      matrix[0][matrix.numcols()-1]+=(1-board[i][j].cleared)*board[i][j].bomb*(1-board[i][j].flagged);
   }
   int r=board.numrows(), c=board.numcols(); //placeholder temps

   //set up matrix
   cout<<endl;
   for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   {
		if(countunmarked(board,i,j)>board[i][j].status)
      {  //add a line, initialize
      	matrix.resize(matrix.numrows()+1,matrix.numcols());
         for(int k=0; k<matrix.numcols(); k++)
         	matrix[matrix.numrows()-1][k]=0;

         if(SHOW_R4)
         	cout<<"M#"<<(matrix.numrows()-1)<<" ("<<i<<","<<j<<")"<<endl;

         //assign status-flagcount to final element
         matrix[matrix.numrows()-1][matrix.numcols()-1]=board[i][j].status-countflags(board,i,j);

         //assign 1 to neighboring tiles that are unclear and unflagged
         if(!BORDER)
         {
	         if(board[((i-1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j-1)+c)%c]=1;
	         if(board[((i-1)+r)%r][((j-0)+c)%c].cleared==0 && board[((i-1)+r)%r][((j-0)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j-0)+c)%c]=1;
	         if(board[((i-1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-1)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j+1)+c)%c]=1;
	         if(board[((i-0)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][i*c+((j-1)+c)%c]=1;
	         if(board[((i-0)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][i*c+((j+1)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)%r*c+((j-1)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j-0)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-0)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)%r*c+((j-0)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)%r*c+((j+1)+c)%c]=1;
         }
      	else
         {
         	if(0<i && 0<j)
  	         if(board[((i-1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j-1)+c)%c]=1;
            if(0<i)
	         if(board[((i-1)+r)%r][j].cleared==0 && board[((i-1)+r)%r][j].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+j]=1;
            if(0<i && j<c-1)
	         if(board[((i-1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-1)+r)%r][j+1].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j+1)+c)%c]=1;
            if(0<j)
	         if(board[((i-0)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-0)+r)%r*c+((j-1)+c)%c]=1;
            if(j<c-1)
	         if(board[((i-0)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-0)+r)%r*c+((j+1)+c)%c]=1;
            if(i<r-1 && 0<j)
	         if(board[((i+1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j-1)+c)%c]=1;
            if(i<r-1)
	         if(board[((i+1)+r)%r][((j-0)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-0)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j-0)+c)%c]=1;
            if(i<r-1 && j<c-1)
	         if(board[((i+1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j+1)+c)%c]=1;
         }
      }
   }

   apvector <int> temp(matrix.numcols());
   //begin checking for useful data, storing temporary values in temp[]
   for(int i=0; i<matrix.numrows(); i++)
   for(int j=0; j<matrix.numrows(); j++)
   {
   	if(i!=j) //two different rows
      {
	   	for(int k=0; k<matrix.numcols(); k++)
	      	temp[k]=matrix[i][k]-matrix[j][k];

         if(SHOW_R4)
         {
         	cout<<"("<<i<<"-"<<j<<")";
		   	for(int k=0; k<matrix.numcols()-1; k++)
            	if(temp[k]>=0)
			      	cout<<setw(2)<<temp[k];
               else
               	cout<<temp[k];
            cout<<"| "<<temp[temp.length()-1]<<endl;
            getch();
         }

	   	//Rule 1a: if number of +1's = total, then all +1's are mined
	      if(r4_count(temp,1)==temp[temp.length()-1] && r4_sum(temp,1)!=0)         {
	         if(1)
	         {
            	cout<<endl;
	         	cout<<"("<<i<<"-"<<j<<")";
			   	for(int k=0; k<matrix.numcols()-1; k++)
	            	if(temp[k]>=0)
				      	cout<<setw(2)<<temp[k];
	               else
	               	cout<<temp[k];
	            cout<<"| "<<temp[temp.length()-1]<<endl;
         	}
         	for(int k=0; k<temp.length()-1; k++)
            	if(temp[k]==1)
               	board[k/c][k%c].flagged=1;
            if(SHOW_R4)
            	cout<<"[OK]";
            return true;
         }
         //Rule 1b: if number of -1's = -total, then all -1's are mined
	      if(r4_count(temp,-1)==abs(temp[temp.length()-1]) && r4_sum(temp,1)!=0)
         {
         	for(int k=0; k<temp.length()-1; k++)
            	if(temp[k]==-1)
               	board[k/c][k%c].flagged=1;
            if(SHOW_R4)
            	cout<<"[OK]";
            return true;
         }


         //Rule 2: all remaining unknowns are either 1 or -1, and total is 0.
         if(r4_sum(temp,1)==abs(r4_sum(temp,0)) && temp[temp.length()-1]==0)
         {
         	for(int k=0; k<temp.length()-1; k++)
            	if(k!=0)
               	board[k/c][k%c].cleared=1;
            if(SHOW_R4)
            	cout<<"[OK]";
            return true;
         }
      }
   }
   return false;
}

int r4_sum(apvector <int> &equation, bool absolute)
//Use: adds up values in "equation", if abs=true, adds up abs. values.
//Args: matrix, row to check, absolute-value-sum toggle
//Returns: sum of row, or sum of absolute values of row
//Notes: for use with R4 logic
{
	int ret=0;
	for(int i=0; i<equation.length()-1; i++) //don't add up final box!
   	if(absolute)
      	ret+=abs(equation[i]);
      else
      	ret+=equation[i];
   return ret;
}
int r4_count(apvector <int> &equation, int target)
{
	int ret=0;
   for(int i=0; i<equation.length()-1; i++)
   	if(equation[i]==target)
      	ret++;
   return ret;
}


int minesleft(apmatrix <_tile> &board)
{
	int ret=0;
	for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   	if(board[i][j].bomb && !board[i][j].flagged)
      	ret++;
   return ret;
}

bool matrix_exe(apmatrix <_tile> &board)
//Use: used as initial move. Assigns systems of equations to the matrix, one for
//     each spot on the board, then solves using refined-row-echelon-format. The sum
//     of the adjacent squares equals the status
//Args: board to be solved- referenced just in case a solution IS found
//Returns: false if contradiction or no solution, true is solved, along with a
//       solved board
//Notes: Child of R4 function
{
	//make matrix, with enough space to assign values to all tiles, plus one
   //for the total
	apmatrix <double> matrix(0,board.numrows()*board.numcols()+1);
   /*matrix[0][matrix.numcols()-1]=0;
   for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   {	//tally for all unaccounted tiles: mark 1 if hidden, and not flagged.
   	matrix[0][i*board.numcols()+j]=(1-board[i][j].cleared)*(1-board[i][j].flagged);
      //increment unaccounted mine total by 1 if hidden, not flagged, and a bomb.
      matrix[0][matrix.numcols()-1]+=(1-board[i][j].cleared)*board[i][j].bomb*(1-board[i][j].flagged);
   }*///don't make a top line accounting for all tiles and all bombs
   int r=board.numrows(), c=board.numcols(); //placeholder temps

   //set up matrix
   //cout<<endl;
   for(int i=0; i<board.numrows(); i++)
   for(int j=0; j<board.numcols(); j++)
   {
		if(!board[i][j].cleared && !board[i][j].flagged)//countunmarked(board,i,j)>board[i][j].status)
      {  //add a line, initialize
      	matrix.resize(matrix.numrows()+1,matrix.numcols());
         for(int k=0; k<matrix.numcols(); k++)
         	matrix[matrix.numrows()-1][k]=0;

         //if(SHOW_MATRIX_STEPS)
         //	cout<<"M#"<<matrix.numrows()-1<<" ("<<i<<","<<j<<")"<<endl;

         //assign status-flagcount to final element
         matrix[matrix.numrows()-1][matrix.numcols()-1]=board[i][j].status-countflags(board,i,j);

         //assign 1 to neighboring tiles that are unclear and unflagged
         if(!BORDER)
         {
	         if(board[((i-1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j-1)+c)%c]=1;
	         if(board[((i-1)+r)%r][((j-0)+c)%c].cleared==0 && board[((i-1)+r)%r][((j-0)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j-0)+c)%c]=1;
	         if(board[((i-1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-1)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-1)+r)%r*c+((j+1)+c)%c]=1;
	         if(board[((i-0)+r)%r][((j-1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-0)+r)%r*c+((j-1)+c)%c]=1;
	         if(board[((i-0)+r)%r][((j+1)+c)%c].cleared==0 && board[((i-0)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i-0)+r)%r*c+((j+1)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j-1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j-1)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j-0)+c)%c].cleared==0 && board[((i+1)+r)%r][((j-0)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j-0)+c)%c]=1;
	         if(board[((i+1)+r)%r][((j+1)+c)%c].cleared==0 && board[((i+1)+r)%r][((j+1)+c)%c].flagged==0)
	         	matrix[matrix.numrows()-1][((i+1)+r)%r*c+((j+1)+c)%c]=1;
         }
      	else
         {
         	if(0<i && 0<j)
  	         {if(board[i-1][j-1].cleared==0 && board[i-1][j-1].flagged==0)
	         	matrix[matrix.numrows()-1][(i-1)*c+(j-1)]=1;}
            if(0<i)
	         {if(board[i-1][j].cleared==0 && board[i-1][j].flagged==0)
	         	matrix[matrix.numrows()-1][(i-1)*c+j]=1;}
            if(0<i && j<c-1)
	         {if(board[i-1][j+1].cleared==0 && board[i-1][j+1].flagged==0)
	         	matrix[matrix.numrows()-1][(i-1)*c+(j+1)]=1;}
            if(0<j)
	         {if(board[i][j-1].cleared==0 && board[i][j-1].flagged==0)
	         	matrix[matrix.numrows()-1][i*c+(j-1)]=1;}
            if(j<c-1)
	         {if(board[i][j+1].cleared==0 && board[i][j+1].flagged==0)
	         	matrix[matrix.numrows()-1][i*c+(j+1)]=1;}
            if(i<r-1 && 0<j)
	         {if(board[i+1][j-1].cleared==0 && board[i+1][j-1].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)*c+(j-1)]=1;}
            if(i<r-1)
	         {if(board[i+1][j].cleared==0 && board[i+1][j].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)*c+j]=1;}
            if(i<r-1 && j<c-1)
	         {if(board[i+1][j+1].cleared==0 && board[i+1][j+1].flagged==0)
	         	matrix[matrix.numrows()-1][(i+1)*c+(j+1)]=1;}
         }
      }
   }

   if(SHOW_MATRIX_STEPS)
	   showmatrix(matrix);
   //start RREFing
	for(int i=0; i<matrix.numrows(); i++)
   {
   	if(matrix[i][i]==0)
      	if(matrix_swapout(matrix,i) && SHOW_MATRIX_STEPS)
         {
         	if(SHOW_MATRIX_COMMANDS)
            {
         		cout<<"matrix_swapout(matrix,"<<i<<")";
	            getch();
            }
         	showmatrix(matrix);
         }
         //else
         	//{cout<<"Matrix failed"; getch(); return false;}

      if(matrix[i][i]!=0)
      {
      	if(SHOW_MATRIX_COMMANDS)
         {
         	cout<<"\nmatrix_mult(matrix,"<<i<<","<<1.0/matrix[i][i]<<");";
            getch();
         }
	      matrix_mult(matrix,i,1.0/matrix[i][i]); //scale pivot element to 1
	      for(int j=i+1; j<matrix.numrows(); j++)
         {
	         if(SHOW_MATRIX_COMMANDS)
	         {
		         cout<<"\nmatrix_add(matrix,"<<i<<","<<-matrix[j][i]<<","<<j<<");";
	         	getch();
	         }
	      	matrix_add(matrix,i,-matrix[j][i],j); //turn everything below pivot element to 0
         }
      }
      if(SHOW_MATRIX_STEPS)
	      showmatrix(matrix);
   }
   for(int i=matrix.numrows()-1; i>=0; i--)
   {//at this point, there is a diagonal of 1's- now go back through and zero out
    //everything above the ones starting at the bottom right and going up
   	for(int j=0; j<i; j++)
      	//if(matrix[i][i]!=0)
		   matrix_add(matrix,i,-matrix[j][i],j);//zero out from top down to row in question
      if(SHOW_MATRIX_STEPS)
	      showmatrix(matrix);
   }

   if(SHOW_MATRIX)
   {
   	showmatrix(matrix);
   }

   if(matrix_verify(board,matrix))
   {
   	for(int i=0; i<board.numrows(); i++)
      for(int j=0; j<board.numcols(); j++)
      {
         board[i][j].flagged=int(matrix[i*board.numcols()+j][matrix.numcols()-1]+.5);//last element
         if(!board[i][j].flagged)
	         board[i][j].cleared=1;
      }
      if(SHOW_MATRIX)
	      showboard(board);
      return true;
   }
   else
	   return false;
}

bool matrix_swapout(apmatrix <double> &matrix, int P)
//Use: called from matrix- swaps all elements of two rows
//Args: matrix to use, swapping row P with the nearest below it with a non-zero
//      pivot element
//Returns: true if it worked, false if it didn't
//Notes: used in finding RREF to avoid division by zero- only used going down
{
	int Q=-1;
	for (int i=P+1; i<matrix.numrows(); i++)
   	if(matrix[i][P]!=0)
      {	Q=i; i=matrix.numrows();}//break

   if(Q==-1)
   	return true;

	double temp;
	for(int i=0; i<matrix.numcols(); i++)
   {
   	temp=matrix[P][i];
      matrix[P][i]=matrix[Q][i];
      matrix[Q][i]=temp;
   }
   return true;
}

void showmatrix (apmatrix <double> &matrix)
//Use: clears screen, displays matrix, and then pauses
//Args: matrix to show
{
	clrscr();
   for(int i=0; i<matrix.numrows(); i++)
   {
	   for(int j=0; j<matrix.numcols(); j++)
	   {
	   	if(j==matrix.numcols()-1)
	      	cout<<" | ";//<<matrix[i][j];
         //else
	        	//if(0<abs(matrix[i][j]) && abs(matrix[i][j])<0.01)
	         //  	cout<<"~";
	         //else
		      	//cout<<int(matrix[i][j]+.5); //round
               cout<<matrix[i][j]<<" "; //don't round

	   }
      cout<<endl;
   }
   getch();
}

void matrix_mult(apmatrix <double> &matrix, int r, double scale)
//Use: multiplies an entire row by a certain factor
//Args: Matrix to edit, row to edit, scale factor
{
	for(int i=0; i<matrix.numcols(); i++)
   	matrix[r][i]*=scale;
}

void matrix_add(apmatrix <double> &matrix, int r, double scale, int r2)
//Use: multiplies an entire row by a certain factor, and add it to row r2
//Args: Matrix to edit, row to edit, scale factor, target row to be changed
{
	for(int i=0; i<matrix.numcols(); i++)
   {
   	matrix[r2][i]+=matrix[r][i]*scale;
      if(abs(matrix[r2][i])<0.000001)
      	matrix[r2][i]=0;
   }
}

bool matrix_verify(apmatrix <_tile> &board, apmatrix <double> &matrix)
//Use: shows board after matrix results have been tallied in
//Args: original board, used for sizes, and matrix in question
//Note: Needs code from plantbombs, because matrix supposedly contains bomb info
{
	int a, r=board.numrows(), c=board.numcols();
	apmatrix <_tile> tempboard(r,c);
   initialize(tempboard);
   //dummy board to contain all of matrix's bomb data
	for(a=0; a<matrix.numrows(); a++)
   {
   	tempboard[a/c][a%c].bomb2=matrix[a][matrix.numcols()-1]; //assign last column's data to bomb
      if(BORDER)
   	{
	      if(0<=a/c-1 && 0<=a%c-1) tempboard[a/c-1][a%c-1].stat2+=tempboard[a/c][a%c].bomb2;
	      if(0<=a/c-1            ) tempboard[a/c-1][a%c  ].stat2+=tempboard[a/c][a%c].bomb2;
	      if(0<=a/c-1 && a%c+1< c) tempboard[a/c-1][a%c+1].stat2+=tempboard[a/c][a%c].bomb2;
	      if(            0<=a%c-1) tempboard[a/c  ][a%c-1].stat2+=tempboard[a/c][a%c].bomb2;
	      if(            a%c+1< c) tempboard[a/c  ][a%c+1].stat2+=tempboard[a/c][a%c].bomb2;
	      if(a/c+1< r && 0<=a%c-1) tempboard[a/c+1][a%c-1].stat2+=tempboard[a/c][a%c].bomb2;
	      if(a/c+1< r            ) tempboard[a/c+1][a%c  ].stat2+=tempboard[a/c][a%c].bomb2;
	   	if(a/c+1< r && a%c+1< c) tempboard[a/c+1][a%c+1].stat2+=tempboard[a/c][a%c].bomb2;
	   }
	   else
	   {//increment status numbers in ALL adjacent squares
	 	   tempboard[((a/c-1)+r)%r][((a%c-1)+c)%c].stat2+=tempboard[a/c][a%c].bomb2;
		   tempboard[((a/c-1)+r)%r][a%c          ].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[((a/c-1)+r)%r][(a%c+1)%c    ].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[a/c          ][((a%c-1)+c)%c].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[a/c          ][(a%c+1)%c    ].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[(a/c+1)%r    ][((a%c-1)+c)%c].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[(a/c+1)%r    ][a%c          ].stat2+=tempboard[a/c][a%c].bomb2;
			tempboard[(a/c+1)%r    ][(a%c+1)%c    ].stat2+=tempboard[a/c][a%c].bomb2;
	   }
   }

   if(SHOW_MATRIX)
   	cout<<"\nDOUBLE CHECK:\n";
   int allclear=true;

   for(int i=0; i<tempboard.numrows(); i++)
   {
   	for(int j=0; j<tempboard.numcols(); j++)
      {
      	if(SHOW_MATRIX)
	   		cout<<int(tempboard[i][j].stat2+.5)<<" ";
	      if(int(tempboard[i][j].stat2+.5)!=board[i][j].status)
	      	allclear=false;
      }
      if(SHOW_MATRIX)
	      cout<<endl;
   }
   if(SHOW_MATRIX)
   {
	   showboard(board);
	   cout<<"VERIFIED: ["<<allclear<<"]";
	   getch();
   }
   return allclear;
}
