

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <globals.h>
#include <string.h>

#define SEQUENCELENGTH 16
#define SPECIESPERCLADE 16777216
#define STARTINGSPECIES 4096
#define STARTINGCLADES 256
#define MAXLINELENGTH 66536

//Define lineage elements (species and higher taxa)
typedef struct species
{
   int index; //This is just an index
   int ancestor; //The index of the species this species is derived from
   int extant; //0 if the species is extinct, 1 if not extinct
   float extinction; //A variable measuring the probability of the species' extinction in a given timestep
   float speciation; //A variable measuring the probability of the species giving rise to new species in a given timestep
   float evolution; //The rate of evolution of the species' gene sequence over its history
   int speciesage; //The number of timesteps in which the species has existed
   int highertaxon; //The index of the higher taxon (clade) to which the species belongs
   int pollination; //0 if the species is wind-pollinated, 1 if insect-pollinated
   int dispersal; //0 if the species is wind-dispersed, 1 if vertebrate-dispersed
   float range; //Geographic range of a species, in arbitrary units
   char Sequence[SEQUENCELENGTH]; //Sequence of 512 nucleotides, to be modeled each timestep
   int couplet; //Couplet is used for tree building
   int *Descendents; //Descendents is for the finding of couplets, the list of descendent species
   int numdescendents; //numdescendents keeps track of the number of descendents.
   int currentlyancestral; //Used each timestep to see if it's currently ancestral to a living species.
} species;

typedef struct clade
{
   int index; //Also just an index
   char Name[MAXLINELENGTH]; //Name of the clade - for the human to keep track of it with.
   int ancestor; //Index of the species this clade is derived from or sister to
   int ancestorclade; //Index of the clade to which the ancestral species belongs (yes, that "clade" is paraphyletic if this one is excluded from it - but this is how evolution happens)
   int specieslist[SPECIESPERCLADE]; //Array containing the indeces of all of the species in the clade; if it gets over 256, create a new clade
   int diversity; //Number of species in the clade, so we don't run off the end of specieslist.
   int standingdiversity; //Number of species still surviving in the clade.
   int extant; //0 if the entire clade is extinct, 1 if at least some of its species are still extant
   float extinction; //A variable measuring the rate of species extinction probability over the entire clade (used in calculating probabilities for new species)
   float speciation; //As above, but for extinction
   float evolution; //As above, but for sequence evolution
   float cladogenesis; //Probability of a clade giving rise to an entirely new higher taxon (yes, this makes the clade paraphyletic)
   int age; //Age of the clade
   int pollinationtendency; //Overall preferred pollination type of the clade, used for making new species (together with a global clade sensitivity constant). Numbers same as species.
   int dispersaltendency; //As above, but dispersal
   float rangetendency; //Tendency of the clade to have a large range or a small range. Species will gravitate toward occupying this entire range over a clade.
} clade;

typedef struct couplet
{
   int index;
   int firstmember;    //member is the index of the member of the couplet
   int firsttype;      //type is 0 if species, 1 if another couplet
   int secondmember;   //age is the age of the split
   int secondtype;     //CladeName is the string name of the couplet for a NEXUS file.
   int age;
   char *CladeName;
   int cladenamelength;
} couplet;

//Define globals to be directly used
species *Lineages = 0; //Array containing all of the species, to be reallocated as necessary
clade *Classes = 0; //Array containing all of chte clades, also may be reallocated
couplet *Pairings = 0;

int Speciescount = 0; //Number of species
int Speciesextinct = 0; //Number of species which have become extinct
int Classcount = 0; //Number of clades
int Cladesextinct = 0; //Number of clades which have become extinct
int Timestep = 0; //Timestep
int CurrentMaxSpecies = STARTINGSPECIES;
int CurrentMaxClades = STARTINGCLADES;
int ExtinctionPulse = 0;
int ExtinctionPulseCount = 0;
int CoupletCount = 0;

//Constants to be read from file.
float SpeciationDecayConstant; //Rate at which speciation rate decays with time
float ExtinctionDecayConstant; //Rate at which extinction rate decays with time
float EvolutionDecayConstant; //Rate at which sequence evolution rates decay with time
float PollinationSpeciationMultiplier; //Arithmetic multiplier to speciation rate for animal pollination (lowers speciation rate if < 1.0)
float PollinationExtinctionMultiplier; //As you would expect, but extinction
float PollinationSpeciationDecayConstant; //Arithmetic multiplier to SpeciationDecayConstant for animal-pollinated things
float PollinationExtinctionDecayConstant; //Extinction
float PollinationEvolutionMultiplier; //Multiplies rate of molecular evolution for animal-pollinated things
float PollinationRangeMultiplier; //Increases (if > 1.0) geographic range tendency for animal-pollinated (reduces if < 1.0)
float DispersalSpeciationMultiplier; //These are the same things, but for dispersal
float DispersalExtinctionMultiplier;
float DispersalSpeciationDecayConstant;
float DispersalExtinctionDecayConstant;
float DispersalEvolutionMultiplier;
float DispersalRangeMultiplier;
float StochasticRangeMultiplier;
float ExtinctionPulseFrequency;
float ExtinctionPulseIntensity;
float ExtinctionPulsePollinationSelectivity;
float ExtinctionPulseDispersalSelectivity;
float RangeImportance;
float TransitionRate; //Intrinsic rate of transitions (C to T, T to C, A to G, G to A), as per a Kimura two-parameter evolutionary model
float TransversionRate; //Intrinsic rate of transversions (A to C, C to G, G to T, T to A, C to A, G to C, T to G, A to T), as per a Kimura two-parameter evolutionary model
float SpeciationStateChangeRates[2][2][2][2]; //Rates of character state transitions during speciation; first and second indicies represent the state changing from, the third and fourth the state changing to;
float BackgroundStateChangeRates[2][2][2][2]; //Rates of character state transitions during background evolution; work the same way as speciation
//first and third are pollination, second and fourth are dispersal; 0 in all cases is wind-, and 1 is animal-.
float CladePollinationImportance[2]; //Multiplication constant on the rates of state changes TO wind (0) or animal (1) pollination.
//Clade tendency has no effect if this constant is 1.0, but has a stronger positive effect if > 1.0. Clades will actually move AWAY from their "preferred" type if < 1.0.
float CladeDispersalImportance[2]; //Exactly the same as above, but for dispersal
int MaxSpecies; //If the simulation reaches this number of species, terminate. Ignored if 0.
int MaxClades; //If the simulation reaches this number of clades, terminate. Ignored if 0.
int MaxTimesteps; //When the simulation has run for this number of timesteps, terminate. Ignored if 0 (not recommended, as it may run on forever).
float MaxSpeciesExtinction; //When this proportion of the total number of species that have become extinct reaches this value, terminate.
float MaxCladeExtinction; //As above, but for clades.

//File management
FILE *model;            //Input file that describes the model of evolution
FILE *biota;            //Input file that describes the starting clade(s)
FILE *output;           //Output file containing a table of the final parameters of each species
FILE *nexus;            //Output file of the surviving species in a phylogenetic tree
FILE *csv;              //Output file of the final character states of surviving species, for use with diversitree
FILE *diversitycurve;   //Output file that prints diversity over time.
FILE *finalstats;       //Output file that gives general statistics (used in the R code invoking both this and diversitree)
char modelname[STARTINGCLADES];
char biotaname[STARTINGCLADES];
char outname[STARTINGCLADES];
char nexusname[STARTINGCLADES];
char csvname[STARTINGCLADES];
char curvename[STARTINGCLADES];
char statsname[STARTINGCLADES];

