Created
March 29, 2017 08:25
-
-
Save kkabdol/ac3e24b2160b5e940527afadf35b9e6b to your computer and use it in GitHub Desktop.
Codingame Coders Strike Back - Bronze to Silver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <algorithm> | |
using namespace std; | |
#define PI 3.14159265 | |
struct vec2 { | |
float x; | |
float y; | |
vec2( float s = float(0.0) ) : | |
x(s), y(s) {} | |
vec2( float x, float y ) : | |
x(x), y(y) {} | |
vec2( const vec2& v ) | |
{ x = v.x; y = v.y; } | |
float& operator [] ( int i ) { return *(&x + i); } | |
const float operator [] ( int i ) const { return *(&x + i); } | |
// | |
// --- (non-modifying) Arithematic Operators --- | |
// | |
vec2 operator - () const // unary minus operator | |
{ return vec2( -x, -y ); } | |
vec2 operator + ( const vec2& v ) const | |
{ return vec2( x + v.x, y + v.y ); } | |
vec2 operator - ( const vec2& v ) const | |
{ return vec2( x - v.x, y - v.y ); } | |
vec2 operator * ( const float s ) const | |
{ return vec2( s*x, s*y ); } | |
vec2 operator * ( const vec2& v ) const | |
{ return vec2( x*v.x, y*v.y ); } | |
friend vec2 operator * ( const float s, const vec2& v ) | |
{ return v * s; } | |
vec2 operator / ( const float s ) const { | |
float r = float(1.0) / s; | |
return *this * r; | |
} | |
bool operator == ( const vec2& v ) const | |
{ return ( x == v.x ) && ( y == v.y ); } | |
bool operator != ( const vec2& v ) const | |
{ return ( x != v.x ) || ( y != v.y ); } | |
// | |
// --- (modifying) Arithematic Operators --- | |
// | |
vec2& operator += ( const vec2& v ) | |
{ x += v.x; y += v.y; return *this; } | |
vec2& operator -= ( const vec2& v ) | |
{ x -= v.x; y -= v.y; return *this; } | |
vec2& operator *= ( const float s ) | |
{ x *= s; y *= s; return *this; } | |
vec2& operator *= ( const vec2& v ) | |
{ x *= v.x; y *= v.y; return *this; } | |
vec2& operator /= ( const float s ) { | |
float r = float(1.0) / s; | |
*this *= r; | |
return *this; | |
} | |
}; | |
//---------------------------------------------------------------------------- | |
// | |
// Non-class vec2 Methods | |
// | |
inline | |
float dot( const vec2& u, const vec2& v ) { | |
return u.x * v.x + u.y * v.y; | |
} | |
inline | |
float length( const vec2& v ) { | |
return std::sqrt( dot(v,v) ); | |
} | |
inline | |
vec2 normalize( const vec2& v ) { | |
return v / length(v); | |
} | |
inline | |
vec2 rotate( const vec2& v, float angle ) { | |
float radian = angle * PI / 180; | |
double sinAngle = sin(radian); | |
double cosAngle = cos(radian); | |
return vec2( v.x * cosAngle - v.y * sinAngle, v.y * cosAngle + v.x * sinAngle ); | |
} | |
class BoostHelper { | |
public: | |
BoostHelper() : boostAvailable_( true ), allCheckpointFound_( false ), fartestDist_( 0.0 ) {} | |
bool UseBoost( float dist ) { | |
cerr << "BOOST left:" << boostAvailable_; | |
cerr << " is 2nd Lap:" << allCheckpointFound_; | |
cerr << " best boost dist:" << fartestDist_; | |
cerr << " current dist:" << dist << endl; | |
if( boostAvailable_ && | |
allCheckpointFound_ && | |
dist + distError > fartestDist_ ) | |
{ | |
boostAvailable_ = false; | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
void SetNextCheckpoint( int x, int y, int dist ) { | |
if( allCheckpointFound_ ) | |
{ | |
return; | |
} | |
const vec2 newCheckpoint( x, y ); | |
if( checkpoints_.empty() ) | |
{ | |
checkpoints_.push_back( newCheckpoint ); | |
} | |
else if( checkpoints_.back() != newCheckpoint ) | |
{ | |
checkpoints_.push_back( newCheckpoint ); | |
if( checkpoints_.front() == newCheckpoint ) | |
{ | |
allCheckpointFound_ = true; | |
} | |
} | |
if( fartestDist_ < dist ) | |
{ | |
fartestDist_ = dist; | |
} | |
} | |
bool BoostAvailable() | |
{ | |
return boostAvailable_; | |
} | |
private: | |
const float distError = 2000; | |
bool boostAvailable_; | |
bool allCheckpointFound_; | |
float fartestDist_; | |
vector< vec2 > checkpoints_; | |
}; | |
/** | |
* Auto-generated code below aims at helping you parse | |
* the standard input according to the problem statement. | |
**/ | |
int main() | |
{ | |
// Steering Behaviors | |
// https://gamedevelopment.tutsplus.com/series/understanding-steering-behaviors--gamedev-12732 | |
// 1. Seek | |
// 2. Boost | |
// 3. Slowing Down ( straight only ) | |
int oldX = 0; | |
int oldY = 0; | |
int oldOpponentX = 0; | |
int oldOpponentY = 0; | |
BoostHelper boostHelper; | |
const int kAngleToSteer = 1; | |
const int kSlowingAngle = 90; | |
const float kSlowingRadius = 600 * 4; // check point radius = 600 | |
// game loop | |
while (1) { | |
int x; | |
int y; | |
int nextCheckpointX; // x position of the next check point | |
int nextCheckpointY; // y position of the next check point | |
int nextCheckpointDist; // distance to the next checkpoint | |
int nextCheckpointAngle; // angle between your pod orientation and the direction of the next checkpoint | |
cin >> x >> y >> nextCheckpointX >> nextCheckpointY >> nextCheckpointDist >> nextCheckpointAngle; cin.ignore(); | |
int opponentX; | |
int opponentY; | |
cin >> opponentX >> opponentY; cin.ignore(); | |
boostHelper.SetNextCheckpoint( nextCheckpointX, nextCheckpointY, nextCheckpointDist ); | |
cerr << "x:" << x << ", y:" << y << endl; | |
cerr << "nextCheckpoint x:" << nextCheckpointX << ", y:" << nextCheckpointY << endl; | |
cerr << "nextCheckpoint angle:" << nextCheckpointAngle << endl; | |
cerr << "nextCheckpointDist:" << nextCheckpointDist << endl; | |
int thrust = 100; | |
bool useBoost = false; | |
if( nextCheckpointAngle <= -kAngleToSteer || nextCheckpointAngle >= kAngleToSteer ) | |
{ | |
// 1. Seek | |
vec2 desiredDirection( nextCheckpointX - x, nextCheckpointY - y ); | |
desiredDirection = normalize( desiredDirection ); | |
vec2 currentDirection = rotate( desiredDirection, -nextCheckpointAngle ); | |
//vec2 currentDirection( x - oldX, y - oldY ); | |
currentDirection = normalize( currentDirection ); | |
vec2 steeringDirection = ( desiredDirection - currentDirection ); | |
steeringDirection = normalize( steeringDirection ) * 100; | |
nextCheckpointX += steeringDirection.x; | |
nextCheckpointY += steeringDirection.y; | |
// 2. Slowing Down ( angle ) | |
if( nextCheckpointAngle <= -kSlowingAngle || nextCheckpointAngle >= kSlowingAngle ) | |
{ | |
thrust = 0; | |
} | |
else if( nextCheckpointDist < kSlowingRadius ) | |
{ | |
thrust *= ( kSlowingAngle - abs(nextCheckpointAngle) ) / ( float )kSlowingAngle; | |
} | |
cerr << "steering to x:" << nextCheckpointX << ", y:" << nextCheckpointY; | |
cerr << " by: " << thrust << endl; | |
} | |
else | |
{ | |
if( boostHelper.UseBoost( nextCheckpointDist ) ) | |
{ | |
useBoost = true; | |
cerr << "BOOST" << endl; | |
} | |
else if( nextCheckpointDist < kSlowingRadius ) | |
{ | |
// 2. Slowing Down ( radius ) | |
thrust *= nextCheckpointDist / kSlowingRadius; | |
} | |
cerr << "not steering" << endl; | |
} | |
if( boostHelper.BoostAvailable() ) | |
{ | |
cerr << "BOOST available" << endl; | |
} | |
else | |
{ | |
cerr << "BOOST used" << endl; | |
} | |
// output | |
cout << nextCheckpointX << " " << nextCheckpointY << " "; | |
if( useBoost ) | |
{ | |
cout << "BOOST" << endl; | |
} | |
else | |
{ | |
cout << thrust << endl; | |
} | |
cerr << "thrust :" << thrust << endl; | |
oldX = x; | |
oldY = y; | |
oldOpponentX = opponentX; | |
oldOpponentY = opponentY; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment