/*
 * play.c
 *
 *  Scott Adkins
 *    sadkins@bigbird.cs.ohiou.edu
 *    sadkins@oucsace.cs.ohiou.edu
 *
 *  Purpose: Plays the game in various ways.
 *
 */

#include "corewar.h"
#include "externs.h"


int ClearResults(programs)
PROGRAM *programs;
{
	PROGRAM *p;

	p = programs;
	while (p) {
		p->twins = p->wins + p->twins;
		p->tlosses = p->losses + p->tlosses;
		p->tties = p->ties + p->tties;

		p->wins = 0;
		p->losses = 0;
		p->ties = 0;

		p = p->next;
	}

	return (1);
}

int PrintResults(program)
PROGRAM *program;
{
	PROGRAM *p;

	p = program;
	printf("W=%d L=%d T=%d\t",p->wins,p->losses,p->ties);
	printf("%4d\t%s\n",3 * p->wins + p->ties,p->filename);

	return (1);
}

int PrintSingles(programs, cycles, Tasks)
PROGRAM *programs;
int cycles, *Tasks;
{
	PROGRAM *p;

	printf("  W/  L/  T%40s%8s\n","Name","Tasks");
	printf("-----------------------------------------");
	printf("------------------\tCycles: %6d\n",cycles);

	p = programs;
	while (p) {
		printf("%3d/%3d/%3d",p->twins,p->tlosses,p->tties);
		printf("%40s%8d\n",p->filename,Tasks[p->index]);
		p = p->next;
	}

	return (1);
}

int PrintTotals(programs)
PROGRAM *programs;
{
	register int i;
	int max, score;
	PROGRAM *p;

	printf("  W/  L/  T%40s%8s\n","Name","Score");
	printf("-------------------------------");
	printf("----------------------------\n");

	p = programs;
	while (p) {
		score = 3 * p->twins + p->ties;
		if (score > max) max = score;
		p = p->next;
	}

	for (i = max; i >= 0; i--) {
		p = programs;
		while (p) {
			score = 3 * p->twins + p->ties;
			if (i != score) {
				p = p->next;
				continue;
			}

			printf("%3d/%3d/%3d",p->twins,p->tlosses,p->tties);
			printf("%40s%8d\n",p->filename,score);
			p = p->next;
		}
	}

	return (1);
}

int Assemble(programs)
PROGRAM *programs;
{
	PROGRAM *p;

	p = programs;
	while (p) {
		printf("Assembling file %s:\n",p->filename);
		if (!LoadProgram(NULL,p,0,ASSEMBLE)) return (0);
		printf("\n\n");
		p = p->next;
	}

	return (1);
}
	
int Singles(Core, programs, arena, process, size)
CORE *Core;
PROGRAM *programs;
int arena, process, size;
{
	int play, Tasks[MAX_PROG];
	TASKS *CLL[MAX_PROG];
	char output[81];
	register int i;
	PROGRAM *p;

	InitCore(Core,size);

	p = programs;
	while (p) {
		if (!LoadProgram(Core,p,size,LOAD))
			return (0);

		if (Stats) {
			printf("Loading program %s into Core!\n",p->filename);
			PrintCore(Core,p->address,p->length,size);
		}

		if (!InitProgram(p,&CLL[p->index],&Tasks[p->index]))
			return (0);

		p = p->next;
	}

	if (Display) InitDisplay(programs,size);

	for (i=0, play=arena; (i < Cycles) && (play-1 > 0); i++) {
		if (Display)
			if (!DisplayCore(Core,size,i,Display,Fade,arena,Tasks))
				break;
		EMI88(CLL,Core,process,size,Tasks,arena,i);

		play = 0;
		p = programs;
		while (p) {
			if (Tasks[p->index] > 0) play++;
			p = p->next;
		}
	}

	if (Display) DisplayCore(Core,size,i,0,Fade,arena,Tasks);

	p = programs;
	while (p) {
		if ((Tasks[p->index] > 0) && (play-1 > 0)) {
			if (Display) DisplayString("a tie is declared");
			p->ties++;
		} else if (Tasks[p->index] > 0) {
			sprintf(output," %s is winner",p->filename);
			if (Display) DisplayString(output);
			p->wins++;
		} else if ((play-1 < 0) && (!p->next)) {
			sprintf(output," %s is winner",p->filename);
			if (Display) DisplayString(output);
			p->wins++;
		} else p->losses++;
		p = p->next;
	}

	ClearResults(programs);

	if (Display) EndDisplay();
	else if (Totals) PrintSingles(programs,i,Tasks);

	return (1);
}

