Fruit War

The Fruit War project has been totally revised and enhanced. Now it is online at:
http://robotypo.appspot.com


Archive

Table of Content


Owner Guide - for owner who hosts Fruit War
Introduction
Download
Deployment
Security model
Contact & Related links
Other projects
User Guide - for users who use Fruit War
What is Fruit War?
How to write a Fruit War Robot?
Detailed Rules
Sample 1: MyFirstRobot
Sample 2: Focus - Let's defeat MyFirstRobot
Sample 3: FocusKiller - Beat 'Focus' perfectly!
How to upload my Robot?
How to debug my robot?
During debug, it always says "timeout"
Interface IFruitWarRobot
Interface IFruitThrower
Class EnemyInfo
Ranking
Battle result
Detailed battle result




Introduction

Fruit War is a platform which hosts battles between Fruit War robots - special java programs. The platform accepts source code as robot, and ranks all robots according to battle result. This is a Web application written in java: all in servlet/HTML and with flat-file as storage, so it's a lightweight implementation and easy to be hosted.
Till the first publication (v0.2.5), Fruit War platform has been running stably for more than 70 days, with more than 600000 total battles between 80 different robots. It has also been tested under two types of Web application server (Tomcat & IBM integrated application server) on two different OS (Windows & IBM i).
The platform is actually a play-thing for developers and only developers. Publish it in case it provides someone some fun.

Some screenshots:


Top    Back



Deployment

Please refer to the README file within the released package.

Top    Back



Security model

Allowing user java program to run on server is a security challenge. Fruit War platform uses a simple mechanism to make it secure: robot program is actually run in a separate process, rather than the main server process. The robot process is assigned with a low authority user profile. So the security problem is handled by OS. The advantage is that OS level security is more secure than application level security for such an "open" application. The disadvantage is that if you want to achieve a good security, you need to setup the environment manually, and the target OS must have a good security definition.
The current security framework is simple made according to IBM i (originally named OS/400, iSeries, or i5/OS). It works well on IBM i with JTOpen support. The security implementation for other OS are still dummy now, because though there's one simple abstraction level for the security utility in Fruit War, we don't think it fits for other OS. The security related classes are LAT: fruitwar.web.server.BattleUtil.LowAuthorityThread (the LAT) and package fruitwar.web.server.tempauthutil.
Anyway, an application as Fruit War platform should normally be used only internally and the first problem may be whether there's any interested coder or not. Security becomes a fun stuff for owner only, and users do not care about it normally.

In addition, the following specific internal security requirements have all been considered during implementation:
[1][2]: Running robot in standalone process fulfills these two requirements. We treat the sub process as a whole, define the JVM max memory, and if any error occurs, kill the process if necessary.

Top    Back



Contact & Related links

Home page on SourceForge.net
nanwang@users.sourceforge.net

My other projects

Top    Back




User Guide - for users who use Fruit War


What is Fruit War?

Fruit War is an open source platform which makes battles between Fruit War Robots from time to time. The winner robot receives a ranking bonus. The higher ranking a robot is, the more powerful it is, in general.

You can create your own Fruit War Robot and upload it to this platform to participate the battles. A Fruit War Robot is a simple java program, which normally consists of only a few lines of code. Even you're not familiar with java, you can create a robot based on the sample. Also, even without any java tool or editors, you can create a robot: the platform has everything you need for creating a simple robot.

Top    Back



How to write a Fruit War Robot?

The basic rules are very simple:
* Each team (side) has 3 Fruit Throwers.
* In each round, a thrower chooses an opponent thrower to hit.
* A thrower can also hide behind basket to avoid being hit. In this case, it can not hit others, too.
* If a thrower is hit too many times, it's out.
* If all throwers of a team are out, the team loses.

It's recommended to read through the sample series:
Sample 1: MyFirstRobot
Sample 2: Focus - Let's defeat MyFirstRobot
Sample 3: FocusKiller - Beat 'Focus' perfectly!

An easy way to write a Fruit War Robot is using the sample. Click My Robots! on the left area, then click Upload new robot link on the page. On the upload page, click the Sample link, which fills the robot source area with the default sample robot. So even without any java IDE, you can participate in Fruit War (Actually before today, 2008-Oct-15, the champion robot author has never written java before, not to mention using any java IDE).



