atagen

jelq

public

an http based roguelike rpg about jelqing

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

Blame: src/game/hazards.rs

782069860236atagen2026-10-10 12:44 UTC1
use std::{ops::ControlFlow, time::SystemTime};
782069860236atagen2026-10-10 12:44 UTC2
782069860236atagen2026-10-10 12:44 UTC3
use axum::http::{StatusCode, header};
782069860236atagen2026-10-10 12:44 UTC4
use serde_json::json;
782069860236atagen2026-10-10 12:44 UTC5
782069860236atagen2026-10-10 12:44 UTC6
use super::{
8b8e83329a1datagen2026-10-12 12:01 UTC7
    Cause, Floor, Notice, Outcome, Run,
782069860236atagen2026-10-10 12:44 UTC8
    balance::{
4b1f5f88827datagen2026-10-13 10:18 UTC9
        BURN_RUPTURE, COLD_DEGLOVING, COLD_EQ, CURVE_MISSES, DANGER_EQ, DEGLOVING,
3ac624339c98atagen2026-10-13 12:21 UTC10
        DEGLOVING_INTENSITY, EQ_BAND, FRICTION_MAX, FRICTION_TEAR, FRIEND, HOT_EQ, LOST_IT_EQ,
3ac624339c98atagen2026-10-13 12:21 UTC11
        PREMATURE_EQ, RAW_DEGLOVING, RUPTURE_HOT, RUPTURE_IN_BAND, RUPTURE_PREMATURE, RUPTURE_WARM,
3ac624339c98atagen2026-10-13 12:21 UTC12
        SOFT_INTENSITY, SUSPICION_LIMIT, WANDERER_VISIT, WINDOW,
782069860236atagen2026-10-10 12:44 UTC13
    },
97c05b741d8fatagen2026-10-13 11:27 UTC14
    measure::round3,
782069860236atagen2026-10-10 12:44 UTC15
    techniques::Training,
8b8e83329a1datagen2026-10-12 12:01 UTC16
    travel::Exit,
782069860236atagen2026-10-10 12:44 UTC17
};
782069860236atagen2026-10-10 12:44 UTC18
use crate::problem::Problem;
782069860236atagen2026-10-10 12:44 UTC19
782069860236atagen2026-10-10 12:44 UTC20
type Interruption = Result<ControlFlow<Outcome>, Problem>;
782069860236atagen2026-10-10 12:44 UTC21
782069860236atagen2026-10-10 12:44 UTC22
impl Run {
53bce0d93000atagen2026-10-14 13:39 UTC23
    /// EQ with a friction burn dragging every line down.
53bce0d93000atagen2026-10-14 13:39 UTC24
    pub(super) fn heat(&self) -> i32 {
8b8e83329a1datagen2026-10-12 12:01 UTC25
        let burn = if self.body.conditions.friction_burn {
b85a0d4536c3atagen2026-10-11 08:50 UTC26
            BURN_RUPTURE
b85a0d4536c3atagen2026-10-11 08:50 UTC27
        } else {
b85a0d4536c3atagen2026-10-11 08:50 UTC28
            0
8b8e83329a1datagen2026-10-12 12:01 UTC29
        };
53bce0d93000atagen2026-10-14 13:39 UTC30
        self.body.eq + burn
53bce0d93000atagen2026-10-14 13:39 UTC31
    }
53bce0d93000atagen2026-10-14 13:39 UTC32
53bce0d93000atagen2026-10-14 13:39 UTC33
    pub(super) fn hotter_than(&self, line: i32) -> bool {
53bce0d93000atagen2026-10-14 13:39 UTC34
        self.heat() > line
53bce0d93000atagen2026-10-14 13:39 UTC35
    }
53bce0d93000atagen2026-10-14 13:39 UTC36
53bce0d93000atagen2026-10-14 13:39 UTC37
    /// Ruptures go by the cooler of now and the turn's start, so a line crossed this turn cannot rupture
53bce0d93000atagen2026-10-14 13:39 UTC38
    /// before `X-EQ` has had a chance to name it.
53bce0d93000atagen2026-10-14 13:39 UTC39
    pub(super) fn risked(&self, line: i32) -> bool {
53bce0d93000atagen2026-10-14 13:39 UTC40
        self.heat().min(self.body.heat_at_turn_start) > line
b85a0d4536c3atagen2026-10-11 08:50 UTC41
    }
b85a0d4536c3atagen2026-10-11 08:50 UTC42
b85a0d4536c3atagen2026-10-11 08:50 UTC43
    /// The rupture tier for any turn that is not a jelq, so never the premature band's 1 in 3.
b85a0d4536c3atagen2026-10-11 08:50 UTC44
    pub(super) fn rupture_odds(&self) -> u32 {
53bce0d93000atagen2026-10-14 13:39 UTC45
        if !self.risked(DANGER_EQ) {
b85a0d4536c3atagen2026-10-11 08:50 UTC46
            RUPTURE_IN_BAND
53bce0d93000atagen2026-10-14 13:39 UTC47
        } else if !self.risked(HOT_EQ) {
b85a0d4536c3atagen2026-10-11 08:50 UTC48
            RUPTURE_WARM
b85a0d4536c3atagen2026-10-11 08:50 UTC49
        } else {
b85a0d4536c3atagen2026-10-11 08:50 UTC50
            RUPTURE_HOT
b85a0d4536c3atagen2026-10-11 08:50 UTC51
        }
b85a0d4536c3atagen2026-10-11 08:50 UTC52
    }
b85a0d4536c3atagen2026-10-11 08:50 UTC53
bf5f8cb6f60fatagen2026-10-13 12:10 UTC54
    pub(super) fn cold(&self) -> bool {
bf5f8cb6f60fatagen2026-10-13 12:10 UTC55
        self.body.eq < COLD_EQ
bf5f8cb6f60fatagen2026-10-13 12:10 UTC56
    }
bf5f8cb6f60fatagen2026-10-13 12:10 UTC57
bf5f8cb6f60fatagen2026-10-13 12:10 UTC58
    pub(super) fn mishaps(
bf5f8cb6f60fatagen2026-10-13 12:10 UTC59
        &mut self,
bf5f8cb6f60fatagen2026-10-13 12:10 UTC60
        training: Training,
bf5f8cb6f60fatagen2026-10-13 12:10 UTC61
        intensity: i32,
bf5f8cb6f60fatagen2026-10-13 12:10 UTC62
        cold: bool,
bf5f8cb6f60fatagen2026-10-13 12:10 UTC63
    ) -> Interruption {
bf5f8cb6f60fatagen2026-10-13 12:10 UTC64
        if cold {
4b1f5f88827datagen2026-10-13 10:18 UTC65
            if !self.notices.contains(&Notice::ColdStart) {
4b1f5f88827datagen2026-10-13 10:18 UTC66
                self.notices.push(Notice::ColdStart);
4b1f5f88827datagen2026-10-13 10:18 UTC67
            }
4b1f5f88827datagen2026-10-13 10:18 UTC68
            if self.chance(
4b1f5f88827datagen2026-10-13 10:18 UTC69
                self.decision("cold-degloving", "Cold and unprepared, does the skin tear?"),
4b1f5f88827datagen2026-10-13 10:18 UTC70
                COLD_DEGLOVING,
4b1f5f88827datagen2026-10-13 10:18 UTC71
            ) {
97c05b741d8fatagen2026-10-13 11:27 UTC72
                return Err(self.deglove());
4b1f5f88827datagen2026-10-13 10:18 UTC73
            }
4b1f5f88827datagen2026-10-13 10:18 UTC74
        }
3ac624339c98atagen2026-10-13 12:21 UTC75
        if self.body.friction >= FRICTION_MAX {
3ac624339c98atagen2026-10-13 12:21 UTC76
            self.tear()?;
3ac624339c98atagen2026-10-13 12:21 UTC77
        }
3f9091557ec3atagen2026-10-11 11:43 UTC78
        if training == Training::Dry
3f9091557ec3atagen2026-10-11 11:43 UTC79
            && intensity >= DEGLOVING_INTENSITY
3f9091557ec3atagen2026-10-11 11:43 UTC80
            && self.chance(
3f9091557ec3atagen2026-10-11 11:43 UTC81
                self.decision("degloving", "Dry at this intensity, does the skin tear?"),
3f9091557ec3atagen2026-10-11 11:43 UTC82
                DEGLOVING,
3f9091557ec3atagen2026-10-11 11:43 UTC83
            )
3f9091557ec3atagen2026-10-11 11:43 UTC84
        {
97c05b741d8fatagen2026-10-13 11:27 UTC85
            return Err(self.deglove());
782069860236atagen2026-10-10 12:44 UTC86
        }
782069860236atagen2026-10-10 12:44 UTC87
        Ok(ControlFlow::Continue(()))
782069860236atagen2026-10-10 12:44 UTC88
    }
782069860236atagen2026-10-10 12:44 UTC89
3ac624339c98atagen2026-10-13 12:21 UTC90
    fn tear(&mut self) -> Result<(), Problem> {
3ac624339c98atagen2026-10-13 12:21 UTC91
        if !self.notices.contains(&Notice::SkinGivingWay) {
3ac624339c98atagen2026-10-13 12:21 UTC92
            self.notices.push(Notice::SkinGivingWay);
3ac624339c98atagen2026-10-13 12:21 UTC93
        }
3ac624339c98atagen2026-10-13 12:21 UTC94
        match self.body.foreskin {
3ac624339c98atagen2026-10-13 12:21 UTC95
            Some(left) if left - FRICTION_TEAR > 1e-9 => {
3ac624339c98atagen2026-10-13 12:21 UTC96
                self.body.foreskin = Some(left - FRICTION_TEAR);
3ac624339c98atagen2026-10-13 12:21 UTC97
                self.body.torn += FRICTION_TEAR;
3ac624339c98atagen2026-10-13 12:21 UTC98
                Ok(())
3ac624339c98atagen2026-10-13 12:21 UTC99
            }
3ac624339c98atagen2026-10-13 12:21 UTC100
            Some(left) => {
3ac624339c98atagen2026-10-13 12:21 UTC101
                self.body.foreskin = None;
3ac624339c98atagen2026-10-13 12:21 UTC102
                self.standing.shame += 25;
3ac624339c98atagen2026-10-13 12:21 UTC103
                Err(Problem::new(
3ac624339c98atagen2026-10-13 12:21 UTC104
                    StatusCode::GONE,
3ac624339c98atagen2026-10-13 12:21 UTC105
                    "foreskin-lost",
3ac624339c98atagen2026-10-13 12:21 UTC106
                    "The friction has removed the foreskin. It will not be returning.",
3ac624339c98atagen2026-10-13 12:21 UTC107
                )
3ac624339c98atagen2026-10-13 12:21 UTC108
                .with("foreskin", -round3(left))
3ac624339c98atagen2026-10-13 12:21 UTC109
                .header(header::CONTENT_LOCATION, self.path("/foreskin")))
3ac624339c98atagen2026-10-13 12:21 UTC110
            }
3ac624339c98atagen2026-10-13 12:21 UTC111
            None => {
3ac624339c98atagen2026-10-13 12:21 UTC112
                if self.chance(
3ac624339c98atagen2026-10-13 12:21 UTC113
                    self.decision("raw-degloving", "Rubbed raw, does the skin tear?"),
3ac624339c98atagen2026-10-13 12:21 UTC114
                    RAW_DEGLOVING,
3ac624339c98atagen2026-10-13 12:21 UTC115
                ) {
3ac624339c98atagen2026-10-13 12:21 UTC116
                    return Err(self.deglove());
3ac624339c98atagen2026-10-13 12:21 UTC117
                }
3ac624339c98atagen2026-10-13 12:21 UTC118
                Ok(())
3ac624339c98atagen2026-10-13 12:21 UTC119
            }
3ac624339c98atagen2026-10-13 12:21 UTC120
        }
3ac624339c98atagen2026-10-13 12:21 UTC121
    }
3ac624339c98atagen2026-10-13 12:21 UTC122
97c05b741d8fatagen2026-10-13 11:27 UTC123
    fn deglove(&mut self) -> Problem {
97c05b741d8fatagen2026-10-13 11:27 UTC124
        let lost = self.body.foreskin.take();
97c05b741d8fatagen2026-10-13 11:27 UTC125
        let problem = self.end(Cause::Degloved);
97c05b741d8fatagen2026-10-13 11:27 UTC126
        match lost {
97c05b741d8fatagen2026-10-13 11:27 UTC127
            Some(lost) => problem.with("foreskin", -round3(lost)),
97c05b741d8fatagen2026-10-13 11:27 UTC128
            None => problem,
97c05b741d8fatagen2026-10-13 11:27 UTC129
        }
97c05b741d8fatagen2026-10-13 11:27 UTC130
    }
97c05b741d8fatagen2026-10-13 11:27 UTC131
782069860236atagen2026-10-10 12:44 UTC132
    pub(super) fn hazards(&mut self, intensity: i32) -> Interruption {
8b8e83329a1datagen2026-10-12 12:01 UTC133
        if !self.hotter_than(PREMATURE_EQ)
3f9091557ec3atagen2026-10-11 11:43 UTC134
            && self.chance(
3f9091557ec3atagen2026-10-11 11:43 UTC135
                self.decision("rupture", "Does this jelq rupture something?"),
3f9091557ec3atagen2026-10-11 11:43 UTC136
                self.rupture_odds(),
3f9091557ec3atagen2026-10-11 11:43 UTC137
            )
3f9091557ec3atagen2026-10-11 11:43 UTC138
        {
782069860236atagen2026-10-10 12:44 UTC139
            return Err(self.rupture());
782069860236atagen2026-10-10 12:44 UTC140
        }
3f9091557ec3atagen2026-10-11 11:43 UTC141
        if self.floor.has_window()
8b8e83329a1datagen2026-10-12 12:01 UTC142
            && !self.items.kit.blinds
3f9091557ec3atagen2026-10-11 11:43 UTC143
            && self.oracle.chance_not(
3f9091557ec3atagen2026-10-11 11:43 UTC144
                self.decision("window", "Are the curtains still closed?"),
3f9091557ec3atagen2026-10-11 11:43 UTC145
                WINDOW,
3f9091557ec3atagen2026-10-11 11:43 UTC146
            )
3f9091557ec3atagen2026-10-11 11:43 UTC147
        {
8b8e83329a1datagen2026-10-12 12:01 UTC148
            self.standing.shame += 30;
8b8e83329a1datagen2026-10-12 12:01 UTC149
            self.online.filmed_at.get_or_insert_with(SystemTime::now);
782069860236atagen2026-10-10 12:44 UTC150
            return Ok(ControlFlow::Break(
782069860236atagen2026-10-10 12:44 UTC151
                Outcome::json(
782069860236atagen2026-10-10 12:44 UTC152
                    StatusCode::CREATED,
782069860236atagen2026-10-10 12:44 UTC153
                    json!({ "detail": "A neighbour was at the window. A recording has been created. It has been shared." }),
782069860236atagen2026-10-10 12:44 UTC154
                )
782069860236atagen2026-10-10 12:44 UTC155
                .header(header::LOCATION, self.path("/footage")),
782069860236atagen2026-10-10 12:44 UTC156
            ));
782069860236atagen2026-10-10 12:44 UTC157
        }
3f9091557ec3atagen2026-10-11 11:43 UTC158
        if self.floor == Floor::ChangingRoom
3f9091557ec3atagen2026-10-11 11:43 UTC159
            && self.chance(
3f9091557ec3atagen2026-10-11 11:43 UTC160
                self.decision("friend", "Does a friend walk in and offer to help?"),
3f9091557ec3atagen2026-10-11 11:43 UTC161
                FRIEND,
3f9091557ec3atagen2026-10-11 11:43 UTC162
            )
3f9091557ec3atagen2026-10-11 11:43 UTC163
        {
8b8e83329a1datagen2026-10-12 12:01 UTC164
            self.standing.shame += 1;
782069860236atagen2026-10-10 12:44 UTC165
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC166
                StatusCode::USE_PROXY,
782069860236atagen2026-10-10 12:44 UTC167
                "friend",
782069860236atagen2026-10-10 12:44 UTC168
                "A friend has offered to help. Use Proxy is deprecated, and the server has declined on your behalf.",
782069860236atagen2026-10-10 12:44 UTC169
            ));
782069860236atagen2026-10-10 12:44 UTC170
        }
