void MotionRequest::draw() const { DECLARE_DEBUG_DRAWING("representation:MotionRequest", "drawingOnField"); // drawing of a request walk vector if(motion == walk) { switch(walkRequest.mode) { case WalkRequest::targetMode: { LINE("representation:MotionRequest", 0, 0, walkRequest.target.translation.x(), walkRequest.target.translation.y(), 0, Drawings::solidPen, ColorRGBA(0xcd, 0, 0)); CROSS("representation:MotionRequest", walkRequest.target.translation.x(), walkRequest.target.translation.y(), 50, 0, Drawings::solidPen, ColorRGBA(0xcd, 0, 0)); Vector2f rotation(500.f, 0.f); rotation.rotate(walkRequest.target.rotation); ARROW("representation:MotionRequest", walkRequest.target.translation.x(), walkRequest.target.translation.y(), walkRequest.target.translation.x() + rotation.x(), walkRequest.target.translation.y() + rotation.y(), 0, Drawings::solidPen, ColorRGBA(0xcd, 0, 0, 127)); break; } case WalkRequest::speedMode: case WalkRequest::percentageSpeedMode: { Vector2f translation = walkRequest.mode == WalkRequest::speedMode ? walkRequest.speed.translation * 10.f : walkRequest.speed.translation * 1000.f; ARROW("representation:MotionRequest", 0, 0, translation.x(), translation.y(), 0, Drawings::solidPen, ColorRGBA(0xcd, 0, 0)); if(walkRequest.target.rotation != 0.0f) { translation.x() = translation.norm(); translation.y() = 0; translation.rotate(walkRequest.speed.rotation); ARROW("representation:MotionRequest", 0, 0, translation.x(), translation.y(), 0, Drawings::solidPen, ColorRGBA(0xcd, 0, 0, 127)); } break; } } } }
void World::processOutputs() { //assign meaning for (Agent & agent : agents) { agent.color.red = agent.out[OutputType::RED]; agent.color.green = agent.out[OutputType::GREEN]; agent.color.blue = agent.out[OutputType::BLUE]; agent.wheel_left = agent.out[OutputType::WHEEL_LEFT]; //-(2*agent.out[0]-1); agent.wheel_right = agent.out[OutputType::WHEEL_RIGHT]; //-(2*agent.out[1]-1); agent.boost = agent.out[OutputType::BOOST] > 0.5; agent.soundmul = agent.out[OutputType::SOUND_MULTIPLIER]; agent.give = agent.out[OutputType::GIVING]; //spike length should slowly tend towards out[OutputType::SPIKE] float g = agent.out[OutputType::SPIKE]; if (agent.spikeLength < g) agent.spikeLength += conf::SPIKESPEED; else if (agent.spikeLength > g) agent.spikeLength = g; //its easy to retract spike, just hard to put it up } //move bots //#pragma omp parallel for for (size_t i = 0; i < agents.size(); ++i) { Agent &agent = agents[i]; Vector2f v(conf::BOTRADIUS / 2, 0); v.rotate(agent.angle + M_PI / 2); Vector2f w1p = agent.pos + v; //wheel positions Vector2f w2p = agent.pos - v; float BW1 = conf::BOTSPEED * agent.wheel_left; float BW2 = conf::BOTSPEED * agent.wheel_right; if (agent.boost) { BW1 = BW1 * conf::BOOSTSIZEMULT; BW2 = BW2 * conf::BOOSTSIZEMULT; } //move bots Vector2f vv = w2p - agent.pos; vv.rotate(-BW1); agent.pos = w2p - vv; agent.angle -= BW1; if (agent.angle < -M_PI) agent.angle = M_PI - (-M_PI - agent.angle); vv = agent.pos - w1p; vv.rotate(BW2); agent.pos = w1p + vv; agent.angle += BW2; if (agent.angle > M_PI) agent.angle = -M_PI + (agent.angle - M_PI); //wrap around the map if (agent.pos.x < 0) agent.pos.x = conf::WIDTH + agent.pos.x; if (agent.pos.x >= conf::WIDTH) agent.pos.x = agent.pos.x - conf::WIDTH; if (agent.pos.y < 0) agent.pos.y = conf::HEIGHT + agent.pos.y; if (agent.pos.y >= conf::HEIGHT) agent.pos.y = agent.pos.y - conf::HEIGHT; } // process food intake for herbivores for (size_t i = 0; i < agents.size(); ++i) { int cx = (int) agents[i].pos.x / conf::CZ; int cy = (int) agents[i].pos.y / conf::CZ; float f = food[cx][cy]; if (f > 0 && agents[i].health < 2) { // agent eats the food float itk = min(f, conf::FOODINTAKE); float speedmul = (1 - (abs(agents[i].wheel_left) + abs(agents[i].wheel_right)) / 2) * 0.7 + 0.3; itk = itk * agents[i].herbivore * speedmul; //herbivores gain more from ground food agents[i].health += itk; agents[i].repcounter -= 3 * itk; food[cx][cy] -= min(f, conf::FOODWASTE); } } //process giving and receiving of food for (size_t i = 0; i < agents.size(); ++i) { agents[i].dfood = 0; } for (size_t i = 0; i < agents.size(); ++i) { if (agents[i].give > 0.5) { for (size_t j = 0; j < agents.size(); ++j) { float d = (agents[i].pos - agents[j].pos).length(); if (d < conf::FOOD_SHARING_DISTANCE) { //initiate transfer if (agents[j].health < 2) agents[j].health += conf::FOODTRANSFER; agents[i].health -= conf::FOODTRANSFER; agents[j].dfood += conf::FOODTRANSFER; //only for drawing agents[i].dfood -= conf::FOODTRANSFER; } } } } // Process spike dynamics for carnivores // we dont need to do this TOO often. can save efficiency here since this is n^2 op in #agents if (modcounter % 2 == 0) { for (size_t i = 0; i < agents.size(); ++i) { // NOTE: herbivore cant attack. TODO: hmmmmm // for now ok: I want herbivores to run away from carnivores, not kill them back if (agents[i].herbivore > 0.8 || agents[i].spikeLength < 0.2 || agents[i].wheel_left < 0.5 || agents[i].wheel_right < 0.5) continue; for (size_t j = 0; j < agents.size(); ++j) { if (i == j) continue; float d = (agents[i].pos - agents[j].pos).length(); if (d < 2 * conf::BOTRADIUS) { //these two are in collision and agent i has extended spike and is going decent fast! Vector2f v(1, 0); v.rotate(agents[i].angle); float diff = v.angle_between(agents[j].pos - agents[i].pos); if (fabs(diff) < M_PI / 8) { //bot i is also properly aligned!!! that's a hit /*float mult = 1; if (agents[i].boost) mult = conf::BOOSTSIZEMULT;*/ float DMG = conf::SPIKEMULT * agents[i].spikeLength * max(fabs(agents[i].wheel_left), fabs(agents[i].wheel_right)) * conf::BOOSTSIZEMULT; agents[j].health -= DMG; CeilingCap(&agents[i].health, 2.0f); // cap health at 2 agents[i].spikeLength = 0; //retract spike back down agents[i].initEvent(40 * DMG, 1, 1, 0); //yellow event means bot has spiked other bot. nice! Vector2f v2(1, 0); v2.rotate(agents[j].angle); float adiff = v.angle_between(v2); if (fabs(adiff) < M_PI / 2) { //this was attack from the back. Retract spike of the other agent (startle!) //this is done so that the other agent cant right away "by accident" attack this agent agents[j].spikeLength = 0; } agents[j].spiked = true; //set a flag saying that this agent was hit this turn } } } } } }