atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
5cc6ab966f30f5bc5611ddefd166242a46ff3954
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);
5dfebcc0ac43atagen2026-10-11 05:28 UTC66
        let detail = if self.conditions.friction_burn {
5dfebcc0ac43atagen2026-10-11 05:28 UTC67
            self.conditions.friction_burn = false;
5dfebcc0ac43atagen2026-10-11 05:28 UTC68
            "The friction burn is treated. EQ has been reduced. The ice pack is gone."
5dfebcc0ac43atagen2026-10-11 05:28 UTC69
        } else {
5dfebcc0ac43atagen2026-10-11 05:28 UTC70
            "EQ has been reduced. The ice pack is gone."
5dfebcc0ac43atagen2026-10-11 05:28 UTC71
        };
5dfebcc0ac43atagen2026-10-11 05:28 UTC72
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
782069860236atagen2026-10-10 12:44 UTC73
    }
782069860236atagen2026-10-10 12:44 UTC74
0a0bfee8329eatagen2026-10-11 05:11 UTC75
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
0a0bfee8329eatagen2026-10-11 05:11 UTC76
        if self.items.energy_drinks == 0 {
0a0bfee8329eatagen2026-10-11 05:11 UTC77
            return Err(Problem::new(
0a0bfee8329eatagen2026-10-11 05:11 UTC78
                StatusCode::FAILED_DEPENDENCY,
0a0bfee8329eatagen2026-10-11 05:11 UTC79
                "no-energy-drink",
0a0bfee8329eatagen2026-10-11 05:11 UTC80
                "The energy technique depends on an energy drink.",
0a0bfee8329eatagen2026-10-11 05:11 UTC81
            ));
0a0bfee8329eatagen2026-10-11 05:11 UTC82
        }
0a0bfee8329eatagen2026-10-11 05:11 UTC83
        self.items.energy_drinks -= 1;
0a0bfee8329eatagen2026-10-11 05:11 UTC84
        self.stamina = (self.stamina + ENERGY_STAMINA).min(self.max_stamina());
0a0bfee8329eatagen2026-10-11 05:11 UTC85
        self.touch();
0a0bfee8329eatagen2026-10-11 05:11 UTC86
        Ok(Outcome::json(
0a0bfee8329eatagen2026-10-11 05:11 UTC87
            StatusCode::OK,
0a0bfee8329eatagen2026-10-11 05:11 UTC88
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
0a0bfee8329eatagen2026-10-11 05:11 UTC89
        ))
0a0bfee8329eatagen2026-10-11 05:11 UTC90
    }
0a0bfee8329eatagen2026-10-11 05:11 UTC91
782069860236atagen2026-10-10 12:44 UTC92
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC93
        if self.items.supplements == 0 {
782069860236atagen2026-10-10 12:44 UTC94
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC95
                StatusCode::FAILED_DEPENDENCY,
782069860236atagen2026-10-10 12:44 UTC96
                "no-supplement",
782069860236atagen2026-10-10 12:44 UTC97
                "The supplement technique depends on a supplement.",
782069860236atagen2026-10-10 12:44 UTC98
            ));
782069860236atagen2026-10-10 12:44 UTC99
        }
782069860236atagen2026-10-10 12:44 UTC100
        self.items.supplements -= 1;
782069860236atagen2026-10-10 12:44 UTC101
        self.touch();
782069860236atagen2026-10-10 12:44 UTC102
        if self.chance(SUPPLEMENT_WORKS) {
0a0bfee8329eatagen2026-10-11 05:11 UTC103
            self.stamina = self.max_stamina();
782069860236atagen2026-10-10 12:44 UTC104
            self.conditions.priapism_turns = PRIAPISM_TURNS;
782069860236atagen2026-10-10 12:44 UTC105
            self.eq = self.eq.max(PRIAPISM_EQ);
782069860236atagen2026-10-10 12:44 UTC106
            return Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC107
                StatusCode::OK,
0a0bfee8329eatagen2026-10-11 05:11 UTC108
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
782069860236atagen2026-10-10 12:44 UTC109
            ));
782069860236atagen2026-10-10 12:44 UTC110
        }
782069860236atagen2026-10-10 12:44 UTC111
        Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC112
            StatusCode::BAD_GATEWAY,
782069860236atagen2026-10-10 12:44 UTC113
            "bad-gateway",
782069860236atagen2026-10-10 12:44 UTC114
            "The upstream returned an invalid response.",
782069860236atagen2026-10-10 12:44 UTC115
        )
782069860236atagen2026-10-10 12:44 UTC116
        .with("upstream", "Pump-Bro"))
782069860236atagen2026-10-10 12:44 UTC117
    }
782069860236atagen2026-10-10 12:44 UTC118
782069860236atagen2026-10-10 12:44 UTC119
    pub(super) fn edge(&mut self, now: Instant) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC120
        self.commit(5, None, now, 1);
782069860236atagen2026-10-10 12:44 UTC121
        self.here.edges += 1;
782069860236atagen2026-10-10 12:44 UTC122
        self.eq = (self.eq + EDGE_EQ).min(100);
782069860236atagen2026-10-10 12:44 UTC123
        self.girth += EDGE_GIRTH;
782069860236atagen2026-10-10 12:44 UTC124
        if self.here.edges >= EDGE_LOOP {
782069860236atagen2026-10-10 12:44 UTC125
            self.here.edges = 0;
782069860236atagen2026-10-10 12:44 UTC126
            self.exhaust(now);
782069860236atagen2026-10-10 12:44 UTC127
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC128
                StatusCode::LOOP_DETECTED,
782069860236atagen2026-10-10 12:44 UTC129
                "edging-loop",
782069860236atagen2026-10-10 12:44 UTC130
                "Edging has looped. The server detected an infinite loop and terminated it.",
782069860236atagen2026-10-10 12:44 UTC131
            ));
782069860236atagen2026-10-10 12:44 UTC132
        }
782069860236atagen2026-10-10 12:44 UTC133
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
782069860236atagen2026-10-10 12:44 UTC134
            return Ok(interrupted);
782069860236atagen2026-10-10 12:44 UTC135
        }
782069860236atagen2026-10-10 12:44 UTC136
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC137
            StatusCode::OK,
782069860236atagen2026-10-10 12:44 UTC138
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
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(super) fn pump(&mut self, now: Instant) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC143
        self.commit(4, None, now, 1);
782069860236atagen2026-10-10 12:44 UTC144
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
782069860236atagen2026-10-10 12:44 UTC145
            return Ok(interrupted);
782069860236atagen2026-10-10 12:44 UTC146
        }
782069860236atagen2026-10-10 12:44 UTC147
        self.here.temp_length += PUMP_GAIN;
782069860236atagen2026-10-10 12:44 UTC148
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC149
            StatusCode::TEMPORARY_REDIRECT,
782069860236atagen2026-10-10 12:44 UTC150
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
782069860236atagen2026-10-10 12:44 UTC151
        )
782069860236atagen2026-10-10 12:44 UTC152
        .header(header::LOCATION, self.path("/length")))
782069860236atagen2026-10-10 12:44 UTC153
    }
782069860236atagen2026-10-10 12:44 UTC154
}