void CheckCladogenesis(int cladenumber);
void CheckExtinction(int species);
void CheckExtinctionPulse();
void CheckRangeDynamics(int species);
void CheckSpeciation(int species);
void ClearExtinctionPulse();
int DefineCouplet(int firstmember, int firstiscouplet, int secondmember, int secondiscouplet, int divergenceage);
void DoBackgroundEvolution(int species);
void ExitBadBiota();
void ExitBadModel(char *Bad, char *Explanation);
void Extinction(int species);
int FindExtantDescendentSpecies(int ancestorspecies);
void GenerateDiversityCurves(int *truediversity);
double GetRandomFloat(double randommax);
int GetRandomInt(int randommax);
void IdentifyExtinctClades(int cladenumber);
void InitializeStartingClade(char *CharacterLine);
float NthWordFloat(int wordnumber, char *Line);
int NthWordInt(int wordnumber, char *Line);
int RecursiveBuildTreeFromSpecies(int focalspecies);
void SequenceEvolution(int species);
void Speciate(int ancestor);

int main (int argc, char **argv)
{
   char line[MAXLINELENGTH];
   int i, j, k, l;
   int *truediversity = 0;
   //   int iscomma = 0;
   double numstates[2];
   
   Lineages = (species*) malloc(STARTINGSPECIES * sizeof(species));
   Classes = (clade*) malloc(STARTINGCLADES * sizeof(clade));
   
   
   
   //Obsolete code for when this program was compiled on a different system
   /*
    if (argc != 8)
    {
    fprintf(stderr, "Speciation Extinction Model for Bisse data: wrong number of arguments used (needed 8, used %d). Remember, the number of arguments is 1 + the number of filenames given.\n",
				argc);
    fprintf(stderr, "First argument given should be the model, second argument the starting clade(s), and the final argument the name of the file to be output.\n");
    exit(1);
    } */
   
   
   sprintf(modelname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Data/Model.txt", getenv("HOME"));
   sprintf(biotaname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Data/Biota.txt", getenv("HOME"));
   sprintf(outname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Output/output.txt", getenv("HOME"));
   sprintf(nexusname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Output/TreeFile.txt", getenv("HOME"));
   sprintf(csvname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Output/CharStates.csv", getenv("HOME"));
   sprintf(curvename, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Output/DiversityCurve.txt", getenv("HOME"));
   sprintf(statsname, "%s/Written_C_Programs/src/SpeciationExtinctionModel/Output/FinalStats.csv", getenv("HOME"));
   
   
   //Seed the random number generator
   srand48(time(0));
   
   
   //Load Files
   model = fopen(modelname, "r");
   biota = fopen(biotaname, "r");
   output = fopen(outname, "w");
   nexus = fopen(nexusname, "w");
   csv = fopen(csvname, "w");
   diversitycurve = fopen(curvename, "w");
   finalstats = fopen(statsname, "w");
   
   
   //Input model parameters
   //NthWordFloat needs to use strtod(), which has the same format as strtol().
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "SpeciationDecayConstant");
   SpeciationDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "ExtinctionDecayConstant");
   ExtinctionDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "EvolutionDecayConstant");
   EvolutionDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationSpeciationMultiplier");
   PollinationSpeciationMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationExtinctionMultiplier");
   PollinationExtinctionMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationSpeciationDecayConstant");
   PollinationSpeciationDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationExtinctionDecayConstant");
   PollinationExtinctionDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationEvolutionMultiplier");
   PollinationEvolutionMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "PollinationRangeMultiplier");
   PollinationRangeMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalSpeciationMultiplier");
   DispersalSpeciationMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalExtinctionMultiplier");
   DispersalExtinctionMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalSpeciationDecayConstant");
   DispersalSpeciationDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalExtinctionDecayConstant");
   DispersalExtinctionDecayConstant = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalEvolutionMultiplier");
   DispersalEvolutionMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "DispersalRangeMultiplier");
   DispersalRangeMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "StochasticRangeMultiplier");
   StochasticRangeMultiplier = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "RangeImportance");
   RangeImportance = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "ExtinctionPulseFrequency");
   ExtinctionPulseFrequency = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "ExtinctionPulseIntensity");
   ExtinctionPulseIntensity = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "ExtinctionPulsePollinationSelectivity");
   ExtinctionPulsePollinationSelectivity = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "ExtinctionPulseDispersalSelectivity");
   ExtinctionPulseDispersalSelectivity = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "TransitionRate");
   TransitionRate = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "TransversionRate");
   TransversionRate = NthWordFloat(0, line);
   
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "SpeciationStateChangeRates");
   for (i = 0; i < 2; i++)
   {
      for (j = 0; j < 2; j++)
      {
         for (k = 0; k < 2; k++)
         {
            for (l = 0; l < 2; l++)
               SpeciationStateChangeRates[i][j][k][l] = NthWordFloat(i + (2 * j) + (4 * k) + (8 * l), line);
         }
      }
   }
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "BackgroundStateChangeRates");
   for (i = 0; i < 2; i++)
   {
      for (j = 0; j < 2; j++)
      {
         for (k = 0; k < 2; k++)
         {
            for (l = 0; l < 2; l++)
               BackgroundStateChangeRates[i][j][k][l] = NthWordFloat(i + (2 * j) + (4 * k) + (8 * l), line);
         }
      }
   }
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "CladePollinationImportance");
   CladePollinationImportance[0] = NthWordFloat(0, line);
   CladePollinationImportance[1] = NthWordFloat(1, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "CladeDispersalImportance");
   CladeDispersalImportance[0] = NthWordFloat(0, line);
   CladeDispersalImportance[1] = NthWordFloat(1, line);
   
   
   //Input termination conditions
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "MaxSpecies");
   MaxSpecies = NthWordInt(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "MaxClades");
   MaxClades = NthWordInt(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "MaxTimesteps");
   MaxTimesteps = NthWordInt(0, line);
   
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "MaxSpeciesExtinction");
   MaxSpeciesExtinction = NthWordFloat(0, line);
   if (!fgets(line, MAXLINELENGTH, model))
      ExitBadModel("", "MaxCladeExtinction");
   MaxCladeExtinction = NthWordFloat(0, line);
   
   
   //Input starting clades
   for (i = 0;; i++)
   {
      if (!fgets(line, MAXLINELENGTH, biota))
         break;
      if (strcmp(line, "\n") == 0)
         ExitBadBiota();
      InitializeStartingClade(line);
      Classcount++;
   }
   if (i == 0)
      ExitBadBiota();
   
   //Run the evolutionary model
   for (Timestep = 0; (Timestep < MaxTimesteps) || (MaxTimesteps == 0); Timestep++)
   {
      CheckExtinctionPulse();
      numstates[0] = 0;
      numstates[1] = 0;
      
      if (Timestep == 128)
         i = 0;
      
      //Species evolution
      for (i = 0; i < Speciescount; i++)
      {
         Lineages[i].speciesage++;
         if (Lineages[i].extant)
         {
            DoBackgroundEvolution(i);
            CheckRangeDynamics(i);
            CheckSpeciation(i);
            CheckExtinction(i);
         }
         if (Lineages[i].extant)
         {
            SequenceEvolution(i);
            numstates[Lineages[i].pollination]++;
         }
      }
      //Anything happening at the class level
      for (i = 0; i < Classcount; i++)
      {
         Classes[i].age++;
         if (Classes[i].extant)
            IdentifyExtinctClades(i);
         if (Classes[i].extant)
            CheckCladogenesis(i);
      }
      
      printf("Timestep %d done.\n", Timestep);
      printf("Ancestral state count: %f. Derived state count: %f\n", numstates[0], numstates[1]);
      printf("Proportion with derived state %f\n", numstates[1] / (numstates[0] + numstates[1]));
      
      //break conditions
      if ((Speciescount >= MaxSpecies) && (MaxSpecies > 0))
         break;
      else if ((Classcount >= MaxClades) && (MaxClades > 0))
         break;
      else if (((float) Speciesextinct / (float) Speciescount) >= MaxSpeciesExtinction)
         break;
      else if (((float) Cladesextinct / (float) Classcount) >= MaxCladeExtinction)
         break;
      
      ClearExtinctionPulse();
      
      //Need to initialize truediversity for the diversity curve.
      if (Timestep == 0)
         truediversity = calloc(1, sizeof(int));
      else
         truediversity = realloc(truediversity, (1 + Timestep) * sizeof(int));
      for (i = 0, truediversity[Timestep] = 0; i < Speciescount; i++)
      {
         truediversity[Timestep] += Lineages[i].extant;
      }
   }
   
   
   //Once broken from previous loop, we're done with the simulation. Make the general output table
   for (i = 0; i < Speciescount; i++)
   {
      fprintf(output, ">Species %d %d %d ", Lineages[i].index,  Lineages[i].ancestor,  Lineages[i].extant);
      fprintf(output, "%f %f %f ", Lineages[i].extinction,  Lineages[i].speciation,
              Lineages[i].evolution);
      fprintf(output, "%d %d %d %d %f\n",  Lineages[i].speciesage,  Lineages[i].highertaxon,  Lineages[i].pollination,  Lineages[i].dispersal,  Lineages[i].range);
      fprintf(output, "%s\n",  Lineages[i].Sequence);
      
   }
   fprintf(output, "\n\n\n\n");
   for (i = 0; i < Classcount; i++)
   {
      fprintf(output, "%d %s ", Classes[i].index, Classes[i].Name);
      fprintf(output, "%d %d %d %d ", Classes[i].ancestor, Classes[i].ancestorclade, Classes[i].diversity,
              Classes[i].standingdiversity);
      fprintf(output, "%f %f %f %f ", Classes[i].extinction, Classes[i].speciation, Classes[i].evolution, Classes[i].cladogenesis);
      fprintf(output, "%d %d %d:\n",Classes[i].age, Classes[i].pollinationtendency, Classes[i].dispersaltendency);
      
      fprintf(output, "Species: ");
      for (j = 0; j < Classes[i].diversity; j++)
         fprintf(output, "%d ", Classes[i].specieslist[j]);
      fprintf(output, "\nSurviving species: ");
      for (j = 0; j < Classes[i].diversity; j++)
      {
         if (Lineages[Classes[i].specieslist[j]].extant == 1)
            fprintf(output, "%d ", Classes[i].specieslist[j]);
      }
      fprintf(output, "\n\n");
   }
   
   //Now, make the tree file!
   fprintf(nexus, "#NEXUS\n");
   
   //Taxa first
   fprintf(nexus, "BEGIN TAXA;\n");
   fprintf(nexus, "\tTITLE Taxa;\n");
   fprintf(nexus, "\tDIMENSIONS NTAX=%d;\n", Speciescount - Speciesextinct);
   fprintf(nexus, "\tTAXLABELS\n");
   fprintf(nexus, "\t\t");
   for (i = 0; i < Speciescount; i++)
   {
      if (Lineages[i].extant)
         fprintf(nexus, "%d ", i);
   }
   fprintf(nexus, "\n\t;\n\nEND;\n\n");
   
   //Characters next
   fprintf(nexus, "BEGIN CHARACTERS;\n");
   fprintf(nexus, "\tTITLE  Character_Matrix;\n");
   fprintf(nexus, "\tDIMENSIONS  NCHAR=2;\n");
   fprintf(nexus, "\tFORMAT DATATYPE = STANDARD GAP = - MISSING = ? SYMBOLS = \"0 1\";\n");
   fprintf(nexus, "\tMATRIX\n");
   for (i = 0; i < Speciescount; i++)
   {
      if (Lineages[i].extant)
         fprintf(nexus, "\t%d %d%d\n", i, Lineages[i].pollination, Lineages[i].dispersal);
   }
   fprintf(nexus, "\n\n;\n\nEND;\n\n");
   
   //Tree last
   fprintf(nexus, "BEGIN TREES;\n");
   fprintf(nexus, "\tTitle 'Simulated taxon tree';\n");
   fprintf(nexus, "\tLINK Taxa = Taxa;\n");
   /*
    fprintf(nexus, "\tTRANSLATE");
    for (i = 0; i < Speciescount; i++)
    {
    if (Lineages[i].extant)
    {
    if (iscomma)
    fprintf(nexus, ",");
    else
    iscomma = 1;
    fprintf(nexus, "\n\t\t%d Spc%d", i, i);
    }
    }
    fprintf(nexus, ";\n");
    */
   RecursiveBuildTreeFromSpecies(0);
   if (CoupletCount > 1)
      fprintf(nexus, "\tTREE simulatedtree = %s;\n", Pairings[CoupletCount - 1].CladeName);
   else
   {
      fprintf(stderr, "Warning: surviving diversity insufficient to generate tree (i.e. one or zero species surviving in total)!\n");
      fprintf(finalstats, "finalspecies,finalsurvivors\n%d,%d\n", Speciescount, Speciescount - Speciesextinct);
      exit(1);
   }
   fprintf(nexus, "\nEND;\n\n");
   
   
   //Now we make the csv text file because BiSSE can't seem to read characters out of a nexus file!
   fprintf(csv, "species,pollination,dispersal\n");
   for (i = 0; i < Speciescount; i++)
   {
      if (Lineages[i].extant)
         fprintf(csv, "%d,%d,%d\n", i, Lineages[i].pollination, Lineages[i].dispersal);
   }
   
   printf("Total species: %d\nTotal surviving species: %d\nTotal number of extinction pulses: %d\n", Speciescount, Speciescount - Speciesextinct, ExtinctionPulseCount);
   
   //And print out the final stats!
   fprintf(finalstats, "finalspecies,finalsurvivors\n%d,%d\n", Speciescount, Speciescount - Speciesextinct);
   
   GenerateDiversityCurves(truediversity);
   
   exit(0);
}



void CheckCladogenesis(int cladenumber)
{
   //No constants currently implemented.
}

void CheckExtinction(int species)
{
   float actualextinction, survival, multiplier, timemeasure, randomint;
   
   actualextinction = Lineages[species].extinction;
   survival = 1 - actualextinction;
   
   timemeasure = Timestep;
   
   if (Lineages[species].pollination == 0)
   {
      if (Lineages[species].dispersal == 0)
         multiplier = pow(ExtinctionDecayConstant, timemeasure);
      else
         multiplier = pow(ExtinctionDecayConstant * DispersalExtinctionDecayConstant, timemeasure);
   }
   else
   {
      if (Lineages[species].dispersal == 0)
         multiplier = pow(ExtinctionDecayConstant * PollinationExtinctionDecayConstant, timemeasure);
      else
         multiplier = pow(ExtinctionDecayConstant * PollinationExtinctionDecayConstant * DispersalExtinctionDecayConstant, timemeasure);
   }
   
   multiplier *= pow(Lineages[species].range, RangeImportance);
   
   multiplier *= pow(ExtinctionPulseIntensity, ExtinctionPulse);
   if (Lineages[species].pollination)
      multiplier *= ExtinctionPulsePollinationSelectivity; //state 1
   if (Lineages[species].dispersal)
      multiplier *= ExtinctionPulseDispersalSelectivity;
   
   actualextinction *= multiplier;
   
   if (Lineages[species].pollination == 1)
      actualextinction *= PollinationExtinctionMultiplier;
   if (Lineages[species].dispersal == 1)
      actualextinction *= DispersalExtinctionMultiplier;
   
   randomint = GetRandomFloat(actualextinction + survival);
   if (randomint < actualextinction)
      Extinction(species);
}


