~jacqueline/pokemon

578ff1d30ed64de1dd785914b78bc95dfec0c166 — jacqueline leykam 1 year, 12 days ago 25bf8e5 prof-oak
Format files
2 files changed, 376 insertions(+), 159 deletions(-)

M src/lib.rs
M src/main.rs
M src/lib.rs => src/lib.rs +257 -133
@@ 1,80 1,123 @@
#![no_std]

pub mod pokedex {
    use minicbor::{Encode, Decode, bytes::ByteArray};
    
    use minicbor::{bytes::ByteArray, Decode, Encode};

    #[derive(Encode, Decode, Debug)]
    pub struct Pokemon {
        #[n(0)] pub species_id: u8,
        #[n(1)] pub nickname: Option<[u8; 12]>,

        #[n(2)] pub level: u8,
        #[n(3)] pub xp: u16,
        #[n(5)] pub current_hp: u16,

        #[n(6)] pub hp: StatData,
        #[n(7)] pub attack: StatData,
        #[n(8)] pub defense: StatData,
        #[n(9)] pub special_attack: StatData,
        #[n(10)] pub special_defense: StatData,
        #[n(11)] pub speed: StatData,

        #[n(12)] pub moves: [Option<u16>; 4],
        #[n(0)]
        pub species_id: u8,
        #[n(1)]
        pub nickname: Option<[u8; 12]>,

        #[n(2)]
        pub level: u8,
        #[n(3)]
        pub xp: u16,
        #[n(5)]
        pub current_hp: u16,

        #[n(6)]
        pub hp: StatData,
        #[n(7)]
        pub attack: StatData,
        #[n(8)]
        pub defense: StatData,
        #[n(9)]
        pub special_attack: StatData,
        #[n(10)]
        pub special_defense: StatData,
        #[n(11)]
        pub speed: StatData,

        #[n(12)]
        pub moves: [Option<u16>; 4],
    }

    #[derive(Encode, Decode, Debug, Clone, Copy)]
    pub struct StatData {
        #[n(0)] pub value: u16,
        #[n(2)] pub effort_value: u16,
        #[n(3)] pub individual_value: u8,
        #[n(0)]
        pub value: u16,
        #[n(2)]
        pub effort_value: u16,
        #[n(3)]
        pub individual_value: u8,
    }

    #[derive(Encode, Decode, Debug)]
    pub struct PokemonSpecies {
        #[n(0)] pub id: u8,
        #[n(1)] pub name: [u8; 12],
        #[n(2)] pub type_primary: Type,
        #[n(3)] pub type_secondary: Option<Type>,
        #[n(14)] pub growth_rate: GrowthRate,

        #[n(4)] pub capture_rate: u8,
        #[n(5)] pub base_experience: u8,

        #[n(7)] pub hp: SpeciesStatData,
        #[n(8)] pub attack: SpeciesStatData,
        #[n(9)] pub defense: SpeciesStatData,
        #[n(10)] pub special_attack: SpeciesStatData,
        #[n(11)] pub special_defense: SpeciesStatData,
        #[n(12)] pub speed: SpeciesStatData,

        #[n(13)] pub sprite: ByteArray<578>,
        #[n(0)]
        pub id: u8,
        #[n(1)]
        pub name: [u8; 12],
        #[n(2)]
        pub type_primary: Type,
        #[n(3)]
        pub type_secondary: Option<Type>,
        #[n(14)]
        pub growth_rate: GrowthRate,

        #[n(4)]
        pub capture_rate: u8,
        #[n(5)]
        pub base_experience: u8,

        #[n(7)]
        pub hp: SpeciesStatData,
        #[n(8)]
        pub attack: SpeciesStatData,
        #[n(9)]
        pub defense: SpeciesStatData,
        #[n(10)]
        pub special_attack: SpeciesStatData,
        #[n(11)]
        pub special_defense: SpeciesStatData,
        #[n(12)]
        pub speed: SpeciesStatData,

        #[n(13)]
        pub sprite: ByteArray<578>,
    }

    #[derive(Encode, Decode, Debug)]
    #[cbor(index_only)]
    pub enum Stats {
        #[n(0)] Hp,
        #[n(1)] Attack,
        #[n(2)] Defense,
        #[n(3)] SpecialAttack,
        #[n(4)] SpecialDefense,
        #[n(5)] Speed,
        #[n(0)]
        Hp,
        #[n(1)]
        Attack,
        #[n(2)]
        Defense,
        #[n(3)]
        SpecialAttack,
        #[n(4)]
        SpecialDefense,
        #[n(5)]
        Speed,
    }

