/******************************************************************************
                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,"]\n");

                }

                /*index through whole population to adjust scores*/
        if (SHARING || (!HILL_TEST))
           for (source_number=1;source_number<=population_size;source_number++)
                {
                pop[source_number].score = 0.0;
                for (i = 1; i < num_tests+1; i++)
                        {
                        if (SHARING)
                                pop[source_number].score +=
                                   pop[source_number].subscores[i]/(sub[i] + .001);
                        else
                                pop[source_number].score +=
                                   pop[source_number].subscores[i]/(float)num_tests;
                        }
                }

        }
//*************** end of SHARE ************************************

// **************************** TRUE STAT ***************************
// get the statistics for the population
//
void true_stat(individual pop[])
        {
        int source_number, i;
        float sum=0.0, avg, max, min;
        int best=1, worst=1;
        long length = 0;
        int oldest = 1;
 

        share( pop, 1);
        printf("STAT\n");
        max = pop[1].score; min = pop[1].score; sum = 0.0;
                /*index through whole population*/
 

        if (!Verbose)           // print out stats for first individual only
                {               // which is from "bestwar.red"
                source_number=1;
                fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
                        pop[source_number].born_on, pop[source_number].score );
                printf("%2d born on %2d, score = %.2f ", source_number,
                        pop[source_number].born_on, pop[source_number].score);
                printf("["); if (Verbose) fprintf(fp1,"[");
                for (i = 1; i < num_tests+1; i++)
                        {
                        printf(" %3d",(int)pop[source_number].subscores[i]);
                        fprintf(fp1," %3d",(int)pop[source_number].subscores[i]);
                        }
                printf("] true %.2f\n",pop[source_number].subscores[0] );
                fprintf(fp1,"] true %.2f\n",pop[source_number].subscores[0] );
                }
 

        for (source_number=1;source_number<=population_size;source_number++)
                {
                if (Verbose) fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
                        pop[source_number].born_on, pop[source_number].score );
                if (Verbose) printf("%2d born on %2d, score = %.2f ", source_number,
                        pop[source_number].born_on, pop[source_number].score);
                if (Verbose) printf("["); if (Verbose) fprintf(fp1,"[");
                for (i = 1; i < num_tests+1; i++)
                        {
                        if (Verbose) printf(" %3d",(int)pop[source_number].subscores[i]);
                        if (Verbose) fprintf(fp1," %3d",(int)pop[source_number].subscores[i]);
                        }
                if (Verbose) printf("] true %.2f\n",pop[source_number].subscores[0] );
                if (Verbose) fprintf(fp1,"] true %.2f\n",pop[source_number].subscores[0] );
 

                sum += pop[source_number].score;
                length += pop[source_number].length;

                if (pop[source_number].score > pop[best].score ) {best = source_number;}
                if (pop[source_number].score < pop[worst].score) {worst = source_number;}
                if (pop[source_number].born_on < pop[oldest].born_on) {oldest = source_number;}
                }
        avg = sum/population_size;

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

        max = pop[1].subscores[0]; min = pop[1].subscores[0]; sum = 0.0;
        most_venerable = oldest; most_outdated = oldest;
                /*index through whole population*/
        for (source_number=1;source_number<=population_size;source_number++)
                {
                sum += pop[source_number].subscores[0];
                if (pop[source_number].subscores[0] > pop[best].subscores[0] ) {best = source_number;}
                if (pop[source_number].subscores[0] < pop[worst].subscores[0]) {worst = source_number;}
 
 

                if (pop[source_number].born_on == pop[oldest].born_on)
                 {
                 if (pop[source_number].score > pop[most_venerable].score )
                 most_venerable = source_number;
                 if (pop[source_number].score < pop[most_outdated].score )
                 most_outdated = source_number;
                 }

                }
        avg = (sum - pop[worst].score)/(population_size-1);
        fprintf(fp1,"STAT: adjusted average - not including the worst\n");
        printf("STAT: adjusted average - not including the worst\n");
        printf("STAT: average length = %f\n",( (float)(length) )/(float)(population_size) );
 

        printf("most venerable is %3d which was born on %d and scores %f\n",
          most_venerable, pop[most_venerable].born_on, pop[most_venerable].score);
        printf("most outdated is  %3d which was born on %4d and scores %f\n",
          most_outdated, pop[most_outdated].born_on, pop[most_outdated].score);

        fprintf(fp1,"STAT: average length = %f\n",( (float)(length) )/(float)(population_size) );
        printf("TRUE STAT: max = %f, min = %f, best = %d (born on %d), avg = %f\n",
                pop[best].subscores[0], pop[worst].subscores[0], best, pop[best].born_on, avg);
        fprintf(fp1,"TRUE STAT: max = %f, min = %f, best = %d (born on %d), avg = %f\n",
                pop[best].subscores[0], pop[worst].subscores[0], best, pop[best].born_on, avg);
        fprintf(fp1,"most venerable is %3d which was born on %d and scores %f\n",
          most_venerable, pop[most_venerable].born_on, pop[most_venerable].score);
        fprintf(fp1,"most outdated is  %3d which was born on %4d and scores %f\n",
          most_outdated, pop[most_outdated].born_on, pop[most_outdated].score);

        share( pop, 1);

        //fflush(fp1);

        best_in_pop = best; // 11/17/98 will challenge the hill
        }
