#include "globals.h"

move *g;

/*  

Gen sees if an en passant capture or castling is possible.
It then loops through the board searching for pieces of one 
side and generates
moves for them.

 */
void Gen()
{
first_move[ply + 1] = first_move[ply];

GenEp();

GenCastle();
	
for(int x = 0;x < 64;x++)
{
	if(color[x] == side)
	{
		switch(board[x])
		{
		case P:
			GenPawn(x);
			break;
		case N:
			GenKnight(x);
			break;
		case B:
			GenBishop(x,NE);
			GenBishop(x,SE);
			GenBishop(x,SW);
			GenBishop(x,NW);
			break;
		case R:
			GenRook(x,NORTH);
			GenRook(x,EAST);
			GenRook(x,SOUTH);
			GenRook(x,WEST);
			break;
		case Q:
			GenQueen(x,NE);
			GenQueen(x,SE);
			GenQueen(x,SW);
			GenQueen(x,NW);
			GenQueen(x,NORTH);
			GenQueen(x,EAST);
			GenQueen(x,SOUTH);
			GenQueen(x,WEST);
			break;
		case K:
			GenKing(x);
			break;
		default:
			break;
		}
	}
}
}
/*    

GenEp looks at the last move played and sees if it is a double pawn move.
If so, it sees if there is an opponent pawn next to it.
If there is, it adds the en passant capture to the move list.
Note that sometimes two en passant captures may be possible.

 */
void GenEp()
{
int ep = GetHistoryDest(hply - 1);
	
if(board[ep] == 0 && color[ep] == xside && abs(GetHistoryStart(hply - 1) - ep) == 16)
{
	if(col[ep] > 0 && color[ep-1]==side && board[ep-1]==P)
	{
		if(side == 0)
		{
			AddCapture(ep-1,ep+8,10);				
		}
		else
		{
			AddCapture(ep-1,ep-8,10);
		}
	}
	if(col[ep] < 7 && color[ep+1]==side && board[ep+1]==P)
	{
		if(side == 0)
		{
			AddCapture(ep+1,ep+8,10);
		}
		else
		{
			AddCapture(ep+1,ep-8,10);
		}
	}
}
}
/*   

GenPawn generates single and double pawn moves and pawn 
captures for a pawn. 

 */
void GenPawn(const int x)
{
if(side == White)
{
	if(board[x+8] == EMPTY)
	{
	    AddMove(x,x+8,history[x][x + 8]);
		if(row[x]==1 && board[x+16] == EMPTY)
		{
			AddMove(x,x+16);
		}
	}
	if(col[x] > 0 && color[x+7] == Black)
	{
		AddCapture(x,x+7,board[x+7] * 10);
	}
	if(col[x] < 7 && color[x+9] == Black)
	{
		AddCapture(x,x+9,board[x+9] * 10);
	}
}
else
{
	if(board[x-8] == 6)
	{
		AddMove(x,x - 8);
		if(row[x]==6 && board[x-16] == 6)
		{
			AddMove(x,x-16);
		}
	}
	if(col[x] < 7 && color[x-7] == 0)
	{
		AddCapture(x,x-7,board[x-7] * 10);
	}
	if(col[x] > 0 && color[x-9] == 0)
	{
		AddCapture(x,x-9,board[x-9] * 10);
	}
}

}
/*   

GenKnight generates knight moves and captures by using the 
knightmoves look up
table created in init.cpp. 

 */
void GenKnight(const int sq)
{
int k = 0;
int sq2 = knightmoves[sq][k++];
while(sq2 > -1)
{
	if(color[sq2] == EMPTY)
		AddMove(sq,sq2);
	else if(color[sq2] == xside)
		AddCapture(sq,sq2,board[sq2] * 10 - 3);
	sq2 = knightmoves[sq][k++];
}
}
/*   
GenBishop generates bishop moves and 
captures for each diagonal. 

 */
void GenBishop(const int x,const int dir)
{
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
			AddCapture(x,sq,board[sq] * 10 - 3);
		break;
	}
	AddMove(x,sq);
	sq = kmoves[sq][dir];
}

}
/*   
GenRook generates straight moves and captures 
for each rank and file. 

 */
void GenRook(const int x,const int dir)
{
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
		{
			AddCapture(x,sq,board[sq] * 10 - 5);
		}
		break;
	}
	AddMove(x,sq);
	sq = kmoves[sq][dir];
}

}
/*   
GenQueen generates queen moves and captures 
for line. 

 */
void GenQueen(const int x,const int dir)
{
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
		{
			AddCapture(x,sq,board[sq] * 10 - 9);
		}
		break;
	}
	AddMove(x,sq);
	sq = kmoves[sq][dir];
}

}
/*   

GenKing generates king moves and captures by using the 
kingmoves look up table created in init.cpp. 

 */
