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