#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define TRUE 1
#define FALSE 0

typedef short int bool;

typedef struct {
  bool origin[2];
  bool target[2];
  bool castle[4];
} move;

struct nodetype {
  char board[8][8];
  bool turn;
  move lastMove;
  struct nodetype *next;
};

struct nodesize {
  char board[8][8];
  bool turn;
  move lastMove;
  int *next;
};

typedef struct nodetype *NODEPTR;

//Node operation functions
NODEPTR getNode(void);
void freeNode(NODEPTR p);

//Function called by main program, initializes variables
void initialize(char board[][8], move *lastmove);

//Functions called by main program, print board or move
void printBoard(char board[][8]);
void printMove(move m);

//Function called by main program, reads user input
move getMove(char board[][8], move lastmove, char name[]);

//Function called by main program, finds best next move
move nextMove(char brd[][8], move lastmove, int looklevel, char player);

//Functions build game tree for use by function nextMove
NODEPTR buildTree(char brd[][8], move lastmove, int looklevel, char player, NODEPTR *best, int *value);
NODEPTR generate(NODEPTR position, char player, int *mate, int *moves);
NODEPTR tacticalgen(NODEPTR p, char player, int *morecaptures);
void makeNode(char brd[][8], NODEPTR q, move newmove, bool firstnode);

//Functions evaluate game tree, assisting function nextMove
void miniMax(NODEPTR pnd, int plevel, int depth, int uvalue, char player, NODEPTR *pbest, int *pvalue);
int evaluate(char brd[][8], char player, move lastmove);
void tacticaleval(NODEPTR pnd, int plevel, int depth, int uvalue, char player, int *pvalue);
int peiceValue(char peice);
int positionalValue(int i, int j, char brd[][8]);
int tacticalValue(char brd[][8], move lastmove);
bool attackedByPawn(int i, int j, char brd[][8]);
bool attackedByBishop(int i, int j, char brd[][8], move lastmove);
bool attackedByKnight(int i, int j, char brd[][8], move lastmove);
bool attackedByRook(int i, int j, char brd[][8], move lastmove);

//Function to test legality of a move, assists generate and is called by main program
bool isLegal(move m, char brd[][8], move lastmove);

//Helper Functions for isLegal
bool isLegalP(move m, char brd[][8], move lastmove);
bool isLegalp(move m, char brd[][8], move lastmove);
bool isLegalKNight(move m);
bool isLegalBishop(move m, char brd[][8]);
bool isLegalRook(move m, char brd[][8]);
bool isLegalQueen(move m, char brd[][8]);
bool isLegalK(move m, char brd[][8]);
bool isLegalk(move m, char brd[][8]);
bool whiteInCheck(char brd[][8], move lastmove);
bool blackInCheck(char brd[][8], move lastmove);
bool whiteIsPinned(int alpha, int numeric, char brd[][8], move lastmove);
bool blackIsPinned(int alpha, int numeric, char brd[][8], move lastmove);
bool isClearDiagonal(move m, char brd[][8]);
bool isClearFile(move m, char brd[][8]);
bool isClearRank(move m, char brd[][8]);

//Function to find checkmate and stalemate
int isMate(char brd[][8], move lastmove);

//Function to take a board position and a move and makes a new board position by applying the move
void executeMove(char position[][8], move *newmove, char newposition[][8]);

//Minor helper functions that help to maintain abstraction
move lastMove(NODEPTR p);
move makeMove(int oa, int on, int ta, int tn, move lastmove);
move convertInput(char input[], move lastmove);
move copyMove(move m);
char originAlpha(move newmove);
char originNumeric(move newmove);
char targetAlpha(move newmove);
char targetNumeric(move newmove);
bool whiteCanCastleLeft(move m);
bool whiteCanCastleRight(move m);
bool blackCanCastleLeft(move m);
bool blackCanCastleRight(move m);

NODEPTR getNode(void)
{
  NODEPTR newnode;
  newnode =(NODEPTR) malloc(sizeof(struct nodesize));
  return newnode;
}

void freeNode(NODEPTR p)
{ 
  free(p);
}

void initialize(char board[][8], move *lastmove)
{
  int i;
  board[0][7]=board[7][7]='r';
  board[1][7]=board[6][7]='n';
  board[2][7]=board[5][7]='b';
  board[3][7]='q';
  board[4][7]='k';
  for(i=0;i<8;i++)
    board[i][6]='p';
  for(i=0;i<8;i++)
    board[i][5]='-';
  for(i=0;i<8;i++)
    board[i][4]='-';
  for(i=0;i<8;i++)
    board[i][3]='-';
  for(i=0;i<8;i++)
    board[i][2]='-';
  for(i=0;i<8;i++)
    board[i][1]='P';
  board[0][0]=board[7][0]='R';
  board[1][0]=board[6][0]='N';
  board[2][0]=board[5][0]='B';
  board[3][0]='Q';
  board[4][0]='K';
  //lastmove's target implies that it is white's turn to move
  lastmove->target[0]=4;
  lastmove->target[1]=7;
  for(i=0;i<4;i++)
    lastmove->castle[i]=1;
}

void printBoard(char board[][8])
{
  int i, j;
  for(i=7;i>-1;i--){
    printf("\n%i ", i+1);
    for(j=0;j<8;j++)
    printf(" %c", board[j][i]);
  }
  printf("\n\n   A B C D E F G H\n");
}

void printMove(move m)
{
	int oa, on, ta, tn;
	char origin, target;
	oa = m.origin[0];
	on = m.origin[1] + 1;
	ta = m.target[0];
	tn = m.target[1] + 1;
	switch(oa) {
	case 7: origin = 'h'; break;
	case 6: origin = 'g'; break;
	case 5: origin = 'f'; break;
	case 4: origin = 'e'; break;
	case 3: origin = 'd'; break;
	case 2: origin = 'c'; break;
	case 1: origin = 'b'; break;
	case 0: origin = 'a'; break;
	default: printf("Error: cannot print invalid move");
	}
	switch(ta) {
	case 7: target = 'h'; break;
	case 6: target = 'g'; break;
	case 5: target = 'f'; break;
	case 4: target = 'e'; break;
	case 3: target = 'd'; break;
	case 2: target = 'c'; break;
	case 1: target = 'b'; break;
	case 0: target = 'a'; break;
	default: printf("Error: cannot print invalid move");
	}
	printf("%c%d%c%d\n", origin, on, target, tn);
}

