atagen

jelq

public

an http based roguelike rpg about jelqing

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