atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
cddf59e37d5f7b2a7e0f8b644252196caf5a7e97
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/utility.rsRust184 lines6.5 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
        if self.body.conditions.priapism_turns > 0 {
80
            return Ok(Outcome::json(
81
                StatusCode::OK,
82
                json!({ "detail": "The ice has no effect. The condition persists. The ice pack is gone." }),
83
            ));
84
        }
85
        self.body.eq = (self.body.eq - ICE_EQ).max(0);
86
        let detail = if self.body.conditions.friction_burn {
87
            self.body.conditions.friction_burn = false;
88
            "The friction burn is treated. EQ has been reduced. The ice pack is gone."
89
        } else {
90
            "EQ has been reduced. The ice pack is gone."
91
        };
92
        Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail })))
93
    }
94
95
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
96
        if self.items.stores.energy_drinks == 0 {
97
            return Err(Problem::new(
98
                StatusCode::FAILED_DEPENDENCY,
99
                "no-energy-drink",
100
                "The energy technique depends on an energy drink.",
101
            ));
102
        }
103
        self.items.stores.energy_drinks -= 1;
104
        self.step_away();
105
        self.body.exhausted = false;
106
        self.body.stamina = (self.body.stamina + ENERGY_STAMINA).min(self.max_stamina());
107
        self.touch();
108
        Ok(Outcome::json(
109
            StatusCode::OK,
110
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
111
        ))
112
    }
113
114
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
115
        if self.items.stores.supplements == 0 {
116
            return Err(Problem::new(
117
                StatusCode::FAILED_DEPENDENCY,
118
                "no-supplement",
119
                "The supplement technique depends on a supplement.",
120
            ));
121
        }
122
        self.items.stores.supplements -= 1;
123
        self.step_away();
124
        self.touch();
125
        if self.chance(
126
            self.decision(
127
                "supplement",
128
                "Does the supplement from Pump-Bro actually work?",
129
            ),
130
            SUPPLEMENT_WORKS,
131
        ) {
132
            self.body.stamina = self.max_stamina();
133
            self.body.conditions.priapism_turns = PRIAPISM_TURNS;
134
            self.body.eq = self.body.eq.max(PRIAPISM_EQ);
135
            return Ok(Outcome::json(
136
                StatusCode::OK,
137
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
138
            ));
139
        }
140
        Err(Problem::new(
141
            StatusCode::BAD_GATEWAY,
142
            "bad-gateway",
143
            "The upstream returned an invalid response.",
144
        )
145
        .with("upstream", "Pump-Bro"))
146
    }
147
148
    pub(super) fn edge(&mut self) -> Result<Outcome, Problem> {
149
        self.chafe(None, 5, false);
150
        self.commit(5, None, 1)?;
151
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
152
            return Ok(interrupted);
153
        }
154
        self.here.edges += 1;
155
        self.body.eq = (self.body.eq + EDGE_EQ).min(100);
156
        self.body.girth += EDGE_GIRTH;
157
        if self.here.edges >= EDGE_LOOP {
158
            self.here.edges = 0;
159
            self.exhaust();
160
            return Err(Problem::new(
161
                StatusCode::LOOP_DETECTED,
162
                "edging-loop",
163
                "Edging has looped. The server detected an infinite loop and terminated it.",
164
            ));
165
        }
166
        Ok(Outcome::json(
167
            StatusCode::OK,
168
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
169
        ))
170
    }
171
172
    pub(super) fn pump(&mut self) -> Result<Outcome, Problem> {
173
        self.commit(4, None, 1)?;
174
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
175
            return Ok(interrupted);
176
        }
177
        self.here.temp_length += PUMP_GAIN;
178
        Ok(Outcome::json(
179
            StatusCode::TEMPORARY_REDIRECT,
180
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
181
        )
182
        .header(header::LOCATION, self.path("/length")))
183
    }
184
}