atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
0a0bfee8329e7283a802b33eb4365c2bf4c433b9
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/utility.rsRust151 lines5.3 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
        Ok(Outcome::json(
67
            StatusCode::OK,
68
            json!({ "detail": "EQ has been reduced. The ice pack is gone." }),
69
        ))
70
    }
71
72
    pub(super) fn energy(&mut self) -> Result<Outcome, Problem> {
73
        if self.items.energy_drinks == 0 {
74
            return Err(Problem::new(
75
                StatusCode::FAILED_DEPENDENCY,
76
                "no-energy-drink",
77
                "The energy technique depends on an energy drink.",
78
            ));
79
        }
80
        self.items.energy_drinks -= 1;
81
        self.stamina = (self.stamina + ENERGY_STAMINA).min(self.max_stamina());
82
        self.touch();
83
        Ok(Outcome::json(
84
            StatusCode::OK,
85
            json!({ "detail": "The energy arrives before the regret. Stamina +3." }),
86
        ))
87
    }
88
89
    pub(super) fn supplement(&mut self) -> Result<Outcome, Problem> {
90
        if self.items.supplements == 0 {
91
            return Err(Problem::new(
92
                StatusCode::FAILED_DEPENDENCY,
93
                "no-supplement",
94
                "The supplement technique depends on a supplement.",
95
            ));
96
        }
97
        self.items.supplements -= 1;
98
        self.touch();
99
        if self.chance(SUPPLEMENT_WORKS) {
100
            self.stamina = self.max_stamina();
101
            self.conditions.priapism_turns = PRIAPISM_TURNS;
102
            self.eq = self.eq.max(PRIAPISM_EQ);
103
            return Ok(Outcome::json(
104
                StatusCode::OK,
105
                json!({ "detail": "The upstream returned a valid response. It is still returning it. Stamina is fully restored." }),
106
            ));
107
        }
108
        Err(Problem::new(
109
            StatusCode::BAD_GATEWAY,
110
            "bad-gateway",
111
            "The upstream returned an invalid response.",
112
        )
113
        .with("upstream", "Pump-Bro"))
114
    }
115
116
    pub(super) fn edge(&mut self, now: Instant) -> Result<Outcome, Problem> {
117
        self.commit(5, None, now, 1);
118
        self.here.edges += 1;
119
        self.eq = (self.eq + EDGE_EQ).min(100);
120
        self.girth += EDGE_GIRTH;
121
        if self.here.edges >= EDGE_LOOP {
122
            self.here.edges = 0;
123
            self.exhaust(now);
124
            return Err(Problem::new(
125
                StatusCode::LOOP_DETECTED,
126
                "edging-loop",
127
                "Edging has looped. The server detected an infinite loop and terminated it.",
128
            ));
129
        }
130
        if let ControlFlow::Break(interrupted) = self.hazards(5)? {
131
            return Ok(interrupted);
132
        }
133
        Ok(Outcome::json(
134
            StatusCode::OK,
135
            json!({ "detail": "Edged. EQ is rising. Nothing else is.", "edges": self.here.edges }),
136
        ))
137
    }
138
139
    pub(super) fn pump(&mut self, now: Instant) -> Result<Outcome, Problem> {
140
        self.commit(4, None, now, 1);
141
        if let ControlFlow::Break(interrupted) = self.hazards(4)? {
142
            return Ok(interrupted);
143
        }
144
        self.here.temp_length += PUMP_GAIN;
145
        Ok(Outcome::json(
146
            StatusCode::TEMPORARY_REDIRECT,
147
            json!({ "detail": "Gains applied. They are temporary.", "length": PUMP_GAIN }),
148
        )
149
        .header(header::LOCATION, self.path("/length")))
150
    }
151
}