8b8e83329a1datagen2026-10-12 12:01 UTC171
        if self.body.conditions.peyronie
3f9091557ec3atagen2026-10-11 11:43 UTC172
            && self.chance(
3f9091557ec3atagen2026-10-11 11:43 UTC173
                self.decision(
3f9091557ec3atagen2026-10-11 11:43 UTC174
                    "misdirected",
3f9091557ec3atagen2026-10-11 11:43 UTC175
                    "With the curve, does the stroke land sharply to the left?",
3f9091557ec3atagen2026-10-11 11:43 UTC176
                ),
3f9091557ec3atagen2026-10-11 11:43 UTC177
                CURVE_MISSES,
3f9091557ec3atagen2026-10-11 11:43 UTC178
            )
3f9091557ec3atagen2026-10-11 11:43 UTC179
        {
782069860236atagen2026-10-10 12:44 UTC180
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC181
                StatusCode::MISDIRECTED_REQUEST,
782069860236atagen2026-10-10 12:44 UTC182
                "misdirected",
782069860236atagen2026-10-10 12:44 UTC183
                "The technique landed slightly to the left. It was meant for a different server.",
782069860236atagen2026-10-10 12:44 UTC184
            ));
782069860236atagen2026-10-10 12:44 UTC185
        }
8b8e83329a1datagen2026-10-12 12:01 UTC186
        if intensity <= SOFT_INTENSITY && self.body.eq < *EQ_BAND.start() {
8b8e83329a1datagen2026-10-12 12:01 UTC187
            self.body.eq = (self.body.eq - LOST_IT_EQ).max(0);
782069860236atagen2026-10-10 12:44 UTC188
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC189
                StatusCode::REQUEST_TIMEOUT,
782069860236atagen2026-10-10 12:44 UTC190
                "lost-it",
782069860236atagen2026-10-10 12:44 UTC191
                "The request took too long. It was lost.",
782069860236atagen2026-10-10 12:44 UTC192
            )
