MY ROBOTS

ABSOLUTELY EVERYTHING ABOUT YOUR ARMY OF ROBOTS
  • none
    CRUSADER V2.4
    created 06/21/13 75 code lines fight
    1500 SCORE
    0 KILLS
    0 SHOTS
    0 HITS
    0.00%
    AVERAGE HITS/SHOT
    SCORE OVER TIME
  • # 12
    CRUSADER V3.0
    created 07/21/13 1327 code lines fight
    1660 SCORE
    30 KILLS
    569 SHOTS
    211 HITS
    37.02%
    AVERAGE HITS/SHOT
    SCORE OVER TIME
  • none
    Krstaš V0.51
    created 04/30/14 40 code lines fight
    1500 SCORE
    0 KILLS
    0 SHOTS
    0 HITS
    0.00%
    AVERAGE HITS/SHOT
    SCORE OVER TIME
  • none
    WCrusader V1.34
    created 04/29/14 54 code lines fight
    1500 SCORE
    0 KILLS
    0 SHOTS
    0 HITS
    0.00%
    AVERAGE HITS/SHOT
    SCORE OVER TIME
  • none
    YANICHI
    created 09/08/13 2352 code lines fight fork
    1500 SCORE
    0 KILLS
    0 SHOTS
    0 HITS
    0.00%
    AVERAGE HITS/SHOT
    SCORE OVER TIME
    var Robot; (function () { Robot = function (a) { this.parentState = new s(a); this.parentState.strafeDirection = 1; }; var a = Robot.prototype; a.onIdle = function (a) { var b = a.robot; try { if (b.parentId == null && b.availableClones != 0) { b.clone(); this.cloneState = new s(b); this.cloneState.position = null; this.cloneState.parentId = b.id; this.cloneState.id = null; this.cloneState.tracker = this.parentState.tracker; this.cloneState.strafeDirection = -1 * this.parentState.strafeDirection; this.cloneState.time = this.parentState.time; return; } var c = this.getState(b); c.update(b); var d = this.otherState(c); if (d.parentId == null && d.time != c.time) { c.time = Math.max(c.time, d.time); d.time = c.time; } this.next(b); } catch (e) { } }; a.onRobotCollision = function (a) { var c = a.robot; var d = this.getState(c); d.update(c); d.tracker.push(a.collidedRobot, d); var e = b.FromBearing(c.angle, a.bearing); var f = d.direction.dotProduct(e); if (f > 0.3) { c.move(1, -1); } else if (f < -0.3) { c.move(1, 1); } else { c.turn(1); } }; a.onScannedRobot = function (a) { var b = a.robot; b.disappear(); var c = this.getState(b); c.update(b); c.tracker.push(a.scannedRobot, c); this.next(b); }; a.onWallCollision = function (a) { var b = a.robot; var c = this.getState(b); c.update(b); this.next(b); }; a.onHitByBullet = function (a) { var c = a.robot; c.disappear(); var e = this.getState(c); e.update(c); var f = b.FromBearing(c.angle, a.bearing); var g = e.arena.marginRect.getDistToIntersection(new d(e.position, f), true); var h = e.position.add(f.scale(0.5 * g)); var i = b.FromAngle(0).signedAngleTo(f.flip()); var j = new HitByBullet(null, h, null, i, null, null); e.tracker.push(j, e); this.next(c); }; a.next = function (a) { try { var b = this.getState(a); if (!b.isInitialized) { this.initialize(a, b); } if (this.updateCannon(a, b)) { if (b.tracker.isHunting(b) && b.arcAndDirection == null) { this.setToSeekMode(a, b); } return; } this.updateStrafeDirection(a, b); if (b.arcAndDirection != null && !b.arcAndDirection.isPastEnd(b, b.arcAndDirection.targetPoint)) { b.arcAndDirection.update(b, b.arcAndDirection.targetPoint); } if (b.tracker.isHunting(b)) { this.huntNext(a, b); } else { this.scanNext(a, b); } } catch (c) { } }; a.scanNext = function (a, b) { try { if (b.arcAndDirection != null && !b.arcAndDirection.isScanArc()) { b.strafeDirection = b.arcAndDirection.direction; b.arcAndDirection = null; } if (b.strafeDirection == 0) { b.strafeDirection = a.cannonRelativeAngle < 90 ? -1 : 1; } this.moveToArc(a, b, b.arcAndDirection); } catch (c) { } }; a.huntNext = function (a, b) { try { var c = b.tracker.lastTrackingScans(null, b).timeSinceLast(b); var d = b.position; var e = b.tracker.isTracking(b); if (a.gunCoolDownTime == 0) { if (!e && this.canFire(b)) { a.fire(); this.setToSeekMode(a, b); return; } var f = b.tracker.getAttackPoint(a, b, null); var g = d.distanceTo(f); var h = d.add(b.cannonDirection.scale(g)); var i = h.distanceTo(f); if (i < (0.6 * b.arena.radius) && this.canFire(b)) { a.fire(); if (b.arcAndDirection == null || b.arcAndDirection.isAttacArc()) { this.setToSeekMode(a, b); } return; } } if (e && c < 25 || (b.arcAndDirection != null && b.arcAndDirection.isAttacArc())) { if (b.arcAndDirection == null || !b.arcAndDirection.isAttacArc()) { var f = b.tracker.getAttackPoint(a, b, null); b.arcAndDirection = new q(b, f, a.gunCoolDownTime, q.attackArcEnum()); } else if (b.arcAndDirection.isAttacArc() && b.arcAndDirection.isPastEnd(b, b.arcAndDirection.targetPoint)) { var f = b.tracker.getAttackPoint(a, b, null); b.arcAndDirection.update(b, f); } } else { this.setToSeekMode(a, b); } this.moveToArc(a, b, b.arcAndDirection); } catch (j) { } }; a.setToSeekMode = function (a, b) { try { var c = b.tracker.lastTrackingScans(null, b).timeSinceLast(b); if (b.arcAndDirection == null || !b.arcAndDirection.isSeekArc()) { var d = b.tracker.nextSeekPoint(a, b); b.arcAndDirection = new q(b, d.targetPoint, d.targetTimeOffset, d.arcEnum); } else if (b.arcAndDirection.isSeekArc()) { if (b.arcAndDirection.isPastEnd(b, b.arcAndDirection.targetPoint) && c > 55) { var d = b.tracker.nextSeekPoint(a, b); b.arcAndDirection = new q(b, d.targetPoint, d.targetTimeOffset, d.arcEnum); } if (b.arcAndDirection.isPastEnd(b, b.arcAndDirection.targetPoint) && c <= 50) { b.arcAndDirection.update(b, b.arcAndDirection.targetPoint); } } } catch (e) { } }; a.updateCannon = function (a, b) { try { var c = b.getScanningCannonAngle(a); var e = b.angleDiff(c, a.cannonRelativeAngle); if (b.tracker.isHunting(b)) { var f = b.position; if (b.arcAndDirection == null) { return false; } if (b.strafeDirection == 0) { b.strafeDirection = -1 * b.sign(this.cannonAngleDiff(a, b, e)); } if (this.isCrashing(a, b, 10)) { var g = b.arcAndDirection != null && b.arcAndDirection.arc.radius > 1 ? b.arcAndDirection.getMoveSign(b) : 0; var h = b.direction.scale(g); var i = new d(f, h); var j = b.arena.marginRect.getInterSectingLines(i, true); var k = j.length > 0 ? Math.abs(j[0].direction().signedAngleTo(h)) : 0; var l = this.cannonAngleDiff(a, b, e); if (Math.abs(l) < 1 && (k > 45 || k < 135)) { return false; } a.rotateCannon(b.sign(l) * b.strafeDirection); return true; } if (b.tracker.timeSinceLast(b, null) < 40 && a.gunCoolDownTime > 15 && b.time % 5 == 0) { var l = this.cannonAngleDiff(a, b, e); a.rotateCannon(b.sign(l) * b.strafeDirection); return true; } } else if (Math.abs(e) > 1) { a.rotateCannon(this.parentState.getRotationDirection(a.cannonRelativeAngle, c)); return true; } return false; } catch (m) { } }; a.updateStrafeDirection = function (a, b) { try { var c = b.position; if (this.isCrashingWithOpponent(a, b, 1)) { b.strafeDirection *= -1; } var d = b.arena.marginRect.minDistanceToPoint(c) < (b.arena.radius + 5) && this.isCrashing(a, b, 5); if (d) { var e = this.distToIdeal(a, b); if (e < 0) { b.strafeDirection *= -1; return; } } var f = this.isCrashingWithFriend(a, b, 5); var g = this.isShadowedByOther(a, b); var h = this.otherState(b); var i = this.isShadowedByOther(a, h); if (f || g || i) { var e = this.distToIdeal(a, b); var j = this.distToIdeal(a, h); var k = this.strafeArc(a, b); var l = k.centerPoint; var m = l.vectorTo(c); var n = l.vectorTo(h.position); var o = m.signedAngleTo(n); if (Math.abs(e) <= 110 && b.strafeDirection != (-1 * b.sign(o))) { b.strafeDirection = -1 * b.sign(o); } if (Math.max(Math.abs(e), Math.abs(j)) > 100 && Math.abs(e) > Math.abs(j) && b.strafeDirection != (-1 * b.sign(o))) { b.strafeDirection = -1 * b.sign(o); } return; } var p = this.distToIdeal(a, b); if (p < -100) { b.strafeDirection *= -1; } } catch (q) { } }; a.cannonAngleDiff = function (a, b, c) { var e = b.position; var f = this.strafeArc(a, b); var g = this.idealPoint(a, b); var h = f.centerPoint; var i = h.distanceTo(e); var j = b.arena.marginRect.getDistToIntersection(new d(h, h.vectorTo(e)), true); var k = Math.min(j, h.distanceTo(g)); var l = k - i; var m = Math.atan2(l, 100) * 180 / Math.PI; var n = b.strafeDirection * c; var o = m - n; return o; }; a.isCrashing = function (a, b, c) { var d = b.arcAndDirection != null && b.arcAndDirection.arc.radius > 1 ? b.arcAndDirection.getMoveSign(b) : 0; if (d == 0) { return false; } var e = b.position; var f = b.direction.scale(d); var g = e.add(f.scale(c)); return !g.isWithin(b.arena.marginRect, 0); }; a.isCrashingWithFriend = function (a, b, c) { var d = this.otherState(b); if (b.arcAndDirection == null || b.arcAndDirection.arc.radius < 1 || d == null || d.position == null || Math.abs(b.time - d.time) > 10) { return false; } var e = b.position; var f = d.position; if (e.distanceTo(f) > (2 * b.arena.radius + c)) { return false; } var g = b.direction.scale(b.arcAndDirection.getMoveSign(b)); var h = e.add(g.scale(c)); var i = h.distanceTo(d.position); if (i < (2 * b.arena.radius)) { return true; } return false; }; a.isCrashingWithOpponent = function (a, b, c) { if (b.arcAndDirection == null || b.arcAndDirection.arc.radius < 1 || b.tracker.timeSinceLast(b, null) > 50) { return false; } var d = b.position; var e = b.tracker.last(null).robot.position; if (d.distanceTo(e) > (2 * b.arena.radius + c)) { return false; } var f = b.direction.scale(b.arcAndDirection.getMoveSign(b)); var g = d.add(f.scale(c)); var h = g.distanceTo(e); if (h < (2 * b.arena.radius)) { return true; } return false; }; a.isShadowedByOther = function (a, b) { if (b == null || b.position == null) { return false; } var c = this.otherState(b); if (b.arcAndDirection == null || c == null || c.position == null || a.gunCoolDownTime > 25 && b.tracker.timeSinceLast(b, null) < 25 || Math.abs(b.time - c.time) > 10) { return false; } var e = b.position; var f = c.position; var g = b.cannonDirection; var h = new d(e, g); var i = h.closestPoint(f); if (!i.isOnRay(h)) { return false; } var j = f.distanceTo(i); return j < (3 * b.arena.radius); }; a.distToIdeal = function (a, b) { if (!b.tracker.isHunting(b)) { return 0; } var c = b.position; var d = this.strafeArc(a, b); var e = d.centerPoint; var f = this.idealPoint(a, b); var g = e.vectorTo(f); var h = e.vectorTo(c); var i = h.signedAngleTo(g); var j = b.sign(i) * b.strafeDirection * d.arcLengthFromAngle(i); return j; }; a.moveToArc = function (a, b, c) { if (c == null) { if (b.strafeDirection == 0) { b.strafeDirection = 1; } a.turn(b.strafeDirection); return; } var d = c.arc; if (c.direction == 0) { c.direction = 1; } if (d.radius < 1e-3) { a.turn(c.direction); return; } var e = d.centerPoint; var f = b.position; var g = b.direction.scale(c.getMoveSign(b)); var h = f.add(g); var i = e.distanceTo(h); if (i > d.radius) { a.turn(c.direction); return; } a.move(1, c.getMoveSign(b)); }; a.driveWithin = function (a, b) { var c = b.position; var d = b.arena.borderRect.minDistanceToPoint(c); var e = b.arena.borderRect.minDistanceToPoint(c.add(b.direction)); if (Math.abs(d - e) > 0.2) { if (e > d) { a.move(1, 1); } else { a.move(1, -1); } } else { a.turn(1); } b.arcAndDirection = null; }; a.initialize = function (a, b) { try { var c = b.position; var d = b.cannonDirection; var e = this.otherState(b); if (e == null) { var f = c.vectorTo(b.arena.centerPoint()); var g = d.signedAngleTo(f); if (g > 0) { a.rotateCannon(1); b.strafeDirection = 1; } else { a.rotateCannon(-1); b.strafeDirection = -1; } } else { if (e.position == null) { return; } var h = e.position; var i = c.vectorTo(h); var j = d.signedAngleTo(i); a.rotateCannon(-1 * b.sign(j)); b.strafeDirection = -1 * b.sign(j); } b.isInitialized = true; } catch (k) { } }; a.canFire = function (a) { var b = this.otherState(a); if (b == null) { return true; } if (Math.abs(a.time - b.time) > 10) { return true; } var c = a.position; var e = new d(c, a.cannonDirection); var f = b.position; var g = e.closestPoint(f); if (!g.isOnRay(e)) { return true; } return g.distanceTo(f) > (1.5 * a.arena.radius); }; a.getState = function (a) { var b = (a.parentId == null) ? this.parentState : this.cloneState; return b; }; a.otherState = function (a) { var b = a.parentId == null ? this.cloneState : this.parentState; return b; }; a.strafeArc = function (a, b) { var c = b.position; var d = b.tracker.isTracking(b); var e = b.tracker.isHunting(b); if (!d && !e) { return new f(b.arena.centerPoint(), b.arena.centerPoint().distanceTo(c)); } if (e && !d) { var g = b.tracker.last(null).robot.position; return new f(g, g.distanceTo(c)); } var h = b.tracker.predict(b, 0, null); return new f(h, c.distanceTo(h)); }; a.idealPoint = function (a, b) { var c = b.position; if (!b.tracker.isHunting(b)) { return c; } var d = this.strafeArc(a, b); var f = b.tracker.predict(b, 0, null); var g = b.tracker.lastTrackingScans(null, b); var h = g.last().robot.direction; var i = d.centerPoint; var j = i.vectorTo(c); if (b.tracker.isWallHugger(null, b)) { return b.arena.centerPoint(); } var k = d.getIntersectionPoints(new e(f.add(h.scale(-2 * d.radius)), f.add(h.scale(2 * d.radius)))); if (k.length < 2) { return b.arena.centerPoint(); } var l = this.createIdealPoint(b, i, k[0]); var m = i.vectorTo(l); var n = j.signedAngleTo(m); var o = Math.acos(Math.abs(h.normalize().dotProduct(m.normalize()))) * 180 / Math.PI; if (Math.abs(n) < 90 && Math.abs(o) < 10) { return l; } var p = this.createIdealPoint(b, i, k[1]); var q = i.vectorTo(p); var r = j.signedAngleTo(q); var s = Math.acos(Math.abs(h.normalize().dotProduct(q.normalize()))) * 180 / Math.PI; if (Math.abs(r) < 90 && Math.abs(s) < 10) { return p; } if (Math.abs(n) < Math.abs(r)) { return l; } return p; }; a.createIdealPoint = function (a, b, c) { var e = a.position; var f = b.vectorTo(c); var g = b.vectorTo(e); var h = a.arena.marginRect.getDistToIntersection(new d(b, f), true); var i = a.arena.marginRect.getDistToIntersection(new d(b, f.rotate(10)), true); var j = a.arena.marginRect.getDistToIntersection(new d(b, f.rotate(-10)), true); var k = Math.min(h, Math.max(i, j)); if (k > 150) { var l = b.add(f.normalize().scale(k)); l = a.arena.marginRect.trimToWithin(l, 15); if (b.distanceTo(l) > 100) { return l; } } var m = a.arena.marginRect.getInterSectingLines(new d(b, f), true)[0]; var n = m.vectorFromPointToClosestPoint(b); if (m.direction().dotProduct(f) > 0) { var o = m.endPoint.add(m.direction().scale(-30)); var p = o.add(n.normalize().scale(-150)); return p; } else { var o = m.startPoint.add(m.direction().scale(30)); var p = o.add(n.normalize().scale(-150)); return p; } }; function b(a, b) { this.x = a; this.y = b; } b.FromAngle = function (a) { return new b(Math.sin(a * Math.PI / 180), -1 * Math.cos(a * Math.PI / 180)); }; b.FromBearing = function (a, c) { return b.FromAngle(a).rotate(c); }; b.prototype.normalize = function () { return new b(this.x / this.length(), this.y / this.length()); }; b.prototype.scale = function (a) { return new b(a * this.x, a * this.y); }; b.prototype.flip = function () { return this.scale(-1); }; b.prototype.dotProduct = function (a) { return a.x * this.x + a.y * this.y; }; b.prototype.signedAngleTo = function (a) { var b = -1 * (Math.atan2(this.y, this.x) - Math.atan2(a.y, a.x)) * 180 / Math.PI; if (b < -179.9) { return 360 + b; } if (b > 180) { return b - 360; } return b; }; b.prototype.positiveAngleto = function (a) { var b = this.signedAngleTo(a); if (b < 0) { b += 360; } return b; }; b.prototype.getPerpendicular = function () { return new b(this.y, -1 * this.x); }; b.prototype.rotate = function (a) { var c = b.FromAngle(0).signedAngleTo(this); return b.FromAngle(c + a).scale(this.length()); }; b.prototype.isParallelTo = function (a) { return Math.abs(this.normalize().dotProduct(a.normalize())) > (1 - 1E-6); }; b.prototype.length = function () { return Math.sqrt(this.x * this.x + this.y * this.y); }; b.prototype.nextOrtho = function (a) { var c = b.FromAngle(0).signedAngleTo(this); if (c < 0) { c += 360; } var d = c % 90; if (Math.abs(d) > 1e-2) { if (a < 0) { return b.FromAngle(c - d); } else { return b.FromAngle(c + 90 - d); } } return b.FromAngle(c + a * 90); }; b.prototype.toString = function () { return "(" + this.x.toFixed(1) + ", " + this.y.toFixed(1) + ")"; }; b.prototype.equals = function (a) { return(Math.abs(this.x - a.x) + Math.abs(this.y - a.y)) < 1E-3; }; function c(a, b) { this.x = a; this.y = b; } c.prototype.add = function (a) { return new c(this.x + a.x, this.y + a.y); }; c.prototype.vectorTo = function (a) { return new b(a.x - this.x, a.y - this.y); }; c.prototype.distanceTo = function (a) { return this.vectorTo(a).length(); }; c.prototype.isWithin = function (a, b) { return a.isPointWithin(this, b); }; c.prototype.isOnLine = function (a) { return a.isPointOnLine(this); }; c.prototype.isOnRay = function (a) { return a.isPointOnRay(this); }; c.prototype.trimToWithin = function (a, b) { return a.trimToWithin(this, b); }; c.prototype.equals = function (a) { return(Math.abs(this.x - a.x) + Math.abs(this.y - a.y)) < 1E-3; }; c.prototype.toString = function () { return "(" + this.x.toFixed(1) + ", " + this.y.toFixed(1) + ")"; }; function d(a, b) { this.startPoint = a; this.direction = b; } d.prototype.intersectionPoint = function (a) { var b = this.startPoint.x; var f = this.startPoint.y; var g = this.startPoint.x + this.direction.x; var h = this.startPoint.y + this.direction.y; var i = a.startPoint.x; var j = a.startPoint.y; var k = 0; var l = 0; if (a instanceof d) { k = a.startPoint.x + a.direction.x; l = a.startPoint.y + a.direction.y; } else if (a instanceof e) { k = a.endPoint.x; l = a.endPoint.y; } var m = ((g - b) * (i * l - k * j) - (k - i) * (b * h - g * f)) / ((b - g) * (j - l) - (f - h) * (i - k)); var n = ((j - l) * (b * h - g * f) - (f - h) * (i * l - k * j)) / ((b - g) * (j - l) - (f - h) * (i - k)); return new c(m, n); }; d.prototype.intersectsWith = function (a) { if (a instanceof d) { if (this.direction.isParallelTo(a.direction)) { return false; } } if (a instanceof e) { if (this.direction.isParallelTo(a.direction())) { return false; } } var b = this.intersectionPoint(a); if (!this.isPointOnRay(b)) { return false; } if (a instanceof d) { return a.isPointOnRay(b); } if (a instanceof e) { return a.isPointOnLine(b); } return true; }; d.prototype.isPointOnRay = function (a) { if (this.startPoint.distanceTo(a) < 1E-3) { return true; } var b = this.startPoint.vectorTo(a); if (!b.isParallelTo(this.direction)) { return false; } return b.dotProduct(this.direction) > 0; }; d.prototype.offset = function (a) { return new d(this.startPoint.add(a), this.direction); }; d.prototype.vectorFromPointToClosestPoint = function (a) { return a.vectorTo(this.closestPoint(a)); }; d.prototype.closestPoint = function (a) { var b = this.startPoint.vectorTo(a); var c = b.dotProduct(this.direction); if (Math.abs(c) < 1e-4) { return this.startPoint; } var d = this.direction.scale(c); var e = this.startPoint.add(d); return e; }; d.prototype.equals = function (a) { return this.startPoint.equals(a.startPoint) && this.direction.equals(a.direction); }; d.prototype.toString = function () { return "{" + this.startPoint + "; " + this.direction + "}"; }; function e(a, b) { this.startPoint = a; this.endPoint = b; } e.prototype.direction = function () { return this.startPoint.vectorTo(this.endPoint).normalize(); }; e.prototype.length = function () { return this.startPoint.vectorTo(this.endPoint).length(); }; e.prototype.intersectionPoint = function (a) { var b = new d(this.startPoint, this.direction()); var c = 0; if (a instanceof e) { c = new d(a.startPoint, a.direction()); } if (a instanceof d) { c = a; } return b.intersectionPoint(c); }; e.prototype.intersectsWith = function (a) { var b = new d(this.startPoint, this.direction()); var c = (a instanceof e) ? new d(a.startPoint, a.direction()) : a; if (!b.intersectsWith(c)) { return false; } var f = b.intersectionPoint(c); if (a instanceof e) { if (!f.isOnLine(a)) { return false; } } if (a instanceof d) { if (!f.isOnRay(a)) { return false; } } return f.isOnLine(this); }; e.prototype.isPointOnLine = function (a) { if (this.startPoint.distanceTo(a) < 1E-3) { return true; } var b = this.startPoint.vectorTo(a); if (!b.isParallelTo(this.direction())) { return false; } var c = b.dotProduct(this.direction()); return 0 <= c && c <= this.length(); }; e.prototype.distanceToPoint = function (a) { var b = this.startPoint.vectorTo(a); return Math.abs(b.dotProduct(this.direction().getPerpendicular())); }; e.prototype.vectorFromPointToClosestPoint = function (a) { var b = this.closestPoint(a); return a.vectorTo(b); }; e.prototype.closestPoint = function (a) { var b = this.startPoint.vectorTo(a); var c = b.dotProduct(this.direction()); if (Math.abs(c) < 1e-4) { return this.startPoint; } var d = this.direction().scale(c); var e = this.startPoint.add(d); return e; }; e.prototype.equals = function (a) { return this.startPoint.equals(a.startPoint) && this.endPoint.equals(a.endPoint); }; e.prototype.toString = function () { return "{ " + this.startPoint + "; " + this.endPoint + ";" + this.direction() + "}"; }; function f(a, b) { this.centerPoint = a; this.radius = Math.abs(b); } f.FromRayAndLine = function (a, b) { var c = b.direction().signedAngleTo(a.direction); var d = c > 0 ? 1 : -1; var e = a.direction.rotate(d * 90); var g = Math.abs(a.startPoint.vectorTo(b.startPoint).dotProduct(b.direction().getPerpendicular())); var h = -1 * g / (Math.cos(c * Math.PI / 180) - 1); var i = a.startPoint.add(e.scale(-1 * h)); if (Math.abs(b.distanceToPoint(i) - h) > h / 100) { i = a.startPoint.add(e.scale(h)); } return new f(i, h); }; f.getDistanceToStartPoint = function (a, c, e) { var f = c.direction().signedAngleTo(a.direction); var g = f > 0 ? 1 : -1; var h = a.direction.rotate(g * 90); var i = b.FromAngle(0).signedAngleTo(h); if (i < 0) { i += 360; } var j = c.direction().rotate(g * 90); var k = b.FromAngle(0).signedAngleTo(j); if (k < 0) { k += 360; } var l = Math.abs(a.startPoint.vectorTo(c.startPoint).dotProduct(c.direction().getPerpendicular())); var m = -1 * l / (Math.cos(f * Math.PI / 180) - 1); if (m < e) { return 0; } m = e; var n = b.FromAngle(i); var o = new d(a.startPoint.add(n.scale(-1 * m)), a.direction); var p = b.FromAngle(k); var q = new d(c.startPoint.add(p.scale(-1 * m)), c.direction()); var r = o.intersectionPoint(q); if (o.startPoint.vectorTo(r).dotProduct(o.direction) > 0) { return o.startPoint.distanceTo(r); } return 0; }; f.getTangentPoint = function (a, b, c) { var e = new d(a, b); var f = new d(c, b.getPerpendicular()); return e.intersectionPoint(f); }; f.prototype.getIntersectionPoints = function (a) { var b = []; var c = this.centerPoint; var d = a.distanceToPoint(this.centerPoint); if (d > 0.1) { var e = a.vectorFromPointToClosestPoint(this.centerPoint); if (e.length() > this.radius) { return b; } c = this.centerPoint.add(e); } var f = Math.sqrt(Math.pow(this.radius, 2) - Math.pow(d, 2)); var g = c.add(a.direction().scale(f)); var h = c.add(a.direction().scale(-1 * f)); if (a.isPointOnLine(g)) { b.push(g); } if (a.isPointOnLine(h)) { b.push(h); } return b; }; f.prototype.arcLengthFromAngle = function (a) { return 2 * Math.PI * this.radius * Math.abs(a) / 360; }; f.prototype.angleLeft = function (a, b, c) { var d = 360.0; var e = this.centerPoint.vectorTo(a); for (var f = 0; f < c.lines.length; f++) { var g = c.lines[f]; var h = this.getIntersectionPoints(g); for (var i = 0; i < h.length; i++) { var j = this.centerPoint.vectorTo(h[i]); var k = e.signedAngleTo(j); if (k * b > 0 && Math.abs(k) < d) { d = Math.abs(k); } } } return d; }; f.prototype.angleLeftToPoint = function (a, b, c) { var d = this.centerPoint.vectorTo(a); var e = this.centerPoint.vectorTo(b); var f = d.positiveAngleto(e); return c > 0 ? f : 360 - f; }; f.prototype.isPointOnArc = function (a, c, d, e) { var f = this.centerPoint.distanceTo(a.startPoint); if (f < d) { return false; } if (e != null) { if (f > e) { return false; } } var g = this.centerPoint.vectorTo(a.startPoint).normalize(); var h = Math.abs(g.dotProduct(a.direction)); var i = b.FromAngle(c).dotProduct(b.FromAngle(90)); return h < i; }; f.prototype.signedAngleToTangent = function (a) { var b = this.positiveTangentDirection(a.startPoint); if (b.dotProduct(a.direction) > 0) { return a.direction.signedAngleTo(b); } return a.direction.signedAngleTo(b.flip()); }; f.prototype.positiveTangentDirection = function (a) { return this.centerPoint.vectorTo(a).normalize().rotate(90); }; f.prototype.angleAtPos = function (a) { if (a.distanceTo(this.centerPoint) < 1) { return 0; } return b.FromAngle(0).positiveAngleto(this.centerPoint.vectorTo(a)); }; f.prototype.posAtAngle = function (a) { var c = b.FromAngle(0).rotate(a); return this.centerPoint.add(c.scale(this.radius)); }; function g(a, b) { var d = a; var f = new c(b.x, a.y); var g = b; var h = new c(a.x, b.y); this.lines = [new e(d, f), new e(f, g), new e(g, h), new e(h, d)]; this.minX = Math.min(Math.min(d.x, f.x), Math.min(g.x, h.x)); this.maxX = Math.max(Math.max(d.x, f.x), Math.max(g.x, h.x)); this.minY = Math.min(Math.min(d.y, f.y), Math.min(g.y, h.y)); this.maxY = Math.max(Math.max(d.y, f.y), Math.max(g.y, h.y)); } g.prototype.trimToWithin = function (a, b) { var d = a.x; var e = a.y; if (d < (this.minX + b)) { d = this.minX + b; } if (d > (this.maxX - b)) { d = this.maxX - b; } if (e < (this.minY + b)) { e = this.minY + b; } if (e > (this.maxY - b)) { e = this.maxY - b; } return new c(d, e); }; g.prototype.isPointWithin = function (a, b) { return this.minX - b <= a.x && a.x <= this.maxX + b && this.minY - b <= a.y && a.y <= this.maxY + b; }; g.prototype.getDistToIntersection = function (a, b) { var c = this.getIntersectionPoints(a, b)[0]; return a.startPoint.distanceTo(c); }; g.prototype.getIntersectingLine = function (a, b) { return this.getInterSectingLines(a, b)[0]; }; g.prototype.getIntersectionPoints = function (a, b) { var c = []; var e = a; if (b) { if (!a.startPoint.isWithin(this, 0)) { e = new d(this.trimToWithin(a.startPoint, 1), a.direction); } } for (var f = 0; f < this.lines.length; f += 1) { var g = this.lines[f]; if (e.intersectsWith(g)) { var h = e.intersectionPoint(g); if (e.isPointOnRay(h)) { c.push(h); } } } if (c.length > 1) { if (e.startPoint.distanceTo(c[1]) < e.startPoint.distanceTo(c[0])) { var i = c[0]; c[0] = c[1]; c[1] = i; } } return c; }; g.prototype.getInterSectingLines = function (a, b) { var c = []; var e = a; if (b) { if (!a.startPoint.isWithin(this, 0)) { e = new d(this.trimToWithin(a.startPoint, 1), a.direction); } } for (var f = 0; f < this.lines.length; f += 1) { var g = this.lines[f]; if (e.intersectsWith(g)) { var h = e.intersectionPoint(g); if (e.isPointOnRay(h)) { c.push(g); } } } if (c.length > 1) { var i = e.intersectionPoint(c[0]); var j = e.intersectionPoint(c[1]); if (e.startPoint.distanceTo(j) < e.startPoint.distanceTo(i)) { var k = c[0]; c[0] = c[1]; c[1] = k; } } return c; }; g.prototype.minDistanceToPoint = function (a) { var b = Math.max(this.maxX, this.maxY); var c = this.isPointWithin(a, 1E-3) ? 1 : -1; for (var d = 0; d < this.lines.length; d++) { var e = this.lines[d]; var f = e.distanceToPoint(a); if (f < b) { b = f; } } return c * b; }; g.prototype.getClosestLines = function (a) { var b = this.lines.slice(0); var c = true; do { c = false; for (var d = 0; d < b.length - 1; d++) { if (b[d].distanceToPoint(a) > b[d + 1].distanceToPoint(a)) { var e = b[d]; b[d] = b[d + 1]; b[d + 1] = e; c = true; } } } while (c); return b; }; g.prototype.equals = function (a) { return this.minX === a.minX && this.maxX === a.minX && this.minY === a.minY && this.maxY === a.maxY; }; g.prototype.toString = function () { return "minPoint: " + new c(this.minX, this.minY) + " maxPoint: " + new c(this.maxX, this.maxY); }; function h(a) { this.padding = 26; this.radius = 12; this.width = a.arenaWidth; this.height = a.arenaHeight; this.seekRadius = 360 / (2 * Math.PI); this.scanRadius = (Math.min(this.width, this.height) / 4 - this.padding); this.attackRadius = this.scanRadius - 5; this.huntRadius = this.scanRadius + 10; var b = new c(this.radius, this.radius); var d = new c(this.width - this.radius, this.height - this.radius); this.marginRect = new g(b, d); var e = new c(0, 0); var f = new c(this.width, this.height); this.borderRect = new g(e, f); this.tempRect = null; this.tempRectExpiryTime = 0; } h.prototype.centerPoint = function () { return new c(this.borderRect.maxX / 2, this.borderRect.maxY / 2); }; function i() { this.parentScans = new o(); this.cloneScans = new o(); this.unknownScans = new o(); } i.prototype.push = function (a, b) { var c = this.last(a.id); if (c != null) { if (b.time < (c.time + 10)) { return; } } var d = new m(a, b.time); if (!d.isOpponent(b)) { return; } if (d.isParent()) { this.parentScans.push(d); } else if (d.isClone()) { this.cloneScans.push(d); } else if (d.isUnknown()) { this.unknownScans.push(d); } }; i.prototype.any = function (a) { if (a == null) { return this.parentScans.any() || this.cloneScans.any(); } if (this.parentScans.id == a) { return this.parentScans.any(); } if (this.cloneScans.id == a) { return this.cloneScans.any(); } return false; }; i.prototype.lastTime = function () { if (this.last(null) == null) { return -5000; } return this.last(null).time; }; i.prototype.timeSinceLast = function (a, b) { if (!this.any(b)) { return 10000; } return a.time - this.last(b).time; }; i.prototype.last = function (a) { if (!this.any(a)) { return null; } return this.lastScans(a).last(); }; i.prototype.lastScans = function (a) { if (a == null) { if (!this.parentScans.any() && !this.cloneScans.any()) { return null; } if (this.parentScans.any() && !this.cloneScans.any()) { return this.parentScans; } if (!this.parentScans.any() && this.cloneScans.any()) { return this.cloneScans; } return this.parentScans.lastTime() > this.cloneScans.lastTime() ? this.parentScans : this.cloneScans; } var b = this.parentScans.id == a ? this.parentScans : this.cloneScans; return b; }; i.prototype.lastTrackingScans = function (a, b) { var c = this.lastScans(a); if (a == null) { if (this.parentScans.isTracking(b) && this.cloneScans.isTracking(b)) { c = this.parentScans.lastTime() < this.cloneScans.lastTime() ? this.cloneScans : this.parentScans; } else if (this.parentScans.isTracking(b) && !this.cloneScans.isTracking(b)) { c = this.parentScans; } else if (!this.parentScans.isTracking(b) && this.cloneScans.isTracking(b)) { c = this.cloneScans; } } return c; }; i.prototype.lastUnknown = function () { return this.unknownScans.any() ? this.unknownScans.last() : null; }; i.prototype.predict = function (a, b, c) { if (!this.any(c)) { return null; } var d = this.lastTrackingScans(c, a); if (!d.isTracking(a)) { return d.last().robot.position; } if (d.isWallHugger(a)) { return this.predictWallHugger(a, d, b); } var e = d.speed(a, 5); var f = d.timeSinceLast(a); var g = f + b; var h = d.last().robot.position; if (g < 0) { return h; } var i = d.last().robot.direction; var j = i; var k = h; var l = d.averageTurnSpeed(a, 5); if (d.stdDevTurnSpeed(a, 5, 0) > 0.1) { l = 0; } for (var m = 0; m < g; m++) { k = k.add(j.scale(e)); j = j.rotate(l); if (!k.isWithin(a.arena.marginRect, 0)) { e *= -1; } var n = this.collisionPoint(k, k.add(j.scale(e)), a); if (n != null) { return n; } } return k; }; i.prototype.isWallHugger = function (a, b) { var c = this.lastTrackingScans(a, b); if (!c.isTracking(b)) { return false; } return c.isWallHugger(b); }; i.prototype.predictWallHugger = function j(a, b, c) { var f = b.speed(a, 5); if (Math.abs(f) < 1e-2) { return b.last().robot.position; } var g = b.timeSinceLast(a) + c; var h = b.last().robot.position; if (Math.abs(g) < 1) { return h; } var i = b.last().robot.direction.scale(a.sign(f)); var j = new d(h, i); var k = a.arena.marginRect.getInterSectingLines(j, true); var l = k.length > 0 ? k[0] : a.arena.marginRect.lines[0]; if (h.distanceTo(l.startPoint) > h.distanceTo(l.endPoint)) { l = new e(l.endPoint, l.startPoint); } var m = h.add(i.scale(Math.abs(f) * g)); if (!a.arena.marginRect.isPointWithin(m, 1)) { var n = a.arena.marginRect.getDistToIntersection(j, true); var o = Math.abs(n / f); var p = n > 1 ? h.add(i.scale(n)) : h; g -= o; var q = l.direction(); var r = Math.abs(b.lastStep().angleDiff()) > 1 ? b.lastStep().angleDiff() / Math.abs(b.lastStep().angleDiff()) : a.sign(i.signedAngleTo(q)); while (!i.isParallelTo(q)) { i = i.rotate(r); g--; } if (g > 0) { m = p.add(i.scale(Math.abs(f) * g)); } } return m; }; i.prototype.nextSeekPoint = function (a, b) { var c = b.tracker.lastTrackingScans(null, b).timeSinceLast(b); var d = c < 25 ? 50 - c : 25.0; var e = this.lastTrackingScans(null, b); if (b.arcAndDirection == null) { return new n(this.getSeekPoint(b, d, true, e.id), q.maxSeekArcEnum(), d); } this.updateSeekStatus(b, e); if (e.isTracking(b) && b.arcAndDirection.isAttacArc()) { if (!e.hasSoughtStd) { return new n(this.predict(b, d, null), q.stdSeekArcEnum(), d); } if (e.hasSoughtMax && e.hasSoughtMin) { return new n(b.position, q.scanArcEnum(), 0); } if (e.hasSoughtStd && !e.hasSoughtMin && !b.arcAndDirection.isMinSeekArc()) { return new n(this.getSeekPoint(b, d, false, e.id), q.minSeekArcEnum(), d); } if (e.hasSoughtStd && !e.hasSoughtMax && !b.arcAndDirection.isMaxSeekArc()) { return new n(this.getSeekPoint(b, d, true, e.id), q.maxSeekArcEnum(), d); } } else if (e.isTracking(b)) { var f = this.getAttackPoint(a, b, e.id); var g = b.tracker.lastTrackingScans(null, b).last().robot.position; var h = g.vectorTo(f); if (!e.hasSoughtMin && !b.arcAndDirection.isMinSeekArc()) { var i = this.getSeekPoint(b, d, false, e.id); var j = g.vectorTo(i); if (h.dotProduct(j) < 0) { return new n(i, q.minSeekArcEnum(), d); } return new n(f, q.attackArcEnum(), a.gunCoolDownTime); } if (!e.hasSoughtMax && !b.arcAndDirection.isMaxSeekArc()) { var k = this.getSeekPoint(b, d, true, e.id); var j = g.vectorTo(k); if (h.dotProduct(j) < 0) { return new n(k, q.maxSeekArcEnum(), d); } return new n(f, q.attackArcEnum(), a.gunCoolDownTime); } } else if (e.isHunting(b)) { if (e.hasSoughtMax && e.hasSoughtMin) { return new n(b.position, q.scanArcEnum(), 0); } if (!e.hasSoughtMin && !b.arcAndDirection.isMinSeekArc()) { return new n(this.getSeekPoint(b, d, false, e.id), q.minSeekArcEnum(), d); } if (!e.hasSoughtMax && !b.arcAndDirection.isMaxSeekArc()) { return new n(this.getSeekPoint(b, d, true, e.id), q.maxSeekArcEnum(), d); } } return new n(b.position, q.scanArcEnum(), 0); }; i.prototype.updateSeekStatus = function (a, b) { var c = b.timeSinceLast(a); if (c < 50) { return; } var d = false; var e = false; if (c > 50 && a.arcAndDirection.isPastEnd(a, a.arcAndDirection.targetPoint)) { if (a.arcAndDirection.isMaxSeekArc()) { e = true; } if (a.arcAndDirection.isMinSeekArc()) { d = true; } if (a.arcAndDirection.isStdSeekArc()) { b.hasSoughtStd = true; } } if (a.arcAndDirection.isAttacArc()) { var f = this.getSeekPoint(a, 0, true, b.id); var g = a.time - a.arcAndDirection.targetTime; if (g < 0) { g = 5; } var h = new q(a, f, g, q.maxSeekArcEnum()); if (h.isPastEnd(a, f)) { e = true; } var i = this.getSeekPoint(a, 0, false, b.id); h = new q(a, i, g, q.minSeekArcEnum()); if (h.isPastEnd(a, i)) { d = true; } } if (b.parentId != null) { b.hasSoughtMin = d || b.hasSoughtMin; b.hasSoughtMax = e || b.hasSoughtMax; } else { if (d) { b.hasSoughtMin = true; b.hasSoughtMax = false; } if (e) { b.hasSoughtMin = false; b.hasSoughtMax = true; } } }; i.prototype.getSeekPoint = function k(a, b, c, d) { var e = this.lastTrackingScans(d, a); var f = e.last().robot.direction; var g = e.last().robot.position; var h = e.speed(a, 5) < 0 ? -1 : 1; var i = f.scale(h); var j = e.timeSinceLast(a); var k = j + b; if (Math.abs(k) < 1) { return g; } var l = c ? g.add(i.scale(k)) : g.add(i.scale(-1 * k)); var m = this.collisionPoint(g, l, a); if (m != null) { return m; } return l; }; i.prototype.collisionPoint = function (a, b, c) { var d = new e(a, b); if (d.length() < 0.1) { return null; } var f = c.position; var g = d.closestPoint(f); var h = g.isOnLine(d); var i = g.distanceTo(f); if (h && i < 2 * c.arena.radius) { return a.add(d.direction().scale(Math.min(a.distanceTo(f), a.distanceTo(f) - 2 * c.arena.radius))); } return null; }; i.prototype.getTimeToAttackPos = function (a, b, c) { var d = b.position.distanceTo(this.last(c).robot.position); var e = this.predict(b, a.gunCoolDownTime + d / 2, c); d = b.position.distanceTo(e); return a.gunCoolDownTime + d / 2; }; i.prototype.getAttackPoint = function l(a, b, c) { var d = this.getTimeToAttackPos(a, b, c); var e = this.predict(b, d, c); return e; }; i.prototype.isHunting = function (a) { if (!this.any(null)) { return false; } return this.lastTrackingScans(null, a).isHunting(a); }; i.prototype.isTracking = function (a) { if (!this.any(null)) { return false; } return this.lastTrackingScans(null, a).isTracking(a); }; function m(a, b) { this.robot = a; this.time = b; this.robot.position = new c(a.position.x, a.position.y); this.robot.cannonDirection = this.getOpponentCannonDirectionFromAngle(a.cannonAngle, a.angle); if (a.id != null) { this.robot.direction = this.getOpponentDirectionFromAngle(a.angle); } } m.prototype.getOpponentDirectionFromAngle = function (a) { return b.FromAngle(a + 90); }; m.prototype.getOpponentCannonDirectionFromAngle = function (a, c) { return b.FromAngle(a + c + 90); }; m.prototype.isUnknown = function () { return this.robot.id == null; }; m.prototype.isParent = function () { return this.robot.id != null && this.robot.parentId == null; }; m.prototype.isClone = function () { return this.robot.id != null && this.robot.parentId != null; }; m.prototype.isOpponent = function (a) { if (this.isUnknown()) { return true; } return this.robot.parentId != a.id && this.robot.id != a.parentId; }; function n(a, b, c) { this.targetPoint = a; this.arcEnum = b; this.targetTimeOffset = c; } function o() { this.data = []; this.id = null; this.parentId = null; this.hasSoughtMax = false; this.hasSoughtMin = false; this.hasSoughtStd = false; } o.prototype.push = function (a) { this.data.push(a); this.id = a.robot.id; this.parentId = a.robot.parentId; this.hasSoughtStd = false; this.hasSoughtMin = false; this.hasSoughtMax = false; }; o.prototype.speed = function (a, b) { if (this.data.length < 2) { return 0.4; } if (this.isWallHugger(a)) { return this.wallSpeed(a, 5); } if (this.data.length == 2) { return this.lastStep().speed(a); } var c = this.averageTurnSpeed(a, b); var d = this.stdDevTurnSpeed(a, b, 0); var e = this.averageMoveRatio(a, 5); var f = this.stdDevMoveRatio(a, 5, 0.1); var g = this.stepsTo(b); var h = 0.0; var i = 0; for (var j = 0; j < g.length; j++) { var k = g[j]; var l = k.turnSpeed(); var m = (!(d > 0.1)) || l < c; var n = k.suspectFlip(e - 2 * f); if (n != true && m) { h += Math.abs(k.speed(a)); i++; if (i > 2) { break; } } } var o = (i == 0) ? this.lastStep().speed(a) : h / i; var p = this.lastSpeedSign(a); return p * o < 0 ? p * o : o; }; o.prototype.wallSpeed = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = 0; var d = this.stepsTo(b); var e = 0.0; for (var f = 0; f < d.length; f++) { var g = d[f]; if (g.hasWallSpeed(a)) { var h = g.wallSpeed(a); e += Math.abs(h); c++; if (c > 2) { break; } } } var i = c > 0 ? e / c : Math.max(Math.abs(this.maxSpeed(a, 5)), Math.abs(this.minSpeed(a, 5)), 0.1); var j = this.lastSpeedSign(a); return j * i < 0 ? j * i : i; }; o.prototype.lastSpeedSign = function (a) { if (this.data.length < 2) { return 1; } if (this.data.length == 2) { return this.lastStep().speedSign(); } var b = this.averageMoveRatio(a, 5); var c = this.stdDevMoveRatio(a, 5, 0.1); var d = this.lastStep(); var e = this.previousStep(); var f = 3; while (!e.hasSpeed()) { if (this.data.length <= f) { return d.speedSign(); } e = this.stepTo(this.data.length - f); f++; } if ((d.isWallHugger(a) && d.hasWallSpeed(a)) || (!d.isWallHugger(a) && d.turnSpeed() < 0.3 && d.cannonTurnSpeed() < 0.3)) { if (d.suspectFlip(b - 2 * c) != true) { return d.speedSign(); } return d.speedSign() * e.speedSign() > 0 ? -1 * d.speedSign() : d.speedSign(); } return e.speedSign(); }; o.prototype.averageSpeed = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = this.stepsTo(b); var d = 0.0; var e = 0; for (var f = 0; f < c.length; f++) { var g = c[f]; if (g.hasSpeed()) { d += g.speed(a); e++; } } if (e == 0) { return 0.1; } return d / e; }; o.prototype.maxSpeed = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = this.stepsTo(b); var d = -1.0; for (var e = 0; e < c.length; e++) { var f = c[e]; if (f.hasSpeed()) { var g = f.speed(a); if (g > d) { d = g; } } } return d; }; o.prototype.minSpeed = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = this.stepsTo(b); var d = 1.0; for (var e = 0; e < c.length; e++) { var f = c[e]; if (f.hasSpeed()) { var g = f.speed(a); if (g < d) { d = g; } } } return d; }; o.prototype.stdDevSpeed = function (a, b, c) { var d = this.averageSpeed(a, b); var e = this.stepsTo(b); var f = 0.0; for (var g = 0; g < e.length; g++) { var h = e[g].speed(a); f += Math.pow(h - d, 2); } var i = Math.sqrt(f) / e.length; return i < c ? c : i; }; o.prototype.averageMoveRatio = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = this.stepsTo(b); var d = 0.0; var e = 0; for (var f = 0; f < c.length; f++) { var g = c[f]; if (g.hasSpeed()) { var h = g.moveRatio(); d += h; e++; } } if (e == 0) { return this.lastStep().moveRatio(); } return d / b; }; o.prototype.stdDevMoveRatio = function (a, b, c) { var d = this.averageMoveRatio(a, b); var e = this.stepsTo(b); var f = 0; var g = 0.0; for (var h = 0; h < e.length; h++) { var i = e[h]; if (i.hasSpeed()) { var j = i.moveRatio(); g += Math.pow(j - d, 2); f++; } } if (f == 0) { return c; } var k = Math.sqrt(g) / f; return k < c ? c : k; }; o.prototype.averageTurnSpeed = function (a, b) { if (this.data.length < 2) { return 0; } b = this.data.length < (b + 1) ? this.data.length - 1 : b; var c = this.stepsTo(b); var d = 0.0; for (var e = 0; e < c.length; e++) { d += c[e].turnSpeed(); } return d / b; }; o.prototype.stdDevTurnSpeed = function (a, b, c) { var d = this.averageTurnSpeed(a, b); var e = this.stepsTo(b); var f = 0.0; for (var g = 0; g < e.length; g++) { var h = e[g].turnSpeed(); f += Math.pow(h - d, 2); } var i = Math.sqrt(f) / e.length; return i < c ? c : i; }; o.prototype.cannonTurnSpeed = function (a) { if (this.data.length < 2) { return 0; } a = this.data.length < (a + 1) ? this.data.length - 1 : a; var b = this.stepsTo(a); var c = 0.0; for (var d = 0; d < b.length; d++) { c += b[d].cannonTurnSpeed(); } return c / a; }; o.prototype.stepTo = function (a) { return new p(this.data[a - 1], this.data[a]); }; o.prototype.stepsTo = function (a) { var b = []; var c = 0; var d = this.data.length - 1; while (c < a && d > 0) { b.push(this.stepTo(d)); c++; d--; } return b; }; o.prototype.last = function () { if (!this.any()) { return null; } return this.data[this.data.length - 1]; }; o.prototype.lastStep = function () { return this.stepTo(this.data.length - 1); }; o.prototype.previousStep = function () { return this.stepTo(this.data.length - 2); }; o.prototype.any = function () { return this.data.length != 0; }; o.prototype.isWallHugger = function (a) { var b = this.last().robot.position; var c = this.last().robot.direction; var d = a.arena.borderRect.getClosestLines(b); var e = d[0].distanceToPoint(b); if (e < a.arena.radius + 2) { if (e < a.arena.radius + 2) { if (d[1].distanceToPoint(b) < a.arena.radius + 2) { return !a.arena.marginRect.isPointWithin(b.add(c.scale(5)), 0) && !a.arena.marginRect.isPointWithin(b.add(c.scale(5)), 0); } if (d[0].direction().isParallelTo(c)) { return true; } if (this.data.length == 1) { return false; } return this.lastStep().isWallHugger(a); } } return false; }; o.prototype.timeSinceLast = function (a) { if (!this.any()) { return 10000; } return a.time - this.last().time; }; o.prototype.isHunting = function (a) { if (!this.any()) { return false; } if (this.timeSinceLast(a) > 400) { return false; } if (this.last().robot.parentId != null) { if (this.hasSoughtMin && this.hasSoughtMax) { return false; } return this.timeSinceLast(a) < 200; } return true; }; o.prototype.isTracking = function (a) { if (!this.isHunting(a)) { return false; } if (this.data.length < 2) { return false; } return true; }; o.prototype.lastTime = function () { return this.any() ? this.last().time : -5000; }; function p(a, b) { this.previous = a; this.last = b; } p.prototype.previousRay = function () { return new d(this.previous.robot.position, this.previous.robot.direction); }; p.prototype.lastRay = function () { return new d(this.last.robot.position, this.last.robot.direction); }; p.prototype.timeStep = function () { return this.last.time - this.previous.time; }; p.prototype.vectorStep = function () { return this.previous.robot.position.vectorTo(this.last.robot.position); }; p.prototype.angleDiff = function () { return this.last.robot.angle - this.previous.robot.angle; }; p.prototype.cannonAngleDiff = function () { return this.last.robot.cannonAngle - this.previous.robot.cannonAngle; }; p.prototype.speed = function (a) { if (this.isWallHugger(a)) { return this.wallSpeed(a); } var b = this.vectorStep().length(); var c = this.timeStep(); if (Math.abs(b) < 1e-2) { return 0.01; } var d = this.speedSign(); var e = d * b / c; return e; }; p.prototype.wallSpeed = function (a) { var b = this.previous.robot.position; var c = a.arena.marginRect.getClosestLines(b)[0]; var d = this.last.robot.position; var e = a.arena.marginRect.getClosestLines(d)[0]; var f = this.timeStep(); var g = this.angleDiff(); var h = f - Math.abs(g); if (c == e) { var i = this.vectorStep().length(); if (Math.abs(i) < 1e-2) { return 0.01; } return this.speedSign() * i / h; } var j = this.previousRay(); var k = this.lastRay(); var l = j.intersectionPoint(k); var m = this.previous.robot.position.distanceTo(l) + l.distanceTo(this.last.robot.position); if (Math.abs(m) < 1e-2) { return 0.01; } return this.speedSign() * m / h; }; p.prototype.hasSpeed = function () { var a = this.angleDiff(); var b = this.cannonAngleDiff(); var c = this.timeStep() - Math.abs(a) - Math.abs(b); if (c < 10) { return false; } var d = this.vectorStep().length(); return d > 10; }; p.prototype.hasWallSpeed = function (a) { if (!this.isWallHugger(a)) { return false; } var b = this.previous.robot.position; var c = a.arena.marginRect.getClosestLines(b)[0]; var d = this.last.robot.position; var e = a.arena.marginRect.getClosestLines(d)[0]; var f = this.timeStep(); var g = this.angleDiff(); if (Math.abs(g) > 10) { return false; } var h = this.cannonAngleDiff(); var i = f - Math.abs(g); if ((i - Math.abs(h)) < 10) { return false; } if (c.distanceToPoint(b) > (a.arena.radius + 2) || e.distanceToPoint(d) > (a.arena.radius + 2)) { return false; } if (this.vectorStep().length() < 10) { return false; } if (c != e) { var j = c.direction(); var k = e.direction(); if (j.isParallelTo(k)) { return false; } var l = this.previousRay(); var m = this.lastRay(); if (l.direction.isParallelTo(m.direction)) { return false; } } return true; }; p.prototype.speedSign = function () { var a = this.vectorStep(); if (a.length() < 1) { return 1; } return this.last.robot.direction.dotProduct(a) < 0 ? -1 : 1; }; p.prototype.turnSpeed = function () { var a = this.angleDiff() / (this.timeStep()); return a; }; p.prototype.cannonTurnSpeed = function () { var a = this.cannonAngleDiff() / (this.timeStep()); return a; }; p.prototype.suspectFlip = function (a) { var b = this.moveRatio(); var c = b < a && Math.abs(this.turnSpeed()) < 0.3 && Math.abs(this.cannonTurnSpeed()) < 0.3; return c; }; p.prototype.moveRatio = function () { var a = this.angleDiff(); var b = this.cannonAngleDiff(); var c = this.timeStep() - Math.abs(a) - Math.abs(b); if (Math.abs(c) < 5) { return 1; } var d = this.vectorStep().length(); return d / c; }; p.prototype.isWallHugger = function (a) { var b = this.last.robot.position; var c = a.arena.marginRect.getClosestLines(b)[0]; if (c.distanceToPoint(b) > (a.arena.radius + 2)) { return false; } if (this.last.robot.direction.isParallelTo(c.direction())) { return true; } return this.isTurningAtWall(a); }; p.prototype.isTurningAtWall = function (a) { var b = this.angleDiff(); if (Math.abs(b) < 1) { return false; } var c = this.previousRay().intersectionPoint(this.lastRay()); var d = this.last.robot.position; if (a.arena.marginRect.minDistanceToPoint(d) > 2) { return false; } return a.arena.marginRect.minDistanceToPoint(c) < 2; }; function q(a, b, c, d) { this.targetPoint = b; this.cannonRelativeAngle = a.cannonRelativeAngle; this.arcEnum = d; this.createdTime = a.time; this.targetTime = 0; this.setup(a, c); }; q.stdSeekArcEnum = function () { return 1; }; q.minSeekArcEnum = function () { return 2; }; q.maxSeekArcEnum = function () { return 3; }; q.attackArcEnum = function () { return 4; }; q.scanArcEnum = function () { return 5; }; q.cruiseArcEnum = function () { return 6; }; q.prototype.setup = function (a, b) { if (b < 0) { b = 0; } if (this.strafeDirection != a.strafeDirection) { this.strafeDirection = a.strafeDirection; this.strafeDirectionChangedTime = a.time; } var c = a.position; var d = this.getArcRadius(a, b, this.targetPoint); var e = d.radius; if (this.targetTime == 0) { this.targetTime = a.time + d.timeOffset; } var g = this.cannonAngleToTarget(a.position, a.cannonDirection, this.targetPoint); var h = this.convexDirection(a, false); this.arc = Math.abs(e) > 0.1 ? new f(c.add(h.scale(e)), e) : new f(c, e); this.direction = (Math.abs(e) > 0) ? a.strafeDirection * a.sign(e) : a.sign(g); }; q.prototype.angleLeftToTarget = function (a) { var b = this.cannonAngleToTarget(a.position, a.cannonDirection, this.targetPoint); return b * this.direction; }; q.prototype.timeLeftToTarget = function (a) { return this.targetTime - a.time; }; q.prototype.isPastEnd = function (a, b) { var c = a.position; var d = a.cannonDirection; var e = this.cannonAngleToTarget(c, d, b); if (this.direction > 0 && e > 0) { return false; } if (this.direction < 0 && e < 0) { return false; } return true; }; q.prototype.getArcRadius = function (a, b, c) { var f = a.position; var g = a.cannonDirection; var h = Math.abs(this.cannonAngleToTarget(a.position, a.cannonDirection, c)); if (h > 90 || b > 50 || b < 2) { return new r(h, 0); } var i = h * a.strafeDirection; var j = new d(f, g); var k = j.closestPoint(c); var l = new e(k, f); if (l.length() < 0.1) { return new r(b, f.vectorTo(c).dotProduct(g)); } var m = 1; var n = (Math.abs(i) > b) ? new r(Math.abs(i), 0) : null; while (m < Math.max(b, Math.abs(h))) { var o = l.direction().rotate(a.strafeDirection * m); var p = new d(c, o); var q = l.direction().rotate(-1 * a.strafeDirection * m); var s = new d(c, q); var t = p.intersectionPoint(l); var u = s.intersectionPoint(l); var v = f.vectorTo(t); var w = f.vectorTo(u); var x = 2 * Math.PI * v.length() * m / 360; var y = 2 * Math.PI * w.length() * m / 360; var z = (m + x); var A = (m + y); var B = v.dotProduct(g); var C = w.dotProduct(g); if (A > b && C < 0) { if (n == null) { n = new r(A, C); } else { var D = A - b; var E = n.timeOffset - b; if (D < E) { n = new r(A, C); } } } if (z > b && B > 0) { if (n == null) { n = new r(z, B); } else { var F = z - b; var E = n.timeOffset - b; if (F < E) { n = new r(z, B); } } } m++; } if (n == null) { return new r(Math.abs(i), 0); } return n; }; q.prototype.cannonAngleToTarget = function (a, b, c) { var d = a.vectorTo(c); return b.signedAngleTo(d); }; q.prototype.isConvex = function (a) { var b = a.position.vectorTo(this.arc.centerPoint); return b.dotProduct(a.cannonDirection) < 0; }; q.prototype.convexDirection = function (a, b) { var c = a.direction; var d = a.cannonDirection; var e = c.signedAngleTo(d) < 0 ? (b == true) ? c.rotate(90) : c.rotate(-90) : (b == true) ? c.rotate(-90) : c.rotate(+90); return e; }; q.prototype.getMoveSign = function (a) { if (this.arc.centerPoint.distanceTo(a.position) < 0.1) { return this.direction; } var b = this.arc.positiveTangentDirection(a.position); var c = b.dotProduct(a.direction); var d = this.direction * a.sign(c); return d; }; q.prototype.update = function (a, b) { var c = (b != null) ? b.distanceTo(this.targetPoint) : 0; if (Math.abs(a.cannonRelativeAngle - this.cannonRelativeAngle) > 1 || a.strafeDirection != this.strafeDirection || c > 3 || this.targetTime < a.time) { this.targetPoint = b; this.cannonRelativeAngle = a.cannonRelativeAngle; this.setup(a, this.targetTime - a.time); } }; q.prototype.getPosAtTime = function (a, b) { var c = this.arc.angleAtPos(a); var d = this.arc.radius * 2 * Math.PI / 360; var e = c + b / (1 + d) * this.direction; return this.arc.posAtAngle(e); }; q.prototype.isSeekArc = function () { return this.arcEnum == q.maxSeekArcEnum() || this.arcEnum == q.minSeekArcEnum() || this.arcEnum == q.stdSeekArcEnum(); }; q.prototype.isStdSeekArc = function () { return this.arcEnum == q.stdSeekArcEnum(); }; q.prototype.isMinSeekArc = function () { return this.arcEnum == q.minSeekArcEnum(); }; q.prototype.isMaxSeekArc = function () { return this.arcEnum == q.maxSeekArcEnum(); }; q.prototype.isAttacArc = function () { return this.arcEnum == q.attackArcEnum(); }; q.prototype.isScanArc = function () { return this.arcEnum == q.scanArcEnum(); }; q.prototype.isCruiseArc = function () { return this.arcEnum == q.cruiseArcEnum(); }; function r(a, b) { this.timeOffset = a; this.radius = b; } function s(a) { this.strafeDirection = 0; this.tracker = new i(); this.arena = new h(a); this.id = a.id; this.parentId = a.parentId; this.update(a); this.time = 0; this.isInitialized = false; } s.prototype.update = function (a) { this.time++; this.id = a.id; this.parentId = a.parentId; this.direction = b.FromAngle(a.angle); this.position = new c(a.position.x, a.position.y); this.cannonDirection = b.FromAngle(a.cannonAbsoluteAngle - 90); this.cannonRelativeAngle = a.cannonRelativeAngle; this.gunCoolDownTime = a.gunCoolDownTime; }; s.prototype.getScanningCannonAngle = function (a) { if (a.cannonRelativeAngle > 90 && a.cannonRelativeAngle < 270) { return 180; } return 0; }; s.prototype.getRotationDirection = function (a, b) { var c = b - a; if (c < -180) { c += 360; } if (c > 180) { c -= 360; } return this.sign(c); }; s.prototype.angleDiff = function (a, b) { var c = b - a; if (Math.abs(c) < 180) { return c; } else { while (Math.abs(c) > 180) { c -= this.sign(c) * 360; } return c; } }; s.prototype.sign = function (a) { if (a < 0) { return -1; } if (a > 0) { return 1; } return 0; }; })();