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