782069860236atagen2026-10-10 12:44 UTC193
            .header(header::CONNECTION, "close"));
782069860236atagen2026-10-10 12:44 UTC194
        }
8b8e83329a1datagen2026-10-12 12:01 UTC195
        if self.hotter_than(PREMATURE_EQ) {
53bce0d93000atagen2026-10-14 13:39 UTC196
            if self.risked(PREMATURE_EQ)
53bce0d93000atagen2026-10-14 13:39 UTC197
                && self.chance(
53bce0d93000atagen2026-10-14 13:39 UTC198
                    self.decision(
53bce0d93000atagen2026-10-14 13:39 UTC199
                        "rupture",
53bce0d93000atagen2026-10-14 13:39 UTC200
                        "Right at the edge of finishing, does it rupture instead?",
53bce0d93000atagen2026-10-14 13:39 UTC201
                    ),
53bce0d93000atagen2026-10-14 13:39 UTC202
                    RUPTURE_PREMATURE,
53bce0d93000atagen2026-10-14 13:39 UTC203
                )
53bce0d93000atagen2026-10-14 13:39 UTC204
            {
782069860236atagen2026-10-10 12:44 UTC205
                return Err(self.rupture());
782069860236atagen2026-10-10 12:44 UTC206
            }
8b8e83329a1datagen2026-10-12 12:01 UTC207
            self.standing.shame += 5;
8b8e83329a1datagen2026-10-12 12:01 UTC208
            self.next_floor(Exit::Premature);
782069860236atagen2026-10-10 12:44 UTC209
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC210
                StatusCode::TOO_EARLY,
782069860236atagen2026-10-10 12:44 UTC211
                "premature",
782069860236atagen2026-10-10 12:44 UTC212
                "The floor has ended early. Everyone involved has agreed not to discuss it.",
782069860236atagen2026-10-10 12:44 UTC213
            ));