// **************** end of TRUE STAT ***************************
// ********************** WILK IT ****************************************
float wilk_it(char source_name[256])
        {
        char target_name[256];
        //char command[256];
        int score=0, temp;
        float s1, s2;
        temp = number_of_battles; // remember old value
        number_of_battles = 100;

                sprintf(target_name,"time.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"bluefunk.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"cannon.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"fstorm.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"irongate.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"marcia13.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"nobody.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"paperone.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"pswing.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"rave.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"thermite.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"tornado.red");
                score += compete_warriors(source_name,target_name,&s1,&s2);
 

                printf("WILK IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
                fprintf(fp1,"WILK IT: %s score = %f\n\n",source_name,(float)(score)/12.0);

        number_of_battles = temp; // remember old value

        //fflush(fp1);
        return( (float)(score)/12.0 );
}// ************* end of WILK IT ****************************************

// ********************** WILMOO IT ****************************************
float wilmoo_it(char source_name[256])
        {
        char target_name[256];
        //char command[256];
        int score=0, temp;
        float s1, s2;
        temp = number_of_battles; // remember old value
        number_of_battles = 100;

                sprintf(target_name,"BENJSRE.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"BLUR2.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"ELECTRIC.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"HESCANSA.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"IMPFINIT.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"JACKINTH.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"NEWT.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"SCANMAN.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"STEPPING.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"THEFUGIT.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"TORCHT18.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);
                sprintf(target_name,"UNREQUIT.RED");
                score += compete_warriors(source_name,target_name,&s1,&s2);

                printf("WILMOO IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
                fprintf(fp1,"WILMOO IT: %s score = %f\n\n",source_name,(float)(score)/12.0);

        number_of_battles = temp; // remember old value

        //fflush(fp1);
        return( (float)(score)/12.0 );
}// ************* end of WILMOO IT ****************************************

// ********************** BENCH MARK ****************************************
float bench_mark(char source_name[256],individual *W)
        {
        char target_name[256];
        //char command[256];
        int score=0, temp,i;
        float s1, s2;
        individual I;

        temp = number_of_battles; // remember old value
        number_of_battles = num_S_battles;
        for (i=1; i<= NUMBER_OF_BENCHMARKS; i++)
         {
  sprintf(target_name,"b1_%d.red",i);
         read_warrior(target_name,&I);
         internal_compete_warriors_rnd(W,&I,&s1,&s2);
         printf("number %d benchmark warrior %f %f\n",i, s1,s2);
         fprintf(fp1,"number %d benchmark warrior %f %f\n",i, s1,s2);
         score += s1;
         }

        printf("BENCH MARK: %s score = %f\n\n",
         source_name,(float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles));
        fprintf(fp1,"WILK IT: %s score = %f\n\n",
         source_name,(float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles));

        number_of_battles = temp; // remember old value

        //fflush(fp1);
        return( (float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles) );
}// ************* end of BENCH MARK ****************************************

//************************** new_warrior ****************************
//      Form a new random warrior.
// 8/07/00
//
void new_warrior(individual *w)
        {
        int line,j;
        individual dummy[1]; // not pretty!

        printf("new_warrior for %s\n",w->population_name);
                j = 1 + (rand()%max_instructions);

                if ( j > MAXwSIZE ) {j = MAXwSIZE;}
                dummy[0].length = 2;

                for (line = 0; (line < 3)&&(line < j); line++) //create a few lines
                        {
                        dummy[0].cmd[line] = rand()%num_cmd_0;
                        dummy[0].mod[line] =  rand()%num_mod_list_0;
                        dummy[0].Am[line] = rand()%num_am_0;
                        dummy[0].Bm[line] = rand()%num_am_0;
                        dummy[0].A[line] = rand()%CORESIZE;
                        dummy[0].B[line] = rand()%CORESIZE;
                        dummy[0].A_AFF[line] = -1;
                        dummy[0].B_AFF[line] = -1;
                        }
                dummy[0].start_point = 0;
                 // insert random lines until you reach the proper size
                while (dummy[0].length < j)
                 {process_insertion(dummy,0,(dummy[0].length/2)+rand()%(dummy[0].length/2));}

                //memcpy(w,&dummy[0],sizeof(individual)); this would overwrite the names
                for (line = 0; line < dummy[0].length; line++) //copy the lines back
                 {copy_a_line(&dummy[0], w, line,line );}
                w->length = dummy[0].length;
                for (line = w->length; line < 100; line++) //neatness
                        {
                        w->cmd[line] = 0;
                        w->mod[line] = 0;
                        w->Am[line] = 1;
                        w->A[line] =  0;
                        w->B[line] =  0;
                        w->Bm[line] = 1;
                        w->A_AFF[line] =  -1;
                        w->B_AFF[line] =  -1;
                        }
        enforce_94_rules(w); // catch whatever is screwing up the warriors. 10/23/00
       // now test all the fields. 9/29/00
        for (line = 0; line < w->length; line++)
         {
                standard_coords(&w->A[line]); // clean up references
                standard_coords(&w->B[line]);
                                //      check for errors
                if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
                     (w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
                     (w->Am[line] < 0)  || (w->Am[line] >= num_am_0) ||
                     (w->Bm[line] < 0)  || (w->Bm[line] >= num_am_0) )
                        {
                        printf("new warrior: ERROR. [%d %d %d %d, %d %d]\n",
                                w->cmd[line],w->mod[line],w->Am[line],w->A[line],
                                w->Bm[line], w->B[line]);
                        printf("In line %d of %d\n",line,w->length);
                        w->length = line;
                        if (w->start_point >= line) { w->start_point = 0;}
                        printf("exit now\n");
                        fflush(fp1);
                        exit(0);
                        }
                 }

        if (w->start_point >= w->length ) { w->start_point = 0;}

        }
//******************* end of new_warrior ****************************

//************************** enforce_94_rules ****************************
//      Enforce 94 rules.
// 10/10/00
//
void enforce_94_rules(individual *w)
        {
        int line;
 

        printf("enforce_94_rules for %s\n",w->population_name);

        // first test the fields for out of bounds
       // now test all the fields. 9/29/00
        for (line = 0; line < w->length; line++)
         {
                standard_coords(&w->A[line]); // clean up references
                standard_coords(&w->B[line]);
                                //      check for errors
                if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
                     (w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
                     (w->Am[line] < 0)  || (w->Am[line] >= num_am_0) ||
                     (w->Bm[line] < 0)  || (w->Bm[line] >= num_am_0) )
                        {
                        printf("enforce 88: ERROR. [%d %d %d %d, %d %d]\n",
                            w->cmd[line],w->mod[line],w->Am[line],w->A[line],
                                w->Bm[line], w->B[line]);
                        printf("In line %d of %d\n",line,w->length);
                        if (w->start_point >= line) { w->start_point = rand()%(w->length);;}
                        printf("setting line to default\n");
                        w->cmd[line] = 0;
                        w->mod[line] = 0;
                        w->Am[line] = 1;
                        w->A[line] =  0;
                        w->B[line] =  0;
                        w->Bm[line] = 1;
                        w->A_AFF[line] =  -1;
                        w->B_AFF[line] =  -1;
                        fflush(fp1);
                        }
                 }
 

       if (0)
        { // turn this stuff off for now. 10/23/00

        for (line = 0; line < MAXwSIZE; line++) // for every line
         {
         // check the command
         //(this case shouldn't happen)
         if ((w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0))
          w->cmd[line] = rand()%num_cmd_0;

         // can't use DIV, MUL, SEQ, SNE
         /***********
                "dat","mov","add","sub",\
                "mul","div","mod","jmp",\
                "jmz","jmn","djn","spl",\
                "slt","cmp","seq","sne",\
                "nop",
         ***************/
         while ( (strncmp(cmd_list_0[w->cmd[line]],"seq",3) == 0 ) ||
           (strncmp(cmd_list_0[w->cmd[line]],"sne",3) == 0 ) ||
           (strncmp(cmd_list_0[w->cmd[line]],"mul",3) == 0 ) ||
           (strncmp(cmd_list_0[w->cmd[line]],"mod",3) == 0 ) ||
           (strncmp(cmd_list_0[w->cmd[line]],"nop",3) == 0 ) ||
           (strncmp(cmd_list_0[w->cmd[line]],"div",3) == 0 )    )
          w->cmd[line] = rand()%num_cmd_0;
         w->mod[line] = 4; // only .f modifier

         // For any command
         while (    (strncmp(am_list_0[w->Am[line]],"#",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
            w->Am[line] = rand()%num_am_0;
         while ((strncmp(am_list_0[w->Bm[line]],"#",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
            w->Bm[line] = rand()%num_am_0;

         // DAT [#<] [<#]
         if ((strncmp(cmd_list_0[w->cmd[line]],"dat",3) == 0 ))
          {
          while ((strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"#",1) != 0 ) )
            w->Am[line] = rand()%num_am_0;
          while ((strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"#",1) != 0 ) )
            w->Bm[line] = rand()%num_am_0;
          }
         // MOV [#$@<] [$@<] (add, sub, cmp)
         if ((strncmp(cmd_list_0[w->cmd[line]],"mov",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"add",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"sub",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"cmp",3) == 0 ) )
          {
          while ((strncmp(am_list_0[w->Am[line]],"#",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
            w->Am[line] = rand()%num_am_0;
          while ((strncmp(am_list_0[w->Bm[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
            w->Bm[line] = rand()%num_am_0;
          }
         // SPL [$@<] [#$@<] (jmp,jmn,jmz,djn)
         if ((strncmp(cmd_list_0[w->cmd[line]],"spl",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"jmp",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"jmn",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"jmz",3) == 0 ) ||
             (strncmp(cmd_list_0[w->cmd[line]],"djn",3) == 0 ) )
          {
          while ((strncmp(am_list_0[w->Am[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
            w->Am[line] = rand()%num_am_0;
          while ((strncmp(am_list_0[w->Bm[line]],"#",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"$",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
              (strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
            w->Bm[line] = rand()%num_am_0;
          }

         }
       // now test all the fields. 9/29/00
        for (line = 0; line < w->length; line++)
         {
                standard_coords(&w->A[line]); // clean up references
                standard_coords(&w->B[line]);
                                //      check for errors
                if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
                     (w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
                     (w->Am[line] < 0)  || (w->Am[line] >= num_am_0) ||
                     (w->Bm[line] < 0)  || (w->Bm[line] >= num_am_0) )
                        {
                        printf("enforce 88: ERROR. [%d %d %d %d, %d %d]\n",
                            w->cmd[line],w->mod[line],w->Am[line],w->A[line],
                                w->Bm[line], w->B[line]);
                        printf("In line %d of %d\n",line,w->length);
                        w->length = line;
                        if (w->start_point >= line) { w->start_point = 0;}
                        printf("exit now\n");
                        fflush(fp1);
                        exit(0);
                        }
                 }
       } // above section is turned off. 10/23/00

        if (w->start_point >= w->length ) { w->start_point = rand()%(w->length);;}
        printf("enforce_94_rules for %s is finished\n",w->population_name);

        }
//******************* end of enforce_94_rules ****************************

//************************** BOOTSTRAP Population ****************************
//      9/20/00 Form a new random population using a bootstrap method.
//  Create randomized individuals and accept the first one
// automatically.  Only accept individual # n into the population
// if it can defeat individual # (n-1) in head-to-head combat.
//   After 100 unsuccessful tries, it will give up, form a
//      new random individual and continue from there.
//  The idea is that this will force the initial population
// to be much stronger than otherwise and that the initial amount
// of usefull variation may be higher.
//
void bootstrap_pop(individual pop[],int p_size)
        {
        int j,k,attempts=0;
        long length=0;
        float s1, s2, bestsofar=0;

        printf("bootstrap_pop for %s\n",pop[1].population_name);
        new_warrior(&pop[0]); // position zero is unused

        for (k = 1; k <= p_size;k++)  // index starts at 1
           {
           pop[k].score = 0.0;
           pop[k].wilkies_score = 0.0;
           bestsofar = 0.0;
           for (j=0;j<= max_num_tests;j++) // update total scores
                {
                pop[k].subscores[j] = 0.0;
                }
           pop[k].born_on = 0;
          printf("BOOTSTRAP: Warrior %s number %d attempt number %d\n",
           pop[1].population_name, k, attempts+1);
          new_warrior(&pop[k]); // form a new warrior

               // compete it withwarrior k-1
           internal_compete_warriors_rnd(&pop[k], &pop[k-1], &s1,&s2);

               // if it beats it, it lives!
           if (s1 > s2)
            {
            find_affinities(pop, k, 1);
            write_warrior(pop[k], "temp.red");
            length += pop[k].length;
            printf("BOOTSTRAP: Accepted after %d attempts\n",attempts+1);
            fprintf(fp1,"BOOTSTRAP: Accepted after %d attempts\n",attempts+1);
            attempts=0;
            }
           else
            {
            if ( s1 >= bestsofar )
             {
             bestsofar = s1;
             memcpy(&pop[k+1],&pop[k],sizeof(individual));
             if (FL_BASED) write_warrior(pop[k], "temp2.red");
             }
            attempts++;
            k--;
            }
           if (attempts > 100)
            {
            k++;
            attempts=0;
            printf("BOOTSTRAP: Giving up on beating number %d\n",k-1);
            printf("BOOTSTRAP: best score against it was %f\n",bestsofar);
            fprintf(fp1,"BOOTSTRAP: Giving up on beating number %d\n",k-1);
            fprintf(fp1,"BOOTSTRAP: best score against it was %f\n",bestsofar);
            memcpy(&pop[k],&pop[k+1],sizeof(individual));
            find_affinities(pop, k, 1);
            if (FL_BASED) write_warrior(pop[k], "temp.red");
            }
           //write_warrior(pop[k], file_name);
           }

        printf("init: average length = %f\n",( (float)(length) )/(float)(p_size) );
        fprintf(fp1,"init: average length = %f\n",( (float)(length) )/(float)(p_size) );
        }
//******************* end of bootstrap_pop ****************************

//************************** init_pop ****************************
//      Form a new random population.
// 5/28/99 create the internal representation for a new population
// 6/16/00      Create a number of random individuals and compete them
//      on a melee hill, then select the winner to enter the general population.
//
void init_pop(individual pop[],int p_size)
        {
        int i,j,k;
        char file_name[256];
        //char source_name[256];
        long length=0;
        float s1,s2;

        printf("init_pop for %s\n",pop[1].population_name);
        for (k = 1; k <= p_size;k++)  // index starts at 1
           {
           pop[k].score = 0.0;
           pop[k].wilkies_score = 0.0;
           for (j=0;j<= max_num_tests;j++) // update total scores
                {
                pop[k].subscores[j] = 0.0;
                }
           pop[k].born_on = 0;

                sprintf(file_name,"%s_%d.red",pop[1].population_name,k);
           for (i = p_size+1; i <= p_size+2; i++)
                {
                new_warrior(&pop[i]); // form a new warrior
            }
                //compete the 20 new warriors all together in 1 core
          // melee_fraticide(population_size,pop[1].population_name, pop,
          //                            p_size+1, p_size+20, 0);
           internal_compete_warriors(&pop[p_size+1], &pop[p_size+2], &s1,&s2);
           if (s1 > s2) {memcpy(&pop[k],&pop[p_size+1],sizeof(individual));}
           else         {memcpy(&pop[k],&pop[p_size+2],sizeof(individual));}
          // read_warrior("temp.red",&pop[k]); // read in melee winner
           //write_warrior(pop[k], file_name);
           find_affinities(pop, k, 1);
           length += pop[k].length;
           }

        printf("init: average length = %f\n",( (float)(length) )/(float)(p_size) );
        fprintf(fp1,"init: average length = %f\n",( (float)(length) )/(float)(p_size) );
        }
//******************* end of init_pop ****************************

// ************************** read_in_pop ****************************
// 5/28/99 create the internal representation for a new population
//
void read_in_pop(individual pop[],int p_size)
        {
        int i, j, line;
        char file_name[256];
        int length=0;

        printf("init_pop\n");
        for (i = 1; i <= p_size;i++)  // index starts at 1
                {
                pop[i].score = 0.0;
                pop[i].wilkies_score = 0.0;
                for (j=0;j<= max_num_tests+1;j++) // update total scores
                        {
                        pop[i].subscores[j] = 0.0;
                        }
                pop[i].born_on = 0;
                sprintf(file_name,"%s_%d.red",pop[1].population_name,i);
                printf("reading %s\n",file_name);
                read_warrior(file_name, &pop[i]);
                length += pop[i].length;
                find_affinities(pop, i, 1);
                }

        for (line = pop[i].length; line < 100; line++) //neatness
                {
                pop[i].cmd[line] = 0;
                pop[i].mod[line] = 0;
                pop[i].Am[line] = 0;
                pop[i].A[line] =  0;
                pop[i].B[line] =  0;
                pop[i].Bm[line] = 0;
                }

        printf("read_in_pop: average length = %f\n",( (float)(length) )/(float)(p_size) );
        fprintf(fp1,"read_in_pop: average length = %f\n",( (float)(length) )/(float)(p_size) );
        }
//******************* end of read_in_pop ****************************

// ************************** write_out_pop ****************************
// 5/28/99 create the internal representation for a new population
//
void write_out_pop(individual pop[],int p_size)
        {
        int i;
        char file_name[256];

        printf("write out pop\n");
        for (i = 1; (i <= p_size)&&(i <= 500);i++)  // index starts at 1
                {
                sprintf(file_name,"%s_%d.red",pop[1].population_name,i);
                printf("writing %s\n",file_name);
                write_warrior(pop[i], file_name);
                }
        }
//******************* end of write_out_pop ****************************

// ************************** mutate ****************************
// 5/30/99
// Every new individual must be processed by this procedure before
//    entering the general population. It performs mutation functions but
//    also checks the individuals for errors and enforces constraints.
//
void mutate(individual pop[],int n)
        {
        int line, L;
        //char file_name[256];
        int tag_A, tag_B, x_A, x_B;
 

        for (line = 0; line < pop[n].length; line++) //for each  line
                {
                                //      check for errors
                if ( (pop[n].cmd[line] < 0) || (pop[n].cmd[line] >= num_cmd_0) ||
                     (pop[n].mod[line] < 0) || (pop[n].mod[line] >= num_mod_list_0) ||
                     (pop[n].Am[line] < 0)  || (pop[n].Am[line] >= num_am_0) ||
                     (pop[n].Bm[line] < 0)  || (pop[n].Bm[line] >= num_am_0) )
                        {
                        printf("MUTATION: ERROR. [%d %d %d %d, %d %d]\n",
                                pop[n].cmd[line],pop[n].mod[line],pop[n].Am[line],pop[n].A[line],
                                pop[n].Bm[line], pop[n].B[line]);
                        printf("In line %d of %d\n",line,pop[n].length);
                        pop[n].length = line;
                        if (pop[n].start_point >= line) { pop[n].start_point = 0;}
                        printf("exit now\n");
                        fflush(fp1);
                        exit(0);
                        }

                standard_coords(&pop[n].A[line]); // clean up references
                standard_coords(&pop[n].B[line]);
                tag_A = 0; tag_B = 0;
                x_A = pop[n].A[line];   // old address
                x_B = pop[n].B[line];   // old address

                if (rand()%100 < P_SWAP) process_line_swap(pop,n,line);
                if (a_insertion())
                        process_insertion(pop,n,line);
                if (a_removal())
                        process_deletion(pop,n,line);

                if (a_mutation())
                        pop[n].cmd[line] = rand()%num_cmd_0;
                if (a_mutation())
                        {
                        pop[n].mod[line] = rand()%num_mod_list_0;
                                // only bias 'MOV' commands to have modifier '.i'
                        if (strcmp(cmd_list_0[pop[n].cmd[line]],cmd_list_0[1])!=0)
                                {pop[n].mod[line] =  rand()%num_mod_list_1;}

                        }
                if (a_mutation())
                        pop[n].Am[line] = rand()%num_am_0;
                if (a_mutation())
                        {
                        tag_A = 1;
                        pop[n].A_AFF[line] = -1;
                        if ( (rand()%100) < P_long_ref)
                                {
                                        // point to a random line in core
                                pop[n].A[line] = rand()%CORESIZE;
                                if (rand()%100 > 50) // pick a line that is pointed to by another line
                                        {
                                        L = rand()%pop[n].length;
                                        pop[n].A[line] = pop[n].B[L] + (L-line);
                                        }
                                }
                        else  //point to a line in the program
                                {pop[n].A[line] = (rand()%(pop[n].length+3)) - (line+3);}
                        }
                if (a_mutation())
                        pop[n].Bm[line] = rand()%num_am_0;
                if (a_mutation())
                        {
                        tag_B = 1;
                        pop[n].B_AFF[line] = -1;
                        if ( (rand()%100) < P_long_ref)
                                {
                                        // point to a random line in core
                                pop[n].B[line] = rand()%CORESIZE;
                                if (rand()%100 > 50) // pick a line that is pointed to by another line
                                        {
                                        L = rand()%pop[n].length;
                                        pop[n].B[line] = pop[n].A[L] + (L-line);
                                        }
                                }
                        else  //point to a line in the program
                                {pop[n].B[line] = (rand()%(pop[n].length+3)) - (line+3);}
                        }
                /******************** turned off for now
                //chance of changing a field along w/ every other field that pointed
                //to the same address (4/21/00)
                if (tag_A || a_mutation())
                        {
                        if (!tag_A) {pop[n].A[line] = rand()%CORESIZE; pop[n].A_AFF[line] = -1;}

                        for (i = 0; i < pop[n].length; i++) //for each  line
                                {
                                if (pop[n].B[i] + i == x_A + line)
                                        {pop[n].B[i] = pop[n].A[line] + (line - i);}
                                if (pop[n].A[i] + i == x_A + line)
                                        {pop[n].A[i] = pop[n].A[line] + (line - i);}
                                }
                        }
                if (tag_B || a_mutation())
                        {
                        if (!tag_B) {pop[n].B[line] = rand()%CORESIZE; pop[n].B_AFF[line] = -1;}
                        for (i = 0; i < pop[n].length; i++) //for each  line
                                {
                                if (pop[n].B[i] + i == x_B + line)
                                        {pop[n].B[i] = pop[n].B[line] + (line - i);}
                                if (pop[n].A[i] + i == x_B + line)
                                        {pop[n].A[i] = pop[n].B[line] + (line - i);}
                                }
                        }
                **************************************/
                if (a_mutation())
                        pop[n].A_AFF[line] = rand()%num_cmd_0;
                if (a_mutation())
                        pop[n].B_AFF[line] = rand()%num_cmd_0;
 

                if (pop[n].length > MAXwSIZE) pop[n].length = MAXwSIZE;

                } // mutation completed
 
 

       // 8/28/00 100% chance of forcing the line length <= max_instructions
        // if (rand()%100 > 50)
            while ( pop[n].length >  max_instructions )
          {
          process_deletion(pop,n,rand()%pop[n].length);
          }

        for (line = 0; line < pop[n].length; line++) //for each  line
                {
                standard_coords(&pop[n].A[line]); // clean up references
                standard_coords(&pop[n].B[line]);
                                //      check for errors
                if ( (pop[n].cmd[line] < 0) || (pop[n].cmd[line] >= num_cmd_0) ||
                     (pop[n].mod[line] < 0) || (pop[n].mod[line] >= num_mod_list_0) ||
                     (pop[n].Am[line] < 0)  || (pop[n].Am[line] >= num_am_0) ||
                     (pop[n].Bm[line] < 0)  || (pop[n].Bm[line] >= num_am_0) )
                        {
                        printf("final check in mutation(). MUTATION: ERROR. [%d %d %d %d, %d %d]\n",
                                pop[n].cmd[line],pop[n].mod[line],pop[n].Am[line],pop[n].A[line],
                                pop[n].Bm[line], pop[n].B[line]);
                        printf("In line %d of %d\n",line,pop[n].length);
                        pop[n].length = line;
                        if (pop[n].start_point >= line) { pop[n].start_point = 0;}
                        printf("exit now\n");
                        fflush(fp1);
                        exit(0);
                        }
                }

        // chance of changing the starting line
        if (a_mutation()) pop[n].start_point = rand()%pop[n].length;

        // make sure the start point is inside the program
        if ((pop[n].start_point >= pop[n].length) || ( pop[n].start_point < 0) )
                {pop[n].start_point = rand()%pop[n].length;}

        if (rand()%100 < - 50) //turn affinities off. 2/08/01
                satisfy_affinities(pop, n, 0);
        else
                find_affinities(pop, n, 0);
        if (FL_BASED) write_warrior(pop[n], "temp.red");

        }
// ******************* end of mutate ****************************
 

// ******************* PROCESS DELETION *************************
// 6/10/99      Delete a new line. Fix any broken edges.
//
void process_deletion(individual pop[],int n, int the_line)
        {
        int line;
 

        //write_warrior(pop[n], "beforeD.red");

        printf("deleting line %d\n",the_line);

        if (pop[n].length < 2) return; //don't bother
        pop[n].length--;
                        // shift the following lines
        for (line = the_line; line <= pop[n].length; line++) //for each  line
                {
                copy_a_line(&pop[n], &pop[n], line+1,line );
                }
        /************************ don't need this 5/30/00 ****/
        if (rand()%100 > 50)
                {
                        // now fix any broken edges on preceeding fields
                for (line = 0; line < the_line; line++)
                        {
                        if (( (pop[n].A[line] + line) > the_line) &&
                                ( (pop[n].A[line] + line) <=  pop[n].length) )
                                pop[n].A[line]--;
                        if (( (pop[n].B[line] + line) > the_line) &&
                                ( (pop[n].B[line] + line) <=  pop[n].length) )
                                pop[n].B[line]--;
                        }
                        // now fix any broken edges on following fields
                for (line = the_line; line < pop[n].length; line++)
                        {
                                {
                                pop[n].A[line]++;
                                if (( (pop[n].A[line] + line) >= the_line) &&
                                        ( (pop[n].A[line] + line) <=  pop[n].length) )
                                        pop[n].A[line]--;
                                }
                                {
                                pop[n].B[line]++;
                                if (( (pop[n].B[line] + line) >= the_line) &&
                                        ( (pop[n].B[line] + line) <=  pop[n].length) )
                                        pop[n].B[line]--;
                                }
                        }
                }
        /******************************************/
        //now fix the starting line so it points to the same place. 9/24/99
        if ((pop[n].start_point >= the_line) && (the_line != 0))
                {
                pop[n].start_point--;
                printf("now starts at %d\n",
pop[n].start_point);
                }
        if (pop[n].start_point < 0)
                {
                printf("start was %d, resetting to start at 0\n",
pop[n].start_point);
                pop[n].start_point = 0;
                }

        if (pop[n].start_point >= pop[n].length)
                {
                printf("start was %d",
pop[n].start_point);
                pop[n].start_point = rand()%pop[n].length;
                printf(", resetting to start at %d\n",
pop[n].start_point);
                }
        //write_warrior(pop[n], "afterD.red");

        }
//******************* end of PROCESS DELETION ****************************
 
 

// ******************* PROCESS LINE SWAP *************************
// 7/01/02      Swap a line with another random line in the warrior.
//
void process_line_swap(individual pop[],int n, int the_line)
        {
        int line;
 

        line = rand()%pop[n].length;
        printf("swapping lines %d and %d\n",the_line,line);
        copy_a_line(&pop[n], &pop[n], the_line, pop[n].length + 1); // temporary location
        copy_a_line(&pop[n], &pop[n], line, the_line);
        copy_a_line(&pop[n], &pop[n],  pop[n].length + 1, line);
        }
//  ******************* end of PROCESS LINE SWAP ****************************

// ******************* PROCESS INSERTION *************************
// 6/10/99      Insert a new line. Fix any broken edges.
//4/21/00       make fields point to places lines in the program or to lines
//              pointed to by other lines in the program.
//
void process_insertion(individual pop[],int n, int the_line)
        {
        int line, L, j;
 

        //write_warrior(pop[n], "before.red");

        printf("Inserting line %d\n",the_line);
        if (pop[n].length < MAXwSIZE) pop[n].length++; //otherwise just lose last line
        else pop[n].length = MAXwSIZE;

                        // shift the following lines
        for (line = pop[n].length; line > the_line; line--) //for each  line
                {
                copy_a_line(&pop[n], &pop[n], line-1, line );
                }
                        // insert the new (random) line
        pop[n].cmd[the_line] = rand()%num_cmd_0;
        pop[n].mod[the_line] = rand()%num_mod_list_0;
        pop[n].Am[the_line] = rand()%num_am_0;
        pop[n].Bm[the_line] = rand()%num_am_0;
        pop[n].A_AFF[the_line] = rand()%num_cmd_0;
        pop[n].B_AFF[the_line] = rand()%num_cmd_0;

        line = the_line; //make sure
       pop[n].A_AFF[line] = -1;
       if ((rand()%100) < P_long_ref)
         {
                                        // point to a random line in core
         pop[n].A[line] = rand()%CORESIZE;
         if (rand()%100 > 3) // pick a line that is pointed to by another line
          {
           L = rand()%pop[n].length;
           pop[n].A[line] = pop[n].B[L] + (L-line);  // MATCH B FIELD
          }
         }
        else  //point to a line in the program
                                {pop[n].A[line] = (rand()%(pop[n].length+3)) - (line+3);}
       pop[n].B_AFF[line] = -1;
       if ( (rand()%100) < P_long_ref)
         {
                                        // point to a random line in core
         pop[n].B[line] = rand()%CORESIZE;
         if (rand()%100 > 3) // pick a line that is pointed to by another line
          {
           L = rand()%pop[n].length;
           pop[n].B[line] = pop[n].A[L] + (L-line);  // MATCH A FIELD
          }
         }
        else  //point to a line in the program
                                {pop[n].B[line] = (rand()%(pop[n].length+3)) - (line+3);}
 

        // OVERWRITE WITH ARCHIVED LINE (Automatic Function Discovery)
        if ((arch_length > 0) && (rand()%100 < P_ARCH_USE))
                {
                j = rand()%arch_length;
                copy_a_line(&arch, &pop[n], j, the_line);
                }

        if (rand()%100 < 98)
                {
                        // now fix any broken edges on preceeding fields
                for (line = 0; line < the_line; line++)
                        {
                        if (( (pop[n].A[line] + line) >= the_line ) &&
                                ( (pop[n].A[line] + line) <=  pop[n].length) && (pop[n].Am[line]!= 0)  )
                        pop[n].A[line]++;
                        if (( (pop[n].B[line] + line) >= the_line) &&
                                ( (pop[n].B[line] + line) <=  pop[n].length)  && (pop[n].Bm[line]!= 0))
                                pop[n].B[line]++;
                        }
                        // now fix any broken edges on following fields
                for (line = the_line+1; line < pop[n].length; line++)
                        {
                        if (pop[n].Am[line]!= 0) pop[n].A[line]--;
                        if (pop[n].Bm[line]!= 0) pop[n].B[line]--;
                        if (( (pop[n].A[line] + line) >= the_line) &&
                                ( (pop[n].A[line] + line) <=  pop[n].length) && (pop[n].Am[line]!= 0) )
                                pop[n].A[line]++; // change it back
                        if (( (pop[n].B[line] + line) <= the_line) &&
                                ( (pop[n].B[line] + line) <=  pop[n].length)  && (pop[n].Bm[line]!= 0))
                                pop[n].B[line]--; // change it back
                }
         }
        if ((pop[n].start_point >= the_line) && (pop[n].start_point < MAXwSIZE))
                {
                pop[n].start_point++;
                printf("now starts at %d\n",pop[n].start_point);
                printf("length = %d\n",pop[n].length);
                }
        if (pop[n].start_point >= pop[n].length)
                {
                printf("start was %d",pop[n].start_point);
                pop[n].start_point = rand()%pop[n].length;
                printf(", resetting to start at %d\n",pop[n].start_point);
                }
        //write_warrior(pop[n], "after.red");

        }
//******************* end of PROCESS INSERTION ****************************

// ******************* FIND AFFINITIES *************************
//      Look at the warrior and fill in the affinity fields based on the code.
//      If an address field points to a MOV, then the affinity for that field is
//      assigned to MOV.
//
void find_affinities(individual pop[],int n, int verbose)
        {
        int x, line;
 

        printf("find affinities\n");
        for (line = 0; line < pop[n].length; line++) //for each  line
                {
                // find affinity for A-field
                x = pop[n].A[line] + line;      // absolute coordinates
                if ( (x >= pop[n].length) || (x < 0) || (pop[n].Am[line] == 0) )
                        {pop[n].A_AFF[line] = -1; } // no affinity
                else
                        {pop[n].A_AFF[line] = pop[n].cmd[ x ];}

                // find affinity for B-field
                x = pop[n].B[line] + line;      // absolute coordinates
                if ( (x >= pop[n].length) || (x < 0) || (pop[n].Bm[line] == 0) )
                        {pop[n].B_AFF[line] = -1;}  // no affinity
                else
                        {pop[n].B_AFF[line] = pop[n].cmd[ x ];}

                if (verbose)
                        {
                        if (line == pop[n].start_point) {printf("START  ");}
                        else                            {printf("       ");}
                        printf("%s%s   %s %5d, %s %5d;\n", cmd_list_0[pop[n].cmd[line]],
                                mod_list_0[ pop[n].mod[line] ],
                                am_list_0[ pop[n].Am[line] ], pop[n].A[line],
                                am_list_0[ pop[n].Bm[line] ], pop[n].B[line]);
                               /***
                        if (pop[n].A_AFF[line] >= 0)
                           {printf("    %s and ",cmd_list_0[ pop[n].A_AFF[line] ]);}
                        else
                           {printf("    %d and ",pop[n].A_AFF[line]);}
                        if (pop[n].B_AFF[line] >= 0)
                           {printf("%s \n",cmd_list_0[ pop[n].B_AFF[line] ]);}
                        else
                           {printf("%d \n",pop[n].B_AFF[line]);}
                           ***/
                        }
                }

        }
//******************* end of FIND AFFINITIES ****************************

// ******************* SATISFY AFFINITIES *************************
//              7/01/00
//              Massage a warrior so that it's affinities are satisfied.
//      This now includes inserting new lines if needed. (doesn't seem useful.7/10/00)
//      if (HARD_AFF == 0) don't add lines.
//
void satisfy_affinities(individual pop[],int n, int verbose)
        {
        int x, old, line, L, satisfied;
        int needed_cmd;

        //write_warrior(pop[n], "before.red");
        printf("SATISFY affinities\n");
        for (line = 0; line < pop[n].length; line++) //for each  line
                {

                /**********************
                printf("\n LINE %d\n",line);
                for (the_line = 0; the_line < pop[n].length; the_line++) //for each line
                        {
                        if (the_line == pop[n].start_point) {printf("START  ");}
                        else                            {printf("       ");}
                        printf("%s%s   %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[the_line]],
                           mod_list_0[ pop[n].mod[the_line] ],
                           am_list_0[ pop[n].Am[the_line] ], pop[n].A[the_line],
                           am_list_0[ pop[n].Bm[the_line] ], pop[n].B[the_line],
                           cmd_list_0[pop[n].A_AFF[the_line]],
                           cmd_list_0[pop[n].B_AFF[the_line]]);
                        if (pop[n].A_AFF[the_line] >= 0)
                           {printf("    %s and ",cmd_list_0[ pop[n].A_AFF[the_line] ]);}
                        else
                           {printf("    %d and ",pop[n].A_AFF[the_line]);}
                        if (pop[n].B_AFF[the_line] >= 0)
                           {printf("%s \n",cmd_list_0[ pop[n].B_AFF[the_line] ]);}
                        else
                           {printf("%d \n",pop[n].B_AFF[the_line]);}
                        }
                printf("\n LINE %d\n",line);
                ***********************************/
 

                // affinity for A-field
                satisfied = 1;
                L = -1;
                old = pop[n].A[line];
                if ( pop[n].A_AFF[line] != -1 )
                        {
                        satisfied = 0;
                        old += line;    // absolute coordinates
                        if ((old < 0) || (old >=  pop[n].length))
                           {old = rand()%pop[n].length;}
                        }
                while (!satisfied)
                        {
                        L++;
 

                        satisfied = 1;          // try bumping it up
                        pop[n].A[line] = old + L;
                        x = pop[n].A[line];     // absolute coordinates
                        if (x >= pop[n].length) {x = pop[n].length - 1;}
                        if (x < 0)              {x = 0;}
                        pop[n].A[line] = x - line;
                        //printf("checking for %d at line %d\n",pop[n].A_AFF[line], x);
                        if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
                                {satisfied = 0;}
                        //else {printf("found a %s at line %d\n",cmd_list_0[pop[n].A_AFF[line]], x);};
                        if ( (!satisfied) && (pop[n].A_AFF[line] != -1) )
                                {
                                satisfied = 1;          // try bumping it down
                                pop[n].A[line] = old - L;
                                x = pop[n].A[line] + line;      // absolute coordinates
                                if (x >= pop[n].length) {x = pop[n].length - 1;}
                                if (x < 0)              {x = 0;}
                                pop[n].A[line] = x - line;
                                //printf("checking for %d at line %d\n",pop[n].A_AFF[line], x);
                                if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
                                        {satisfied = 0;}
                                //else {printf("found a %s at line %d\n",cmd_list_0[pop[n].A_AFF[line]], x);};
                                }
                        if (L >= pop[n].length + 4) // No longer just  give up and restore old value
                                {               // Now it inserts a line to satisfy the affinity
                                satisfied = 1;  // if it has to. This makes the routine somewhat recursive.
                                if ((pop[n].length < (MAXwSIZE/1)) && HARD_AFF)
                                  {
                                  line = -1;
                                  //pop[n].A[line] = old;
                                  pop[n].A[line] = old - line;
                                  needed_cmd = pop[n].A_AFF[line];
                                  process_insertion(pop,n,old);
                                  pop[n].cmd[old] = needed_cmd;
                                  //printf("inserting a %s at line %d\n",cmd_list_0[needed_cmd],old);
                                  //if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[old]])!=0)
                                  //    {printf("WHY NOT!\n");}
                                  //printf("aff:(line %d) inserted line %d\n",line,old);
                                  line = -1;
                                  //write_warrior(pop[n], "after.red");
                                  }
                                }
                        }

                // affinity for B-field
                satisfied = 1;
                L = -1;
                old = pop[n].B[line];
                if (line >=0)
                        {
                        if ( pop[n].B_AFF[line] != -1 )
                                {
                                satisfied = 0;
                                old += line;    // absolute coordinates
                                if ((old < 0) || (old >=  pop[n].length)) {old = rand()%pop[n].length;}
                                }
                        }
                while (!satisfied)
                        {
                        L++;
 

                        satisfied = 1;          // try bumping it up
                        pop[n].B[line] = old + L;
                        x = pop[n].B[line];     // absolute coordinates
                        if (x >= pop[n].length) {x = pop[n].length - 1;}
                        if (x < 0)              {x = 0;}
                        pop[n].B[line] = x - line;
                        //printf("checking for %d at line %d\n",pop[n].B_AFF[line], x);
                        if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
                                {satisfied = 0;}
                        //else {printf("found a %s at line %d\n",cmd_list_0[pop[n].B_AFF[line]], x);};
                        if ( (!satisfied) && (pop[n].B_AFF[line] != -1) )
                                {
                                satisfied = 1;          // try bumping it down
                                pop[n].B[line] = old - L;
                                x = pop[n].B[line] + line;      // absolute coordinates
                                if (x >= pop[n].length) {x = pop[n].length - 1;}
                                if (x < 0)              {x = 0;}
                                pop[n].B[line] = x - line;
                                //printf("checking for %d at line %d\n",pop[n].B_AFF[line], x);
                                if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
                                        {satisfied = 0;}
                                //else {printf("found a %s at line %d\n",cmd_list_0[pop[n].B_AFF[line]], x);};
                                }
                        if (L >= pop[n].length + 4) // No longer just  give up and restore old value
                                {               // Now it inserts a line to satisfy the affinity
                                satisfied = 1;  // if it has to. This makes the routine somewhat recursive.
                                if ((pop[n].length < (MAXwSIZE/1)) && HARD_AFF)
                                  {
                                  line = -1;
                                  //pop[n].B[line] = old;
                                  pop[n].B[line] = old - line;
                                  needed_cmd = pop[n].B_AFF[line];
                                  process_insertion(pop,n,old);
                                  pop[n].cmd[old] = needed_cmd;
                                  //printf("inserting a %s at line %d\n",cmd_list_0[needed_cmd],old);
                                  //if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[old]])!=0)
                                  //    {printf("WHY NOT!\n");}
                                 //printf("aff:(line %d) inserted line %d\n",line,old);
                                  line = -1;
                                  //write_warrior(pop[n], "after.red");
                                  }
                                }
                        }
                standard_coords(&pop[n].A[line]); // clean up references
                standard_coords(&pop[n].B[line]);

                if (verbose)
                        {
                        if (line == pop[n].start_point) {printf("START  ");}
                        else                            {printf("       ");}
                      &bbsp; printf("%s%s   %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[line]],
                                mod_list_0[ pop[n].mod[line] ],
                                am_list_0[ pop[n].Am[line] ], pop[n].A[line],
                                am_list_0[ pop[n].Bm[line] ], pop[n].B[line]);
                        if (pop[n].A_AFF[line] >= 0) {printf("    %s and ",cmd_list_0[ pop[n].A_AFF[line] ]);}
                        else                         {printf("    %d and ",pop[n].A_AFF[line]);}
                        if (pop[n].B_AFF[line] >= 0) {printf("%s \n",cmd_list_0[ pop[n].B_AFF[line] ]);}
                        else                         {printf("%d \n",pop[n].B_AFF[line]);}
                        }
                }

        }
// ******************* end of SATISFY AFFINITIES ****************************

// ******************* COPY A LINE ****************************************
// 6/01/00
//              Copy one line of Redcode from s into d
//
void copy_a_line(individual *s, individual *d, int s_line, int d_line)
        {

        //printf("COPY A LINE\n");
        d->cmd[d_line]   = s->cmd[s_line];
        d->mod[d_line]   = s->mod[s_line];
        d->Am[d_line]    = s->Am[s_line];
        d->A[d_line]     = s->A[s_line];
        d->Bm[d_line]    = s->Bm[s_line];
        d->B[d_line]     = s->B[s_line];
        d->A_AFF[d_line] = s->A_AFF[s_line];
        d->B_AFF[d_line] = s->B_AFF[s_line];

        }
// ******************* FILL ARCHIVE ****************************************
// 5/31/00
//              Read in a warrior and add its lines of code to the global archive. This
//      procedure also keeps track of affinities.
void fill_archive(individual pop[],int n, int verbose)
        {
        int i;
 

        printf("FILL ARCHIVE\n");
        for (i = 0; (i < pop[n].length)&&(arch_length < MAX_ARCH_LENGTH); i++)
                {
                copy_a_line(&pop[n], &arch, i, arch_length);
                arch_length++;

                if (verbose)
                        {
                        printf("%s%s   %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[i]],
                                mod_list_0[ pop[n].mod[i] ],
                                am_list_0[ pop[n].Am[i] ], pop[n].A[i],
                                am_list_0[ pop[n].Bm[i] ], pop[n].B[i]);
                        if (pop[n].A_AFF[i] >= 0) {printf("%s and ",cmd_list_0[ pop[n].A_AFF[i] ]);}
                        else                         {printf("%d and ",pop[n].A_AFF[i]);}
                        if (pop[n].B_AFF[i] >= 0) {printf("%s \n",cmd_list_0[ pop[n].B_AFF[i] ]);}
                        else                         {printf("%d \n",pop[n].B_AFF[i]);}
                        }
                }
        printf("arch_length = %d\n",arch_length);
        }
// ************* end of FILL ARCHIVE ****************************************

// ******************* STANDARD COORDINATES *******************************
// 6/18/99
//              Take a reference, map it to an address between 0 and 7999.
//      Then remap it to lie between -3999 and 4000. This should make the
//      warriors a little more readable and simplify other routines that
//      compare addresses.
//
void standard_coords(int *ref)
        {
        int x;

        x = *ref;
        if (x >= 0) x %= CORESIZE;
        else
                {
                x = - ((-x) % CORESIZE);
                x += CORESIZE;
                }
                        // now 0 <= x <= CORESIZE-1;
        if (x > (CORESIZE/2)) x = - (CORESIZE - x);
        if ((x < -((CORESIZE/2)-1)) || (x > (CORESIZE/2)))
                {printf("STANDARD COORDINATES: error\n"); exit(0);}
        *ref = x;
        }
// ************ end of STANDARD COORDINATES *******************************
 
 

//************************** write_warrior ****************************
// 5/28/99 Write a warrior into a file.
// 6/05/99 Adding code to check for errors.
//
void write_warrior(individual w, char *target_name)
        {
        int line;
        FILE * target_file=0;
 

        remove(target_name); // delete the old file to avoid problems
        if (0==(target_file=fopen(target_name,"w")))
                        {printf("error in write_warrior()\n");exit(0);}
 
 

        dbh_fprint_header(target_file,target_name);

        if (w.length > MAXwSIZE)        w.length = MAXwSIZE;
        for (line = 0; line < w.length; line++) //write 1 line
                {
                                //      check for errors
                if ( (w.cmd[line] < 0) || (w.cmd[line] >= num_cmd_0) ||
                     (w.mod[line] < 0) || (w.mod[line] >= num_mod_list_0) ||
                     (w.Am[line] < 0)  || (w.Am[line] >= num_am_0) ||
                     (w.Bm[line] < 0)  || (w.Bm[line] >= num_am_0) )
                        {
                        printf("write_warrior ERROR. [%d %d %d %d, %d %d]\n",
                                w.cmd[line],w.mod[line],w.Am[line],w.A[line],
                                w.Bm[line], w.B[line]);
                        printf("In line %d of %d\n",line,w.length);
                        //w.length = line;
                        }

                else

                   fprintf(target_file,"%s%s %s%6d, %s%6d\n",
                        cmd_list_0[ w.cmd[line] ],
                        mod_list_0[ w.mod[line] ],
                        am_list_0[ w.Am[line] ],
                        w.A[line],
                        am_list_0[w.Bm[line] ],
                        w.B[line]);

                }
        fprint_end(target_file,w.start_point);

        fclose(target_file);

        }
//******************* end of write_warrior ****************************

// ************************ older_READ WARRIOR *************************
// 6/01/99
// read a warrior from a file.
// 9/20/99 need to fix this so that it reads the number following the end. Done.
//
void older_read_warrior(char * w_name, individual *w)
        {
        FILE * par1_file=0;

        char buffer[256];
        int i=0, j, k;
        char * old_line_ptr;
        char * b_ptr;
        int new_number;
        // A HACK TO ACCOMODATE DIFFERENT STRING MANIPULATION FUNCTIONS BTWN COMPILERS (SIGH)
 char *CMD[]={\
                "DAT","MOV","ADD","SUB",\
                "mul","div","mod","jmp",\
                "JMZ","JMN","DJN","SPL",\
                "SLT","CMP","SEQ","SNE",\
                "NOP"};
         char *MOD[] = {  ".A ",".B ",".AB",".BA",".F ",".X ",".I " };

        b_ptr = b_line; //global. just a handy variable

        if (0==(par1_file=fopen(w_name, "r")))
                {
                printf("read_warrior(): file %s doesn't exist. Making a new warrior.\n",w_name);
                new_warrior(w);
                return;
                }
                        // read in the file
        strcpy(buffer,";");
        while (strstr(buffer,";")!=0)
                fgets (buffer,255,par1_file);  // skip header
        i = 0;
        while ( (i<MAXwSIZE) && (strstr(buffer,"end")==0) )
                {
                strcpy( ParentA[i].l, buffer );
                //printf("%3d: %s",i,ParentA[i].l);
                fgets (buffer,255,par1_file);
                i++;
                }

        // catch the starting line. 9/20/99
        w->start_point = 0;
        if ( strstr(buffer,"end ")!=0 )
                {
                old_line_ptr = buffer;
                old_line_ptr+=3;
                strcpy(b_line,"   ");
                b_ptr = b_line;
                strncpy(b_ptr,old_line_ptr,8); // grab starting line number
                //printf("Reading the starting line number. %s\n",b_line);
                new_number = atoi(b_line);
                //printf("starting at line %d\n",new_number);
                w->start_point = new_number;
                }
        else    {
                printf("Didn't find a starting line number. Default is 0.\n");
                w->start_point = 0;
                }
        w->length = i;
                if (w->length > MAXwSIZE) w->length = MAXwSIZE;
        fclose(par1_file);
        printf("%d lines in %s\n",i,w_name);

        for (j=0;j<i;j++)
                {
                //fprintf(target_file,"%s",ParentA[j].l);
                                // decode one line. Format must be exact.
                old_line_ptr = ParentA[j].l;
                strcpy(b_line,"   ");
                b_ptr = b_line;
                strncpy(b_ptr,old_line_ptr,3); // grab command
                w->cmd[j] = 0;
                //printf("%3d: %s  ",i,b_line);
                for (k=0;k<num_cmd_0;k++)
                        if ( strncmp(b_ptr,cmd_list_0[k],3) == 0 ) {w->cmd[j] = k;}
                         // now CHECK FOR UPPER CASE
                for (k=0;k<17;k++)
                        if ( strncmp(b_ptr,CMD[k],3) == 0 ) {w->cmd[j] = k;}

                old_line_ptr+=3; //skip command

                strncpy(b_ptr,old_line_ptr,3); // grab modifier
                w->mod[j] = 6;
                for (k=0;k<num_mod_list_0;k++)
                        if ( strncmp(b_ptr,mod_list_0[k],3) == 0 ) {w->mod[j] = k;}
                         // now CHECK FOR UPPER CASE
                for (k=0;k<7;k++)
                        if ( strncmp(b_ptr,MOD[k],3) == 0 ) {w->mod[j] = k;}
                old_line_ptr+=3; //skip modifier

                old_line_ptr+=1; //skip space

                strncpy(b_ptr,old_line_ptr,1); // grab address mode
                w->Am[j] = rand()%num_am_0;
                //printf("(%s)  ", b_ptr);
                for (k=0;k<num_am_0;k++)
                        if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Am[j] = k;}
                old_line_ptr+=1; //skip address_mode

                strncpy(b_ptr,old_line_ptr,8); // grab A field
                new_number = atoi(b_line);
                w->A[j] = new_number;
                //printf(" ( %s ) A field was: %d ",b_line, new_number);

                old_line_ptr+=8; //past A field, comma and space

                strncpy(b_ptr,old_line_ptr,1); // grab address mode
                w->Bm[j] = rand()%num_am_0;
                for (k=0;k<num_am_0;k++)
                        if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Bm[j] = k;}
                old_line_ptr+=1; //skip address_mode

                strncpy(b_ptr,old_line_ptr,8); // grab B field
                new_number = atoi(b_line);
                w->B[j] = new_number;
                //printf(" ( %s ) B field was: %d .",b_line, new_number);
                //printf(" %d  %d  \n",w->A[j], w->B[j]);
                }
        //write_warrior(*w,w_name);
        printf("%d lines in %s, starts at %d\n",i,w_name,w->start_point);
        }
// ************ end of older_READ WARRIOR *************************
 

// ************************ READ WARRIOR *************************
// 6/01/99
// read a warrior from a file.
// 9/25/00 more robust
// You can use upper or lower case, you can use ORG START or END to
//    specify the starting line, and the number of spaces between fields
//    isn't so critical anymore.
//
void read_warrior(char * w_name, individual *w)
        {
        FILE * par1_file=0;

        char buffer[256];
        int i=0, k;
        char * old_line_ptr;
        char * b_ptr;
        int new_number=0;
        // A HACK TO ACCOMODATE DIFFERENT STRING MANIPULATION FUNCTIONS BTWN COMPILERS (SIGH)
 char *CMD[]={\
                "DAT","MOV","ADD","SUB",\
                "MUL","DIV","MOD","JMP",\
                "JMZ","JMN","DJN","SPL",\
                "SLT","CMP","SEQ","SNE",\
                "NOP"};
         char *MOD[] = {  ".A ",".B ",".AB",".BA",".F ",".X ",".I " };
         int verB = 0; // verbose mode for debugging
         int is_obj = 0; // is this a line of object code?

        printf("Reading %s  ",w_name);
        b_ptr = b_line; //global. just a handy variable
        old_line_ptr = buffer;
        if (0==(par1_file=fopen(w_name, "r")))
                {
                printf("read_warrior(): file %s doesn't exist. Making a new warrior.\n",w_name);
                new_warrior(w);
                return;
                }
                        // read in the file
        strcpy(buffer,";");
        w->start_point = 0;
        i = 0;
        while ( (i<MAXwSIZE) && (strstr(buffer,"end")==0) &&(!feof(par1_file)) )// read in the file
                {
                //strcpy( ParentA[i].l, buffer );
                //printf("%3d: %s",i,ParentA[i].l);
                fgets (buffer,255,par1_file);
                if (verB) printf("%3d: %s",i,buffer);
                // for now I will ignore completely any line with a ";" in it

                if ( strstr(buffer,"name") != 0 )
                 {
                 printf("%s",buffer);
                 }
                if ( strstr(buffer,"Program") != 0 )
                 {
                 printf("%s",buffer);
                 }
                if ( strstr(buffer,";") == 0 )
                 {
                 is_obj = 0;
                 if ( strstr(buffer,"START") != 0 )
                  {
                  w->start_point = i;
                  if (verB) printf("START = %d\n",i);
                  }
                 if ( strstr(buffer,"start") != 0 )
                  {
                  w->start_point = i;
                  if (verB) printf("start = %d\n",i);
                  }
          if ( strstr(buffer,"end ")!=0 )
                  {
                  old_line_ptr = buffer;
                  b_ptr=strstr(buffer,"end");
                  if (b_ptr!=0)
                     {
                     b_ptr+= 3;
                            new_number=atoi(b_ptr);
                            }
                  // grab starting line number
                  w->start_point = new_number;
                  }
          if ( strstr(buffer,"END ")!=0 )
                  {
                  old_line_ptr = buffer;
                  b_ptr=strstr(buffer,"END");
                  if (b_ptr!=0)
                     {
                     b_ptr+= 3;
                            new_number=atoi(b_ptr);
                            }
                  // grab starting line number
                  w->start_point = new_number;
                  }
                // now check to see if the line holds object code
                  for (k=0;k<num_cmd_0;k++) // check every command type
                         if ( strstr(buffer,cmd_list_0[k]) != 0 )
                          {
                          is_obj = 1;
                          w->cmd[i] = k;
                          if (verB) printf("command was %s\n",cmd_list_0[k]);
                          old_line_ptr=strstr(buffer,cmd_list_0[k]);
                          old_line_ptr+=3; //skip past command
                          }
                         // now CHECK FOR UPPER CASE
                  for (k=0;k<17;k++)
                         if ( strstr(buffer,CMD[k]) != 0 )
                          {
                          is_obj = 1;
                          w->cmd[i] = k;
                          if (verB) printf("command was %s\n",cmd_list_0[k]);
                          old_line_ptr=strstr(buffer,CMD[k]);
                          old_line_ptr+=3; //skip past command
                          }
                        if ((!is_obj) && (verB)) printf("Line is not object code\n");

                        if (is_obj)
                         {
                  strncpy(b_ptr,old_line_ptr,3); // grab modifier
                  w->mod[i] = 6;
                  for (k=0;k<num_mod_list_0;k++)
                          if ( strncmp(b_ptr,mod_list_0[k],3) == 0 )
                           {w->mod[i] = k;}
                         // now CHECK FOR UPPER CASE
                  for (k=0;k<7;k++)
                          if ( strncmp(b_ptr,MOD[k],3) == 0 )
                           {w->mod[i] = k;}
                  old_line_ptr+=3; //skip modifier

                  old_line_ptr+=1; //skip space

                  strncpy(b_ptr,old_line_ptr,1); // grab address mode
                  w->Am[i] = rand()%num_am_0;
                  for (k=0;k<num_am_0;k++)
                          if ( strncmp(b_ptr,am_list_0[k],1) == 0 )
                           {w->Am[i] = k;}
                  old_line_ptr+=1; //skip past address_mode

                  new_number = atoi(old_line_ptr);
                  w->A[i] = new_number;
                  if (verB) printf(" ( %s ) A field was: %d ",b_line, new_number);

                  if (strstr(buffer,",") != 0)
                   {
                   if (verB) printf("found the   ,  \n");
                   old_line_ptr=strstr(buffer,","); // skip to the ","
                   }
                  else {if (verB) printf("NEVER found the   ,  \n");}

                  old_line_ptr+=2; //skip space

                  strncpy(b_ptr,old_line_ptr,1); // grab address mode
                  w->Bm[i] = rand()%num_am_0;
                  for (k=0;k<num_am_0;k++)
                         if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Bm[i] = k;}
                   old_line_ptr+=1; //skip address_mode

                  new_number = atoi(old_line_ptr);
                   w->B[i] = new_number;

                  if (verB)  printf("A== %d, b==  %d  \n",w->A[i], w->B[i]);
                         i++;
                         }
                 }
                }
        w->length = i;
        if (w->length > MAXwSIZE) w->length = MAXwSIZE;
        fclose(par1_file);
        if (w->start_point > w->length) w->start_point = 0;

        //write_warrior(*w,w_name);
        printf("%d lines in %s, starts at %d\n",i,w_name,w->start_point);
        }
// ************ end of READ WARRIOR *************************
 

// *********************** next generation **********************
//              11/04/98
//      Uses tournament selection and steady state GA.
//      Generates a new individual and replaces the weakest individual. Does this
//      n times (n = population_size). Uses crossover.
//
// 8/24/00 Checks children for functional uniqueness. All battles used the
// same sequence of starting points. If the child has subscores identical to
//  those of another pop member, the child is discarded (if CROWDING==1).
// if (FREEZE != 0) the starting sequence changes every generation.
//
// 10/26/00. if (PARSIMONY==1), and a child is functionally identical to a
// population member (they have identical subscores), then the shorter of the
// 2 of them survives.
void nextgen(int p_size,char * population_name,individual pop[],
                int generation, individual hill[])
        {
        int source_number;
        int target_number;
        char source_name[256];
        char target_name[256];
        int par1_number;
        int par2_number;
        char par1_name[256];
        char par2_name[256];
        int num_resurrected = 0,num_born = 0, skipped=0, killed=0;

        // generate children; iterate n times
        printf("nextgen1\n");
        share( pop, 0);
        printf("nextgen2\n");
        for (source_number=1;source_number<=p_size;source_number++)
                {
                target_number= weakest(pop);
                sprintf(target_name,"%s_%d.red",population_name,target_number);

                if (ROULETTE)
                        {
                        par1_number = Roulette(pop);
                        par2_number = Roulette(pop);
                        while (par1_number == target_number)
                           {par1_number = Roulette(pop); printf("try again: %d is par1\n",par1_number);}
                        while (par2_number == target_number)
                           {par2_number = Roulette(pop); printf("try again: %d is par2\n",par2_number);}
                        }
                  else
                        {
                        par1_number = tournament(pop);
                        par2_number = tournament(pop);
                        while (par1_number == target_number)
                           {par1_number = tournament(pop); printf("try again: %d is par1\n",par1_number);}
                        while (par2_number == target_number)
                           {par2_number = tournament(pop); printf("try again: %d is par2\n",par2_number);}
                        }

                  sprintf(source_name,"%s_%d.red",population_name,par1_number);

                  sprintf(par1_name,"%s_%d.red",population_name,par1_number);
                  sprintf(par2_name,"%s_%d.red",population_name,par2_number);
                  if (Verbose) fprintf(fp1,"%d %d %d \n",par1_number,par2_number,target_number);

                 if ( a_resurrection() && (generation > GEN_GAP) )    // IF A RESURRECTION
                    {                    // reintroduce an old hill member to the population
                    printf("RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
                    if (Verbose)
                         fprintf(fp1,"RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
                    par1_number = rand()%(generation-1);
                    par1_number = 1 + par1_number % RINGSIZE;
                    sprintf(source_name,"%s_%d.red",pop[target_number].Valhalla_name,par1_number);
                    read_warrior(source_name,&pop[target_number]);
                    find_affinities(pop, target_number, 1);
        // Throw out non-unique new individuals. (Don't count them against the number of new individuals.)
                   if ( unique(pop, target_number) )
                        {
                        if (rand()%2 == 0) mutate(pop, target_number); // mutate resurrected warrior
                   //   write_warrior(pop[target_number], target_name);
                        pop[target_number].born_on = generation; // mark birth
                        hill_objective(target_name,pop,target_number,hill);
                        if ( functionally_unique(pop, target_number) )
                         {
                         share( pop, 0);
                         if (target_number != weakest(pop)) {num_resurrected++;}
                         }
                        else  //  kill it BUT DON'T try again
                         {
                         killed++;
                         if (CROWDING) pop[target_number].score = 0.0; // kill it
                         else {if (target_number != weakest(pop)) {num_resurrected++;}}
                         }
                        }
                    else { skipped++; source_number--; } // if you get a duplicate, just try again
                    par1_number = par2_number; // avoid overflow later
                    }// end if a resurrection
                  else
                    {
                    if ( rand()%100 < P_CR ) // chance of crossover
                        {
                        if (rand()%100 > 90)
                                {two_point_crossover(pop, par1_number, par2_number, target_number);}
                        else
                                {
                                if (rand()%100 > 20)
                                        {point_crossover(pop, par1_number, par2_number, target_number);}
                                else
                                        {uniform_crossover(pop, par1_number, par2_number, target_number);}
                                }
                        }
                    else                                        // just mutate par1
                        {
                        memcpy(&pop[target_number],&pop[par1_number],sizeof(individual));
                        pop[target_number].score = 0.0;
                        }
                 //   }
                 mutate(pop, target_number); // mutate offspring
                        // Throw out non-unique new individuals.
                        //(Don't count them against the number of new individuals.)
                        if ( unique(pop, target_number) )
                                {
                                //write_warrior(pop[target_number], target_name);
                                        pop[target_number].born_on = generation; // mark birth
                                hill_objective(target_name,pop,target_number,hill);

                         if ( functionally_unique(pop, target_number) )
                          {
                          share( pop, 0);
                          if (target_number != weakest(pop)) {num_born++;}
                          }
                         else  //  kill it BUT DON'T try again
                          {
                          killed++;
                                 if (CROWDING) pop[target_number].score = 0.0; // kill it
                                 else {if (target_number != weakest(pop)) {num_born++;}}
                          }
                                }
                        else { skipped++; source_number--; } // if you get a duplicate, just try again
                }
                printf("parents %d and %d. (scores %f and %f)\n",
                                par1_number,par2_number,pop[par1_number].score,
                                pop[par2_number].score);
                printf("%d scores %f\n",target_number,pop[target_number].score);

                printf("SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
                printf("SUCCESSFUL BIRTHS %d .Total %d\n",num_born,source_number);
        printf("%d were not literally unique, %d others were not functionally unique\n", skipped, killed);
                }//for
        fprintf(fp1,"SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
        printf("%d not functionally unique\n",killed);
        fprintf(fp1,"%d not functionally unique\n",killed);
        printf("\n                      SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
                                num_born,source_number, skipped);
        fprintf(fp1,"\n                 SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
                                num_born,source_number, skipped);
        if (CROWDING) { printf("using crowding\n"); fprintf(fp1,"using crowding\n");}
        else          { printf("not using crowding\n"); fprintf(fp1,"not using crowding\n");}
        }
// ******** end of next generation *************************

// *********************** standard (STD) next generation **********************
//              7/24/00
//      Uses tournament selection and complete replacement GA.
//      melee fratricide and affinities may make this practical - we'll see ...
//      Uses crossover.
//
void nextgen_STD(int p_size,char * population_name,individual pop[],
                int generation, individual hill[])
        {
        int source_number;
        int target_number=0;
        char source_name[256];
        char target_name[256];
        int par1_number;
        int par2_number;
        char par1_name[256];
        char par2_name[256];
        int i, num_resurrected = 0,num_born = 0, skipped=0, num_children = 10;
        //individual *nxtpop;

        // generate a new generation in nxtpop, then copy it back into pop
        /***************
        printf("starting Malloc for nxtpop\n");
        if((nxtpop = ( individual *)malloc( (p_size+MELEE_BUFFER) * sizeof( individual ) )) == NULL )
                printf("Malloc Error from nxtpop\n");
        else    printf("Malloc okay for nxtpop\n");
        fix_names(nxtpop,  "x1", "h1", "v1", p_size+1);  // temporary population
        printf("fix_names finished for nxtpop\n");
        ******************/
        for (source_number=1;source_number<=p_size;source_number++)
                {
                target_number = source_number;
                sprintf(target_name,"%s_%d.red",population_name,target_number);
                if (ROULETTE)
                        {
                        par1_number = Roulette(pop);
                        par2_number = Roulette(pop);
                        while (par1_number == target_number)
                           {par1_number = Roulette(pop); printf("try again: %d is par1\n",par1_number);}
                        while (par2_number == target_number)
                           {par2_number = Roulette(pop); printf("try again: %d is par2\n",par2_number);}
                        }
                  else
                        {
                        par1_number = tournament(pop);
                        par2_number = tournament(pop);
                        while (par1_number == target_number)
                           {
                           par1_number = tournament(pop);
                           printf("try again: %d is par1\n",par1_number);
                           }
                        while (par2_number == target_number)
                           {
                           par2_number = tournament(pop);
                           printf("try again: %d is par2\n",par2_number);
                           }
                        }
                  sprintf(source_name,"%s_%d.red",population_name,par1_number);

                  sprintf(par1_name,"%s_%d.red",population_name,par1_number);
                  sprintf(par2_name,"%s_%d.red",population_name,par2_number);
                  if (Verbose) fprintf(fp1,"%d %d %d \n",par1_number,par2_number,target_number);
 

                    // 6/13/00 Breed 10 children, then run them on a melee hill together.
                    // Only the strongest survives to be tested against the hill.

                    for (i = 1; i <= num_children; i++)
                        {
                        if (rand()%100 > 95)
                                {two_point_crossover(pop, par1_number, par2_number, p_size+i);}
                        else
                                {
                                if (rand()%100 < P_CR)
                                  {
                                  if (rand()%100 > 50)
                                        {point_crossover(pop, par1_number, par2_number, p_size+i);}
                                  else
                                        {uniform_crossover(pop, par1_number, par2_number, p_size+i);}
                                  }
                                }
                        mutate(pop, p_size+i); // mutate offspring
                        sprintf(source_name,"%s_%d.red",pop[1].population_name,p_size+i);
                        //write_warrior(pop[p_size+i], source_name);
                        }
                printf("parents %d and %d. (scores %f and %f)\n",
                                par1_number,par2_number,pop[par1_number].score,
                                pop[par2_number].score);
                printf("%d scores %f\n",target_number,pop[target_number].score);

                printf("SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
                printf("SUCCESSFUL BIRTHS %d .Total %d\n",num_born,source_number+skipped);

                    if ( melee_fraticide(p_size,pop[1].population_name, pop,
                                        p_size+1, p_size+num_children, 1) )
                                {num_born++;}
                    else        {source_number--;skipped++;}

                    read_warrior("temp.red",&pop[p_size+1]); // read in melee winner
                    write_warrior(pop[p_size+1], target_name); // write child into a file
 

                }//for
        fprintf(fp1,"SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
        printf("\n                      SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
                                num_born,source_number, skipped);
        fprintf(fp1,"\n                 SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
                                num_born,source_number, skipped);
 

                                // now copy them back
        for (source_number=1;source_number<=p_size;source_number++)
                {
                 if ( a_resurrection() && (generation > GEN_GAP) )    // IF A RESURRECTION
                    {                    // reintroduce an old hill member to the population
                    printf("RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
                    if (Verbose)
                         fprintf(fp1,"RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
                    par1_number = rand()%(generation-1);
                    par1_number = 1 + par1_number % RINGSIZE;
                    sprintf(source_name,"%s_%d.red",pop[target_number].Valhalla_name,par1_number);
                    read_warrior(source_name,&pop[target_number]);
                    find_affinities(pop, target_number, 1);
                    if (rand()%2 == 0) mutate(pop, target_number); // mutate resurrected warrior
                    pop[target_number].born_on = par1_number; // mark birth
                    num_resurrected++;
                    }                           // end if a resurrection
                else
                    {           // read new individual in from file
                    sprintf(source_name,"%s_%d.red",pop[1].population_name,source_number);
                    read_warrior(source_name,&pop[source_number]);
                    }
                }
        //free(nxtpop);
        }
// ******** end of next standard generation *************************

//********************* UNIQUE ************************************
//      1/15/00
// Compare the indiviual new_ind with the rest of the population.
// return a 1 if n is unique and a 0 otherwise.
//
int unique(individual pop[], int new_ind)
        {
        int i, line;
        int diff=1;
 

                /*index through whole population*/
        for (i=1;i<=population_size;i++)
                {
                if (new_ind != i)
                  {
                  diff = 0;
                  if ( (pop[new_ind].length != pop[i].length) ||
                       (pop[new_ind].start_point != pop[i].start_point) )
                        {diff = 1;}
                 for (line = 0;(line<pop[i].length)&&(!diff); line++) //check 1 line
                        {
                        if (pop[new_ind].cmd[line] != pop[i].cmd[line]) diff = 1;
                        if (pop[new_ind].mod[line] != pop[i].mod[line]) diff = 1;
                        if (pop[new_ind].Am[line]  != pop[i].Am[line])  diff = 1;
                        if (pop[new_ind].A[line]   != pop[i].A[line])   diff = 1;
                        if (pop[new_ind].B[line]   != pop[i].B[line])   diff = 1;
                        if (pop[new_ind].Bm[line]  != pop[i].Bm[line])  diff = 1;
                        }
 

                  if (! diff)
                        {
printf("new # %d same as # %d\n",new_ind, i );
                        if (Verbose) {fprintf(fp1,"new # %d same as # %d\n",new_ind, i );}
                        return(0);
                        }
                  }
                }//end for loop

if (Verbose) printf("new # %d is unique\n",new_ind);

        if (Verbose) fprintf(fp1,"new # %d is unique\n",new_ind);
        //fflush(fp1);
        return(1);
        }
//*************** end of UNIQUE ************************************

//********************* FUNCTIONALLY UNIQUE ************************************
//      8/24/00
// Compare the individual new_ind with the rest of the population.
// return a 1 if n is unique and a 0 otherwise.
// The measure of comparison is the subscores. The idea is that if all of
// the subscores are identical, then the 2 warriors may not be different in any
// meaningful way. This test only makes sense if the scores for the new and old
// warriors have been obtained using the same sequence of starting points.
//
// 10/26/00. if (PARSIMONY==1), and a child is functionally identical to a
// population member (they have identical subscores), then the shorter of the
// 2 of them survives.
//
int functionally_unique(individual pop[], int new_ind)
        {
        int i, index;
        int diff=1;
 

                /*index through whole population*/
        for (i=1;i<=population_size;i++)
                {
                if (new_ind != i)
                  {
                  diff = 0;
                  if ( pop[new_ind].score != pop[i].score )
                        {diff = 1;}
         for (index=1;index< num_tests+1;index++) // for each subscore
                 {
                        if (pop[new_ind].subscores[index] != pop[i].subscores[index]) diff = 1;
                        }
 

                  if (! diff)
                        {
   printf("new # %d is functionally the same as # %d (%d,%d)\n",
    new_ind, i, pop[new_ind].length, pop[i].length );
                        if (Verbose)
                            {fprintf(fp1,"new # %d is functionally the same as # %d\n",new_ind, i );}
                        if ( PARSIMONY && (pop[new_ind].length < pop[i].length) )
                         {
           pop[i].score = 0;
    printf("new # %d is SHORTER THAN # %d (%d,%d)\n",
     new_ind, i, pop[new_ind].length, pop[i].length );
    if (Verbose) fprintf(fp1,"new # %d is SHORTER THAN # %d (%d,%d)\n",
     new_ind, i, pop[new_ind].length, pop[i].length );
                         return(1);
                         }
                        else return(0);
                        }
                  }
                }//end for loop

 if (Verbose) printf("new # %d is functionally unique\n",new_ind);

        if (Verbose) fprintf(fp1,"new # %d is functionally unique\n",new_ind);
        //fflush(fp1);
        return(1);
        }
//*************** end of FUNCTIONALLY UNIQUE ************************************

// ******** POINT CROSSOVER ***************************************
//              5/28/99
//              Using internal representation of the individuals.
//
//              Added rubber banding: backwards references are now protected when
//      crosspoints don't line up. Forward references are not presently protected.
//
// The child must be different from the parents
//
//      4/13/00.  Crossover occurs between any 2 fields, not just between lines.
//
void point_crossover(individual pop[], int par1, int par2, int child)
        {
        int cross_pt1, cross_pt2, i, line_ct=0,n;
        //int new_end=MAXwSIZE;
        //int shortpar, longpar;

        n = population_size+1; // a handy unused slot

        printf("POINT crossover:parents %d, %d  produce %d\n",par1, par2, child);
 

        cross_pt1 = 1 + (rand()%(pop[par1].length));
        cross_pt2 = 0 + (rand()%(pop[par2].length));
        if ((rand()%100) > 10)
                {
                cross_pt1 = 1 + (rand()%(pop[par1].length));
                cross_pt2 = cross_pt1;
                }
        printf("crosspoints = %d, %d\n",cross_pt1,cross_pt2);
 

          for (i = 0; i < cross_pt1; i++)  // first half from par1
               {
                copy_a_line(&pop[par1], &pop[child], i, i);
                line_ct++;
                }
        printf("point crossover: 1st half. %d lines copied\n",line_ct);
        // --------------------------- add rubberbanding. 6/20/99
         for (i = cross_pt2; (i < pop[par2].length)&&(line_ct < MAXwSIZE); i++)
                {  // copy par2 into pop[n]
                copy_a_line(&pop[par2], &pop[child], i, line_ct);
                line_ct++;
                }
        pop[child].length = line_ct;
        printf("point crossover: 2nd half. %d lines copied\n",line_ct);

                // pick the starting line ----------------
        pop[child].start_point = pop[par1].start_point;
        if (pop[child].start_point >= pop[child].length)
                pop[child].start_point = pop[par2].start_point;
        if (pop[child].start_point >= pop[child].length)
                pop[child].start_point = rand()%pop[child].length;

        //write_warrior(pop[child], "test.red");
        }
// ******** end of POINT CROSSOVER *************************

// ******** 2 POINT CROSSOVER ***************************************
//              6/07/00
//              Using internal representation of the individuals.
//
// The child must be different from the parents
//
//      4/13/00.  Crossover occurs between any 2 fields, not just between lines.
//
void two_point_crossover(individual pop[], int par1, int par2, int child)
        {
        int cross_pt1, cross_pt2, i,n;
        //int new_end=MAXwSIZE, offset=0;
        //int shortpar, longpar, L;

        n = population_size+1; // a handy unused slot

        printf("2 POINT crossover:parents %d, %d  produce %d\n",par1, par2, child);
 

        cross_pt1 = 0 + (rand()%(pop[par1].length));
        if (pop[par1].length - cross_pt1 == 0)  cross_pt1 += -1;

        cross_pt2 = cross_pt1 + (rand()%(pop[par1].length - cross_pt1));
        printf("crosspoints for par1 = %d, %d\n",cross_pt1,cross_pt2);
                // copy par1 into child
        memcpy(&pop[child],&pop[par1],sizeof(individual));

        for (i = cross_pt1; i < cross_pt2; i++)  // make space
                {
                process_deletion(pop,child,i);
                }

        cross_pt1 = 0 + (rand()%(pop[par2].length));
        if (pop[par2].length - cross_pt1 == 0)  cross_pt1 += -1;

        cross_pt2 = cross_pt1 + (rand()%(pop[par2].length - cross_pt1));
        printf("crosspoints for par2 = %d, %d\n",cross_pt1,cross_pt2);

        // copy from par2
        for (i = cross_pt1; (i < cross_pt2)&&(pop[child].length < MAXwSIZE); i++)
                {
                process_insertion(pop,child,i);
                copy_a_line(&pop[par2], &pop[child], i, i);
                }

        printf("2 point crossover: par1 length = %d, par2 = %d, child = %d\n",
                pop[par1].length, pop[par2].length,pop[child].length);
        if (pop[child].start_point >= pop[child].length)
                pop[child].start_point = rand()%pop[child].length;
        //write_warrior(pop[child], "test.red");
        }
// ******** end of 2 POINT CROSSOVER *************************
 

// ******** UNIFORM CROSSOVER ***************************************
//              5/28/99
//              Using internal representation of the individuals.
//      Perform uniform crossover: Every line of the child has an even
//      probability of coming from par1 or par2.
//
// The child must be different from the parents
//
void uniform_crossover(individual pop[], int par1, int par2, int child)
        {
        int i, j, line_ct=0;
        int  offset=0;
        int diff, scramble;
        int shortpar, longpar, L;

        printf("uniform crossover:parents %d, %d  produce %d\n",par1, par2, child);

        if (pop[par1].length >=  pop[par2].length) {longpar = par1; shortpar = par2;}
        else              {longpar = par2; shortpar = par1;}
        diff = abs(pop[par1].length - pop[par2].length);
        L = rand()%(diff+1);
        pop[child].length = pop[shortpar].length;
        pop[child].length += L;
 

        if (pop[child].length < 1) pop[child].length = max_instructions;
        if (pop[child].length > MAXwSIZE) pop[child].length = MAXwSIZE;
 
 

        printf("par1 length = %d, par2 = %d, child = %d\n",
                pop[par1].length, pop[par2].length,pop[child].length);
        //5/20/99 chance of truncation, offset
        scramble = rand()%2;
        if ((rand()%100) < 1) offset = 1;
        else                   offset = 0;
          for (i = 0; i < pop[shortpar].length; i++)
                {
                 j = i;
                   if (rand()%2)
                        {
                        copy_a_line(&pop[par1], &pop[child], i, i);
                        }
                   else
                        {
                        copy_a_line(&pop[par2], &pop[child], j, i);
                        }

                line_ct++;
                }

          for (i = line_ct; i < pop[child].length; i++)
                {
                if (i < pop[longpar].length) // take from parent
                        {
                        copy_a_line(&pop[longpar], &pop[child], i, i);
                        }
                else                    // random old line
                        {
                        copy_a_line(&pop[longpar], &pop[child], rand()%pop[longpar].length, i);
                        }
                line_ct++;
                }

        printf("point crossover: 2nd half. %d lines copied\n",line_ct);

                // pick the starting line ----------------
        pop[child].start_point = pop[par1].start_point;
        if (pop[child].start_point >= pop[child].length)
                pop[child].start_point = pop[par2].start_point;
        if (pop[child].start_point >= pop[child].length)
                pop[child].start_point = rand()%pop[child].length;
 

        }
// ******** end of UNIFORM CROSSOVER *************************

// ****************** pmars **************************
// 7/28/00  Procedure from Martin Ankerl.
// It calls the pmars simulator, exhaust, written by Joonas Pihlaja
//
void pmars(int *w1_score, int *w2_score, int rounds,
  unsigned long cycles, unsigned long distance, int type)
 {
 int i=0, j=0, pos=0;
 int result=0;
 int start1=0;
 int start2=0;
 int n_cycles; // keep track of how many cycles
 float w1_time_score = 0.0;  // factor for the length of the battles
 float w2_time_score = 0.0;
 float r, p;
 

 *w1_score=0;
 *w2_score=0;
 //printf("SO FAR. start at (%d  %d)\n", w1.start, w2.start);
 if (0) printf("avoid warning msg from compiler (%ld  %d)\n", distance,type);
 for (i=0; i<rounds/2; i++)
 {
  pos = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
  if (i < POS_SEQ_LENGTH) pos = FixedPositionSeq[i];
  //printf(". pos = %d \n",pos);
  for (j=0; j<2; j++)
  {
   /* coreclear */
   memset( core, 0, sizeof(insn_t) * CORESIZE );

   start1=0;
   start2=0;
   n_cycles = (int) cycles;
   if (j)
    {
    start1 = pos;
    memcpy(core + start1, w1.code, sizeof(insn_t) * w1.len);
    memcpy(core + start2, w2.code, sizeof(insn_t) * w2.len);

    result = sim( 2, start1 + w1.start, start2 + w2.start, n_cycles, NULL );
    r = (n_cycles)/(float)(2*cycles); // reward winning quickly
    p = (2*cycles - n_cycles)/(float)(2*cycles);       //reward holding on longer
    switch(result)
     {
     case 0: *w1_score += 3; w1_time_score += r-1; w2_time_score += p; break;
     case 1: *w2_score += 3; w2_time_score += r-1; w1_time_score += p; break;
     case 2: *w1_score += 1; *w2_score += 1;break;
     case -1: printf("simulator panic attack!"); exit(1); break;
     }
    }
   else
    {
    start2 = pos;
    memcpy(core + start1, w1.code, sizeof(insn_t) * w1.len);
    memcpy(core + start2, w2.code, sizeof(insn_t) * w2.len);

    result = sim( 2, start2 + w2.start, start1 + w1.start, n_cycles, NULL );
    r = (n_cycles)/(float)(2*cycles); // reward winning quickly
    p = (2*cycles - n_cycles)/(float)(2*cycles);       //reward holding on longer
    switch(result)
     {
     case 0: *w2_score += 3; w2_time_score += r-1; w1_time_score += p; break;
     case 1: *w1_score += 3; w1_time_score += r-1; w2_time_score += p; break;
     case 2: *w1_score += 1; *w2_score += 1;break;
     case -1: printf("simulator panic attack!"); exit(1); break;
     }
    }
 //printf("SO FAR. pos = %d (%d  %d), result = %d\n",pos, w1.start, w2.start, result);
   /* one-on-one two warriors:
      0: warrior 1 won
      1: warrior 2 won
      2: tie
     -1: simulator panic attack -- something's gone wrong */
  }/*for(0 --> 1)*/
 }/*for (0 --> rounds)*/
 /************* this code uses the number of cycles in the scoring **********
 it does not work with the standard exhaust code
 if (type==1)
  {
  printf("skewing the score. was %d and %d. ",*w1_score,*w2_score);
  *w1_score *= cycles;
  *w2_score *= cycles;
  *w1_score += (int)(cycles * w1_time_score);
  *w2_score += (int)(cycles * w2_time_score);
  printf(" now it's %d and %d. ",*w1_score,*w2_score);
  }
 *****************************/

 }
// ************** end of pmars() *****************************************

// ****************** pmars **************************
// 7/28/00  Procedure from Martin Ankerl.
// It calls the pmars simulator, exhaust, written by Joonas Pihlaja
//
void pmars_rnd(int *w1_score, int *w2_score, int rounds,
  unsigned long cycles, unsigned long distance, int type)
 {
 int i=0, j=0, pos=0;
 int result=0;
 int start1=0;
 int start2=0;
 int n_cycles; // keep track of how many cycles
 float w1_time_score = 0.0;  // factor for the length of the battles
 float w2_time_score = 0.0;
 float r, p;
 

 *w1_score=0;
 *w2_score=0;
 //printf("SO FAR. start at (%d  %d)\n", w1.start, w2.start);
 if (0) printf("avoid warning msg from compiler (%ld  %d)\n", distance,type);
 for (i=0; i<rounds/2; i++)
 {
  pos = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
  for (j=0; j<2; j++)
  {
   /* coreclear */
   memset( core, 0, sizeof(insn_t) * CORESIZE );

   start1=0;
   start2=0;
   n_cycles = (int) cycles;
   if (j)
    {
    start1 = pos;
    memcpy(core + start1, w1.code, sizeof(insn_t) * w1.len);
    memcpy(core + start2, w2.code, sizeof(insn_t) * w2.len);

    result = sim( 2, start1 + w1.start, start2 + w2.start, n_cycles, NULL );
    r = (n_cycles)/(float)(2*cycles); // reward winning quickly
    p = (2*cycles - n_cycles)/(float)(2*cycles);       //reward holding on longer
    switch(result)
     {
     case 0: *w1_score += 3; w1_time_score += r-1; w2_time_score += p; break;
     case 1: *w2_score += 3; w2_time_score += r-1; w1_time_score += p; break;
     case 2: *w1_score += 1; *w2_score += 1;break;
     case -1: printf("simulator panic attack!"); exit(1); break;
     }
    }
   else
    {
    start2 = pos;
    memcpy(core + start1, w1.code, sizeof(insn_t) * w1.len);
    memcpy(core + start2, w2.code, sizeof(insn_t) * w2.len);

    result = sim( 2, start2 + w2.start, start1 + w1.start, n_cycles, NULL );
    r = (n_cycles)/(float)(2*cycles); // reward winning quickly
    p = (2*cycles - n_cycles)/(float)(2*cycles);       //reward holding on longer
    switch(result)
     {
     case 0: *w2_score += 3; w2_time_score += r-1; w1_time_score += p; break;
     case 1: *w1_score += 3; w1_time_score += r-1; w2_time_score += p; break;
     case 2: *w1_score += 1; *w2_score += 1;break;
     case -1: printf("simulator panic attack!"); exit(1); break;
     }
    }
 //printf("SO FAR. pos = %d (%d  %d), result = %d\n",pos, w1.start, w2.start, result);
   /* one-on-one two warriors:
      0: warrior 1 won
      1: warrior 2 won
      2: tie
     -1: simulator panic attack -- something's gone wrong */
  }/*for(0 --> 1)*/
 }/*for (0 --> rounds)*/
 /************* this code uses the number of cycles in the scoring
 if (type==1)
  {
  printf("skewing the score. was %d and %d. ",*w1_score,*w2_score);
  *w1_score += (int)w1_time_score;
  *w2_score += (int)w2_time_score;
  printf(" now it's %d and %d. ",*w1_score,*w2_score);
  }
 ****************/

 }
// ************** end of pmars_rnd() *****************************************

// ****************** CHANGE REPRESENTATION *********************
// 7/28/00      Take a warrior in one of my structures and copy it
//      into a warrior_t structure. This procedure eliminates the need
//      for file IO. It is modeled after asm_file(). It puts each line
//      of code into a string and uses asm_line() to translate.
//
void change_representation(individual *W, warrior_t *w)
        {
        int line;
        //char J_line[MAX_ALL_CHARS];
        char J_line[256];//dbh. DOS
        insn_t *c;
        int ok;                 /* return code from asm_line() */
                                /* < 0 for done assembling */
                                /* == 0 for nothing to assemble */
                                /* > 0 for assembled line OK */

        w->len = w->start = 0;
        c = w->code;
 
 

        if (W->length > MAXwSIZE)       W->length = MAXwSIZE;
        //w->len = W->length-1;
        //w->start = W->start_point;
        for (line = 0; line < W->length; line++) //write 1 line
                {
                                //      check for errors
                if ( (W->cmd[line] < 0) || (W->cmd[line] >= num_cmd_0) ||
                     (W->mod[line] < 0) || (W->mod[line] >= num_mod_list_0) ||
                     (W->Am[line] < 0)  || (W->Am[line] >= num_am_0) ||
                     (W->Bm[line] < 0)  || (W->Bm[line] >= num_am_0) )
                        {
                        printf("write_warrior ERROR. [%d %d %d %d, %d %d]\n",
                                W->cmd[line],W->mod[line],W->Am[line],W->A[line],
                                W->Bm[line], W->B[line]);
                        printf("In line %d of %d\n",line,W->length);
                        //W->length = line;
                        }

                else
                        {
                        /***********
                        printf("write_warrior OK. [%d %d %d %d, %d %d]\n",
                                W->cmd[line],W->mod[line],W->Am[line],W->A[line],
                                W->Bm[line], W->B[line]);
                        printf("%s%s %s%6d, %s%6d\n",
                                cmd_list_0[ W->cmd[line] ],
                                mod_list_0[ W->mod[line] ],
                                am_list_0[ W->Am[line] ],
                                W->A[line],
                                am_list_0[W->Bm[line] ],
                                W->B[line]);
                        ***********/

                        sprintf(J_line,"%s%s %s%6d, %s%6d",
                                cmd_list_0[ W->cmd[line] ],
                                mod_list_0[ W->mod[line] ],
                                am_list_0[ W->Am[line] ],
                                W->A[line],
                                am_list_0[W->Bm[line] ],
                                W->B[line]);
                        }
                //while ( fgets(line, MAX_ALL_CHARS, F) ) {
                ok = asm_line( J_line, c, CORESIZE );
                if ( ok > 0 )
                        {
              //          printf("line %d is OK for asm_line()\n",line);

                        //if ( get_flags( c->in ) & fl_START )
                        //        w->start = w->len;
                        if ( w->len < MAXLENGTH) c++;
                        w->len++;

                        }

                if ( ok < 0 ) printf("line maybe not OK\n");
                //if ( w->len > MAXLENGTH ) {
                //fprintf(stderr, "too many instructions in warrior %d\n", w->no);
                //exit(1);
                }
        w->start = W->start_point;
        //printf("finished\n\n");
        }
// ************** end of CHANGE REPRESENTATION *********************
 
 

// ******** ONE CYCLE *************************
//12/07/99      One generation cycle for one population.
//
float one_cycle(individual pop[], individual hill[], int i)
        {
        int j;
        float w;
        char challenger_name[256];
        char new_name[256];
        int h_num;

                // ------------- The 1st population competes against hill2 -----
        printf("%s..... %d ..... %d ..... %d .....%d\n",pop[1].population_name,i,i,i,i);

        if (FREEZE && ( (i==starting_cycle)||((i%10) == 0) ) )
         {
         fprintf(fp1," CHANGING THE POSITION SEQUENCE\n");
         for (j=0;j<POS_SEQ_LENGTH;j++)
           {
           FixedPositionSeq[j] = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
    if (j < 10) printf(". pos = %d \n",FixedPositionSeq[j]);
           }
  dbh_test_one_cycle(population_size,pop[1].population_name, pop, i+1,hill);
  }

 if (!FREEZE) for (j=0;j<POS_SEQ_LENGTH;j++)
         {
         FixedPositionSeq[j] = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
  //printf(". pos = %d \n",FixedPositionSeq[j]);
  }
        if (STEADYSTATE)
                {
                        // score each individual against the hill
                if (!FREEZE) dbh_test_one_cycle(population_size,pop[1].population_name, pop, i+1,hill);
                        // calculate some statistics
                if (!FREEZE) true_stat(pop);
                        // form a new generation using a steady state GA
                nextgen(population_size, pop[1].population_name, pop, i,hill);
                }
        else
                {
                        // form a new generation using a standard GA
                nextgen_STD(population_size, pop[1].population_name, pop, i,hill);
                        // score each individual against the hill
                dbh_test_one_cycle(population_size,pop[1].population_name, pop, i+1,hill);
                }
                // calculate some statistics for the new generation
       true_stat(pop);
 

                // Take the best warrior, send a copy to Valhalla and get
                // a Wilkies benchmark score for it.
                // See if it can get onto the hill (it almost always can),
                // and update the hill if necessary

        fprintf(fp1,"%s: generation %d\n",pop[1].population_name, i);
        printf("%s: generation %d\n",pop[1].population_name, i);

         sprintf(challenger_name,"%s_%d.red", pop[1].population_name, best_in_pop);
        sprintf(new_name,"%s_%d.red", pop[1].Valhalla_name, 1 + i%RINGSIZE);
        printf("stored in %s \n",new_name);
        fprintf(fp1,"stored in %s \n",new_name);
        write_warrior( pop[best_in_pop],new_name); //send to valhalla
        write_warrior( pop[best_in_pop],"temp.red"); //for display purposes

        w = 0.0;
        if (Take_Benchmark)
         {
         //fprintf(fp1,"WILK IT: (most_venerable, most_outdated, best_in_pop) score = -111\n");
         //w = bench_mark(new_name,&pop[most_venerable]);
         //w = bench_mark(new_name,&pop[most_outdated]);
         w = bench_mark(new_name,&pop[best_in_pop]);
         }
         // benchmark the best. 12/05/98

        if (!STATIC_HILL)   // The best individual tries to get onto the hill
           if (challenge_hill(pop[best_in_pop],challenger_name, hill, &h_num, i))
                hill[h_num].wilkies_score = w;
 

        return(w);
        }
// ******** end of ONE CYCLE *************************

// ************************ MAIN ***************************

int main()
{

int i,j,p;                           // don't know population size yet
individual *POP[100];
individual  hill1[ max_num_tests+MELEE_BUFFER];
int count=0;            // number of generations
float w;
char challenger_name[256],x_name[256];
int age[100];
float best_wilkies[100];

/*********
read_warrior("b.red", &arch);
write_warrior(arch,"a.red" ); // save to file
exit(0);
**************/
remove("HAL0.log"); // delete the old file to avoid problems
        //open up a log file
if ((fp1 = fopen("HAL0.log","w")) == NULL)
                 {
                printf("Unable to open output file: \n");
                exit(1);
                }
printf("Log file Opened\n");
 

 // set up fixed position sequence (start points for battles)
if((FixedPositionSeq = ( int *)malloc( (POS_SEQ_LENGTH+10) * sizeof( int ) )) == NULL )
        {printf("Malloc Error for FixedPositionSeq\n");exit(0);}
else    printf("Malloc okay for FixedPositionSeq\n");
 // fill the sequence

for (i=0;i<30;i++) rand();

// rand() is randomized in setup()

setup();        // read in the parameters

for (i=0;i<POS_SEQ_LENGTH;i++)
        {
        FixedPositionSeq[i] = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
        if (i<10) fprintf(fp1,"Fixed sequence %d: %d\n",i,FixedPositionSeq[i]);
        }
  /*
   * Allocate core memory
   */
   //assumes that you want the same number of processes as core spaces
   //modify the setup() procedure to change this.
  core = sim_alloc_bufs( 2, CORESIZE, CORESIZE, NUMBERofCYCLES );
  if ( core == NULL )
    {
    printf("can't allocate memory.\n");
    exit(0);
    }

    /* request address of core memory */
//(void) sim(-1, 0, 0, 0, (void**)&core );

for (p=1;p<=NUMBER_OF_SPECIES;p++)
        {
 printf("starting Malloc for pop%d\n",p);
 if((POP[p] = ( individual *)malloc( (population_size+MELEE_BUFFER) * sizeof( individual ) )) == NULL )
          {printf("Malloc Error from pop%d\n",p);exit(0);}
 else    printf("Malloc okay for pop%d\n",p);
 

 sprintf(challenger_name,"x%d",p);
 sprintf(x_name,"v%d",p);
 fix_names(POP[p],  challenger_name, "h1", x_name, population_size+(MELEE_BUFFER/2));
 best_wilkies[p] = 0.0; age[p] = 0;
 }
fix_names(hill1, "h1", "h1", "h", max_num_tests+(MELEE_BUFFER/2));     // first hill
printf("fix_names finished\n");

arch_length = 0;
 

if (create_new_population)      // form a new random population
        {
        if (!STATIC_HILL) bootstrap_pop(hill1,num_tests+2);
        else              read_in_pop(hill1,num_tests+2);
        for (p=1;p<=NUMBER_OF_SPECIES;p++)
         {
         bootstrap_pop(POP[p],population_size);
         printf("population %d created\n",p);
         }
        }
else
        {
        read_in_pop(hill1,num_tests+2);
        for (p=1;p<=NUMBER_OF_SPECIES;p++)
         {
         read_in_pop(POP[p],population_size);
   }
  read_warrior("h1_1.red", &arch);
  arch_length = arch.length;
        }   // read from files

// don't score the hill the first time
//score_hill(hill1);    // compete hill members amongst themselves
if (!STEADYSTATE) dbh_test_one_cycle(population_size,POP[1]->population_name, POP[1], 0,hill1);
for (i=starting_cycle;i<(starting_cycle+number_of_cycles);i++)
        {
        if ( (count%100) == 99 ) //periodically clear the log file
                {
                fclose(fp1);
                remove("HAL0.log"); // delete the old file to avoid problems
                        //open up a log file
                if ((fp1 = fopen("HAL0.log","w")) == NULL)
                        {
                        printf("Unable to open output file: \n");
                        exit(1);
                        }
                printf("Log file cleared\n");
                }
        //------------------------- for each separate population
        for (p=1;p<=NUMBER_OF_SPECIES;p++)
         {
         printf("v%d\n",p);
         fprintf(fp1,"v%d\n",p);
         memcpy(&arch,&hill1[1+(rand()%num_tests)],sizeof(individual));
         arch_length = arch.length;
         fflush(fp1);
         w = one_cycle(POP[p], hill1, i);
   // keep the best scoring warrior (against Wilkies). 7/23/99
  sprintf(challenger_name,"bestwar%d.red",p);
  if (w > best_wilkies[p])
      {
      printf("\n\n%f v%d  A NEW BEST SCORE!\n",w,p);
      fprintf(fp1,"\n\n%f v%d  A NEW BEST SCORE!\n",w,p);
      best_wilkies[p] = w;
      write_warrior( POP[p][best_in_pop],challenger_name); // save to file
      age[p] = count;
      }

  printf("TRUE COUNT = %d, best score v%d was %f at %d\n",
    count,p,best_wilkies[p],age[p]);
  fprintf(fp1,"TRUE COUNT = %d, best score v%d was %f at %d\n",
    count,p,best_wilkies[p],age[p]);

  // The best warrior found so far, as measured by the Wilkies Benchmark
  // is reborn in position 1, at each generation.
   if (Take_Benchmark) read_warrior(challenger_name, &(POP[p][1])); // bestwar*.red is reborn
         write_out_pop(POP[p],population_size);
         if (STATIC_HILL) // allow user to change "static" hill on-the-fly
          {
          read_in_pop(hill1,num_tests);
          }
 

          printf("max score was %f\n",POP[p][best_in_pop].score);
          fprintf(fp1,"max score was %f\n",POP[p][best_in_pop].score);
   if (!FREEZE) for (j=0;j<POS_SEQ_LENGTH;j++)
           {
           FixedPositionSeq[j] = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
    }
                        hill_objective("dummy",POP[p],best_in_pop,hill1);
          printf("second test gives %f\n",POP[p][best_in_pop].score);
          fprintf(fp1,"second test gives %f\n",POP[p][best_in_pop].score);
          printf("reading in the hill\n");
         }

        fflush(fp1);
        count++;
        }
fclose(fp1);

  sim_free_bufs(); //free the core
        for (p=1;p<=NUMBER_OF_SPECIES;p++)
         {free(&POP[p]);}
return 1;

}