// A computer game of engarde
// by James Brunskill


#include <iostream.h>
#include <time.h>
#include <stdlib.h>

const int BOARDSIZE = 23;
const int PACKSIZE = 25;
const int HANDSIZE = 5;
const int YOU = 25;
const int COMP = 10;

int deck[PACKSIZE];                   //Deck of Cards
int chand[HANDSIZE], phand[HANDSIZE]; //Computers Hand and Players Hand
int cpos = BOARDSIZE, ppos = 1;       //Computers position and Players position
int dused = 0;                        // Number of card used so far
bool uwon = false;                    // You won
bool cwon = false;                    // computer won

void Shuffle(void);
// A function to rearrange (shuffle) the numbers in an integer array (deck) size is the number of values in deck[](PACKSIZE)
// deck[] will be changed but contain the same values in a different (random) order

void SortPack(void);
// A function to initialize 1's in to the first 5th of the array 2's in the second... N's in the Nth 5th
// deck[] will be changed
// size is the length of the array deck[] (PACKSIZE)

void SeePack(void);
// Prints out the integer array deck[]
// size is the length of the array deck[] (PACKSIZE)
// does not change deck[]

void CLS(void);
// clears the screen doesn't make any changes to anything

void Board(void);
// Draws the board on the screen with a P at the players position  (ppos) and a C at the computers position (cpos) 
// It also displays the human players hand on the screen (phand[]) 
// This does not make any changes to any variable

void Deal(void);
// Deals each players original hand
// sets values for chand[] and phand[]

void SeeHand(void);
//Displays the users hand on the screen
//Doesn't change anything

void GetInput(void);
//Gets the user input prompts for the Card to play and the direction
//Changes ppos and Cards for Player Computers auto Parry is included.

void CompMove(void);
//chooses the computers move
//Includes Players parry
//changes cpos, updates chand[]

void init(void);
//calls SortPack, Shuffle, Deal and sets all variables to there starting positions

int PlayRound(void);
// Plays one round and returns winner COMP or YOU

bool NoMoves(int player);
// Checks for any posible moves for player COMP or YOU
// returns "true" if no moves possible and sets who won if that case

int main()
{
  int cgwon = 0;
  int ugwon = 0;
  int gwon = 0;
  char yn = 'y';
  
  while (cgwon < 5 && ugwon < 5)
    {
  gwon = PlayRound();
  
  if(gwon == COMP)
    cgwon++;
  else if (gwon == YOU)
    ugwon++;
  
  cout << "\tRounds Won" << endl;
  cout << "------------------------" << endl;
  cout << "Computer \t You" << endl;
  cout << "   " << cgwon << "\t\t  " << ugwon << endl;
  
  cout << "Do You want to play the next round ? Y/n" << endl;
  cin >> yn;
  if(yn == 'n'|| yn == 'N')
    break;
  }
  
  if (cgwon > ugwon)
    {
      cout << "The Computer has won this game" << endl;
    }
  else if (ugwon > cgwon)
    {
      cout << "You beat the computer" << endl;
    }
  
  return 0;
}

int PlayRound()
{
  int i = 0;
  
  init(); 
  
  do
    {
      Board();
      GetInput();
      Board();
      if(!uwon)
	CompMove();
    }
  while(dused < PACKSIZE && !uwon && !cwon);  
  
  if(cwon)
    { 
      Board(); // show board again if computer has won
      return COMP;
    }
  
  if(uwon)  
    return YOU;
}


void Shuffle(void)
{
  srand(time(NULL)); //SEED RANDOM NUMBER GENERATOR
  int swap, tmp;
  
  for(int j=0;j<50;j++)
    {
      for(int i=0;i<PACKSIZE;i++)
	{
	  swap = rand() % PACKSIZE;
	  // cout << "Swap = " << swap << endl;
	  tmp = deck[i];
	  deck[i]= deck[swap];
	  deck[swap]=tmp;
	}
    }
  
 
  return;
}

