/******************************************************************************
                RedRace
                Written by Dave Hillis
                dbhillis@erols.com
                or
                hillis@arl.army.mil
                Version 0.1 for WINDOWS or UNIX
                DATE: 2/08/01
 

This program was adapted from ga_war.c written by Jason Boer. Many of Boer's ideas
and some of his code still remain.
 

--------------------- exhaust ---------------------------------------
It includes the pmars simulator "exhaust" v 1.7, written by M Joonas Pihlaja,
which plays out the actual battles between warriors.

Here is the license info for exhaust

 * Copyright (C) 2000 M Joonas Pihlaja
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * You may contact the author by:
 *   email: jpihlaja@cc.helsinki.fi
 *   mail:  M Joonas Pihlaja
 *          Artturi Kannistontie 4A11
 *          00320, Helsinki
 *          Finland
--------------------- exhaust ---------------------------------------
 
 

And Martin Ankerl provided a procedure to call exhaust, pmars(), which was the basis
for the pmars() procedure in this program.

This file is: redrace.c

type the line below to compile

gcc -o redrace redrace.c -lm -O6 -fomit-frame-pointer -W -Wall
 
 

********************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "exhaust.h"
#include "sim.h"
#include "asm.h"
//#include "sim.c" //for gcc
//#include "asm.c" //for gcc
 

/********************

#define Verbose         0       // store more info in log file? (it can grow very large)
#define FL_BASED        1       // keep a file for each warrior? (keep set to 1)
#define ELITE           0

#define P_CR            .5      // prob of using crossover vs just mutation

                                // set to zero if you don't want to use crossover
#define SHARING         0       // fitness sharing
#define ROULETTE        1       // if 1, use proportional selection - if 0, use tournament
#define T_SIZE          5       // tournament size (should be > 1,
                                //      but much smaller than the population size)
#define NEIGHBORHOOD    10      // neighborhood for local tournament selection (obsolete)
#define GEN_GAP         40      // wait this many generations before resurrecting
#define num_S_battles   100     // number of battles for scoring round
#define RINGSIZE        1000    // number of warriors in Valhalla
******************************/

#define max_num_tests   50      // hill size is num_tests
#define HILL_TEST       1  // don't change
#define MAX_ARCH_LENGTH 100
#define P_ARCH_USE 0 //  don't change
//#define SCOREFORM     " -c 500000 -p 10000 -s 55440 -l 200 -d 200"
#define SCOREFORM       ""      //Beginner hill
#define SCOREFORM_M     "-= \"S==1\" "
/*************  THESE were DEFINED IN exhaust.h
they are now set in the file redrace.dat
CORESIZE        8000  // default
MAXwSIZE        100        // default
MINwDIST        100        // default
NUMBERofCYCLES  80000    // default

#define MAXwSIZE        MAXLENGTH        //maximum warrior length
#define MINwDIST        MINSEP        //minimum distance between wariors
#define NUMBERofCYCLES  CYCLES    //cycles in pmars before a tie is declared
*********************/
#define MAXimumSIZE     210        //absolute maximum warrior length
#define MELEE_BUFFER    20      // extra space for melees
#define HARD_AFF        0       //  don't change
#define STEADYSTATE     1       // use steady state GA? don't change
#define POS_SEQ_LENGTH 1000 // length of fixed position sequence
#define SENIORITY_RULES 0 // Pick parents by age, break ties w/ score
#define FREEZE  0 // if 1, never change the position sequence
#define CROWDING 1 // if 1, don't accept functionally identical individuals
#define TIMED_OR_NOT 0 // if 1, length of battle is part of score. don't change
#define PARSIMONY 1 // if 1 && (CROWDING==1), shorter funct. identical warrior stays
// ******************* dbh. structures *******************************

typedef struct                          // INDIVIDUAL
   {
   float score;                         // fitness
   float subscores[max_num_tests + 100]; // scores against each warrior in obj. function
   float wilkies_score;                 //12/10/98
                                        // subscores[0] holds the sum
   float parentA_fitness, parentB_fitness;
   int born_on;
   char population_name[32];            //it's own name
   char hill_name[32];                  //name of the hill it tests against
   char Valhalla_name[32];              //name of its archived warriors
                                        // 5/28/99. New fields to hold the code itself
   int A[MAXimumSIZE+111], B[MAXimumSIZE+111];  // hold relative addresses of fields
   int cmd[MAXimumSIZE+111];                        // the command
   int mod[MAXimumSIZE+111];                        // the address modes
   int Am[MAXimumSIZE+111], Bm[MAXimumSIZE+111];                // the address mod_list_0
   int A_AFF[MAXimumSIZE+111], B_AFF[MAXimumSIZE+111];          // the affinities
   int length, start_point;
   }individual;
 
 

typedef struct          // line of Redcode
   {
   char l[40];
   }c_line;

// ******************* dbh. globals *******************************

float SUBSCORES[max_num_tests + MELEE_BUFFER];

FILE *fp1;
c_line ParentA[200], ParentB[200], Child[200];
individual arch;
int arch_length;
// *********************************************************************

int internal_compete_warriors(individual *W1, individual *W2, float *s1, float *s2);

int internal_compete_warriors_rnd(individual *W1, individual *W2, float *s1, float *s2);

int compete_warriors(char * source_name, char * t_name, float *s1, float *s2);

int timed_compete_warriors(char * source_name, char * t_name, float *s1, float *s2);

int dbh_run_competion(char * source_name,char * t_name);

void dbh_test_one_cycle(int p_size,char * population_name, individual pop[],
                int generation, individual hill[]);

float objective(char * source_name);

void true_stat(individual pop[]);

void dbh_fprint_header(FILE * file,char * file_name);

int weakest(individual pop[]);

void nextgen(int p_size,char * population_name,individual pop[],
                int generation, individual hill[]);

void nextgen_STD(int p_size,char * population_name,individual pop[],
                int generation, individual hill[]);