Then how to write the robot actually?
First of all, you need to write a java class, implements the fruitwar.IFruitWarRobot interface. Customize the strategy method. In this method, set the action of each Fruit Thrower in your team.

Please refer to Detailed Rules and example.

Top    Back



Detailed Rules

Each round, the IFruitWarRobot.strategy method is called. In this method, the action of each Fruit Thrower (IFruitThrower) should be set. There are only two actions:
Throw: throw at a member in opponent team.
Hide: hide behind the basket.
* When setting strategy, you do not know whether an rival thrower is hiding or not.
* The opponent position ranges from 0 to fruitwar.Rules.BASKET_ID_MAX (include). Throw at 0 means the current thrower will throw at the first position in opponent team, and so on. If the position given is out of range, exception occurs and your robot loses.
* If no action is set, by default the action is Hide.
* If you hide behind basket, no one can hit you. This is useful, but be care of the following rule:
Coward: A Fruit Thrower is decided to be a coward if he/she hides too many rounds continuously.
For the limit for "too many rounds", please refer to constant value fruitwar.Rules.COWARD_LIMIT.
* If a thrower is not hiding, the coward count will be reset to 0.
* If a thrower is a coward, it's out of play.
Out of play: If a Fruit Thrower is out of play, it will be removed from the team and can not do any action. If all throwers are out of play, most likely the team loses.
* At the beginning, a Fruit Thrower has fruitwar.Rules.FRUIT_THROWER_HP hit points (HP). Each time it is hit, its HP is reduced by 1. When its HP is equal or lower than 0, it's out of play.

* If a team has no active Fruit Thrower (all of them are out of play), the battle is over. In this case, if both teams have no active thrower, it's a draw game, otherwise the team with active thrower wins.

* In addition, if after fruitwar.Rules.ROUND_TOTAL rounds, both of the teams are still active, the team with more HP wins.

Special rules
So, if you can "make" your rival robot throwing an exception or timeout, you win.

Top    Back



Sample 1: MyFirstRobot

This is a sample Fruit War Robot. For details, please refer to Detailed Rules

import java.util.Random;

import fruitwar.EnemyInfo;

import fruitwar.IFruitThrower;

import fruitwar.IFruitWarRobot;

import fruitwar.Rules;

 

public class MyFirstRobot implements IFruitWarRobot {

 

    Random rand = new Random();

   

    // Customize this method to set action of each thrower in the current round.

    public void strategy(IFruitThrower[] throwers) {

      

       //for each thrower in our team

       for(int i = 0; i < throwers.length; i++){

           IFruitThrower t = throwers[i];

      

           //throw at a random enemy position

           t.throwAt(rand.nextInt(Rules.BASKET_CNT));

       }

    }

 

    // This method is called after a round. Get enemy strategy here.

    public void result(EnemyInfo[] enemies) {

       //nothing. This robot does not care about results.

    }

}

 

Top    Back



Sample 2: Focus - Let's defeat MyFirstRobot

A simple strategy is enough to defeat MyFirstRobot: if every thrower throws at the same enemy, it will be hit many times and will be out of play soon. So our new robot Focus is created:

 

import fruitwar.EnemyInfo;

import fruitwar.IFruitThrower;

import fruitwar.IFruitWarRobot;

import fruitwar.Rules;

 

/**

 *

 * This robot tries to make all throwers hit the same position in

 * opponent team, so it's likely that the opponent thrower at our

 * "focus" will be "out of play" quickly. Then we have 3 throwers,

 * while our opponent has only 2...

 *  

 */

public class Focus implements IFruitWarRobot{

 

    int focus = 0;    //our focus: the position we throw at.

   

    public void strategy(IFruitThrower[] throwers) {

       for(int i = 0; i < throwers.length; i++){

          

           //all throwers focus on the same enemy!

           throwers[i].throwAt(focus);

       }

    }

 

    //get opponent strategy here.

    public void result(EnemyInfo[] enemies) {

      

       //at our focus, get the enemy info

       EnemyInfo e = enemies[focus];

      

       //if there's no one at focus (e == null),

       //or it's just hit down (e.hp <= 0)

       if(e == null || e.hp <= 0){

           //changeFocus

           focus++;

          

           //In Fruit War, the max position is Rules.BASKET_ID_MAX().

           //If the focus is bigger than that, we strat from 0.

           if(focus > Rules.BASKET_ID_MAX())

              focus = 0;

       }

    }

}

 