void GenKing(const int sq)
{
int k = 0;
int sq2 = kingmoves[sq][k++];

while(sq2 > -1)
{
	if(color[sq2] == EMPTY)
		AddMove(sq,sq2);
	else if(color[sq2] == xside)
		AddCapture(sq,sq2,board[sq2] * 10);
	sq2 = kingmoves[sq][k++];
}
}
/*   

AddMove adds the start and dest squares of a move to the movelist. 
The score is the history value.

 */
void AddMove(const int x,const int sq)
{
	g = &move_list[first_move[ply + 1]++];
	g->start = x;
	g->dest = sq;
	g->score = history[x][sq];
}
/*   

AddMove adds the start and dest squares of a move to the movelist. 
The score is also added and will be used in move ordering.

 */
void AddMove(const int x,const int sq,const int score)
{
	g = &move_list[first_move[ply + 1]++];
	g->start = x;
	g->dest = sq;
	g->score = score;
}
/*   
AddCapture adds the start and dest squares of a move to the 
movelist. 
CAPTURE_SCORE is added to the score so that captures will be 
looked at first.
The score is also added and will be used in move ordering.

 */
void AddCapture(const int x,const int sq,const int score)
{
	g = &move_list[first_move[ply + 1]++];
	g->start = x;
	g->dest = sq;
	g->score = score + CAPTURE_SCORE;
}
/*   

GenCaptures is very similar to Gen, except that only captures 
are being generatedinstead of all moves.

 */
void GenCaptures()
{
first_move[ply + 1] = first_move[ply];

for(int x = 0;x < 64;x++)
{
	if(color[x] == side)
	{
		switch(board[x])
		{
		case P:
			CapPawn(x);
			break;
		case N:
			CapKnight(x);
			break;
		case B:
			CapBishop(x,NE);
			CapBishop(x,SE);
			CapBishop(x,SW);
			CapBishop(x,NW);
			break;
		case R:
			CapRook(x,EAST);
			CapRook(x,SOUTH);
			CapRook(x,WEST);
			CapRook(x,NORTH);
			break;
		case Q:
			CapQueen(x,NE);
			CapQueen(x,SE);
			CapQueen(x,SW);
			CapQueen(x,NW);
			CapQueen(x,EAST);
			CapQueen(x,SOUTH);
			CapQueen(x,WEST);
			CapQueen(x,NORTH);
			break;
		case K:
			CapKing(x);
			break;
		default:
			break;
		}
	}
}
}
/*   
CapPawn generates pawn captures.

 */
void CapPawn(const int x)
{
if(side==0)
{
	if(col[x] > 0 && color[x+7] == xside)
	{
		AddCapture(x,x+7,board[x+7] * 10);
	}
	if(col[x] < 7 && color[x+9] == xside)
	{
		AddCapture(x,x+9,board[x+9] * 10);
	}
}
else
{
	if(col[x] < 7 && color[x-7] == xside)
	{
		AddCapture(x,x-7,board[x-7] * 10);
	}
	if(col[x] > 0 && color[x-9] == xside)
	{
		AddCapture(x,x-9,board[x-9] * 10);
	}
}

}
/*   

CapKnight generates knight captures.

 */
void CapKnight(const int sq)
{
int k = 0;
int sq2 = knightmoves[sq][k++];
while(sq2 > -1)
{
	if(color[sq2] == xside)
		AddCapture(sq,sq2,board[sq] * 10 - 3);
	sq2 = knightmoves[sq][k++];
}
}
/*   

CapBishop generates bishop captures.

 */
void CapBishop(const int x,const int dir)
{
		
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
			AddCapture(x,sq,board[sq] * 10 - 3);
		break;
	}
	sq = kmoves[sq][dir];
}

}
/*   

CapRook generates rook captures.

 */
void CapRook(const int x,const int dir)
{
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
		{
			AddCapture(x,sq,board[sq] * 10 - 5);
		}
		break;
	}
	sq = kmoves[sq][dir];
}

}
/*  

CapQueen generates queen captures.

 */
void CapQueen(const int x,const int dir)
{
int sq = kmoves[x][dir];
while(sq > -1)
{
	if(color[sq] != EMPTY)
	{
		if(color[sq] == xside)
		{
			AddCapture(x,sq,board[sq] * 10 - 9);
		}
		break;
	}
	sq = kmoves[sq][dir];
}

}
/*   

CapKing generates king captures.

 */
void CapKing(const int x)
{
	int k = 0;
	int sq = kingmoves[x][k++];

	while(sq > -1)
	{
		if(color[sq] == xside)
			AddCapture(x,sq,board[sq] * 10);
		sq = kingmoves[x][k++];
	}
}