atagen

jelq

public

an http based roguelike rpg about jelqing

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

Blame: src/game/utility.rs

782069860236atagen2026-10-10 12:44 UTC1
use std::{
782069860236atagen2026-10-10 12:44 UTC2
    ops::ControlFlow,
782069860236atagen2026-10-10 12:44 UTC3
    time::{Duration, Instant, SystemTime},
782069860236atagen2026-10-10 12:44 UTC4
};
782069860236atagen2026-10-10 12:44 UTC5
782069860236atagen2026-10-10 12:44 UTC6
use axum::http::{StatusCode, header};
782069860236atagen2026-10-10 12:44 UTC7
use serde_json::json;
782069860236atagen2026-10-10 12:44 UTC8
782069860236atagen2026-10-10 12:44 UTC9
use super::{
782069860236atagen2026-10-10 12:44 UTC10
    Floor, Outcome, Run,
782069860236atagen2026-10-10 12:44 UTC11
    balance::{
0a0bfee8329eatagen2026-10-11 05:11 UTC12
        EDGE_EQ, EDGE_GIRTH, EDGE_LOOP, ENERGY_STAMINA, HOTEL_STRESS, ICE_EQ, PRIAPISM_EQ,
0a0bfee8329eatagen2026-10-11 05:11 UTC13
        PRIAPISM_TURNS, PUMP_GAIN, SHOWER_EQ, SUPPLEMENT_WORKS, TOWELLESS_EQ, WARMUP_EQ,
782069860236atagen2026-10-10 12:44 UTC14
    },
782069860236atagen2026-10-10 12:44 UTC15
};
782069860236atagen2026-10-10 12:44 UTC16
use crate::problem::Problem;
782069860236atagen2026-10-10 12:44 UTC17
782069860236atagen2026-10-10 12:44 UTC18
const WEEK: Duration = Duration::from_secs(7 * 24 * 60 * 60);
782069860236atagen2026-10-10 12:44 UTC19
782069860236atagen2026-10-10 12:44 UTC20
impl Run {
782069860236atagen2026-10-10 12:44 UTC21
    pub(super) fn warm_up(&mut self) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC22
        if self.floor == Floor::Hotel && self.chance(HOTEL_STRESS) {
782069860236atagen2026-10-10 12:44 UTC23
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC24
                StatusCode::SERVICE_UNAVAILABLE,
782069860236atagen2026-10-10 12:44 UTC25
                "service-unavailable",
782069860236atagen2026-10-10 12:44 UTC26
                "Service is unavailable. The server estimates next week. The server is being pessimistic.",
782069860236atagen2026-10-10 12:44 UTC27
            )
782069860236atagen2026-10-10 12:44 UTC28
            .header(
782069860236atagen2026-10-10 12:44 UTC29
                header::RETRY_AFTER,
782069860236atagen2026-10-10 12:44 UTC30
                httpdate::fmt_http_date(SystemTime::now() + WEEK),
782069860236atagen2026-10-10 12:44 UTC31
            ));
782069860236atagen2026-10-10 12:44 UTC32
        }
782069860236atagen2026-10-10 12:44 UTC33
        let (boost, detail) = if self.floor == Floor::Bathroom {
782069860236atagen2026-10-10 12:44 UTC34
            (
782069860236atagen2026-10-10 12:44 UTC35
                SHOWER_EQ,
7d3fb63208bfatagen2026-10-11 04:38 UTC36
                "Warmed up. The shower is hot. Your brother's will not be.",
782069860236atagen2026-10-10 12:44 UTC37
            )
782069860236atagen2026-10-10 12:44 UTC38
        } else if self.here.towel_stolen {
782069860236atagen2026-10-10 12:44 UTC39
            (TOWELLESS_EQ, "Warmed up, poorly. The cat has the towel.")
782069860236atagen2026-10-10 12:44 UTC40
        } else {
782069860236atagen2026-10-10 12:44 UTC41
            (WARMUP_EQ, "Warmed up. The towel has cooled.")
782069860236atagen2026-10-10 12:44 UTC42
        };
782069860236atagen2026-10-10 12:44 UTC43
        self.touch();
782069860236atagen2026-10-10 12:44 UTC44
        self.warmed_up = true;
782069860236atagen2026-10-10 12:44 UTC45
        self.eq = (self.eq + boost).min(100);
