Leaguify cheating
[troll.git] / src / test / java / TrollTest.java
1 import java.util.Properties;
2 import java.util.List;
3 import java.util.ListIterator;
4 import java.util.Map;
5 import java.io.PrintStream;
6
7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.*;
9 import org.junit.Test;
10
11 import com.codingame.gameengine.runner.MultiplayerGameRunner;
12 import com.codingame.gameengine.runner.dto.*;
13
14 public class TrollTest implements Cloneable {
15     Integer leagueLevel;
16     Long seed;
17     TrollTest branch() {
18         try { return (TrollTest) clone(); }
19         catch (CloneNotSupportedException e) { throw new InternalError(e); }
20     }
21     TrollTest setLeague(int league) { leagueLevel = league; return this; }
22     TrollTest setSeed(long seed) { this.seed = seed; return this; }
23
24     GameResult runGame(String left, String right) {
25         MultiplayerGameRunner gameRunner = new MultiplayerGameRunner();
26         Properties gameParameters = new Properties();
27         gameParameters.setProperty("roadLength", "6");
28         gameParameters.setProperty("initialStones", "15");
29         gameRunner.setGameParameters(gameParameters);
30         if (seed != null) gameRunner.setSeed(seed); else gameRunner.setSeed(0l);
31         if (leagueLevel != null) gameRunner.setLeagueLevel(leagueLevel);
32
33         gameRunner.addAgent(left);
34         gameRunner.addAgent(right);
35
36         return gameRunner.simulate();
37     }
38
39     @Test
40     public void drawGame() {
41         assertIsDraw(runGame(agentOne, agentOne));
42     }
43
44     @Test
45     public void defeatGames() {
46         assertIsDefeat(runGame(agentCrash, agentCrash));
47         assertIsDefeat(runGame(agentGarbage, agentGarbage));
48     }
49
50     @Test
51     public void simpleGames() {
52         // wins by direct reach, no fastforward
53         assertWinLose(agentTwo, agentOne);
54
55         // win by fastforward after loser exhaustion
56         assertWinLose(agentOne, "yes 15");
57
58         // win despite fastforward after winner exhaustion
59         // (harder to construct :-D )
60         assertWinLose(agent(1,2,2,2,8), agent(3,1,1,1,8));
61     }
62
63     @Test
64     public void cheatingGames() {
65         // win by cheating (works in league 1, which is the default)
66         assertWinLose(agentCheat, agentTwo);
67
68         // league 2 randomizes: we should be able to get a win and a loss
69         branch().setLeague(2).setSeed(0).assertWinLose(agentCheat, agentTwo);
70         branch().setLeague(2).setSeed(1).assertWinLose(agentTwo, agentCheat);
71     }
72
73     // great thanks to @dbdr for the intense moral support leading to
74     // the following:
75     static String agentOne = "yes 1";
76     static String agentTwo = "yes 2";
77     static String agentCrash = "false";
78     static String agentGarbage = "yes this_is_assuredly_not_an_int";
79     static String agentCheat = agent(-100,25,25,25,25);
80
81     static String agent(int... tosses) {
82         String cmd = "echo -e ";
83         for (int i = 0; i < tosses.length; i++) {
84             if (i > 0) cmd += "\\n";
85             cmd += tosses[i];
86         }
87         return cmd;
88     }
89
90     static void dumpGameResult(PrintStream p, GameResult gameResult) {
91         for (AgentDto agent : gameResult.agents) dumpAgent(p, agent);
92         dumpMap(p, "errors", gameResult.errors);
93         dumpString(p, "failCause", gameResult.failCause);
94         dumpMap(p, "ids", gameResult.ids);
95         dumpString(p, "metadata", gameResult.metadata);
96         dumpMap(p, "outputs", gameResult.outputs);
97         dumpList(p, "summaries", gameResult.summaries);
98         dumpList(p, "tooltips", gameResult.tooltips);
99         // dumpList(p, "views", gameResult.views);
100     }
101
102     static <V> void dumpList(PrintStream p, String tag, List<V> list) {
103         ListIterator i = list.listIterator();
104         while (i.hasNext()) {
105             if (tag != null) p.print(tag + " ");
106             p.print(i.nextIndex() + ": ");
107             dumpGeneric(p, i.next());
108         }
109     }
110
111     static <K,V> void dumpMap(PrintStream p, String tag, Map<K,V> map) {
112         for (Map.Entry kv : map.entrySet()) {
113             p.print(tag + " for " + kv.getKey() + ": ");
114             dumpGeneric(p, kv.getValue());
115         }
116     }
117
118     static <E,V> void dumpGeneric(PrintStream p, E v) {
119         if (v instanceof List) {
120             dumpList(p, null, (List<?>) v);
121         }
122         else {
123             p.println(v);
124         }
125     }
126
127     static void dumpString(PrintStream p, String tag, String msg) {
128         p.println(tag + ": " + msg);
129     }
130
131     static void dumpAgent(PrintStream p, AgentDto agent) {
132         p.println("[agent] " + agent.agentId + ": " + agent.avatar + " " + agent.index + " " + agent.name);
133     }
134
135     void assertWinLose(String winner, String loser) {
136         assertLeftWin(runGame(winner, loser));
137         assertRightWin(runGame(loser, winner));
138     }
139
140     static void assertLeftWin(GameResult gameResult) {
141         assertLeftWin(gameResult, false);
142     }
143     static void assertLeftWin(GameResult gameResult, boolean strict) {
144         int[] scores = assertTwoScores(gameResult);
145         if (scores == null) return;
146
147         int s1 = scores[0], s2 = scores[1];
148         assertTrue("Left player has higher score than right player", s1 > s2);
149         if (strict) assertTrue("Right player isn't disqualified", s2 >= 0);
150     }
151
152     static void assertRightWin(GameResult gameResult) {
153         assertRightWin(gameResult, false);
154     }
155     static void assertRightWin(GameResult gameResult, boolean strict) {
156         int[] scores = assertTwoScores(gameResult);
157         if (scores == null) return;
158
159         int s1 = scores[0], s2 = scores[1];
160         assertTrue("Right player has higher score than right player", s2 > s1);
161         if (strict) assertTrue("Left player isn't disqualified", s1 >= 0);
162     }
163
164     static void assertIsDraw(GameResult gameResult) {
165         int[] scores = assertTwoScores(gameResult);
166         if (scores == null) return;
167
168         int s1 = scores[0], s2 = scores[1];
169         assertEquals("Player scores are equal", s1, s2);
170         assertTrue("Player scores are non-negative", s1 >= 0);
171     }
172
173     static void assertIsDefeat(GameResult gameResult) {
174         int[] scores = assertTwoScores(gameResult);
175         if (scores == null) return;
176
177         int s1 = scores[0], s2 = scores[1];
178         assertTrue("First player score is negative", s1 < 0);
179         assertTrue("Second player score is negative", s2 < 0);
180     }
181
182     static int[] assertTwoScores(GameResult gameResult) {
183         Map<Integer,Integer> scores = gameResult.scores;
184         assertEquals("Two scores are reported", scores.size(), 2);
185         assertTrue("Player 0 has a score", scores.containsKey(0));
186         assertTrue("Player 1 has a score", scores.containsKey(1));
187         return new int[] { scores.get(0), scores.get(1) };
188     }
189 }