782069860236atagen2026-10-10 12:44 UTC214
        }
782069860236atagen2026-10-10 12:44 UTC215
        Ok(ControlFlow::Continue(()))
782069860236atagen2026-10-10 12:44 UTC216
    }
782069860236atagen2026-10-10 12:44 UTC217
9683736a2c5eatagen2026-10-10 13:15 UTC218
    /// The enemies suspicion summons on floors without Mum.
782069860236atagen2026-10-10 12:44 UTC219
    pub(super) fn floor_enemy(&mut self) -> Result<(), Problem> {
8b8e83329a1datagen2026-10-12 12:01 UTC220
        let visits = u32::from(self.standing.suspicion) + 1;
782069860236atagen2026-10-10 12:44 UTC221
        let wanders_in = matches!(self.floor, Floor::Bathroom | Floor::Hotel)
3f9091557ec3atagen2026-10-11 11:43 UTC222
            && self.oracle.ratio_choice(
3f9091557ec3atagen2026-10-11 11:43 UTC223
                self.decision("wanderer", "Does anyone else come through the door?"),
3f9091557ec3atagen2026-10-11 11:43 UTC224
                visits,
3f9091557ec3atagen2026-10-11 11:43 UTC225
                WANDERER_VISIT,
3f9091557ec3atagen2026-10-11 11:43 UTC226
                "No",
3f9091557ec3atagen2026-10-11 11:43 UTC227
                "Yes",
3f9091557ec3atagen2026-10-11 11:43 UTC228
            );
8b8e83329a1datagen2026-10-12 12:01 UTC229
        if self.standing.suspicion < SUSPICION_LIMIT && !wanders_in {
782069860236atagen2026-10-10 12:44 UTC230
            return Ok(());
782069860236atagen2026-10-10 12:44 UTC231
        }
782069860236atagen2026-10-10 12:44 UTC232
        match self.floor {
782069860236atagen2026-10-10 12:44 UTC233
            Floor::Bathroom => {
8b8e83329a1datagen2026-10-12 12:01 UTC234
                self.standing.suspicion = 0;
782069860236atagen2026-10-10 12:44 UTC235
                self.touch();
8b8e83329a1datagen2026-10-12 12:01 UTC236
                if self.items.stores.door_locks > 0 {
8b8e83329a1datagen2026-10-12 12:01 UTC237
                    self.items.stores.door_locks -= 1;
8b8e83329a1datagen2026-10-12 12:01 UTC238
                    self.notices.push(Notice::BrotherTriedTheDoor);
782069860236atagen2026-10-10 12:44 UTC239
                    return Ok(());
782069860236atagen2026-10-10 12:44 UTC240
                }
7d3fb63208bfatagen2026-10-11 04:38 UTC241
                self.here.brother_told = true;
782069860236atagen2026-10-10 12:44 UTC242
                Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC243
                    StatusCode::CONFLICT,
7d3fb63208bfatagen2026-10-11 04:38 UTC244
                    "brother",
7d3fb63208bfatagen2026-10-11 04:38 UTC245
                    "Your brother needs the bathroom. He will tell Mum.",
782069860236atagen2026-10-10 12:44 UTC246
                ))
782069860236atagen2026-10-10 12:44 UTC247
            }