move getMove(char board[][8], move lastmove, char name[])
{
  int originalpha, originnumeric, targetalpha, targetnumeric;
  char originchar, targetchar, nowhere;
  move newmove;
  printf("\n\nPlease enter your move, %s.\n", name);
  printf("Please enter origin square (ex. e2):");
  scanf("%c%i", &originchar, &originnumeric);scanf("%c", &nowhere);
  printf("Please enter target square (ex. e4):");
  scanf("%c%i", &targetchar, &targetnumeric);scanf("%c", &nowhere);
  originnumeric-=1;
  targetnumeric-=1;
  switch(originchar) {
  case'A':
  case'a': originalpha=0; break;
  case'B':
  case'b': originalpha=1; break;
  case'C':
  case'c': originalpha=2; break;
  case'D':
  case'd': originalpha=3; break;
  case'E':
  case'e': originalpha=4; break;
  case'F':
  case'f': originalpha=5; break;
  case'G':
  case'g': originalpha=6; break;
  case'H':
  case'h': originalpha=7; break;
  default: originalpha=99;  
  }
  switch(targetchar) {
  case'A':
  case'a': targetalpha=0; break;
  case'B':
  case'b': targetalpha=1; break;
  case'C':
  case'c': targetalpha=2; break;
  case'D':
  case'd': targetalpha=3; break;
  case'E':
  case'e': targetalpha=4; break;
  case'F':
  case'f': targetalpha=5; break;
  case'G':
  case'g': targetalpha=6; break;
  case'H':
  case'h': targetalpha=7; break;
  default: targetalpha=99;
  }
  if(0 <= originalpha <= 7)
  	if(0 <= originnumeric <= 7)
      if(0 <= targetalpha <= 7)
        if(0 <= targetnumeric <= 7)
          if(!(board[originalpha][originnumeric]=='-')) {
            newmove=makeMove(originalpha, originnumeric, targetalpha, targetnumeric, lastmove);
            if(isLegal(newmove, board, lastmove))
              return newmove;
          }
  printf("\nI'm sorry, but that move is not valid");
  printBoard(board);
  if(whiteInCheck(board, lastmove))
    printf("\nCheck!");
  if(blackInCheck(board, lastmove))
    printf("\nCheck!");
  return getMove(board, lastmove, name);
  
}

move nextMove(char brd[][8], move lastmove, int looklevel, char player)
{
  move newmove;
  NODEPTR ptree, best;
  int value;
  //float valueprintable;
  ptree = buildTree(brd, lastmove, looklevel, player, &best, &value);
  //printf("Found best branch!\n");
  //valueprintable = (float)value;
  //valueprintable /= 1000;
  //printf("\nComputer has a tactical score of %.2f compared to the player", valueprintable);
  newmove = lastMove(best);
  return newmove;
}

NODEPTR buildTree(char brd[][8], move lastmove, int looklevel, char player, NODEPTR *best, int *value)
{
  NODEPTR ptree;
  int i, j;
  ptree=getNode();
  //printf("\nThinking...");
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      ptree->board[i][j]=brd[i][j];
  ptree->turn=1;
  ptree->lastMove=lastmove;
  //printf("\nReady to expand...");
  ptree->next=NULL;
  miniMax(ptree, 0, looklevel, 100000, player, best, value);
  //printf("\nTree build success!\n");
  return(ptree);
}

NODEPTR generate(NODEPTR p, char player, int *mate, int *moves)
{
  int i, j, k, l;
  move newmove;
  NODEPTR q = getNode();
  bool firstnode = TRUE;
  *mate=0;
  *moves=0;
  if(p->turn == -1) {
    if(player == 'W')
      player = 'B';
    else
      player = 'W';
  }
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(p->board[i][j] != '-')
        if( (player == 'W' && isupper(p->board[i][j])) || (player == 'B' && islower(p->board[i][j])) )
          for(k=0;k<8;k++)
            for(l=0;l<8;l++) {
              newmove = makeMove(i, j, k, l, lastMove(p));
              if(isLegal(newmove, p->board, lastMove(p))) {
                makeNode(p->board, q, newmove, firstnode);
				(*moves)++;
				firstnode = FALSE;
              }
            }
  if(firstnode) {
    freeNode(q);
    if(!whiteInCheck(p->board, lastMove(p)) && !blackInCheck(p->board, lastMove(p)))
      *mate=1;
    else
      *mate=2;
  }
  return q;
}

void makeNode(char brd[][8], NODEPTR q, move newmove, bool firstnode)
{
  if(firstnode==1){
    q->lastMove=newmove;
    executeMove(brd, &newmove, q->board);
    q->next=NULL;
    return;}
  if(q->next==NULL){
    NODEPTR newnode;
    newnode=getNode();
    executeMove(brd, &newmove, newnode->board);
    newnode->lastMove=newmove;
    q->next=newnode;
    newnode->next=NULL;
    return;}
  makeNode(brd, q->next, newmove, firstnode);
}

void executeMove(char position[][8], move *newmove, char newposition[][8])
{
  char temp, enpassanttemp;
  int i, j;
  if((originAlpha(*newmove)==0&&originNumeric(*newmove)==0) || (targetAlpha(*newmove)==0&&targetNumeric(*newmove)==0))
    newmove->castle[0]=0;
  if((originAlpha(*newmove)==7&&originNumeric(*newmove)==0) || (targetAlpha(*newmove)==7&&targetNumeric(*newmove)==0))
    newmove->castle[1]=0;
  if((originAlpha(*newmove)==0&&originNumeric(*newmove)==7) || (targetAlpha(*newmove)==0&&targetNumeric(*newmove)==7))
    newmove->castle[2]=0;
  if((originAlpha(*newmove)==7&&originNumeric(*newmove)==7) || (targetAlpha(*newmove)==7&&targetNumeric(*newmove)==7))
    newmove->castle[3]=0;
  temp = position[originAlpha(*newmove)][originNumeric(*newmove)];
  enpassanttemp = position[targetAlpha(*newmove)][targetNumeric(*newmove)];
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      newposition[i][j]=position[i][j];
  if(temp=='P'&&targetNumeric(*newmove)==7)
    temp='Q';
  if(temp=='p'&&targetNumeric(*newmove)==0)
    temp='q';
  newposition[originAlpha(*newmove)][originNumeric(*newmove)]='-';
  newposition[targetAlpha(*newmove)][targetNumeric(*newmove)]=temp;
  //Special conditions for castling moves
  if(temp=='K')
    if(originAlpha(*newmove)==4&&originNumeric(*newmove)==0){
      if(targetAlpha(*newmove)==2) {
        newposition[3][0]='R';
        newposition[0][0]='-';
      }
      if(targetAlpha(*newmove)==6) {
        newposition[5][0]='R';
        newposition[7][0]='-';
      }
      newmove->castle[0]=0;
      newmove->castle[1]=0;
    }
  if(temp=='k')
    if(originAlpha(*newmove)==4&&originNumeric(*newmove)==7){
      if(targetAlpha(*newmove)==2) {
        newposition[3][7]='r';
        newposition[0][7]='-';
      }
      if(targetAlpha(*newmove)==6) {
        newposition[5][7]='r';
        newposition[7][7]='-';
      }
      newmove->castle[2]=0;
      newmove->castle[3]=0;
    }
  //Special conditions for en passant
  if(temp=='P')
    if(originAlpha(*newmove) != targetAlpha(*newmove))
      if(enpassanttemp=='-')
        newposition[targetAlpha(*newmove)][4]='-';
  if(temp=='p')
    if(originAlpha(*newmove) != targetAlpha(*newmove))
      if(enpassanttemp=='-')
        newposition[targetAlpha(*newmove)][3]='-';
}

