Now I am not all that interested in good segment / bad segment comments. While they would be helpful, what I am really looking to find is if the math is correct. I suspect that it is not and I can not figure it out. Thanks for taking the time to look -- jim
/* * Created on Aug 4, 2003 * */ package jekl.gunnery; import robocode.*; import robocode.util.Utils; import java.awt.geom.*; import java.awt.Color; import java.util.*; import jekl.utils.*; import jekl.*; /** * @author jbishop * */ public class WaveGun implements Constants,Gun { private Point2D.Double myLocation; private Enemy target; private static float [][][][][][] statBuffer; private static float [] fastStatBuf; private int lastLatVelIndex, enemyWaveCount, lastDecelTime = 0; private static int waveID = 0; private DarkHallow ar; private ArrayList waves; public WaveGun(DarkHallow _ar) { this.ar = _ar; this.waves = new ArrayList(); this.myLocation = new Point2D.Double(); if (statBuffer == null) { //[getOutIndex()][timeSinceDecel][lastLatVelIndex][latVelIndex][distanceIndex]; statBuffer = new float[3][5][5][5][5][(int) GUESS_FACTORS]; } if (fastStatBuf == null) { fastStatBuf = new float[(int) GUESS_FACTORS]; } } public void onScannedRobot(ScannedRobotEvent e) { target = ar.getTarget(); doStats(); myLocation.setLocation(ar.getX(), ar.getY()); if (Math.abs(target.getLatVel()) - Math.abs(target.getLastLatVel()) < 0) { lastDecelTime = (int) ar.getTime(); } double firePower = 3.0; //Retrieve the current stat segment to use //[getOutIndex()][timeSinceDecel][lastLatVelIndex][latVelIndex][distanceIndex]; float[] stats = statBuffer[JeklUtils.getOutIndex(target.getLocation(),target.getHeading(),target.getDirection())][Math.min(4,(lastDecelTime / 10))][(int)Math.abs(target.getLastLatVel())/2][(int)Math.abs(target.getLatVel())/2][JeklUtils.getDistanceIndex(target)]; //float[] stats = statBuffer[JeklUtils.getOutIndex(target.getLocation(),target.getHeading(),target.getDirection())][Math.min(4, (lastDecelTime / 10))][target.getAccellIndex()][(int)Math.abs(target.getLatVel())/2][JeklUtils.getDistanceIndex(target)]; float[] fast = fastStatBuf; //Aim the gun and fire ar.setTurnGunRightRadians(Utils.normalRelativeAngle(target.getAbsBearing() - ar.getGunHeadingRadians() + getGuessAngle(getIndex(stats), firePower, target.getDirection()))); ar.setFire(firePower); if (firePower >= 1) { addWave(firePower, stats, fast, true, myLocation, target.getLocation(), 1, target.getDirection(), Color.RED ); } } //--------------------------------------- Helpers ------------------------------------------------------ //Adds a wave. private void addWave(double firePower, float[] stats, float[] fastBuffer, boolean myShot, Point2D.Double origin, Point2D.Double target, int ticks, int shotDir, Color color) { Wave w = new Wave(ar); w.guessFactors = stats; w.fastBuff = fastBuffer; w.wDirection = shotDir; w.shotPower = firePower; w.bulletVel = JeklUtils.bulletV(firePower); w.dist += (w.bulletVel * ticks); w.shotOrigin = new Point2D.Double(origin.x, origin.y); w.targetLoc = target; w.startingAbsTargetBearing = JeklUtils.getAbsBearing(origin, target); w.maxAnglePossible = Math.asin(8.0 / w.bulletVel); w.myShot = myShot; w.color = color; w.id = ++waveID; waves.add(w); } private void doStats() { Iterator it = waves.iterator(); while(it.hasNext()) { Wave w = (Wave)it.next(); if ((w.dist += w.bulletVel) >= w.shotOrigin.distance(w.targetLoc) - 18) { if (w.myShot && w.shotPower > 1.0) { w.incrementHits(); } else { enemyWaveCount--; } it.remove(); } } } /** Get the current best Guess Factor to shoot at */ private int getIndex(float[] stats) { int bestIndex = (int) MIDDLE_FACTOR; for (int i = 1; i < stats.length; i++) { if (stats[i] > stats[bestIndex]) { bestIndex = i; } } return bestIndex; } public double getGuessAngle(int guessIndex, double firePower, int eDirection) { return (guessIndex - ((double) (GUESS_FACTORS - 1) / 2)) / ((GUESS_FACTORS - 1) / 2) * Math.asin(8.0 / JeklUtils.bulletV(firePower)) * eDirection; } }Here is the wave code. I took out the movement related code to aid clarity some.
/* * Created on Jun 14, 2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package jekl.utils; import robocode.util.Utils; import java.awt.geom.*; import jekl.paint.WavePainter; import jekl.*; /** * @author Jim */ public class Wave implements Constants { public WavePainter p; public Point2D.Double shotOrigin; public Point2D.Double targetLoc; Enemy target; public double shotPower; public double bulletVel; public double dist; public double startingAbsTargetBearing; public double maxAnglePossible; public float[] guessFactors; public float[] fastBuff; public int wDirection; public boolean myShot; public double botWidth; public java.awt.Color color; private JeklUtils u; public int id; private DarkHallow ar; public Wave(DarkHallow _ar) { this.ar = _ar; if (DRAW) p = new WavePainter(this); } //Returns the successful guess factor public int getGuessFactor() { double currentAbsBearingFromShotOrigin = JeklUtils.getAbsBearing(shotOrigin, targetLoc); return (int) Math.max(0,Math.min((GUESS_FACTORS - 1),(int) Math.round(((((Utils.normalRelativeAngle(JeklUtils.getAbsBearing(shotOrigin, targetLoc) - startingAbsTargetBearing) * wDirection) / maxAnglePossible) * MIDDLE_FACTOR) + MIDDLE_FACTOR)))); } public void incrementHits() { guessFactors[0]++; fastBuff[0]++; for(int i=1; i<guessFactors.length; i++){ fastBuff[i]*=0.98f; guessFactors[i]*=0.98f; } guessFactors[getGuessFactor()] += 0.01f; fastBuff[getGuessFactor()] += 0.01f; //Andrew's cool way if(getGuessFactor() + 1 <= (GUESS_FACTORS - 1)) { fastBuff[getGuessFactor() + 1] += 0.006f; guessFactors[getGuessFactor() + 1] += 0.006f; } if(getGuessFactor() - 1 >= 1) { fastBuff[getGuessFactor() - 1] += 0.006f; guessFactors[getGuessFactor() - 1] += 0.006f; } } public void drawWave() { p.drawWave(color, wDirection); } public void removeWave() { p.remove(); } public void debug () { System.out.println("Shot Power: " + shotPower); System.out.println("Velocity: " + bulletVel); System.out.println("Dist: " + dist); System.out.println("SABS: " + startingAbsTargetBearing); System.out.println("MAP: " + maxAnglePossible); System.out.println("AIA: " + JeklUtils.getAbsBearing(shotOrigin, targetLoc)); System.out.println("WDIR: " + wDirection); } }
I have compared my gun code with several other open source guns line for line. I am missing something obvious. I see not differences in the logic or the math. The segments differ some, but when I use identical segments as the comparison gun I get significantly different results. I am about to give up and use an old robocode idea and "steal" someone elses. =^> -- jim
I think you'll need to publish your wave code too for us to be able to follow along. I see one strange thing immediately though, "enemyWaveCount?--", but it probably is a naming issue. -- PEZ
If it's got nothing to do with gunnery, then what is it doing in the code above? You might need to disentangle your gun and your movement some. My daughter wants this computer now. I'll try to get some time later to read your code more carefully. -- PEZ
I took a look at your code and didnt notice any errors in the math. Perhaps your gun isnt broken at all, after all DarkHallow is still a top 10 bot (ok currently 11th, but i'm sure i have seen it in the top 10 before), and i dont think any of these bots has a 'broken' gun. Anyway i wondered about some things in the code above:
Top-10 is fully reachable with a broken gun. I would try to simplify the gun before adding complexety such as fast learning buffers and neighbouring bin updates (after all, Raiko manages quite well without any of those tricks). -- PEZ
@PEZ, now that it is not 5:00AM I can more fully respond as I am at least fully awake now =^>. enemyWaveCount? is an artifact of when my gun and movement were fully entangled. It does not belong here and actually never gets used. It should be (and has) been removed. Thanks for catching that. @Mue, As PEZ said, top 10 is possible with a broken gun. Top 5 is not I think. In targeting challenges I score some where in the mid 80's. Against DT over 500 rounds I score somewhere near 65%. Considering top guns get somewhere near 85% my gun is clearly not optimal. I am also some 5 - 10% below other guns in performance vs. all other bots. The good news is that I learn quickly and do not seem to suffer than much of a degradation in performance in fast runs. You are also correct that the fast learning buffer is not in there yet. I have toyed with it but unless I can find the otherwise subtle bug that persists, fast learning only makes things worse. I have also used bot width as a means of determining which bins actually hit, but doing so seems to adversly affect my surfing (they both currently use the same all purpose wave) so I have avoided that so far. @Everybody, I appreciate the time it takes to look at this. Keep the ideas coming. I know someone will eventually see it. I am just too familiar with the code. -- jim
Run the bot without the neighbouring bin updates, how much of a TC score change is that? You definitely may be smoothing bins over poorly. It may also be worth it to check tiny things like to make sure JeklUtils?.bulletV(firePower) returns 20 - 3 * firePower, or that eDirection is calculated as the sign of velocity times the clock direction you're facing. -- Kuuran
Both excellent suggestions. I have checked and the fire power is correct. I use the following:
target.setLatVel(target.getVelocity() * Math.sin(target.getHeading() - target.getAbsBearing())); if (target.getLatVel() != 0) { target.setDirection((int)(Math.abs(target.getLatVel()) / target.getLatVel())); }as direction code. I think the calculation is correct but there is room for the implementation to be poorly executed. I have never come up with a good way to handle velocity zero shots. I have tried, at various times, to flip the sign when the velocity is zero guess that a target was reversing. I know of no elegant way to make that work. Thanks Kuuran!! -- jim
The calculations look right. Did removing the smoother change the accuracy at all, or was it insignificant? -- Kuuran
1/2 a bot width or even one bot with off shouldn't matter much I think. The bot and the bullet moves in a way that even a half miss becomse a hit (and sometimes a half hit scores nil). Another thing though. Have you written down the order of things as you expect them to happen and looked if your code actually follows along? -- PEZ
Short question even if it doesnt fit here, but in code snipped above i saw @author jbishop . It might sound strange, but i have seen this before: i read a book about jave written by judith bishop, that was the german translation of 'Jave gently'. Is it your nick, too, or did u use a template .... --deathcon
Pretty cool. Jim's surname is Bishop, so it's just a coincidence. Maybe Bishop is a very common name. First names starting with J are pretty common, that much I know. -- PEZ
You just never hesitate to complicate things. =) Seriously you'll have to roll your stats super fast to keep up with the surfers. In the process you'll lose tons of rating points against the rest. -- PEZ
Maybe so, but look at my ratings page vs. Surfers with this version and last. I am below 25% or so for almost all of the upper echelon bots. So how do you hit them and still manage to hit the rest of the rumble. Remember jim's mantra: "first beat everyone else as bad as they do, and then beat them." I quickly approaching the second half of that statement. =^> -- jim
I'd say you have some milage still to cover. Neither RaikoMX nor CassiusClay use rolling stats for their guns. Still they manage pretty well against the surfers. It's a matter of improving your gun rather than to specialize it I think. Besides, it's simple math really; Improve your score against a surfer with 15% or against a low-ranked bot with 5% and you'll earn much more rating points by the latter. -- PEZ
In my experience nailing the surfers usually only requires a good wall segment to get close. Going over the top is another matter, but it's not something I'd worry about yet if I were you. -- Kuuran
All right. Color me sceptical. And my mantra still holds. If you are on top, you are officially on notice: I want the #1 spot and I am to get it. No pun intended =^P -- jim