    #[derive(Encode, Decode, Debug, Clone, Copy)]
    pub struct SpeciesStatData {
        #[n(0)] pub base_value: u16,
        #[n(1)] pub effort_value_yield: u8,
        #[n(0)]
        pub base_value: u16,
        #[n(1)]
        pub effort_value_yield: u8,
    }

    #[derive(Encode, Decode, Debug, Clone, Copy)]
    pub enum GrowthRate {
        #[n(0)] ERRATIC,
        #[n(1)] FAST,
        #[n(2)] MEDIUM_FAST,
        #[n(3)] MEDIUM_SLOW,
        #[n(4)] SLOW,
        #[n(5)] FLUCTUATING
        #[n(0)]
        ERRATIC,
        #[n(1)]
        FAST,
        #[n(2)]
        MEDIUM_FAST,
        #[n(3)]
        MEDIUM_SLOW,
        #[n(4)]
        SLOW,
        #[n(5)]
        FLUCTUATING,
    }

    impl GrowthRate {


@@ 95,24 138,42 @@ pub mod pokedex {
    #[derive(Encode, Decode, Debug, Clone, Copy)]
    #[cbor(index_only)]
    pub enum Type {
        #[n(0)] Normal,
        #[n(1)] Fighting,
        #[n(2)] Flying,
        #[n(3)] Poison,
        #[n(4)] Ground,
        #[n(5)] Rock,
        #[n(6)] Bug,
        #[n(7)] Ghost,
        #[n(8)] Steel,
        #[n(9)] Fire,
        #[n(10)] Water,
        #[n(11)] Grass,
        #[n(12)] Electric,
        #[n(13)] Psychic,
        #[n(14)] Ice,
        #[n(15)] Dragon,
        #[n(16)] Dark,
        #[n(17)] Fairy,
        #[n(0)]
        Normal,
        #[n(1)]
        Fighting,
        #[n(2)]
        Flying,
        #[n(3)]
        Poison,
        #[n(4)]
        Ground,
        #[n(5)]
        Rock,
        #[n(6)]
        Bug,
        #[n(7)]
        Ghost,
        #[n(8)]
        Steel,
        #[n(9)]
        Fire,
        #[n(10)]
        Water,
        #[n(11)]
        Grass,
        #[n(12)]
        Electric,
        #[n(13)]
        Psychic,
        #[n(14)]
        Ice,
        #[n(15)]
        Dragon,
        #[n(16)]
        Dark,
        #[n(17)]
        Fairy,
    }

    impl Type {


@@ 135,116 196,170 @@ pub mod pokedex {
                Type::Ice => "ICE",
                Type::Dragon => "DRAGON",
                Type::Dark => "DARK",
                Type::Fairy => "FAIRY"
                Type::Fairy => "FAIRY",
            }
        }
    }

    #[derive(Encode, Decode, Debug)]
    pub struct MoveListChunk {
        #[n(0)] pub is_final_chunk: bool,
        #[n(1)] pub moves: [Option<LearnableMove>; 16],
        #[n(0)]
        pub is_final_chunk: bool,
        #[n(1)]
        pub moves: [Option<LearnableMove>; 16],
    }

    #[derive(Encode, Decode, Debug, Copy, Clone)]
    pub struct LearnableMove {
        #[n(0)] pub id: u16,
        #[n(1)] pub condition: LearnCondition,
        #[n(0)]
        pub id: u16,
        #[n(1)]
        pub condition: LearnCondition,
    }

    #[derive(Encode, Decode, Debug, Copy, Clone)]
    pub enum LearnCondition {
        #[n(0)] LevelUp(#[n(0)] u8),
        #[n(1)] Machine,
        #[n(0)]
        LevelUp(#[n(0)] u8),
        #[n(1)]
        Machine,
    }

    #[derive(Encode, Decode, Debug)]
    pub struct Move {
        #[n(0)] pub id: u16,
        #[n(1)] pub name: [u8; 12],

        #[n(2)] pub type_: Type,
        #[n(3)] pub damage_class: DamageClass,
        #[n(4)] pub target: Target,

        #[n(5)] pub accuracy: u8,
        #[n(6)] pub power: u8,
        #[n(7)] pub pp: u8,
        #[n(8)] pub priority: u8,

