
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <strings.h>

#include <X11/IntrinsicP.h>
#include <X11/Xlib.h>

#include "xgammon.h"
#include "gammon.h"

extern Widget toplevel, text_display;
extern char add_text[];
extern FILE *endgame_database;
extern int end_of_game;

extern void Quit();
extern void AppendDialogText();
extern void CreateDialogWindow();
extern void load();
extern void save ();
extern void switch_turn();
extern int  doubler();
extern int  test_move();
extern struct _Move *find_best_move();
extern int  end_of_game_test();

void RollOut();
void RolloutLoop(void);
void RolloutGame(void);
void RolloutMove(void);
void init_rollout(void);
void rollout_roll_dice();
void exec_rollout();

void RollOut(void)
{
	char *v[2], *flag = "m";
	int i;

	CreateDialogWindow(toplevel);
	XtRealizeWidget(toplevel);

	v[0] = flag;
	v[1] = gammon_resource.position_file;
	load (0L, 0L, v, 0);

	for (i=0; i<29; i++) {
		rollout_position[i].count = Pin[i].count;
		rollout_position[i].color = Pin[i].color;
	}

	rollout_save.turn          = turn;
	rollout_save.doubler_value = doubler_value;
	rollout_save.last_doubler  = last_doubler;
	rollout_save.roll[0]       = roll[0];
	rollout_save.roll[1]       = roll[1];

	tournament.winning_point = gammon_resource.num_rollouts;
	AppendDialogText(text_display, "xgammon rollout: ");
	sprintf (add_text, "rollout: %d games\n", gammon_resource.num_rollouts);
	AppendDialogText(text_display, add_text);
	AppendDialogText(text_display, "points: white 0, black 0\n");

	tournament.points[BLACK] = 0;
	tournament.points[WHITE] = 0;


	XtRealizeWidget(toplevel);
	XSync(dpy, 0);
	sleep(1);
	RolloutLoop();

	AppendDialogText(text_display, "rollout done\n");
	sleep(7);
	Quit(toplevel, 0L, 0L);
}

void RolloutLoop(void)
{
	FILE *result_file;

	unsigned int won_games[3] ={0,0,0};

	while (tournament.game_number < (tournament.winning_point + 1)) {
		init_rollout();
		RolloutGame();
		tournament.points[turn] += doubler_value;
		won_games[turn] ++;
		sprintf (add_text, "done.. won games: black %d, white %d points: black %d, white %d\n",won_games[BLACK], won_games[WHITE], tournament.points[BLACK], tournament.points[WHITE]);
		AppendDialogText(text_display, add_text);
	}
	result_file = fopen(gammon_resource.position_file, "a");
	AppendDialogText(text_display, "\nrollout complete. result:\n");

	fprintf (result_file, "\nrollout result of %d games:\n", tournament.winning_point);
	sprintf (add_text, "of %d games\n", tournament.winning_point);
	AppendDialogText(text_display, add_text);
	sprintf (add_text, "   black won %d games and got %d points.\n", won_games[BLACK], tournament.points[BLACK]);
	fprintf (result_file, add_text);
	AppendDialogText(text_display, add_text);

	sprintf (add_text, "   white won %d games and got %d points.\n", won_games[WHITE], tournament.points[WHITE]);
	fprintf (result_file, add_text);
	AppendDialogText(text_display, add_text);

	sprintf (add_text, "   backgammons: black: %d white %d\n", backgammons[BLACK], backgammons[WHITE]);
	fprintf (result_file, add_text);
	AppendDialogText(text_display, add_text);

	sprintf (add_text, "   gammons: black: %d white %d\n", gammons[BLACK], gammons[WHITE]);
	fprintf (result_file, add_text);
	AppendDialogText(text_display, add_text);

	sprintf (add_text, "   in percent: black won %2.2f%%, white won %2.2f%%\n",  ((float) won_games[BLACK] * 100 / (float) tournament.winning_point), ((float) won_games[WHITE] * 100 / (float) tournament.winning_point));
	fprintf (result_file, add_text);
	AppendDialogText(text_display, add_text);

	fclose(result_file);

	XSync(dpy, 0);	/* and 7 seconds */
}

void RolloutGame(void)
{
	end_of_game = 0;
	while (1) {
		RolloutMove();
		if (end_of_game) break;
		switch_turn();
	/*	RolloutMove();
		if (end_of_game) break;
		switch_turn(); */
	}
}