void CheckExtinctionPulse()
{
   for (ExtinctionPulse = 0; GetRandomFloat(1) < ExtinctionPulseFrequency; ExtinctionPulse++);
   
   if (ExtinctionPulse)
   {
      //printf("Extinction pulse of intensity %f in timestep %d\n", pow(ExtinctionPulseIntensity, ExtinctionPulse), Timestep);
      ExtinctionPulseCount++;
   }
}


void CheckRangeDynamics(int species)
{
   int highertaxon = Lineages[species].highertaxon;
   float targetrange = Classes[highertaxon].rangetendency / sqrt((float) Classes[highertaxon].standingdiversity);
   float stochasticvariation = pow(StochasticRangeMultiplier, 1 - GetRandomFloat(2));
   
   if (Lineages[species].pollination == 1)
      targetrange *= PollinationRangeMultiplier;
   if (Lineages[species].dispersal == 1)
      targetrange *= DispersalRangeMultiplier;
   
   Lineages[species].range = sqrt(Lineages[species].range * targetrange);
   Lineages[species].range *= stochasticvariation;
}


void CheckSpeciation(int species)
{
   float actualspeciation, nonspeciation, multiplier, timemeasure, randomint;
   
   actualspeciation = Lineages[species].speciation;
   nonspeciation = 1 - actualspeciation;
   
   timemeasure = Timestep;
   
   if (Lineages[species].pollination == 0)
   {
      if (Lineages[species].dispersal == 0)
         multiplier = pow(SpeciationDecayConstant, timemeasure);
      else
         multiplier = pow(SpeciationDecayConstant * DispersalSpeciationDecayConstant, timemeasure);
   }
   else
   {
      if (Lineages[species].dispersal == 0)
         multiplier = pow(SpeciationDecayConstant * PollinationSpeciationDecayConstant, timemeasure);
      else
         multiplier = pow(SpeciationDecayConstant * PollinationSpeciationDecayConstant * DispersalSpeciationDecayConstant, timemeasure);
   }
   
   actualspeciation *= multiplier;
   
   if (Lineages[species].pollination == 1)
      actualspeciation *= PollinationSpeciationMultiplier;
   if (Lineages[species].dispersal == 1)
      actualspeciation *= DispersalSpeciationMultiplier;
   
   randomint = GetRandomFloat(actualspeciation + nonspeciation);
   if (randomint < actualspeciation)
   {
      Speciate(species);
      CheckSpeciation(species);
   }
}


void Cladogenesis(int ancestorspecies, float statechangeprob, int extranewspecies)
{
   int ancestorclade = Lineages[ancestorspecies].highertaxon;
   float nonectarnofruit, nonectarfruit, nectarnofruit, nectarfruit, randomstate, i;
   
   
   if ((CurrentMaxClades - Classcount) == 0)
   {
      CurrentMaxClades += STARTINGCLADES;
      Classes = (clade*) realloc(Classes, CurrentMaxClades * sizeof(clade));
   }
   if ((CurrentMaxSpecies - Speciescount) == 0)
   {
      CurrentMaxSpecies += STARTINGSPECIES;
      Lineages = (species*) realloc(Lineages, CurrentMaxSpecies * sizeof(species));
   }
   
   //Make the new species first.
   Lineages[Speciescount].index = Speciescount;
   Lineages[Speciescount].ancestor = ancestorspecies;
   Lineages[Speciescount].extant = 1;
   //Come back to evolution, extinction, and speciation; they're complicated.
   Lineages[Speciescount].speciesage = 0;
   Lineages[Speciescount].highertaxon = ancestorclade;
   
   
   //Now, character evolution
   nonectarnofruit = SpeciationStateChangeRates[Lineages[ancestorspecies].pollination][Lineages[ancestorspecies].dispersal][0][0];
   nectarnofruit = SpeciationStateChangeRates[Lineages[ancestorspecies].pollination][Lineages[ancestorspecies].dispersal][1][0];
   nonectarfruit = SpeciationStateChangeRates[Lineages[ancestorspecies].pollination][Lineages[ancestorspecies].dispersal][0][1];
   nectarfruit = SpeciationStateChangeRates[Lineages[ancestorspecies].pollination][Lineages[ancestorspecies].dispersal][1][1];
   
   if (Classes[ancestorclade].pollinationtendency == 0)
   {
      nonectarnofruit *= CladePollinationImportance[0];
      nonectarfruit *= CladePollinationImportance[0];
   }
   else
   {
      nectarnofruit *= CladePollinationImportance[1];
      nectarfruit *= CladePollinationImportance[1];
   }
   if (Classes[ancestorclade].dispersaltendency == 0)
   {
      nonectarnofruit *= CladeDispersalImportance[0];
      nectarnofruit *= CladeDispersalImportance[0];
   }
   else
   {
      nonectarfruit *= CladeDispersalImportance[1];
      nectarfruit *= CladeDispersalImportance[1];
   }
   
   randomstate = GetRandomFloat(nonectarnofruit + nonectarfruit + nectarnofruit + nectarfruit);
   if (randomstate < nonectarnofruit)
   {
      Lineages[Speciescount].pollination = 0;
      Lineages[Speciescount].dispersal = 0;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit))
   {
      Lineages[Speciescount].pollination = 0;
      Lineages[Speciescount].dispersal = 1;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit + nectarnofruit))
   {
      Lineages[Speciescount].pollination = 1;
      Lineages[Speciescount].dispersal = 0;
   }
   else
   {
      Lineages[Speciescount].pollination = 1;
      Lineages[Speciescount].dispersal = 1;
   }
   
   
   strcpy(Lineages[Speciescount].Sequence, Lineages[ancestorspecies].Sequence); //At separation, two lineages share identical sequence.
   
   Lineages[Speciescount].range = GetRandomFloat(Lineages[ancestorspecies].range); //New ranges start out small.
   Lineages[ancestorspecies].range -= GetRandomFloat(Lineages[Speciescount].range); //They also take away from existing ranges.
   
   Lineages[Speciescount].evolution = Lineages[ancestorspecies].evolution;
   Lineages[Speciescount].speciation = Lineages[ancestorspecies].speciation;
   Lineages[Speciescount].extinction = Lineages[ancestorspecies].extinction;
   
   
   //Cladogenesis-related changes in state
   if (GetRandomFloat(1 + statechangeprob) < statechangeprob)
      Lineages[Speciescount].pollination = GetRandomInt(2);
   if (GetRandomFloat(1 + statechangeprob) < statechangeprob)
      Lineages[Speciescount].dispersal = GetRandomInt(2);
   
   //Incomplete code from an earlier draft of the model, used to set up new radiations from within otherwise declining groups
   /*	if (statechangeprob)
    {
    Lineages[Speciescount].evolution *= pow(1 / EvolutionDecayConstant, Classes[ancestorclade].age / 2);
    Lineages[Speciescount].extinction *= pow(1 / ExtinctionDecayConstant, Classes[ancestorclade].age / 2);
    Lineages[Speciescount].speciation *= pow(1 / SpeciationDecayConstant, Classes[ancestorclade].age / 2);
    }  */
   
   //Now, create the clade.
   Classes[Classcount].index = Classcount;
   sprintf(Classes[Classcount].Name, "%s.%d", Classes[ancestorclade].Name, Classcount);
   Classes[Classcount].ancestor = ancestorspecies;
   Classes[Classcount].ancestorclade = ancestorclade;
   Classes[Classcount].specieslist[0] = Speciescount;
   Classes[Classcount].diversity = 1;
   Classes[Classcount].extant = 1;
   Classes[Classcount].extinction = Lineages[Speciescount].extinction;
   Classes[Classcount].speciation = Lineages[Speciescount].speciation;
   Classes[Classcount].evolution = Lineages[Speciescount].evolution;
   Classes[Classcount].cladogenesis = Classes[ancestorclade].cladogenesis;
   Classes[Classcount].age = 0;
   Classes[Classcount].pollinationtendency = Lineages[Speciescount].pollination;
   Classes[Classcount].dispersaltendency = Lineages[Speciescount].dispersal;
   if (statechangeprob)
   {
      if (GetRandomInt(2))
         Classes[Classcount].rangetendency = Classes[ancestorclade].rangetendency * (1 - statechangeprob);
      else
         Classes[Classcount].rangetendency = Classes[ancestorclade].rangetendency / (1 - statechangeprob);
   }
   else
      Classes[Classcount].rangetendency = Classes[ancestorclade].rangetendency;
   
   printf("New clade %s originated, founded by species %d\n", Classes[Classcount].Name, Speciescount);
   
   Speciescount++;
   
   for (i = 0; i < extranewspecies; i++)
      Speciate(Classes[Classcount].specieslist[GetRandomInt(Classes[Classcount].diversity)]);
   
   Classcount++;
}