int unique(individual pop[], int new_ind);

int functionally_unique(individual pop[], int new_ind);

int tournament(individual pop[]);

int Roulette(individual pop[]);

void share(individual pop[], int verb);

float hill_objective(char * source_name, individual pop[], int n, individual hill[]);

int melee_fraticide(int p_size,char * population_name, individual pop[],
                int start, int stop, int score_form);

void make_new_hill(individual hill[]);

void score_hill( individual hill[]);

void update_hill(individual hill[], int new_member);

int challenge_hill(individual V, char * source_name, individual hill[], int *h_num, int gen_number);

void fix_names(individual r[], char * own_name, char * hill_name, char * val_name, int n);

float wilk_it(char source_name[256]);

float wilmoo_it(char source_name[256]);

float bench_mark(char source_name[256],individual *W);

void new_warrior(individual *w);

void enforce_94_rules(individual *w);

void bootstrap_pop(individual pop[],int p_size);

void init_pop(individual pop[],int p_size);

void read_in_pop(individual pop[],int p_size);

void write_out_pop(individual pop[],int p_size);

void write_warrior(individual w, char *target_name);

void read_warrior(char * w_name, individual *w);

void uniform_crossover(individual pop[], int par1, int par2, int child);

void point_crossover(individual pop[], int par1, int par2, int child);

void two_point_crossover(individual pop[], int par1, int par2, int child);

void mutate(individual pop[],int n);

void process_insertion(individual pop[],int n, int the_line);

void process_line_swap(individual pop[],int n, int the_line);

void process_deletion(individual pop[],int n, int the_line);

void standard_coords(int *ref);

void find_affinities(individual pop[],int n, int verbose);

void satisfy_affinities(individual pop[],int n, int verbose);

void fill_archive(individual pop[],int n, int verbose);

float one_cycle(individual pop[], individual hill[], int i);

void copy_a_line(individual *s, individual *d, int s_line, int d_line);

void pmars(int *w1_score, int *w2_score, int rounds,
                unsigned long cycles, unsigned long distance, int type);

void pmars_rnd(int *w1_score, int *w2_score, int rounds,
                unsigned long cycles, unsigned long distance, int type);

void change_representation(individual *W, warrior_t *w);

// ******************* dbh. procedures *******************************

int SEED;
/************************* RANDOM ************************/
/*
*       9/28/97. Returns a random integer. I think that I need this
*               to reconcile the gcc code with codewarrior libraries.
*/
// OK now I don't need it. I will swap in the standard "rand()" call
int randomX()
{
int OUT;

//SEED = (25173 * SEED + 13849) % 65536;
//OUT = SEED/65536;
OUT = rand();
return(OUT);
}
/************************* exit ************************/
/*
*       9/28/97.
*/
void exit1()
{
        printf("Error in program: Halt!\n");
}
 

//   ******************* Martin Ankerl's variables **************
// to work with Joonas' exhaust simulator
insn_t *core;           /* address of core */
warrior_t w1, w2;       /* warriors structs hold code and misc. info */

//   ******************* Martin Ankerl's variables **************

// ******************* static variables *****************************
static int best_in_pop;  // strongest
static int most_venerable; // strongest of the old
static int most_outdated; // weakest of the old

static char b_line[10];
//static char new_line[256];

// I am going to skew the prob. of picking some op_codes. 11/08/98
//
int   num_cmd_0 = 17 + 12;
char *cmd_list_0[]={\
                "dat","mov","add","sub",\
                "mul","div","mod","jmp",\
                "jmz","jmn","djn","spl",\
                "slt","cmp","seq","sne",\
                "nop",\
                "mov","mov","mov","mov",\
                "mov","mov","mov","mov",\
                "spl","spl","spl","spl",\
                "add","add","add","add",\
                "jmz","jmz","jmz","jmz",\
                "add","add","sub","sub",\
                "spl","spl","mov","mov",\
                "djn","djn","djn","djn",\
                "cmp","cmp","cmp","cmp",\
                "add","add","add","add"};

int   num_mod_list_1 = 7 + 6;
char *mod_list_1[] = {  ".a ",".b ",".ab",".ba",".f ",".x ",".i "  };
// modifiers. skewed toward "i"
int   num_mod_list_0 = 7 + 6;
char *mod_list_0[] = {  ".a ",".b ",".ab",".ba",".f ",".x ",".i ",\
                 ".i ",".i ",".i ",".i ",".i ",".i ",".i "  };

// addressing modes (can be skewed)
int   num_am_0 = 8;// + 35;
int   num_am_1 = 8;// + 35;
char *am_list_0[] = {  "#","$","@","<",">","*","{","}",\
                        "#","#","#","$","$","$","$",\
                        "#","#","#","$","$","$","$",\
                        "}","}","}","}","}","}","}",\
                        "}","}","}","}","}","}","}",\
                        "}","}","}","}","}","}","}"    };

/************************************/
//these are set in the setup()

//static char path_symbol[32]="";

static int create_new_population=0;
static char population_name[32]="";
static int population_size=0;

static int starting_cycle=0;
static int number_of_cycles=0;

static int number_of_battles=0;

static int mutation_rate=0;
static int resurrection_rate=0;
static int insertion_rate=0;
static int removal_rate=0;

static int max_number_size=0;
static int max_instructions=0;

// and here are some more
/***************************/
int P_SWAP = 3;                 //prob. of swapping positions of 2 lines
int P_long_ref = 50;    // prob of making a long (vs. local) reference
static int Verbose =    0;      // store more info in log file? (it can grow very large)
static int FL_BASED     =1;     // keep a file for each warrior?
static int  ELITE       =       0;
int P_CR = 50;  // prob of using crossover vs just mutation
                                // set to zero if you don't want to use crossover
static int  SHARING =   0;      // fitness sharing
static int  ROULETTE =  1;      // if 1, use proportional selection - if 0, use tournament
static int  T_SIZE      =       5;      // tournament size (should be > 1,
                                          //    but much smaller than the population size)
