2 hours for 10k iterations spurred me to rewrite code in Rust, as I'm considering applying this to sofrrush
extern crate rand;
extern crate rayon;
use std::collections::HashSet;
use rayon::prelude::*;
use rand::Rng;
fn decks() -> Vec<((u8, u8, u8, u8), [u8; 6])> {
let mut ret = Vec::new();
let pcount = 14;
let lidr = 17 - pcount;
for aepi in 0..pcount {
for lipi in 0..(pcount - aepi) {
let lipe = pcount - aepi - lipi;
if lipe < 7 || lipi + lidr + lipe < 15 { continue }
let maxups = [aepi, 0, lipi, lipe, lidr, 3];
let mut ups = HashSet::new();
ups.insert([0; 6]);
for _ in 0..8 {
let mut nups = HashSet::new();
for up in &ups {
for &i in &[0, 2, 3, 4, 5] {
if up[i] < maxups[i] {
let mut nup = *up;
nup[i] += 1;
nups.insert(nup);
}
}
}
ups = nups;
}
for up in &ups {
if up[2] + up[3] + up[4] >= 4 {
ret.push(((aepi, lipi, lipe, lidr), *up))
}
}
}
}
ret
}
fn simulate(tdeck: ((u8, u8, u8, u8), [u8; 6])) -> (((u8, u8, u8, u8), [u8; 6]), [i32; 6], i32, i32, i32) {
let ((aeli, lipi, lipe, lidr), up) = tdeck;
let mut deck = vec![6,6,6,6,6,6,7];
deck.reserve(23);
for _c0 in 0..(aeli - up[0]) {
deck.push(0);
}
for _c2 in 0..(lipi - up[2]) {
deck.push(2);
}
for _c3 in 0..(lipe - up[3]) {
deck.push(3);
}
for _c4 in 0..(lidr - up[4]) {
deck.push(4);
}
for _c5 in 0..(6 - up[5]) {
deck.push(5);
}
for &cx in &[0, 2, 3, 4, 5] {
for _c in 0..up[cx as usize] {
deck.push(!cx);
}
}
let mut turns = [0; 6];
let mut dies = 0;
let mut exae = 0;
let mut exli = 0;
for _ in 0..100000 {
rand::thread_rng().shuffle(&mut deck);
let mut aepi = 0;
let mut lipi = 0;
let mut lipe = 0;
let mut lupe = 0;
let mut lidr = 0;
let mut ludr = 0;
let mut lidrx = deck.iter().position(|&x| x == 4).unwrap_or(99);
let mut ludrx = deck.iter().position(|&x| x == !4).unwrap_or(99);
let mut pux = deck.iter().position(|&x| x == 5).unwrap_or(99);
let mut upux = deck.iter().position(|&x| x == !5).unwrap_or(99);
let mut dix = deck.iter().position(|&x| x == 6).unwrap_or(99);
let mut lox = deck.iter().position(|&x| x == 7).unwrap_or(99);
let mut li = 0;
let mut ae = 0;
for &c in &deck[0..7] {
match c {
0 => aepi += 1,
2 => lipi += 1,
3 => lipe += 1,
-1 => {aepi += 1; ae += 1},
-3 => {lipi += 1; li += 1},
-4 => {lupe += 1; li += 1},
_ => (),
}
}
ae += aepi;
li += lipi + lipe + lupe;
let mut lit = lipe > 0;
let mut lut = lupe > 0;
let mut dim = false;
let mut lob = false;
let mut turn = turns;
for i in 0..6 {
let ti = i+7;
let c = deck[ti];
match c {
0 => aepi += 1,
2 => lipi += 1,
3 => lipe += 1,
-1 => {aepi += 1; ae += 1},
-3 => {lipi += 1; li += 1},
-4 => {lupe += 1; li += 1},
_ => (),
}
while ludrx <= ti && li >= 13 {
ludr += 1;
li -= 13;
ludrx = deck[ludrx+1..].iter().position(|&x| x == !4).unwrap_or(99);
}
while lidrx <= ti && li >= 12 {
lidr += 1;
li -= 12;
lidrx = deck[lidrx+1..].iter().position(|&x| x == 4).unwrap_or(99);
}
while !dim && dix <= ti && i>3 && ae >= 6 {
ae -= 6;
dim = true;
dix = deck[dix+1..].iter().position(|&x| x == 6).unwrap_or(99);
}
while upux <= ti &&
ae >= if dim || i<4 { 6 } else { 12 } &&
(lidr > 0 || ludr > 0)
{
if ludr > 0 { ludr += 1 }
else { lidr += 1 }
ae -= 6;
upux = deck[upux+1..].iter().position(|&x| x == !5).unwrap_or(99);
}
while pux <= ti &&
ae >= if dim || i<4 { 7 } else { 13 } &&
(lidr > 0 || ludr > 0)
{
if ludr > 0 { ludr += 1 }
else { lidr += 1 }
ae -= 7;
pux = deck[pux+1..].iter().position(|&x| x == 5).unwrap_or(99);
}
while !lob && lox <= ti && ae >= if dim || i<5 { 3 } else { 9 } {
ae -= 3;
lob = true;
lox = deck[lox+1..].iter().position(|&x| x == 7).unwrap_or(99);
}
ae += aepi;
li += lipi;
if lit { ae += lipe }
else { li += lipe }
if lut { ae += lupe }
else { li += lupe }
lit ^= lipe > 0;
lut ^= lupe > 0;
turn[i] += ludr * 12 + lidr * 10 + if lob { 5 } else { 0 };
}
if dim { turns = turn }
else { dies += 1}
exae += ae;
exli += li;
}
(tdeck, turns, exae, exli, dies)
}
fn dmg(turns: &[i32]) -> i32 {
let mut x = 0;
let mut d = 0;
for a in turns {
x += *a;
d += x;
}
d
}
fn main() {
let d = decks();
let mut sim = Vec::new();
d.into_par_iter().weight_max().map(simulate).collect_into(&mut sim);
sim.sort_by_key(|x| dmg(&x.1));
println!("{:?}", sim.last().unwrap());
}