Robotypo Help - Drunkard

Table of Content

What is Drunkard?
Rules
    Example 1: MyFirstDrunkard
    Example 2: Recorder - Let's defeat MyFirstDrunkard
    Example 3: BeatRecorder - Defeat 'Recorder' perfectly!
Fight Result
Knowing Opponent's Strategy
Base Robot Class Details: Fruitday

Common Help For All Sub-platforms
    Upload A Robot
    Advanced Rules
    Debugging
    Member Variables, Initialization, and Using Java Utilities



What is Drunkard?

Drunkard is a sub-platform in Robotypo. Drunkard hosts fights between Drunkard robots.

You can create your own robots and upload them to this platform, and challenge other robots. A Drunkard Robot is simply a Java program, which normally consists of only a few lines of code. Even you are not familiar with Java, you may create robots based on examples. Neither Java tool, nor IDE is a must.


Robots fight with others. Each match has two robots, and consists of multiple rounds. Before each round, each robot sets its strategy for the round. Your robot never knows for sure what the opponent's strategy is, and vice versa. It is up to you to create a strategy, and if necessary, analyze opponent's strategy and adjust yours to win.



Top    Back



Rules

It's in the bar. Two guys play the game against each other. They wave fist, then yell a number, and raise some fingers at the same time (just like the Rock-paper-scissors game). He who yells the correct sum of the total fingers wins. The loser drinks the cup. Write a robot to calculate the finger and guess the sum. Make your opponent drunnnk!


Details
  • The match: The match between two drunkards (robots) has 1000 rounds.
  • What the robot does: Before each round, the strategy() method of each robot is called. In this method, the robot should set the finger count (the fingers member variable), and guess the total sum (set the sum member variable).
  • The round: In each round, the finger counts from the two drunkards are added, as the actual sum. The drunkard who makes the correct guess of the sum wins the round, and gain 1 score. If no one guesses correctly, or both drunkards guess correctly, it's a draw. In this case no one gains score. But one exception is the Full Hand Rule.
  • The Full Hand rule: when both sides guess of the sum correctly, the drunkard who raises 5 fingers wins the round.
  • End of game: After all rounds are passed, the drunkard who has more score wins.

Before each round, the strategy() method of each robot is called. When setting the strategy, a robot never knows for sure what the opponent's strategy is. However you can know opponent's actions in previous rounds. It is up to you to analyze opponent's strategy, and adjust yours.


It is recommended to read through the following three examples:
Example 1: MyFirstDrunkard
Example 2: Recorder - Let's defeat MyFirstDrunkard
Example 3: BeatRecorder - Defeat 'Recorder' perfectly!
Top    Back



Example 1: MyFirstDrunkard

MyFirstDrunkard shows what a Drunkard robot looks like.

public class MyFirstDrunkard extends Drunkard {

 

    //This method is called before a round. Set our strategy here.

    public void strategy() {

   

        fingers = 3;                       //Raise some fingers (0 to 5). Here we always raise 3.

        sum = 3 + random.nextInt(6);    //The total number we guess.

    }

}

Top    Back



Example 2: Recorder - Let's defeat MyFirstDrunkard

/**

 * This robot analyzes action of opponent in the previous round.

 * For some robots, it is likely that it will raise the same

 * finger count, and/or make the same guess as previous rounds.

 * We read that info, and adjust our strategy.

 */

public class Recorder extends Drunkard {

 

    public void strategy() {

 

        // My finger count that guessed by opponent in the previous round

        int opponentGuessed = prevOpponentSum - prevOpponentFingers;

   

        // If my finger count matches opponent guess...

        while (fingers == opponentGuessed)

            //change my finger count.

            if (++fingers > 5)

                fingers = 0;

       

        //Guess opponent raises the same finger count as the previous round.

        sum = fingers + prevOpponentFingers;

    }

}

Top    Back



Example 3: BeatRecorder - Defeat 'Recorder' perfectly!

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

/**

 * Recorder is good. Let's defeat it simply and perfectly.

 */

public class BeatRecorder extends Drunkard {

   

    public void strategy() {

 

        if (++fingers > 5)

            fingers = 0;

        sum = fingers * 2;

    }

}


Top    Back



Create My Robot

Click My Robots! in the left navigation area, you may need to login with Google account or an Open ID. Then click the Create button. Example code is already there. You can create your robots base on that.


Top    Back



Fight Result

The result consists of blocks of each round, looks like this:

Round Finger Sum Win 
[1]56
37
[2]23+
15
[3]14
23+
[4]35
25
[5]56+
16


The number between [ ] is the round number. In this example, it shows rounds from 1 to 5.

Each round result consists of two rows. They represent the first robot and the second robot respectively.

Each row has 2 numbers. They are the finger count and the guessed sum of the robot in this round.

If a robot wins the round, there is a plus character (+) to the right of its row. If the round is draw, there's no plus character.


About this example:
In Round 1, the first robot raises 5 fingers, and guesses sum as 6. The second robot raises 3 fingers, and guesses 7. The actual sum is 5 + 3 = 8. No one is correct. This round is a draw.
In Round 2, the first robot guesses correctly. So it wins the round and there's a plus character (+) at the end of its row.
In Round 3, the second robot wins.
In Round 4, both robots guess correctly. It's a draw again.
In Round 5, both robots guess correctly, but the first robot raises 5 fingers, and the opponent not. So the first robot wins the round by the Full Hand Rule.


Top    Back



Knowing Opponent's Strategy

You can analysis the strategy of your opponent robot. Before each round (at the beginning of each strategy() method call), the following member variables represent the state at the end of the previous round:

  • fingers
  • sum
  • prevOpponentFingers
  • prevOpponentSum
  • result: WIN, LOSE, or DRAW, from current robot's point of view.

