atagen

jelq

public

an http based roguelike rpg about jelqing

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