782069860236atagen2026-10-10 12:44 UTC46
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
782069860236atagen2026-10-10 12:44 UTC47
    }
782069860236atagen2026-10-10 12:44 UTC48
782069860236atagen2026-10-10 12:44 UTC49
    pub(super) fn ice(&mut self) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC50
        if self.items.ice_packs == 0 {
782069860236atagen2026-10-10 12:44 UTC51
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC52
                StatusCode::FAILED_DEPENDENCY,
782069860236atagen2026-10-10 12:44 UTC53
                "no-ice",
782069860236atagen2026-10-10 12:44 UTC54
                "The ice technique depends on an ice pack. There are none.",
782069860236atagen2026-10-10 12:44 UTC55
            ));
782069860236atagen2026-10-10 12:44 UTC56
        }
782069860236atagen2026-10-10 12:44 UTC57
        self.touch();
782069860236atagen2026-10-10 12:44 UTC58
        self.items.ice_packs -= 1;
782069860236atagen2026-10-10 12:44 UTC59
        if self.conditions.priapism_turns > 0 {
782069860236atagen2026-10-10 12:44 UTC60
            return Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC61
                StatusCode::OK,
782069860236atagen2026-10-10 12:44 UTC62
                json!({ "detail": "The ice has no effect. The condition persists. The ice pack is gone." }),
782069860236atagen2026-10-10 12:44 UTC63
            ));
782069860236atagen2026-10-10 12:44 UTC64
        }
782069860236atagen2026-10-10 12:44 UTC65
        self.eq = (self.eq - ICE_EQ).max(0);
782069860236atagen2026-10-10 12:44 UTC66
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC67
            StatusCode::OK,
782069860236atagen2026-10-10 12:44 UTC68
            json!({ "detail": "EQ has been reduced. The ice pack is gone." }),
782069860236atagen2026-10-10 12:44 UTC69
        ))
782069860236atagen2026-10-10 12:44 UTC70
    }
782069860236atagen2026-10-10 12:44 UTC71
0a0bfee8329eatagen2026-10-11 05:11 UTC72
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
0a0bfee8329eatagen2026-10-11 05:11 UTC73
        if self.items.energy_drinks == 0 {
0a0bfee8329eatagen2026-10-11 05:11 UTC74
            return Err(Problem::new(
0a0bfee8329eatagen2026-10-11 05:11 UTC75
                StatusCode::FAILED_DEPENDENCY,
0a0bfee8329eatagen2026-10-11 05:11 UTC76
                "no-energy-drink",
0a0bfee8329eatagen2026-10-11 05:11 UTC77
                "The energy technique depends on an energy drink.",
0a0bfee8329eatagen2026-10-11 05:11 UTC78
            ));
0a0bfee8329eatagen2026-10-11 05:11 UTC79
        }
0a0bfee8329eatagen2026-10-11 05:11 UTC80
        self.items.energy_drinks -= 1;
0a0bfee8329eatagen2026-10-11 05:11 UTC81
        self.stamina = (self.stamina + ENERGY_STAMINA).min(self.max_stamina());
0a0bfee8329eatagen2026-10-11 05:11 UTC82
        self.touch();
0a0bfee8329eatagen2026-10-11 05:11 UTC83
        Ok(Outcome::json(
0a0bfee8329eatagen2026-10-11 05:11 UTC84
            StatusCode::OK,
0a0bfee8329eatagen2026-10-11 05:11 UTC85
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
0a0bfee8329eatagen2026-10-11 05:11 UTC86
        ))
0a0bfee8329eatagen2026-10-11 05:11 UTC87
    }
0a0bfee8329eatagen2026-10-11 05:11 UTC88
782069860236atagen2026-10-10 12:44 UTC89
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC90
        if self.items.supplements == 0 {
782069860236atagen2026-10-10 12:44 UTC91
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC92
                StatusCode::FAILED_DEPENDENCY,
782069860236atagen2026-10-10 12:44 UTC93
                "no-supplement",
782069860236atagen2026-10-10 12:44 UTC94
                "The supplement technique depends on a supplement.",
782069860236atagen2026-10-10 12:44 UTC95
            ));
782069860236atagen2026-10-10 12:44 UTC96
        }
