/*****
 * Carlo C. Maley   7/17/94


In the spirit of Artificial Life exploring the space of all posible life, this is a model
that explores the basic conditions for evolution; survival and reproduction.  Or perhaps
more specifically, longevity and mutation.  These parameters were suggested by
Richard Lewontin in a conversation in October 1993.


The only reason I can think of to limit one's life span is to increase turnover and thus
adaptation in the lineage (a group selectionist argument).  Thus I need some model of
shifting fitness landscapes as well as longevity and mutation rates.  I will use Holland's
"attack and defense tags" as a start.

Survival will be a function of senescence as well as competition.  Each organism will
interact with N neighbors in the array each time step.  It will build up a score for
its fitness via the interactions.  That may be compared to the average score and those
below will be killed.  The deaths by competition and senescence will be collected in a
stack.  Then the survivors (organized in a ring) will get to reproduce into the empty
spaces in the ring.  The last reproducer will be remembered an reproduction for the
next turn will pick up there.

An interaction consists of comparing the organism's attack tag versus its neighbor's
defense tag.  (not vice versa)  This allows the full range of interactions from
mutualism to competition.  An organism doesn't loose points from being attacked, only
by a non-sucessful attempt to attack a neighbor.

Call a mutation of the escape tag a defection, and assume that without defection that the
pursuit tag of one's opponent matches your escape tag (as it seems to evolve to do).
Then the payoff matrix looks like:

						C	D
					C	4,4 3,4
					D	4,3 3,3
					
This is not a prisoner's dilemma since it doesn't matter what I do, once my opponent has
chosen a move.  I'll get the same payoff either way.

Now consider making an interaction a two way street with a double bonus for a sucessful 
pursuit, minus my opponent's pursuit.  Then the payoff matrix looks like:

						C	D
					C	4,4 2,5
					D	5,2 3,3
	
A true prisoner's dilemma.  A player here is a lineage.

In the previous payoff scheme, I seem to get convergence towards 100 heritability, but
with the prisoner's dilemma it looks like heritability stays in the 90's.

An environment could easily be added by attaching a pursue and escape tag to each
position.  Changes in the environment could occur slowly over time or seasonally.
 *
 *****/
 
 
#include <stdio.h>
#include <string.h>
#include <oops.h>
/*#include <profile.h>*/
#include <console.h>
#include "windowUtils.h"
#include "LewObjects.h"
#include "Lewstats.h"
#include "Lew.h"


/****
 * main
 *
 *
 ****/

void main( void)
{
	cPopulation *the_pop;
	cContext *context;
	cStats *stats;
/*	FILE *proffp;

	InitProfile(200,200);
*/	
	SetUpWindows();

	context = new cContext;
	
	the_pop = new cPopulation;
	the_pop->init_pop(context);
	
	stats = new cStats;
	stats->setup(context->pop_size);
	

/*	the_pop->print_pop();*/

	for(;context->num_trials > 0; context->num_trials--, context->current_trial++)
	{
		init_new_trial(context,the_pop,stats);
	
		printf("%d: Time: %d\n", context->current_trial, context->time_step);
		the_pop->competition(context);
		stats->record_state(the_pop, context);
		context->time_step++;

		for (;context->running(); context->time_step++) 
		{
			the_pop->update_pop();
			printf("%d: Time: %d\n", context->current_trial, context->time_step);
			the_pop->competition(context);
			stats->record_state(the_pop, context);
		}

		the_pop->save_pop(context->endfp);
	}
	
/*	cecho2file("profile.out", 0, proffp);*/
	
	clean_up();
}


/* Subroutines ----------------------------------------------------*/

/*reverses a string.*/

void reverse(char s[])
{
	int i, j;
	char c;
	
	for(i=0, j=strlen(s)-1; i<j; i++, j--)
	{
		c = s[i];
		s[i] = s[j];
		s[j] = c;
	}
}

/*converts an integer into a string.*/
void itoa(int n, char s[])
{
	int i;
	
	i = 0;
	do
	{
		s[i++] = n % 10 + '0';
	} while ((n /= 10) > 0);
	
	s[i] = '\0';
	reverse(s);
}


/*This has to setup the new file names, open them, initialize a new population, and reset
most everything.*/

void init_new_trial(cContext *context, cPopulation *pop, cStats *stats)
{
	char log_suffix[10] = ".log";
	char data_suffix[10] = ".dat";
	char num_string[10];
	char temp[20];
	char logfile[MAXLINELENGTH];
	char datafile[MAXLINELENGTH];

	context->time_step = 0;
	
	itoa(context->current_trial, num_string);
	
	strcpy(logfile, context->prefix);
	strcat(logfile, num_string);
	strcpy(datafile, logfile);
	strcat(logfile, log_suffix);
	strcat(datafile, data_suffix);
	/*
	strcpy(temp, strcat(num_string, log_suffix));
	strcpy(logfile, strcat(context->prefix, temp));
	strcpy(temp, strcat(num_string, data_suffix));
	strcpy(context->endfile, strcat(context->prefix, temp));
	*/
	
	stats->close_file();/*close and flush last log file.*/
	if (context->endfp != NULL)
		fclose(context->endfp); /*close and flush last data file*/
	
	stats->open_file(logfile);

	context->endfp = fopen(datafile, "w");
	fprintf(context->endfp, "Population size = %d\t Number of time steps = %d\n", context->pop_size,
			context->max_iterations);
	fprintf(context->endfp, "Radius of interaction = %d\t Random number seed = %d\n", context->radius,
			context->randseed);
	fprintf(context->endfp, "Pursuit factor = %f\t Escape factor = %f\n\n", context->pursuit_factor,
			context->escape_factor);
			
			
	pop->reset_pop();  /*Just puts in new genes.*/
	




}
void clean_up()
{	
	/*Pause before exiting.*/
	fflush(stdin);
	printf("Hit any key to exit. ");
	getchar();
}