[Home]Marshmallow/Source

Robo Home | Marshmallow | Changes | Preferences | AllPages

 package pez;
 import robocode.*;
 import java.awt.Color;

 import java.util.Vector;
 import java.util.Iterator;

 // Marshmallow the Robot, by PEZ. It's good toasted too!
 public class Marshmallow extends AdvancedRobot {
    static final double longTravel = 99999.0;
    static final double closeDistance = 180;
    static final double farAwayDistance? = 850;

    double previousEnergy = 100;
    double previousDistance = 500;
    double firePower = 3;

    int direction = 1;

    Enemies enemies = new Enemies();
    Enemy currentEnemy = null;

    public void run() {
        setColors(Color.green,Color.yellow,Color.green);
        setAdjustGunForRobotTurn(true);
        setAdjustRadarForGunTurn(true);
        while (true) {
            setTurnRadarRight(720);
            currentEnemy = enemies.getClosest();
            if (currentEnemy != null) {
                scan();
                //fireAt(currentEnemy);

            }
            execute();
        }
    }

    public void onHitWall?(HitWallEvent? e) {
        direction = -direction;
        setAhead(closeDistance * direction);
    }

    public void onHitRobot?(HitRobotEvent? e) {
        direction = -direction;
        setAhead(closeDistance * direction);
    }

    public void onHitByBullet?(HitByBulletEvent? e) {
        setTurnRight?((e.getBearing()+100) * direction);
        direction = -direction;
        setAhead((closeDistance) * direction);
    }

    public void onScannedRobot(ScannedRobotEvent e) {
        double energyDelta;
        Enemy storedEnemy = null;
        Enemy newEnemy = new Enemy(e.getName(), e.getEnergy(), e.getBearing(), e.getDistance(), e.getTime());
        int index = enemies.indexOf(newEnemy);
        if (index >= 0) {
            storedEnemy = (Enemy)enemies.elementAt(index);
            storedEnemy.update(newEnemy);
            energyDelta = storedEnemy.getEnergyDelta?();
            if (energyDelta < 0 && energyDelta >= -3) {
                elude(newEnemy.getBearing(), newEnemy.getDistance());
            }
        }
        else {
            out.println("Adding " + newEnemy.getName() + " to my list of enemies");
            enemies.add(newEnemy);
        }
        fireAt(newEnemy);
    }

    public void onRobotDeath?(RobotDeathEvent? e) {
        Enemy enemy = new Enemy(e.getName());
        enemies.removeElement(enemy);
    }

    private void fireAt(Enemy enemy) {
        //out.println("Shooting at " + enemy.getName() + ", energyDelta is " + enemy.getEnergyDelta?());

        out.println("Shooting at " + enemy.getName() + ", bearingDelta is " + enemy.getBearingDelta?());
        setTurnGunRight(normalRelativeAngle(getHeading() - getGunHeading?() + enemy.getBearing() - enemy.getBearingDelta?()));
        waitFor(new GunTurnCompleteCondition?(this));
        firePower = enemy.getDistance() < closeDistance ? 3 : 1.2;
        fire(firePower);
    }

    private void elude(double enemyBearing, double enemyDistance) {
        setTurnRight?(normalRelativeAngle(enemyBearing+60) * direction);
        direction = -direction;
        setAhead(enemyDistance / 3);
    }

    public double normalRelativeAngle(double angle) {
        double mod = angle % 360;

        if( mod <= -180 )
            return 180+(mod % 180);
        else if( mod > 180 )
            return -180 + (mod % 180);
        else

            return mod;
    }

    class Enemy {
        private String name;
        private double energy;
        private double bearing;
        private double distance;
        private long time;
        private double energyDelta = -2;
        private double bearingDelta = 0;
        private long timeDelta = 10;

        private long getTime() {
            return this.time;
        }

        public Enemy(String name) {
            setName(name);
        }

        public Enemy(String name, double energy, double bearing, double distance, long time) {
            setName(name);
            setEnergy(energy);
            setBearing(bearing);
            setDistance(distance);
            this.time = time;
        }

        public void update(Enemy newEnemy) {
            energyDelta = newEnemy.getEnergy() - this.getEnergy();
            //out.println("updating " + newEnemy.getName() + ", energyDelta is " + this.getEnergyDelta?()); 

            bearingDelta = newEnemy.getBearing() - this.getBearing();
            out.println("updating " + newEnemy.getName() + ", bearingDelta is " + this.getBearingDelta?());
            timeDelta = newEnemy.getTime() - this.getTime();
            setEnergy(newEnemy.getEnergy());
            setBearing(newEnemy.getBearing());
            setDistance(newEnemy.getDistance());
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public double getEnergy() {
            return this.energy;
        }

        public void setEnergy(double energy) {
            this.energy = energy;
        }

        public double getBearing() {
            return this.bearing;
        }

        public void setBearing(double bearing) {
            this.bearing = bearing;
        }

        public double getDistance() {
            return this.distance;
        }

        public void setDistance(double distance) {
            this.distance = distance;
        }

        public double getEnergyDelta?() {
            //out.println("getEnergyDelta?() " + this.getName() + ",  " + this.energyDelta);

            return this.energyDelta;
        }

        public double getBearingDelta?() {
            //out.println("getBearingDelta?() " + this.getName() + ",  " + this.bearingDelta);

            return this.bearingDelta;
        }

        public long getTimeDelta?() {
            return this.timeDelta;
        }

        public boolean equals(Object object) {
            if (object instanceof Enemy) {

                return (((Enemy) object).getName().equals(this.getName()));
            }
            return false;
        }
    }

    class Enemies extends Vector {
        public Enemies() {
        }

        public Enemy getClosest() {
            double shortestDistance = longTravel;
            Enemy closestEnemy = null;
            Iterator iterator = this.iterator();
            while (iterator.hasNext()) {
                Enemy anEnemy = (Enemy)iterator.next();
                double aDistance = anEnemy.getDistance();
                if (aDistance < shortestDistance) {
                    shortestDistance = aDistance;
                    closestEnemy = anEnemy;
                }
            }
            return closestEnemy;
        }
    }
 }

Hmm, this is a great way to make a bot open source and yet unreadable... -- Jokester

Heh, ironic that PEZ would use HTML tags (generated by Vim, no doubt) and then disable them on the wiki. -- Kawigi

You can still download them and render from the disk... --lRem

The real irony is that anyone would still be interested in this old carcass of a bot. =) -- PEZ

Oh, come on, it's not as old as some interesting bots ;-) -- Kawigi

Especially after seeing all of these old wiki pages, Id love to see what made Marshmallow tick. I can't believe its gone from your little pet project to "old carcass" ;) -- Jokester

Well, as one of the people who kept telling him that Marshmallow's targeting algorithm couldn't work, I admit I'm more surprised he didn't just re-write Marshmallow to become CassiusClay. I'm also relieved that he finally spent some time in MiniBot world while retiring this bot, because I think the MiniBot concept is what moved Robocode development to where it is now. -- Kawigi

For me it certainly was good to go via mini and micro and flank mega so to speak. But Robocode where it is today... Well, among megas, CC is the only top-5 bot with mini heritage. And neither GuessFactorTargeting nor WaveSurfing was born in MiniBot land, even if I think I helped advance both concepts using minibot techniques. As for Marshmallow being a dead old carcass... If you write a complicated enough bot, adding feature for feature without testing if they really work and not a tenth of them do work and while not caring at all about keeping your code tidy at all you go lose to the source code alltogether; Voila! old. There! carcass. Marshmallow had excellent random movement, with some surfing on top even, though I didn't have a name for it then. But I only really cared about it's guns, which were crap, save for one which might have been half good if it hadn't been hooked up in a broken VirtualGuns array. I needed to go MiniBot to clean my Karma really. I had room for one targeting idea and one small movement idea in Aristocles and in Pugilist I had room for the same targeting idea and a more advanced movement idea. From there it was natural to step up and try dethrone that RaikoMX bot which seemed so unbeatable at the time. -- PEZ

I think the way MiniBots contributed to robocode is to avoid this whole "adding feature for feature without testing if they really work" - many of us didn't have the discipline to test every idea before assuming it worked so we needed the focus required for smaller bots where we had a few focussed features and fudged the rest. Paul Evans was so good from the start because he did have that discipline, and he knew how to refine and test his bots when the best bots he had to test against were his own. Tad also seemed to have that kind of discipline, but might have benefitted from MiniBotting if he gave it a shot. Focus was the main contribution I think the MiniBotChallenge gave us, even if it was only really a side effect. Back in the days when 2/3 of the top bots on the ER were MiniBots, MegaBots were huge, bloated, over-featured, had massive VG arrays, and sometimes even movement arrays that didn't work. The best MegaBots were SandboxDT, Tron (and a few other oldies, especially in melee, to be sure), Marshmallow (thank goodness it didn't have a movement array), and the ones that were based on MiniBots - Chameleon (Spark's movement), CigaretBH (Spark's gun and Cigaret's movement), FloodHT (version 0.8 was like a megabot-ized version of FloodMini after I figured out that FloodMini was better than FloodHT 0.7), Jekyl (originally based on SandboxMini).