void SortPack(void)
{
  int i=0;
  
  for(;i<(PACKSIZE/5);i++)
    {
      deck[i]=1;
    }
  
  for(;i<2*(PACKSIZE/5);i++)
    {
      deck[i]=2;
    }
  
  for(;i<3*(PACKSIZE/5);i++)
    {
      deck[i]=3;
    }
  
  for(;i<4*(PACKSIZE/5);i++)
    {
      deck[i]=4;
    }

  for(;i<5*(PACKSIZE/5);i++)
    {
      deck[i]=5;
    }
  
  
  
  return;
}

void SeePack(void)
{
  cout << "The deck is: " << endl;
  for(int i=0;i<PACKSIZE;i++)
    {
      cout << deck[i];
    }
  cout << endl;
  
      return;
}


void CLS(void)
{
  for (int i=0; i < 23 ;i++) // 23 is number of lines on a screen
    {
      cout << endl;
    } 
  
}


void Board(void)
{
  //CLS();
  //cout number of cards left
  cout << "   There is " << PACKSIZE-dused << " Cards left in the pack" << endl;
  // draw the numbers on screen  
  for(int i = 1; i <= BOARDSIZE ; i++)
    {
      
      if(i < 10)
	cout << " 0";
      
      else if (i >= 10)
	cout << " " << i/10;
      
    }
  cout << endl;
  
  
  for(int i = 1 ; i <= BOARDSIZE ;i++)
    {
      if (i < 10)
	cout << " " << i;
      
      else if (i >= 10)
	cout << " " << i%10;
    }
  cout << endl;
  
  //Draw a row of +-  
  for(int i = 0 ; i < BOARDSIZE ;i++)
    {
      cout << "+-";
    }
  cout << "+" << endl;
  
  // draw player positions 
  for(int i = 1 ; i <= BOARDSIZE ;i++)
    {
      if(i == (ppos) && !cwon)
	cout << "|P";
      
      else if(i == (cpos) && !uwon)
	cout << "|C";
      
      else
	cout << "| ";
    }
  cout << "|" << endl;
  
  // draw a row of +-
  for(int i = 0 ; i < BOARDSIZE ;i++)
    {
      cout << "+-";
    }
  cout << "+" << endl;
  
  if(cwon)
    {
      cout << "The computer has won!" << endl;
    }

  //State player position
  cout << " Player position = " << ppos << ", Computer Position = " << cpos << endl;
  
  //Show the Players Hand
  SeeHand();

}


void Deal(void)
{
  int i = 0;
  
  for (i = 0; i < HANDSIZE; i++)
    {
      //cout << "Deck i is :" << deck[i] << endl;
      chand[i]=deck[i];
      //cout << "chand i is :" << chand[i] << endl;
      dused++;
    }
  
  for (;i < (2 * HANDSIZE);i++)
    {
      //cout << "Deck i is :" << deck[i] << endl;
      phand[i-HANDSIZE]=deck[i];
      // cout << "phand[i] is :" << phand[i-HANDSIZE] << endl;
      dused++;
    }
}


void SeeHand(void)
{
  cout << " \nPlayers Hand." << endl;
  
  for(int i = 0; i < HANDSIZE; i++)
    {
      cout << "Card " << char('a'+ i) << "=" << phand[i] << ", "; 
    }
  cout << endl;
}


void GetInput(void)
{
  char card = 'a';
  char dir = 'f';
  int ctrl = 0;

  if (!NoMoves(YOU)) //if there is at least one possible move
    {
      
      dused++;
      while(ctrl == 0)
	{
	  cout << "Enter a card to play:" << endl;
	  cin >> card;
	  cout << "Enter direction - (f)oward or (b)ackward:" << endl;
	  cin >> dir;
	  
	  if(int(card-'a') < HANDSIZE && (dir == 'f'|| dir == 'F' || dir == 'b' || dir == 'B'))
	    {
	      ctrl = 1;
	      if(dir == 'f'|| dir == 'F')
		{
		  //check if legal move
	      if((ppos + phand[int(card-'a')]) > cpos)
		{
		  cout << "You can't jump over another player" << endl;
		  ctrl = 0;
		}
	      
	      else if ((ppos + phand[int(card-'a')]) < 1)
		{
		  cout << "You can't go off the board" << endl;
		}
	      
	      else
		{
		  
		  if((ppos+phand[int(card-'a')]) == cpos)
		    {
		      for(int i; i < HANDSIZE; i++)
			{
			  if(chand[i] == phand[int(card-'a')])
			    {
			    cout << "Computer parrys with a " << chand[i] << endl;
			    return;
			    }
			}
		    }
		  
		  
		  ppos = ppos + phand[int(card-'a')];
		  
		  if(dused <= PACKSIZE)
		    {
		      phand[int(card-'a')] = deck[dused];
		    }
		}
		}
	      
	      
	      
	      
	      if(ppos == cpos)
		{
		  cout << "You Won!!!!!!!!" << endl;
		  uwon = true;
		}
	      
	    }    
	  
	  if(dir == 'b' || dir == 'B')
	    {
	      if((ppos - phand[int(card-'a')]) < 1)
		{
		  cout << "You can't go off the board" << endl;
		  ctrl = 0;
		}
	      else
		{
		  ppos = ppos - (phand[int(card-'a')]);
		  if(dused < PACKSIZE)
		    {
		      phand[int(card-'a')]= deck[dused];
		    }
		}
	      
	      
	    }
	      
	  else
		cout << "Not a valid selection, Try again:" << endl;
	}
      
    }    
}
  
      
void CompMove(void)
{
  if (!NoMoves(COMP))
    {
      
      for(int i= 0; i < HANDSIZE; i++)
	{
	  if ((cpos - chand[i]) == ppos)
	    {
	      char card = '@';
	      cout << "The computer is attacking with a " << chand[i] << endl;
	      cout << "You can ONLY parry with a " << chand[i] << "\nPlease enter a card to parry with" << endl;
	      cin >> card;
	      
	      if(phand[card-'a']==chand[i])
		{
		  cout << "You won the parry!" << endl;
		  return;
		}
	      
	      else
		{
		  cout << "computer moves " << chand[i] << " Places" << endl;
		  cpos = cpos - chand[i];
		  cout << "Computer won !" << endl;
		  cwon = true;
		  return;
		}
	    }
	}
      
      {  
	int closest = 10000;
	int colpos = 50;
	int j = 0;
	
	for(j = 0; j < HANDSIZE; j++)
	  {
	    
	    if ((ppos + 5) < cpos - chand[j])
	      {
		
		if((cpos-chand[j]) < closest)
		  {
		    closest = cpos-chand[j];
		    colpos = j;
		  }
	      }
	    
	  }
	
	if (colpos == 50)
	  {
	    for(int i = 0; i < HANDSIZE;i++)
	      {
		if((cpos + chand[i]) < BOARDSIZE)
		  {	    
		    cout << "computer moves back " << chand[i] << " Places" << endl;
		    cpos = cpos + chand[i];
		    break;
		  }
	      }
	  }
	else
	  {
	    cout << "computer moves forward " << chand[colpos] << " Places" << endl;
	    cpos = cpos - chand[colpos];
	  }
	
	return;
      }
      
    }
}

  
void init(void)
{
  
  dused=0; //set the cards used to 0
  
  SortPack(); 
  //SeePack();
  //Deal();
  
  Shuffle();
  //SeePack();
  
  Deal();
  
  cpos = BOARDSIZE;
  ppos = 1;              //Computers position and Players position
  uwon = false;          // You won
  cwon = false;          //computer won
  
  return;
}


bool NoMoves(int player)
{
  bool rn = true;

  if(player == COMP)
    {
      for (int i = 0; i < HANDSIZE; i++)
	{
	  if(cpos - chand[i] > ppos)
	    {
	      rn = false;
	      break;
	    }
	  else if(cpos + chand[i] < BOARDSIZE)
	    {
	      rn = false;
	      break;
	    }
	}
    }
  else if (player == YOU)
    {
      for (int i = 0; i < HANDSIZE; i++)
	{
	  if(ppos + phand[i] < cpos)
	    {
	      rn = false;
	      break;
	    } 
	  else if(ppos - phand[i] > 0)
	    {
	      rn = false;
	      break;
	    }
	}
    }

  if (rn == true)
    {
      if ((BOARDSIZE - cpos) > ppos)
	cwon = true;
      else if ((BOARDSIZE - cpos)< ppos)
	uwon = true;

	cout << "No possible moves!" << endl;
    }

  return rn;
}









 