1 /* "Species" - a CoreWars evolver. Copyright (C) 2003 'Varfar'
2 *
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the Free
5 * Software Foundation; either version 1, or (at your option) any later
6 * version.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18 #include "inst_gen.hpp"
19
20 // concrete implementation headers
21 #include "inst_gen_weighted_random.hpp"
22 #include "inst_gen_markov.hpp"
23 #include "inst_gen_markov_2.hpp"
24
25 #include "opcode_branch_lookup.hpp"
26
27 #include "species.hpp"
28 #include "rand.hpp"
29
30 //#include <string.h>
31
32 /************ CInstGenerator implementation ****************************/
33
34 const char *CInstGenerator::IMPL_DESC[CInstGenerator::IMPL_LAST] = { "weighted_random","markov","markov_2" };
35
CInstGenerator()36 CInstGenerator::CInstGenerator() {
37 for(unsigned i=0; i<OPCODE_LAST; i++) {
38 _opcode_allowed[(OPCODE)i] = true; // assume it is
39 }
40 }
41
impl_desc(const CInstGenerator::IMPL type)42 const char *CInstGenerator::impl_desc(const CInstGenerator::IMPL type) {
43 if((type >= 0) && (type < IMPL_LAST))
44 return IMPL_DESC[type];
45 return 0; // bad
46 }
47
desc_to_impl(const char * desc)48 CInstGenerator::IMPL CInstGenerator::desc_to_impl(const char *desc) {
49 for(int i=0; i<IMPL_LAST; i++) {
50 if(strcasecmp(desc,IMPL_DESC[i])==0)
51 return (IMPL)i;
52 }
53 PANIC(MISC,"bad inst_gen type",NULL);
54 }
55
read_ini(INIFile & ini)56 CInstGenerator *CInstGenerator::read_ini(INIFile &ini) {
57 KeyValuePair *kvp;
58 CInstGenerator *ret;
59 // identify which implementation, based upon keywords
60 kvp = ini.get("inst_gen");
61 if(0 == kvp) PANIC(MISC,"inst_gen expected",NULL);
62 switch(desc_to_impl(kvp->getValueAsChar())) {
63 case MARKOV_2:
64 ret = new CInstGeneratorMarkov2();
65 break;
66 case WEIGHTED_RANDOM:
67 ret = new CInstGeneratorWeightedRandom();
68 break;
69 case MARKOV:
70 ret = new CInstGeneratorMarkov();
71 break;
72 default:
73 PANIC(MISC,kvp->getValueAsChar(),"inst_gen not yet supported");
74 }
75 ret->read_ini_impl(ini);
76 return ret;
77 }
78
read_override_ini(CInstGenerator * gen,INIFile & ini)79 CInstGenerator *CInstGenerator::read_override_ini(CInstGenerator *gen,INIFile &ini) {
80 KeyValuePair *kvp;
81 CInstGenerator *ret;
82 // identify which implementation, based upon keywords
83 kvp = ini.get("inst_gen");
84 if(0 == kvp) return gen; // nothing to do?
85 switch(desc_to_impl(kvp->getValueAsChar())) {
86 case MARKOV_2:
87 if(same_type(gen,ret)) {
88 ret = new CInstGeneratorMarkov2((CInstGeneratorMarkov2&)*gen);
89 ret->read_override_ini_impl(ini);
90 } else {
91 ret = new CInstGeneratorMarkov2();
92 ret->read_ini_impl(ini);
93 }
94 break;
95 case MARKOV:
96 if(same_type(gen,ret)) {
97 ret = new CInstGeneratorMarkov((CInstGeneratorMarkov&)*gen);
98 ret->read_override_ini_impl(ini);
99 } else {
100 ret = new CInstGeneratorMarkov();
101 ret->read_ini_impl(ini);
102 }
103 break;
104 case WEIGHTED_RANDOM:
105 if(same_type(gen,ret)) {
106 ret = new CInstGeneratorWeightedRandom((CInstGeneratorWeightedRandom&)*gen);
107 ret->read_override_ini_impl(ini);
108 } else {
109 ret = new CInstGeneratorWeightedRandom();
110 ret->read_ini_impl(ini);
111 }
112 break;
113 default:
114 PANIC(MISC,kvp->getValueAsChar(),"inst_gen not yet supported");
115 }
116 return ret;
117 }
118
generate_completely_random(insn_t & instruction) const119 void CInstGenerator::generate_completely_random(insn_t &instruction) const { // utility
120 OPCODE op;
121 do {
122 op = (OPCODE)CRand::irand(OPCODE_LAST);
123 } while(!opcode_allowed(op));
124 instruction.in = OP(op,CRand::irand(MODIFIER_LAST),CRand::irand(ADDRMODE_LAST),CRand::irand(ADDRMODE_LAST));
125 instruction.set_modifier(EFFECTIVE_MODIFIER(op,instruction.modifier()));
126 _chromosome->type()->operands()->rnd(instruction,COperand::A);
127 _chromosome->type()->operands()->rnd(instruction,COperand::B);
128 }
129
read_opcode_allowed(INIFile & ini)130 void CInstGenerator::read_opcode_allowed(INIFile &ini) {
131 for(unsigned i=0; i<OPCODE_LAST; i++) {
132 KeyValuePair *kvp = ini.get(MNEMONIC_OPCODE((OPCODE)i));
133 if(0 != kvp) {
134 _opcode_allowed[(OPCODE)i] = kvp->getValueAsBool(_opcode_allowed[(OPCODE)i]);
135 }
136 }
137 }
138
write_opcode_allowed(std::ostream & os,const CInstGenerator * parent) const139 void CInstGenerator::write_opcode_allowed(std::ostream &os,const CInstGenerator *parent) const {
140 for(unsigned i=0; i<OPCODE_LAST; i++) {
141 bool allowed = opcode_allowed((OPCODE)i);
142 if(0 != parent) allowed = (allowed == parent->opcode_allowed((OPCODE)i));
143 if(!allowed) {
144 os << MNEMONIC_OPCODE((OPCODE)i) << '=' << opcode_allowed((OPCODE)i) << std::endl;
145 }
146 }
147 }
148
149
150