1 
2 #ifndef SPECIES_HPP
3 #define SPECIES_HPP
4 
5 /* "Species" - a CoreWars evolver.  Copyright (C) 2003 'Varfar'
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 1, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 /**
23  * species.h
24  * (c) Will Sutton, 2002
25  * the main header, exposes global information about the simulation;
26  *
27  * taxonomic groups -- in descending order -- are Kingdom, Phylum, Class, Order, Family, Genus, Species
28  * more detailed classifications -- in descending order -- are:
29  * domain
30  *  superkingdom
31  *   kingdom*
32  *     subkingdom
33  *      superphylum
34  *       phylum* (plural phyla)
35  *        subphylum
36  *         infraphylum
37  *          subterphylum
38  *            superclass
39  *             class*
40  *              subclass
41  *               infraclass
42  *                subterclass
43  *                 supersection
44  *                  section
45  *                   subsection
46  *                    infrasection
47  *                     supercohort
48  *                      cohort
49  *                        subcohort
50  *                         infracohort
51  *                          subtercohort
52  *                           superorder
53  *                            order*
54  *                             suborder
55  *                              infraorder
56  *                               superfamily
57  *                                family*
58  *                                 subfamily
59  *                                  supertribe
60  *                                   tribe
61  *                                    subtribe
62  *                                     genus* (plural genera)
63  *                                      subgenus
64  *                                       superspecies
65  *                                        species* (plural species)
66  *                                         geographical race (synonym race, subspecies)
67  *
68  * in this simplified simulation, only a few are used:
69  *
70  * CKingdom: a collection of genera
71  * CGenus: a collection of species
72  * CSpecies: a collection of warriors
73  * CWarrior : a warrior
74  *
75  * CSpecies come in two flavours; evolving species, and 'benchmark' species that assist in directing evolution
76  * by weighing scores.  Both CSpecies and CWarriors can be queried as to whether they are 'evolving' or 'bench'.
77  * CSpecies and their CWarriors must have the same value for this 'evolving' flag.
78  **/
79 
80 /** global constants, expect compiler to treat this as #define **/
81 
82 static const bool
83 	verbose = false,		// lots of couts following program execution?
84 	silent = false,
85 	terse = !verbose && !silent,
86 	metrics = true,			// time fights to generate performance statistics?
87 	safety_checks = true;// double check the warriors/core for corruption?
88 
89 const int PROGRESS_MOD = 4;
90 extern int progress;
91 extern const char *progress_twiddle;
92 #ifdef SHOW_PROGRESS_TWIDDLE
93 	#define PROGRESS_TWIDDLE cout << progress_twiddle[progress++ % PROGRESS_MOD] << '\r' << flush;
94 #else
95 	#define PROGRESS_TWIDDLE
96 #endif
97 
98 /* forwards */
99 class CChromosomeType;
100 class CWarrior;
101 class CSpecies;
102 class CGenus;
103 class CKingdom;
104 class CResumeFile;
105 class CExecTrail;
106 
107 #include "hook.hpp"
108 #include "exhaust.hpp"
109 #include "rand.hpp"
110 #include "ini.hpp"
111 
112 #include "error.hpp"
113 #include "length.hpp"
114 #include "operand.hpp"
115 #include "fitness.hpp"
116 #include "inst_gen.hpp"
117 #include "reproduction.hpp"
118 
119 #include <iostream>
120 
121 #include <stdio.h>
122 
123 extern const float VERSION; // actually in kingdom.cpp
124 
125 #include "generation.hpp"
126 
127 #include "chromosome.hpp"
128 #include "warrior.hpp"
129 
130 class CSpecies: public CHookable {
131 	public:
132 		typedef unsigned int TUid;
133 		CSpecies(CGenus *genus,const std::string &name,const bool evolving); // create an empty species
134 		~CSpecies();
135 		void clear(); /* this will delete all warriors from this species */
name() const136 		std::string name() const { return _name; }
137 		void read_ini(INIFile &ini); /* expects to be in the correct section */
138 		void write_ini(std::ostream &os);
139 		void save();
is_evolving() const140 		bool is_evolving() const { return _evolving; }
is_bench() const141 		bool is_bench() const { return !_evolving; }
142 		int find(const CWarrior::TUid uid) const; // -1 if not found in this species
size() const143 		int size() const { return _num_warriors; }
num_warriors() const144 		int num_warriors() const { return size(); } /* returns a trivia number of warriors 'live' in this species at this time */
145 		void ready(); /* this will blank all fitness metrics preceeding the fighting of a species */
146 		int fight(CSpecies &enemy); /* this will actually do all the fights for a generation; returns number of rounds fought */
147 		CWarrior *selection(); /* this will do selection on all the warriors in this species; returns the best */
genus() const148 		CGenus *genus() const { return _genus; }
149 		CKingdom *kingdom() const;
fitness() const150 		CFitness *fitness() const { return _fitness; }
length() const151 		CLength *length() const { return _length; }
freq() const152 		CInstGenerator *freq() const { return _freq; }
operands() const153 		COperand *operands() const { return _operands; }
reproduction() const154 		CReproduction *reproduction() const { return _reproduction; }
exec_trail() const155 		CExecTrail *exec_trail() const { return _exec_trail; }
fitness_weighting() const156 		CFitness::NUM fitness_weighting() const { return _fitness_weighting; }
uid() const157 		TUid uid() const { return _uid; }
158 		CWarrior *warrior(const CWarrior::TUid uid) const; /* fetch a particular warrior from this species; NULL if not present */
num_chromosomes() const159 		unsigned int num_chromosomes() const { return _num_chromosomes; }
start_chromosome() const160 		unsigned int start_chromosome() const { return _start_chromosome; }
161 		CChromosomeType *chromosome(const unsigned int i) const;
162 	protected:
163 		TUid _uid;
164 		static TUid _uid_seq;
165 		CResumeFile *_resume;
166 		bool _resuming;
167 		CWarrior **_warrior, // warriors in this species
168 			**_next; // a holder while doing selection
169 		bool *_survives; // a flag to keep track of who survives during selection
170 		int _num_warriors;
171 		std::string _name;
172 		bool _evolving; /* immutable species are benchmarks only; they do not 'evolve' */
173 		CGenus *_genus; // parent
174 		CFitness *_fitness; // might be referencing CGenus::_fitness if not overriden
175 		CFitness::NUM _fitness_weighting; // a balance to magnify species with a small number of warriors
176 		static const CFitness::NUM DEFAULT_FITNESS_WEIGHTING;
177 		CLength *_length; // might be CGenus::_length if not overriden
178 		CInstGenerator *_freq; // might be CGenus::_freq if not overriden
179 		COperand *_operands; // might be CGenus::_operands if not overriden
180 		CReproduction *_reproduction; // might be CGenus::_reproduction if not overriden
181 		CExecTrail *_exec_trail; // might be null
182 		CFitness::NUM _min, _sum; // these variables are used in rnd() for selection; see scores(..)
183 		// subdivision of each warrior into chromosomes
184 		bool _auto_chromosome; // wasn't there any chromosomes defined for this species?
185 		unsigned int _num_chromosomes, _start_chromosome;
186 		CChromosomeType **_chromosome;
187 		/*	This returns a random warrior index based upon fitness */
188 		int rnd() const;
189 		/*	This returns the minimum and sum (adjusted relative to min) scores for this species;
190 			these are the numbers needed to do roulette selection of the warriors based upon fitness.
191 			The min is actually 1 less than the true min, so even the worst warriors have a small chance
192 			of being selected */
193 		int scores(CFitness::NUM &min,CFitness::NUM &sum) const; /* returns index of best too */
194 		/* this sorts the warriors into score order, best in 0 */
195 		void sort();
196 };
197 
198 #include "genus.hpp"
199 
200 //TODO: This seems to be a little bit back-to-front; we ought to pass a stream to a warrior and ask it to serialise?
201 
202 class CSpeciesFile {
203 	friend class CSpecies;
204 	public:
205 		CSpeciesFile(const std::string species,const CGeneration::NUM generation);
206 		CSpeciesFile(const CSpecies &species,const CGeneration::NUM generation);
207 		~CSpeciesFile();
filename() const208 		std::string const &filename() const { return _filename; }
209 	protected:
210 		CGeneration::NUM _num;
211 		FILE *_f;
212 		std::string _filename;
213 		void set_filename(const std::string name,const CGeneration::NUM generation);
214 		void open_file();
215 		typedef struct {
216 			enum { // plenty of room for more flags in future
217 				NONE = 0,
218 				HAS_INFO = 1,
219 				HAS_BENCH = 2
220 			};
221 			unsigned short int options;
222 			CWarrior::TUid uid,
223 				mother, father;
224 			CGeneration::NUM generation;
225 			unsigned int num_chromosomes, start;
226 		} HEADER;
227 		static const int MAX_INFO_LEN = 256;
228 		char _info[MAX_INFO_LEN];
229 		static const size_t
230 			_header_size = sizeof(HEADER),
231 			_insn_size = sizeof(insn_st);
232 		void writeWarrior(const CWarrior &warrior);
233 		void readWarrior(CWarrior &warrior);
234 };
235 
236 #include "kingdom.hpp"
237 
238 #endif // ifndef SPECIES_HPP
239 
240