2 #include "Simulation.hpp"
7 #include "../creature/Creature.hpp"
8 #include "../ui/string.hpp"
17 int Record::Update(creature::Creature &c, double value, double time) noexcept {
19 for (int i = 0; i < MAX; ++i) {
20 if (value > rank[i].value) {
29 for (int i = 0; i < MAX; ++i) {
30 if (rank[i].holder == &c) {
36 // move all below down by one
37 std::copy_backward(rank + found, rank + MAX - 1, rank + MAX);
38 } else if (found > previous) {
39 // better than last, but not an improvement
40 // this ensures only one slot occupied per creature
42 } else if (found < previous) {
43 // move all in between down by one
44 std::copy_backward(rank + found, rank + previous, rank + previous + 1);
47 rank[found].holder = &c;
48 rank[found].value = value;
49 rank[found].time = time;
53 std::string Record::ValueString(int i) const {
54 if (i < 0 || i >= MAX || !rank[i].holder) {
60 return ui::DecimalString(rank[i].value, 2);
62 return ui::LengthString(rank[i].value);
64 return ui::MassString(rank[i].value);
66 return ui::PercentageString(rank[i].value);
68 return ui::TimeString(rank[i].value);
72 Simulation::Simulation(app::Assets &assets)
81 records[0].name = "Age";
82 records[0].type = Record::TIME;
83 records[1].name = "Mass";
84 records[1].type = Record::MASS;
85 records[2].name = "Size";
86 records[2].type = Record::LENGTH;
87 records[3].name = "Strength";
88 records[4].name = "Stamina";
89 records[5].name = "Dexerty";
90 records[6].name = "Intelligence";
93 Simulation::~Simulation() {
94 for (auto c : alive) {
102 void Simulation::Tick(double dt) {
104 for (auto body : bodies) {
107 for (auto c : alive) {
112 void Simulation::AddBody(Body &b) {
113 b.SetSimulation(*this);
117 void Simulation::AddPlanet(Planet &p) {
122 void Simulation::AddSun(Sun &s) {
127 Planet &Simulation::PlanetByName(const std::string &name) {
128 for (auto &p : planets) {
129 if (p->Name() == name) {
133 throw std::runtime_error("planet named \"" + name + "\" not found");
136 void Simulation::SetAlive(creature::Creature *c) {
140 void Simulation::SetDead(creature::Creature *c) {
141 auto entry = std::find(alive.begin(), alive.end(), c);
142 if (entry != alive.end()) {
149 void Simulation::CheckRecords(creature::Creature &c) noexcept {
151 creature::Creature *prev = records[0].rank[0].holder;
152 int rank = records[0].Update(c, c.Age(), time);
153 if (rank == 0 && prev && prev != &c) {
154 LogRecord(records[0]);
158 creature::Creature *prev = records[1].rank[0].holder;
159 int rank = records[1].Update(c, c.Mass(), time);
160 if (rank == 0 && prev && prev != &c) {
161 LogRecord(records[1]);
165 creature::Creature *prev = records[2].rank[0].holder;
166 int rank = records[2].Update(c, c.Size(), time);
167 if (rank == 0 && prev && prev != &c) {
168 LogRecord(records[2]);
172 creature::Creature *prev = records[3].rank[0].holder;
173 int rank = records[3].Update(c, c.Strength(), time);
174 if (rank == 0 && prev && prev != &c) {
175 LogRecord(records[3]);
179 creature::Creature *prev = records[4].rank[0].holder;
180 int rank = records[4].Update(c, c.Stamina(), time);
181 if (rank == 0 && prev && prev != &c) {
182 LogRecord(records[4]);
186 creature::Creature *prev = records[5].rank[0].holder;
187 int rank = records[5].Update(c, c.Dexerty(), time);
188 if (rank == 0 && prev && prev != &c) {
189 LogRecord(records[5]);
193 creature::Creature *prev = records[6].rank[0].holder;
194 int rank = records[6].Update(c, c.Intelligence(), time);
195 if (rank == 0 && prev && prev != &c) {
196 LogRecord(records[6]);
201 void Simulation::LogRecord(const Record &r) {
202 Log() << "at age " << ui::TimeString(r.rank[0].holder->Age()) << " "
203 << r.rank[0].holder->Name() << " broke the " << r.name << " record of "
204 << r.ValueString(1) << " by " << r.rank[1].holder->Name()
205 << " (established " << ui::TimeString(r.rank[1].time) << ")" << std::endl;
208 std::ostream &Simulation::Log() {
209 return std::cout << '[' << ui::TimeString(Time()) << "] ";