]> git.localhorst.tv Git - blobs.git/blob - src/world/sim.cpp
b23790dbef9a47d01eace54cb399d09f2d74c772
[blobs.git] / src / world / sim.cpp
1 #include "Record.hpp"
2 #include "Simulation.hpp"
3
4 #include "Body.hpp"
5 #include "Planet.hpp"
6 #include "Sun.hpp"
7 #include "../creature/Creature.hpp"
8 #include "../ui/string.hpp"
9
10 #include <algorithm>
11 #include <iostream>
12
13
14 namespace blobs {
15 namespace world {
16
17 std::string Record::ValueString() const {
18         switch (type) {
19                 default:
20                 case VALUE:
21                         return ui::DecimalString(value, 2);
22                 case LENGTH:
23                         return ui::LengthString(value);
24                 case MASS:
25                         return ui::MassString(value);
26                 case PERCENTAGE:
27                         return ui::PercentageString(value);
28                 case TIME:
29                         return ui::TimeString(value);
30         }
31 }
32
33 Simulation::Simulation(Body &r, app::Assets &assets)
34 : root(r)
35 , assets(assets)
36 , bodies()
37 , planets()
38 , suns()
39 , alive()
40 , dead()
41 , time(0.0)
42 , records(7) {
43         AddBody(r);
44         records[0].name = "Age";
45         records[0].type = Record::TIME;
46         records[1].name = "Mass";
47         records[1].type = Record::MASS;
48         records[2].name = "Size";
49         records[2].type = Record::LENGTH;
50         records[3].name = "Strength";
51         records[4].name = "Stamina";
52         records[5].name = "Dexerty";
53         records[6].name = "Intelligence";
54 }
55
56 Simulation::~Simulation() {
57         for (auto c : alive) {
58                 delete c;
59         }
60         for (auto c : dead) {
61                 delete c;
62         }
63 }
64
65 void Simulation::Tick(double dt) {
66         time += dt;
67         for (auto body : bodies) {
68                 body->Tick(dt);
69         }
70         for (auto c : alive) {
71                 CheckRecords(*c);
72         }
73 }
74
75 void Simulation::AddBody(Body &b) {
76         b.SetSimulation(*this);
77         bodies.insert(&b);
78 }
79
80 void Simulation::AddPlanet(Planet &p) {
81         AddBody(p);
82         planets.insert(&p);
83 }
84
85 void Simulation::AddSun(Sun &s) {
86         AddBody(s);
87         suns.insert(&s);
88 }
89
90 void Simulation::SetAlive(creature::Creature *c) {
91         alive.push_back(c);
92 }
93
94 void Simulation::SetDead(creature::Creature *c) {
95         auto entry = std::find(alive.begin(), alive.end(), c);
96         if (entry != alive.end()) {
97                 alive.erase(entry);
98         }
99         dead.push_back(c);
100         CheckRecords(*c);
101 }
102
103 void Simulation::CheckRecords(creature::Creature &c) noexcept {
104         if (c.Age() > records[0].value) {
105                 Record rold(records[0]);
106                 records[0].value = c.Age();
107                 records[0].time = Time();
108                 records[0].holder = &c;
109                 if (rold.holder && rold.holder != &c) {
110                         LogRecord(rold, records[0]);
111                 }
112         }
113         if (c.Mass() > records[1].value) {
114                 Record rold(records[1]);
115                 records[1].value = c.Mass();
116                 records[1].time = Time();
117                 records[1].holder = &c;
118                 if (rold.holder && rold.holder != &c) {
119                         LogRecord(rold, records[1]);
120                 }
121         }
122         if (c.Size() > records[2].value) {
123                 Record rold(records[2]);
124                 records[2].value = c.Size();
125                 records[2].time = Time();
126                 records[2].holder = &c;
127                 if (rold.holder && rold.holder != &c) {
128                         LogRecord(rold, records[2]);
129                 }
130         }
131         if (c.Strength() > records[3].value) {
132                 Record rold(records[3]);
133                 records[3].value = c.Strength();
134                 records[3].time = Time();
135                 records[3].holder = &c;
136                 if (rold.holder && rold.holder != &c) {
137                         LogRecord(rold, records[3]);
138                 }
139         }
140         if (c.Stamina() > records[4].value) {
141                 Record rold(records[4]);
142                 records[4].value = c.Stamina();
143                 records[4].time = Time();
144                 records[4].holder = &c;
145                 if (rold.holder && rold.holder != &c) {
146                         LogRecord(rold, records[4]);
147                 }
148         }
149         if (c.Dexerty() > records[5].value) {
150                 Record rold(records[5]);
151                 records[5].value = c.Dexerty();
152                 records[5].time = Time();
153                 records[5].holder = &c;
154                 if (rold.holder && rold.holder != &c) {
155                         LogRecord(rold, records[5]);
156                 }
157         }
158         if (c.Intelligence() > records[6].value) {
159                 Record rold(records[6]);
160                 records[6].value = c.Intelligence();
161                 records[6].time = Time();
162                 records[6].holder = &c;
163                 if (rold.holder && rold.holder != &c) {
164                         LogRecord(rold, records[6]);
165                 }
166         }
167 }
168
169 void Simulation::LogRecord(const Record &rold, const Record &rnew) {
170         Log() << "at age " << ui::TimeString(rnew.holder->Age()) << " "
171                 << rnew.holder->Name() << " broke the " << rnew.name << " record of "
172                 << rold.ValueString() << " by " << rold.holder->Name()
173                 << " (established " << ui::TimeString(rold.time) << ")" << std::endl;
174 }
175
176 std::ostream &Simulation::Log() {
177         return std::cout << '[' << ui::TimeString(Time()) << "] ";
178 }
179
180 }
181 }