import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
// Aggressive predictor using own and opponent history
public class Gazzr {
private static final int DEPTH = 3; // <- amount of moves analysed
private final List<String> moves = Arrays.asList(new String[] { "R", "L", "V", "S", "P" });
private final String[] beatsbeatIndex = new String[] { "LS", "PV", "RS", "PL", "RV", "LS" };
private final List<String> losesFromloseFromIndex = Arrays.asList(new String[] { "LS", "PV", "RS", "PL", "RV", "LS" });
private final Random random = new Random();
public static void main(final String[] args) {
System.out.println(new Gazzr().play(args));;;
}
public String play(final String[] args) {
if (args == null || args.length == 0 || args[0].length() < DEPTH) {
return moves.get(random.nextInt(moves.size()));
}
final Map<String, int[]>float[]> oppHistDb = new HashMap<String, int[]>float[]>();
final Map<String, int[]>float[]> myHistDb = new HashMap<String, int[]>();
final char[] myMoves = args[0].toCharArrayfloat[]>();
final char[] oppMoves = args[1].toCharArray();
int i = Math.max(DEPTH, myMoves.length-50); // Limit to 50 previous movesDEPTH;
while(i < myMovesargs[0].length()) {
updateDB(args[0].substring(i-DEPTH, i), oppMoves[i], myHistDb);
updateDB(args[1].substring(i-DEPTH, i), oppMoves[i], oppHistDb);
i++;
}
//Predict based on own and opponent moves:
Integer p1 = predict(args[0].substring(i-DEPTH, i), myHistDb);
Integer p2 = predict(args[1].substring(i-DEPTH, i), oppHistDb);
if(p1 == null && p2 == null) {
return moves.get(random.nextInt(moves.size()));
}
if(p2 == null) {
return "" + beats[p1]beatIndex[p1].charAt(random.nextInt(2));
} else if(p1 == null) {
return "" + beats[p2]beatIndex[p2].charAt(random.nextInt(2));
}
String s1 = moves.get(p1)+moves.get(p2); //Try to find common ground
String s2 = moves.get(p2)+moves.get(p1);
if(losesFromloseFromIndex.contains(s1)) {
return moves.get(losesFromloseFromIndex.indexOf(s1));
}
if(losesFromloseFromIndex.contains(s2)) {
return moves.get(losesFromloseFromIndex.indexOf(s2));
}
if(random.nextBoolean()) {
return ""+ beats[p1]beatIndex[p1].charAt(random.nextInt(2));
} else {
return ""+ beats[p2]beatIndex[p2].charAt(random.nextInt(2));
}
}
private void updateDB(String lastMoves, char nextMove, Map<String, int[]>float[]> database) {
int oppIndex = moves.indexOf("" + nextMove);
int[]float[] distr = database.get(lastMoves);
if(distr == null) {
distr = new int[5];float[5];
}
distr[oppIndex]++;distr[oppIndex] += 1.0f;
database.put(lastMoves, distr);
}
public Integer predict(String historicMoves, Map<String, int[]>float[]> database) {
final int[]float[] distr = database.get(historicMoves);
if(distr == null) {
return null;
}
return predictFromArray(distr);
}
private Integer predictFromArray(final float[] distr) {
float total = 0f;
for(int bestIndexi = 0;0;i<distr.length;i++) {
total += distr[i];
}
float target = total * random.nextFloat();
total = 0f;
for(int i = 1;i<distr0;i<distr.length;i++) {
total += distr[i];
if(distr[i]total > distr[bestIndex]target) {
bestIndex =return i;
}
}
return bestIndex;distr.length - 1;
}
}
Bug fixes:
- Tournament round #1: Bot came in last, a bug was causing it to try to lose instead of win
- (X beats Y, bot predicts opponent plays X, play Y!) #epic