void miniMax(NODEPTR pnd, int plevel, int depth, int uvalue, char player, NODEPTR *pbest, int *pvalue)
{ /*** Leaf, unless lastmove was a capture ***/
  if(plevel==depth) {
    tacticaleval(pnd, 0, 1, 100000, player, pvalue);
    /*val = evaluate(pnd->board, player, lastMove(pnd));
    if (val > *pvalue)
      *pvalue = val;*/
    return;
  }
  /*** Root of tree ***/
  if(plevel==0){
    NODEPTR p;
    int val, mate, moves;
    p=generate(pnd, player, &mate, &moves);
	/*if(moves < 10)
		depth = 3;*/
    p->turn=-1;
    miniMax(p, plevel+1, depth, 100000, player, pbest, pvalue);
    *pbest=p;
    p=p->next;
    while(p != NULL) {
      p->turn=-1;
      miniMax(p, plevel+1, depth, *pvalue, player, pbest, &val);
	  if(val == *pvalue)
		if(rand()%2)  // Randomly pick one of the two equivalent moves
		  *pbest = p;
      if(val>*pvalue) {
          *pvalue=val;
          *pbest=p;          
        }
      p=p->next;
    }
    return;
  }
  /*** Branches of tree ***/
  else {
    NODEPTR p, q;
    int val, mate, moves;  
    p=generate(pnd, player, &mate, &moves);
    if(mate == 1) {
      *pvalue = 0;
      return;
    }
    if(mate == 2) {
      if(player=='W') {
        if(whiteInCheck(pnd->board, lastMove(pnd)))
          *pvalue = -99000;
        else
          *pvalue = 99000;
      }
      else {
        if(blackInCheck(pnd->board, lastMove(pnd)))
          *pvalue = -99000;
        else
          *pvalue = 99000;
      }
      return;
    }
    if(pnd->turn==1)
      p->turn=-1;
    else
      p->turn=1;      
    miniMax(p, plevel+1, depth, 100000, player, pbest, pvalue);
    q=p;
    p=p->next;
    freeNode(q);
    while(p != NULL) {
      if(pnd->turn==1)
        p->turn=-1;
      else
        p->turn=1;
      miniMax(p, plevel+1, depth, *pvalue, player, pbest, &val);
      if(pnd->turn==1) {
        if(val>*pvalue) {
          *pvalue=val;          
        }
        if(uvalue != 100000)
          if(uvalue<*pvalue)
          {
          	while(p != NULL)
          	{
          	  q=p;
          	  p=p->next;
          	  freeNode(q);
          	}
            return;
          }
      }
      if(pnd->turn==-1) {
        if(val<*pvalue) {
          *pvalue=val;     
        }
        if(uvalue != 100000)
          if(uvalue>*pvalue)
          {
          	while(p != NULL)
          	{
          	  q=p;
          	  p=p->next;
          	  freeNode(q);
          	}
            return;
          }
      }
      q=p;
      p=p->next;
      freeNode(q);
    }
  }
}

void tacticaleval(NODEPTR pnd, int plevel, int depth, int uvalue, char player, int *pvalue)
{
  NODEPTR p, q;
  int val, morecaptures;  
  p=tacticalgen(pnd, player, &morecaptures);
  if(morecaptures == TRUE && plevel < depth) {
    if(pnd->turn==1)
      p->turn=-1;
    else
      p->turn=1;
    tacticaleval(p, plevel+1, depth, 100000, player, pvalue);
    q=p;
    p=p->next;
    freeNode(q);
    while(p != NULL) {
      if(pnd->turn==1)
        p->turn=-1;
      else
        p->turn=1;
      tacticaleval(p, plevel+1, depth, *pvalue, player, &val);
      if(pnd->turn==1) {
        if(val>*pvalue)
          *pvalue=val;
        if(uvalue != 100000)
          if(uvalue<*pvalue)
          {
          	while(p != NULL)
          	{
          	  q=p;
          	  p=p->next;
          	  freeNode(q);
          	}
            return;
          }
      }
      if(pnd->turn==-1) {
        if(val<*pvalue)
          *pvalue=val;
        if(uvalue != 100000)
          if(uvalue>*pvalue)
          {
          	while(p != NULL)
          	{
          	  q=p;
          	  p=p->next;
          	  freeNode(q);
          	}
            return;
          }
      }
      q=p;
      p=p->next;
      freeNode(q);
    }
    val = evaluate(pnd->board, player, lastMove(pnd));
    if(pnd->turn == 1)
      if(val > *pvalue)
        *pvalue = val;
    if(pnd->turn == -1)
      if(val < *pvalue)
        *pvalue = val;
  }
  else
    *pvalue = evaluate(pnd->board, player, lastMove(pnd)); 
}

NODEPTR tacticalgen(NODEPTR p, char player, int *morecaptures)
{
  int i, j, k, l;
  move newmove;
  NODEPTR q = getNode();
  bool firstnode = TRUE;
  *morecaptures= TRUE;
  if(p->turn == -1) {
    if(player == 'W')
      player = 'B';
    else
      player = 'W';
  }
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(p->board[i][j] != '-')
        if( (player == 'W' && isupper(p->board[i][j])) || (player == 'B' && islower(p->board[i][j])) )
          for(k=0;k<8;k++)
            for(l=0;l<8;l++)
              if( (player == 'W' && islower(p->board[k][l])) || (player == 'B' && isupper(p->board[k][l])) ) {
                newmove = makeMove(i, j, k, l, lastMove(p));
                if(isLegal(newmove, p->board, lastMove(p))) {
                  makeNode(p->board, q, newmove, firstnode);
                  firstnode = FALSE;
                }
              }
  if(firstnode) {
    freeNode(q);
    *morecaptures = FALSE;
  }
  return q;
}

