tweaks
This commit is contained in:
parent
727f4f2957
commit
df8d4d06bf
2 changed files with 57 additions and 43 deletions
|
@ -13,13 +13,13 @@ end
|
||||||
branches = eff.flat_map do |eff|
|
branches = eff.flat_map do |eff|
|
||||||
type = eff['name']
|
type = eff['name']
|
||||||
[
|
[
|
||||||
*make_branches(type, eff['immunes'], 'Immune'),
|
*make_branches(type, eff['immunes'], 'Zero'),
|
||||||
*make_branches(type, eff['weaknesses'], 'Weak'),
|
*make_branches(type, eff['weaknesses'], 'Weak'),
|
||||||
*make_branches(type, eff['strengths'], 'Strong'),
|
*make_branches(type, eff['strengths'], 'Strong'),
|
||||||
*make_branches(type, ['_'], 'Neutral'),
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "match (self, defender) {
|
puts "match (self, defender) {
|
||||||
#{branches.join("\n ")}
|
#{branches.join("\n ")}
|
||||||
|
#{make_branches('_', ['_'], 'Neutral')[0]}
|
||||||
}"
|
}"
|
||||||
|
|
96
src/main.rs
96
src/main.rs
|
@ -11,7 +11,7 @@ use clap::Parser;
|
||||||
use image::{ImageBuffer, Rgb};
|
use image::{ImageBuffer, Rgb};
|
||||||
use rand::{
|
use rand::{
|
||||||
distr::{Distribution, StandardUniform},
|
distr::{Distribution, StandardUniform},
|
||||||
Rng,
|
Rng, RngCore,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
@ -33,17 +33,22 @@ fn main() {
|
||||||
|
|
||||||
let mut buffer = ImageBuffer::new(u32::from(width), u32::from(height));
|
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 {
|
for i in 0..steps {
|
||||||
let GameStep { old, new } = game.step(last, &mut rng);
|
rng.fill_bytes(&mut rolls);
|
||||||
|
let GameStep { old, new } = game.step(last, &mut rng, &rolls);
|
||||||
game = new;
|
game = new;
|
||||||
last = old;
|
last = old;
|
||||||
|
|
||||||
game.write_to_buffer(&mut buffer);
|
game.write_to_buffer(&mut buffer);
|
||||||
|
|
||||||
let path = format!("{output_prefix}{i:0OUTPUT_DIGITS$}.png");
|
let path = format!("{output_prefix}{i:0OUTPUT_DIGITS$}.png");
|
||||||
if let Err(e) = buffer.save(path) {
|
if let Err(e) = buffer.save(path) {
|
||||||
eprintln!("error saving image: {e}");
|
eprintln!("error saving image: {e}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
eprintln!("step {:step_digits$}/{steps}", i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +110,7 @@ impl Game {
|
||||||
|
|
||||||
// let's see if we can get away with not swapping the field
|
// let's see if we can get away with not swapping the field
|
||||||
// nah it's easy
|
// nah it's easy
|
||||||
fn step(self, mut next: Self, rng: &mut impl Rng) -> GameStep {
|
fn step(self, mut next: Self, rng: &mut impl Rng, rolls: &[u8]) -> GameStep {
|
||||||
for x in 0..self.width {
|
for x in 0..self.width {
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
let dx = rng.random_range(-1..=1);
|
let dx = rng.random_range(-1..=1);
|
||||||
|
@ -126,7 +131,8 @@ impl Game {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let won = rng.random::<f32>() <= here.win_chance(other);
|
let roll = rolls[x as usize + y as usize * self.width as usize];
|
||||||
|
let won = roll <= here.win_chance(other);
|
||||||
if won {
|
if won {
|
||||||
next.set(ox, oy, here);
|
next.set(ox, oy, here);
|
||||||
} else {
|
} else {
|
||||||
|
@ -173,12 +179,37 @@ enum Type {
|
||||||
Fairy,
|
Fairy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Type> for usize {
|
||||||
|
fn from(value: Type) -> Self {
|
||||||
|
match value {
|
||||||
|
Type::Normal => 0,
|
||||||
|
Type::Fire => 1,
|
||||||
|
Type::Water => 2,
|
||||||
|
Type::Electric => todo!(),
|
||||||
|
Type::Grass => todo!(),
|
||||||
|
Type::Ice => todo!(),
|
||||||
|
Type::Fighting => todo!(),
|
||||||
|
Type::Poison => todo!(),
|
||||||
|
Type::Ground => todo!(),
|
||||||
|
Type::Flying => todo!(),
|
||||||
|
Type::Psychic => todo!(),
|
||||||
|
Type::Bug => todo!(),
|
||||||
|
Type::Rock => todo!(),
|
||||||
|
Type::Ghost => todo!(),
|
||||||
|
Type::Dragon => todo!(),
|
||||||
|
Type::Dark => todo!(),
|
||||||
|
Type::Steel => todo!(),
|
||||||
|
Type::Fairy => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
enum Efficacy {
|
enum Efficacy {
|
||||||
Strong,
|
Strong,
|
||||||
Neutral,
|
Neutral,
|
||||||
Weak,
|
Weak,
|
||||||
Immune,
|
Zero,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
@ -229,20 +260,20 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing is immune to itself, phew
|
// nothing is immune to itself, phew
|
||||||
fn win_chance(self, other: Type) -> f32 {
|
fn win_chance(self, other: Type) -> u8 {
|
||||||
use Efficacy::{Immune, Neutral, Strong, Weak};
|
use Efficacy::{Neutral, Strong, Weak, Zero};
|
||||||
let self_eff = self.efficacy(other);
|
let self_eff = self.efficacy(other);
|
||||||
let def_eff = other.efficacy(self);
|
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 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
|
// if you are four times as effective, you should win four times as often: 4/5 vs 1/5
|
||||||
match (self_eff, def_eff) {
|
match (self_eff, def_eff) {
|
||||||
(Strong, Strong) | (Neutral, Neutral) | (Weak, Weak) | (Immune, Immune) => 0.5,
|
(Strong, Strong) | (Neutral, Neutral) | (Weak, Weak) | (Zero, Zero) => u8::MAX / 2,
|
||||||
(Immune, _) => 1.0,
|
(Zero, _) => 0,
|
||||||
(_, Immune) => 0.0,
|
(_, Zero) => u8::MAX,
|
||||||
(Strong, Neutral) | (Neutral, Weak) => 2. / 3.,
|
(Strong, Neutral) | (Neutral, Weak) => 170, // 2/3
|
||||||
(Neutral, Strong) | (Weak, Neutral) => 1. / 3.,
|
(Neutral, Strong) | (Weak, Neutral) => 85, // 1/3
|
||||||
(Strong, Weak) => 4. / 5.,
|
(Strong, Weak) => 204, // 4/5
|
||||||
(Weak, Strong) => 1. / 5.,
|
(Weak, Strong) => 51, // 1/5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,67 +285,50 @@ impl Type {
|
||||||
use Efficacy::*;
|
use Efficacy::*;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
match (self, defender) {
|
match (self, defender) {
|
||||||
(Normal, Ghost) => Immune,
|
(Normal, Ghost) => Zero,
|
||||||
(Normal, Rock | Steel) => Weak,
|
(Normal, Rock | Steel) => Weak,
|
||||||
(Normal, _) => Neutral,
|
|
||||||
(Fire, Fire | Water | Rock | Dragon) => Weak,
|
(Fire, Fire | Water | Rock | Dragon) => Weak,
|
||||||
(Fire, Grass | Ice | Bug | Steel) => Strong,
|
(Fire, Grass | Ice | Bug | Steel) => Strong,
|
||||||
(Fire, _) => Neutral,
|
|
||||||
(Water, Water | Grass | Dragon) => Weak,
|
(Water, Water | Grass | Dragon) => Weak,
|
||||||
(Water, Fire | Ground | Rock) => Strong,
|
(Water, Fire | Ground | Rock) => Strong,
|
||||||
(Water, _) => Neutral,
|
(Electric, Ground) => Zero,
|
||||||
(Electric, Ground) => Immune,
|
|
||||||
(Electric, Electric | Grass | Dragon) => Weak,
|
(Electric, Electric | Grass | Dragon) => Weak,
|
||||||
(Electric, Water | Flying) => Strong,
|
(Electric, Water | Flying) => Strong,
|
||||||
(Electric, _) => Neutral,
|
|
||||||
(Grass, Fire | Grass | Poison | Flying | Bug | Dragon | Steel) => Weak,
|
(Grass, Fire | Grass | Poison | Flying | Bug | Dragon | Steel) => Weak,
|
||||||
(Grass, Water | Ground | Rock) => Strong,
|
(Grass, Water | Ground | Rock) => Strong,
|
||||||
(Grass, _) => Neutral,
|
|
||||||
(Ice, Fire | Water | Ice | Steel) => Weak,
|
(Ice, Fire | Water | Ice | Steel) => Weak,
|
||||||
(Ice, Grass | Ground | Flying | Dragon) => Strong,
|
(Ice, Grass | Ground | Flying | Dragon) => Strong,
|
||||||
(Ice, _) => Neutral,
|
(Fighting, Ghost) => Zero,
|
||||||
(Fighting, Ghost) => Immune,
|
|
||||||
(Fighting, Poison | Flying | Psychic | Bug | Fairy) => Weak,
|
(Fighting, Poison | Flying | Psychic | Bug | Fairy) => Weak,
|
||||||
(Fighting, Normal | Ice | Rock | Dark | Steel) => Strong,
|
(Fighting, Normal | Ice | Rock | Dark | Steel) => Strong,
|
||||||
(Fighting, _) => Neutral,
|
(Poison, Steel) => Zero,
|
||||||
(Poison, Steel) => Immune,
|
|
||||||
(Poison, Poison | Ground | Rock | Ghost) => Weak,
|
(Poison, Poison | Ground | Rock | Ghost) => Weak,
|
||||||
(Poison, Grass | Fairy) => Strong,
|
(Poison, Grass | Fairy) => Strong,
|
||||||
(Poison, _) => Neutral,
|
(Ground, Flying) => Zero,
|
||||||
(Ground, Flying) => Immune,
|
|
||||||
(Ground, Grass | Bug) => Weak,
|
(Ground, Grass | Bug) => Weak,
|
||||||
(Ground, Fire | Electric | Poison | Rock | Steel) => Strong,
|
(Ground, Fire | Electric | Poison | Rock | Steel) => Strong,
|
||||||
(Ground, _) => Neutral,
|
|
||||||
(Flying, Electric | Rock | Steel) => Weak,
|
(Flying, Electric | Rock | Steel) => Weak,
|
||||||
(Flying, Grass | Fighting | Bug) => Strong,
|
(Flying, Grass | Fighting | Bug) => Strong,
|
||||||
(Flying, _) => Neutral,
|
(Psychic, Dark) => Zero,
|
||||||
(Psychic, Dark) => Immune,
|
|
||||||
(Psychic, Psychic | Steel) => Weak,
|
(Psychic, Psychic | Steel) => Weak,
|
||||||
(Psychic, Fighting | Poison) => Strong,
|
(Psychic, Fighting | Poison) => Strong,
|
||||||
(Psychic, _) => Neutral,
|
|
||||||
(Bug, Fire | Fighting | Poison | Flying | Ghost | Steel | Fairy) => Weak,
|
(Bug, Fire | Fighting | Poison | Flying | Ghost | Steel | Fairy) => Weak,
|
||||||
(Bug, Grass | Psychic | Dark) => Strong,
|
(Bug, Grass | Psychic | Dark) => Strong,
|
||||||
(Bug, _) => Neutral,
|
|
||||||
(Rock, Fighting | Ground | Steel) => Weak,
|
(Rock, Fighting | Ground | Steel) => Weak,
|
||||||
(Rock, Fire | Ice | Flying | Bug) => Strong,
|
(Rock, Fire | Ice | Flying | Bug) => Strong,
|
||||||
(Rock, _) => Neutral,
|
(Ghost, Normal) => Zero,
|
||||||
(Ghost, Normal) => Immune,
|
|
||||||
(Ghost, Dark) => Weak,
|
(Ghost, Dark) => Weak,
|
||||||
(Ghost, Psychic | Ghost) => Strong,
|
(Ghost, Psychic | Ghost) => Strong,
|
||||||
(Ghost, _) => Neutral,
|
(Dragon, Fairy) => Zero,
|
||||||
(Dragon, Fairy) => Immune,
|
|
||||||
(Dragon, Steel) => Weak,
|
(Dragon, Steel) => Weak,
|
||||||
(Dragon, Dragon) => Strong,
|
(Dragon, Dragon) => Strong,
|
||||||
(Dragon, _) => Neutral,
|
|
||||||
(Dark, Fighting | Dark | Fairy) => Weak,
|
(Dark, Fighting | Dark | Fairy) => Weak,
|
||||||
(Dark, Psychic | Ghost) => Strong,
|
(Dark, Psychic | Ghost) => Strong,
|
||||||
(Dark, _) => Neutral,
|
|
||||||
(Steel, Fire | Water | Electric | Steel) => Weak,
|
(Steel, Fire | Water | Electric | Steel) => Weak,
|
||||||
(Steel, Ice | Rock | Fairy) => Strong,
|
(Steel, Ice | Rock | Fairy) => Strong,
|
||||||
(Steel, _) => Neutral,
|
|
||||||
(Fairy, Fire | Poison | Steel) => Weak,
|
(Fairy, Fire | Poison | Steel) => Weak,
|
||||||
(Fairy, Fighting | Dragon | Dark) => Strong,
|
(Fairy, Fighting | Dragon | Dark) => Strong,
|
||||||
(Fairy, _) => Neutral,
|
(_, _) => Neutral,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue