Great German Games with a Hedgehog | ||||
Our Games About us Online Games Events Other Contact Order Infos | ||||
Home > Online Games > Numfield > Do Your Strategy |
abstract class Strategy { int maxSteps; int stepBonus; int opponents; int maxPlayableNumber; // You have to keep that method since it is final final public void init(int maxSteps, int maxPlayableNumber, int stepBonus, int opponents) { this.maxSteps = maxSteps; this.stepBonus = stepBonus; this.opponents = opponents; this.maxPlayableNumber = maxPlayableNumber; priv_init(); } // Overload this procedure to do your own // initialization: void priv_init() { } // Overload this procedure to decide your first turn: abstract public int initial_turn(); // Overload this procedure to decide further turns: abstract public int turn(int last_turns[], int scores[], int carryOver, int turn_no); // This hook is usually ignoreable but was necessary // for the PlayYourSelf strategy! public void destroy() { } public void show() { } public void hide() { } } } |
Yes I see the coding is not entirely consistent about the naming convention for variables, but I didn't know the Sun conventions when I started that project.
To derive your own version you need to override the following methods:
priv_init | for special initialization |
initial_turn | for the first turn in the game |
turn | for all further turns |
The only method of the above which uses parameters is turn . The parameters have the following meaning:
last_turns | contains the last bets of all strategies. Note the strategies own last turn is located at index 0. The existing indices are 0 to (number of players-1). |
scores | contains the accumulated points of all strategies. Indices work as for last_turns. |
carryOver | contains the points of the pot carried over from last round |
turn_no | is the number of the current round. |
To make programming easier every sub class of strategy should use the following variables which are set appropriately during initialization:
maxPlayableNumber | The highest number a strategy can play legaly (default is 99). |
stepBonus | amount added to the pot by the bank every turn (default is 1). |
opponents | Number of opponents found during initialization. To find the currently living you have to count dead ones (score less or equal zero). |
maxSteps | has no meaning yet. |
If your strategy needs any other information it could derive them from that information and should do its own bookkeeping. Somewhere below there is an example of simple bookkeeping
Note: If I get classes which exhaust CPU time or memory I might have to exclude them from participation. But I think there should be many interesting strategies with a reasonable amount of resource consumption.
This very simple strategy shows that a simple strategy is coded fairly simple:
class Strat23 extends Strategy { public int initial_turn() { return 2; } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { // What did we do last time? return last_turns[0] == 2 ? 3 : 2; } } |
You can also derive your own subclasses which have a common behaviour, e.g.:
class StratConst extends Strategy { public int initial_turn() { return 1; } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { return last_turns[0]; } } class Const2 extends StratConst { public int initial_turn() { return 2; } } |
A randomized player:
class Random11 extends Strategy { public int initial_turn() { return (int) (Math.random() * 11.0 + 1); } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { return initial_turn(); } } |
This is a very simple strategy which does a bit of own bookkeeping:
class Nihilist extends Strategy { public int average, sum; public int initial_turn() { return 0; } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { sum += carryOver; average = sum / turn_no; if ( carryOver > average ) return 1; else return 0; } } |
// Play the number which would have made highest // gain in last turn. class Shark5 extends Strategy { public int initial_turn() { return 1; } // A tiny little turn-evaluator: int eval(int turns[], int carry, int scores[]) { int i, j, sum, t, parts, t0; sum = carry; parts = 0; t0 = 0; for (i = 0; i < opponents; i++) if ( scores[i] > 0 ) { if ( turns[i] > 0 ) { sum += turns[i]; t = 0; for (j = 0; j < opponents; j++) { if ( turns[j] > 0 && turns[i] >= turns[j] ) t++; } if (i == 0) t0 = t; parts += t; } } sum += stepBonus; if ( parts == 0 ) return 0; return (int) ( sum * t0 ) / parts - turns[0]; } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { int i, i0, w, w0; w0 = - maxPlayableNumber; i0 = 0; for (i = 0; i <= maxPlayableNumber; i++) { last_turns[0] = i; w = eval(last_turns, carryOver, scores); if ( w > w0 ) { w0 = w; i0 = i; } } return i0; } } |
// Play the number which would have made highest // gain in last 2 turns. class Shark6 extends Shark5 { public int initial_turn() { return 0; } int lt[]; void priv_init() { // Allocate memory to remember previous turns: lt = new int[opponents]; } public int turn(int last_turns[], int scores[], int carryOver, int turn_no) { int i, i0, w, w0; if ( turn_no <= 1 ) { i0 = 0; } else { w0 = - maxPlayableNumber; i0 = 0; for (i = 0; i <= maxPlayableNumber; i++) { last_turns[0] = i; lt[0] = i; w = eval(last_turns, carryOver, scores) +eval(lt,carryOver, scores); if ( w > w0 ) { w0 = w; i0 = i; } } } for (i = 0; i < opponents; i++) lt[i] = last_turns[i]; return i0; } } |
A few pages further ahead there can be found more samples of strategy source code .
And please forget about the examples: Try s.th. completely different! Just take the examples as demonstrations of the technique.
OK, thats all by now. Now its your turn!