int evaluate(char brd[][8], char player, move lastmove)
{
  int i, j, mate=0, score=0;
  mate = isMate(brd, lastmove);
  if(mate==2) {
    if(blackInCheck(brd, lastmove))
      score += 99000;
    if(whiteInCheck(brd, lastmove))
      score += -99000;
  }
  else if(mate==1)
    return 0;
  if(score == 0)
    for(i=0;i<8;i++)
      for(j=0;j<8;j++) {
        score += peiceValue(brd[i][j]);
        score += positionalValue(i, j, brd);
      }
  //score += tacticalValue(brd, lastmove);
  if(player=='B')
    score = -score;
  return score;
}

int peiceValue(char peice)
{
  switch(peice) {
  case'K': return 99000;
  case'k': return -99000;
  case'Q': return 9000;
  case'q': return -9000;
  case'R': return 5000;
  case'r': return -5000;
  case'B': return 3000;
  case'b': return -3000;
  case'N': return 3000;
  case'n': return -3000;
  case'P': return 1000;
  case'p': return -1000;
  case'-':
  default: return 0;
  }
}

int positionalValue(int j, int i, char brd[][8])
{
  int bishopPlacement[8][8] = {
  { -100, -100, -100, -100, -100, -100, -100, -100  },
  {	-100,   25,    0,    0,    0,    0,   25, -100  },
  {	-100,    0,   50,   50,   50,   50,    0, -100  },
  {	-100,    0,   50,  100,  100,   50,    0, -100  },
  {	-100,    0,   50,  100,  100,   50,    0, -100  },
  { -100,    0,   50,   50,   50,   50,    0, -100  },
  {	-100,   25,    0,    0,    0,    0,   25, -100  },
  {	-100, -100, -200, -100, -100, -200, -100, -100  } };
  int knightPlacement[8][8] = {
  { -100, -100, -100, -100, -100, -100, -100, -100  },
  {	-100,    0,    0,    0,    0,    0,    0, -100  },
  {	-100,    0,   50,   50,   50,   50,    0, -100  },
  {	-100,    0,   50,  100,  100,   50,    0, -100  },
  {	-100,    0,   50,  100,  100,   50,    0, -100  },
  { -100,    0,   50,   50,   50,   50,    0, -100  },
  {	-100,    0,    0,    0,    0,    0,    0, -100  },
  {	-100, -200, -100, -100, -100, -100, -200, -100  } };
  int pawnPlacement[8][8] = {
  {    0,    0,    0,    0,    0,    0,    0,    0  },
  {	 200,  200,  200,  200,  200,  200,  200,  200  },
  {	  40,   80,  120,  160,  160,  120,   80,   40  },
  {	  30,   60,   90,  120,  120,   90,   60,   30  },
  {	  20,   20,   60,  100,  100,   10,   20,   10  },
  {   10,   20,    0,  -10,  -10,    0,   20,    0  },
  {	   0,    0,    0, -200, -200,    0,    0,    0  },
  {	   0,    0,    0,    0,    0,    0,    0,    0  } };
  int kingPlacement[8][8] = {
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80  },
  {  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40  },
  {	   0,   40,  200,  -40,    0,  -40,  200,   40  } };
  int flipI[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
  switch(brd[j][i]) {
  case'K': return kingPlacement[ flipI[i] ][j];
  case'k': return -kingPlacement[i][j];
  case'Q': return 0;
  case'q': return 0;
  case'R': return 0;
  case'r': return 0;
  case'B': return bishopPlacement[ flipI[i] ][j];
  case'b': return -bishopPlacement[i][j];
  case'N': return knightPlacement[ flipI[i] ][j];
  case'n': return -knightPlacement[i][j];
  case'P': return pawnPlacement[ flipI[i] ][j];
  case'p': return -pawnPlacement[i][j];
  case'-':
  default: return 0;
  }
}

int tacticalValue(char brd[][8], move lastmove)
{
	int i, j, value, multiplier;
	value = multiplier = 0;
	for(i=0;i<8;i++)
		for(j=0;j<8;j++)
			switch(brd[i][j]) { 
            case'K':
				if(whiteInCheck(brd, lastmove)) { 
					value += -300;
					multiplier--;
				}
				break;
			case'k':
				if(blackInCheck(brd, lastmove)) {
					 value += 300;
					 multiplier++;
				}
				break;
			case'Q': 
				if(attackedByPawn(i, j, brd)) {
					value += -200;
					multiplier--;
				}
				if(attackedByBishop(i, j, brd, lastmove)) {
					value += -150;
					multiplier--;
				}
				if(attackedByKnight(i, j, brd, lastmove)) {
					value += -150;
					multiplier--;
				}
				if(attackedByRook(i, j, brd, lastmove)) {
					value += -100;
					multiplier--;
				}
				break;
			case'q':
				if(attackedByPawn(i, j, brd)) {
					value += 200;
					multiplier++;
				}
				if(attackedByBishop(i, j, brd, lastmove)) {
					value += 150;
					multiplier++;
				}
				if(attackedByKnight(i, j, brd, lastmove)) {
					value += 150;
					multiplier++;
				}
				if(attackedByRook(i, j, brd, lastmove)) {
					value += 100;
					multiplier++;
				}
				break;
			case'R':
				if(attackedByPawn(i, j, brd)) {
					value += -100;
					multiplier--;
				}
				if(attackedByBishop(i, j, brd, lastmove)) {
					value += -50;
					multiplier--;
				}
				if(attackedByKnight(i, j, brd, lastmove)) {
					value += -50;
					multiplier--;
				}
				break;
			case'r':
				if(attackedByPawn(i, j, brd)) {
					value += 100;
					multiplier++;
				}
				if(attackedByBishop(i, j, brd, lastmove)) {
					value += 50;
					multiplier++;
				}
				if(attackedByKnight(i, j, brd, lastmove)) {
					value += 50;
					multiplier++;
				}
				break;
			case'B':
				if(attackedByPawn(i, j, brd)) {
					value += -50;
					multiplier--;
				}
				break;
			case'b':
				if(attackedByPawn(i, j, brd)) {
					value += 50;
					multiplier++;
				}
				break;
			case'N':
				if(attackedByPawn(i, j, brd)) {
					value += -50;
					multiplier--;
				}
				break;
			case'n':
				if(attackedByPawn(i, j, brd)) {
					value += 50;
					multiplier++;
				}
				break;
			default:;
			}
	if(multiplier < 0)
		multiplier *= -1;
	switch(multiplier) {
	case'0': return value;
		break;
	case'1': return value;
		break;
	case'2': return value * 3;
		break;
	case'3': return value * 6;
		break;
	case'4': return value * 10;
	default: ;
	}
	if(multiplier > 4)
		return value * 12;
	else
		return value;
}

