atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
b85a0d4536c3b294547a682ac046d8a38beb47a3
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/utility.rsRust154 lines5.5 KB
1
use std::{
2
    ops::ControlFlow,
3
    time::{Duration, Instant, SystemTime},
4
};
5
6
use axum::http::{StatusCode, header};
7
use serde_json::json;
8
9
use super::{
10
    Floor, Outcome, Run,
11
    balance::{
12
        EDGE_EQ, EDGE_GIRTH, EDGE_LOOP, ENERGY_STAMINA, HOTEL_STRESS, ICE_EQ, PRIAPISM_EQ,
13
        PRIAPISM_TURNS, PUMP_GAIN, SHOWER_EQ, SUPPLEMENT_WORKS, TOWELLESS_EQ, WARMUP_EQ,
14
    },
15
};
16
use crate::problem::Problem;
17
18
const WEEK: Duration = Duration::from_secs(7 * 24 * 60 * 60);
19
20
impl Run {
21
    pub(super) fn warm_up(&mut self) -> Result<Outcome, Problem> {
22
        if self.floor == Floor::Hotel && self.chance(HOTEL_STRESS) {
23
            return Err(Problem::new(
24
                StatusCode::SERVICE_UNAVAILABLE,
25
                "service-unavailable",
26
                "Service is unavailable. The server estimates next week. The server is being pessimistic.",
27
            )
28
            .header(
29
                header::RETRY_AFTER,
30
                httpdate::fmt_http_date(SystemTime::now() + WEEK),
31
            ));
32
        }
33
        let (boost, detail) = if self.floor == Floor::Bathroom {
34
            (
35
                SHOWER_EQ,
36
                "Warmed up. The shower is hot. Your brother's will not be.",
37
            )
38
        } else if self.here.towel_stolen {
39
            (TOWELLESS_EQ, "Warmed up, poorly. The cat has the towel.")
40
        } else {
41
            (WARMUP_EQ, "Warmed up. The towel has cooled.")
42
        };
43
        self.touch();
44
        self.warmed_up = true;
45
        self.eq = (self.eq + boost).min(100);
46
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
47
    }
48
49
    pub(super) fn ice(&mut self) -> Result<Outcome, Problem> {
50
        if self.items.ice_packs == 0 {
51
            return Err(Problem::new(
52
                StatusCode::FAILED_DEPENDENCY,
53
                "no-ice",
54
                "The ice technique depends on an ice pack. There are none.",
55
            ));
56
        }
57
        self.touch();
58
        self.items.ice_packs -= 1;
59
        if self.conditions.priapism_turns > 0 {
60
            return Ok(Outcome::json(
61
                StatusCode::OK,
62
                json!({ "detail": "The ice has no effect. The condition persists. The ice pack is gone." }),
63
            ));
64
        }
65
        self.eq = (self.eq - ICE_EQ).max(0);
66
        let detail = if self.conditions.friction_burn {
67
            self.conditions.friction_burn = false;
68
            "The friction burn is treated. EQ has been reduced. The ice pack is gone."
69
        } else {
70
            "EQ has been reduced. The ice pack is gone."
71
        };
72
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
73
    }
74
75
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
76
        if self.items.energy_drinks == 0 {
77
            return Err(Problem::new(
78
                StatusCode::FAILED_DEPENDENCY,
79
                "no-energy-drink",
80
                "The energy technique depends on an energy drink.",
81
            ));
82
        }
83
        self.items.energy_drinks -= 1;
84
        self.stamina = (self.stamina + ENERGY_STAMINA).min(self.max_stamina());
85
        self.touch();
86
        Ok(Outcome::json(
87
            StatusCode::OK,
88
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
89
        ))
90
    }
91
92
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
93
        if self.items.supplements == 0 {
94
            return Err(Problem::new(
95
                StatusCode::FAILED_DEPENDENCY,
96
                "no-supplement",
97
                "The supplement technique depends on a supplement.",
98
            ));
99
        }
100
        self.items.supplements -= 1;
101
        self.touch();
102
        if self.chance(SUPPLEMENT_WORKS) {
103
            self.stamina = self.max_stamina();
104
            self.conditions.priapism_turns = PRIAPISM_TURNS;
105
            self.eq = self.eq.max(PRIAPISM_EQ);
106
            return Ok(Outcome::json(
107
                StatusCode::OK,
108
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
109
            ));
110
        }
111
        Err(Problem::new(
112
            StatusCode::BAD_GATEWAY,
113
            "bad-gateway",
114
            "The upstream returned an invalid response.",
115
        )
116
        .with("upstream", "Pump-Bro"))
117
    }
118
119
    pub(super) fn edge(&mut self, now: Instant) -> Result<Outcome, Problem> {
120
        self.commit(5, None, now, 1);
121
        self.here.edges += 1;
122
        self.eq = (self.eq + EDGE_EQ).min(100);
123
        self.girth += EDGE_GIRTH;
124
        if self.here.edges >= EDGE_LOOP {
125
            self.here.edges = 0;
126
            self.exhaust(now);
127
            return Err(Problem::new(
128
                StatusCode::LOOP_DETECTED,
129
                "edging-loop",
130
                "Edging has looped. The server detected an infinite loop and terminated it.",
131
            ));
132
        }
133
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
134
            return Ok(interrupted);
135
        }
136
        Ok(Outcome::json(
137
            StatusCode::OK,
138
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
139
        ))
140
    }
141
142
    pub(super) fn pump(&mut self, now: Instant) -> Result<Outcome, Problem> {
143
        self.commit(4, None, now, 1);
144
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
145
            return Ok(interrupted);
146
        }
147
        self.here.temp_length += PUMP_GAIN;
148
        Ok(Outcome::json(
149
            StatusCode::TEMPORARY_REDIRECT,
150
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
151
        )
152
        .header(header::LOCATION, self.path("/length")))
153
    }
154
}