blob: 2c0697aab307918d6742a9d6e032e63d24dbad86 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include "colony.hh"
#include <iostream>
#include "nurturer.hh"
#include "provider.hh"
Colony::Colony(uint32_t passport)
: passport_pheromone_(passport)
, workers_()
{}
bool Colony::addAnt(const Ant& ant, std::shared_ptr<Colony> colony)
{
auto q = dynamic_cast<const Queen*>(&ant);
if (q)
{
if (colony->queen_ || q->get_stage() != DevelopmentStage::ADULT)
return false;
colony->queen_ = std::make_unique<Queen>(*q);
return true;
}
auto n = dynamic_cast<const Nurturer*>(&ant);
if (n)
{
colony->workers_.push_back(std::make_shared<Nurturer>(*n));
return true;
}
auto p = dynamic_cast<const Provider*>(&ant);
if (p)
{
colony->workers_.push_back(std::make_shared<Provider>(*p));
return true;
}
return false;
}
void Colony::manageQueen()
{
if (queen_ == nullptr)
throw std::runtime_error("Cannot manage a colony without a Queen.");
// check if the queen should lose health points
if (queen_->food_level_ < 0)
queen_->hp_ -= 1;
if (queen_->hp_ <= 0)
{
queen_ = nullptr;
throw std::runtime_error("The Queen died.");
}
// Append to workers_ all the new workers contained in the queen's
// eggs_queue_
while (!queen_->eggs_queue_.empty())
{
//! we insert eggs that were laid by the queen
workers_.emplace_back(queen_->eggs_queue_.front());
queen_->eggs_queue_.pop();
}
}
void Colony::removeDeadWorkers()
{
auto dead_count = std::erase_if(
workers_, [](const std::shared_ptr<Worker> w) { return w->hp_ <= 0; });
if (dead_count > 0)
{
std::cout << dead_count << " workers_ died.\n";
// each dead worker decrease the cleanliness of the colony
cleanliness -= 0.5 * dead_count;
}
}
// this method can be considered as one round of management
void Colony::manageAnts()
{
// We first manage the queen
manageQueen();
// We remove all dead workers contained in workers_
removeDeadWorkers();
std::cout << "-- THERE ARE " << workers_.size() << " WORKERS --\n";
// We iterate over all workers
for (auto worker : workers_)
{
if (worker->stage_ == DevelopmentStage::ADULT)
{
/*
* Because work() is a virtual method, dynamic dispatch will be
* used. Which means that the overridden work method of the true
* type (either Nurturer or Provider) will actually be called
* instead of Worker::work().
*/
worker->work();
}
else
{
/*
* We increment their food_level_ as if it is a ticking time,
* EXCEPT for the larvae, as they are fed by nurturers.
*/
if (worker->stage_ != DevelopmentStage::LARVA)
worker->food_level_ += 1;
if (worker->food_level_ >= 4.0)
{
/* FIXME : Make the worker change stage_ and reset their
* food_level_ to 0. HINT : This can take only 2/3 lines if
* you use a certain C++ cast instead of a switch.
*/
worker->food_level_ = 0;
auto ant = static_cast<Ant*>(worker.get());
ant->stage_ = static_cast<DevelopmentStage>(
static_cast<int>(ant->stage_) + 1);
}
}
}
queen_->food_level_ -= 0.2;
}
// FIXME : Implements addAnt() static method.
|