void ClearExtinctionPulse()
{
   ExtinctionPulse = 0;
}


int DefineCouplet(int firstmember, int firstiscouplet, int secondmember, int secondiscouplet, int divergenceage)
{
   int firstbranch, secondbranch, neededlength, i;
   char firststring[40], secondstring[40]; //40 digits is way more than needed!
   char *firstpointer, *secondpointer;
   
   if (CoupletCount == 0)
      Pairings = calloc(Speciescount, sizeof(couplet));
   
   for (i = 0; i < CoupletCount; i++)
   {
      if ((Pairings[i].firstmember == firstmember) && (Pairings[i].firsttype == firstiscouplet))
         return i;
      if ((Pairings[i].secondmember == firstmember) && (Pairings[i].secondtype == firstiscouplet))
         return i;
      if ((Pairings[i].firstmember == secondmember) && (Pairings[i].firsttype == secondiscouplet))
         return i;
      if ((Pairings[i].secondmember == secondmember) && (Pairings[i].secondtype == secondiscouplet))
         return i;
   }
   
   Pairings[CoupletCount].index = CoupletCount;
   Pairings[CoupletCount].firstmember = firstmember;
   Pairings[CoupletCount].firsttype = firstiscouplet;
   Pairings[CoupletCount].secondmember = secondmember;
   Pairings[CoupletCount].secondtype = secondiscouplet;
   Pairings[CoupletCount].age = divergenceage;
   
   if (firstiscouplet)
   {
      firstbranch = divergenceage - Pairings[firstmember].age;
      firstpointer = Pairings[firstmember].CladeName;
      neededlength = strlen(Pairings[firstmember].CladeName);
   }
   else
   {
      firstbranch = divergenceage;
      sprintf(firststring, "%d", firstmember);
      firstpointer = firststring;
      neededlength = strlen(firststring);
      Lineages[firstmember].couplet = CoupletCount;
   }
   
   if (secondiscouplet)
   {
      secondbranch = divergenceage - Pairings[secondmember].age;
      secondpointer = Pairings[secondmember].CladeName;
      neededlength += strlen(Pairings[secondmember].CladeName);
   }
   else
   {
      secondbranch = divergenceage;
      sprintf(secondstring, "%d", secondmember);
      secondpointer = secondstring;
      neededlength += strlen(secondstring);
      Lineages[secondmember].couplet = CoupletCount;
   }
   
   neededlength += 2 + log10(MAX(firstbranch,1)) + log10(MAX(secondbranch,1));
   
   Pairings[CoupletCount].CladeName = calloc(10 + neededlength, sizeof(char)); //need only 6 characters (two colons, a comma, open and close parens, and a \0), but give a cushion
   sprintf(Pairings[CoupletCount].CladeName, "(%s:%d,%s:%d)", firstpointer, firstbranch, secondpointer, secondbranch);
   
   Pairings[CoupletCount].cladenamelength = strlen(Pairings[CoupletCount].CladeName);
   
   CoupletCount++;
   return Pairings[CoupletCount - 1].index;
}


void DoBackgroundEvolution(int species)
{
   int highertaxon = Lineages[species].highertaxon;
   float nectarnofruit, nonectarnofruit, nonectarfruit, nectarfruit, randomstate;
   
   nonectarnofruit = BackgroundStateChangeRates[Lineages[species].pollination][Lineages[species].dispersal][0][0];
   nectarnofruit = BackgroundStateChangeRates[Lineages[species].pollination][Lineages[species].dispersal][1][0];
   nonectarfruit = BackgroundStateChangeRates[Lineages[species].pollination][Lineages[species].dispersal][0][1];
   nectarfruit = BackgroundStateChangeRates[Lineages[species].pollination][Lineages[species].dispersal][1][1];
   
   if (Classes[highertaxon].pollinationtendency == 0)
   {
      nonectarnofruit *= CladePollinationImportance[0];
      nonectarfruit *= CladePollinationImportance[0];
   }
   else
   {
      nectarnofruit *= CladePollinationImportance[1];
      nectarfruit *= CladePollinationImportance[1];
   }
   if (Classes[highertaxon].dispersaltendency == 0)
   {
      nonectarnofruit *= CladeDispersalImportance[0];
      nectarnofruit *= CladeDispersalImportance[0];
   }
   else
   {
      nonectarfruit *= CladeDispersalImportance[1];
      nectarfruit *= CladeDispersalImportance[1];
   }
   
   randomstate = GetRandomFloat(nonectarnofruit + nonectarfruit + nectarnofruit + nectarfruit);
   if (randomstate < nonectarnofruit)
   {
      Lineages[species].pollination = 0;
      Lineages[species].dispersal = 0;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit))
   {
      Lineages[species].pollination = 0;
      Lineages[species].dispersal = 1;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit + nectarnofruit))
   {
      Lineages[species].pollination = 1;
      Lineages[species].dispersal = 0;
   }
   else
   {
      Lineages[species].pollination = 1;
      Lineages[species].dispersal = 1;
   }
}


void ExitBadBiota()
{
   fprintf(stderr, "Biota file not initialized!\n");
   fprintf(stderr, "Copy the results file into the biota for a (simple) starting clade (note all parameters, including speciation and extinction, will be set to neutral values!).\n");
   
   fprintf(output, "Amborellales 0.5 0.5 1.0 1.0 0 0 1.0 20");
   exit(1);
}