        #[n(9)] pub parameters: Parameters,
        #[n(10)] pub stat_changes: [Option<StatChange>; 2]
        #[n(0)]
        pub id: u16,
        #[n(1)]
        pub name: [u8; 12],

        #[n(2)]
        pub type_: Type,
        #[n(3)]
        pub damage_class: DamageClass,
        #[n(4)]
        pub target: Target,

        #[n(5)]
        pub accuracy: u8,
        #[n(6)]
        pub power: u8,
        #[n(7)]
        pub pp: u8,
        #[n(8)]
        pub priority: u8,

        #[n(9)]
        pub parameters: Parameters,
        #[n(10)]
        pub stat_changes: [Option<StatChange>; 2],
    }

    #[derive(Encode, Decode, Debug)]
    #[cbor(map)]
    pub struct Parameters {
        #[n(0)] pub ailment: Option<AilmentParameter>,
        #[n(1)] pub crit_rate: u8,
        #[n(2)] pub drain: u8,
        #[n(3)] pub flinch_chance: u8,
        #[n(4)] pub healing: u8,
        #[n(5)] pub stat_chance: u8,
        #[n(6)] pub turn_range: Option<ParameterRange>,
        #[n(7)] pub hit_range: Option<ParameterRange>,
        #[n(0)]
        pub ailment: Option<AilmentParameter>,
        #[n(1)]
        pub crit_rate: u8,
        #[n(2)]
        pub drain: u8,
        #[n(3)]
        pub flinch_chance: u8,
        #[n(4)]
        pub healing: u8,
        #[n(5)]
        pub stat_chance: u8,
        #[n(6)]
        pub turn_range: Option<ParameterRange>,
        #[n(7)]
        pub hit_range: Option<ParameterRange>,
    }

    #[derive(Encode, Decode, Debug)]
    pub struct AilmentParameter {
        #[n(0)] pub ailment: AilmentType,
        #[n(1)] pub chance: u8,
        #[n(0)]
        pub ailment: AilmentType,
        #[n(1)]
        pub chance: u8,
    }

    #[derive(Encode, Decode, Debug)]
    #[cbor(index_only)]
    pub enum AilmentType {
        #[n(0)] Burn,
        #[n(1)] Confusion,
        #[n(2)] Disable,
        #[n(3)] Freeze,
        #[n(4)] LeechSeed,
        #[n(5)] Paralysis,
        #[n(6)] Poison,
        #[n(7)] Sleep,
        #[n(8)] Trap,
        #[n(0)]
        Burn,
        #[n(1)]
        Confusion,
        #[n(2)]
        Disable,
        #[n(3)]
        Freeze,
        #[n(4)]
        LeechSeed,
        #[n(5)]
        Paralysis,
        #[n(6)]
        Poison,
        #[n(7)]
        Sleep,
        #[n(8)]
        Trap,
    }

    #[derive(Encode, Decode, Debug)]
    pub struct ParameterRange {
        #[n(0)] pub min: u8,
        #[n(1)] pub max: u8,
        #[n(0)]
        pub min: u8,
        #[n(1)]
        pub max: u8,
    }

    #[derive(Encode, Decode, Debug)]
    #[cbor(index_only)]
    pub enum DamageClass {
        #[n(0)] Physical,
        #[n(1)] Special,
        #[n(2)] Status,
        #[n(0)]
        Physical,
        #[n(1)]
        Special,
        #[n(2)]
        Status,
    }

    #[derive(Encode, Decode, Debug)]
    #[cbor(index_only)]
    pub enum Target {
        #[n(0)] AllOpponents,
        #[n(1)] AllOtherPokemon,
        #[n(2)] EntireField,
        #[n(3)] RandomOpponent,
        #[n(4)] SelectedPokemon,
        #[n(5)] SpecificMove,
        #[n(6)] User,
        #[n(7)] UserField,
        #[n(0)]
        AllOpponents,
        #[n(1)]
        AllOtherPokemon,
        #[n(2)]
        EntireField,
        #[n(3)]
        RandomOpponent,
        #[n(4)]
        SelectedPokemon,
        #[n(5)]
        SpecificMove,
        #[n(6)]
        User,
        #[n(7)]
        UserField,
    }

    #[derive(Encode, Decode, Debug)]
    pub struct StatChange {
        #[n(0)] pub amount: u8,
        #[n(1)] pub stat: Stats,
        #[n(0)]
        pub amount: u8,
        #[n(1)]
        pub stat: Stats,
    }
}

pub mod generation {
    use crate::pokedex::{Pokemon, PokemonSpecies, StatData, SpeciesStatData, StatChange, LearnableMove, LearnCondition};
    use crate::pokedex::{
        LearnCondition, LearnableMove, Pokemon, PokemonSpecies, SpeciesStatData, StatChange,
        StatData,
    };

    trait Random {
        fn random(&self) -> u8;


@@ 254,7 369,12 @@ pub mod generation {
        }
    }

    pub fn generate_pokemon(species: PokemonSpecies, move_list: &mut dyn Iterator<Item = &LearnableMove>, level: u8, rng: &dyn Random) -> Pokemon {
    pub fn generate_pokemon(
        species: PokemonSpecies,
        move_list: &mut dyn Iterator<Item = &LearnableMove>,
        level: u8,
        rng: &dyn Random,
    ) -> Pokemon {
        let mut moves = [None; 4];
        let mut i = 0;
        for m in move_list {


@@ 271,9 391,9 @@ pub mod generation {
        let hp = StatData {
            value: calculate_hp_stat(species.hp.base_value, 0, hp_iv, level),
            effort_value: 0,
            individual_value: hp_iv
            individual_value: hp_iv,
        };
        return Pokemon{
        return Pokemon {
            species_id: species.id,
            nickname: None,
            level,


@@ 285,20 405,24 @@ pub mod generation {
            special_attack: new_stat(species.special_attack, level, rng),
            special_defense: new_stat(species.special_defense, level, rng),
            speed: new_stat(species.speed, level, rng),
            moves
        }
            moves,
        };
    }

    fn new_stat(stat: SpeciesStatData, level: u8, rng: &dyn Random) -> StatData {
        let iv = rng.generate_iv();
        return StatData { value: calculate_stat(stat.base_value, 0, iv, level), effort_value: 0, individual_value: iv }
        return StatData {
            value: calculate_stat(stat.base_value, 0, iv, level),
            effort_value: 0,
            individual_value: iv,
        };
    }

    fn calculate_stat(base: u16, ev: u16, iv: u8, level: u8) -> u16 {
        return (((2 * base) + (iv as u16) + ev) * (level as u16) / 100) + 5
        return (((2 * base) + (iv as u16) + ev) * (level as u16) / 100) + 5;
    }

    fn calculate_hp_stat(base: u16, ev: u16, iv: u8, level: u8) -> u16 {
        return (((2 * base) + (iv as u16) + ev) * (level as u16) / 100) + (level as u16) + 10
        return (((2 * base) + (iv as u16) + ev) * (level as u16) / 100) + (level as u16) + 10;
    }
}

M src/main.rs => src/main.rs +119 -26
@@ 4,11 4,11 @@
extern crate nb;

use bitbang_hal;
use embedded_graphics::{egrectangle, egtext, egline};
use embedded_graphics::fonts::Text;
use embedded_graphics::image::Image;
use embedded_graphics::primitives::Rectangle;
use embedded_graphics::style::{PrimitiveStyleBuilder, TextStyleBuilder};
use embedded_graphics::{egline, egrectangle, egtext};
use embedded_graphics::{pixelcolor::BinaryColor, prelude::*};
use embedded_picofont::FontPico;
use esp8266_hal::ehal::digital::v2::InputPin;


@@ 187,7 187,13 @@ fn main() -> ! {

        if !has_drawn {
            has_drawn = true;
            egrectangle!(top_left = (0, 0), bottom_right = (128, 64), style = black_solid).draw(&mut display).ok();
            egrectangle!(
                top_left = (0, 0),
                bottom_right = (128, 64),
                style = black_solid
            )
            .draw(&mut display)
            .ok();

            let res = read_pokemon(pokemon_id, &mut storage);
            if res.is_err() {


@@ 205,29 211,116 @@ fn main() -> ! {
            }
            pokemon = res.unwrap();

            egrectangle!(top_left = (0, 0), bottom_right = (128, 6), style = white_solid).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&pokemon.name).unwrap(), top_left = (1, 1), style = black_text).draw(&mut display).ok();
            egline!(start = (57, 7), end = (57, 64), style = white_solid).draw(&mut display).ok();

            egtext!(text = pokemon.type_primary.name(), top_left = (58, 10), style = white_text).draw(&mut display).ok();
            pokemon.type_secondary.and_then(|t| egtext!(text = t.name(), top_left = (58, 16), style = white_text).draw(&mut display).ok());

            egtext!(text = "HP", top_left = (58, 28), style = white_text).draw(&mut display).ok();
            egtext!(text = "ATK", top_left = (58, 36), style = white_text).draw(&mut display).ok();
            egtext!(text = "DEF", top_left = (58, 44), style = white_text).draw(&mut display).ok();
            egtext!(text = "SPD", top_left = (93, 28), style = white_text).draw(&mut display).ok();
            egtext!(text = "SATK", top_left = (93, 36), style = white_text).draw(&mut display).ok();
            egtext!(text = "SDEF", top_left = (93, 44), style = white_text).draw(&mut display).ok();

            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.hp.base_value.into())).unwrap(), top_left = (75, 28), style = white_text).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.attack.base_value.into())).unwrap(), top_left = (75, 36), style = white_text).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.defense.base_value.into())).unwrap(), top_left = (75, 44), style = white_text).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.speed.base_value.into())).unwrap(), top_left = (113, 28), style = white_text).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.special_attack.base_value.into())).unwrap(), top_left = (113, 36), style = white_text).draw(&mut display).ok();
            egtext!(text = core::str::from_utf8(&num_to_str(pokemon.special_defense.base_value.into())).unwrap(), top_left = (113, 44), style = white_text).draw(&mut display).ok();

            egrectangle!(top_left = (56, 57), bottom_right = (128, 64), style = white_solid).draw(&mut display).ok();
            egtext!(text = "A:MOVES    B:BACK", top_left = (58, 58), style = black_text).draw(&mut display).ok();
            egrectangle!(
                top_left = (0, 0),
                bottom_right = (128, 6),
                style = white_solid
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = core::str::from_utf8(&pokemon.name).unwrap(),
                top_left = (1, 1),
                style = black_text
            )
            .draw(&mut display)
            .ok();
            egline!(start = (57, 7), end = (57, 64), style = white_solid)
                .draw(&mut display)
                .ok();

            egtext!(
                text = pokemon.type_primary.name(),
                top_left = (58, 10),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            pokemon.type_secondary.and_then(|t| {
                egtext!(text = t.name(), top_left = (58, 16), style = white_text)
                    .draw(&mut display)
                    .ok()
            });

            egtext!(text = "HP", top_left = (58, 28), style = white_text)
                .draw(&mut display)
                .ok();
            egtext!(text = "ATK", top_left = (58, 36), style = white_text)
                .draw(&mut display)
                .ok();
            egtext!(text = "DEF", top_left = (58, 44), style = white_text)
                .draw(&mut display)
                .ok();
            egtext!(text = "SPD", top_left = (93, 28), style = white_text)
                .draw(&mut display)
                .ok();
            egtext!(text = "SATK", top_left = (93, 36), style = white_text)
                .draw(&mut display)
                .ok();
            egtext!(text = "SDEF", top_left = (93, 44), style = white_text)
                .draw(&mut display)
                .ok();

            egtext!(
                text = core::str::from_utf8(&num_to_str(pokemon.hp.base_value.into())).unwrap(),
                top_left = (75, 28),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = core::str::from_utf8(&num_to_str(pokemon.attack.base_value.into())).unwrap(),
                top_left = (75, 36),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text =
                    core::str::from_utf8(&num_to_str(pokemon.defense.base_value.into())).unwrap(),
                top_left = (75, 44),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = core::str::from_utf8(&num_to_str(pokemon.speed.base_value.into())).unwrap(),
                top_left = (113, 28),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = core::str::from_utf8(&num_to_str(pokemon.special_attack.base_value.into()))
                    .unwrap(),
                top_left = (113, 36),
                style = white_text
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = core::str::from_utf8(&num_to_str(pokemon.special_defense.base_value.into()))
                    .unwrap(),
                top_left = (113, 44),
                style = white_text
            )
            .draw(&mut display)
            .ok();

            egrectangle!(
                top_left = (56, 57),
                bottom_right = (128, 64),
                style = white_solid
            )
            .draw(&mut display)
            .ok();
            egtext!(
                text = "A:MOVES    B:BACK",
                top_left = (58, 58),
                style = black_text
            )
            .draw(&mut display)
            .ok();

            let image = Bmp::from_slice(pokemon.sprite.as_ref()).unwrap();
            let mut real_image = Image::new(&image, Point::zero());


@@ 268,7 361,7 @@ fn num_to_str(mut num: u32) -> [u8; 3] {
        num %= base;
        base /= 10;
    }
    return buf
    return buf;
}

const DATA_OFFSET: u32 = 0x200000;