bool attackedByPawn(int i, int j, char brd[][8])
{
	if(isupper(brd[i][j])) {
		if(brd[i+1][j+1] == 'p')
			return TRUE;
		if(brd[i-1][j+1] == 'p')
			return TRUE;
		return FALSE;
	}
	else {
		if(brd[i+1][j-1] == 'P')
			return TRUE;
		if(brd[i-1][j-1] == 'P')
			return TRUE;
		return FALSE;
	}
}

bool attackedByBishop(int i, int j, char brd[][8], move lastmove)
{
	int k, l;
	if(isupper(brd[i][j])) {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='b')
					if(isLegalBishop(makeMove(i, j, k, l, lastmove), brd))
						return TRUE;
		return FALSE;
	}
	else {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='B')
					if(isLegalBishop(makeMove(i, j, k, l, lastmove), brd))
						return TRUE;
		return FALSE;
	}
}

bool attackedByKnight(int i, int j, char brd[][8], move lastmove)
{
	int k, l;
	if(isupper(brd[i][j])) {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='n')
					if(isLegalKNight(makeMove(i, j, k, l, lastmove)))
						return TRUE;
		return FALSE;
	}
	else {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='N')
					if(isLegalKNight(makeMove(i, j, k, l, lastmove)))
						return TRUE;
		return FALSE;
	}
}

bool attackedByRook(int i, int j, char brd[][8], move lastmove)
{
	int k, l;
	if(isupper(brd[i][j])) {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='r')
					if(isLegalRook(makeMove(i, j, k, l, lastmove), brd))
						return TRUE;
		return FALSE;
	}
	else {
		for(k=0; k<8; k++)
			for(l=0; l<8; l++)
				if(brd[k][l]=='R')
					if(isLegalRook(makeMove(i, j, k, l, lastmove), brd))
						return TRUE;
		return FALSE;
	}
}

// Here is where the fun begins!!

bool isLegal(move m, char brd[][8], move lastmove)
{ 
  char player = 'W';
  char nextposition[8][8];
  move nextmove = makeMove(originAlpha(m), originNumeric(m), targetAlpha(m), targetNumeric(m), lastmove);
  if(0 > originAlpha(m))
    return FALSE;
  if(originAlpha(m) > 7)
  	return FALSE;
  if(0 > originNumeric(m))
    return FALSE;
  if(originNumeric(m) > 7)
    return FALSE;
  if(0 > targetAlpha(m))
    return FALSE;
  if(targetAlpha(m) > 7)
    return FALSE;
  if(0 > targetNumeric(m))
    return FALSE;
  if(targetNumeric(m) > 7)
    return FALSE;
  if(isupper(brd[targetAlpha(lastmove)][targetNumeric(lastmove)]))
    player = 'B';
  // We now know that the move involves two legit board squares.
  // Additionally we have determined whose turn it is to move.
  if(brd[originAlpha(m)][originNumeric(m)]=='-'){
    //printf(" -'s are being passed to isLegal");
    return FALSE;}
  // The origin is not an empty square.
  if(player=='W') {
    if(isupper(brd[targetAlpha(m)][targetNumeric(m)]))
      return FALSE;
    if(islower(brd[originAlpha(m)][originNumeric(m)]))
      return FALSE;
  }
  if(player=='B') {
    if(islower(brd[targetAlpha(m)][targetNumeric(m)]))
      return FALSE;
    if(isupper(brd[originAlpha(m)][originNumeric(m)]))
      return FALSE;
  }
  // The move does not try to take a peice of the same army or move a peice of the other army
  switch(brd[originAlpha(m)][originNumeric(m)]) {
    case'P': 
      if(!isLegalP(m, brd, lastmove))
        return FALSE;
      break;
    case'p':
      if(!isLegalp(m, brd, lastmove))
        return FALSE;
      break;
    case'N':
      if(!isLegalKNight(m))
        return FALSE;
      break;
    case'n':
      if(!isLegalKNight(m))
        return FALSE;
      break;
    case'B':
      if(!isLegalBishop(m, brd))
        return FALSE;
      break;
    case'b':
      if(!isLegalBishop(m, brd))
        return FALSE;
      break;
    case'R':
      if(!isLegalRook(m, brd))
        return FALSE;
      break;
    case'r':
      if(!isLegalRook(m, brd))
        return FALSE;
      break;
    case'Q':
      if(!isLegalQueen(m, brd))
        return FALSE;
      break;
    case'q':
      if(!isLegalQueen(m, brd))
        return FALSE;
      break;
    case'K':
      if(!isLegalK(m, brd))
        return FALSE;
      break;
    case'k':
      if(!isLegalk(m, brd))
        return FALSE;
      break;
    default: printf("\nError: Invalid Peice Type... %c\n", brd[originAlpha(m)][originNumeric(m)]);
    }
  // We now know that the move is to a valid square given peice type.
  executeMove(brd, &nextmove, nextposition);
  if(player=='W')
    if(whiteInCheck(nextposition, nextmove))
      return FALSE;
  if(player=='B')
    if(blackInCheck(nextposition, nextmove))
      return FALSE;
  // We now know that the move is not a move into check.
  return TRUE;
}

bool isLegalP(move m, char brd[][8], move lastmove)
{
  if(originAlpha(m)==targetAlpha(m))
    if(targetNumeric(m)==(originNumeric(m)+1))
      if(brd[targetAlpha(m)][targetNumeric(m)]=='-')
        return TRUE;
  if(targetAlpha(m)==(originAlpha(m)+1) || targetAlpha(m)==(originAlpha(m)-1))
    if(targetNumeric(m)==(originNumeric(m)+1)) {
      if(islower(brd[targetAlpha(m)][targetNumeric(m)])) {
        return TRUE; }
      else if(brd[targetAlpha(lastmove)][targetNumeric(lastmove)]=='p')
        if(targetNumeric(lastmove)==4)
          if(originNumeric(lastmove)==6)
            if(targetNumeric(m)==5)
              if(targetAlpha(m)==targetAlpha(lastmove))
                return TRUE;
    }
  if(originNumeric(m)==1)
    if(targetNumeric(m)==3)
      if(originAlpha(m)==targetAlpha(m))
        if(brd[targetAlpha(m)][targetNumeric(m)]=='-')
          if(brd[targetAlpha(m)][targetNumeric(m)-1]=='-')
            return TRUE;
  return FALSE;
}

bool isLegalp(move m, char brd[][8], move lastmove)
{
  if(originAlpha(m)==targetAlpha(m))
    if(targetNumeric(m)==(originNumeric(m)-1))
      if(brd[targetAlpha(m)][targetNumeric(m)]=='-')
        return TRUE;
  if((targetAlpha(m)==(originAlpha(m)+1) || targetAlpha(m)==(originAlpha(m)-1)))
    if(targetNumeric(m)==(originNumeric(m)-1)) {
      if(isupper(brd[targetAlpha(m)][targetNumeric(m)])) {
        return TRUE; }
      else if(brd[targetAlpha(lastmove)][targetNumeric(lastmove)]=='P')
        if(targetNumeric(lastmove)==3)
          if(originNumeric(lastmove)==1)
            if(targetNumeric(m)==2)
              if(targetAlpha(m)==targetAlpha(lastmove))
                return TRUE;
    }
  if(originNumeric(m)==6)
    if(targetNumeric(m)==4)
      if(originAlpha(m)==targetAlpha(m))
        if(brd[targetAlpha(m)][targetNumeric(m)]=='-')
          if(brd[targetAlpha(m)][targetNumeric(m)+1]=='-')
            return TRUE;
  return FALSE;
}

bool isLegalKNight(move m)
{
  if(targetAlpha(m)==(originAlpha(m)+2))
    if((targetNumeric(m)==(originNumeric(m)+1) || targetNumeric(m)==(originNumeric(m)-1)) )
      return TRUE;
  if(targetAlpha(m)==(originAlpha(m)+1))
    if((targetNumeric(m)==(originNumeric(m)+2) || targetNumeric(m)==(originNumeric(m)-2)) )
      return TRUE;
  if(targetAlpha(m)==(originAlpha(m)-1))
    if((targetNumeric(m)==(originNumeric(m)+2) || targetNumeric(m)==(originNumeric(m)-2)) )
      return TRUE;
  if(targetAlpha(m)==(originAlpha(m)-2))
    if((targetNumeric(m)==(originNumeric(m)+1) || targetNumeric(m)==(originNumeric(m)-1)) )
      return TRUE;
  return FALSE;
}

bool isLegalBishop(move m, char brd[][8])
{
  if((originAlpha(m)-targetAlpha(m)==originNumeric(m)-targetNumeric(m) || originAlpha(m)-targetAlpha(m)==targetNumeric(m)-originNumeric(m) ))
    if(isClearDiagonal(m, brd) )
      return TRUE;
  return FALSE;
}

bool isLegalRook(move m, char brd[][8])
{
  if(originAlpha(m)==targetAlpha(m))
    if(isClearFile(m, brd) )
      return TRUE;
  if(originNumeric(m)==targetNumeric(m))
    if(isClearRank(m, brd) )
      return TRUE;
  return FALSE;
}

bool isLegalQueen(move m, char brd[][8])
{
  if(isLegalRook(m, brd))
    return TRUE;
  if(isLegalBishop(m, brd))
    return TRUE;
  return FALSE;
}

bool isLegalK(move m, char brd[][8])
{
  if(targetAlpha(m)==(originAlpha(m)+1) || targetAlpha(m)==(originAlpha(m)-1) || originAlpha(m)==targetAlpha(m) )
    if(targetNumeric(m)==originNumeric(m) || targetNumeric(m)==(originNumeric(m)+1) || targetNumeric(m)==(originNumeric(m)-1) )
      return TRUE;
  if(targetAlpha(m)==2)
    if(targetNumeric(m)==0)
      if(whiteCanCastleLeft(m))
		if(brd[1][0]=='-')
          if(isClearRank(m, brd))
            if(!whiteIsPinned(3, 0, brd, m))
              if(!whiteIsPinned(2, 0, brd, m))
                if(!whiteInCheck(brd, m)) 
                  return TRUE;
  if(targetAlpha(m)==6)
    if(targetNumeric(m)==0)
      if(whiteCanCastleRight(m))
        if(isClearRank(m, brd))
          if(!whiteIsPinned(5, 0, brd, m))
            if(!whiteIsPinned(6, 0, brd, m))
              if(!whiteInCheck(brd, m))
                return TRUE;
  return FALSE;
}

bool isLegalk(move m, char brd[][8])
{
  if(targetAlpha(m)==(originAlpha(m)+1) || targetAlpha(m)==(originAlpha(m)-1) || originAlpha(m)==targetAlpha(m) )
    if(targetNumeric(m)==originNumeric(m) || targetNumeric(m)==(originNumeric(m)+1) || targetNumeric(m)==(originNumeric(m)-1) )
      return TRUE;
  if(targetAlpha(m)==2)
    if(targetNumeric(m)==7)
      if(blackCanCastleLeft(m))
	    if(brd[1][7]=='-')
          if(isClearRank(m, brd))
            if(!blackIsPinned(3, 7, brd, m))
              if(!blackIsPinned(2, 7, brd, m))
                if(!blackInCheck(brd, m))
                  return TRUE;
  if(targetAlpha(m)==6)
    if(targetNumeric(m)==7)
      if(blackCanCastleRight(m))
        if(isClearRank(m, brd))
          if(!blackIsPinned(5, 7, brd, m))
            if(!blackIsPinned(6, 7, brd, m))
              if(!blackInCheck(brd, m))
                return TRUE;
  return FALSE;
}

bool whiteInCheck(char brd[][8], move lastmove)
{
  int i, j, alpha, numeric;
  bool kingfound = 0;
  move checkingmove;
  for(i=0;i<8 && kingfound==0;i++)
    for(j=0;j<8 && kingfound==0;j++)
      if(brd[i][j]=='K') {
        alpha=i;
        numeric=j;
        kingfound=TRUE;
      }        
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(islower(brd[i][j])){
        checkingmove = makeMove(i, j, alpha, numeric, lastmove);
        switch(brd[i][j]) {
        case'k':
          if(isLegalk(checkingmove, brd))
            return TRUE;
          break;
        case'q': 
          if(isLegalQueen(checkingmove, brd))
            return TRUE;
          break;
        case'r': 
          if(isLegalRook(checkingmove, brd))
            return TRUE;
          break;
        case'b': 
          if(isLegalBishop(checkingmove, brd))
            return TRUE;
          break;
        case'n': 
          if(isLegalKNight(checkingmove))
            return TRUE;
          break;
        case'p': 
          if(isLegalp(checkingmove, brd, lastmove))
            return TRUE;
        default: break;
        }
      }
  return FALSE;
}

