Saturday, March 3, 2012

A little SWATH elitism

I've been improving the API of the terminal component from my last post. I've also been playing TradeWars. Playing leads me to write SWATH scripts, and writing SWATH scripts keeps me thinking about how Weapon M should work.

I've built up a pretty good library of reusable components for SWATH scripts. Classes like WarpCache and BreadthFirstSearch replicate most of the TWX scripting capabilities that are absent in SWATH. My library allows for deceptively simple scripts like this one, which I wrote in a few minutes as a proof of concept. Behind those uses of BreadthFirstSearch and NodeMatcher are hundreds of lines of code. When I have more time, I'll turn the basic idea of this script into an automated hunting bot that lays grid and SSMs as it goes.

This is where SWATH and Java have a tremendous advantage over TWX. Most of the problems players encounter in setting up and using TWX scripts arise from fragile code that lacks a clearly defined API. I'm not even sure if TWX scripts have any concept of namespaces or encapsulation. Interaction between modules seems to rely pretty heavily on global variables, and the naïve use of text triggers often leads to race conditions. By contrast, it's very easy to build things up from Java classes. And SWATH's event-driven approach is so vastly superior that I probably won't design any text-matching capability at all into Weapon M's scripting API.

import com.swath.Sector;
import com.swath.Swath;
import com.swath.UserDefinedScript;

public class NearestEnemy extends UserDefinedScript {
    
    protected NodeMatcher find;

    @Override
    public String getName() {
        return "Nearest Enemy";
    }

    @Override
    public boolean initScript() throws Exception {

        find = new NodeMatcher() {
            @Override
            public boolean matches(BreadthFirstSearch.Node node) throws Exception {
                return node.sector.portStatus() == Sector.PORT_BLOCKED ||
                        node.sector.isAvoided();
            }
        };
        
        return true;
    }

    @Override
    public boolean runScript() throws Exception {
        BreadthFirstSearch bfs = new BreadthFirstSearch(
                WarpCacheDaemon.getCache(),
                Swath.sector,
                NodeMatcher.ANY,
                find
            );
        if(bfs.foundTarget()) {
            printTrace("Nearest sector of interest: " + bfs.getTarget().sector());
        }
        else {
            printTrace("No enemy sectors found.");
        }
        return true;
    }
    
}

No comments:

Post a Comment