All previous history records can also be retrieved from the history member variable. history[0] represents the state of round 0, history[i] represents the state of round 1, and so on. For example:

  • history[0].myFingers: fingers set by our robot in round 0
  • history[0].mySum: sum set by our robot in round 0
  • history[0].oppFingers: fingers set by our opponent in round 0
  • history[0].oppSum: sum set by our opponent in round 0
  • history[0].result: The result of this round, from our robot's perspective. Could be: WIN, LOSE, or DRAW.

  • history[1].myFingers: fingers set by our robot in round 1
  • ...

Further, you can create class member variables to form your own data structures and store your own data.


Read the next section Base Class Details: Drunkard for more details.


Top    Back



Base Class Details: Drunkard

Here's the source code for the base class Drunkard. Read the comments for details.

/**

 * The base class for Drunkard robots.

 */

public abstract class Drunkard {

   public static final int TOTAL_ROUNDS = 1000;

   public static final int MAX_FINGERS = 5;

   public static final int DRAW = 0;

   public static final int WIN = 1;

   public static final int LOSE = -1;

   public static final int UNKNOWN = -2;

  

   /**

    * Random utility.

    */

   protected Random random = new Random();

 

   /**

    * The fingers this drunkard raises, for this round.

    * There are 5 fingers on each hand, so the value must be 0, 1, 2, 3, 4, or 5.

    * Set this value in the strategy() method.

    */

   public int fingers;

  

   /**

    * The sum we guess (my fingers + opponent's fingers) for this round.

    * We win this round if this value equals the actual value (unless the opponent also guesses correctly). 

    * This is a guess we make before each round.

    * Set this value in the strategy() method.

    */

   public int sum;

  

   /**

    * The fingers the opponent raises in the previous round.

    * For the first round, this value is 0.

    *

    * This value is set during each round. So in the

    * strategy() method which is called prior to each round, this

    * value indicates the value of the previous round.

    *

    * This is a read only value, and changing it has no effect.

    */

   public int prevOpponentFingers;

  

   /**

    * The guessed sum by the opponent in the previous round.

    * For the first round, this value is 0.

    *

    * This value is set during each round. So in the

    * strategy() method which is called prior to each round, this

    * value indicates the value of the previous round.

    *

    * This is a read only value, and changing it has no effect.

    */

   public int prevOpponentSum;

  

   /**

    * The result of the previous round.

    * Possible values are: WIN, LOSE, or DRAW. From perspective of this robot.

    *

    *

    * This value is set during each round. So in the

    * strategy() method which is called prior to each round, this

    * value indicates the value of the previous round.

    *

    * This is a read only value, and changing it has no effect.

    */

   public int prevResult;

  

   /**

    * Helper. Stores the current round.

    */

   public int round;

  

   /**

    * Raise our fingers and guess the sum for this round.

    * This method is called before each round.

    * Set fingers & sum in this method.

    */

   public abstract void strategy();

  

   //////////////////////////////////////////////////////////

   // Helper for history records

   //////////////////////////////////////////////////////////

 

   public static class Record {

      public int myFingers = -1;

      public int mySum = -1;

      public int oppFingers = -1;

      public int oppSum = -1;

      public int result = UNKNOWN;

   }

  

   /**

    * Stores all previous records.

    */

   public Record[] history;

}


Top    Back



Common Help For All Sub-platforms

This part of help applies to app sub-platforms in Robotypo. It tells you some common rules of creating robots.




Upload A Robot

Click My Robots! in the left navigation area, you may need to login with Google account or an Open ID. Then click the Create button. Example code is already there. You can create your robots base on that.


Top    Back



Advanced Rules

Besides the basic rules, there are some other advanced rules:

  • Time limit: Each strategy() call must not take too long, and the accumulated time a robot consumes must not take too long. Exceeding the limit will result exception from the robot. This rule protects the system from being blocked by deadlock robots. Normally the time is enough. For example, the time limit per round for each robot is about 3 seconds, and the total accumulated time limit for each robot is about 15 seconds. However, since robot code runs in a complex and secured environment, it runs much slower than on your PC. So optimize your code, and use simple structure as much as possible (e.g. int[]).
  • Exception: If the action is out of range, (not HIDE, 0, 1, or 2), then exception occurs and the robot loses. Also, avoid modifying things except the action. For example, surely it is OK to set myTeam to null from perspective of Java language, but that will cause your robot exceptions.
Top    Back



Debugging

When you need this, you're likely creating some really good robots. Refer to the guide Setup Debug Environment for details.


Top    Back



Member Variables, Initialization, and Using Java Utilities

Since each robot is a Java class, you can create member variables to record and analyze opponent strategy. However, note that all opponent information of the previous round is already stored in some member variables, and you do not need to create additional member variables for that. Refer to the base class document of each platform for details. In addition, custom funtions, inner classes, and Java utilities can also be used. For example, the collection classes in package java.util. They are imported by default.


If you want to do some custom initialization, you can create a class constructor function to do this, or just inside a non-static initialization block (recommended). For example:


public class MyRobot extends ... {

 

    // A custom class

    static class MyData {

       //...

    }

   

    // A custom member variable

    List<MyData> items = new ArrayList<MyData>();

   

    // Initialization block

    {

       // Your class initialization code here

    }

 

    //A custom function

    void analyzeOpponentStrategy() {

       //...

    }

   

    public void strategy() {

      

       analyzeOpponentStrategy();

      

       // Other stuff

       // ...

    }

}


Top    Back



For more help, visit forum.