mirror of
https://github.com/LukasKalbertodt/programmieren-in-rust.git
synced 2025-08-16 10:58:52 +02:00
Rename sheet folders to assure proper sorting
This commit is contained in:
120
aufgaben/sheet05/sol1/src/engine/canon.rs
Executable file
120
aufgaben/sheet05/sol1/src/engine/canon.rs
Executable file
@@ -0,0 +1,120 @@
|
||||
use db::types::*;
|
||||
use super::Pokemon;
|
||||
|
||||
impl TypeEffectiveness {
|
||||
/// Returns the type effectiveness of an attack from one attacker type
|
||||
/// on one defender type.
|
||||
pub fn of_attack(attacker: Type, defender: Type) -> Self {
|
||||
use db::Type::*;
|
||||
use db::TypeEffectiveness as Te;
|
||||
|
||||
// TODO: complete this
|
||||
match (attacker, defender) {
|
||||
(Fire, Water) => Te::NotVeryEffective,
|
||||
(Fire, Grass) => Te::SuperEffective,
|
||||
(Water, Fire) => Te::SuperEffective,
|
||||
(Water, Grass) => Te::NotVeryEffective,
|
||||
(Grass, Fire) => Te::NotVeryEffective,
|
||||
(Grass, Water) => Te::SuperEffective,
|
||||
(Ground, Flying) => Te::NotEffective,
|
||||
_ => Te::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the corresponding multiplier for the damage formula.
|
||||
pub fn multiplier(&self) -> f64 {
|
||||
match *self {
|
||||
TypeEffectiveness::NotEffective => 0.0,
|
||||
TypeEffectiveness::NotVeryEffective => 0.5,
|
||||
TypeEffectiveness::Normal => 1.0,
|
||||
TypeEffectiveness::SuperEffective => 2.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Stats {
|
||||
/// Given the base stats and a level, this function returns the actual
|
||||
/// stats for that level.
|
||||
///
|
||||
/// This function doesn't implement the correct formula used by Pokemon
|
||||
/// games. It is a simplified version of the original formula for now: we
|
||||
/// ignore IVs, EVs and the Pokemon's nature). The complete formula can be
|
||||
/// found [here (HP)][1] and [here (other stats)][2].
|
||||
///
|
||||
/// [1]: http://bulbapedia.bulbagarden.net/wiki/File:HPStatCalcGen34.png
|
||||
/// [2]: http://bulbapedia.bulbagarden.net/wiki/File:OtherStatCalcGen34.png
|
||||
pub fn at_level(base: Self, level: u8) -> Self {
|
||||
/// The formula is the same for all stats != hp
|
||||
fn stat_formula(base: u16, level: u8) -> u16 {
|
||||
((base as f64 * level as f64) / 50.0 + 5.0) as u16
|
||||
}
|
||||
|
||||
let hp = (
|
||||
(base.hp as f64 * level as f64) / 50.0
|
||||
+ level as f64
|
||||
+ 10.0
|
||||
) as u16;
|
||||
|
||||
Stats {
|
||||
hp: hp,
|
||||
speed: stat_formula(base.speed, level),
|
||||
attack: stat_formula(base.attack, level),
|
||||
special_attack: stat_formula(base.special_attack, level),
|
||||
defense: stat_formula(base.defense, level),
|
||||
special_defense: stat_formula(base.special_defense, level),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// ===========================================================================
|
||||
// ===========================================================================
|
||||
// Formulas to calculate stuff
|
||||
// ===========================================================================
|
||||
// ===========================================================================
|
||||
// ===========================================================================
|
||||
|
||||
/// Calculates the damage of an attack. We don't use the exact formula, but
|
||||
/// a simplified version of it. In particular, we simplified the "Modifier"
|
||||
/// term quite a bit. The correct and complete formula can be found [here][1].
|
||||
///
|
||||
/// [1]: http://bulbapedia.bulbagarden.net/wiki/Damage#Damage_formula
|
||||
pub fn attack_damage(attacker: &Pokemon, defender: &Pokemon, attack: Attack) -> u16 {
|
||||
// Depending on the attack category, get the correct stats
|
||||
let (attack_mod, defense_mod) = match attack.category {
|
||||
AttackCategory::Physical => {
|
||||
(attacker.stats().attack, defender.stats().defense)
|
||||
}
|
||||
AttackCategory::Special => {
|
||||
(attacker.stats().special_attack, defender.stats().special_defense)
|
||||
}
|
||||
};
|
||||
|
||||
// Cast everything to f64 to reduce noise in actual formula
|
||||
let (attack_mod, defense_mod) = (attack_mod as f64, defense_mod as f64);
|
||||
let base_power = attack.base_power as f64;
|
||||
let attacker_level = attacker.level() as f64;
|
||||
|
||||
// The modifier only depends on the type effectiveness (in our simplified
|
||||
// version!).
|
||||
let modifier = match defender.model().type_ {
|
||||
PokemonType::One(ty) => {
|
||||
TypeEffectiveness::of_attack(attack.type_, ty).multiplier()
|
||||
}
|
||||
PokemonType::Two(ty_a, ty_b) => {
|
||||
TypeEffectiveness::of_attack(attack.type_, ty_a).multiplier()
|
||||
* TypeEffectiveness::of_attack(attack.type_, ty_b).multiplier()
|
||||
}
|
||||
};
|
||||
|
||||
// With every parameter prepared above, here is the formula
|
||||
(
|
||||
(
|
||||
((2.0 * attacker_level + 10.0) / 250.0)
|
||||
* (attack_mod / defense_mod)
|
||||
* base_power
|
||||
+ 2.0
|
||||
) * modifier
|
||||
) as u16
|
||||
}
|
57
aufgaben/sheet05/sol1/src/engine/mod.rs
Executable file
57
aufgaben/sheet05/sol1/src/engine/mod.rs
Executable file
@@ -0,0 +1,57 @@
|
||||
use db::types::*;
|
||||
|
||||
pub mod canon;
|
||||
|
||||
pub struct Pokemon {
|
||||
/// Reference to the kind of the Pokemon, which contains the name, base
|
||||
/// stats, id and more global data.
|
||||
model: PokemonModel,
|
||||
/// These are the actual stats of the pokemon, that fit to the current
|
||||
/// level
|
||||
stats: Stats,
|
||||
/// The current level of the Pokemon.
|
||||
level: u8,
|
||||
}
|
||||
|
||||
impl Pokemon {
|
||||
/// Creates a new living Pokemon of the given Pokemon kind (model) with the
|
||||
/// specified level.
|
||||
pub fn with_level(model: PokemonModel, level: u8) -> Self {
|
||||
Pokemon {
|
||||
model: model,
|
||||
stats: Stats::at_level(model.base_stats, level),
|
||||
level: level,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current stats.
|
||||
pub fn stats(&self) -> &Stats {
|
||||
&self.stats
|
||||
}
|
||||
|
||||
/// Returns the Pokemon kind of this Pokemon.
|
||||
pub fn model(&self) -> &PokemonModel {
|
||||
&self.model
|
||||
}
|
||||
|
||||
/// Returns the name.
|
||||
pub fn name(&self) -> &str {
|
||||
self.model.name
|
||||
}
|
||||
|
||||
/// Returns the current level.
|
||||
pub fn level(&self) -> u8 {
|
||||
self.level
|
||||
}
|
||||
|
||||
/// Decreases the Pokemon's HP according to the given attack and attacker.
|
||||
pub fn endure_attack(&mut self, attacker: &Pokemon, attack: Attack) {
|
||||
let damage = canon::attack_damage(attacker, self, attack);
|
||||
self.stats.hp = self.stats.hp.saturating_sub(damage);
|
||||
}
|
||||
|
||||
/// Returns whether or not the Pokemon is still alive (more than 0 HP).
|
||||
pub fn is_alive(&self) -> bool {
|
||||
self.stats.hp > 0
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user