Top    Back



Sample 3: FocusKiller - Beat 'Focus' perfectly!

'Focus' is smart, but is too predictable. Let's defeat it PERFECTLY:

 

import fruitwar.EnemyInfo;

import fruitwar.IFruitThrower;

import fruitwar.IFruitWarRobot;

import fruitwar.Rules;

 

/**

 * This robot is specifically designed to defeat the robot

 * 'Focus'. We know their focus, and we always let our

 * thrower hide at their focus. So they can never hit us.

 */

public class FocusKiller implements IFruitWarRobot {

 

    int enemyFocus = 0;

   

    public void strategy(IFruitThrower[] throwers) {

       for(int i = 0; i < throwers.length; i++){

           IFruitThrower t = throwers[i];

          

           //if the thrower is at enemy focus, hide.

           //So enemy will not hit us.

           if(t.getPosition() == enemyFocus)

              t.hide();

           else

              //simply, we throw at the same focus they have.

              //Let our opponents taste their focus!

              t.throwAt(enemyFocus);

       }

    }

 

    public void result(EnemyInfo[] enemies) {

       //enemy focus is guaranteed to work like this.

       enemyFocus++;

       if(enemyFocus > Rules.BASKET_ID_MAX())

           enemyFocus = 0;

    }

}

Top    Back



How to upload my robot?

Click My Robots! on the left navigation area, you may need to login with a valid IBM intranet ID. Then click Upload new robot on the My Robots page. On the Upload Page, paste robot source code in source area and click Upload button. That's all! In addition, you can also click the Sample link on the upload page, which automatically fills the source code area with the default sample robot source code.

Top    Back



How to debug my robot?

Congratulations! When you need this you're starting to create some awfully good robots indeed. First you need to download the source code from download page. Note that the source package is one package (whose name contains "src") inside the released package.

To setup the development environment:
Assuming you that have Eclipse with JDT (if you write java code, most likely you have).

Select "File -> Import... -> Existing Projects into Workspace" to import the Fruit War project:




Select the fruitwar_x.x.x.jar you have:




It's done! You should have the Fruit War project imported, without any error in the project. If there's any red "x" or something alike, please contact developers.
Run the TestMyRobot.java, this is a simple case to run two robots:




Congratulations! The debug environment is ready.

Top    Back



During debug, it always says "timeout"

Set fruitwar.Rules.ROBOT_CALCULATION_TIMEOUT to 0.

Top    Back



Interface fruitwar.IFruitWarRobot

package fruitwar;

 

/**

 * This is the base of Fruit War robot. Implement this interface

 * to create your own robot.

 *

 */

public interface IFruitWarRobot {

 

    /**

     * This method is used to set actions in the next round. Customize

     * this method to set action of each thrower in the current round.

     *

     * @param throwers Array with dynamic length

     * {max @code fruitwar.core.Rules.BASKET_CNT}, which contains only

     * active throwers. If at position n the thrower is out of play,

     * it will not be included in this array.

     */

    public void strategy(IFruitThrower[] throwers);

   

    /**

     * The enemy info of the last round. The length of parameter

     * "enemies" is fixed value: {@code fruitwar.Rules.BASKET_CNT}.

     * If there's no enemy thrower at a position, the element in

     * the array is null.

     *

     */

    public void result(EnemyInfo[] enemies);

}

 

Top    Back



Interface fruitwar.IFruitThrower

package fruitwar;

 

/**

 * Represent a thrower in Fruit War.

 *

 */

public interface IFruitThrower {

   

    /**

     * Throw at the rival thrower at the given position.  Range from

     * 0 to {@code fruitwar.Rules.BASKET_ID_MAX}. If the position is

     * out of range, your whole team loses! (Exception will be thrown).

     *

     * This is an action command. You can call only one action command

     * each round. If action commands are invoked multiple times, only

     * the last one takes effect.

     *

     * @param target Position of a rival fruit thrower. Range from

     *                0 to {@code fruitwar.Rules.BASKET_ID_MAX}

     */

