atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
27256acf27800b63fd950b95ecc55b2a2486c1c5
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: src/game/techniques.rs

dfa38cf4cd4batagen2026-10-10 09:17 UTC1
use serde_json::{Value, json};
dfa38cf4cd4batagen2026-10-10 09:17 UTC2
8b8e83329a1datagen2026-10-12 12:01 UTC3
use super::lube::LubeRule;
dfa38cf4cd4batagen2026-10-10 09:17 UTC4
782069860236atagen2026-10-10 12:44 UTC5
/// Techniques that roll for gains.
dfa38cf4cd4batagen2026-10-10 09:17 UTC6
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC7
pub enum Training {
782069860236atagen2026-10-10 12:44 UTC8
    Wet,
782069860236atagen2026-10-10 12:44 UTC9
    Dry,
782069860236atagen2026-10-10 12:44 UTC10
    Stretch,
782069860236atagen2026-10-10 12:44 UTC11
    Uli,
782069860236atagen2026-10-10 12:44 UTC12
}
782069860236atagen2026-10-10 12:44 UTC13
782069860236atagen2026-10-10 12:44 UTC14
/// Techniques that change EQ or spend an item without rolling.
782069860236atagen2026-10-10 12:44 UTC15
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC16
pub enum Utility {
dfa38cf4cd4batagen2026-10-10 09:17 UTC17
    Warmup,
dfa38cf4cd4batagen2026-10-10 09:17 UTC18
    Ice,
dfa38cf4cd4batagen2026-10-10 09:17 UTC19
    Edge,
dfa38cf4cd4batagen2026-10-10 09:17 UTC20
    Pump,
dfa38cf4cd4batagen2026-10-10 09:17 UTC21
    Supplement,
0fdc47364c8catagen2026-10-11 04:45 UTC22
    Meditate,
0a0bfee8329eatagen2026-10-11 05:11 UTC23
    Energy,
782069860236atagen2026-10-10 12:44 UTC24
}
782069860236atagen2026-10-10 12:44 UTC25
782069860236atagen2026-10-10 12:44 UTC26
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC27
pub enum Technique {
782069860236atagen2026-10-10 12:44 UTC28
    Training(Training),
782069860236atagen2026-10-10 12:44 UTC29
    Utility(Utility),
dfa38cf4cd4batagen2026-10-10 09:17 UTC30
}
dfa38cf4cd4batagen2026-10-10 09:17 UTC31
782069860236atagen2026-10-10 12:44 UTC32
pub struct Profile {
8b8e83329a1datagen2026-10-12 12:01 UTC33
    pub(crate) dc: i32,
8b8e83329a1datagen2026-10-12 12:01 UTC34
    pub(crate) length: f64,
8b8e83329a1datagen2026-10-12 12:01 UTC35
    pub(crate) girth: f64,
782069860236atagen2026-10-10 12:44 UTC36
    /// Minimum and maximum foreskin the technique tolerates. A minimum above zero means it is used.
8b8e83329a1datagen2026-10-12 12:01 UTC37
    pub(crate) foreskin: Option<(f64, f64)>,
8b8e83329a1datagen2026-10-12 12:01 UTC38
    pub(crate) foreskin_growth: f64,
8b8e83329a1datagen2026-10-12 12:01 UTC39
    pub(crate) lube: LubeRule,
dfa38cf4cd4batagen2026-10-10 09:17 UTC40
}
dfa38cf4cd4batagen2026-10-10 09:17 UTC41
782069860236atagen2026-10-10 12:44 UTC42
impl Training {
dfa38cf4cd4batagen2026-10-10 09:17 UTC43
    pub fn name(self) -> &'static str {
dfa38cf4cd4batagen2026-10-10 09:17 UTC44
        match self {
dfa38cf4cd4batagen2026-10-10 09:17 UTC45
            Self::Wet => "wet",
dfa38cf4cd4batagen2026-10-10 09:17 UTC46
            Self::Dry => "dry",
dfa38cf4cd4batagen2026-10-10 09:17 UTC47
            Self::Stretch => "stretch",
dfa38cf4cd4batagen2026-10-10 09:17 UTC48
            Self::Uli => "uli",
dfa38cf4cd4batagen2026-10-10 09:17 UTC49
        }
dfa38cf4cd4batagen2026-10-10 09:17 UTC50
    }
