Segmentation

From Robowiki
Jump to navigation Jump to search
This article may require cleanup to meet RoboWiki's quality standards.
Please improve this article if you can.

/Old Discussion - /Implementation - Selecting Best Segment - Smoothing and Decay - Saving

Segmentation is probably one of the most complex and most necessary parts of current robocoding. This is the age of GuessFactorTargeting and WaveSurfing, where success is about finding and exploiting your opponents weaknesses. This is where segmentation comes in. Segmentation is where one takes the traditional statistics gained through Waves or VirtualBullets and split it into segments based on the current factors at the time. A target may have the flattest profile you have ever seen, but when it is approaching a wall, changing velocity, advancing or retreating, or doing one of many other things, this profile could fail and allow you to exploit the spikes that occur.

Segments

When gathering data for a statistical operation, you will segment on one or more of these variables. Here are most of the variables that are segmented on, feel free to add variables and how to collect them to the list.

Generic

  • VisitCount: Typically GuessFactor, but it could be applied to whatever you wish. You always have this segment.
 (oldAngle-newAngle)/max_escape_angle // eg, Math.asin(max bot velocity/bullet velocity)
  • Distance: Range to the target at shot time.
 e.getDistance() 
  • Bullet Flight Time: Time from fire until the bot will be hit.
 e.getDistance() / (20 - 3 * shotPower) 
  • Bullet Power: The power of the bullet you fire with. Could be useful against wavesurfers that weight danger on power.
 shotPower 
  • Target Velocity: The targets velocity.
 e.getVelocity() 
  • Target Heading: Can either use the change in target heading or relative target heading.
 e.getHeading() - oldHeading 
 e.getHeading() - (e.getBearing() + getHeading()) // abs heading - abs bearing 
  • Target LateralVelocity: The velocity perpendicular to your direction.
 e.getVelocity() * Math.sin(e.getHeadingRadians() - (e.getBearingRadians() + getHeadingRadians())) 
  • Target AdvancingVelocity: The velocity parallel to your direction.
 e.getVelocity() * -1 * Math.cos(e.getHeadingRadians() - (e.getBearingRadians() + getHeadingRadians())) 
  • Target Acceleration: If target is accelerating, constant, or decelerating. Often very useful.
    int accelSegment(double deltaBearing, double oldDeltaBearing) {
        int delta = (int)(Math.round(5 * enemyDistance * (Math.abs(deltaBearing) - Math.abs(oldDeltaBearing))));
        if (delta < 0) {
            return 0;
        } else if (delta > 0) {
            return 2;
        }
        return 1;
    }
  • Near Wall: Probably the most useful. Usually split into middle, near wall, and near corner.
  • Move Times: Number of ticks since the velocity was last 0, since velocity changed, or since velocity was max speed. Useful against stop and go and oscillators, and many other types of movement. Some tanks, like CassiusClay, also make this (inversely) proportional to the enemy's distance.
if(enemyVelocity==0) moveTimes=0;  else  moveTimes++;
moveTimesIndex = Math.min(9, moveTimes/5);
  • Wave Type: If data is from real or virtual bullet. Only useful if profiles match.


Melee

  • Antigravity Force: The magnitude of the antigravity vector acting on an enemy
    • This means calculating the antigravity for the enemy rather than for self, and segmenting on this; I had been planning something similar in another of my bots a while back, but never got around to it
  • Robots Remaining: The number of enemies remaining.

Teams

  • Number of Teammates: The number of teammates an enemy has remaining
    • Could be very useful; droids can die when there are no radars left, and certain teams may modify their movement strategies based on this (DrunkenTeam comes to mind)

Expansions

  • Potential Near Wall Segmentation: The "getWallSpace" method returns a value of 0-1, knowing the enemy's location, given some querying heading. The utilization

below also rescales and clips it before binning, so distances far from the wall all fall into the same bin, as the wall was arguably inconsequential.

    private double getWallSpace(final double eGoing) {
        final double wallDistLat = Utils.normalAbsoluteAngle(eGoing) < Math.PI ? (Bot.PLAY_WIDTH-enemyPos.getX()) / (Math.cos((Math.PI/2d - eGoing)))
                : enemyPos.getX() / (Math.cos(((3d*Math.PI/2d) - eGoing)));
        final double wallDistVirt = Math.abs(Utils.normalRelativeAngle(eGoing)) < Math.PI / 2d  ?
                        (Bot.PLAY_HEIGHT-enemyPos.getY()) / (Math.cos(eGoing)) : enemyPos.getY() / (Math.cos(Math.PI-Utils.normalAbsoluteAngle(eGoing)));
        final double wallSpace = Math.max(0, Math.min(1,(float)(Math.min(wallDistLat, wallDistVirt) / Math.max(Bot.PLAY_WIDTH, Bot.PLAY_HEIGHT))));
        return wallSpace;
    }
    ... final double wallSpace = getWallSpace(eGoing);
        eGoing += Math.PI;
        final double revWallSpace = getWallSpace(eGoing);
        final double wallKey = (Math.min(0.44444d, wallSpace) * 2.25);
        final double revWallKey = (Math.min(0.44444d, revWallSpace) * 2.25);
        
        nearWall = (int)Math.floor(wallKey*6);
        revNearWall = (int)Math.floor(revWallKey*4);

See Also