void ExitBadModel(char *Bad, char *Explanation)
{
   if (Bad[0] == '\0')
      fprintf(stderr, "Error in input of model parameter %s: either model file truncated or extra line input.\n", Explanation);
   else
      fprintf(stderr, "There is an error in the model input (1st input file):\n%s, bad value %s.\n", Explanation, Bad);
   fprintf(stderr, "A sample model (all parameters set to 1.0, meaning no effects) file that you could use is being printed to the output.\n");
   
   fprintf(output, "1.0 --SpeciationDecayConstant; //Rate at which speciation rate decays with time (does not decay if 1.0, grows if > 1)\n");
   fprintf(output, "1.0 --ExtinctionDecayConstant; //Rate at which extinction rate decays with time (ditto)\n");
   fprintf(output, "1.0 --EvolutionDecayConstant; //Rate at which rates of sequence evolution decay with time\n");
   fprintf(output, "1.0 --PollinationSpeciationMultiplier; //Arithmetic multiplier to speciation rate for animal pollination (lowers speciation rate if < 1.0)\n");
   fprintf(output, "1.0 --PollinationExtinctionMultiplier; //As you would expect, but extinction\n");
   fprintf(output, "1.0 --PollinationSpeciationDecayConstant; //Arithmetic multiplier to SpeciationDecayConstant for animal-pollinated things\n");
   fprintf(output, "1.0 --PollinationExtinctionDecayConstant; //Extinction\n");
   fprintf(output, "1.0 --PollinationEvolutionMultiplier; //Multiplies rate of molecular evolution for animal-pollinated things\n");
   fprintf(output, "1.0 --PollinationRangeMultiplier; //Increases (if > 1.0) geographic range tendency for animal-pollinated (reduces if < 1.0)\n");
   fprintf(output, "1.0 --DispersalSpeciationMultiplier; //These are the same things, but for dispersal\n");
   fprintf(output, "1.0 --DispersalExtinctionMultiplier;\n");
   fprintf(output, "1.0 --DispersalSpeciationDecayConstant;\n");
   fprintf(output, "1.0 --DispersalExtinctionDecayConstant\n");
   fprintf(output, "1.0 --DispersalEvolutionMultiplier\n");
   fprintf(output, "1.0 --DispersalRangeMultiplier\n");
   fprintf(output, "1.0 --StochasticRangeMultiplier //Inter-timestep random volatility in species ranges; a value of 1.0 means no variation.\n");
   fprintf(output, "0.0 --RangeImportance //Exponent on the effect of geographic range on extinction. 0.0 = no effect.\n");
   fprintf(output, "0.0 --ExtinctionPulseFreuency //Frequency of elevated extinction timesteps. 0.0 = no effect.\n");
   fprintf(output, "1.0 --ExtinctionPulseIntensity //Intensity of extinction pulses. 1.0 = extinctions have no effect.\n");
   fprintf(output, "1.0 --ExtinctionPulsePollinationSelectivity //Selectivity of extinction pulses. 1.0 = no effect; >1 means animal pollination suffers more severe extinction.\n");
   fprintf(output, "1.0 --ExtinctionPulseDispersalSelectivity //Selectivity of extinction pulses. 1.0 = no effect; >1 means animal dispersal suffers more severe extinction.\n");
   fprintf(output, "1.0 --TransitionRate; //Intrinsic rate of transitions (C to T, T to C, A to G, G to A), as per a Kimura two-parameter evolutionary model\n");
   fprintf(output, "1.0 --TransversionRate; //Intrinsic rate of transversions (A to C, C to G, G to T, T to A, C to A, G to C, T to G, A to T), as per a Kimura two-parameter evolutionary model\n");
   fprintf(output, "1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0");
   fprintf(output, " --Rates of character state transitions during speciation ; first and second indicies represent the state changing from, the third and fourth the state changing to;");
   fprintf(output, " first and third are pollination, second and fourth are dispersal; 0 in all cases is wind-, and 1 is animal-. This configuration generates no character evolution.\n");
   fprintf(output, "1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0");
   fprintf(output, " --Rates of character state transitions during background evolution; mechanics are the same as for speciation, but happen when a species already exists.");
   fprintf(output, "1.0 1.0 --CladePollinationImportance[2]; //Multiplication constant on the rates of state changes TO wind (0) or animal (1) pollination.\n");
   fprintf(output, "1.0 1.0 --CladeDispersalImportance[2]; //Exactly the same as above, but for dispersal; ");
   fprintf(output, "clade tendency has no effect if this constant is 1.0, but has a stronger positive effect if > 1.0. Clades will actually move AWAY from their 'preferred' type if < 1.0.\n");
   fprintf(output, "0 --MaxSpecies; //If the simulation reaches this number of species, terminate. Ignored if 0.\n");
   fprintf(output, "0 --MaxClades; //If the simulation reaches this number of clades, terminate. Ignored if 0.\n");
   fprintf(output, "1024 --MaxTimesteps; //When the simulation has run for this number of timesteps, terminate. Ignored if 0 (not recommended, as it may run on forever).\n");
   fprintf(output, "1.0 --MaxSpeciesExtinction; //When this proportion of the total number of species that have become extinct reaches this value, terminate.\n");
   fprintf(output, "1.0 --MaxCladeExtinction; //As above, but for clades.\n");
   fprintf(output, "\n\nOnly the numbers at the beginning of each line before the hyphens are actually necessary; everything else is comments. Hyphens do not create comments, however;");
   fprintf(output, " including hyphenated comments will cause the program to abort and print this file (the position of the numbers in each line is what matters). Similarly, the program does not");
   fprintf(output, " read after the MaxCladeExtinction variable, so additional comments can be put here without aborting the program.\n");
   fprintf(output, "\nBe advised, however: rates of speciation, extinction, and evolution input into this model are not the actual rates (the true rates are modified by range, pollination, dispersal, and time, as determined by other parameters above).\n");
   fflush(output);
   exit(1);
}


void Extinction(int species)
{
   Lineages[species].extant = 0;
   //printf("Species %d of clade %d (%s) has become extinct.\n", species, Lineages[species].highertaxon, Classes[Lineages[species].highertaxon].Name);
   Speciesextinct++;
}


int FindExtantDescendentSpecies(int ancestorspecies)
{
   int i, targetspecies;
   
   if (Lineages[ancestorspecies].extant)
      return ancestorspecies;
   else
   {
      for (i = 0; i < Lineages[ancestorspecies].numdescendents; i++)
      {
         targetspecies = FindExtantDescendentSpecies(Lineages[ancestorspecies].Descendents[i]);
         if (targetspecies >= 0)
            return targetspecies;
      }
      
      return -1;
   }
}


void GenerateDiversityCurves(int *truediversity)
{
   int i, j, k, origindate;
   int *treediversity;
   
   treediversity = calloc(Timestep, sizeof(int));
   
   fprintf(diversitycurve, "Timestep\tTrue diversity\tTree diversity");
   
   for (i = 0; i < Timestep; i++) //Cycle through each timestep to generate the diversity curve.
   {
      //Housekeeping: no species yet ancestral to anything in this timestep.
      for (j = 0; j < Speciescount; j++)
         Lineages[j].currentlyancestral = 0;
      
      for (j = 0; j < Speciescount; j++) //Cycle through each species to find who is extant.
      {
         if (Lineages[j].extant) //Species that are extant, loop back and find the ancestor.
         {
            for (k = j; k >= 0; k = Lineages[k].ancestor)
            {
               origindate = Timestep - Lineages[k].speciesage; //Origindate is the timestep in which the ancestor species speciated.
               //If i >= origindate, then the species was in existence by timestep i, so this was the species in our lineages through time plot.
               if (i >= origindate)
               {
                  Lineages[k].currentlyancestral = 1; //Set it as an ancestor (it may already be from another living descendent).
                  break;
               }
            }
         }
      }
      
      //Now, we generate the original diversity curve data for timestep i (need truediversity from outside);
      for (j = 0; j < Speciescount; j++)
         treediversity[i] += Lineages[j].currentlyancestral;
      
      //Print out the table
      fprintf(diversitycurve, "\n%d\t%d\t%d", i, truediversity[i], treediversity[i]);
   }
   
   fflush(diversitycurve);
}


double GetRandomFloat(double randommax)
{
   double random = drand48() * randommax;
   return random;
}


int GetRandomInt(int randommax)
{
   int random = GetRandomFloat(randommax);
   return random;
}