static int  GEN_GAP     =       40;     // wait this many generations before resurrecting
static int  num_S_battles  = 300;       // number of battles for scoring round
static int  RINGSIZE  =         1000;   // number of warriors in Valhalla
int num_tests = 5;
int do_random_start = 0;
int Take_Benchmark = 1;
char AUTHOR_NAME[256];
int STATIC_HILL = 0;   //if 1, never change the hill
int NUMBER_OF_SPECIES = 1;
int NUMBER_OF_BENCHMARKS = 12;
 // with the latest version of exhaust, you can set these dynamically. 10/27/00
int CORESIZE = 8000;
int MAXwSIZE = 100;        //maximum warrior length
int MINwDIST = 100;        //minimum distance between wariors
int NUMBERofCYCLES = 80000;    //cycles in pmars before a tie is declared

//int MAXwSIZE = MAXLENGTH;        //maximum warrior length
//int MINwDIST = MINSEP;        //minimum distance between wariors
//int NUMBERofCYCLES = CYCLES;    //cycles in pmars before a tie is declared
/******************/
// 8/24/00. A dynamically allocated array that holds the start position for
// each battle.
int *FixedPositionSeq;
 
 
 

int a_random_number(int range)
        {
        if (range <= 0) return(0);
        return (int)rand()%range;
        }

int a_mutation() {
        return ((a_random_number(100)+1)<=mutation_rate);
}
int b_mutation() {
        return ((rand()%1000)<=20);
}

int a_resurrection() {
        return ((a_random_number(100)+1)<=resurrection_rate);
}

int a_insertion() {
        return ((a_random_number(100)+1)<=insertion_rate);
}

int a_removal() {
        return ((a_random_number(100)+1)<=removal_rate);
}

/********************/

// ******************** dbh_fprint_header *******************
// 10/20/98. Dave Hillis
//      make a header for the warrior file
//
void dbh_fprint_header(FILE * file,char * file_name)
        {
        fprintf(file,";redcode-x verbose\n");
        fprintf(file,";assert CORESIZE == %d\n",CORESIZE);
//      fprintf(file,";assert %d\n",1);
        fprintf(file,";name %s\n",file_name);
        fprintf(file,";author %s",AUTHOR_NAME); // your name here
        fprintf(file,";strat %s\n","-   Created using RedRace.c.");
        fprintf(file,";strat %s\n","-   An evolving population playing KOTH.");
        if (CORESIZE == 8000)
          fprintf(file,";strat %s\n","-   Configured for the beginner hill.");
        if (CORESIZE == 800)
          fprintf(file,";strat %s\n","-   Configured for the Tiny hill.");
        if (CORESIZE == 55440)
          fprintf(file,";strat %s\n","-   Configured for the big hill.");
        }
// ***********end of dbh_fprint_header *******************
 

void fprint_end(FILE * target_file,int start)
// 9/20/99 puts the starting line number at the end
        {
        fprintf(target_file,"end   %d\n",start);
        }

// reads the configuration file
// virtually identical to Boer's procedure
void setup(void){

        FILE * config_file=0;
        time_t t;
        //int index;
        char buffer[256];
        char * parm_ptr=0;

        /*seed the random numbers*/
        srand((unsigned int) time(& t));

        /*set defaults*/
        create_new_population=0;
        population_size=20;
        number_of_cycles=250;
        starting_cycle=0;
        max_instructions=10;
        max_number_size=10;
        mutation_rate=1;
        insertion_rate=1;
        removal_rate=1;
        resurrection_rate=4;
        number_of_battles=3;
        do_random_start=1;
        Take_Benchmark = 0;
// and here are some more
/**************/
        Verbose =       0;      // store more info in log file? (it can grow very large)
        FL_BASED        =1;     // keep a file for each warrior? (keep set to 1)
        ELITE   =       0;
        num_tests = 25;
        P_CR    =       50;     // prob of using crossover vs just mutation
                                // set to zero if you don't want to use crossover
        P_SWAP = 3;
        P_long_ref = 50;        // Prob. of NOT restricting a field to point to a program line
        SHARING =       0;      // fitness sharing
        ROULETTE =      0;      // if 1, use proportional selection - if 0, use tournament
        T_SIZE  =       3;      // tournament size (should be > 1,
                                //      but much smaller than the population size)
        GEN_GAP =       40;     // wait this many generations before resurrecting
        num_S_battles  = 100;   // number of battles for scoring round
        RINGSIZE  =     1000;   // number of warriors in Valhalla
        sprintf(AUTHOR_NAME,"Distributed GA\n");
 STATIC_HILL = 0; //if 1, never change the hill
 NUMBER_OF_SPECIES = 1;
 NUMBER_OF_BENCHMARKS = 12;
 CORESIZE = 8000;
 MAXwSIZE = 100;        //maximum warrior length
 MINwDIST = 100;        //minimum distance between wariors
 NUMBERofCYCLES = 80000;    //cycles in pmars before a tie is declared
/************************/

        //strcpy(population_name,"ga");
        //strcpy(path_symbol,"\\");

        /*read config file if there*/
        if (0==(config_file=fopen("redrace.dat","r")))
                {
                printf("redrace.dat not found. Using defaults.\n");
                }
        else
                {
                while (fgets(buffer,255,config_file)!=0)
                        {
                        //ignore comment lines
                        if(strstr(buffer,";")!=0) continue;

                        if(strstr(buffer,"create_new_population")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        create_new_population=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"population_size")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        population_size=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"starting_cycle")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        starting_cycle=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"number_of_cycles")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        number_of_cycles=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"max_instructions")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        max_instructions=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"max_number_size")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        max_number_size=atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"mutation_rate")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        mutation_rate=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"insertion_rate")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        insertion_rate=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"removal_rate")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        removal_rate=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"resurrection_rate")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        resurrection_rate=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"number_of_battles")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        number_of_battles=atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"population_name")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        strncpy(population_name,++parm_ptr,2);
                        }
 // new parameters
                        if(strstr(buffer,"Verbose")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        Verbose = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"FL_BASED")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        FL_BASED = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"num_test")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        num_tests = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"GEN_GAP")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        GEN_GAP = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"P_CR")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        P_CR = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"P_SWAP")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        P_SWAP = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"ROULETTE")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        ROULETTE = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"T_SIZE")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        T_SIZE = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"num_S_battles")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        num_S_battles = atoi(++parm_ptr);
                        }
 

                        if(strstr(buffer,"RINGSIZE")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        RINGSIZE = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"do_random_start")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        do_random_start = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"Take_Benchmark")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        Take_Benchmark = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"P_long_ref")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        P_long_ref = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"author_name")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        strcpy(AUTHOR_NAME,++parm_ptr);
                        }
                        if(strstr(buffer,"STATIC_HILL")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        STATIC_HILL = atoi(++parm_ptr);
                        }
                        if(strstr(buffer,"NUMBER_OF_SPECIES")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        NUMBER_OF_SPECIES = atoi(++parm_ptr);
                        }
                        if(strstr(buffer,"NUMBER_OF_BENCHMARKS")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        NUMBER_OF_BENCHMARKS = atoi(++parm_ptr);
                        }
 

                        // new parameters. 11/15/00
                        if(strstr(buffer,"CORESIZE")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        CORESIZE = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"MAXwSIZE")!=0) {
                               parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        MAXwSIZE = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"MINwDIST")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        MINwDIST = atoi(++parm_ptr);
                        }

                        if(strstr(buffer,"NUMBERofCYCLES")!=0) {
                                parm_ptr=strstr(buffer,"=");
                                if (parm_ptr!=0)
                                        NUMBERofCYCLES = atoi(++parm_ptr);
                        }
 

                        }// while
                fclose(config_file);
                }// if configuration file is found
        if (do_random_start)
                {
                starting_cycle = RINGSIZE + rand()%RINGSIZE;
                //SEED =  rand()%1000;//(int) time(0);
                //srand(time(0));
                }
    if (num_tests >= max_num_tests) num_tests = max_num_tests;
        //print the values
        printf("create_new_population=%d\n",create_new_population);
        printf("population_size=%d\n",population_size);
        printf("number_of_cycles=%d\n",number_of_cycles);
        printf("starting_cycle=%d\n",starting_cycle);
        printf("max_instructions=%d\n",max_instructions);
        printf("max_number_size=%d\n",max_number_size);
        printf("mutation_rate=%d\n",mutation_rate);
        printf("insertion_rate=%d\n",insertion_rate);
        printf("removal_rate=%d\n",removal_rate);
        printf("resurrection_rate=%d\n",resurrection_rate);
        printf("number_of_battles=%d\n",number_of_battles);
        printf("(Prob of crossover) P_CR=%d\n",P_CR);
        printf("(prob. of swapping lines) P_SWAP=%d\n",P_SWAP);
        printf("(Size of the hill) num_tests=%d\n",num_tests);
        printf("(Write temp files?) FL_BASED=%d\n",FL_BASED);
        printf("(First generation when ressurection can occur) GEN_GAP=%d\n",GEN_GAP);
        printf("(Use roulette or tournament selection) ROULETTE=%d\n",ROULETTE);
        printf("(Size of tournament >= 2) T_SIZE=%d\n",T_SIZE);
        printf("(Number of battles to get on the hill) num_S_battles=%d\n",num_S_battles);
        printf("RINGSIZE=%d\n",RINGSIZE);
        printf("(prob. of generating a long vs. a local reference) P_long_ref=%d\n",P_long_ref);
        printf("STATIC_HILL=%d\n",STATIC_HILL);
        printf("NUMBER_OF_SPECIES=%d\n",NUMBER_OF_SPECIES);
        printf("NUMBER_OF_BENCHMARKS=%d\n",NUMBER_OF_BENCHMARKS);

        printf("CORESIZE=%d\n",CORESIZE);
        printf("MAXwSIZE=%d\n",MAXwSIZE);
        printf("MINwDIST=%d\n",MINwDIST);
        printf("NUMBERofCYCLES=%d\n",NUMBERofCYCLES);
        if (Take_Benchmark) printf("Calculate benchmark scores\n");
        else  printf("Don't calculate benchmark scores\n");
        printf("author name is %s\n",AUTHOR_NAME);
        //print the values
        fprintf(fp1,"create_new_population=%d\n",create_new_population);
        fprintf(fp1,"population_size=%d\n",population_size);
        fprintf(fp1,"number_of_cycles=%d\n",number_of_cycles);
        fprintf(fp1,"starting_cycle=%d\n",starting_cycle);
        fprintf(fp1,"max_instructions=%d\n",max_instructions);
        fprintf(fp1,"max_number_size=%d\n",max_number_size);
        fprintf(fp1,"mutation_rate=%d\n",mutation_rate);
        fprintf(fp1,"insertion_rate=%d\n",insertion_rate);
        fprintf(fp1,"removal_rate=%d\n",removal_rate);
        fprintf(fp1,"resurrection_rate=%d\n",resurrection_rate);
        fprintf(fp1,"number_of_battles=%d\n",number_of_battles);
        fprintf(fp1,"(Prob of crossover) P_CR=%d\n",P_CR);
        fprintf(fp1,"(prob. of swapping lines) P_SWAP=%d\n",P_SWAP);
        fprintf(fp1,"(prob. of generating a long vs. a local reference) P_long_ref=%d\n",P_long_ref);
        fprintf(fp1,"(Size of the hill) num_tests=%d\n",num_tests);
        fprintf(fp1,"(Write temp files?) FL_BASED=%d\n",FL_BASED);
        fprintf(fp1,"(First generation when ressurection can occur) GEN_GAP=%d\n",GEN_GAP);
        fprintf(fp1,"(Use roulette or tournament selection) ROULETTE=%d\n",ROULETTE);
        fprintf(fp1,"(Size of tournament >= 2) T_SIZE=%d\n",T_SIZE);
        fprintf(fp1,"(Number of battles to get on the hill) num_S_battles=%d\n",num_S_battles);
        fprintf(fp1,"RINGSIZE=%d\n",RINGSIZE);
        if (Take_Benchmark) fprintf(fp1,"Calculate benchmark scores\n");
        else  fprintf(fp1,"Don't calculate benchmark scores\n");
        fprintf(fp1,"author name is %s\n",AUTHOR_NAME);
        fprintf(fp1,"STATIC_HILL=%d\n",STATIC_HILL);
        fprintf(fp1,"NUMBER_OF_SPECIES=%d\n",NUMBER_OF_SPECIES);
        fprintf(fp1,"NUMBER_OF_BENCHMARKS=%d\n",NUMBER_OF_BENCHMARKS);
 

        fprintf(fp1,"CORESIZE=%d\n",CORESIZE);
        fprintf(fp1,"MAXwSIZE=%d\n",MAXwSIZE);
        fprintf(fp1,"MINwDIST=%d\n",MINwDIST);
        fprintf(fp1,"NUMBERofCYCLES=%d\n",NUMBERofCYCLES);
   if ( MAXwSIZE > 100 )
      {
      MAXwSIZE = 100;
      fprintf(fp1,"warning: MAXwSIZE reset to %d. see exhaust.h\n",MAXwSIZE);
      }
        fflush(fp1);
}