782069860236atagen2026-10-10 12:44 UTC97
        self.items.supplements -= 1;
782069860236atagen2026-10-10 12:44 UTC98
        self.touch();
782069860236atagen2026-10-10 12:44 UTC99
        if self.chance(SUPPLEMENT_WORKS) {
0a0bfee8329eatagen2026-10-11 05:11 UTC100
            self.stamina = self.max_stamina();
782069860236atagen2026-10-10 12:44 UTC101
            self.conditions.priapism_turns = PRIAPISM_TURNS;
782069860236atagen2026-10-10 12:44 UTC102
            self.eq = self.eq.max(PRIAPISM_EQ);
782069860236atagen2026-10-10 12:44 UTC103
            return Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC104
                StatusCode::OK,
0a0bfee8329eatagen2026-10-11 05:11 UTC105
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
782069860236atagen2026-10-10 12:44 UTC106
            ));
782069860236atagen2026-10-10 12:44 UTC107
        }
782069860236atagen2026-10-10 12:44 UTC108
        Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC109
            StatusCode::BAD_GATEWAY,
782069860236atagen2026-10-10 12:44 UTC110
            "bad-gateway",
782069860236atagen2026-10-10 12:44 UTC111
            "The upstream returned an invalid response.",
782069860236atagen2026-10-10 12:44 UTC112
        )
782069860236atagen2026-10-10 12:44 UTC113
        .with("upstream", "Pump-Bro"))
782069860236atagen2026-10-10 12:44 UTC114
    }
782069860236atagen2026-10-10 12:44 UTC115
782069860236atagen2026-10-10 12:44 UTC116
    pub(super) fn edge(&mut self, now: Instant) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC117
        self.commit(5, None, now, 1);
782069860236atagen2026-10-10 12:44 UTC118
        self.here.edges += 1;
782069860236atagen2026-10-10 12:44 UTC119
        self.eq = (self.eq + EDGE_EQ).min(100);
782069860236atagen2026-10-10 12:44 UTC120
        self.girth += EDGE_GIRTH;
782069860236atagen2026-10-10 12:44 UTC121
        if self.here.edges >= EDGE_LOOP {
782069860236atagen2026-10-10 12:44 UTC122
            self.here.edges = 0;
782069860236atagen2026-10-10 12:44 UTC123
            self.exhaust(now);
782069860236atagen2026-10-10 12:44 UTC124
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC125
                StatusCode::LOOP_DETECTED,
782069860236atagen2026-10-10 12:44 UTC126
                "edging-loop",
782069860236atagen2026-10-10 12:44 UTC127
                "Edging has looped. The server detected an infinite loop and terminated it.",
782069860236atagen2026-10-10 12:44 UTC128
            ));
782069860236atagen2026-10-10 12:44 UTC129
        }
782069860236atagen2026-10-10 12:44 UTC130
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
782069860236atagen2026-10-10 12:44 UTC131
            return Ok(interrupted);
782069860236atagen2026-10-10 12:44 UTC132
        }
782069860236atagen2026-10-10 12:44 UTC133
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC134
            StatusCode::OK,
782069860236atagen2026-10-10 12:44 UTC135
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
782069860236atagen2026-10-10 12:44 UTC136
        ))
782069860236atagen2026-10-10 12:44 UTC137
    }
782069860236atagen2026-10-10 12:44 UTC138
782069860236atagen2026-10-10 12:44 UTC139
    pub(super) fn pump(&mut self, now: Instant) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC140
        self.commit(4, None, now, 1);
782069860236atagen2026-10-10 12:44 UTC141
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
782069860236atagen2026-10-10 12:44 UTC142
            return Ok(interrupted);
782069860236atagen2026-10-10 12:44 UTC143
        }
782069860236atagen2026-10-10 12:44 UTC144
        self.here.temp_length += PUMP_GAIN;
782069860236atagen2026-10-10 12:44 UTC145
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC146
            StatusCode::TEMPORARY_REDIRECT,
782069860236atagen2026-10-10 12:44 UTC147
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
782069860236atagen2026-10-10 12:44 UTC148
        )
782069860236atagen2026-10-10 12:44 UTC149
        .header(header::LOCATION, self.path("/length")))
782069860236atagen2026-10-10 12:44 UTC150
    }
782069860236atagen2026-10-10 12:44 UTC151
}