int Multiples(Core, programs, arena, process, size, counter)
CORE *Core;
PROGRAM *programs;
int arena, process, size, counter;
{
	int play, Tasks[MAX_PROG];
	TASKS *CLL[MAX_PROG];
	register int i;
	PROGRAM *p;

	while (counter-- > 0) {
		InitCore(Core,size);

		p = programs;
		while (p) {
			if (!LoadProgram(Core,p,size,LOAD))
				return (0);

			if (!InitProgram(p,&CLL[p->index],&Tasks[p->index]))
				return (0);

			p = p->next;
		}

		for (i=0, play=arena; (i < Cycles) && (play-1 > 0); i++) {
			EMI88(CLL,Core,process,size,Tasks,arena,i);

			play = 0;
			p = programs;
			while (p) {
				if (Tasks[p->index] > 0) play++;
				p = p->next;
			}
		}

		p = programs;
		while (p) {
			if ((Tasks[p->index] > 0) && (play-1 > 0)) p->ties++;
			else if (Tasks[p->index] > 0) p->wins++;
			else if ((play-1 < 0) && (!p->next)) p->wins++;
			else p->losses++;
			p = p->next;
		}
	}

	ClearResults(programs);

	if (Totals) PrintTotals(programs);

	return (1);
}

int Challenge(Core, programs, process, size, counter)
CORE *Core;
PROGRAM *programs;
int process, size, counter;
{
	int play, Tasks[MAX_PROG];
	TASKS *CLL[MAX_PROG];
	register int c, i;
	PROGRAM *p, *q;

	p = q = programs;
	while (q) {
		c = counter;
		if (p == q) c = counter/2 + counter%2;

		while (c-- > 0) {
			InitCore(Core,size);

			if (!LoadProgram(Core,p,size,LOAD))
				return (0);

			if (!InitProgram(p,&CLL[0],&Tasks[0]))
				return (0);

			if (!LoadProgram(Core,q,size,LOAD))
				return (0);

			if (!InitProgram(q,&CLL[1],&Tasks[1]))
				return (0);

			for (i=0, play=1; (i < Cycles) && (play); i++) {
				EMI88(CLL,Core,process,size,Tasks,2,i);
				if (Tasks[0] <= 0) {
					p->losses++;
					play = 0;
				} else if (Tasks[1] <= 0) {
					q->losses++;
					play = 0;
				}
			}

			if (play) p->ties++;
			else if (Tasks[0] > 0) p->wins++;

			if (play) q->ties++;
			else if (Tasks[1] > 0) q->wins++;
		}

		if (Results) {
			if (p == q) {
				printf("Program \"%s\" ",p->filename);
				printf("fights against itself:\n");
			}

			PrintResults(p);
			if (p != q) PrintResults(q);
			printf("\n");
		}

		ClearResults(programs);

		q = q->next;
	}

	if (!Totals) return (1);

	printf("  W/  T/  L%40s%8s\n","Name","Score");
	printf("-----------------------------------------------------------\n");
	printf("%3d/%3d/%3d",p->twins,p->tlosses,p->tties);
	printf("%40s%8d\n",p->filename,3 * p->twins + p->tties);

	return (1);
}

int Rounds(Core, programs, process, size, counter)
CORE *Core;
PROGRAM *programs;
int process, size, counter;
{
	int play, Tasks[MAX_PROG];
	TASKS *CLL[MAX_PROG];
	register int c, i;
	PROGRAM *p, *q;

	p = programs;
	while (p) {
		q = p;
		while (q) {
			c = counter;
			if (p == q) c = counter/2 + counter%2;

			while (c-- > 0) {
				InitCore(Core,size);

				if (!LoadProgram(Core,p,size,LOAD))
					return (0);

				if (!InitProgram(p,&CLL[0],&Tasks[0]))
					return (0);

				if (!LoadProgram(Core,q,size,LOAD))
					return (0);

				if (!InitProgram(q,&CLL[1],&Tasks[1]))
					return (0);

				for (i=0, play=1; (i < Cycles) && (play); i++) {
					EMI88(CLL,Core,process,size,Tasks,2,i);
					if (Tasks[0] <= 0) {
						p->losses++;
						play = 0;
					} else if (Tasks[1] <= 0) {
						q->losses++;
						play = 0;
					}
				}

				if (play) p->ties++;
				else if (Tasks[0] > 0) p->wins++;

				if (play) q->ties++;
				else if (Tasks[1] > 0) q->wins++;
			}

			if (Results) {
				if (p == q) {
					printf("Program \"%s\" ",p->filename);
					printf("fights against itself:\n");
				}

				PrintResults(p);
				if (p != q) PrintResults(q);
				printf("\n");
			}

			ClearResults(programs);

			q = q->next;
		}

		p = p->next;
	}

	if (Totals) {
		if (Results) printf("\n");
		PrintTotals(programs);
	}

	return (1);
}