void IdentifyExtinctClades(int cladenumber)
{
   int i, cladeextant = 0;
   
   if (Classes[cladenumber].extant == 0) //Already extinct
      return;
   
   for (i = 0; i < Classes[cladenumber].diversity; i++)
      cladeextant += Lineages[Classes[cladenumber].specieslist[i]].extant;
   
   if (cladeextant == 0)
   {
      //printf("Clade %d (%s) has become extinct in timestep %d!\n", cladenumber, Classes[cladenumber].Name, Timestep);
      Classes[cladenumber].extant = 0;
   }
   else
   {
      printf("In timestep %d, ", Timestep);
      printf("clade %d ", cladenumber);
      printf("(%s) ", Classes[cladenumber].Name);
      printf("comprises %d species.\n", cladeextant);
   }
}


void InitializeStartingClade(char *CharacterLine)
{
   int i, randomint, diversity;
   
   if ((CurrentMaxClades - Classcount) == 0)
   {
      CurrentMaxClades += STARTINGCLADES;
      Classes = (clade*) realloc(Classes, CurrentMaxClades * sizeof(clade));
   }
   
   Classes[Classcount].index = Classcount;
   Classes[Classcount].ancestor = -1; //Signifies that the clade is initial
   Classes[Classcount].ancestorclade = -1; //Also signifies that clade is initial
   Classes[Classcount].extant = 1;
   
   for (i = 0; CharacterLine[i] != ' '; i++)
      Classes[Classcount].Name[i] = CharacterLine[i];
   Classes[Classcount].Name[i] = '\0';
   
   Classes[Classcount].extinction = NthWordFloat(1, CharacterLine);
   Classes[Classcount].speciation = NthWordFloat(2, CharacterLine); //Note: speciation and extinction for initialized species does NOT account for dispersal or pollination!
   Classes[Classcount].evolution = NthWordFloat(3, CharacterLine);
   Classes[Classcount].cladogenesis = NthWordFloat(4, CharacterLine);
   Classes[Classcount].age = 0;
   Classes[Classcount].pollinationtendency = NthWordInt(5, CharacterLine);
   Classes[Classcount].dispersaltendency = NthWordInt(6, CharacterLine);
   Classes[Classcount].rangetendency = NthWordFloat(7, CharacterLine);
   
   //Now, add species
   diversity = NthWordInt(8, CharacterLine);
   if (diversity == 0)
   {
      fprintf(stderr, "Error: clade %d, %s, has been coded as extinct upon initialization! Not much evolution in an already extinct clade...\n", Classes[Classcount].index, Classes[Classcount].Name);
      Classes[Classcount].extant = 0;
      Cladesextinct++;
      return;
   }
   else
   {
      if ((CurrentMaxSpecies - Speciescount) == 0)
      {
         CurrentMaxSpecies += STARTINGSPECIES;
         Lineages = (species*) realloc(Lineages, CurrentMaxSpecies * sizeof(species));
      }
      
      Classes[Classcount].specieslist[0] = Speciescount;
      Classes[Classcount].diversity++;
      Classes[Classcount].standingdiversity++;
      Lineages[Speciescount].index = Speciescount;
      Lineages[Speciescount].ancestor = -1;
      Lineages[Speciescount].extant = 1;
      Lineages[Speciescount].extinction = Classes[Classcount].extinction;
      Lineages[Speciescount].speciation = Classes[Classcount].speciation;
      Lineages[Speciescount].evolution = Classes[Classcount].evolution;
      Lineages[Speciescount].speciesage = 0;
      Lineages[Speciescount].highertaxon = Classcount;
      Lineages[Speciescount].pollination = Classes[Classcount].pollinationtendency;
      Lineages[Speciescount].dispersal = Classes[Classcount].dispersaltendency;
      Lineages[Speciescount].range = GetRandomFloat(Classes[Classcount].rangetendency);
      Lineages[Speciescount].couplet = -1;
      
      for (i = 0; i < SEQUENCELENGTH; i++)
      {
         randomint = GetRandomInt(4);
         if (randomint == 0)
            Lineages[Speciescount].Sequence[i] = 'A';
         else if (randomint == 1)
            Lineages[Speciescount].Sequence[i] = 'C';
         else if (randomint == 2)
            Lineages[Speciescount].Sequence[i] = 'G';
         else
            Lineages[Speciescount].Sequence[i] = 'T';
      }
      
      Speciescount++;
      
      for (i = 1; i < diversity; i++)
         Speciate(Classes[Classcount].specieslist[GetRandomInt(Classes[Classcount].diversity)]);
   }
}



float NthWordFloat(int wordnumber, char *Line)
{
   int i, wordlength, countdown;
   char NewWord[MAXLINELENGTH];
   char *bad = 0;
   float targetvalue;
   
   for (i = 0, wordlength = 0, countdown = wordnumber; countdown >= 0; i++)
   {
      if (Line[i] == ' ')
         countdown--;
      else if ((Line[i] == '\n') || (Line[i] == '\0'))
      {
         if (countdown == 0)
            break;
         else
         {
            sprintf(NewWord, "End of line reached finding Nth word in line, word %d", wordnumber);
            ExitBadModel(Line, NewWord);
         }
      }
      else if (countdown == 0)
      {
         NewWord[wordlength] = Line[i];
         wordlength++;
      }
   }
   NewWord[wordlength] = '\0';
   
   targetvalue = strtod(NewWord, &bad);
   if (*bad)
      ExitBadModel(NewWord, "Bad floating point number");
   else
      return targetvalue;
}


int NthWordInt(int wordnumber, char *Line)
{
   int i, wordlength, countdown, targetvalue;
   char NewWord[MAXLINELENGTH];
   char *bad = 0;
   
   for (i = 0, wordlength = 0, countdown = wordnumber; countdown >= 0; i++)
   {
      if (Line[i] == ' ')
         countdown--;
      else if ((Line[i] == '\n') || (Line[i] == '\0'))
      {
         if (countdown == 0)
            break;
         else
         {
            sprintf(NewWord, "End of line reached finding Nth word in line, word %d", wordnumber);
            ExitBadModel(Line, NewWord);
         }
      }
      else if (countdown == 0)
      {
         NewWord[wordlength] = Line[i];
         wordlength++;
      }
   }
   NewWord[wordlength] = '\0';
   
   targetvalue = strtol(NewWord, &bad, 10);
   if (*bad)
      ExitBadModel(NewWord, "Bad integer");
   else
      return targetvalue;
}


