From ee66365d18db06607bf4f8b64d908ab5eaca98b2 Mon Sep 17 00:00:00 2001 From: Toby Date: Sun, 16 Feb 2025 16:46:44 +0100 Subject: [PATCH] wip 1 --- Cargo.lock | 118 ++++++++---------------- Cargo.toml | 3 +- src/data/mod.rs | 82 ++++++++++++++++- src/data/pokemon_db.json | 20 ++++- src/main.rs | 9 +- src/pokemon.rs | 48 ++++------ src/trainer.rs | 2 +- src/types.rs | 190 +++++++++++++++++---------------------- src/utils.rs | 5 +- 9 files changed, 242 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d655b09..36cd1bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,55 +3,30 @@ version = 4 [[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.2.15" +name = "itoa" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] -name = "libc" -version = "0.2.169" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "pokemon" version = "0.1.0" dependencies = [ - "rand", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", + "serde", + "serde_json", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -66,40 +41,48 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.8.5" +name = "ryu" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ - "libc", - "rand_chacha", - "rand_core", + "serde_derive", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "serde_derive" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ - "ppv-lite86", - "rand_core", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "serde_json" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ - "getrandom", + "itoa", + "memchr", + "ryu", + "serde", ] [[package]] name = "syn" -version = "2.0.94" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -108,33 +91,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" diff --git a/Cargo.toml b/Cargo.toml index 7b08663..5ae1387 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.5" +serde = { version = "1.0.217", features = ["derive"] } +serde_json = "1.0.135" diff --git a/src/data/mod.rs b/src/data/mod.rs index 61686cb..3757ca2 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -3,18 +3,68 @@ use crate::types::PokemonType; use crate::moves::{Move, MoveCategory}; -fn load_pokemon_db() { - todo!(); +#[non_exhaustive] +enum EvolutionItem { + FireStone, + WaterStone, + ThunderStone, +} + +enum EvolutionCondition { + Level(u8), + Item(EvolutionItem), +} + +struct EvolutionPath { + evolves_to: SpeciesId, + condition: EvolutionCondition, +} + +pub struct SpeciesId(u16); + +pub struct Species { + species_id: SpeciesId, + base_stats: Stats, + types: Vec, + learnset: Vec<(u8, Move)>, + evolutions: Vec, +} + +impl Species { + pub fn new( + species_id: SpeciesId, + base_stats: Stats, + types: Vec, + learnset: Vec<(u8, Move)>, + evolutions: Vec, + ) -> Self { + Self { + species_id, + base_stats, + types, + learnset, + evolutions, + } + } +} + +pub fn load_pokemon_db() -> String { + let data = std::fs::read_to_string("./src/data/pokemon_db.json") + .expect("Unable to read Pokemon database"); + // let pokemon_db: HashMap = + + data } pub fn get_pokemon(species: &str) -> Pokemon { let types: Vec; let stats: Stats; let moves: Vec; + let evolutions: Vec; + let learnset: Vec<(u8, &str)>; match species { "Bulbasaur" => { - types = vec![PokemonType::Grass]; stats = Stats { max_hp: 45, attack: 49, @@ -23,11 +73,15 @@ pub fn get_pokemon(species: &str) -> Pokemon { special_defense: 65, speed: 45, }; + types = vec![PokemonType::Grass]; moves = vec![get_move("Tackle"), get_move("Vine Whip")]; + evolutions = vec![EvolutionPath { + evolves_to: SpeciesId(2), // Ivysaur + condition: EvolutionCondition::Level(16), + }]; } "Pikachu" => { - types = vec![PokemonType::Electric]; stats = Stats { max_hp: 35, attack: 55, @@ -36,7 +90,27 @@ pub fn get_pokemon(species: &str) -> Pokemon { special_defense: 40, speed: 90, }; + types = vec![PokemonType::Electric]; moves = vec![get_move("Tackle"), get_move("Thunderbolt")]; + evolutions = vec![EvolutionPath { + evolves_to: SpeciesId(26), // Raichu + condition: EvolutionCondition::Item(EvolutionItem::ThunderStone), + }]; + learnset = vec![ + (1, "Thunder Shock"), + (1, "Growl"), + (5, "Tail Whip"), + (10, "Thunder Wave"), + (13, "Quick Attack"), + (18, "Double Team"), + (21, "Slam"), + (26, "Thunderbolt"), + (29, "Feint"), + (34, "Agility"), + (35, "Discharge"), + (42, "Light Screen"), + (45, "Thunder"), + ]; } _ => unimplemented!("The Pokemon '{}' is not implemented.", species), diff --git a/src/data/pokemon_db.json b/src/data/pokemon_db.json index 2f21601..f725254 100644 --- a/src/data/pokemon_db.json +++ b/src/data/pokemon_db.json @@ -10,10 +10,22 @@ "types": [ "Grass" ], - "moves": [ - "Vine Whip", - "Tackle" - ], + "moves": { + "level_up": [ + { + "level": 1, + "move": "Tackle" + }, + { + "level": 1, + "move": "Growl" + }, + { + "level": 3, + "move": "Vine Whip" + } + ] + }, "evolves_to": { "pokemon": "Ivysaur", "level_required": 16 diff --git a/src/main.rs b/src/main.rs index a6c6814..d4697d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, unused)] +// #![allow(dead_code, unused)] // mod battle; mod constants; @@ -21,8 +21,9 @@ fn main() { leaf.add_pokemon(get_pokemon("Bulbasaur")); red.add_pokemon(get_pokemon("Pikachu")); - dbg!(leaf); - dbg!(red); + println!("{:?}", leaf); - // start_battle(&mut leaf, &mut red); + // let db = data::load_pokemon_db(); + + // println!("{db}"); } diff --git a/src/pokemon.rs b/src/pokemon.rs index 60058a6..1d6e13b 100644 --- a/src/pokemon.rs +++ b/src/pokemon.rs @@ -1,5 +1,4 @@ use crate::constants::{POKEMON_MAX_MOVES, POKEMON_MAX_TYPES}; -use std::default; use crate::moves::Move; use crate::types::PokemonType; @@ -10,39 +9,23 @@ use crate::types::PokemonType; #[derive(Debug)] #[non_exhaustive] -pub enum StatusCondition { - Paralyzed, -} +pub enum StatusCondition {} -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Stats { - pub max_hp: u32, - pub attack: u32, - pub defense: u32, - pub special_attack: u32, - pub special_defense: u32, - pub speed: u32, -} - -impl Default for Stats { - fn default() -> Self { - Self { - max_hp: 10, - attack: 10, - defense: 10, - special_attack: 10, - special_defense: 10, - speed: 10, - } - } + pub max_hp: u16, + pub attack: u16, + pub defense: u16, + pub special_attack: u16, + pub special_defense: u16, + pub speed: u16, } #[derive(Debug)] pub struct Pokemon { - pub name: String, species: String, level: u8, - hp: u32, + hp: u16, stats: Stats, types: Vec, moves: Vec, @@ -50,8 +33,8 @@ pub struct Pokemon { } impl Pokemon { - pub fn new(species: &str) -> Pokemon { - Self::builder(species).build() + pub fn new(species_name: &str) -> Pokemon { + Self::builder(species_name).build() } pub fn builder(species: &str) -> PokemonBuilder { @@ -68,6 +51,10 @@ impl Pokemon { todo!() } + pub fn name(&self) -> &str { + &self.species + } + pub fn level_up(&mut self) { todo!() } @@ -76,7 +63,7 @@ impl Pokemon { self.hp == 0 } - pub fn heal(&mut self, amount: u32) { + pub fn heal(&mut self, amount: u16) { self.hp = (self.hp + amount).min(self.stats.max_hp); } @@ -84,7 +71,7 @@ impl Pokemon { self.hp = self.stats.max_hp; } - pub fn take_damage(&mut self, amount: u32) { + pub fn take_damage(&mut self, amount: u16) { self.hp = self.hp.saturating_sub(amount); } } @@ -134,7 +121,6 @@ impl PokemonBuilder { pub fn build(self) -> Pokemon { Pokemon { - name: self.species.clone(), species: self.species, level: self.level, hp: self.stats.max_hp, diff --git a/src/trainer.rs b/src/trainer.rs index ae48699..e2e7396 100644 --- a/src/trainer.rs +++ b/src/trainer.rs @@ -32,7 +32,7 @@ impl Party { pub fn add(&mut self, pokemon: Pokemon) -> Result<(), String> { if self.is_full() { - Err(format!("Team is full! Cannot add {}.", pokemon.name)) + Err(format!("Team is full! Cannot add {}.", pokemon.name())) } else { self.members.push(pokemon); Ok(()) diff --git a/src/types.rs b/src/types.rs index 86cc994..8284e1c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,10 @@ -// Source: [Generations II-V](https://bulbapedia.bulbagarden.net/wiki/Type/Type_chart) +use Effectiveness::*; +use PokemonType::*; + +// Source: [Generations VI](https://bulbapedia.bulbagarden.net/wiki/Type/Type_chart) +#[rustfmt::skip] const TYPE_TABLE: [[u8; 17]; 17] = [ - // Fi Fl Po Gd Ro Bg Gh St Fi Wa Gs El Ps Ic Dr Da +// No Fi Fl Po Gd Ro Bg Gh St Fi Wa Gs El Ps Ic Dr Da [2, 2, 2, 2, 2, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2], // Normal [4, 2, 1, 1, 2, 4, 1, 0, 4, 2, 2, 2, 2, 1, 4, 2, 4], // Fighting [2, 4, 2, 2, 2, 1, 4, 2, 1, 2, 2, 4, 1, 2, 2, 2, 2], // Flying @@ -51,82 +55,76 @@ pub enum PokemonType { Dark, } -impl PokemonType { - fn _get_effectiveness(attacker: PokemonType, defender: PokemonType) -> Effectiveness { - use Effectiveness::*; - use PokemonType::*; - match (attacker, defender) { - (Normal, Rock) => NotVeryEffective, - (Normal, Rock) => NotVeryEffective, - (Normal, Ghost) => NoEffect, - (Normal, Steel) => NotVeryEffective, - - (Fighting, Normal) => SuperEffective, - (Fighting, Flying) => NotVeryEffective, - (Fighting, Poison) => NotVeryEffective, - (Fighting, Rock) => SuperEffective, - (Fighting, Ghost) => NoEffect, - (Fighting, Steel) => SuperEffective, - (Fighting, Psychic) => NotVeryEffective, - (Fighting, Ice) => SuperEffective, - (Fighting, Dark) => SuperEffective, - - (Flying, Fighting) => SuperEffective, - (Flying, Rock) => NotVeryEffective, - (Flying, Bug) => SuperEffective, - (Flying, Steel) => NotVeryEffective, - (Flying, Grass) => SuperEffective, - (Flying, Electric) => NotVeryEffective, - - (Poison, Poison) => NotVeryEffective, - (Poison, Ground) => NotVeryEffective, - (Poison, Rock) => NotVeryEffective, - (Poison, Ghost) => NotVeryEffective, - (Poison, Steel) => NoEffect, - (Poison, Grass) => SuperEffective, - - (Ground, Flying) => NoEffect, - (Ground, Poison) => SuperEffective, - (Ground, Rock) => SuperEffective, - (Ground, Bug) => NotVeryEffective, - (Ground, Steel) => SuperEffective, - (Ground, Fire) => SuperEffective, - (Ground, Grass) => NotVeryEffective, - (Ground, Electric) => SuperEffective, - - (Fire, Grass) => SuperEffective, - (Water, Grass) => NotVeryEffective, - - (Grass, Flying) => NotVeryEffective, - (Grass, Poison) => NotVeryEffective, - (Grass, Ground) => SuperEffective, - (Grass, Rock) => SuperEffective, - (Grass, Bug) => NotVeryEffective, - (Grass, Fire) => NotVeryEffective, - (Grass, Water) => SuperEffective, - (Grass, Grass) => NotVeryEffective, - (Grass, Dragon) => NotVeryEffective, - - (Electric, Flying) => SuperEffective, - (Electric, Ground) => NoEffect, - (Electric, Water) => SuperEffective, - (Electric, Grass) => NotVeryEffective, - (Electric, Electric) => NotVeryEffective, - (Electric, Dragon) => NotVeryEffective, - - _ => Neutral, - } +fn _get_effectiveness(attacker: PokemonType, defender: PokemonType) -> Effectiveness { + match (attacker, defender) { + (Normal, Rock) => NotVeryEffective, + (Normal, Ghost) => NoEffect, + (Normal, Steel) => NotVeryEffective, + + (Fighting, Normal) => SuperEffective, + (Fighting, Flying) => NotVeryEffective, + (Fighting, Poison) => NotVeryEffective, + (Fighting, Rock) => SuperEffective, + (Fighting, Ghost) => NoEffect, + (Fighting, Steel) => SuperEffective, + (Fighting, Psychic) => NotVeryEffective, + (Fighting, Ice) => SuperEffective, + (Fighting, Dark) => SuperEffective, + + (Flying, Fighting) => SuperEffective, + (Flying, Rock) => NotVeryEffective, + (Flying, Bug) => SuperEffective, + (Flying, Steel) => NotVeryEffective, + (Flying, Grass) => SuperEffective, + (Flying, Electric) => NotVeryEffective, + + (Poison, Poison) => NotVeryEffective, + (Poison, Ground) => NotVeryEffective, + (Poison, Rock) => NotVeryEffective, + (Poison, Ghost) => NotVeryEffective, + (Poison, Steel) => NoEffect, + (Poison, Grass) => SuperEffective, + + (Ground, Flying) => NoEffect, + (Ground, Poison) => SuperEffective, + (Ground, Rock) => SuperEffective, + (Ground, Bug) => NotVeryEffective, + (Ground, Steel) => SuperEffective, + (Ground, Fire) => SuperEffective, + (Ground, Grass) => NotVeryEffective, + (Ground, Electric) => SuperEffective, + + (Fire, Grass) => SuperEffective, + (Water, Grass) => NotVeryEffective, + + (Grass, Flying) => NotVeryEffective, + (Grass, Poison) => NotVeryEffective, + (Grass, Ground) => SuperEffective, + (Grass, Rock) => SuperEffective, + (Grass, Bug) => NotVeryEffective, + (Grass, Fire) => NotVeryEffective, + (Grass, Water) => SuperEffective, + (Grass, Grass) => NotVeryEffective, + (Grass, Dragon) => NotVeryEffective, + + (Electric, Flying) => SuperEffective, + (Electric, Ground) => NoEffect, + (Electric, Water) => SuperEffective, + (Electric, Grass) => NotVeryEffective, + (Electric, Electric) => NotVeryEffective, + (Electric, Dragon) => NotVeryEffective, + + _ => Neutral, } +} - pub fn get_effectiveness(attacker: PokemonType, defender: PokemonType) -> Effectiveness { - use Effectiveness::*; - match TYPE_TABLE[attacker as usize][defender as usize] { - 0 => NoEffect, - 1 => NotVeryEffective, - 2 => Neutral, - 4 => SuperEffective, - _ => unreachable!(), - } +pub fn get_effectiveness(attacker: PokemonType, defender: PokemonType) -> Effectiveness { + match TYPE_TABLE[attacker as usize][defender as usize] { + 0 => NoEffect, + 1 => NotVeryEffective, + 2 => Neutral, + 4 => SuperEffective, + _ => unreachable!(), } } @@ -136,41 +134,17 @@ mod tests { #[test] fn test_type_table() { - assert_eq!( - PokemonType::get_effectiveness(PokemonType::Fire, PokemonType::Grass), - Effectiveness::SuperEffective - ); - assert_eq!( - PokemonType::get_effectiveness(PokemonType::Water, PokemonType::Grass), - Effectiveness::NotVeryEffective - ); - assert_eq!( - PokemonType::get_effectiveness(PokemonType::Fighting, PokemonType::Ghost), - Effectiveness::NoEffect - ); - assert_eq!( - PokemonType::get_effectiveness(PokemonType::Normal, PokemonType::Normal), - Effectiveness::Neutral - ); + assert_eq!(get_effectiveness(Fire, Grass), SuperEffective); + assert_eq!(get_effectiveness(Water, Grass), NotVeryEffective); + assert_eq!(get_effectiveness(Fighting, Ghost), NoEffect); + assert_eq!(get_effectiveness(Normal, Normal), Neutral); } #[test] fn test_get_effectiveness_by_match() { - assert_eq!( - PokemonType::_get_effectiveness(PokemonType::Fire, PokemonType::Grass), - Effectiveness::SuperEffective - ); - assert_eq!( - PokemonType::_get_effectiveness(PokemonType::Water, PokemonType::Grass), - Effectiveness::NotVeryEffective - ); - assert_eq!( - PokemonType::_get_effectiveness(PokemonType::Fighting, PokemonType::Ghost), - Effectiveness::NoEffect - ); - assert_eq!( - PokemonType::_get_effectiveness(PokemonType::Normal, PokemonType::Normal), - Effectiveness::Neutral - ); + assert_eq!(_get_effectiveness(Fire, Grass), SuperEffective); + assert_eq!(_get_effectiveness(Water, Grass), NotVeryEffective); + assert_eq!(_get_effectiveness(Fighting, Ghost), NoEffect); + assert_eq!(_get_effectiveness(Normal, Normal), Neutral); } } diff --git a/src/utils.rs b/src/utils.rs index 09ed505..bb37b7f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,10 @@ use crate::Pokemon; pub fn print_party_members(members: &[Pokemon]) { - let names: Vec = members.iter().map(|pokemon| pokemon.name.clone()).collect(); + let names: Vec = members + .iter() + .map(|pokemon| pokemon.name().to_string()) + .collect(); let s = format!("[ {} ]", names.join(", ")); println!("{}", s); }