#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef __GNUC__
#include "clib.h"
#endif
#include "othello.h"
#include "global.h"
#include "io.h"


/* ================================================================== */

void     resetstate();
bool     do_move();
bool     game_ended();
int      num_legal_moves();
Square   get_best_move();

/* Forward declarations. */
void    play();


/*
 * Tell the user how this program is started.
 */

void
usage()
{
    fprintf(stderr,
	    "usage: %s [-X | -O] [-q] [-l1 | -l2 | ... | -l9] \n",
	    progname);
    fprintf(stderr, "-X\tHuman plays the X color (black). Default\n");
    fprintf(stderr, "-O\tHuman plays the O color (white).\n");
    fprintf(stderr, "-q\tQuiet mode. (default is not quiet mode)\n");
    fprintf(stderr, "-l1\tPlay at level 1. (default is level 3)\n");
    fprintf(stderr, "-l2\tPlay at level 2.\n");
    fprintf(stderr, "...\n");
    fprintf(stderr, "-l9\tPlay at level 9.\n");
    exit(1);
}


void
main(argc, argv)
int    argc;
char   *argv[];
{
    char    *chp;
    int     i;

    /* Find the name of this program. */
    if ((progname = strrchr(argv[0], '/')) == NULL) 
	progname = argv[0] ;
    else 
	progname ++ ;

    /* Some default values. */
    level = 3;
    mycolor = WHITE;
    yourcolor = BLACK;
    quietmode = FALSE;

    /* Get all the options. */
    for (i = 1; i < argc; ++i) {
	chp = argv[i];
	if (*chp++ != '-')
	    usage();
	else {
	    switch (*chp++) {
	      case 'O':
		mycolor = BLACK;
		yourcolor = WHITE;
		break;
	      case 'X':
		mycolor = WHITE;
		yourcolor = BLACK;
		break;
	      case 'l':
		if (isdigit(*chp) && *chp > '0')
		    level = *chp - '0';
		else
		    usage();
		break;
	      case 'q':
		quietmode = TRUE;
		break;
	      default:
		usage();
	    }
	}
    }
    srandom(getpid());
    init_sqlists();
    init_io(&argc, argv);

    show_status(NOGAME);
    start_game();
    do {
	init_io_for_one_game();
	game_in_progress = TRUE;
	play();
	game_in_progress = FALSE;
	show_status(NOGAME);
    } while (another_game());
}



/*
 * Play the actual game. This function is the main loop of the
 * program.
 */


void
play()
{
    State      playstate;
    Square     sq;
    Savemove   moves[60];
    int        currentmove;
    Color      color;
    bool       passed;
    int        leveloffset;
    State      laststate;
    int        lastleveloffset;
    int        lastcurrentmove;
    int        lastpassed;
    bool       undoinfovalid;

    resetstate(&playstate);
    leveloffset = 0;
    currentmove = 0;
    undoinfovalid = FALSE;

    /* There is no need to do a deep search on the first move. */
    if (mycolor == WHITE)
	print_message("You start.\n", FALSE);
    else {
	static Square   first_moves[] = {34, 43, 56, 65};

	sq = first_moves[random() % 4];

	(void) do_move(&playstate, sq, MYCOLOR);
	moves[currentmove].color = MYCOLOR;
	moves[currentmove++].sq = sq;

	print_message("OK, I play black so I start.\n", FALSE);
	print_my_move(sq);
    }
    if (!quietmode)
	print_state(&playstate);

    /* This is the main loop of the program */
    color = YOURCOLOR;
    passed = FALSE;
    while (num_legal_moves(&playstate, MYCOLOR) != 0
	   || num_legal_moves(&playstate, YOURCOLOR) != 0) {
	if (color == YOURCOLOR) {
	    show_status(YOURMOVE);
	    do {
		sq = get_users_move(&playstate);
		if (sq == UNDO) {
		    if (undoinfovalid) {
			playstate = laststate;
			leveloffset = lastleveloffset;
			currentmove = lastcurrentmove;
			passed = lastpassed;
			undoinfovalid = FALSE;
			print_board(&playstate.board[0]);
		    } else {
			print_message("no!\n", TRUE);
		    }
		}
	    } while (sq == UNDO);
	    
	    if (sq == RESIGN)
		break;

	    laststate = playstate;
	    lastleveloffset = leveloffset;
	    lastcurrentmove = currentmove;
	    lastpassed = passed;
	    undoinfovalid = TRUE;

	    print_your_move(sq);
/*	    print_message("\n", TRUE); */

	} else {
/* Not used while testing.
	    if (currentmove + level > 52 && currentmove >= 49){
		sq = endgame(&playstate);
	    } else 
*/
	    show_status(MYMOVE);
	    sq = get_best_move(&playstate, level + leveloffset);
	    print_my_move(sq);
	}

	/* If both players have passed, then the game is ended. */
	if (sq == PASS) {
	    if (passed)
		break;
	    else
		passed = TRUE;
	} else {
	    passed = FALSE;
	    (void) do_move(&playstate, sq, color);
	    moves[currentmove].color = color;
	    moves[currentmove++].sq = sq;
	}

	if (!quietmode)
	    print_state(&playstate);

	/* Increase the depth of the search towards the end of the */
	/* game. The time needed for this is made up for by there */
	/* not being so many moves to choose from at the end. */
	if (currentmove > 45) {
	    leveloffset++;
	}

	color = OTHER(color);
    }

    /* Present some statistics at the end of the game. */
    if (!quietmode)
	print_statistics(&playstate);
}