int RecursiveBuildTreeFromSpecies(int focalspecies)
{
   int i, firstspecies, secondspecies, firstcouplet, secondcouplet, targetspecies;
   
   firstcouplet = -1;
   secondcouplet = -1;
   firstspecies = -1;
   secondspecies = -1;
   for (i = Lineages[focalspecies].numdescendents - 1; i >= 0; i--)
   {
      targetspecies = Lineages[focalspecies].Descendents[i];
      
      if (firstcouplet < 0)
         firstcouplet = RecursiveBuildTreeFromSpecies(targetspecies);
      else
         secondcouplet = RecursiveBuildTreeFromSpecies(targetspecies);
      //There will be no uncoupled extant species from the descentent if there are more than one living descendents.
      //This will only return -1 if there are either no living descendents or if there is only one.
      //FindExtantDescendentSpecies will find the one survivor (it will find *a* survivor if there are more than one, so we don't want to use it unless we're sure there are only one or zero).
      
      if (firstcouplet >= 0)
      {
         if (Lineages[focalspecies].extant && (Lineages[focalspecies].couplet < 0))
            firstcouplet = DefineCouplet(firstcouplet, 1, focalspecies, 0, Lineages[targetspecies].speciesage);
         else if (secondcouplet >= 0)
         {
            firstcouplet = DefineCouplet(firstcouplet, 1, secondcouplet, 1, Lineages[targetspecies].speciesage);
            secondcouplet = -1;
         }
         else if (firstspecies >= 0)
         {
            if (Lineages[firstspecies].couplet < 0)
            {
               firstcouplet = DefineCouplet(firstcouplet, 1, firstspecies, 0, Lineages[targetspecies].speciesage);
               firstspecies = -1;
            }
         }
         else
         {
            firstspecies = FindExtantDescendentSpecies(targetspecies);
            if (firstspecies >= 0)
            {
               if (Lineages[firstspecies].couplet < 0)
               {
                  firstcouplet = DefineCouplet(firstcouplet, 1, firstspecies, 0, Lineages[targetspecies].speciesage);
                  firstspecies = -1;
               }
               else
                  firstspecies = -1;
            }
         }
      }
      else if (firstspecies < 0)
         firstspecies = FindExtantDescendentSpecies(targetspecies);
      else
         secondspecies = FindExtantDescendentSpecies(targetspecies);
      
      if (firstcouplet < 0)
      {
         if (Lineages[focalspecies].extant && (Lineages[focalspecies].couplet < 0) && (firstspecies >= 0))
         {
            if (Lineages[firstspecies].couplet < 0)
            {
               firstcouplet = DefineCouplet(firstspecies, 0, focalspecies, 0, Lineages[firstspecies].speciesage);
               firstspecies = -1;
            }
            else
               firstspecies = -1;
         }
         if ((secondspecies >= 0) && (firstspecies >= 0))
         {
            if ((Lineages[secondspecies].couplet < 0) && (Lineages[firstspecies].couplet < 0))
            {
               firstcouplet = DefineCouplet(firstspecies, 0, secondspecies, 0, Lineages[targetspecies].speciesage);
               firstspecies = -1;
               secondspecies = -1;
            }
            else
            {
               if (Lineages[secondspecies].couplet >= 0)
                  secondspecies = -1;
               else
                  firstspecies = -1;
            }
         }
      }
   }
   
   return firstcouplet;
}


void SequenceEvolution(int species)
{
   int i;
   for (i = 0; i < SEQUENCELENGTH; i++)
   {
      if (GetRandomFloat(1) < TransversionRate)
      {
         if ((Lineages[species].Sequence[i] == 'A') || (Lineages[species].Sequence[i] == 'G'))
         {
            if (GetRandomInt(2))
               Lineages[species].Sequence[i] = 'C';
            else
               Lineages[species].Sequence[i] = 'T';
         }
         else
         {
            if (GetRandomInt(2))
               Lineages[species].Sequence[i] = 'A';
            else
               Lineages[species].Sequence[i] = 'G';
         }
      }
      else if (GetRandomFloat(1) < TransitionRate)
      {
         if (Lineages[species].Sequence[i] == 'A')
            Lineages[species].Sequence[i] = 'G';
         else if (Lineages[species].Sequence[i] == 'C')
            Lineages[species].Sequence[i] = 'T';
         else if (Lineages[species].Sequence[i] == 'G')
            Lineages[species].Sequence[i] = 'A';
         else
            Lineages[species].Sequence[i] = 'C';
      }
   }
}


void Speciate(int ancestor)
{
   int highertaxon = Lineages[ancestor].highertaxon;
   float nonectarnofruit, nonectarfruit, nectarnofruit, nectarfruit, randomstate;
   
   
   //Determine highertaxon
   if (Classes[highertaxon].diversity == SPECIESPERCLADE)
   {
      Cladogenesis(ancestor, 0, 0); //0 and 0 mean no more than usual chance of character state changes
      return;
   }
   
   if ((CurrentMaxSpecies - Speciescount) == 0)
   {
      CurrentMaxSpecies += STARTINGSPECIES;
      Lineages = (species*) realloc(Lineages, CurrentMaxSpecies * sizeof(species));
   }
   
   
   //Note this function only speciates new species, not new clades. Use Cladogenesis for that.
   Lineages[Speciescount].index = Speciescount;
   Lineages[Speciescount].ancestor = ancestor;
   Lineages[Speciescount].extant = 1;
   //Come back to evolution, extinction, and speciation; they're complicated.
   Lineages[Speciescount].speciesage = 0;
   Lineages[Speciescount].highertaxon = highertaxon;
   Classes[highertaxon].specieslist[Classes[highertaxon].diversity] = Speciescount;
   Classes[highertaxon].diversity++;
   Classes[Classcount].standingdiversity++;
   
   if (Timestep > 0)
   {
      //printf("Species %d originated of clade %s, timestep %d.\n", Speciescount, Classes[highertaxon].Name, Timestep);
      Lineages[Speciescount].range = GetRandomFloat(Lineages[ancestor].range); //New species have small ranges
      Lineages[ancestor].range -= GetRandomFloat(Lineages[Speciescount].range); //But they take a chunk out of the original species range.
   }
   else
      Lineages[Speciescount].range = GetRandomFloat(Classes[highertaxon].rangetendency);
   
   
   //Now, character evolution
   nonectarnofruit = SpeciationStateChangeRates[Lineages[ancestor].pollination][Lineages[ancestor].dispersal][0][0];
   nectarnofruit = SpeciationStateChangeRates[Lineages[ancestor].pollination][Lineages[ancestor].dispersal][1][0];
   nonectarfruit = SpeciationStateChangeRates[Lineages[ancestor].pollination][Lineages[ancestor].dispersal][0][1];
   nectarfruit = SpeciationStateChangeRates[Lineages[ancestor].pollination][Lineages[ancestor].dispersal][1][1];
   
   if (Classes[highertaxon].pollinationtendency == 0)
   {
      nonectarnofruit *= CladePollinationImportance[0];
      nonectarfruit *= CladePollinationImportance[0];
   }
   else
   {
      nectarnofruit *= CladePollinationImportance[1];
      nectarfruit *= CladePollinationImportance[1];
   }
   if (Classes[highertaxon].dispersaltendency == 0)
   {
      nonectarnofruit *= CladeDispersalImportance[0];
      nectarnofruit *= CladeDispersalImportance[0];
   }
   else
   {
      nonectarfruit *= CladeDispersalImportance[1];
      nectarfruit *= CladeDispersalImportance[1];
   }
   
   randomstate = GetRandomFloat(nonectarnofruit + nonectarfruit + nectarnofruit + nectarfruit);
   if (randomstate < nonectarnofruit)
   {
      Lineages[Speciescount].pollination = 0;
      Lineages[Speciescount].dispersal = 0;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit))
   {
      Lineages[Speciescount].pollination = 0;
      Lineages[Speciescount].dispersal = 1;
   }
   else if (randomstate < (nonectarnofruit + nonectarfruit + nectarnofruit))
   {
      Lineages[Speciescount].pollination = 1;
      Lineages[Speciescount].dispersal = 0;
   }
   else
   {
      Lineages[Speciescount].pollination = 1;
      Lineages[Speciescount].dispersal = 1;
   }
   
   
   strcpy(Lineages[Speciescount].Sequence, Lineages[ancestor].Sequence); //At separation, two lineages share identical sequence.
   
   Lineages[Speciescount].evolution = Lineages[ancestor].evolution;
   Lineages[Speciescount].speciation = Lineages[ancestor].speciation;
   Lineages[Speciescount].extinction = Lineages[ancestor].extinction;
   
   
   //Manage clades
   if (Lineages[ancestor].numdescendents == 0)
      Lineages[ancestor].Descendents = calloc(256, sizeof(int));
   else if ((Lineages[ancestor].numdescendents % 256) == 0)
      Lineages[ancestor].Descendents = realloc(Lineages[ancestor].Descendents, (Lineages[ancestor].numdescendents + 256) * sizeof(int));
   Lineages[ancestor].Descendents[Lineages[ancestor].numdescendents] = Speciescount;
   Lineages[ancestor].numdescendents++;
   Lineages[Speciescount].numdescendents = 0;
   Lineages[Speciescount].couplet = -1;
   
   Speciescount++;
}