1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
use rand::prelude::*;
use std::collections::HashMap;

use super::row::*;
use super::skill::*;
use super::slab_def::*;

#[derive(PartialEq, PartialOrd)]
struct DefDensity {
    def: SlabDef,
    density: f64,
}

impl std::cmp::Eq for DefDensity {}

impl std::cmp::Ord for DefDensity {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.def.cmp(&other.def)
    }
}

fn build_rng_seed(seed: u64, row_index: usize) -> [u8; 32] {
    let mut buf: [u8; 32] = [0; 32];
    let buf1 = bincode::serialize(&seed).unwrap();
    let mut i: usize = 0;
    for v in buf1.into_iter() {
        buf[i] = v;
        i += 1;
    }
    let buf2 = bincode::serialize(&row_index).unwrap();
    for v in buf2.into_iter() {
        buf[i] = v;
        i += 1;
    }
    buf
}

pub fn generate_first_row(seed: u64, width: usize, skill: Skill) -> Row {
    let rng_seed = build_rng_seed(seed, 0);
    let rng: StdRng = SeedableRng::from_seed(rng_seed);
    let def_density = skill.def_density0();
    row_from_def_density(rng, width, &def_density)
}

pub fn generate_next_row(seed: u64, j: usize, previous_row: &Row, skill: Skill) -> Row {
    let rng_seed = build_rng_seed(seed, j);
    let rng: StdRng = SeedableRng::from_seed(rng_seed);
    let def_density = skill.def_density();
    row_from_previous(rng, previous_row, &def_density, skill.mutability())
}

fn row_from_def_density(
    mut rng: impl Rng,
    width: usize,
    def_density: &HashMap<SlabDef, f64>,
) -> Row {
    let mut row = Row::default();
    let mut v: Vec<DefDensity> = Vec::new();
    for (def, density) in def_density {
        v.push(DefDensity {
            def: *def,
            density: *density,
        });
    }
    v.sort();
    for i in 0..width {
        let f: f64 = rng.gen();
        let mut limit: f64 = 0.0;
        for dd in &v {
            if f >= limit && f < limit + dd.density {
                row.set(i as isize, dd.def);
                break;
            }
            limit += dd.density;
        }
    }
    row
}

fn row_from_previous(
    mut rng: impl Rng,
    previous_row: &Row,
    def_density: &HashMap<SlabDef, f64>,
    mutability: f64,
) -> Row {
    let mut row = Row::default();
    let mut v: Vec<DefDensity> = Vec::new();
    for (def, density) in def_density {
        v.push(DefDensity {
            def: *def,
            density: *density,
        });
    }
    v.sort();
    for i in 0..(previous_row.slabs.len() as isize) {
        let f: f64 = rng.gen();
        let mut limit: f64 = 0.0;
        for dd in &v {
            if f >= limit && f < limit + dd.density {
                row.set(i, dd.def);
                break;
            }
            limit += dd.density;
        }
        let change: f64 = rng.gen();
        let previous_def = previous_row.get(i);
        if change >= mutability && !previous_def.is_special() && !row.get(i).is_special() {
            row.set(i as isize, previous_def);
        }
    }
    row
}