/********************/

// **************************** TEST ONE CYCLE ***************************
void dbh_test_one_cycle(int p_size,char * population_name, individual pop[],
                int generation, individual hill[])
        {

        int source_number;
        //int target_number;

        char source_name[256];
        //char source_file_name[256];
        //char target_name[256];
        int best=1;

        // index through whole population
        for (source_number=1;source_number<=p_size;source_number++)
                {
                    find_affinities(pop, source_number, 1);     // just to get a display on the screen
                        if (FL_BASED) write_warrior( pop[source_number],"temp.red");

                if (generation == -1)
                        {
                        pop[source_number].born_on = -1;
                        hill_objective(source_name,pop,source_number, hill);
                        }
                else
                        {
                        hill_objective(source_name,pop,source_number, hill);
                        }
                printf("%s_%d score = %f\n",
                 population_name, source_number,pop[source_number].score );
                printf("length = %d\n",pop[source_number].length );
                if (pop[source_number].score >= pop[best].score )
                        {
                        best = source_number;
                        printf(" ++++++++++++++++++++++++ best so far\n");
                        write_warrior(pop[best], "top.red");
                        }
                }

}
// ******************* end of TEST ONE CYCLE ***************************
 

// ******************  compete warriors **********************************
// 1/23/99
//              Competes 2 warriors for "number_of_battles" iterations and returns their
//      respective scores in s1 and s2. It skips the "-o" flag, so the scores are
//      returned in order and the names don't matter.
//
int compete_warriors(char * source_name,char * t_name, float *s1, float *s2)
        {
        FILE * file=0;

        char command[256];
        char buffer[256]="";
        char * s_ptr=0;

        int t_score=0;
        int s_score=0;
        int start_pt;

        /********
        printf("compete_warriors(): THIS FUNCTION SHOULD NOT HAVE BEEN CALLED\n");
        exit(0);
        *************/
        start_pt = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
        sprintf(command,"pmars -r %d -b %s %s  %s -F %d > temp.txt",
                                number_of_battles,source_name,t_name, SCOREFORM,start_pt);

        system(command);

        if ((file=fopen("temp.txt","r"))==0) exit(0);

        fgets (buffer,255,file);

        s_ptr=(strstr(buffer,"scores"));
        s_ptr+=7;
        s_score=atoi(s_ptr);
        //printf("b t_score = %d s_score = %d\n",t_score, s_score);

        fgets (buffer,255,file);

        s_ptr=(strstr(buffer,"scores"));
        s_ptr+=7;
        t_score=atoi(s_ptr);
        //printf("c t_score = %d s_score = %d\n",t_score, s_score);
        fclose(file);

        printf("^^^^^%9s %9s:%d %d\n",source_name,t_name,s_score,t_score);
        *s1 = (float) s_score;
        *s2 = (float) t_score;

return (s_score);
}// ****************** end of compete warriors **********************************

// ******************  internal compete warriors **********************************
// 7/29/00
//              Uses the gnu licensed pmars written by Joonas. Doesn't need file I/O.
//
int internal_compete_warriors(individual *W1, individual *W2, float *s1, float *s2)
        {

        int t_score=0;
        int s_score=0;
        //int start_pt;

        printf("compete   ");
        //asm_fname(source_name, &w1);
        //asm_fname(t_name, &w2);
        change_representation(W1,&w1);
        change_representation(W2,&w2);
        /*************/

        pmars(&s_score, &t_score, number_of_battles, NUMBERofCYCLES, MINwDIST, TIMED_OR_NOT);
   /**********/
        printf("EXHAUST ** :%d %d\n",s_score,t_score);
        //printf("EXHAUST ** starting pts:%d %d\n",W1->start_point,W2->start_point);

        //start_pt = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
        *s1 = (float) s_score;
        *s2 = (float) t_score;
       // *s1 /=NUMBERofCYCLES;
       // *s2 /=NUMBERofCYCLES;

return (s_score);
}// ****************** end of internal compete warriors **********************************