9683736a2c5eatagen2026-10-10 13:15 UTC248
            Floor::ChangingRoom => {
8b8e83329a1datagen2026-10-12 12:01 UTC249
                self.standing.suspicion = 0;
782069860236atagen2026-10-10 12:44 UTC250
                self.touch();
058650ec79d6atagen2026-10-12 10:49 UTC251
                if self.girth_respected() {
8b8e83329a1datagen2026-10-12 12:01 UTC252
                    self.notices.push(Notice::GymStaffLeaveIt);
058650ec79d6atagen2026-10-12 10:49 UTC253
                    return Ok(());
058650ec79d6atagen2026-10-12 10:49 UTC254
                }
8b8e83329a1datagen2026-10-12 12:01 UTC255
                self.standing.shame += 5;
782069860236atagen2026-10-10 12:44 UTC256
                Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC257
                    StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS,
782069860236atagen2026-10-10 12:44 UTC258
                    "gym-staff",
782069860236atagen2026-10-10 12:44 UTC259
                    "Gym staff have been notified. The server cannot serve this request for legal reasons.",
782069860236atagen2026-10-10 12:44 UTC260
                ))
782069860236atagen2026-10-10 12:44 UTC261
            }
782069860236atagen2026-10-10 12:44 UTC262
            Floor::Hotel => {
8b8e83329a1datagen2026-10-12 12:01 UTC263
                self.standing.suspicion = 0;
782069860236atagen2026-10-10 12:44 UTC264
                self.touch();
8b8e83329a1datagen2026-10-12 12:01 UTC265
                if self.items.kit.dnd_sign {
8b8e83329a1datagen2026-10-12 12:01 UTC266
                    self.notices.push(Notice::HousekeepingReadTheSign);
782069860236atagen2026-10-10 12:44 UTC267
                    return Ok(());
782069860236atagen2026-10-10 12:44 UTC268
                }
8b8e83329a1datagen2026-10-12 12:01 UTC269
                self.standing.shame += 3;
782069860236atagen2026-10-10 12:44 UTC270
                Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC271
                    StatusCode::UNAUTHORIZED,
782069860236atagen2026-10-10 12:44 UTC272
                    "housekeeping",
782069860236atagen2026-10-10 12:44 UTC273
                    "Housekeeping has entered. Housekeeping accepts no excuses.",
782069860236atagen2026-10-10 12:44 UTC274
                )
782069860236atagen2026-10-10 12:44 UTC275
                .header(header::WWW_AUTHENTICATE, "Excuse realm=\"housekeeping\""))
782069860236atagen2026-10-10 12:44 UTC276
            }
782069860236atagen2026-10-10 12:44 UTC277
            _ => Ok(()),
782069860236atagen2026-10-10 12:44 UTC278
        }
782069860236atagen2026-10-10 12:44 UTC279
    }
782069860236atagen2026-10-10 12:44 UTC280
}