1 
2 /* "Species" - a CoreWars evolver.  Copyright (C) 2003 'Varfar'
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 1, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #include "chromosome.hpp"
20 
21 using namespace std;
22 
23 /***** CChromosome class implementation *******************/
24 
25 /*** construction ***/
26 
CChromosome(CWarrior * warrior,const unsigned int idx,const unsigned int len)27 CChromosome::CChromosome(CWarrior *warrior,const unsigned int idx,const unsigned int len):
28 	_warrior(warrior), _idx(idx), _ofs(0), _len(len) {
29 	_type = _warrior->species()->chromosome(_idx);
30 	calc_ofs();
31 }
32 
33 /*** getters ***/
34 
code(unsigned i) const35 insn_t &CChromosome::code(unsigned i) const {
36 	if(safety_checks)
37 		if(i >= len())
38 			PANIC(MISC,"instruction index in chromosome is out of bounds",NULL);
39 	return warrior()->warrior_t::code[_ofs+i];
40 }
41 
is_start() const42 bool CChromosome::is_start() const {
43 	return (idx() == type()->species()->start_chromosome());
44 }
45 
start() const46 unsigned CChromosome::start() const { // returns MAXLENGTH if warrior start is not in this chromosome
47 	if((_ofs <= _warrior->start) && ((_ofs+_len) > _warrior->start))
48 		return (_warrior->start-_ofs);
49 	else
50 		return MAXLENGTH;
51 }
52 
53 /*** setters ***/
54 
set_len(const unsigned int len)55 void CChromosome::set_len(const unsigned int len) {
56 	_len = len;
57 	const unsigned int num = warrior()->species()->num_chromosomes();
58 	for(unsigned int i=idx()+1; i<num; i++) {
59 		warrior()->chromosome(i)->calc_ofs();
60 	}
61 	warrior()->calc_len();
62 }
63 
rnd_len()64 void CChromosome::rnd_len() {
65 	set_len(type()->length()->rnd()); // a random length within bounds
66 }
67 
clear()68 void CChromosome::clear() {
69 	for(unsigned int i=0; i<len(); i++) {
70 		code(i).invalidate();
71 	}
72 }
73 
set_start(const unsigned i)74 void CChromosome::set_start(const unsigned i) { // actually sets the appropriate stuff in the warrior
75 	if(safety_checks) {
76 		if(idx() != warrior()->species()->start_chromosome())
77 			PANIC(MISC,"cannot set start in wrong chromosome",NULL);
78 		if(i >= len())
79 			PANIC(MISC,"start is beyond end of chromosome",NULL);
80 	}
81 	warrior()->start = _ofs + i;
82 }
83 
check(const field_t coresize) const84 void CChromosome::check(const field_t coresize) const { // panics if not ok
85 	for(unsigned int i=0; i<len(); i++) {
86 		if(!code(i).valid(coresize))
87 			PANIC(MISC,"invalid code in chromosome",NULL);
88 	}
89 }
90 
91 /*** internal ***/
92 
calc_ofs()93 void CChromosome::calc_ofs() {
94 	// ALWAYS CALLED FORWARD!
95 	if(idx()>0) {
96 		CChromosome *prev = warrior()->chromosome(idx()-1);
97 		_ofs = prev->_ofs + prev->len();
98 	} else {
99 		_ofs = 0;
100 	}
101 	if(safety_checks)
102 		if(_ofs + len() > MAXLENGTH)
103 			PANIC(MISC,"combined length of chromosomes too long",NULL);
104 }
105 
106 /***** CChromosomeType class implementation ***************/
107 
108 /*** construction ***/
109 
init()110 void CChromosomeType::init() {
111 	_length = species()->length();
112 	_freq = species()->freq();
113 	_operands = species()->operands();
114 	_reproduction = species()->reproduction();
115 }
116 
CChromosomeType(CSpecies * species)117 CChromosomeType::CChromosomeType(CSpecies *species) { // create an auto-chromosome shim
118 	_species = species;
119 	init();
120 	_auto = true;
121 	_name = "auto";
122 }
123 
CChromosomeType(CSpecies * species,const char * name)124 CChromosomeType::CChromosomeType(CSpecies *species,const char *name) { // create a user-ready shim
125 	_species = species;
126 	init();
127 	_auto = false;
128 	_name = name;
129 }
130 
read_ini(INIFile & ini)131 void CChromosomeType::read_ini(INIFile &ini) {
132 	// anything to do?
133 	if(_auto)
134 		return;
135 	// seek in ini file
136 	if(!ini.seek(_name))
137 		PANIC(MISC,_name.c_str(),"section expected");
138 	// load some defaults; these might be overloaded
139 	_length = _length->read_override_ini(ini);
140 	_freq = CInstGenerator::read_override_ini(_freq,ini);
141 	_operands = COperand::read_override_ini(_operands,ini);
142 	_reproduction = _reproduction->read_override_ini(ini);
143 }
144 
write_ini(ostream & os)145 void CChromosomeType::write_ini(ostream &os) {
146 	// anything to do?
147 	if(_auto)
148 		return;
149 	// and write it
150 	os << '[' << _name << ']' << endl;
151 	_length->write_override_ini(os,species()->length());
152 	_freq->write_override_ini(os,species()->freq());
153 	_operands->write_override_ini(os,species()->operands());
154 	_reproduction->write_override_ini(os,species()->reproduction());
155 }
156 
157