5 * Created by Alyssa Milburn on Sat 13 Nov 2004.
6 * Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "streamutils.h"
25 geneNote
*genomeFile::findNote(uint8 type
, uint8 subtype
, uint8 which
) {
26 for (vector
<gene
*>::iterator x
= genes
.begin(); x
!= genes
.end(); x
++) {
28 if ((uint8
)t
->type() == type
)
29 if ((uint8
)t
->subtype() == subtype
)
30 if ((uint8
)t
->note
.which
== which
)
33 if (typeid(*t
) == typeid(organGene
))
34 for (vector
<gene
*>::iterator y
= ((organGene
*)t
)->genes
.begin(); y
!= ((organGene
*)t
)->genes
.end(); y
++) {
36 if ((uint8
)s
->type() == type
)
37 if ((uint8
)s
->subtype() == subtype
)
38 if ((uint8
)s
->note
.which
== which
)
46 void genomeFile::readNotes(istream
&s
) {
48 uint16 gnover
= read16(s
);
49 uint16 nosvnotes
= read16(s
);
50 std::cout
<< "we have " << nosvnotes
<< " notes" << std::endl
;
52 for (int i
= 0; i
< nosvnotes
; i
++) {
53 uint16 type
= read16(s
);
54 uint16 subtype
= read16(s
);
55 uint16 which
= read16(s
);
56 uint16 rule
= read16(s
);
58 // TODO: we currently skip all the notes (note that there are 18 and then 1!)
59 for (int i
= 0; i
< 19; i
++) {
60 uint16 skip
= read16(s
);
61 uint8
*dummy
= new uint8
[skip
]; s
.read((char *)dummy
, skip
); delete[] dummy
;
68 if (s
.fail() || s
.eof()) throw genomeException("c3 gno loading broke ... second magic not present");
73 uint16 noentries
= read16(s
);
75 for (int i
= 0; i
< noentries
; i
++) {
76 uint16 type
= read16(s
);
77 uint16 subtype
= read16(s
);
78 uint32 which
= read32(s
);
80 geneNote
*n
= findNote(type
, subtype
, which
);
82 uint16 buflen
= read16(s
);
83 char *buffer
= new char[buflen
+ 1];
84 s
.read(buffer
, buflen
); buffer
[buflen
] = 0;
85 if (n
!= 0) n
->description
= buffer
;
87 delete[] buffer
; buffer
= new char[buflen
+ 1];
88 s
.read(buffer
, buflen
); buffer
[buflen
] = 0;
89 if (n
!= 0) n
->comments
= buffer
;
94 void genomeFile::writeNotes(ostream
&s
) const {
98 gene
*genomeFile::nextGene(istream
&s
) {
100 s
.read((char *)majic
, 3);
101 if (strncmp((char *)majic
, "gen", 3) != 0) throw genomeException("bad majic for a gene");
104 if (majic
[0] == 'd') return 0;
106 throw genomeException("bad majic at stage2 for a gene");
109 s
>> type
>> subtype
;
113 // the switch statement of doom... is there a better way to do this?
119 case 1: g
= new oldBrainLobeGene(cversion
); break;
120 case 2: g
= new oldBrainLobeGene(cversion
); break;
121 case 3: g
= new c2eBrainLobeGene(cversion
); break;
122 default: g
= 0; break;
124 case 1: g
= new organGene(cversion
, true); break;
125 case 2: g
= new c2eBrainTractGene(cversion
); break;
129 case 0: g
= new bioReceptorGene(cversion
); break;
130 case 1: g
= new bioEmitterGene(cversion
); break;
131 case 2: g
= new bioReactionGene(cversion
); break;
132 case 3: g
= new bioHalfLivesGene(cversion
); break;
133 case 4: g
= new bioInitialConcentrationGene(cversion
); break;
134 case 5: g
= new bioNeuroEmitterGene(cversion
); break;
138 case 0: g
= new creatureStimulusGene(cversion
); break;
139 case 1: g
= new creatureGenusGene(cversion
); break;
140 case 2: g
= new creatureAppearanceGene(cversion
); break;
141 case 3: g
= new creaturePoseGene(cversion
); break;
142 case 4: g
= new creatureGaitGene(cversion
); break;
143 case 5: g
= new creatureInstinctGene(cversion
); break;
144 case 6: g
= new creaturePigmentGene(cversion
); break;
145 case 7: g
= new creaturePigmentBleedGene(cversion
); break;
146 case 8: g
= new creatureFacialExpressionGene(cversion
); break;
150 case 0: g
= new organGene(cversion
, false); break;
154 if (g
== 0) throw genomeException("genefactory failed");
156 if (((typeid(*g
) == typeid(bioReactionGene
))
157 || (typeid(*g
) == typeid(bioEmitterGene
)))
158 || (typeid(*g
) == typeid(bioReceptorGene
))) {
159 if (currorgan
== 0) {
160 if (cversion
== 1) genes
.push_back(g
); // Creatures 1 doesn't have organs
161 else throw genomeException("reaction/emitter/receptor without an attached organ");
162 } else currorgan
->genes
.push_back(g
);
165 if (typeid(*g
) == typeid(organGene
))
166 if (!((organGene
*)g
)->isBrain())
167 currorgan
= (organGene
*)g
;
175 istream
&operator >> (istream
&s
, genomeFile
&f
) {
176 char majic
[3]; s
.read(majic
, 3);
177 if (strncmp((char *)majic
, "gen", 3) == 0) {
179 if (majic
[0] == 'e') f
.cversion
= 1;
180 else throw genomeException("bad majic for genome");
182 s
.seekg(0, std::ios::beg
);
184 if (strncmp((char *)majic
, "dna", 3) != 0) throw genomeException("bad majic for genome");
187 f
.cversion
= majic
[0] - 48; // 48 = ASCII '0'
188 if ((f
.cversion
< 1) || (f
.cversion
> 3)) throw genomeException("unsupported genome version in majic");
191 //std::cout << "creaturesGenomeFile: reading genome of version " << (unsigned int)f.cversion << ".\n";
193 while (f
.nextGene(s
) != 0);
195 //std::cout << "creaturesGenomeFile: read " << (unsigned int)f.genes.size() << " top-level genes.\n";
200 ostream
&operator << (ostream
&s
, const genomeFile
&f
) {
201 s
<< "dna" << char(f
.cversion
+ 48); // 48 = ASCII '0'
203 // iterate through genes
204 for (vector
<gene
*>::iterator x
= ((genomeFile
&)f
).genes
.begin(); x
!= ((genomeFile
&)f
).genes
.end(); x
++)
212 gene
*genomeFile::getGene(uint8 type
, uint8 subtype
, unsigned int seq
) {
214 for (vector
<gene
*>::iterator i
= genes
.begin(); i
!= genes
.end(); i
++) {
215 if ((*i
)->type() == type
)
216 if ((*i
)->subtype() == subtype
) {
218 if (seq
== c
) return *i
;
225 uint8
geneFlags::operator () () const {
226 return ((_mutable
?1:0) + (dupable
?2:0) + (delable
?4:0) + (maleonly
?8:0) +
227 (femaleonly
?16:0) + (notexpressed
?32:0) + (reserved1
?64:0) + (reserved2
?128:0));
230 void geneFlags::operator () (uint8 f
) {
231 _mutable
= ((f
& 1) != 0);
232 dupable
= ((f
& 2) != 0);
233 delable
= ((f
& 4) != 0);
234 maleonly
= ((f
& 8) != 0);
235 femaleonly
= ((f
& 16) != 0);
236 notexpressed
= ((f
& 32) != 0);
237 reserved1
= ((f
& 64) != 0);
238 reserved2
= ((f
& 128) != 0);
241 ostream
&operator << (ostream
&s
, const gene
&g
) {
242 s
<< "gene" << g
.type() << g
.subtype();
244 s
<< g
.note
.which
<< g
.header
.generation
<< uint8(g
.header
.switchontime
) << g
.header
.flags();
245 if (g
.cversion
> 1) s
<< g
.header
.mutweighting
;
246 if (g
.cversion
== 3) s
<< g
.header
.variant
;
253 istream
&operator >> (istream
&s
, gene
&g
) {
255 s
>> g
.note
.which
>> g
.header
.generation
>> b
;
256 g
.header
.switchontime
= (lifestage
)b
;
259 if (g
.cversion
> 1) s
>> g
.header
.mutweighting
;
260 if (g
.cversion
== 3) s
>> g
.header
.variant
;
267 void bioEmitterGene::write(ostream
&s
) const {
268 s
<< organ
<< tissue
<< locus
<< chemical
<< threshold
<< rate
<< gain
;
269 uint8 flags
= (clear
?1:0) + (digital
?2:0) + (invert
?4:0);
273 void bioEmitterGene::read(istream
&s
) {
274 s
>> organ
>> tissue
>> locus
>> chemical
>> threshold
>> rate
>> gain
;
277 clear
= ((flags
& 1) != 0);
278 digital
= ((flags
& 2) != 0);
279 invert
= ((flags
& 4) != 0);
282 void bioHalfLivesGene::write(ostream
&s
) const {
283 for (int i
= 0; i
< 256; i
++) {
288 void bioHalfLivesGene::read(istream
&s
) {
289 for (int i
= 0; i
< 256; i
++) {
294 void bioInitialConcentrationGene::write(ostream
&s
) const {
295 s
<< chemical
<< quantity
;
298 void bioInitialConcentrationGene::read(istream
&s
) {
299 s
>> chemical
>> quantity
;
302 void bioNeuroEmitterGene::write(ostream
&s
) const {
303 for (int i
= 0; i
< 3; i
++) {
304 s
<< lobes
[i
] << neurons
[i
];
307 for (int i
= 0; i
< 4; i
++) {
308 s
<< chemical
[i
] << quantity
[i
];
312 void bioNeuroEmitterGene::read(istream
&s
) {
313 for (int i
= 0; i
< 3; i
++) {
314 s
>> lobes
[i
] >> neurons
[i
];
317 for (int i
= 0; i
< 4; i
++) {
318 s
>> chemical
[i
] >> quantity
[i
];
322 void bioReactionGene::write(ostream
&s
) const {
323 for (int i
= 0; i
< 4; i
++) {
331 void bioReactionGene::read(istream
&s
) {
332 for (int i
= 0; i
< 4; i
++) {
340 void bioReceptorGene::write(ostream
&s
) const {
341 s
<< organ
<< tissue
<< locus
<< chemical
<< threshold
<< nominal
<< gain
;
342 uint8 flags
= (inverted
?1:0) + (digital
?2:0);
346 void bioReceptorGene::read(istream
&s
) {
347 s
>> organ
>> tissue
>> locus
>> chemical
>> threshold
>> nominal
>> gain
;
350 inverted
= ((flags
& 1) != 0);
351 digital
= ((flags
& 2) != 0);
354 void c2eBrainLobeGene::write(ostream
&s
) const {
355 for (int i
= 0; i
< 4; i
++) s
<< id
[i
];
357 write16(s
, updatetime
, false);
358 write16(s
, x
, false);
359 write16(s
, y
, false);
361 s
<< width
<< height
;
362 s
<< red
<< green
<< blue
;
363 s
<< WTA
<< tissue
<< initrulealways
;
365 for (int i
= 0; i
< 7; i
++) s
<< spare
[i
];
366 for (int i
= 0; i
< 48; i
++) s
<< initialiserule
[i
];
367 for (int i
= 0; i
< 48; i
++) s
<< updaterule
[i
];
370 void c2eBrainLobeGene::read(istream
&s
) {
371 for (int i
= 0; i
< 4; i
++) s
>> id
[i
];
373 updatetime
= read16(s
, false);
374 x
= read16(s
, false);
375 y
= read16(s
, false);
377 s
>> width
>> height
;
378 s
>> red
>> green
>> blue
;
379 s
>> WTA
>> tissue
>> initrulealways
;
381 for (int i
= 0; i
< 7; i
++) s
>> spare
[i
];
382 for (int i
= 0; i
< 48; i
++) s
>> initialiserule
[i
];
383 for (int i
= 0; i
< 48; i
++) s
>> updaterule
[i
];
386 void c2eBrainTractGene::write(ostream
&s
) const {
387 write16(s
, updatetime
, false);
388 for (int i
= 0; i
< 4; i
++) s
<< srclobe
[i
];
389 write16(s
, srclobe_lowerbound
, false);
390 write16(s
, srclobe_upperbound
, false);
391 write16(s
, src_noconnections
, false);
392 for (int i
= 0; i
< 4; i
++) s
<< destlobe
[i
];
393 write16(s
, destlobe_lowerbound
, false);
394 write16(s
, destlobe_upperbound
, false);
395 write16(s
, dest_noconnections
, false);
396 s
<< migrates
<< norandomconnections
<< srcvar
<< destvar
<< initrulealways
;
397 for (int i
= 0; i
< 5; i
++) s
<< spare
[i
];
398 for (int i
= 0; i
< 48; i
++) s
<< initialiserule
[i
];
399 for (int i
= 0; i
< 48; i
++) s
<< updaterule
[i
];
402 void c2eBrainTractGene::read(istream
&s
) {
403 updatetime
= read16(s
, false);
404 for (int i
= 0; i
< 4; i
++) s
>> srclobe
[i
];
405 srclobe_lowerbound
= read16(s
, false);
406 srclobe_upperbound
= read16(s
, false);
407 src_noconnections
= read16(s
, false);
408 for (int i
= 0; i
< 4; i
++) s
>> destlobe
[i
];
409 destlobe_lowerbound
= read16(s
, false);
410 destlobe_upperbound
= read16(s
, false);
411 dest_noconnections
= read16(s
, false);
412 s
>> migrates
>> norandomconnections
>> srcvar
>> destvar
>> initrulealways
;
413 for (int i
= 0; i
< 5; i
++) s
>> spare
[i
];
414 for (int i
= 0; i
< 48; i
++) s
>> initialiserule
[i
];
415 for (int i
= 0; i
< 48; i
++) s
>> updaterule
[i
];
418 void creatureAppearanceGene::write(ostream
&s
) const {
419 s
<< part
<< variant
;
420 if (cversion
> 1) s
<< species
;
423 void creatureAppearanceGene::read(istream
&s
) {
424 s
>> part
>> variant
;
425 if (cversion
> 1) s
>> species
;
428 void creatureFacialExpressionGene::write(ostream
&s
) const {
429 write16(s
, expressionno
);
432 for (int i
= 0; i
< 4; i
++) {
433 s
<< drives
[i
] << amounts
[i
];
437 void creatureFacialExpressionGene::read(istream
&s
) {
438 expressionno
= read16(s
);
441 for (int i
= 0; i
< 4; i
++) {
442 s
>> drives
[i
] >> amounts
[i
];
446 void creatureGaitGene::write(ostream
&s
) const {
449 for (int i
= 0; i
< gaitLength(); i
++) {
454 void creatureGaitGene::read(istream
&s
) {
457 for (int i
= 0; i
< gaitLength(); i
++) {
462 void creatureGenusGene::write(ostream
&s
) const {
467 // TODO: we read past the end of the returned buffer here!
469 for (int i
= 0; i
< ((cversion
== 3) ? 32 : 4); i
++) s
<< b
[i
];
471 for (int i
= 0; i
< ((cversion
== 3) ? 32 : 4); i
++) s
<< b
[i
];
474 void creatureGenusGene::read(istream
&s
) {
478 unsigned int len
= ((cversion
== 3) ? 32 : 4);
489 void creatureInstinctGene::write(ostream
&s
) const {
490 for (int i
= 0; i
< 3; i
++) {
491 s
<< lobes
[i
] << neurons
[i
];
499 void creatureInstinctGene::read(istream
&s
) {
500 for (int i
= 0; i
< 3; i
++) {
501 s
>> lobes
[i
] >> neurons
[i
];
509 void creaturePigmentGene::write(ostream
&s
) const {
510 s
<< color
<< amount
;
513 void creaturePigmentGene::read(istream
&s
) {
514 s
>> color
>> amount
;
517 void creaturePigmentBleedGene::write(ostream
&s
) const {
518 s
<< rotation
<< swap
;
521 void creaturePigmentBleedGene::read(istream
&s
) {
522 s
>> rotation
>> swap
;
525 void creaturePoseGene::write(ostream
&s
) const {
528 for (int i
= 0; i
< poseLength(); i
++) {
533 void creaturePoseGene::read(istream
&s
) {
536 for (int i
= 0; i
< poseLength(); i
++) {
541 void creatureStimulusGene::write(ostream
&s
) const {
542 s
<< stim
<< significance
<< sensoryneuron
<< intensity
;
543 uint8 flags
= (modulate
?1:0) + (addoffset
?2:0) + (whenasleep
?4:0);
544 if (silent
[0]) flags
+= 16;
545 if (silent
[1]) flags
+= 32;
546 if (silent
[2]) flags
+= 64;
547 if (silent
[3]) flags
+= 128;
550 for (int i
= 0; i
< 4; i
++) {
551 s
<< drives
[i
] << amounts
[i
];
555 void creatureStimulusGene::read(istream
&s
) {
556 s
>> stim
>> significance
>> sensoryneuron
>> intensity
;
559 modulate
= ((flags
& 1) != 0);
560 addoffset
= ((flags
& 2) != 0);
561 whenasleep
= ((flags
& 4) != 0);
563 for (int i
= 0; i
< 4; i
++) {
564 s
>> drives
[i
] >> amounts
[i
];
567 silent
[0] = ((flags
& 16) != 0);
568 silent
[1] = ((flags
& 32) != 0);
569 silent
[2] = ((flags
& 64) != 0);
570 silent
[3] = ((flags
& 128) != 0);
573 void oldBrainLobeGene::write(ostream
&s
) const {
574 s
<< x
<< y
<< width
<< height
<< perceptflag
<< nominalthreshold
<< leakagerate
<< reststate
<< inputgain
;
575 s
.write((char *)staterule
, (cversion
== 1) ? 8 : 12);
578 s
<< dendrite1
<< dendrite2
;
581 void oldBrainLobeGene::read(istream
&s
) {
582 s
>> x
>> y
>> width
>> height
>> perceptflag
>> nominalthreshold
>> leakagerate
>> reststate
>> inputgain
;
583 s
.read((char *)staterule
, (cversion
== 1) ? 8 : 12);
586 s
>> dendrite1
>> dendrite2
;
589 void organGene::write(ostream
&s
) const {
590 s
<< clockrate
<< damagerate
<< lifeforce
<< biotickstart
<< atpdamagecoefficient
;
592 // iterate through children
593 for (vector
<gene
*>::iterator x
= ((organGene
*)this)->genes
.begin(); x
!= ((organGene
*)this)->genes
.end(); x
++)
597 void organGene::read(istream
&s
) {
598 s
>> clockrate
>> damagerate
>> lifeforce
>> biotickstart
>> atpdamagecoefficient
;
601 ostream
&operator << (ostream
&s
, const oldDendriteInfo
&i
) {
602 s
<< i
.srclobe
<< i
.min
<< i
.max
<< i
.spread
<< i
.fanout
<< i
.minLTW
<< i
.maxLTW
;
603 s
<< i
.minstr
<< i
.maxstr
<< i
.migrateflag
<< i
.relaxsuscept
<< i
.relaxSTW
<< i
.LTWgainrate
;
606 s
.write((char *)i
.strgainrule
, (i
.cversion
== 1) ? 8 : 12);
608 s
.write((char *)i
.strlossrule
, (i
.cversion
== 1) ? 8 : 12);
609 s
.write((char *)i
.susceptrule
, (i
.cversion
== 1) ? 8 : 12);
610 s
.write((char *)i
.relaxrule
, (i
.cversion
== 1) ? 8 : 12);
612 if (i
.cversion
== 2) {
613 s
.write((char *)i
.backproprule
, 12);
614 s
.write((char *)i
.forproprule
, 12);
620 istream
&operator >> (istream
&s
, oldDendriteInfo
&i
) {
621 s
>> i
.srclobe
>> i
.min
>> i
.max
>> i
.spread
>> i
.fanout
>> i
.minLTW
>> i
.maxLTW
;
622 s
>> i
.minstr
>> i
.maxstr
>> i
.migrateflag
>> i
.relaxsuscept
>> i
.relaxSTW
>> i
.LTWgainrate
;
625 s
.read((char *)i
.strgainrule
, (i
.cversion
== 1) ? 8 : 12);
627 s
.read((char *)i
.strlossrule
, (i
.cversion
== 1) ? 8 : 12);
628 s
.read((char *)i
.susceptrule
, (i
.cversion
== 1) ? 8 : 12);
629 s
.read((char *)i
.relaxrule
, (i
.cversion
== 1) ? 8 : 12);
631 if (i
.cversion
== 2) {
632 s
.read((char *)i
.backproprule
, 12);
633 s
.read((char *)i
.forproprule
, 12);