dfa38cf4cd4batagen2026-10-10 09:17 UTC51
782069860236atagen2026-10-10 12:44 UTC52
    pub fn profile(self) -> Profile {
782069860236atagen2026-10-10 12:44 UTC53
        match self {
dfa38cf4cd4batagen2026-10-10 09:17 UTC54
            Self::Wet => Profile {
dfa38cf4cd4batagen2026-10-10 09:17 UTC55
                dc: 10,
dfa38cf4cd4batagen2026-10-10 09:17 UTC56
                length: 0.010,
dfa38cf4cd4batagen2026-10-10 09:17 UTC57
                girth: 0.005,
dfa38cf4cd4batagen2026-10-10 09:17 UTC58
                foreskin: None,
dfa38cf4cd4batagen2026-10-10 09:17 UTC59
                foreskin_growth: 0.0,
dfa38cf4cd4batagen2026-10-10 09:17 UTC60
                lube: LubeRule::Required,
dfa38cf4cd4batagen2026-10-10 09:17 UTC61
            },
dfa38cf4cd4batagen2026-10-10 09:17 UTC62
            Self::Dry => Profile {
dfa38cf4cd4batagen2026-10-10 09:17 UTC63
                dc: 12,
dfa38cf4cd4batagen2026-10-10 09:17 UTC64
                length: 0.008,
dfa38cf4cd4batagen2026-10-10 09:17 UTC65
                girth: 0.003,
dfa38cf4cd4batagen2026-10-10 09:17 UTC66
                foreskin: Some((0.8, 2.0)),
dfa38cf4cd4batagen2026-10-10 09:17 UTC67
                foreskin_growth: 0.01,
dfa38cf4cd4batagen2026-10-10 09:17 UTC68
                lube: LubeRule::Forbidden,
dfa38cf4cd4batagen2026-10-10 09:17 UTC69
            },
dfa38cf4cd4batagen2026-10-10 09:17 UTC70
            Self::Stretch => Profile {
dfa38cf4cd4batagen2026-10-10 09:17 UTC71
                dc: 11,
dfa38cf4cd4batagen2026-10-10 09:17 UTC72
                length: 0.015,
dfa38cf4cd4batagen2026-10-10 09:17 UTC73
                girth: 0.0,
dfa38cf4cd4batagen2026-10-10 09:17 UTC74
                foreskin: Some((0.0, 1.8)),
dfa38cf4cd4batagen2026-10-10 09:17 UTC75
                foreskin_growth: 0.03,
dfa38cf4cd4batagen2026-10-10 09:17 UTC76
                lube: LubeRule::Optional,
dfa38cf4cd4batagen2026-10-10 09:17 UTC77
            },
dfa38cf4cd4batagen2026-10-10 09:17 UTC78
            Self::Uli => Profile {
dfa38cf4cd4batagen2026-10-10 09:17 UTC79
                dc: 15,
dfa38cf4cd4batagen2026-10-10 09:17 UTC80
                length: 0.002,
dfa38cf4cd4batagen2026-10-10 09:17 UTC81
                girth: 0.020,
dfa38cf4cd4batagen2026-10-10 09:17 UTC82
                foreskin: None,
dfa38cf4cd4batagen2026-10-10 09:17 UTC83
                foreskin_growth: 0.0,
dfa38cf4cd4batagen2026-10-10 09:17 UTC84
                lube: LubeRule::Optional,
dfa38cf4cd4batagen2026-10-10 09:17 UTC85
            },
782069860236atagen2026-10-10 12:44 UTC86
        }
782069860236atagen2026-10-10 12:44 UTC87
    }
