before the wind mine was lasting over 30 mins, now (with the wind) it dies after a few seconds, gona have another go at it somethime.
Moderators: Darobat, RecursiveS, Dante Shamest, Bugdude, Wizard, raimo
Zen wrote:Can I access all global variabels? (Not that it matters all that much)
Zen wrote:I guess I'm allowed to create additional functions to use within the control function? (Not that this matters much either)
#include <math.h>
#include <stdlib.h>
#include "vector2d.hpp"
static const double PI = 3.1415926535897932384626433832795;
signed char control(Vector2D cartPos, Vector2D ballPos);
// Include your implementation here
struct Object
{
Vector2D position;
Vector2D oldPosition;
virtual void step(double deltaTime) { }
virtual void constrain() { }
};
struct MovableObject : Object
{
double mass;
static double gravity;
void step(double deltaTime)
{
// newPos = 2*pos - oldPos + accel * deltaTime^2
Vector2D result(0,0);
accumulateForces(result);
result *= (deltaTime*deltaTime/ mass);
result += position;
result += position;
result -= oldPosition;
oldPosition = position;
position = result;
}
virtual void accumulateForces(Vector2D& result)=0;
};
double MovableObject::gravity = -9.8;
struct LineConstraint : Object
{
MovableObject* left;
MovableObject* right;
double distance;
double invmassLeft, invmassRight;
LineConstraint(MovableObject* a, MovableObject* b, double dist)
{
left = a;
right = b;
distance = dist;
invmassLeft = 1.0/left->mass;
invmassRight = 1.0/right->mass;
}
void constrain()
{
Vector2D delta = right->position - left->position;
double length = sqrt(delta.x*delta.x + delta.y*delta.y);
double diff = (length-distance)/(length*(invmassLeft+invmassRight));
left->position += delta*(invmassLeft*diff);
right->position -= delta*(invmassRight*diff);
}
};
struct Ball : MovableObject
{
double radius;
double windForce;
Ball() : windForce(0.0) { }
virtual void accumulateForces(Vector2D& result)
{
result.x += windForce;
windForce = 0;
result.y += gravity*mass;
}
};
struct Cart : MovableObject
{
static const double WIDTH;
static const double HEIGHT;
static const double FRICTION_COEFFICIENT;
float externalForce;
Cart()
{
externalForce = 0;
position.x = 0;
position.y = -1.0 + HEIGHT;
}
virtual void accumulateForces(Vector2D& result)
{
result.x += externalForce - (position.x - oldPosition.x)*FRICTION_COEFFICIENT;
externalForce = 0;
}
void constrain()
{
position.y = -1.0 + HEIGHT;
}
};
const double Cart::WIDTH = 0.12;
const double Cart::HEIGHT = 0.02;
const double Cart::FRICTION_COEFFICIENT = 0.1;
inline double frand(double min, double max)
{
return ((double)rand())/RAND_MAX*(max-min)+min;
}
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
namespace
{
vector<Object*> objects;
Cart cart;
Ball ball;
LineConstraint rod(&ball, &ball, 0); // this will change
int tickCount=0;
int gustCount=0;
int ticksTillNextGust=-1;
void initDynamics(double ballVelocity, double cartVelocity)
{
cart = Cart();
cart.mass = 5;
ball = Ball();
ball.position.x = cart.position.x;
ball.position.y = 0.8;
ball.mass = 1;
ball.radius = 0.02;
rod = LineConstraint(&ball, &cart, ball.position.y - cart.position.y);
objects.clear();
objects.push_back(&cart);
objects.push_back(&ball);
objects.push_back(&rod);
for(size_t i=0; i < objects.size(); ++i)
{
objects[i]->oldPosition = objects[i]->position;
}
cart.oldPosition.x += cartVelocity;
ball.oldPosition.x += ballVelocity;
}
bool gameOver()
{
return (ball.position.y < cart.position.y) || (cart.position.x < -1) || (cart.position.x > 1);
}
}
static const int TICK_MS = 50;
static const double TICK_SEC = TICK_MS/1000.0;
int tick(void)
{
tickCount=0;
gustCount=0;
while(1){
// query the controlling function and clamp it
signed char force = control(cart.position, ball.position);
if (force < -10) force = -10;
else if (force > 10) force = 10;
cart.externalForce = force*10.0;
// determine wind
if (ticksTillNextGust == 0)
{
++gustCount;
double scale = gustCount;
ball.windForce = frand(-scale,+scale);
}
if (ticksTillNextGust <= 0)
{
ticksTillNextGust = rand()%(4000/TICK_MS);
}
--ticksTillNextGust;
// dynamics step
for(size_t i=0; i < objects.size(); ++i)
objects[i]->step(TICK_SEC);
// satisfy constraints
for(int j=0; j < 32; ++j)
for(size_t i=0; i < objects.size(); ++i)
objects[i]->constrain();
// check for game over condition
++tickCount;
if (gameOver())
return tickCount;
}
}
int main()
{
double sum=0;
unsigned u;
for(u=0;u<1000;++u){
// setup dynamics
srand(u);
static const double VEL_SCALE = 0.01;
initDynamics(frand(-VEL_SCALE,VEL_SCALE), frand(-VEL_SCALE,VEL_SCALE));
sum+=tick();
}
std::cout << (sum/u) << std::endl;
return 0;
}
Dudi Hatotah wrote:I have just sent my code for this contest.
Thanks to Alvaro's tuning code (thanks, Alvaro!), I tuned it up to about 1200 avarage ticks.
Users browsing this forum: No registered users and 1 guest