From e7c7e81b4ed309a6a1c3430f6a90d19bfaa7c3f6 Mon Sep 17 00:00:00 2001
From: mehbark <terezi@pyrope.net>
Date: Tue, 11 Mar 2025 21:52:54 -0400
Subject: [PATCH] fix: much better now

---
 src/main.rs | 36 ++++++++++++++++--------------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 8625995..b5290c8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,7 +11,7 @@ use clap::Parser;
 use image::{ImageBuffer, Rgb};
 use rand::{
     distr::{Distribution, StandardUniform},
-    Rng, RngCore,
+    Rng,
 };
 use serde::Deserialize;
 
@@ -33,13 +33,9 @@ fn main() {
 
     let mut buffer = ImageBuffer::new(u32::from(width), u32::from(height));
 
-    let mut rolls = vec![0; width as usize * height as usize];
-
     let step_digits = format!("{steps}").len();
     for i in 0..steps {
-        rng.fill_bytes(&mut rolls);
-
-        let GameStep { old, new } = game.step(last, &mut rng, &rolls);
+        let GameStep { old, new } = game.step(last, &mut rng);
         game = new;
         last = old;
 
@@ -106,14 +102,13 @@ impl Game {
     }
 
     fn set(&mut self, x: i64, y: i64, to: Type) {
-        if self.in_bounds(x, y) {
-            self.field[(x + y * self.width) as usize] = to;
-        }
+        assert!(self.in_bounds(x, y));
+        self.field[(x + y * self.width) as usize] = to;
     }
 
     // let's see if we can get away with not swapping the field
     // nah it's easy
-    fn step(self, mut next: Self, rng: &mut impl Rng, rolls: &[u8]) -> GameStep {
+    fn step(self, mut next: Self, rng: &mut impl Rng) -> GameStep {
         for x in 0..self.width {
             for y in 0..self.height {
                 let dx = rng.random_range(-1..=1);
@@ -134,12 +129,13 @@ impl Game {
                     continue;
                 }
 
-                let roll = rolls[x as usize + y as usize * self.width as usize];
-                let won = roll <= here.win_chance(other);
+                let won = rng.random::<f32>() <= here.win_chance(other);
                 if won {
+                    next.set(x, y, here);
                     next.set(ox, oy, here);
                 } else {
                     next.set(x, y, other);
+                    next.set(ox, oy, other);
                 }
             }
         }
@@ -238,20 +234,20 @@ impl Type {
     }
 
     // nothing is immune to itself, phew
-    fn win_chance(self, other: Type) -> u8 {
+    fn win_chance(self, other: Type) -> f32 {
         use Efficacy::{Neutral, Strong, Weak, Zero};
         let self_eff = self.efficacy(other);
         let def_eff = other.efficacy(self);
         // if you are twice as effective, you should win twice as often: 2/3 vs 1/3
         // if you are four times as effective, you should win four times as often: 4/5 vs 1/5
         match (self_eff, def_eff) {
-            (Strong, Strong) | (Neutral, Neutral) | (Weak, Weak) | (Zero, Zero) => u8::MAX / 2,
-            (Zero, _) => 0,
-            (_, Zero) => u8::MAX,
-            (Strong, Neutral) | (Neutral, Weak) => 170, // 2/3
-            (Neutral, Strong) | (Weak, Neutral) => 85,  // 1/3
-            (Strong, Weak) => 204,                      // 4/5
-            (Weak, Strong) => 51,                       // 1/5
+            (Strong, Strong) | (Neutral, Neutral) | (Weak, Weak) | (Zero, Zero) => 0.5,
+            (Zero, _) => 0.0,
+            (_, Zero) => 1.0,
+            (Strong, Neutral) | (Neutral, Weak) => 2. / 3.,
+            (Neutral, Strong) | (Weak, Neutral) => 1. / 3.,
+            (Strong, Weak) => 4. / 5.,
+            (Weak, Strong) => 1. / 5.,
         }
     }