atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
6033b0db186c6ca62650ba0dcfdcc28747ad0174
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/utility.rsRust185 lines6.7 KB
1
use std::{
2
    ops::ControlFlow,
3
    time::{Duration, 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.here.towel_warmed && !self.here.kitchen.kettle_boiled {
23
            return Err(Problem::new(
24
                StatusCode::CONFLICT,
25
                "towel-cold",
26
                "The towel has gone cold. It warms once per floor, unless someone boils the kettle.",
27
            ));
28
        }
29
        if self.floor == Floor::Hotel
30
            && self.chance(
31
                self.decision(
32
                    "hotel-stress",
33
                    "Has the hotel's plumbing given up for the week?",
34
                ),
35
                HOTEL_STRESS,
36
            )
37
        {
38
            return Err(Problem::new(
39
                StatusCode::SERVICE_UNAVAILABLE,
40
                "service-unavailable",
41
                "Service is unavailable. The server estimates next week. The server is being pessimistic.",
42
            )
43
            .header(
44
                header::RETRY_AFTER,
45
                httpdate::fmt_http_date(SystemTime::now() + WEEK),
46
            ));
47
        }
48
        let (boost, detail) = if self.floor == Floor::Bathroom {
49
            (
50
                SHOWER_EQ,
51
                "Warmed up. The shower is hot. Your brother's will not be.",
52
            )
53
        } else if self.here.towel_stolen {
54
            (TOWELLESS_EQ, "Warmed up, poorly. The cat has the towel.")
55
        } else {
56
            (WARMUP_EQ, "Warmed up. The towel has cooled.")
57
        };
58
        self.touch();
59
        self.step_away();
60
        if self.here.towel_warmed {
61
            self.here.kitchen.kettle_boiled = false;
62
        }
63
        self.here.towel_warmed = true;
64
        self.body.eq = (self.body.eq + boost).min(100);
65
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
66
    }
67
68
    pub(super) fn ice(&mut self) -> Result<Outcome, Problem> {
69
        if self.items.stores.ice_packs == 0 {
70
            return Err(Problem::new(
71
                StatusCode::FAILED_DEPENDENCY,
72
                "no-ice",
73
                "The ice technique depends on an ice pack. There are none.",
74
            ));
75
        }
76
        self.touch();
77
        self.step_away();
78
        self.items.stores.ice_packs -= 1;
79
        let treated = std::mem::take(&mut self.body.conditions.friction_burn);
80
        let detail = match (self.body.conditions.priapism_turns > 0, treated) {
81
            (true, true) => {
82
                "The friction burn is treated. EQ has not moved. The condition persists. The ice pack is gone."
83
            }
84
            (true, false) => "The ice has no effect. The condition persists. The ice pack is gone.",
85
            (false, true) => {
86
                "The friction burn is treated. EQ has been reduced. The ice pack is gone."
87
            }
88
            (false, false) => "EQ has been reduced. The ice pack is gone.",
89
        };
90
        if self.body.conditions.priapism_turns == 0 {
91
            self.body.eq = (self.body.eq - ICE_EQ).max(0);
92
        }
93
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
94
    }
95
96
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
97
        if self.items.stores.energy_drinks == 0 {
98
            return Err(Problem::new(
99
                StatusCode::FAILED_DEPENDENCY,
100
                "no-energy-drink",
101
                "The energy technique depends on an energy drink.",
102
            ));
103
        }
104
        self.items.stores.energy_drinks -= 1;
105
        self.step_away();
106
        self.body.exhausted = false;
107
        self.body.stamina = (self.body.stamina + ENERGY_STAMINA).min(self.max_stamina());
108
        self.touch();
109
        Ok(Outcome::json(
110
            StatusCode::OK,
111
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
112
        ))
113
    }
114
115
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
116
        if self.items.stores.supplements == 0 {
117
            return Err(Problem::new(
118
                StatusCode::FAILED_DEPENDENCY,
119
                "no-supplement",
120
                "The supplement technique depends on a supplement.",
121
            ));
122
        }
123
        self.items.stores.supplements -= 1;
124
        self.step_away();
125
        self.touch();
126
        if self.chance(
127
            self.decision(
128
                "supplement",
129
                "Does the supplement from Pump-Bro actually work?",
130
            ),
131
            SUPPLEMENT_WORKS,
132
        ) {
133
            self.body.stamina = self.max_stamina();
134
            self.body.conditions.priapism_turns = PRIAPISM_TURNS;
135
            self.body.eq = self.body.eq.max(PRIAPISM_EQ);
136
            return Ok(Outcome::json(
137
                StatusCode::OK,
138
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
139
            ));
140
        }
141
        Err(Problem::new(
142
            StatusCode::BAD_GATEWAY,
143
            "bad-gateway",
144
            "The upstream returned an invalid response.",
145
        )
146
        .with("upstream", "Pump-Bro"))
147
    }
148
149
    pub(super) fn edge(&mut self) -> Result<Outcome, Problem> {
150
        self.chafe(None, 5, false);
151
        self.commit(5, None, 1)?;
152
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
153
            return Ok(interrupted);
154
        }
155
        self.here.edges += 1;
156
        self.body.eq = (self.body.eq + EDGE_EQ).min(100);
157
        self.body.girth += EDGE_GIRTH;
158
        if self.here.edges >= EDGE_LOOP {
159
            self.here.edges = 0;
160
            self.exhaust();
161
            return Err(Problem::new(
162
                StatusCode::LOOP_DETECTED,
163
                "edging-loop",
164
                "Edging has looped. The server detected an infinite loop and terminated it.",
165
            ));
166
        }
167
        Ok(Outcome::json(
168
            StatusCode::OK,
169
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
170
        ))
171
    }
172
173
    pub(super) fn pump(&mut self) -> Result<Outcome, Problem> {
174
        self.commit(4, None, 1)?;
175
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
176
            return Ok(interrupted);
177
        }
178
        self.here.temp_length += PUMP_GAIN;
179
        Ok(Outcome::json(
180
            StatusCode::TEMPORARY_REDIRECT,
181
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
182
        )
183
        .header(header::LOCATION, self.path("/length")))
184
    }
185
}