About the top bots now - I'd assume the one bot you're talking about is your own CassiusClay, which was certainly based on Pugilist and maybe even more so on Tityus (which I can't fail to mention is a contribution related to FloodMini). But Ascendant is quite literally based on CassiusClay and so is PulsarMax in a more conceptual way (although the implementation isn't). Going down the list, I see RaikoMX which is clearly based on Raiko's gun, Pear which probably gets its gun from CigaretST (which wasn't quite a MiniBot, but was meant to be a test bot, so it was just as minimally featured), Phoenix (which was based on lots of research done through DuelistMini), and DarkHallow, (which I'm guessing started with BlackPearl and Jekyl, which was based on SandboxMini). Then we see Pugilist, Aleph and Apollon (I admit, I think Apollon came after Aleph as more of an afterthought). Then Lacrimas, which used to be a MiniBot and Raiko, BlestPain which was definitly derived from Cigaret and CigaretST before it was a wave-surfer, and Tityus. So in other words, in my opinion, I see roughly half of the top 25 (including the top 3) being MiniBots or being the result of research done through MiniBots. That doesn't seem like a huge stretch, since I think that FloodMini's gun is an ancestor of the guns used by about 10 of them, and is probably an ancestor of the gun that even more of them are dodging. I think MiniBot training is what made most of the top Robocoders (minus a few) so good, and if it's not, excepting Paul Evans and ABC, it was the MiniBot training of others being documented on the wiki that allowed them to get to the top.

And soon, this rant will be about the size of Marshmallow's source code, so I'll stop now (plus, with all the links, it's starting to look like a bad blog entry). -- Kawigi

On the countrary. More links => better wiki article, in my book. I'd still say the state of art in Robocode isn't minibot based. Minibot coding helped me focus, no doubt, but it was a rather uncessary struggle to go via Pugilist to create CassiusClay. That was just plain tunnel vision on my side. I just had to do it since I had lost the race with Jamougha of creating the first OpenSource surfer. Speaking of which, I think OpenSource and the sharing of ideas and knowledge on this wiki are a much greater force in advancing Robocode bots than minibotting. Yeah many minibots are open source, but it's still open source that drives it. Closed source minibots just don't advance anything else but themselves.

I strongly disagree CassiusClay would be more based on Tityus than on Pugilist. The main thing about CC is WaveSurfing. Even if it does have a strong gun too.

-- PEZ

Well, my point being more that Pugilist was based on Tityus so transitively CassiusClay is based on Tityus, and many of the bits that still exist in CassiusClay came from or were derived from Tityus. If your WaveSurfing implementation is anything like mine, Tityus's gun is probably partially sitting around in there, probably more than Pugilist's WaveSurfing code (but I haven't looked closely enough to say).

What my real point is, though, that you wouldnj't have written CassiusClay and Jamougha might not have written RaikoMX if you both didn't experiment in a more limited, focussed environment first - and I consider myself to be the same way. -- Kawigi

Yes, with Jam and me certainly minibots was the way. Actually it was Jam who helped me bring out the potential of Tityus by nailing that old bug that had been plauging it for months and months.

I actually didn't build my WaveSurfing by turning my gun backwards. Not conceptually anyway. Technically yes, I guess in my style of WaveSurfing a GuessFactorTargeting gun turned backwards is a key component. But there's so much more to surfing. Read the CassiusClay/Butterfly page and you'll see I do not really think much about the "gun" behind when modelling up my movement. CC's surfing is a straight port of Pugilist's. I've just removed most of those codesize shortcuts and worked really hard with the accuracy part. You just can't get accurate enough with WaveSurfing...

-- PEZ

Hi PEZ, no problem with the readibility, just a(nother) tip to generate html from Java. I remember you once said you did all your coding with Vim (and probably use this to generate the html too). Have you started using an IDE for your coding ? If so, maybe http://www.java2html.com is of interest. You can use this tool as an Ant-build task. greetings, --Loki

Hmm, so all you had to do was remove the html tags... very clever -- Jokester

Thats first time anyone has mentioned Jekyl as a top bot. Even back in the day I do not think it every really rose to that level. While we are on lineage, it is not fair to say that Jekyl was based entirely on SandboxMini. I only used the gun initially. The original movement was just a random circular orbit that eventually evolved into a hand tuned orbiting system that appeared in Griffon. My next bot, and first mini, BlackPearl attempted to extend that movement system and refine what was a VirtualBullet? gun into a Wave gun. I dabbeled briefly with a PatternMatching gun to prove to myself I could do it and because I was having a hard time beating Aspid but I quickly shed that when I got to the MultipleGuess? match problem. About that time, surfing became all the rage so I worked on a WaveSuffering movement in my next bot DarkHallow. I briefly broke the 2028 barrier with that bot only to fall to where it is currently today. Sometimes I think about dusting off the editor and trying to push this bot back into the top 10 but I just don't think I have it in me anymore. My last (and most likely final) was StoneGhost. It has very little in it that was an original thought. I implemented it based on some of kawigi's descriptions of his melee bots. I thought at the time it would be fun to persue but I guess I do not have the fire anymore. This does not really belong here but since I was mentioned I thought I would respond with a little history jekl.* style to let everyone know that I still lurk even if I am not contributing. -- jim

Loki, I'm still using VIM. It's an IDE of sorts. Ant is integrated so using that tool would be as easy from VIM as from any other IDE I guess. Some year ago I fooled around a bit by trying to make a wiki-plugin for colorizing java source code. I actually had one ready, but it used VIM as the colorizer and that's a pretty stupid way to do it. But maybe with a tool like the one you mention I could try it again. Depends on the licensing a bit though. -- PEZ


Robo Home | Marshmallow | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited June 25, 2005 8:22 EST by PEZ (diff)
Search: