# Bugs
+- Turret can fire through walls
# TODOs
- Move game objects into namespace `tanks`
- Should use unit vectors for trajectories?
--> matrix math for reflections?
+
+# The Tank AI Challenge
+
+Your goal is to design an AI tank which does its best to: 1) stay alive; 2) kill all enemy tanks.
+
+Rules:
+- All tanks have 1hp.
+- Tanks shoot bullets. Bullets explode on contact with tanks and other bullets, and bounce once on contact with a wall.
+- Each tank can have up to 5 bullets in the air at a time.
+
+Each tick, you get a bunch of inputs:
+- A pathmap of the level (which you can ask whether an area is passable)
+- A list of friendly and enemy units (including bullets), each with its attributes (trajectory, position, hp, speed, power, shots, etc)
+- Your attributes (position, hp, speed, power, etc)
+
+Ticks occur 30 times per second. When called, you'll return one action, which can be:
+- Move toward (x,y)
+- Fire a projectile toward (x,y)
+- Do nothing
+That is all.
+
+An AI script looks like a list of ordered (test, action) pairs. The game will consider each test in turn, and the first matching will be the action taken. Here's an example:
+
+- If there is a bullet that will collide with me in less than 15 ticks, shoot a bullet at its location.
+- If there is a bullet that will collide with me in less than 30 ticks, move perpendicular to its trajectory.
+- If there is an enemy within 100 pixels, shoot a bullet at it.
+- Finally, move toward the closest enemy tank.
+
return this.x*b.x + this.y*b.y;
},
+ rotate : function rotate(theta){
+ var sin = Math.sin(theta)
+ , cos = Math.cos(theta)
+ , x = this.x, y = this.y ;
+ return this.setXY(x*cos - y*sin, x*sin + y*cos);
+ },
+
toString : function toString(){
var p = 2, x = this.x, y = this.y;
x = ((x % 1 !== 0) ? x.toFixed(p) : x);
traceTrajectories : false
},
debug : {
- projectiles : 10
+ projectiles : 0
}
};
\ No newline at end of file
, barrel = this.barrel, bb = barrel.boundingBox
, theta = barrel.transform.rotate, sin = Math.sin(theta), cos = Math.cos(theta)
, x0 = bb.x2-bb.x1, y0 = (bb.y2-bb.y1)/2
- , x = loc.x + bb.x1 + x0*cos - y0*sin
- , y = loc.y + bb.y1 + x0*sin + y0*cos
+ , x = loc.x + bb.x1 + x0*cos - y0*sin + 3
+ , y = loc.y + bb.y1 + x0*sin + y0*cos + 3
;
// console.log('getTurretLoc()', 'loc:', loc, 'bb.(x2,y2):', [bb.x2,bb.y2], '(x,y):', [x,y]);
return new math.Vec(x,y);
},
keydown : function keydown(evt){
+ this.updateMeta(evt);
+
+ if (evt.which === Key.fire) {
+ var theta = this.tank.barrel.transform.rotate
+ , sin = Math.sin(theta), cos = Math.cos(theta)
+ , bb = this.tank.boundingBox
+ ;
+ this.queue.push({
+ type : 'fire',
+ x : bb.x1+bb.width/2 + REF_SIZE*cos,
+ y : bb.y1+bb.height/2 + REF_SIZE*sin
+ });
+ return;
+ }
+
var dir = Key.getDir(evt.which)
, inv = Key.getInverseDir(evt.which);
this.activeKeys.remove(inv);
this.activeKeys.push(dir);
}
- this.updateMeta(evt);
},
keyup : function keyup(evt){
var action = this.queue.shift();
- if (action && action.type === 'fire')
+ if (action && action.type === 'fire') {
+ // console.log('fire', [action.x, action.y], 'loc', this.tank.loc)
this.tank.fireProjectile(action.x, action.y);
- else if ( this.activeKeys.size() )
+ } else if ( this.activeKeys.size() )
this.move();
return this.tank;