 |  | Contents: |  | |
 | Related content: |  | |
 | Subscriptions: |  | |
| Stretch your Java programming skills with this new animated graphical simulator
Sing Li (westmakaha@yahoo.com) Author, Wrox Press 29 Jun 2004 Guard
your castle! Claim your land! Command your knights to joust valiantly
and defeat their foes. Capture the enemy's position and seize its land
while dodging its menacing knights. If writing mudane Java code is
giving you the blues lately, maybe it's time to turn your medieval
fantasies into reality. You can rule your own kingdom while refining
your Java programming skills and mastering the Eclipse development
environment all at the same time. It's all in a hard day's work for a
supreme CodeRuler. Simulation-gaming enthusiast Sing Li puts you on the
fast track to ultimate kingdom domination. Born of the 2004 ACM International Collegiate Programming Competition (see Resources),
CodeRuler is IBM alphaWorks' newest fantasy gaming simulator challenge.
The game has a simple premise: You are the imperial ruler of your very
own medieval kingdom. Your peasants and knights depend on your
brilliant strategic thinking, agile adaptability, and superior Java
programming skill to survive, increase, and prosper. Your objective as
a player is to write Java code that simulates this ruler. The gaming
simulator pits your ruler against up to six opponents' rulers (or the
included sample rulers) and determines the winner. This article
guides you along the shortest path to ruling your own medieval kingdom.
It reveals the game's environment, describes the rules, discusses
general strategies, and provides two complete working ruler entries
that you can put to use (or modify) immediately. The simulation environment CodeRuler
is a graphical, animated simulation gaming environment. As a medieval
ruler, you must battle other rulers for land and dominance. Your
kingdom consists of: - Peasants who can claim and work the land.
- Knights who can fight battles and capture other rulers' peasants, knights, or castles.
- A castle that can create more knights and peasants. The more land you have, the faster it creates them.
The graphical gaming world The
game is played out in a two-dimensional world represented by a map of
the kingdom. (The background landscape sketch merely acts as wallpaper;
it doesn't affect game play or change as the game progresses.) Figure 1
illustrates a CodeRuler game in progress. Figure 1. CodeRuler in action
 Figure
1 shows two competing rulers at work. The ruler -- the mastermind
behind the strategic movements of the game pieces -- doesn't appear in
the game world. The game pieces (peasants, knights, and castles) are
the colored dots moving within the simulated world. Figure 2
illustrates the pieces' shapes and their possible movement directions. Figure 2. Movement pattern for CodeRuler game pieces
 As
you can see from Figure 2, knights and peasants use the same movement
pattern. They can move a single square in any one of the eight
directions for each turn. Each direction has an associated number,
which you use in Java coding. Each number also has a predefined
constant (such as NW) that you use in your code. The console score display You can see the status console on the right side of Figure 1.
The names of the currently playing rulers, and the organizations to
which they belong, appear at the top of the console. The two numbers
are the ruler's current score (left) and the number of land squares
that the peasants have claimed. Figure 3 shows an example score display. Figure 3. Console score display
 In
Figure 3, ruler number #18 is called Simple Ruler from IBM
developerWorks. The ruler's current score is 123, and the ruler has
captured 774 squares of land for the kingdom. You can abort the
simulation at any time by clicking on the red X on the top right. At-a-glance land occupation display You can see a small version of the world in the middle of the status console of Figure 1.
The image, reproduced in Figure 4, lets you see each ruler's current
occupation of land at a glance. You can easily see in Figure 4 that the
blue-colored ruler has claimed significantly more land than the
magenta-colored ruler. Figure 4. At-a-glance land occupation display
 The simulation clock At the bottom of the status console in Figure 1 is a clock. Figure 5 shows a closeup. Figure 5. The CodeRuler clock
 A
sun travels around the clock's dial. The match is over after the sun
has traveled one complete cycle. Each tick of the clock is a turn for
the simulator. As a ruler, you determine the moves your pieces make
during each turn. Rules of combat Each ruler has initial control over: - 10 peasants
- 10 knights
- 1 castle
Creating new peasants and castles The rate of creation of peasants or knights by a castle depends on the number of land squares that you own: Land you own | Number of turns to create one peasant or knight | 124 or fewer | No creation | 125 | 14 | 250 | 12 | 500 | 10 | 1,000 | 8 | 2,000 | 6 | More than 4,000 | 4 |
|
During the course of the game, you want to: - Use your peasants to claim as much land as possible (and keep it claimed).
- Use your knights to capture as many of your opponent's peasants as possible, stopping them from claiming land.
- Use
your knights to combat and capture as many of your opponent's knights
as possible. This weakens your opponent's defensive capability.
- Use
your knights to attempt capture of the other ruler's castle. Castles
are factories for knights and peasants; you cannot create more peasants
or knights without them. With multiple castles, you gain the ability to
create peasants or knights at a faster rate than your opponents. See
the sidebar Creating new peasants and castles, for creation rates.
- Strategically prevent the capture of your castle.
Capturing game pieces Only
a knight can capture the opponent's peasants, castles, or knights. It
can capture peasants and castles simply by moving into their squares.
To capture an opposing knight, you must first bring its strength value
down to 0. Each knight starts with a strength value of 100 and loses a
random strength value between 15 and 30 for each attempted capture by
an opponent. The knight performing a successful capture gains 20
strength units. The scoring scheme To
win a match, you must be the ruler who has the highest score at the end
of the match. Note that the winner might or might not be the ruler with
the most land claimed. Table 1 provides the game's scoring scheme. Table 1. Scoring scheme for captures
If you... | You get | Capture a peasant | 4 points | Capture a knight | 6 points | Capture a castle | 15 points |
At the end of the match, your remaining pieces, captured castles, and claimed land all add to your score, as shown in Table 2. Table 2. Scoring scheme for remaining pieces
Piece remaining | Score | Peasant | 1 point | Knight | 2 points | Castle | 25 points | Land | 1 point per 10 squares |
Game details Each
player writes Java code that simulates a ruler. The gaming simulator
matches your ruler against other rulers and determines the winner. In
your code, you must orchestrate the movement of your peasants, knights,
and castle(s). A set of API provides information on your pieces and
those of other competing rulers. Using this API, you can write code
that implements offensive, defensive, or even adaptive strategies. Components of the game The CodeRuler game requires the Eclipse IDE for writing, debugging, and testing your ruler's code. (See Eclipse: The integrated kingdom development environment , later in this article.) CodeRuler includes: - An interactive gaming simulator, as a plug-in to the Eclipse IDE.
- The documentation of the API you can use to code your ruler.
- A set of movement, capture, and scoring rules.
- A local arena for running your ruler against a set of sample rulers.
- A networking mechanism for submitting your ruler to compete in public tournaments, or for setting up your own tournaments.
Simulated world coordinate system The
game is staged in a simulated world consisting of 4,608 squares -- 72
squares wide by 64 squares high. The squares are numbered according to
an (x, y) coordinates system. The x axis extends from left to right and the y axis from top to bottom. Figure 6 shows the layout of the CodeRuler world. Position (0,0) is at the top-left corner. Figure 6. The CodeRuler world coordinates system
 CodeRuler API and inheritance hierachy Before
you can command the game pieces, you need to understand the CodeRuler
API. The API is highly object oriented and has an explicit inheritance
hierachy. An understanding of the hierachy is crucial to effective
CodeRuler coding. Figure 7 shows the inheritance hierarchy. Figure 7. CodeRuler inheritance hierachy
 The
inheritance tree in Figure 7 is based on Java interfaces. Each game
piece must implement its associated interface: peasant must implement IPeasant , knights must implement IKnight ,
and so on. However, you never need to code any of these classes,
because the CodeRuler simulator uses built-in implementations. As a
ruler, you need to use the API provided by the interfaces
only to get information about the game pieces. The IObject interface
The IObject interface is the super interface to all pieces on the playing field. Each piece implements IObject indirectly. IObject factors out the common behaviors of all pieces: getRuler() : The ruler the piece belongs togetX(), getY() : The piece's current positionisAlive() : Whether the piece is alive (that is, not captured)getId() : A unique ID (across all pieces -- knights, peasants, and castles)
The IObject
super interface also has two convenience methods. These methods can be
quite handy in your strategy design and help you avoid the need to
employ complex trigonometric math: getDirectionTo() calculates the closest direction to a specified point on the board.getDistanceTo() calculates the distance to a specified point on the board.
The IPeasant interface
The IPeasant interface adds no new behavior to the IObject interface. You can move peasants with the Ruler's move()
method, which changes their positions. You use a peasant to claim land.
A peasant's automatic behavior is to claim any land position that it
moves over. An opposing knight can capture a peasant in a single move;
no calculation of strength is involved. The ICastle interface
The ICastle interface, like the IPeasant interface, adds no new behavior to the IObject
interface. A castle's automatic behavior is to create more peasants or
knights. The speed of creation depends on the amount of land you own.
See the sidebar Creating new peasants and castles, for the creation rate. The IKnight interface
The IKnight interface adds one method, called getStrength() , to the IObject interface. A knight is captured when its strength is reduced to zero. You can use the IKnight interface's getStrength() method in your strategy to avoid the loss of knights. See Capturing game pieces earlier in this article for a discussion of a knight's strength calculation. The interface hierarchy in Figure 7
represents the game pieces that move around the world during the
simulation. The ruler, however, is not a game piece and does not move
in the simulated world. The IRuler interface specifies the ruler's behavior. The IRuler interface
The IRuler interface has no need to -- and does not -- inherit from IObject . Figure 8 shows the IRuler interface's inheritance hierarchy. Figure 8. Inheritance hierachy of the IRuler interface
 The IRuler
interface specifies the generic behaviors that all rulers implement.
They include informational methods that are useful for the
implementation of your strategy: getPeasants() gets a list of all peasants under this ruler.getKnights() gets a list of all knights under this ruler. getCastles() gets a list of all castles under this ruler.getLandCount() gets a count of all the land squares that this ruler owns.getPoints() gets the current number of points this ruler has earned.getRulerName() gets the ruler's name. getSchoolName() gets the organization name of the ruler's creator.
The Ruler and MyRuler classes
To enforce game-rule-specific behaviors, and to help you implement the IRuler interface, CodeRuler supplies the Ruler class as shown in Figure 8. This class provides default implementations for most of the IRuler methods. You write the content of the MyRuler class, which must inherit from the Ruler class. You need not, and should never, modify the Ruler class. The simulator's workflow From the perspective of a CodeRuler player, the simulator has the following workflow: - Places your initial game pieces at a randomly selected kingdom location in the simulated world
- Calls your implementation of the
initialize() method - Calls your
orderSubjects() method on every turn
Your getRulerName() and getSchoolName() methods should not contain strategy code. The simulator can call them at any time. |
Ruler provides several vital action methods that you should use in your implementation of MyRuler :
move() moves pieces around the world.capture() attempts to capture an opponent's game pieces.
Ruler
also implements several methods that can change the generation mode of
your castle(s). By default, your castle(s) manufacture peasants
continuously. However, you use these methods to tell it or them to
manufacture knights instead:
createKnights() tells the castle to manufacture knights.createPeasants() tells the castle to manufacture peasants.
Last but not least, one of the reasons for the existence of the Ruler class is to define additional abstract methods that you must implement in your own MyRuler class. The simulation engine calls these methods during its execution. The only code you must write is the code that implements the methods listed in Table 3: Table 3. Methods in all MyRuler implementations Method | Description | getSchoolName() | Returns
a string of 25 or fewer characters that identify your group or
organization. (CodeRuler was originally designed for competition among
colleges.) This will be used during the game to identify your ruler. In
Figure 1, for example, Simple Ruler has the school name IBM developerWorks. | getRulerName() | Returns a string of 25 or fewer characters that uniquely identify your ruler. For example, one of the rulers in Figure 1 is named Simple Ruler. | initialize() | The
system calls this method when you first place your ruler into the game.
Perform any initialization you need here. You are limited to one second
of initialization. The amount of work your machine can perform during
initialization will vary with the CPU speed and the Java VM in use, but
one second is sufficient for most code-initialization tasks. Do not
attempt any work that might depend on slow input/output. | orderSubjects() | This is the core of a CodeRuler .
The system calls this method once every turn. You need to exercise your
strategy and tell your pieces what to do within this method. |
Eclipse: The integrated kingdom development environment You
need to download and install the Eclipse IDE (version 2.1 or later) in
order to run the CodeRuler simulation environment (see Resources). CodeRuler integrates into the Eclipse IDE as a plug-in, thereby leveraging Eclipse's developer-friendly features. Installing Eclipse and CodeRuler To
install Eclipse, unarchive the distribution into a directory and run
the eclipse executable (eclipse on *nix, and eclipse.exe on Win32
systems). You need JDK/JRE 1.4.2 or later installed. (Version 1.4.2 is
highly recommended because CodeRuler is developed and tested under this
VM version.) After you install Eclipse, download the CodeRuler engine
(see Resources). To install CodeRuler, unarchive the CodeRuler distribution into the <eclipse installation directory>/plugins
directory. This should create a com.ibm.games directory under the
plugins directory. Start or restart Eclipse, and the CodeRuler plug-in
will load. You're now ready to give CodeRuler a try. Creating your CodeRuler project You
need to create a new project in Eclipse to use CodeRuler. From the main
menu, select Windows|Preferences. A dialog box pops up, as shown in
Figure 9. Figure 9. Creating a new CodeRuler project
 Select
IBM Games in the list on the left, as depicted in Figure 9. Next,
select CodeRuler from the Game list on the right. Finally, click on OK to create a new CodeRuler project from the template. You are now ready to code your own CodeRuler. On the tabs bar on the left hand side of the IDE, click on the Java Perspective tab. Figure 10 identifies this tab. Figure 10. Selecting the Java perspective in Eclipse
 Expanding
the src node and the default package reveals the MyRuler.java node, as
in Figure 10. The source code editor opens the file for editing when
you double-click on the MyRuler.java node. This is where you must place
your code. Coding your first ruler The
first ruler you'll create is simple. It moves all the peasants
randomly. Listing 1 shows the code for this ruler, with the added code
highlighted in boldface. The importance of being timely When you code your ruler, be aware of the timing constraint that you are under. For the initialize()
method, you are limited to one second, which should be plenty of time
for any non-input/output code initialization. You are preempted if you
take more than one second and might suffer from partial initialization.
For each turn of the game, the orderSubjects() method limits you to half of a second. An incoming parameter of the orderSubjects()
call lets you know how much time you used in the last turn. If you
exceed the time limit, you are disqualified for the rest of the match. | Listing 1. Simple Ruler implementation of orderSubjects()
import java.util.Random;
...
protected Random rand = new Random();
public String getRulerName() {
return "Simple Ruler";
}
public String getSchoolName() {
return "IBM developerWorks";
}
public void orderSubjects(int lastMoveTime) {
IPeasant[] peasants = getPeasants();
for (int i = 0; i < peasants.length; i++) {
move(peasants[i], rand.nextInt(8) + 1);
}
}
|
The code in Listing 1 uses java.util.Random to generate a random number between 1 and 8. This number determines the direction that a peasant moves. Note the use of the Ruler class's getPeasants() method to obtain an array of all peasants, and the use of the move() method to move the peasants.
Moving the peasants randomly allows them to claim land. But because
this ruler doesn't try to capture anything, your code doesn't need to
move the knights. The "do not try" list for CodeRuler A
clever strategy is important to winning the game, but CodeRuler
discourages tricky use of Java language features to hijack the gaming
engine or win by other devious means. Your code should not: - Define constuctors
- Use initialization blocks
- Create threads
- Create processes
- Write to files
- Use JDBC
- Use Swing or AWT to create GUI components
- Access the network or other similar system features
- Use reflection and introspection to discover and walk simulator internals
In all public matches and tournaments, players who use such hacker tactics will be disqualified from competition. A custom Java SecurityManager will catch most of these attempts. |
Battling in your first match To
try out your first match, first save the newly edited ruler by either
clicking on the save button on the toolbar or selecting File >Save from the menu. A save also compiles your code. Correct any typing or syntax errors before proceeding further.
You'll notice five iconic buttons, shown in Figure 11, that are CodeRuler specific. Figure 11. Integrated CodeRuler buttons in the Eclipse toolbar
 Table 4 explains the functions of the buttons in Figure 11, moving from left to right. Table 4. Functions of the CodeRuler buttons
Button | Description | Run against samples | Use this button to test your ruler against your choice of sample ruler(s). | Debug against samples | Use
this button to test your ruler against your choice of sample ruler(s).
Run your ruler in debug mode, stopping at any breakpoint you have set. | Run against other teams | After
you have submitted your code, rulers from other teams will have been
downloaded. Use this button to test your ruler against those from the
other teams. | Debug against other teams | Run your ruler in the IDE's debug mode while testing your ruler against those from other teams. | Submit code | Submit your ruler. This also downloads an encrypted bundle of all the rulers submitted by other teams thus far. |
Your
first ruler will run against only the sample rulers in your initial
experimentation. This means you'll use only the first button, the one
highlighted in Figure 11.
When you click on this button, CodeRuler starts and loads your ruler.
You're given a chance to select your opponent(s), as shown in Figure 12. Figure 12. Selecting your opponent for a match
 Try
adding one Do Nothing Ruler. Start the match and observe how your
peasants randomly move around and claim the land. You should win this
match easily. Next, try the Random Ruler. This ruler behaves almost identically to yours. The average land occupation is about equal. If
you try any of the other sample rulers, the Simple Ruler you created
will likely lose. Most of the other sample rulers attempt to capture
your pieces agressively. It's time add an offensive edge to your Simple
Ruler. Creating an offensive ruler Listing 2 shows the code for the modified ruler, with the added code highlighted. Listing 2. Modified Simple Ruler implementation to capture opponents aggressively
import com.ibm.ruler.*;
import java.awt.Point;
import java.util.Random;
import java.util.Vector;
public class MyRuler extends Ruler {
public String getRulerName() {
return "Simple Ruler";
}
public String getSchoolName() {
return "IBM developerWorks";
}
public void initialize() {
}
protected Random rand = new Random();
protected Vector enemies = new Vector();
public void orderSubjects(int lastMoveTime) {
IPeasant[] peasants = getPeasants();
IKnight[] knights = getKnights();
for (int i = 0; i < peasants.length; i++) {
move(peasants[i], rand.nextInt(8) + 1);
}
enemies.clear();
IPeasant[] otherPeasants = World.getOtherPeasants();
IKnight[] otherKnights = World.getOtherKnights();
ICastle[] otherCastles = World.getOtherCastles();
for (int i=0; i<otherPeasants.length; i++) {
enemies.add(otherPeasants[i]);
}
for (int i=0; i<otherKnights.length; i++ ){
enemies.add(otherKnights[i]);
}
for (int i=0; i<otherCastles.length; i++) {
enemies.add(otherCastles[i]);
}
int size = knights.length;
for (int i = 0; i < size; i++) {
IKnight curKnight = knights[i];
if (!enemies.isEmpty()) {
IObject curEnemy = (IObject) enemies.remove(0);
moveAndCapture(curKnight, curEnemy);
}
else
break;
} // of outter for
}
public void moveAndCapture(IKnight knight, IObject enemy) {
if ((enemy == null) || !enemy.isAlive())
return;
// find the next position in the direction of the enemy
int dir = knight.getDirectionTo(enemy.getX(), enemy.getY());
Point np = World.getPositionAfterMove(knight.getX(), knight.getY(), dir);
if (np == null)
return;
if ((np.x == knight.getX()) && (np.y == knight.getY())) {
move(knight, rand.nextInt(8) + 1);
return;
}
// capture anything that is in our way
IObject obj = World.getObjectAt(np.x, np.y);
if ((obj != null) && (obj.getRuler()!= this))
capture(knight, dir);
else
move(knight, dir);
}
}
|
The versatile World object Before you embark on extensive ruler coding, make sure you spend some time studying the documentation for the World
object. This object contains many static methods that you'll find
useful for implementing your strategy. For example, you can use getLandOwner() to find out who owns a square of land, use getObjectAt() to identify the game piece that's in a specific location, and use getOtherPeasants() , getOtherKnights() , getOtherCastles() , and getOtherRulers() to discover your enemies. |
You'll recognize the green highlighted code in Listing 2. The red highlighted code sets up a Vector consisting of all the enemy game pieces that are alive in the simulation world. Note the use of the World object to get this information (that is, World.getOtherPeasants() ). The
blue highlighted code loops through all of your knights and makes each
of them move toward a living opponent's game piece. It also captures
any enemy pieces that might be in place. It uses the moveAndCapture() method to move and capture. The moveAndCapture() method moves a specified knight toward a specified enemy piece. It uses the World object's getPositionAfterMove() method to determine if the knight is stuck, and makes a random move if it is. It also uses the World object's getObjectAt() method to test and capture any enemy pieces that might be in its way. Try this new Simple Ruler
against some of the sample rulers. You'll see that it fares quite well
against many of them. Of course, there's plenty of room for
improvement. As an exercise, you can try modifying the code to: - Command your castle(s) to generate knights when the number of knights get low.
- Assign targets to your knights more efficently.
- Program your peasants to claim land more efficiently.
- Program your peasants to evade attempted capture.
- Switch to a defensive survival strategy when the number of peasants and knights is low.
Conclusion It's
your choice: from the simplest heuristic-based robotic ruler to the
most sophisticated statistical gaming theory model driven commanders,
CodeRulers span all possibilities. Just as in the real world, the most
sophisticated strategy and intricate coding don't always guarantee sure
winners. In fact, some of the champion rulers deploy the most simple,
yet elegant, guerrilla tactics. If strategic design and Java
development is your blood, you owe it to yourself to give CodeRuler a
spin. Resources - Learn more about the ACM International Collegiate Programming Contest, the world's oldest, largest, and most prestigious programming contest.
- Download the latest version of the CodeRuler simulation engine and associated documentation from IBM alphaWorks.
- For the latest version of the Eclipse IDE, documentation, mailing lists, and community news, visit eclipse.org.
- Check out another classic simulation game powered by the same simulation engine as CodeRuler. Code Rally puts you in the hot seat at a race car rally!
- For another highly popular battle simulation game from alphaWorks, try Robocode. The active international community of Robocode gamers is sure to give you a challenge.
- Learn more about Robocode from Sing Li's articles "Rock 'em, sock 'em Robocode!" (developerWorks, January 2002) and "Rock 'em, sock 'em Robocode: Round 2" (developerWorks, May 2002).
- Visit the Developer Bookstore for a comprehensive listing of technical books, including hundreds of Java-related titles.
- You'll find hundreds of articles about every aspect of Java programming
in the developerWorks Java technology zone.
- Interested in test driving IBM products without the typical high-cost entry point or short-term evaluation license? The
developerWorks Subscription
provides a low-cost, 12-month, single-user license for WebSphere®,
DB2®, Lotus®, Rational®, and Tivoli® products -- including the
Eclipse-based WebSphere Studio IDE -- to develop, test, evaluate, and
demonstrate your applications.
About the author
Sing Li is the author of Professional Apache Tomcat 5, Pro JSP, Third Edition, Early Adopter JXTA, Professional Jini,
and numerous other books with Wrox Press. He is a regular contributor
to technical magazines and an active evangelist of the P2P evolution.
Sing is a consultant and freelance writer and can be reached at westmakaha@yahoo.com. |

|