Code:
public class Library {
public static void main(String[] args) throws Exception {
int[] counts = {0, 0, 0, 0};
for(int i=0; i<1000000; i++) {
counts[simulateGame(9, 2, 2, 2)]++;
}
System.out.printf("Town Wins:%d\nMafia Wins:%d\nTriad Wins:%d\nNo One Wins:%d\n", counts[0], counts[1], counts[2], counts[3]);
}
static int simulateGame(int town, int mafia, int triad, int namedTown) {
int vt = town - namedTown;
int hpr = namedTown;
int opr = 0;
int maf = mafia;
int tri = triad;
StringBuilder sb = new StringBuilder();
int cycle = 1;
while(!scumMaj(vt + hpr + opr, maf, tri) && (maf>0 || tri>0)) {
sb.append(String.format("Day %d\n", cycle));
sb.append(String.format("%d %d %d %d %d\n", vt, hpr, opr, maf, tri));
// Day
int target = selectDayTarget(vt, hpr, maf, tri);
while(target == 1) {
hpr--;
opr++;
target = selectDayTarget(vt, hpr, maf, tri);
}
if(target == 0) vt--;
if(target == 2) maf--;
if(target == 3) tri--;
// Night
sb.append(String.format("Night %d\n", cycle));
sb.append(String.format("%d %d %d %d %d\n", vt, hpr, opr, maf, tri));
if(opr > 0 && (maf > 0 || tri > 0)) opr = 0;
else {
int mafTarget = selectNightTarget(vt, hpr, tri);
int triTarget = selectNightTarget(vt, hpr, maf);
if(maf == 0) mafTarget = -2;
if(tri == 0) triTarget = -2;
if(mafTarget != -2) {
if (mafTarget == -1) {
tri--;
} else if (mafTarget < vt) {
vt--;
} else {
hpr--;
}
}
if(triTarget != -2) {
if(triTarget == -1) {
maf--;
} else if(triTarget != mafTarget) {
if(triTarget < vt) {
vt--;
} else {
hpr--;
}
}
}
}
cycle++;
sb.append(String.format("Dawn %d\n", cycle));
sb.append(String.format("%d %d %d %d %d\n", vt, hpr, opr, maf, tri));
}
int t = vt + hpr + opr;
if(maf == 0 && tri == 0 && t > 0) return 0;
if(maf >= tri + t && tri < maf + t) return 1;
if(tri >= maf + t && maf < tri + t) return 2;
if(maf + tri + t == 0) return 3;
if(maf == tri && maf >= tri + t && tri >= maf + t) {
if(Math.random() < 0.5) return 1;
return 2;
}
System.out.println(sb.toString());
return -1;
}
static boolean scumMaj(int town, int maf, int tri) {
if(maf >= tri + town) return true;
if(tri >= maf + town) return true;
return false;
}
static int selectDayTarget(int vt, int hpr, int maf, int tri) {
int total = vt + hpr + maf + tri;
int result = (int)(Math.random() * total);
if(result < vt) return 0;
if(result < vt + hpr) return 1;
if(result < vt + hpr + maf) return 2;
return 3;
}
static int selectNightTarget(int vt, int hpr, int enemy) {
int result = (int)(Math.random() * (vt + hpr + enemy));
if(result < vt + hpr) return result;
return -1;
}
}