bool blackInCheck(char brd[][8], move lastmove)
{
  int i, j, alpha, numeric;
  bool kingfound = 0;
  move checkingmove;
  for(i=0;i<8 && kingfound==0;i++)
    for(j=8;j>0 && kingfound==0;--j)
      if(brd[i][j]=='k') {
        alpha=i;
        numeric=j;
        kingfound=TRUE;
      }        
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(isupper(brd[i][j])){
        checkingmove = makeMove(i, j, alpha, numeric, lastmove);
        switch(brd[i][j]) {
        case'K':
          if(isLegalK(checkingmove, brd))
            return TRUE;
          break;
        case'Q': 
          if(isLegalQueen(checkingmove, brd))
            return TRUE;
          break;
        case'R': 
          if(isLegalRook(checkingmove, brd))
            return TRUE;
          break;
        case'B': 
          if(isLegalBishop(checkingmove, brd))
            return TRUE;
          break;
        case'N': 
          if(isLegalKNight(checkingmove))
            return TRUE;
          break;
        case'P': 
          if(isLegalP(checkingmove, brd, lastmove))
            return TRUE;
        default: break;
        }
      }
  return FALSE;
}

bool whiteIsPinned(int alpha, int numeric, char brd[][8], move lastmove)
{
  int i, j;
  move pinningmove;
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(islower(brd[i][j])){
        pinningmove = makeMove(i, j, alpha, numeric, lastmove);
        switch(brd[i][j]) {
        case'q': 
          if(isLegalQueen(pinningmove, brd))
            return TRUE;
          break;
        case'r': 
          if(isLegalRook(pinningmove, brd))
            return TRUE;
          break;
        case'b': 
          if(isLegalBishop(pinningmove, brd))
            return TRUE;
          break;
        case'n': 
          if(isLegalKNight(pinningmove))
            return TRUE;
          break;
        case'p': 
          if(isLegalp(pinningmove, brd, lastmove))
            return TRUE;
        default: break;
        }
      }
  return FALSE;
}

bool blackIsPinned(int alpha, int numeric, char brd[][8], move lastmove)
{
  int i, j;
  move pinningmove;
  for(i=0;i<8;i++)
    for(j=0;j<8;j++)
      if(isupper(brd[i][j])){
        pinningmove = makeMove(i, j, alpha, numeric, lastmove);
        switch(brd[i][j]) {
        case'Q': 
          if(isLegalQueen(pinningmove, brd))
            return TRUE;
          break;
        case'R': 
          if(isLegalRook(pinningmove, brd))
            return TRUE;
          break;
        case'B': 
          if(isLegalBishop(pinningmove, brd))
            return TRUE;
          break;
        case'N': 
          if(isLegalKNight(pinningmove))
            return TRUE;
          break;
        case'P': 
          if(isLegalP(pinningmove, brd, lastmove))
            return TRUE;
        default: break;
        }
      }
  return FALSE;
}

bool isClearDiagonal(move m, char brd[][8])
{
  int i, j, istart, ifinish;
  if(originAlpha(m) > targetAlpha(m) && originNumeric(m) > targetNumeric(m)) {
    istart=targetAlpha(m)+1;
    ifinish=originAlpha(m);
    j=targetNumeric(m)+1;
    for(i=istart;i<ifinish;i++) {
      if(!(brd[i][j]=='-'))
        return FALSE;
      j++;
    }
    return TRUE;
  }
  if(originAlpha(m) > targetAlpha(m) && originNumeric(m) < targetNumeric(m)) {
    istart=originAlpha(m)-1;
    ifinish=targetAlpha(m);
    j=originNumeric(m)+1;
    for(i=istart;i>ifinish;i--) {
      if(!(brd[i][j]=='-'))
        return FALSE;
      j++;
    }
    return TRUE;      
  }
  if(originAlpha(m) < targetAlpha(m) && originNumeric(m) > targetNumeric(m)) {
    istart=targetAlpha(m)-1;
    ifinish=originAlpha(m);
    j=targetNumeric(m)+1;
    for(i=istart;i>ifinish;i--) {
      if(!(brd[i][j]=='-'))
        return FALSE;
      j++;
    }
    return TRUE;
  }
  else {
    istart=originAlpha(m)+1;
    ifinish=targetAlpha(m);
    j=originNumeric(m)+1;
    for(i=istart;i<ifinish;i++) {
      if(!(brd[i][j]=='-'))
        return FALSE;
      j++;
    }
    return TRUE;
  }
}

bool isClearFile(move m, char brd[][8])
{
  int i, start, finish;
  if(originNumeric(m) > targetNumeric(m)) {
    start=targetNumeric(m)+1;
    finish=originNumeric(m);
  }
  else {
    start=originNumeric(m)+1;
    finish=targetNumeric(m);
  }
  for(i=start;i<finish;i++)
    if(brd[originAlpha(m)][i]!='-')
      return FALSE;
  return TRUE;
}

bool isClearRank(move m, char brd[][8])
{
  int i, start, finish;
  if(originAlpha(m) > targetAlpha(m)) {
    start=targetAlpha(m)+1;
    finish=originAlpha(m);
  }
  else {
    start=originAlpha(m)+1;
    finish=targetAlpha(m);
  }
  for(i=start;i<finish;i++)
    if(brd[i][originNumeric(m)]!='-')
      return FALSE;
  return TRUE;
}

int isMate(char brd[][8], move lastmove)
{
  int i, j, k, l;
  move newmove;
  for(i=0;i<8;i++)
    for(j=0;j<8;j++) {
      if((!islower(brd[i][j])) && (!isupper(brd[i][j])) && (brd[i][j] != '-'))
        printf("\nError, invalid board on mate check. %c", brd[i][j]);
      if(brd[i][j] != '-')
        for(k=0;k<8;k++)
          for(l=0;l<8;l++) {
            newmove = makeMove(i, j, k, l, lastmove);
            if(isLegal(newmove, brd, lastmove))
              return 0;
          }}
  if(!whiteInCheck(brd, lastmove) && !blackInCheck(brd, lastmove))
    return 1;
  return 2;
}

move lastMove(NODEPTR p)
{
  move newmove;
  newmove = p->lastMove;
  return newmove;
}

move makeMove(int oa, int on, int ta, int tn, move lastmove)
{
  move newmove;
  int i;
  newmove.origin[0]=oa;
  newmove.origin[1]=on;
  newmove.target[0]=ta;
  newmove.target[1]=tn;
  for(i=0;i<4;i++)
    newmove.castle[i]=lastmove.castle[i];
  return newmove;
}

move convertInput(char input[], move lastmove)
{
  int oa, on, ta, tn;
  oa = (int)input[0];
  oa -= 97;
  on = (int)input[1];
  on -= 49;
  ta = (int)input[2];
  ta -= 97;
  tn = (int)input[3];
  tn -= 49;
  return makeMove(oa, on, ta, tn, lastmove);
}

char originAlpha(move newmove)
{
  return newmove.origin[0];
}

char originNumeric(move newmove)
{
  return newmove.origin[1];
}

char targetAlpha(move newmove)
{
  return newmove.target[0];
}

char targetNumeric(move newmove)
{
  return newmove.target[1];
}

bool whiteCanCastleLeft(move m)
{
  return m.castle[0];  
}

bool whiteCanCastleRight(move m)
{
  return m.castle[1];
}

bool blackCanCastleLeft(move m)
{
  return m.castle[2];
}

bool blackCanCastleRight(move m)
{
  return m.castle[3];
}

void main ( void )
{
  bool gameNotOver=1;
  bool WINBOARD=0;
  char board[8][8];
  move lastmove, newmove;
  int mate=0;
  int depth=2;
  char player='B';
  char computerplayer = 'B';
  char humanplayer = 'W';
  char nowhere;
  char input[30];
  // Buffering I/O interferes with Xboard/Winboard communication
  setbuf(stdout, NULL);
  srand(time(NULL));
  printf("Hello, please enter your name: ");
  scanf("%s", input);scanf("%c", &nowhere);
  printf("\n");
  if(strcmp(input, "xboard") == 0)
    WINBOARD=1;
  if(!WINBOARD) {
	initialize(board, &lastmove);
	printf("Hi, %s! What side would you like to control?\nPlease enter W for white or B for black: ", input);
	scanf("%c", &humanplayer);scanf("%c", &nowhere);
	if(humanplayer == 'W')
	  computerplayer = 'B';
	else
	{
	  computerplayer = 'W';
	  humanplayer = 'B';
	}
	while(gameNotOver) {
	  printBoard(board);
	  if(whiteInCheck(board, lastmove))
	    printf("\nCheck!");
	  if(blackInCheck(board, lastmove))
	    printf("\nCheck!");
	  if(player=='B')
	    player = 'W';
	  else
	    player = 'B';
	  if(player==computerplayer)
	    newmove = nextMove(board, lastmove, depth, player);
	  if(player==humanplayer)
	    newmove = getMove(board, lastmove, input);
	  printf("\n\nYep, that's legal!\nMove made: ");
      printMove(newmove);
	  executeMove(board, &newmove, board);
	  lastmove=newmove;
	  mate = isMate(board, lastmove);
	  if(mate==2) {
	    if(player=='W')
	      printf("\n****White checkmated Black!!****\n");
	    else
	      printf("\n****Black checkmated White!!****\n");
	    printBoard(board);
	    gameNotOver=FALSE;
	    printf("Press enter to exit");
	    scanf("%c", &nowhere);
	  }
	  if(mate==1) {
	    printf("\n****The game is drawn due to stalemate!!****\n");
	    printBoard(board);
	    gameNotOver=FALSE;
	    printf("Press enter to exit");
	    scanf("%c", &nowhere);
	  }
	}
  }
  else {
    // Winboard interface
    bool commandfound;
    //setbuf(stdin, NULL);
    /*if(UNIX) {
      signal(SIGTERM, SIG_IGN);
      signal(SIGINT, SIG_IGN);
    }*/
    initialize(board, &lastmove);
    player = 'W';
    while(TRUE) {
      //_read(0,&input);
      if(player == computerplayer) {               
        newmove = nextMove(board, lastmove, depth, player);
        executeMove(board, &newmove, board);
        lastmove = newmove;
        printf("move ");
        printMove(newmove);
        mate = isMate(board, lastmove);
        if(mate== 2) {
          if(computerplayer=='W')
            printf("1-0 {White mates}\n");
          else
            printf("0-1 {Black mates}\n");
	    gameNotOver=FALSE;
        }
        if(mate== 1) {
          printf("1/2-1/2 {Stalemate}\n");
        gameNotOver=FALSE;
        }
        if(player == 'W')
          player = 'B';
        else
          player = 'W';
      }
      scanf("%s", input);scanf("%c", &nowhere);
      commandfound = FALSE;
      if(strcmp(input, "new") == 0) {
        initialize(board, &lastmove);
        commandfound = TRUE;
      }
      if(strcmp(input, "quit") == 0) {
        exit(0);
      }
      if(strcmp(input, "white") == 0) {
        computerplayer = 'W';
        humanplayer = 'B';
        commandfound = TRUE;
      }
      if(strcmp(input, "black") == 0) {
        computerplayer = 'B';
        humanplayer = 'W';
        commandfound = TRUE;
      }
      // List of unsupported but recognized commands
      if(strcmp(input, "level 40 5 0") == 0) {
        printf("yaya");
        initialize(board, &lastmove);
        commandfound = TRUE;
      }
      if(strcmp(input, "post") == 0)
        commandfound = TRUE;
      if(strcmp(input, "hard") == 0)
        commandfound = TRUE;
      if(strncmp(input, "time", 4) == 0)
        commandfound = TRUE;
      if(!commandfound) {
        if(player == humanplayer) {
          newmove = convertInput(input, lastmove);
          //if(!isLegal(newmove, board, lastmove));
          if(isLegal(newmove, board, lastmove)) {
            executeMove(board, &newmove, board);
            lastmove = newmove;
            mate = isMate(board, lastmove);
            if(mate== 2) {
              if(computerplayer=='B')
                printf("1-0 {White mates}\n");
              else
                printf("0-1 {Black mates}\n");
            gameNotOver=FALSE;
            }
            if(mate== 1) {
              printf("1/2-1/2 {Stalemate}\n");
            gameNotOver=FALSE;
            }
            if(player == 'B')
              player = 'W';
            else
              player = 'B';
          }
        }
      }
    }
  }
}