// ******************  RANDOM internal compete warriors **********************************
// 7/29/00
//              Uses the gnu licensed pmars written by Joonas. Doesn't need file I/O.
//
int internal_compete_warriors_rnd(individual *W1, individual *W2, float *s1, float *s2)
        {

        int t_score=0;
        int s_score=0;
        //int start_pt;

       // printf("compete   ");
        //asm_fname(source_name, &w1);
        //asm_fname(t_name, &w2);
        change_representation(W1,&w1);
        change_representation(W2,&w2);

        pmars_rnd(&s_score, &t_score, number_of_battles, NUMBERofCYCLES, MINwDIST, 0);
        printf("EXHAUST ** :%d %d\n",s_score,t_score);
        //printf("EXHAUST ** starting pts:%d %d\n",W1->start_point,W2->start_point);

        //start_pt = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
        *s1 = (float) s_score;
        *s2 = (float) t_score;

return (s_score);
}// ****************** end of RANDOM internal compete warriors **********************************
 

// ******************  TIMED compete warriors **********************************
// 4/04/00
//              Competes 2 warriors for "number_of_battles" iterations and returns their
//      respective scores in s1 and s2. It skips the "-o" flag, so the scores are
//      returned in order and the names don't matter.
//
int timed_compete_warriors(char * source_name, char * t_name, float *s1, float *s2)
        {
        FILE * file=0;
        int i;
        char command[256];
        char buffer[256]="";
        char * s_ptr=0;
        long num_cycles;
        int t_score=0;
        int s_score=0;

        printf("timed  %9s %9s: ",source_name,t_name);

        *s1 = 0.0; *s2 = 0.0; num_cycles = 80000;
        for (i = 1; i <= 4; i++)
                {
                sprintf(command,"pmars -r %d -b %s %s -c %ld> temp.txt",
                                number_of_battles*i*i,source_name,t_name,num_cycles/(i*i));

                system(command);

                if ((file=fopen("temp.txt","r"))==0) exit(0);

                fgets (buffer,255,file);

                s_ptr=(strstr(buffer,"scores"));
                s_ptr+=7;
                s_score=atoi(s_ptr);
                //printf("b t_score = %d s_score = %d\n",t_score, s_score);

                fgets (buffer,255,file);

                s_ptr=(strstr(buffer,"scores"));
                s_ptr+=7;
                t_score=atoi(s_ptr);
                printf("( %d %d )",s_score, t_score);
                fclose(file);

                *s1 += (float) s_score;
                *s2 += (float) t_score;
                }
        printf(" total: %d  %d\n",(int)(*s1), (int)(*s2));
        return (*s1);
        }
// ****************** end of timed compete warriors **********************************
 

// ******************** FIX NAMES ***********************************************
//  4/17/99
//              This procedure assigns a name to each member of the population (or hill)
//      and also assigns the name of the hill that each member will be tested against.
//              Previously, the names were hard coded. Adding the names as fields
//      makes it easy to have two or more populations of warriors interacting with
//      each other.
//
void fix_names(individual r[], char * own_name, char * hill_name, char * val_name, int n)
        {
        int index;

        for (index=0;index <= n;index++)
                {
                sprintf(r[index].population_name,own_name);
                sprintf(r[index].hill_name,hill_name);
                sprintf(r[index].Valhalla_name,val_name);
                }

        }
// ******************** end of FIX NAMES **********************************

//********************* WEAKEST ************************************
//      11/04/98
// return the number of the weakest member of the population.
// For the steady state GA, new individual will replace the weakest member.
//
int weakest(individual pop[])
        {
        int source_number;
        float min;
        int worst=1;

        min = pop[1].score;
                /*index through whole population*/
        for (source_number=1;source_number<=population_size;source_number++)
                {
                if (pop[source_number].score < pop[worst].score) {worst = source_number;}
                }
 
 

        printf("worst:  %d\n", worst);
        if (Verbose) fprintf(fp1,"worst:  %d\n", worst);
        //fflush(fp1);
        return(worst);
        }
//*************** end of WEAKEST ************************************

//********************* tournament ************************************
//      11/04/98
// Tournament selection to find one parent
// 9/28/00
//  Using seniority. The idea is that a warrior that has survived
// for several generations is probably better than a younger one with a
// higher score.
//  If (SENIORITY_RULES ==1) then the winner of the tournament will
// be the oldest warrior. The highest score breaks a tie.
//
int tournament(individual pop[])
        {
        int t2=0;
        int best, i;

        best = rand()%(population_size) + 1;
        for (i = 1; i < T_SIZE;i++)
                {
                t2 = rand()%(population_size) + 1;

                if (SENIORITY_RULES) //use seniority to pick parents
                 {
                 if (pop[t2].born_on < pop[best].born_on)
                         best = t2;
                 if ((pop[t2].born_on == pop[best].born_on)&&
                    (pop[t2].score > pop[best].score))
                         best = t2;
                 }
                else   // just use scores
                 {
                 if (pop[t2].score > pop[best].score)
                          best = t2;
                 }
                }
        return(best);
        }
//*************** end of tournament ************************************

// ***************** Roulette SELECT **************************************
// select a parent using proportional selection (roulette wheel)
//
// int Roulette(individual pop[],double sumfitness)
int Roulette(individual pop[])
        {
        int i;                       // population index
        float v,vrand, partsum;      // random point on wheel, partial sum
        float sumfitness = 0.0;

        partsum = 0.0;

                // add up all the scores. highly inefficient but simple to code up.
        for (i = 1; (i <= population_size); i++) // add up all the scores
                {
                 sumfitness += pop[i].score;
                }

        v = (float)(rand()%1007);
        vrand = (v/1007.0)*sumfitness;
        /*printf("vrand %f\n",vrand);       */

        for (i = 1; (partsum <= vrand) && (i <= population_size); i++)
                {
                partsum += pop[i].score;
/*              printf("partsum %f \n",partsum);   */
                }
        if ((i <= 1)|| (i > population_size+1)) {printf("ERROR in  Roulette(). i = %d\n",i); exit(0);}
        return(i-1);
        }
// ***************** end of Roulette SELECT *****************************

