Commit 20ad4bc9 authored by Thomas Kolb's avatar Thomas Kolb
Browse files

Snakes now drop food and loose mass while boosting

Also, they die if the get too small.
parent 7d635f9d
......@@ -193,6 +193,18 @@ void Field::moveAllBots(void)
} else {
// no collision, bot still alive
m_updateTracker->botMoved(victim, steps);
if(victim->getSnake()->boostedLastMove()) {
real_t lossValue =
config::SNAKE_BOOST_LOSS_FACTOR * victim->getSnake()->getMass();
victim->getSnake()->dropFood(lossValue);
if(victim->getSnake()->getMass() < config::SNAKE_SELF_KILL_MASS_THESHOLD) {
// Bot is now too small, so it dies
killBot(victim, victim);
}
}
}
}
......@@ -249,7 +261,12 @@ void Field::createDynamicFood(real_t totalValue, const Vector2D &center, real_t
std::size_t count = 1 + totalValue / config::FOOD_SIZE_MEAN;
for(std::size_t i = 0; i < count; i++) {
real_t value = (*m_foodSizeDistribution)(*m_rndGen);
real_t value;
if(totalValue >= config::FOOD_SIZE_MEAN) {
value = (*m_foodSizeDistribution)(*m_rndGen);
} else {
value = totalValue;
}
real_t rndRadius = radius * (*m_simple0To1Distribution)(*m_rndGen);
real_t rndAngle = (*m_angleRadDistribution)(*m_rndGen);
......
......@@ -158,6 +158,8 @@ std::size_t Snake::move(real_t targetAngle, bool boost)
m_segments[i].setPos(m_field->wrapCoords(m_segments[i].pos()));
}
m_boostedLastMove = boost;
return m_segments.size(); // == number of new segments at head
}
......@@ -197,6 +199,21 @@ void Snake::convertToFood(const std::shared_ptr<Bot> &hunter) const
}
}
void Snake::dropFood(float_t value)
{
Vector2D dropOffset = (m_segments.end() - 1)->pos() - (m_segments.end() - 2)->pos();
Vector2D dropPos = (m_segments.end() - 1)->pos() + dropOffset.normalized() * 5;
m_field->createDynamicFood(value * config::SNAKE_CONVERSION_FACTOR, dropPos, m_segmentRadius, nullptr);
m_mass -= value;
if(m_mass < 1e-6) {
m_mass = 1e-6;
}
ensureSizeMatchesMass();
}
real_t Snake::getConsumeRadius()
{
return m_segmentRadius * config::SNAKE_CONSUME_RANGE;
......
......@@ -46,6 +46,8 @@ class Snake
real_t m_movedSinceLastSpawn = 0; //!< Distance the head has moved since the last spawned segment
real_t m_boostedLastMove = false; //!< Track if the snake boosted during the last move
/*!
* Updates the length of m_segments and calculates the current m_segmentRadius
*/
......@@ -111,10 +113,20 @@ class Snake
*/
void convertToFood(const std::shared_ptr<Bot> &hunter) const;
/*!
* Drop food at the end of the Snake. Primarily used for mass loss during boost.
*
* The Snake's mass is reduced by the given amount. The dropped mass is the
* given amount multiplied with SNAKE_CONVERSION_FACTOR.
*/
void dropFood(float_t value);
real_t getMass(void) { return m_mass; }
real_t getConsumeRadius(void);
real_t maxRotationPerStep(void);
bool boostedLastMove(void) const { return m_boostedLastMove; }
};
......@@ -45,6 +45,12 @@ namespace config {
// the Snake’s segment radius.
static const real_t SNAKE_CONSUME_RANGE = 2.0;
// Part of Snake's mass to drop in every frame the boost is on.
static const real_t SNAKE_BOOST_LOSS_FACTOR = 1e-3;
// Mass below which Snake dies through starvation
static const real_t SNAKE_SELF_KILL_MASS_THESHOLD = 1.0;
// Food particle size log-normal distribution parameters
static const real_t FOOD_SIZE_MEAN = 3.5;
static const real_t FOOD_SIZE_STDDEV = 2.0;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment