atagen

jelq

public

an http based roguelike rpg about jelqing

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

Blame: src/game/state.rs

782069860236atagen2026-10-10 12:44 UTC1
use axum::http::StatusCode;
782069860236atagen2026-10-10 12:44 UTC2
782069860236atagen2026-10-10 12:44 UTC3
use crate::problem::Problem;
782069860236atagen2026-10-10 12:44 UTC4
782069860236atagen2026-10-10 12:44 UTC5
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC6
#[repr(u8)]
782069860236atagen2026-10-10 12:44 UTC7
pub enum Floor {
782069860236atagen2026-10-10 12:44 UTC8
    Bedroom = 1,
782069860236atagen2026-10-10 12:44 UTC9
    Bathroom = 2,
782069860236atagen2026-10-10 12:44 UTC10
    LockerRoom = 3,
782069860236atagen2026-10-10 12:44 UTC11
    Grandmas = 4,
782069860236atagen2026-10-10 12:44 UTC12
    Hotel = 5,
782069860236atagen2026-10-10 12:44 UTC13
    Forum = 6,
782069860236atagen2026-10-10 12:44 UTC14
    Clinic = 7,
782069860236atagen2026-10-10 12:44 UTC15
}
782069860236atagen2026-10-10 12:44 UTC16
782069860236atagen2026-10-10 12:44 UTC17
impl Floor {
782069860236atagen2026-10-10 12:44 UTC18
    pub fn number(self) -> u8 {
782069860236atagen2026-10-10 12:44 UTC19
        self as u8
782069860236atagen2026-10-10 12:44 UTC20
    }
782069860236atagen2026-10-10 12:44 UTC21
782069860236atagen2026-10-10 12:44 UTC22
    pub fn next(self) -> Option<Self> {
782069860236atagen2026-10-10 12:44 UTC23
        match self {
782069860236atagen2026-10-10 12:44 UTC24
            Self::Bedroom => Some(Self::Bathroom),
782069860236atagen2026-10-10 12:44 UTC25
            Self::Bathroom => Some(Self::LockerRoom),
782069860236atagen2026-10-10 12:44 UTC26
            Self::LockerRoom => Some(Self::Grandmas),
782069860236atagen2026-10-10 12:44 UTC27
            Self::Grandmas => Some(Self::Hotel),
782069860236atagen2026-10-10 12:44 UTC28
            Self::Hotel => Some(Self::Forum),
782069860236atagen2026-10-10 12:44 UTC29
            Self::Forum => Some(Self::Clinic),
782069860236atagen2026-10-10 12:44 UTC30
            Self::Clinic => None,
782069860236atagen2026-10-10 12:44 UTC31
        }
782069860236atagen2026-10-10 12:44 UTC32
    }
782069860236atagen2026-10-10 12:44 UTC33
782069860236atagen2026-10-10 12:44 UTC34
    pub fn name(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC35
        match self {
782069860236atagen2026-10-10 12:44 UTC36
            Self::Bedroom => "the bedroom",
782069860236atagen2026-10-10 12:44 UTC37
            Self::Bathroom => "the shared bathroom",
782069860236atagen2026-10-10 12:44 UTC38
            Self::LockerRoom => "the gym locker room",
782069860236atagen2026-10-10 12:44 UTC39
            Self::Grandmas => "grandma's house for Thanksgiving",
782069860236atagen2026-10-10 12:44 UTC40
            Self::Hotel => "a business trip hotel",
782069860236atagen2026-10-10 12:44 UTC41
            Self::Forum => "the forum",
782069860236atagen2026-10-10 12:44 UTC42
            Self::Clinic => "the urologist's office",
782069860236atagen2026-10-10 12:44 UTC43
        }
782069860236atagen2026-10-10 12:44 UTC44
    }
782069860236atagen2026-10-10 12:44 UTC45
782069860236atagen2026-10-10 12:44 UTC46
    pub fn note(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC47
        match self {
782069860236atagen2026-10-10 12:44 UTC48
            Self::Bedroom => "The door does not lock. The cat is present.",
782069860236atagen2026-10-10 12:44 UTC49
            Self::Bathroom => "The water is hot. The roommate showers at eight.",
782069860236atagen2026-10-10 12:44 UTC50
            Self::LockerRoom => {
782069860236atagen2026-10-10 12:44 UTC51
                "It is cold. Discretion is advised. Everyone here is lying. Pump-Bro is by the lockers."
782069860236atagen2026-10-10 12:44 UTC52
            }
782069860236atagen2026-10-10 12:44 UTC53
            Self::Grandmas => {
782069860236atagen2026-10-10 12:44 UTC54
                "The walls are thin. Mom is here, and she has been reading about Digest authentication."
782069860236atagen2026-10-10 12:44 UTC55
            }
782069860236atagen2026-10-10 12:44 UTC56
            Self::Hotel => {
782069860236atagen2026-10-10 12:44 UTC57
                "The wifi requires agreement. Housekeeping does not knock. Pump-Bro is in the lobby."
782069860236atagen2026-10-10 12:44 UTC58
            }
782069860236atagen2026-10-10 12:44 UTC59
            Self::Forum => "Nothing physical happens here. The Elder has a spreadsheet.",
782069860236atagen2026-10-10 12:44 UTC60
            Self::Clinic => "The urologist will see you now. He is bored.",
782069860236atagen2026-10-10 12:44 UTC61
        }
782069860236atagen2026-10-10 12:44 UTC62
    }
782069860236atagen2026-10-10 12:44 UTC63
782069860236atagen2026-10-10 12:44 UTC64
    pub fn observer(self) -> Option<Observer> {
782069860236atagen2026-10-10 12:44 UTC65
        match self {
782069860236atagen2026-10-10 12:44 UTC66
            Self::Bedroom => Some(Observer::Cat),
782069860236atagen2026-10-10 12:44 UTC67
            Self::LockerRoom => Some(Observer::Greg),
782069860236atagen2026-10-10 12:44 UTC68
            Self::Grandmas => Some(Observer::Grandma),
782069860236atagen2026-10-10 12:44 UTC69
            _ => None,
782069860236atagen2026-10-10 12:44 UTC70
        }
782069860236atagen2026-10-10 12:44 UTC71
    }
782069860236atagen2026-10-10 12:44 UTC72
782069860236atagen2026-10-10 12:44 UTC73
    pub fn has_mom(self) -> bool {
782069860236atagen2026-10-10 12:44 UTC74
        matches!(self, Self::Bedroom | Self::Grandmas)
782069860236atagen2026-10-10 12:44 UTC75
    }
782069860236atagen2026-10-10 12:44 UTC76
782069860236atagen2026-10-10 12:44 UTC77
    pub fn has_window(self) -> bool {
782069860236atagen2026-10-10 12:44 UTC78
        matches!(self, Self::Bedroom | Self::Grandmas | Self::Hotel)
782069860236atagen2026-10-10 12:44 UTC79
    }
782069860236atagen2026-10-10 12:44 UTC80
782069860236atagen2026-10-10 12:44 UTC81
    pub fn shop_open(self) -> bool {
782069860236atagen2026-10-10 12:44 UTC82
        matches!(self, Self::LockerRoom | Self::Hotel)
782069860236atagen2026-10-10 12:44 UTC83
    }
782069860236atagen2026-10-10 12:44 UTC84
782069860236atagen2026-10-10 12:44 UTC85
    pub fn timed(self) -> bool {
782069860236atagen2026-10-10 12:44 UTC86
        !matches!(self, Self::Forum | Self::Clinic)
782069860236atagen2026-10-10 12:44 UTC87
    }
782069860236atagen2026-10-10 12:44 UTC88
}
782069860236atagen2026-10-10 12:44 UTC89
782069860236atagen2026-10-10 12:44 UTC90
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC91
pub enum Observer {
782069860236atagen2026-10-10 12:44 UTC92
    Cat,
782069860236atagen2026-10-10 12:44 UTC93
    Greg,
782069860236atagen2026-10-10 12:44 UTC94
    Grandma,
782069860236atagen2026-10-10 12:44 UTC95
}
782069860236atagen2026-10-10 12:44 UTC96
782069860236atagen2026-10-10 12:44 UTC97
impl Observer {
782069860236atagen2026-10-10 12:44 UTC98
    pub fn name(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC99
        match self {
782069860236atagen2026-10-10 12:44 UTC100
            Self::Cat => "cat",
782069860236atagen2026-10-10 12:44 UTC101
            Self::Greg => "greg",
782069860236atagen2026-10-10 12:44 UTC102
            Self::Grandma => "grandma",
782069860236atagen2026-10-10 12:44 UTC103
        }
782069860236atagen2026-10-10 12:44 UTC104
    }
782069860236atagen2026-10-10 12:44 UTC105
}
782069860236atagen2026-10-10 12:44 UTC106
782069860236atagen2026-10-10 12:44 UTC107
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC108
pub enum Grip {
782069860236atagen2026-10-10 12:44 UTC109
    Overhand,
782069860236atagen2026-10-10 12:44 UTC110
    Underhand,
782069860236atagen2026-10-10 12:44 UTC111
}
782069860236atagen2026-10-10 12:44 UTC112
782069860236atagen2026-10-10 12:44 UTC113
impl Grip {
782069860236atagen2026-10-10 12:44 UTC114
    pub fn name(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC115
        match self {
782069860236atagen2026-10-10 12:44 UTC116
            Self::Overhand => "overhand",
782069860236atagen2026-10-10 12:44 UTC117
            Self::Underhand => "underhand",
782069860236atagen2026-10-10 12:44 UTC118
        }
782069860236atagen2026-10-10 12:44 UTC119
    }
782069860236atagen2026-10-10 12:44 UTC120
782069860236atagen2026-10-10 12:44 UTC121
    pub fn parse(protocol: &str) -> Option<Self> {
782069860236atagen2026-10-10 12:44 UTC122
        match protocol.to_ascii_lowercase().as_str() {
782069860236atagen2026-10-10 12:44 UTC123
            "overhand" => Some(Self::Overhand),
782069860236atagen2026-10-10 12:44 UTC124
            "underhand" => Some(Self::Underhand),
782069860236atagen2026-10-10 12:44 UTC125
            _ => None,
782069860236atagen2026-10-10 12:44 UTC126
        }
782069860236atagen2026-10-10 12:44 UTC127
    }
782069860236atagen2026-10-10 12:44 UTC128
}
782069860236atagen2026-10-10 12:44 UTC129
782069860236atagen2026-10-10 12:44 UTC130
/// State that belongs to the current floor and resets when you leave it.
782069860236atagen2026-10-10 12:44 UTC131
#[derive(Default)]
782069860236atagen2026-10-10 12:44 UTC132
pub struct FloorState {
782069860236atagen2026-10-10 12:44 UTC133
    pub turns: u32,
782069860236atagen2026-10-10 12:44 UTC134
    pub drawer_searches: u8,
782069860236atagen2026-10-10 12:44 UTC135
    pub edges: u8,
782069860236atagen2026-10-10 12:44 UTC136
    pub temp_length: f64,
782069860236atagen2026-10-10 12:44 UTC137
    pub teapot: bool,
782069860236atagen2026-10-10 12:44 UTC138
    pub towel_stolen: bool,
782069860236atagen2026-10-10 12:44 UTC139
    pub roommate_told: bool,
782069860236atagen2026-10-10 12:44 UTC140
    pub wifi_accepted: bool,
782069860236atagen2026-10-10 12:44 UTC141
}
782069860236atagen2026-10-10 12:44 UTC142
782069860236atagen2026-10-10 12:44 UTC143
#[derive(Default)]
782069860236atagen2026-10-10 12:44 UTC144
pub struct Conditions {
782069860236atagen2026-10-10 12:44 UTC145
    pub peyronie: bool,
782069860236atagen2026-10-10 12:44 UTC146
    pub pulled_muscle: bool,
782069860236atagen2026-10-10 12:44 UTC147
    pub priapism_turns: u8,
782069860236atagen2026-10-10 12:44 UTC148
}
782069860236atagen2026-10-10 12:44 UTC149
782069860236atagen2026-10-10 12:44 UTC150
pub struct MomVisit {
782069860236atagen2026-10-10 12:44 UTC151
    pub errand: &'static str,
782069860236atagen2026-10-10 12:44 UTC152
    pub nonce: String,
782069860236atagen2026-10-10 12:44 UTC153
    pub strikes: u8,
782069860236atagen2026-10-10 12:44 UTC154
}
782069860236atagen2026-10-10 12:44 UTC155
782069860236atagen2026-10-10 12:44 UTC156
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC157
pub enum Elder {
782069860236atagen2026-10-10 12:44 UTC158
    Unverified { strikes: u8 },
782069860236atagen2026-10-10 12:44 UTC159
    Verified,
782069860236atagen2026-10-10 12:44 UTC160
    Beaten,
782069860236atagen2026-10-10 12:44 UTC161
}
782069860236atagen2026-10-10 12:44 UTC162
782069860236atagen2026-10-10 12:44 UTC163
#[derive(Default)]
782069860236atagen2026-10-10 12:44 UTC164
pub struct Clinic {
782069860236atagen2026-10-10 12:44 UTC165
    pub intake_attempts: usize,
782069860236atagen2026-10-10 12:44 UTC166
    pub measured: bool,
782069860236atagen2026-10-10 12:44 UTC167
    pub cured: bool,
782069860236atagen2026-10-10 12:44 UTC168
}
782069860236atagen2026-10-10 12:44 UTC169
782069860236atagen2026-10-10 12:44 UTC170
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC171
pub enum Story {
782069860236atagen2026-10-10 12:44 UTC172
    Unopened,
782069860236atagen2026-10-10 12:44 UTC173
    Pending,
782069860236atagen2026-10-10 12:44 UTC174
    ReadForum,
782069860236atagen2026-10-10 12:44 UTC175
    ClosedTab,
782069860236atagen2026-10-10 12:44 UTC176
}
782069860236atagen2026-10-10 12:44 UTC177
782069860236atagen2026-10-10 12:44 UTC178
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
782069860236atagen2026-10-10 12:44 UTC179
pub enum Cause {
782069860236atagen2026-10-10 12:44 UTC180
    Ruptured { ice_unused: bool },
782069860236atagen2026-10-10 12:44 UTC181
    Caught,
782069860236atagen2026-10-10 12:44 UTC182
    Banned,
782069860236atagen2026-10-10 12:44 UTC183
    Degloved,
782069860236atagen2026-10-10 12:44 UTC184
    Zipper,
782069860236atagen2026-10-10 12:44 UTC185
    Abandoned,
782069860236atagen2026-10-10 12:44 UTC186
}
782069860236atagen2026-10-10 12:44 UTC187
782069860236atagen2026-10-10 12:44 UTC188
impl Cause {
782069860236atagen2026-10-10 12:44 UTC189
    pub fn slug(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC190
        match self {
782069860236atagen2026-10-10 12:44 UTC191
            Self::Ruptured { .. } => "vascular-event",
782069860236atagen2026-10-10 12:44 UTC192
            Self::Caught => "caught",
782069860236atagen2026-10-10 12:44 UTC193
            Self::Banned => "banned",
782069860236atagen2026-10-10 12:44 UTC194
            Self::Degloved => "degloved",
782069860236atagen2026-10-10 12:44 UTC195
            Self::Zipper => "zipper",
782069860236atagen2026-10-10 12:44 UTC196
            Self::Abandoned => "abandoned",
782069860236atagen2026-10-10 12:44 UTC197
        }
782069860236atagen2026-10-10 12:44 UTC198
    }
782069860236atagen2026-10-10 12:44 UTC199
782069860236atagen2026-10-10 12:44 UTC200
    pub fn detail(self) -> &'static str {
782069860236atagen2026-10-10 12:44 UTC201
        match self {
782069860236atagen2026-10-10 12:44 UTC202
            Self::Ruptured { ice_unused: true } => {
782069860236atagen2026-10-10 12:44 UTC203
                "A vessel has exceeded its rated pressure. The run has ended. An ice pack was available and was not used."
782069860236atagen2026-10-10 12:44 UTC204
            }
782069860236atagen2026-10-10 12:44 UTC205
            Self::Ruptured { ice_unused: false } => {
782069860236atagen2026-10-10 12:44 UTC206
                "A vessel has exceeded its rated pressure. The run has ended."
782069860236atagen2026-10-10 12:44 UTC207
            }
782069860236atagen2026-10-10 12:44 UTC208
            Self::Caught => {
782069860236atagen2026-10-10 12:44 UTC209
                "Mom has seen enough. The run has ended. Nobody will mention it at dinner."
782069860236atagen2026-10-10 12:44 UTC210
            }
782069860236atagen2026-10-10 12:44 UTC211
            Self::Banned => "Your account has been banned. The forum can tell. The run has ended.",
782069860236atagen2026-10-10 12:44 UTC212
            Self::Degloved => {
782069860236atagen2026-10-10 12:44 UTC213
                "The outer layer has been removed in one piece. It will not be returning. The run has ended."
782069860236atagen2026-10-10 12:44 UTC214
            }
782069860236atagen2026-10-10 12:44 UTC215
            Self::Zipper => {
782069860236atagen2026-10-10 12:44 UTC216
                "The request conflicts with the current state of the zipper. The run has ended."
782069860236atagen2026-10-10 12:44 UTC217
            }
782069860236atagen2026-10-10 12:44 UTC218
            Self::Abandoned => "The run was abandoned.",
782069860236atagen2026-10-10 12:44 UTC219
        }
782069860236atagen2026-10-10 12:44 UTC220
    }
782069860236atagen2026-10-10 12:44 UTC221
782069860236atagen2026-10-10 12:44 UTC222
    fn status(self) -> StatusCode {
782069860236atagen2026-10-10 12:44 UTC223
        match self {
782069860236atagen2026-10-10 12:44 UTC224
            Self::Ruptured { .. } => StatusCode::INTERNAL_SERVER_ERROR,
782069860236atagen2026-10-10 12:44 UTC225
            Self::Caught | Self::Degloved | Self::Abandoned => StatusCode::GONE,
782069860236atagen2026-10-10 12:44 UTC226
            Self::Banned => StatusCode::FORBIDDEN,
782069860236atagen2026-10-10 12:44 UTC227
            Self::Zipper => StatusCode::CONFLICT,
782069860236atagen2026-10-10 12:44 UTC228
        }
782069860236atagen2026-10-10 12:44 UTC229
    }
782069860236atagen2026-10-10 12:44 UTC230
782069860236atagen2026-10-10 12:44 UTC231
    pub fn problem(self) -> Problem {
782069860236atagen2026-10-10 12:44 UTC232
        Problem::new(self.status(), self.slug(), self.detail())
782069860236atagen2026-10-10 12:44 UTC233
    }
782069860236atagen2026-10-10 12:44 UTC234
}
782069860236atagen2026-10-10 12:44 UTC235
782069860236atagen2026-10-10 12:44 UTC236
pub struct Ending {
782069860236atagen2026-10-10 12:44 UTC237
    pub cause: Cause,
782069860236atagen2026-10-10 12:44 UTC238
    pub turn: u32,
782069860236atagen2026-10-10 12:44 UTC239
}
782069860236atagen2026-10-10 12:44 UTC240
782069860236atagen2026-10-10 12:44 UTC241
pub struct Pending {
782069860236atagen2026-10-10 12:44 UTC242
    pub due: u32,
782069860236atagen2026-10-10 12:44 UTC243
    pub length: f64,
782069860236atagen2026-10-10 12:44 UTC244
    pub girth: f64,
782069860236atagen2026-10-10 12:44 UTC245
}