add wraparound support to C2 physics
[openc2e.git] / historyManager.cpp
blob6850ec28cd7973c81a04e8cf0c4c2efdb1183f7a
1 /*
2 * historyManager.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Wed 26 Apr 2006.
6 * Copyright (c) 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 "historyManager.h"
21 #include "World.h"
22 #include "Catalogue.h"
23 #include "CreatureAgent.h"
24 #include "Creature.h"
25 #include "Engine.h" // version
27 #include <boost/format.hpp>
29 historyevent::historyevent(unsigned int eno, CreatureAgent *c) {
30 timestamp = time(NULL);
31 eventno = eno;
32 worldtick = world.tickcount;
33 // TODO: worldname = world.name;
34 // TODO: worldmoniker = world.moniker;
35 // TODO: networkid = world.username;
37 if (c) {
38 tage = c->getCreature()->getAge();
39 stage = c->getCreature()->getStage();
40 } else {
41 tage = -1;
42 stage = baby; // TODO: correct?
46 void monikerData::init(std::string m, shared_ptr<genomeFile> f) {
47 moniker = m;
48 status = unreferenced;
49 warpveteran = false;
50 variant = -1;
51 gender = -1;
52 no_crossover_points = 0;
53 no_point_mutations = 0;
55 assert(f);
56 genome = f;
58 for (vector<gene *>::iterator i = f->genes.begin(); i != f->genes.end(); i++) {
59 if (typeid(*(*i)) == typeid(creatureGenusGene)) {
60 // initialize genus
61 creatureGenusGene *g = (creatureGenusGene *)(*i);
62 genus = g->genus + 1;
63 break;
68 historyevent &monikerData::addEvent(unsigned int event, std::string moniker1, std::string moniker2) {
69 CreatureAgent *c = 0;
70 if (owner) c = dynamic_cast<CreatureAgent *>(owner.get());
72 events.push_back(historyevent(event, c));
73 events.back().monikers[0] = moniker1;
74 events.back().monikers[1] = moniker2;
76 for (std::list<boost::shared_ptr<Agent> >::iterator i = world.agents.begin(); i != world.agents.end(); i++) {
77 if (!*i) continue;
79 (*i)->queueScript(127, 0, moniker, (int)(events.size() - 1)); // new life event
82 return events.back();
85 void monikerData::moveToAgent(AgentRef a) {
86 assert(status == referenced || status == unreferenced);
88 owner = a;
89 if (!owner) {
90 status = unreferenced;
91 } else {
92 status = referenced;
96 void monikerData::moveToCreature(AgentRef a) {
97 moveToAgent(a);
99 CreatureAgent *c = dynamic_cast<CreatureAgent *>(owner.get());
100 assert(c);
101 status = creature;
104 void monikerData::wasBorn() {
105 assert(status == creature);
106 CreatureAgent *c = dynamic_cast<CreatureAgent *>(owner.get());
107 assert(c);
109 status = borncreature;
110 gender = (c->getCreature()->isFemale() ? 2 : 1);
111 variant = c->getCreature()->getVariant();
114 void monikerData::hasDied() {
115 CreatureAgent *c = dynamic_cast<CreatureAgent *>(owner.get());
116 assert(c);
118 // TODO
120 status = dead;
123 monikerstatus monikerData::getStatus() {
124 switch (status) {
125 case referenced:
126 case exported:
127 case unreferenced:
128 return status;
130 case creature:
131 case borncreature:
132 if (owner)
133 return status;
134 else
135 return deadandkilled; // we missed it?! TODO: what's correct behaviour here?
137 case dead:
138 if (owner)
139 return dead;
140 else
141 return deadandkilled;
143 default:
144 assert(false); // explode!
149 std::string historyManager::newMoniker(shared_ptr<genomeFile> genome) {
150 unsigned int genus = 0;
152 for (vector<gene *>::iterator i = genome->genes.begin(); i != genome->genes.end(); i++) {
153 if (typeid(*(*i)) == typeid(creatureGenusGene)) {
154 // initialize genus
155 creatureGenusGene *g = (creatureGenusGene *)(*i);
156 genus = g->genus + 1;
157 break;
161 std::string basename = "xxxx";
163 if (engine.version > 2) {
164 const std::vector<std::string> *extensions = 0;
165 std::string tagname = boost::str(boost::format("Moniker Friendly Names %i") % genus);
167 if (catalogue.hasTag(tagname)) {
168 extensions = &catalogue.getTag(tagname);
169 } else if (catalogue.hasTag("Moniker Friendly Names")) {
170 extensions = &catalogue.getTag("Moniker Friendly Names");
171 } else {
172 std::cout << "Warning: No \"Moniker Friendly Names\" in catalogue for genus " << genus <<
173 ", defaulting to 'xxxx' for a moniker friendly name." << std::endl;
176 if (extensions) {
177 unsigned int i = (int) (extensions->size() * (rand() / (RAND_MAX + 1.0)));
178 basename = (*extensions)[i];
182 std::string newmoniker = world.generateMoniker(basename);
183 unsigned int i = 0;
184 while (hasMoniker(newmoniker)) { // last-moment sanity check..
185 std::string newmoniker = world.generateMoniker(basename);
186 i++;
187 if (i > 100) // emergency "don't go into an infinite loop handling"
188 throw creaturesException("Couldn't generate a moniker we don't already have!");
191 if (engine.version > 2)
192 newmoniker = "001-" + newmoniker; // TODO: bad hack we should use the generation number here!
194 monikers[newmoniker].init(newmoniker, genome);
195 return newmoniker;
198 bool historyManager::hasMoniker(std::string s) {
199 std::map<std::string, monikerData>::iterator i = monikers.find(s);
200 if (i == monikers.end()) return false;
201 else return true;
204 monikerData &historyManager::getMoniker(std::string s) {
205 std::map<std::string, monikerData>::iterator i = monikers.find(s);
206 if (i == monikers.end()) throw creaturesException("getMoniker was called with a non-existant moniker");
207 return i->second;
210 std::string historyManager::findMoniker(shared_ptr<genomeFile> g) {
211 for (std::map<std::string, monikerData>::iterator i = monikers.begin(); i != monikers.end(); i++) {
212 if (i->second.genome.lock() == g) return i->first;
215 return "";
218 std::string historyManager::findMoniker(AgentRef a) {
219 for (std::map<std::string, monikerData>::iterator i = monikers.begin(); i != monikers.end(); i++) {
220 if (i->second.owner == a) return i->first;
223 return "";
226 void historyManager::delMoniker(std::string s) {
227 std::map<std::string, monikerData>::iterator i = monikers.find(s);
228 if (i == monikers.end()) throw creaturesException("getMoniker was called with a non-existant moniker");
229 monikers.erase(i);
232 /* vim: set noet: */