782069860236atagen2026-10-10 12:44 UTC88
}
782069860236atagen2026-10-10 12:44 UTC89
782069860236atagen2026-10-10 12:44 UTC90
impl Utility {
782069860236atagen2026-10-10 12:44 UTC91
    pub fn name(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC92
        match self {
782069860236atagen2026-10-10 12:44 UTC93
            Self::Warmup => "warmup",
782069860236atagen2026-10-10 12:44 UTC94
            Self::Ice => "ice",
782069860236atagen2026-10-10 12:44 UTC95
            Self::Edge => "edge",
782069860236atagen2026-10-10 12:44 UTC96
            Self::Pump => "pump",
782069860236atagen2026-10-10 12:44 UTC97
            Self::Supplement => "supplement",
0fdc47364c8catagen2026-10-11 04:45 UTC98
            Self::Meditate => "meditate",
0a0bfee8329eatagen2026-10-11 05:11 UTC99
            Self::Energy => "energy",
782069860236atagen2026-10-10 12:44 UTC100
        }
782069860236atagen2026-10-10 12:44 UTC101
    }
782069860236atagen2026-10-10 12:44 UTC102
782069860236atagen2026-10-10 12:44 UTC103
    fn effect(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC104
        match self {
e028a4184d00atagen2026-10-14 10:49 UTC105
            Self::Warmup => "Warms things a good deal. Satisfies the warm-up precondition.",
e028a4184d00atagen2026-10-14 10:49 UTC106
            Self::Ice => "Cools things sharply. Treats a friction burn. Consumes an ice pack.",
e028a4184d00atagen2026-10-14 10:49 UTC107
            Self::Edge => {
e028a4184d00atagen2026-10-14 10:49 UTC108
                "Warms things a little and adds a little girth. Three in a row is a loop."
e028a4184d00atagen2026-10-14 10:49 UTC109
            }
782069860236atagen2026-10-10 12:44 UTC110
            Self::Pump => "Large gains, all temporary. Requires a pump.",
782069860236atagen2026-10-10 12:44 UTC111
            Self::Supplement => "Consumes a supplement.",
e028a4184d00atagen2026-10-14 10:49 UTC112
            Self::Meditate => {
a043b8dc91b7atagen2026-10-14 12:22 UTC113
                "Cools things a little, sheds 2 friction and 2 suspicion. Taught by the forum. Once per floor."
e028a4184d00atagen2026-10-14 10:49 UTC114
            }
0a0bfee8329eatagen2026-10-11 05:11 UTC115
            Self::Energy => "+3 stamina. Consumes an energy drink. Tastes like a battery.",
782069860236atagen2026-10-10 12:44 UTC116
        }
782069860236atagen2026-10-10 12:44 UTC117
    }
782069860236atagen2026-10-10 12:44 UTC118
}
782069860236atagen2026-10-10 12:44 UTC119
782069860236atagen2026-10-10 12:44 UTC120
impl Technique {
0a0bfee8329eatagen2026-10-11 05:11 UTC121
    pub const ALL: [Self; 11] = [
782069860236atagen2026-10-10 12:44 UTC122
        Self::Utility(Utility::Warmup),
fa21a42ca085atagen2026-10-14 12:26 UTC123
        Self::Training(Training::Uli),
782069860236atagen2026-10-10 12:44 UTC124
        Self::Training(Training::Wet),
782069860236atagen2026-10-10 12:44 UTC125
        Self::Training(Training::Dry),
782069860236atagen2026-10-10 12:44 UTC126
        Self::Training(Training::Stretch),
fa21a42ca085atagen2026-10-14 12:26 UTC127
        Self::Utility(Utility::Meditate),
fa21a42ca085atagen2026-10-14 12:26 UTC128
        Self::Utility(Utility::Ice),
fa21a42ca085atagen2026-10-14 12:26 UTC129
        Self::Utility(Utility::Energy),
fa21a42ca085atagen2026-10-14 12:26 UTC130
        Self::Utility(Utility::Supplement),
fa21a42ca085atagen2026-10-14 12:26 UTC131
        Self::Utility(Utility::Edge),
fa21a42ca085atagen2026-10-14 12:26 UTC132
        Self::Utility(Utility::Pump),
782069860236atagen2026-10-10 12:44 UTC133
    ];
782069860236atagen2026-10-10 12:44 UTC134
782069860236atagen2026-10-10 12:44 UTC135
    pub fn name(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC136
        match self {
782069860236atagen2026-10-10 12:44 UTC137
            Self::Training(t) => t.name(),
782069860236atagen2026-10-10 12:44 UTC138
            Self::Utility(u) => u.name(),
782069860236atagen2026-10-10 12:44 UTC139
        }
782069860236atagen2026-10-10 12:44 UTC140
    }
782069860236atagen2026-10-10 12:44 UTC141
782069860236atagen2026-10-10 12:44 UTC142
    pub fn parse(name: &str) -> Option<Self> {
782069860236atagen2026-10-10 12:44 UTC143
        Self::ALL.into_iter().find(|t| t.name() == name)
dfa38cf4cd4batagen2026-10-10 09:17 UTC144
    }
dfa38cf4cd4batagen2026-10-10 09:17 UTC145
58e1fb3943e6atagen2026-10-10 13:30 UTC146
    pub fn lubricant(self) -> Option<&'static str> {
58e1fb3943e6atagen2026-10-10 13:30 UTC147
        match self {
58e1fb3943e6atagen2026-10-10 13:30 UTC148
            Self::Training(training) => Some(training.profile().lube.name()),
e028a4184d00atagen2026-10-14 10:49 UTC149
            Self::Utility(Utility::Edge) => Some(LubeRule::Optional.name()),
e028a4184d00atagen2026-10-14 10:49 UTC150
            Self::Utility(_) => None,
e028a4184d00atagen2026-10-14 10:49 UTC151
        }
e028a4184d00atagen2026-10-14 10:49 UTC152
    }
