Wednesday, September 28, 2011

Ant Katas

So I'm continuing to pick up programming skills. This week, I played around with Ant.

Ant is a build system for Java projects, like make is for C projects. Like all build systems, its primary function is to let you write scripts that intelligently compile the source code files in your project. But it lets you do a lot more than that. Directories referenced in a build script can be relative to the project's directory, meaning its easy to transport the whole project to a different system without having it break. Ant handles any differences across OS environments, such as whether the local system uses \ or / as the path separator. You can write scripts to automate other tasks, such as running test cases, executing other tools like as javadoc, or cleaning up stray files. The scripts can also test conditions in the local environment and adapt their behavior accordingly. When combined with Ivy, Ant can also do dependency management for you, downloading any 3rd party libraries required by your project. In short, Ant lets you automate a lot of routine programming tasks for a specific project. And it does this in a transportable way, across OS environments, so that anyone else who downloads your project can perform those task out-of-the-box too.

To get some practice writing Ant scripts (which are specified in XML), I went through a few katas for a simple Hello, World program. The Ant tasks involved compiling, cleaning, generating javadocs, and packaging the system for distribution.

What I learned from this is that the Ant Manual takes a bit of getting used to. It provides a decent tutorial, but it can be hard to use as a reference. For example, the manual includes a extensive list of all the possible task tags that Ant supports, including documentation of all the attributes they support. But for a while, the only place I could find a link to this important list was an in-text link buried in text of the "Using Ant -> Tasks" manual section. (In writing this post, I found there is a more direct link under Ant Tasks in the Table of Contents, but this is easy to overlook because its location between "Running Apache Ant" and "Concepts and Types" makes it look like a tutorial chapter title.)

I had a bit of trouble using Eclipse write these scripts. Eclipse has a special Ant editor which provides some helpful syntax highlighting and content assistance. However, I couldn't find a way to create an Ant file directly. Instead, I had to create a normal XML file, then right-click on it and open it in the Ant Editor (which required some browsing to find among the various editor options). Once opened there, it was possible to just hit the run button to run the Ant script, which was handy. And I only had to do this once for each file; after that, Eclipse remembered that it was an Ant file.

So I've covered the basics of Ant at this point. I'd like to mess around with filesets and paths a bit more. When I get a minute, I'd also like to figure out how to exclude Eclipse contents (such as the /bin directory and .project file) from distribution zips I build with Ant. Then, since I'm still learning Eclipse too, I want to see how Eclipse handles importing projects that don't have any Eclipse metadata included.

Tuesday, September 20, 2011

Robocode Katas

So for the past week or so, I've been coding robots. Well, virtual robots.

Robocode is a software architecture for constructing little tank-like robots. Each tank is equipped with treads, a rotating gun, and a scanning radar. You can then run battles to the death between the different tanks. Robocode handles all the game physics and animation so that you can just focus on the tank logic.

I've dabbled with virtual robots before. I teach an Introduction to Computer Science lab, and, for the past 2 or 3 years, I've had my students implement a virtual roomba as the last assignment. Like Robocode, I provide the architecture, rule system, and GUI interface, and students then provide the "vroomba" logic. After mastering such a simple system, I was excited to try something a little more complicated.

