King Mode: Fix king placement phase not working correctly with multiple teams in a clan
New king placement phase rules:
* Before the game begins, each team can walk with their king and teleport for free, everything else is disabled
* This special round does not count towards the round counter, like in gfPlaceHog
* TotalRounds is set to -1 during this round, like in gfPlaceHog
Under the old rules, this was much more hacky. The delay of all delay-less weapons was just set to 1
The problem with the old rules was that if any clan had more than 1 team, eventually the weapon delay will time out before all kings have been placed.
pub struct LaggedFibonacciPRNG {
circular_buffer: [u32; 64],
index: usize,
}
impl LaggedFibonacciPRNG {
pub fn new(init_values: &[u8]) -> Self {
let mut buf = [0xa98765 + 68; 64];
for i in 0..std::cmp::min(init_values.len(), 54) {
buf[i] = init_values[i] as u32;
}
let mut prng = Self {
circular_buffer: buf,
index: 54,
};
prng.discard(2048);
prng
}
#[inline]
pub fn discard(&mut self, count: usize) {
for _i in 0..count {
self.get_next();
}
}
#[inline]
fn get_next(&mut self) -> u32 {
self.index = (self.index + 1) & 0x3f;
self.circular_buffer[self.index] = (self.circular_buffer[(self.index + 40) & 0x3f]
+ self.circular_buffer[(self.index + 9) & 0x3f])
& 0x7fffffff;
self.circular_buffer[self.index]
}
#[inline]
pub fn get_random(&mut self, modulo: u32) -> u32 {
self.get_next();
self.get_next() % modulo
}
#[inline]
pub fn add_randomness(&mut self, value: u32) {
self.index = (self.index + 1) & 0x3f;
self.circular_buffer[self.index] ^= value;
}
}
impl Iterator for LaggedFibonacciPRNG {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.get_next();
Some(self.get_next())
}
}
#[cfg(test)]
#[test]
fn compatibility() {
let mut prng = LaggedFibonacciPRNG::new("{052e2aee-ce41-4720-97bd-559a413bf866}".as_bytes());
assert_eq!(prng.get_random(1000), 418);
assert_eq!(prng.get_random(1000000), 554064);
assert_eq!(prng.get_random(0xffffffff), 239515837);
prng.add_randomness(123);
for i in 0..=100000 {
prng.get_random(2);
}
assert_eq!(prng.get_random(0xffffffff), 525333582);
}