// *******************HILL OBJECTIVE **********************************
//              11/16/98
// Objective function (with fitness sharing?)
// Based on scoring against a hill. This is an attempt at making
// an endogenous fitness function that is reasonably balanced and
// stable.
//
//
float hill_objective(char * source_name, individual pop[], int n, individual hill[])
        {
        char target_name[256];
        int index;
        float score, s1, s2;
        int sy=0, y;
        int tmp;
 

        tmp = FixedPositionSeq[0];

        //printf("Testing %s\n",source_name);
        for (index=1;index< num_tests+1;index++) // for each warrior on the hill
                {
                sprintf(target_name,"%s_%d.red",pop[index].hill_name,index);
                //x = timed_compete_warriors(source_name,target_name,&s1,&s2);
                FixedPositionSeq[0] = FixedPositionSeq[index];
                internal_compete_warriors(&pop[n], &hill[index], &s1,&s2);
                y = s1;
                sy += y;
                pop[n].subscores[index] = (float)y;
                }

        FixedPositionSeq[0] = tmp;

//printf("J score = %f\n",(float)(sy) * 100.0/(float)( number_of_battles * (num_tests+0) ));
        score =  (float)(sy) * 100.0/(float)( number_of_battles * (num_tests+0) );
        pop[n].subscores[0] = score;
        pop[n].score = score;
        return(score);
        }
// ********** end of HILL OBJECTIVE **************************************

// **************************** Multi_Warrior_Test ***************************
//      6/30/00
//        This procedure tests a number of warriors on a multiwarrior (melee) hill.
//      The strongest is written into the file temp.red. In nextgen(), parents create
//      10 children and only the strongest gets to enter the general population: (melee
//      fratricide). The procedure is also used to create the initial population.
//      7/27/00
//        The procedure uses the 's==1' scoring function. It returns a zero if non
//      of the children receive a non_zero score.
//
int melee_fraticide(int p_size,char * population_name, individual pop[],
                int start, int stop, int score_form)
        {

        int source_number;
        //int target_number;
        //int blk;
        char source_name[256];
        //char source_file_name[256];
        char target_name[556];
        char command[556];
        char buffer[256]="";
        char * s_ptr=0;
        FILE * file=0;
        //int score=0;
        int best=1;
        //int chunk = 30;
 

        // build list of filenames
           sprintf(target_name,"");
           for (source_number=start;source_number<= stop; source_number++)
                {
                sprintf(source_name,"%s_%d.red ",population_name,source_number);
                strcat(target_name,source_name);

                }
           printf("%s\n",target_name);
           // run the battle
           if (score_form == 0)         // use default scoring
                        sprintf(command,"pmars -r %d -b %s  %s > temp.txt",
                                                20, target_name, SCOREFORM);
           else                         // same as KotH multi-warrior hill
                        sprintf(command,"pmars -r %d -b %s  %s > temp.txt",
                                                20, target_name, SCOREFORM_M);
           system(command);
           if ((file=fopen("temp.txt","r"))==0) exit(0);

           //index through new individuals to read scores
           best=start;
           for (source_number=start;source_number<= stop; source_number++)
                {
                fgets (buffer,255,file);
                s_ptr=(strstr(buffer,"scores"));
                s_ptr+=7;
                pop[source_number].score = atoi(s_ptr);
                //fprintf(fp1,"%s\n",buffer);
                printf("%s  ",buffer);
                fgets (buffer,255,file); // skip next line (the subscores)
                                         //print out subscores
                printf("%s",buffer);
                //fprintf(fp1,"%s\n",buffer);

                //printf("%d score = %f\n",source_number,pop[source_number].score );
                //printf("length = %d\n",pop[source_number].length );
                //fprintf(fp1,"%d score = %f\n",source_number,pop[source_number].score );
                //fprintf(fp1,"length = %d\n",pop[source_number].length );
                if (    (pop[source_number].score > pop[best].score ) ||
                        (
                                (pop[source_number].score == pop[best].score)&&
                                (pop[source_number].length < pop[best].length)
                         )
                   )
                        {
                        best = source_number;
                        printf(" ++++++++++++++++++++++++ best so far\n");
                        //write_warrior(pop[best], "top.red");
                        write_warrior(pop[best], "temp.red");
                        }
                }
           fclose(file);
        if (pop[best].score > 0) return(1); //success
        else                     return(0);
        }
// ******************* end of Multi_Warrior_Test ***************************
 

// ******************* SCORE HILL **********************************
//              11/16/98
//      Get the rankings for the warriors on the hill by battling each of them
//      against all the others. Fortunately, you only need to call this procedure
//      once when you create a new hill.
//
void score_hill( individual hill[])
        {
        int index, i, temp;
        char target_name[256];

        temp = number_of_battles; // remember old value
        number_of_battles = num_S_battles;

        for (index=1;index<num_tests+1;index++) // initialize hill scores
                {
                hill[index].score = 0.0;
                for (i=1;i<= num_tests+1;i++) // update total scores
                        {
                        hill[index].subscores[i] = 0.0;
                        }
                }
        for (index=1;index<num_tests+1;index++)
                {
                sprintf(target_name,"%s_%d.red", hill[index].population_name, index);

                hill_objective(target_name, hill, index, hill);
                printf("hill: %d score = %f\n",index, hill[index].score);
                }

        number_of_battles = temp; // reinstate old value
        }
// ******** end of SCORE HILL **********************************
 

// ******************* UPDATE HILL **********************************
//              1/23/99
//      Get the rankings with repect to the new member and update the hill.
//
void update_hill(individual hill[], int new_member)
        {
        int index, i, temp;
        char target_name1[256], target_name2[256];
        float s1, s2;

        temp = number_of_battles; // remember old value
        number_of_battles = num_S_battles;

        printf("updating hill scores\n");
        sprintf(target_name1,"%s_%d.red",hill[1].population_name, new_member);
        for (index=1;index<num_tests+1;index++) // update subscores
                {
                sprintf(target_name2,"%s_%d.red", hill[index].population_name, index);
                //timed_compete_warriors(target_name1,target_name2,&s1,&s2);
                //compete_warriors(target_name1,target_name2,&s1,&s2);
                internal_compete_warriors(&hill[new_member], &hill[index], &s1,&s2);
                hill[new_member].subscores[index] = s1;
                hill[index].subscores[new_member] = s2;
                if (index == new_member) {hill[index].subscores[new_member] = (s1 + s2)/2;}
                //printf("(%.0f, %.0f) ",s1, s2);
                }

        for (index=1;index<num_tests+1;index++) // update total scores
                {
                hill[index].score = 0.0;
                for (i=1;i<num_tests+1;i++) // update total scores
                        {
                        hill[index].score += hill[index].subscores[i];
                        }
                hill[index].score *= 100.0/(float)( number_of_battles * (num_tests+0) );
                printf("hill: %d score = %f\n",index, hill[index].score);
                fprintf(fp1,"hill: %d score = %f\n",index, hill[index].score);
                }

        number_of_battles = temp; // remember old value
 
 

        }
// ******** end of UPDATE HILL **********************************

// ******************* CHALLENGE HILL **********************************
//              11/16/98
//      A warrior, V, competes against the hill (with more battles and hence higher
//      accuracy than is used for the general population). If its score is higher than
//      that of the lowest ranking hill member, a copy of V is placed on the hill.
//
int challenge_hill(individual V, char * source_name, individual hill[], int *h_num, int gen_number)
        {
        int source_number, i;
        float sum=0.0, avg, max, min;
        int best=1, worst=1, temp, changed = 0;
        char target_name[256];
 

        printf("HILL %s\n",hill[1].population_name);
        fprintf(fp1,"HILL %s\n",hill[1].population_name);

        //score_hill(hill);     // incredibly expensive waste of time
        //      printf("incredibly expensive waste of time\n");

        max = hill[1].score; min =hill[1].score; sum = 0.0;
                /*index through whole population*/
        for (source_number=1;source_number<=num_tests;source_number++)
                {
                fprintf(fp1,"%s ",hill[source_number].Valhalla_name);
                printf("%s ",hill[source_number].Valhalla_name);
                fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
                        hill[source_number].born_on, hill[source_number].score );
                printf("%2d born on %2d, score = %.2f ", source_number,
                        hill[source_number].born_on, hill[source_number].score);
                printf("["); fprintf(fp1,"[");
                for (i = 1; i < num_tests+1; i++)
                        {
                        printf(" %d ",(int)( hill[source_number].subscores[i] ) );
                        fprintf(fp1," %d ",(int)( hill[source_number].subscores[i] ) );
                        }
                printf("] wilk %.2f\n",hill[source_number].wilkies_score );
                fprintf(fp1,"] wilk %.2f\n",hill[source_number].wilkies_score );
 

                sum += hill[source_number].score;
                if (hill[source_number].score > hill[best].score ) {best = source_number;}
                if (hill[source_number].score < hill[worst].score) {worst = source_number;}
                }
        avg = sum/num_tests;

        printf("hill: max = %f, min = %f, best = %d, avg = %f\n",
                hill[best].score, hill[worst].score, best, avg);
        fprintf(fp1,"hill: max = %f, min = %f, best = %d, avg = %f\n",
                hill[best].score, hill[worst].score, best, avg);

        printf("Writing the top warrior to alpha.red\n");
        write_warrior( hill[best],"alpha.red");

        temp = number_of_battles; // remember old value
        number_of_battles = num_S_battles;
        memcpy(&hill[max_num_tests+1],&V,sizeof(individual));
                // but now I have to restore the population name
        sprintf(hill[max_num_tests+1].population_name,hill[1].population_name);
        hill_objective(source_name, hill, max_num_tests+1,hill);  // more accurate measure

        printf("old score %f, new %f\n",hill[worst].score,hill[max_num_tests+1].score);
        fprintf(fp1,"old score %f, new %f\n",hill[worst].score,hill[max_num_tests+1].score);
        number_of_battles = temp; // remember old value
        if (hill[max_num_tests+1].score > hill[worst].score)
                {
                memcpy(&hill[worst],&hill[max_num_tests+1],sizeof(individual));
                printf("Challenger replaces %d on the hill\n",worst);
                fprintf(fp1,"Challenger replaces %d on the hill\n",worst);
                sprintf(target_name,"%s_%d.red", hill[worst].population_name, worst);
                sprintf(hill[worst].Valhalla_name,"%s",V.Valhalla_name);

                write_warrior( V,target_name);
                hill[worst].wilkies_score = 0;
                hill[worst].born_on = gen_number;
                update_hill(hill, worst);     // just update what's needed
                /***************
                score_hill(hill);     // incredibly expensive waste of time
                printf("incredibly expensive waste of time\n");
                ********************/
                changed = 1;
                *h_num = worst;
                }
 

        return(changed);
        }
// ******** end of CHALLENGE HILL **********************************
 

//********************* SHARE ************************************
//      11/04/98
// For fitness sharing. (But mostly used as a diagnostic now.)
//
void share(individual pop[], int verb)
        {
        int source_number, i;
        float sub[max_num_tests+1];
        //int worst=1;
 

        for (i = 0; i < num_tests+1; i++) sub[i] = 0;

                /*index through whole population to find averages*/
        for (source_number=1;source_number<=population_size;source_number++)
                {
                for (i = 1; i < num_tests+1; i++)
                        sub[i] += pop[source_number].subscores[i];
                }

        if (verb)
                {
                printf("share:  ["); fprintf(fp1," [");
                for (i = 1; i < num_tests+1; i++)
                        {
                        printf(" %.2f",(float)sub[i]/(float)population_size );
                        fprintf(fp1,"  %.2f ",(float)sub[i]/(float)population_size );
                        }
                printf("]\n"); fprintf(fp1,"