Luckily, this Robocode work has been part of my Software Engineering class. (Sadly, I probably wouldn't be able to find the time to play around with it otherwise!) We were given 13 "code katas" to bring us up to speed with Robocode. A code kata is basically what it sounds like: a challenging programming exercise intended to build skills. Since the purpose of a code kata is mindful practice, failure can be a learning experience rather than a costly embarrassment, as it would be if the same lessons were being learned as part of a large production project.

These katas were a great way to pick up Robocode, and I recommend them to anyone just starting out with it. Each one tackles another aspect of tank management.

Here are the katas, and what I personally learned from each one. (Most of these lessons were fairly technical, though, and so they may not be of much use to you until you try Robocode yourself!)

Position01: The minimal robot. Does absolutely nothing at all.

Learned: How to create and run a Robot. This is basically the "Hello, World" of RoboCode.

Position02: Move forward a total of 100 pixels per turn. When you hit a wall, reverse direction.

Learned: You can call the ahead(int) method with a negative value to move backwards. Same with the turning methods. A move ends early if you hit something, whether a wall or another tank.

Position03: Each turn, move forward a total of N pixels per turn, then turn right. N is initialized to 15, and increases by 15 per turn.

Position04: Move to the center of the playing field, spin around in a circle, and stop.

Learned: After 15 years of neglect, my trigonometry is very rusty!
It took me over 2 hours to get a working method to compute the absolute heading from Point 1 to Point 2. It seems that Robocode lacks a method for this sort of calculation, though it does have a method for plotting a heading towards another bot. I also learned how to use Eclipse to
refactor methods into a new superclass and proved that the Scala interpreter does indeed make for a very handy interactive Java console.

Position05: Move to the upper right corner. Then move to the lower left corner. Then move to the upper left corner. Then move to the lower right corner.

Learned: I needed to account for the tank's dimensions in order to make it into the corners without hitting the walls on the way in. It seems the (getX(), getY()) point is the tank's center. getWidth() and getHeight() give the bot's dimensions, though, so dividing these by 2 gave me an effective tank "radius". (I added 1 pixel to this value, just to be on the safe side.)

Position06: Move to the center, then move in a circle with a radius of approximately 100 pixels, ending up where you started.

Learned: Circles are too hard/tedious with a Robot (which, unlike an AdvancedRobot, can't turn while moving). So I just traced a diamond here. I also took a break to learn how to color my tank. Important lesson there: setting colors needs to be done in run() or later. Trying to do it in a constructor will cause the bot to explode at the start of each round.

Follow01: Pick one enemy and follow them.

Learned: This got me comfortable with the onScannedRobot(ScannedRobotEvent) method in particular and Robocode's event-driven approach in general. It's initially weird how frequently an infinite while loop in run() will be suspended by other events.

Follow02: Pick one enemy and follow them, but stop if your robot gets within 50 pixels of them.

Learned: This was a surprisingly simple modification of Follow01. Since a negative distance to
ahead(int) moves the bot backwards, I got some cute retreating behavior for free here.

Follow03: Each turn, find the closest enemy, and move in the opposite direction by 100 pixels, then stop.

Learned: Each robot has a unique name accessible with getName(). This is true even if there are more than one instance of the same bot class on the board at a time. From a classmate (Ted), I learned that you can turn the radar (or anything else) to Double.POSITIVE_INFINITY to turn forever without needing an infinite while loop.

Boom01: Sit still. Rotate gun. When it is pointing at an enemy, fire.

Learned: The gun takes a while to cool down. So, even though I continued to rotate my gun, scanning multiple bots per rotation, I could only fire a bullet about once per rotation.

Boom02: Sit still. Pick one enemy. Only fire your gun when it is pointing at the chosen enemy.

Learned: ScannedRobotEvent.getHeading() is the heading in which the scanned robot is pointing, not the heading from you to that bot.

Boom03: Sit still. Rotate gun. When it is pointing at an enemy, use bullet power proportional to the distance of the enemy from you. The farther away the enemy, the less power your bullet should use.

Boom04: Sit still. Pick one enemy and attempt to track it with your gun. In other words, try to have your gun always pointing at that enemy. Don't fire.

Learned: I set my radar to keep rotating in my run() method. Yet I found that the radar would stopped rotating whenever I tracked a moving tank with my gun. This produced some cute behavior, like a little dog that stops panting and puts his ears up while his
target is moving, but relaxes again once the target stops. But it's still a little weird. Presumably, ScannedRobotEvents fire so frequently that, if I update my gun position for each one, Robocode doesn't have time to get back to my run() method before another ScannedRobotEvent fires.

So not every bot here taught me something new, but all were good practice.
Trig review aside, I found the hardest one here was Boom02. I think I may have misinterpetted the requirements for this one, though. I actively tracked the bot with the gun rather than waiting for the bot to pass in front of me. This made Boom04 a bit redundant.

Now that I'm familiar with Robocode, I'm looking forward to designing a combat-ready bot! More on that soon...

Wednesday, September 7, 2011

A short-yet-satisfying open-source license

I've been looking for a good, short, open-source license. This is intended for small projects, such as scripts, that might comprise of one or a handful of files. So I'm looking for a license that is only 2 or 3 paragraphs long that can easily be pasted into the header of the source files. (For larger projects, I would consider something like GPL or Apache License 2.0.)

I've been browsing the Open Source Initiative's list. I'm aware of license proliferation, so I'm trying to pick one that already exists. However, each license seems to have something different to recommend it.

MIT License - I like how short and yet explicit this one is. For example, it explicitly includes the ability to sublicense, so it is obviously compatible with other additional licenses. The only requirement to using the code is to keep the license text (including waiver of liability) and copyright notice (which also acts as an attribution) in place.

BSD 2-Clause License - The nice thing about the BSD license over MIT is that it's a little clearer that the license to freely redistribute also applies to binary (compiled) forms of the work. The 3-Clause version includes an extra clause that prevents any modifying authors from using the names of the original author or contributors in marketing the derived version.

This is a good reminder that, while I want to release my code and have it forever known that I am the originator, I also don't want that reputation tarnished by poor-quality modifications done later by others. In short, I'd like to require that any modifications to the software be clearly marked in some way, which neither MIT or BSD 2-Clause really deal with.

zlib - I think zlib does a good job of dealing with this "don't misrepresent me or my work" issue. However, I don't find the rest of the license as clean and precise as MIT on the main points of what you're allowed to do with the code and that the author(s) are not providing any sort of warranty.

Another issue that none of these licenses really handle is specifying how to clearly mark that the software has been modified. This is something I think Wizard of the Coast's d20 Open Gaming License handled very well: It required later contributors to add their own copyright statement the end of the license, beneath the intact notices from previous contributors. What I like about this is that 1) it's a simple mechanism--just add a line of text, 2) contributors generally want to add their name to a work anyway in order to receive recognition too, and 3) it's clear who the last contributor was, which protects the reputation of earlier contributors from "poor" later modifications.

So, while I was trying to avoid license proliferation, I couldn't find a single short license that was satisfying. I like the MIT License the best, except for a missing "clearly mark that this work has been changed so that you don't misrepresent my work" clause. So I borrowed that from zlib. I also added an explicit requirement that a later contributing author append a copyright notice. Here is my finished "MIT License with Modification Clause":

Copyright (c) <year> <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

1) The above copyright notice(s) and this permission notice shall be
included in all copies or substantial portions of the Software.

2) Modified versions of the Software must be plainly marked as such, and
must not be misrepresented as being the original software.  If you modify
this Software, append your own copyright notice to the list above.

or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose and noninfringement. In
no event shall the authors or copyright holders be liable for any claim,
damages or other liability, whether in an action of contract, tort or
otherwise, arising from, out of or in connection with the Software or the
use or other dealings in the software.

This is still not a perfect license, though. Unlike BSD, it's a little vague as to whether the license should also be included with binary forms of the software. (I think "all copies or substantial portions" should be read to cover binary versions, though this is not explicit. For the most part, I plan to use this license with libraries or scripts, where the distributed form is the source code itself, so this won't be much of an issue for me.)

Also, dealing with contributions (such as from a large project submitting changes through CVS or the like) is probably a little onerous. I considered requiring only those that publish or distribute a modified version to add a copyright notice. (Thus, modifying a private copy without notice would be fine.) However, it would be easy for someone to then unknowingly publish a version that had been previously modified by someone else. So each modifier should update the copyright notice list. It would also be fine if contributors are waiving or granting their copyright to a project (through some separate agreement between project and contributors) and then only the project or licensor is listed as the modifications copyright holder in the license. For example, consider Section 5 of the Apache License 2.0.

Note that, like all the source licenses, this license is not copyleft: modifiers are not required to release their source code.

As stated above, I got the text of these original licenses from OSI. In practice, everyone freely copies the text of these licenses without attribution. However, I'm not entirely certain I have the right to modify this text--except through the Creative Commons Attribution license at the bottom of all of OSI's pages. So, while I waive copyright to my own contributions to the above license text (meaning you may freely copy or modify it without my permission), you may still need to be attributing the text of the original license to OSI.

Copyright issues aside, there's another problem with modifying the MIT license: The license above is no longer an approved OSI license. That means it cannot legally be called "Open Source" because OSI holds a trademark to that term. The term can only legally be applied to software licensed under approved licenses.

So I'm still thinking about whether to actually use this new license or not. An uglier approach (but one that makes OSI happy) is to license software under both MIT and zlib together. Or possibly to only "politely request" that clause 2 be followed without making it an official part of my license.

While I think about it, any comments or suggestions are welcome...