e028a4184d00atagen2026-10-14 10:49 UTC153
e028a4184d00atagen2026-10-14 10:49 UTC154
    pub fn intensity(self) -> Option<&'static str> {
e028a4184d00atagen2026-10-14 10:49 UTC155
        match self {
e028a4184d00atagen2026-10-14 10:49 UTC156
            Self::Training(_) => Some("1-10"),
58e1fb3943e6atagen2026-10-10 13:30 UTC157
            Self::Utility(_) => None,
58e1fb3943e6atagen2026-10-10 13:30 UTC158
        }
58e1fb3943e6atagen2026-10-10 13:30 UTC159
    }
58e1fb3943e6atagen2026-10-10 13:30 UTC160
880b29a0c11eatagen2026-10-13 09:27 UTC161
    pub fn describe(self, known: bool) -> Value {
782069860236atagen2026-10-10 12:44 UTC162
        let training = match self {
782069860236atagen2026-10-10 12:44 UTC163
            Self::Utility(utility) => {
880b29a0c11eatagen2026-10-13 09:27 UTC164
                return json!({
880b29a0c11eatagen2026-10-13 09:27 UTC165
                    "name": utility.name(),
880b29a0c11eatagen2026-10-13 09:27 UTC166
                    "effect": utility.effect(),
e028a4184d00atagen2026-10-14 10:49 UTC167
                    "lubricant": self.lubricant(),
880b29a0c11eatagen2026-10-13 09:27 UTC168
                    "locked": !known,
880b29a0c11eatagen2026-10-13 09:27 UTC169
                });
782069860236atagen2026-10-10 12:44 UTC170
            }
782069860236atagen2026-10-10 12:44 UTC171
            Self::Training(training) => training,
dfa38cf4cd4batagen2026-10-10 09:17 UTC172
        };
782069860236atagen2026-10-10 12:44 UTC173
        let profile = training.profile();
58e1fb3943e6atagen2026-10-10 13:30 UTC174
        let lubricant = profile.lube.name();
dfa38cf4cd4batagen2026-10-10 09:17 UTC175
        json!({
782069860236atagen2026-10-10 12:44 UTC176
            "name": training.name(),
782069860236atagen2026-10-10 12:44 UTC177
            "dc": profile.dc,
dfa38cf4cd4batagen2026-10-10 09:17 UTC178
            "lubricant": lubricant,
782069860236atagen2026-10-10 12:44 UTC179
            "foreskin": profile.foreskin.map(|(min, max)| json!({ "min": min, "max": max })),
880b29a0c11eatagen2026-10-13 09:27 UTC180
            "locked": !known,
dfa38cf4cd4batagen2026-10-10 09:17 UTC181
        })
dfa38cf4cd4batagen2026-10-10 09:17 UTC182
    }
dfa38cf4cd4batagen2026-10-10 09:17 UTC183
}