<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://robowiki.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pkkm</id>
	<title>Robowiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://robowiki.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Pkkm"/>
	<link rel="alternate" type="text/html" href="http://robowiki.net/wiki/Special:Contributions/Pkkm"/>
	<updated>2026-05-04T11:02:24Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.34.1</generator>
	<entry>
		<id>http://robowiki.net/w/index.php?title=CassiusClay/Butterfly&amp;diff=18343</id>
		<title>CassiusClay/Butterfly</title>
		<link rel="alternate" type="text/html" href="http://robowiki.net/w/index.php?title=CassiusClay/Butterfly&amp;diff=18343"/>
		<updated>2011-02-02T18:58:42Z</updated>

		<summary type="html">&lt;p&gt;Pkkm: breaks -&amp;gt; brakes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Butterfly by [[PEZ]] - The [[CassiusClay]] (pluggable) movement ==&lt;br /&gt;
&lt;br /&gt;
Butterfly is all about [[WaveSurfing]]. It's the result of letting the [[Pugilist]] movement grow out of its [[MiniBot]] constraints. The design is pretty simple:&lt;br /&gt;
# Every scan create an [[EnemyWave]]&lt;br /&gt;
## If the enemy fired the tick before then mark the wave as &amp;quot;surfable&amp;quot;&lt;br /&gt;
## If a bullet hits my bot then&lt;br /&gt;
### Find the wave that is in the passing&lt;br /&gt;
### Find out what [[GuessFactor]] we were hit on&lt;br /&gt;
### Update the [[Visit Count Stats|stat buffers]] with this knowledge&lt;br /&gt;
# Every scan:&lt;br /&gt;
## check where (what guess factor) we would impact with the ''closest'' surfable wave were we to:&lt;br /&gt;
### move fully forward&lt;br /&gt;
### move fully reverse&lt;br /&gt;
### hit the brakes&lt;br /&gt;
## For each wave in the air&lt;br /&gt;
### Examine how often we've been hit in each of these destination options compared to all other guess factors&lt;br /&gt;
### Weigh together the results of all surfable waves with the closest one being the most important&lt;br /&gt;
## Go for the option where we've been hit the least (or where it seems the least dangerous to move)&lt;br /&gt;
&lt;br /&gt;
Simple enough, huh? One of those steps is a bit complicated though - step 2.1. It involves predicting our own movement some ticks in the future. This can be done in many ways. [[Pugilist]] does it in a pretty sloppy manner. [[CassiusClay]] is a bit more precise. In fact as of version 1.9.9.00g (g for gamma, my first test version) not only considers how fast CC can accelerate/deccelerate. It also tries to take into account the maximum turn angle it can do at a given velocity. Here's the scheme for the predictor:&lt;br /&gt;
&lt;br /&gt;
''Inputs''&lt;br /&gt;
* The closest &amp;quot;surfable&amp;quot; [[EnemyWave]]&lt;br /&gt;
* The desired orbit direction&lt;br /&gt;
* The desired target velocity (between 0 and 8 inclusive)&lt;br /&gt;
&lt;br /&gt;
''Action''&lt;br /&gt;
# Grab the current heading&lt;br /&gt;
# Grab the current velocity (relative to the desired orbit direction)&lt;br /&gt;
# Do&lt;br /&gt;
## Calculate a [[Wall Smoothing|WallSmoothed]] position in the desired orbit direction&lt;br /&gt;
## Calculate absolute bearing to this position&lt;br /&gt;
## Adjust the velocity according to Robocode physics (aiming for the target velocity)&lt;br /&gt;
## Calculate how much we would need to turn the bot to get the right heading&lt;br /&gt;
## Adjust our virtual heading while considering BackAsFront and the maximum turn rate at the current virtual velocity&lt;br /&gt;
## Calculate the position of the bot 1 tick into the future using the new virtual heading and velocity&lt;br /&gt;
## Advance the wave 1 tick into the future&lt;br /&gt;
# Until the wave impacts with the predicted bot position&lt;br /&gt;
&lt;br /&gt;
Here's the implementing code ([[RWPCL]]):&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
    Move waveImpactLocation(MovementWave closest, double direction, double maxVelocity) {&lt;br /&gt;
	double currentDirection = robotOrbitDirection(closest.gunBearing(robotLocation));&lt;br /&gt;
	double v = Math.abs(robot.getVelocity()) * PUtils.sign(direction);&lt;br /&gt;
	double h = robot.getHeadingRadians();&lt;br /&gt;
	Point2D orbitCenter = orbitCenter(closest);&lt;br /&gt;
	Point2D impactLocation = new Point2D.Double(robot.getX(), robot.getY());&lt;br /&gt;
	Move smoothed;&lt;br /&gt;
	int time = 0;&lt;br /&gt;
	do {&lt;br /&gt;
	    smoothed = wallSmoothedDestination(impactLocation, orbitCenter, currentDirection * direction);&lt;br /&gt;
	    double wantedHeading = PUtils.absoluteBearing(impactLocation, smoothed.location);&lt;br /&gt;
	    h += PUtils.backAsFrontDirection(wantedHeading, h) &amp;lt; 0 ? Math.PI : 0.0;&lt;br /&gt;
	    if (v &amp;lt; maxVelocity) {&lt;br /&gt;
		v = Math.min(maxVelocity, v + (v &amp;lt; 0 ? 2 : 1));&lt;br /&gt;
	    }&lt;br /&gt;
	    else {&lt;br /&gt;
		v = Math.max(maxVelocity, v - 2);&lt;br /&gt;
	    }&lt;br /&gt;
	    double maxTurn = Math.toRadians(MAX_TURN_RATE - 0.75 * Math.abs(v));&lt;br /&gt;
	    h += PUtils.minMax(PUtils.backAsFrontTurn(wantedHeading, h), -maxTurn, maxTurn);&lt;br /&gt;
	    impactLocation = PUtils.project(impactLocation, h, v);&lt;br /&gt;
	} while (closest.distanceFromTarget(impactLocation, time++) &amp;gt; 18);&lt;br /&gt;
	return new Move(impactLocation, smoothed.smoothing, smoothed.wantedEvasion, smoothed.oldDistance, impactLocation.distance(enemyLocation));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The BackAsFront functions there looks like so:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
    public static double backAsFrontTurn(double newHeading, double oldHeading) {&lt;br /&gt;
	return Math.tan(newHeading - oldHeading);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static double backAsFrontDirection(double newHeading, double oldHeading) {&lt;br /&gt;
	return sign(Math.cos(newHeading - oldHeading));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It's the same functions I use to move my bot around [[Jamougha]] style:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
	double newHeading = PUtils.absoluteBearing(robotLocation, destination);&lt;br /&gt;
	double oldHeading = robot.getHeadingRadians();&lt;br /&gt;
	robot.setAhead(PUtils.backAsFrontDirection(newHeading, oldHeading) * 50);&lt;br /&gt;
	robot.setTurnRightRadians(PUtils.backAsFrontTurn(newHeading, oldHeading));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Movement Implementations]]&lt;/div&gt;</summary>
		<author><name>Pkkm</name></author>
		
	</entry>
</feed>