    void throwAt(int target);

   

    /**

     * Hide behind basket this round.

     *

     * This is an action command. You can call only one action command

     * each round. If action commands are invoked multiple times, only

     * the last one takes effect.

     */

    void hide();

   

    /**

     * Get the position of the thrower.

     * @return Basket ID, range from 0 to {@code fruitwar.Rules.BASKET_ID_MAX}

     */

    int getPosition();

   

    /**

     * Get hit points left of the thrower.

     * @return Hit points left.

     */

    int getHP();

   

    /**

     * Get how many continuous rounds this thrower has hide.

     * @return Continuous rounds this thrower has hide.

     */

    int getCowardCount();

}

 

Top    Back



Class EnemyInfo

Class EnemyInfo is for the result function:
IFruitWarRobot.result(EnemyInfo[] enemies)
Note that in the parameter array, an element object may be null, because the thrower is hidding this round or out of play before. If in this round it's out of play this round (no matter it's because of hitting down, or coward), the element is not null, and the HP value is equal or less than 0.

/**

 * Info of one enemy thrower in the last round.

 *

 */

public class EnemyInfo {

   

    /**

     * Which position was the thrower throwing at,

     * in the last round.

     */

    public int target;

   

    /**

     * How many hp does the thrower left

     */

    public int hp;

   

}

 

Top    Back



Ranking

Ranking represents the battle result of a Fruit War Robot. At the beginning, a robot has ranking 1500. Each valid battle will bonus the winner some ranking points, and the loser's ranking will be decreased the same amount. The delta ranking is calculated as:
15 - abs(ranking1 - ranking2) / 15
An example: robot1 battles robot2, assuming robot1 has ranking 1500, and robot2 has ranking 1515. The ranking difference is 15. If robot2 wins, it receives 15 - (1515 - 1500) / 15 = 14 ranking, and robot1 loses 14 ranking. If robot1 wins, it receives 15 - (1500 - 1515) / 15 = 16 ranking, and robot2 loses 16 ranking.
Note that, for two robots, the more ranking difference is, the less chance they'll get a battle. That means it's likely to choose "equivalent rivals". Anyway, any two robots have some chance to battle each other.
Also, if the ranking difference between tow robots is too much, the delta ranking is 0, if the robot with higher ranking wins. That's why there're many battles with delta ranking 0:0.

Top    Back



Battle result

The battle result looks like "0:326". It means that after the battle, the first robot has 0 HP left, and the second robot has 326 HP left. In this case, the second robot is the winner. If both of the numbers are not 0, that's because the battle reached rounds limit and still both sides are active. In this case, the team with more HP wins. If a number is -1, error occurred in the corresponding robot, probably exception is thrown, or it's timeout during calculation.

Top    Back



Detailed battle result

The detailed battle result shows the exact action of each thrower. The result consists of blocks of each round. Take the following block as example:
=== Round 30 ===
1(hp) - 55 44 77
1(at) - 0. 1. H.
2(at) - 2. _. 2.
2(hp) - 44 0 33
The three numbers (55, 44, 77) in the first line represent the HP of throwers in the first robot. The second line represents the actions of throwers in the first robot. For the actions, a number means it's hitting at the position, and an "H" means it is hiding. So for the first robot, thrower 0 has 55 HP, and it's throwing at enemy 0; thrower 1 has 44 HP, and it's throwing at enemy 1; thrower 2 has 77 HP, and it's hiding.
The 3rd line and the 4th line represent the actions and HP respectively for the second robot. A "_" in the action means this robot is already out of play, so no action is available.
The following block shows the HP of the following round of the example above. To make it simple, here it's assumed that everyone's action is hitting 0 in opponent team, so all the actions are 0. In Round 30, because thrower 0 of robot 1 throw at 0, so in this round (31), the HP thrower 0 of robot 2 decrease from 44 to 43. In Round 30, thrower 0 & 2 in robot 2 also threw at thrower 2 of robot 1, but the target is hiding (refer to the upper block), so thrower 2 in robot 1 is not hit, and its HP is still 77 this round.
=== Round 31 ===
1(hp) - 55 44 77
1(at) - 0. 0. 0.
2(at) - 0. _. 0.
2(hp) - 43 0 33

Top    Back




SourceForge.net Logo