void RolloutMove(void)
{
	int i;
	if (gammon_resource.doubling) {
		if (last_doubler != turn && doubler_value <= 64) {
		        last_doubler = turn;
			if (!doubler (OFFER)) {
				end_of_game = 1;
				return;
			}
		}
	}
	rollout_roll_dice();
        if (test_move()) {
		struct _Move *this_move;
		this_move = (struct _Move *) find_best_move();
		for (i=0; i<to_move; i++) {
			Pin[(this_move+i)->from].count--;
			if (Pin[(this_move+i)->from].count == 0) Pin[(this_move+i)->from].color = 0;

			if ((this_move+i)->to == end_pin) {
				if ((end_of_game = end_of_game_test(turn)))
					return;
	        	}
			else if (Pin[(this_move+i)->to].color == other) {
				Pin[(this_move+i)->to].color = turn;
				Pin[OTHER_BAR].count++;
				Pin[OTHER_BAR].color = other;
			}
			else {
				Pin[(this_move+i)->to].count++;
				Pin[(this_move+i)->to].color = turn;
			}
		}
	}
}

void init_rollout(void)
{
	int i;

	for (i=0; i<29; i++) { 
		Pin[i].count = rollout_position[i].count;
		Pin[i].color = rollout_position[i].color;
	}

	turn          = rollout_save.turn;
	doubler_value = rollout_save.doubler_value;
	last_doubler  = rollout_save.last_doubler;
	roll[0]       = rollout_save.roll[0];
	roll[1]       = rollout_save.roll[1];

        if (roll[0] != roll[1]) {
                roll[2] = 0;
                roll[3] = 0;
		to_move = 2;
		pash = 0;
	}
        else {
		roll[2] = roll[0];
		roll[3] = roll[1];
		to_move = 4;
		pash = 1;
	}

	switch_turn(); switch_turn();	/* set vars */

	tournament.game_number++;
	sprintf(add_text,"rollout game number %d\n", tournament.game_number);
	AppendDialogText(text_display, add_text);
}

void rollout_roll_dice(void)
{
	roll[0] = (rand()%6 + 1) * direction;
	roll[1] = (rand()%6 + 1) * direction;

        if (roll[0] != roll[1]) {
                roll[2] = 0;		/* sure and necessary */
                roll[3] = 0;
		to_move = 2;
		pash = 0;
	}
        else {
		roll[2] = roll[0];
		roll[3] = roll[1];
		to_move = 4;
		pash = 1;
	}
}

/* exec_rollout:
   saves the current position in a (position) save file, and then
   execs a xgammon with approriate options.
   this is why:
   1. cause of some problems with X* libs xgammon will grow (fast)
      in memory usage. After about 650 games with certain optins,
      it will use about 24 Mb space. 
      (This is not an xgmmon fault (!?!) Other programs also do,
      for example play (at least older versions of) xbombs and
      do some ps -m sometimes). But they are running only
      short times and don't use that much graphics).
      This may be fixed some day.
   2. you'll get bored with it and your eyes will hurt, and it's slow
   3. you can continue playing
 */

void exec_rollout(void)
{
	int pid;			/* execed process */
	int ppid = getpid();		/* this process */
	static int called_rollout = 0;	/* count to make files somewhat unequivocal */

	char *argv[8];
	char *v[3];
	char rollout_save_file[50];
	char nr[7];
	sprintf (nr, "%d", gammon_resource.num_rollouts);

	called_rollout ++;
	sprintf(rollout_save_file,"xgammon.rollout.%d.save", (ppid + called_rollout));

	v[0] = "r";
	v[1] = rollout_save_file;
	v[2] = NULL;
	save (0L, 0L, v, 0);

	argv[0] = "xgammon";
	argv[1] = "-rollout";
	argv[2] = "-nr";
	argv[3] = nr;
	argv[4] = "-f";
	argv[5] = rollout_save_file;
	argv[6] = "-doubling";		/* yet necessary */
	argv[7] = NULL;

	signal(SIGCLD,SIG_IGN);

	if((pid=fork()) == 0) {
		execvp("xgammon", argv);
	}
	else if(pid>0) {
		return;
	}
	else {	/* should not happen */
		AppendDialogText(text_display, "sorry, couldn't fork rollout process\n");
		return;
	}
}
