atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
0fdc47364c8c704925ae62ea9b987075d6aa022d
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/state.rsRust253 lines6.6 KB
1
use axum::http::StatusCode;
2
3
use crate::problem::Problem;
4
5
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
6
#[repr(u8)]
7
pub enum Floor {
8
    Bedroom = 1,
9
    Bathroom = 2,
10
    ChangingRoom = 3,
11
    Nans = 4,
12
    Hotel = 5,
13
    Forum = 6,
14
    Clinic = 7,
15
}
16
17
impl Floor {
18
    pub fn number(self) -> u8 {
19
        self as u8
20
    }
21
22
    pub fn next(self) -> Option<Self> {
23
        match self {
24
            Self::Bedroom => Some(Self::Bathroom),
25
            Self::Bathroom => Some(Self::ChangingRoom),
26
            Self::ChangingRoom => Some(Self::Nans),
27
            Self::Nans => Some(Self::Hotel),
28
            Self::Hotel => Some(Self::Forum),
29
            Self::Forum => Some(Self::Clinic),
30
            Self::Clinic => None,
31
        }
32
    }
33
34
    pub fn name(self) -> &'static str {
35
        match self {
36
            Self::Bedroom => "the bedroom",
37
            Self::Bathroom => "the shared bathroom",
38
            Self::ChangingRoom => "the gym changing room",
39
            Self::Nans => "Nan's house at Christmas",
40
            Self::Hotel => "a business trip hotel",
41
            Self::Forum => "the forum",
42
            Self::Clinic => "the urologist's office",
43
        }
44
    }
45
46
    pub fn note(self) -> &'static str {
47
        match self {
48
            Self::Bedroom => "The door does not lock. The cat is present.",
49
            Self::Bathroom => "The water is hot. Your brother showers at eight.",
50
            Self::ChangingRoom => {
51
                "It is cold. Discretion is advised. Everyone here is lying. Pump-Bro is by the lockers."
52
            }
53
            Self::Nans => {
54
                "The walls are thin. Mum is here, and she has been reading about Digest authentication."
55
            }
56
            Self::Hotel => {
57
                "The wifi requires agreement. Housekeeping does not knock. Pump-Bro is in the lobby."
58
            }
59
            Self::Forum => "Nothing physical happens here. The Elder has a spreadsheet.",
60
            Self::Clinic => "The urologist will see you now. He is bored.",
61
        }
62
    }
63
64
    pub fn observer(self) -> Option<Observer> {
65
        match self {
66
            Self::Bedroom => Some(Observer::Cat),
67
            Self::ChangingRoom => Some(Observer::Greg),
68
            Self::Nans => Some(Observer::Nan),
69
            _ => None,
70
        }
71
    }
72
73
    pub fn has_mum(self) -> bool {
74
        matches!(self, Self::Bedroom | Self::Nans)
75
    }
76
77
    pub fn has_window(self) -> bool {
78
        matches!(self, Self::Bedroom | Self::Nans | Self::Hotel)
79
    }
80
81
    pub fn shop_open(self) -> bool {
82
        matches!(self, Self::ChangingRoom | Self::Hotel)
83
    }
84
85
    pub fn timed(self) -> bool {
86
        !matches!(self, Self::Forum | Self::Clinic)
87
    }
88
}
89
90
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
91
pub enum Observer {
92
    Cat,
93
    Greg,
94
    Nan,
95
}
96
97
impl Observer {
98
    pub fn name(self) -> &'static str {
99
        match self {
100
            Self::Cat => "cat",
101
            Self::Greg => "greg",
102
            Self::Nan => "nan",
103
        }
104
    }
105
}
106
107
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
108
pub enum Grip {
109
    Overhand,
110
    Underhand,
111
}
112
113
impl Grip {
114
    pub fn name(self) -> &'static str {
115
        match self {
116
            Self::Overhand => "overhand",
117
            Self::Underhand => "underhand",
118
        }
119
    }
120
121
    pub fn parse(protocol: &str) -> Option<Self> {
122
        match protocol.to_ascii_lowercase().as_str() {
123
            "overhand" => Some(Self::Overhand),
124
            "underhand" => Some(Self::Underhand),
125
            _ => None,
126
        }
127
    }
128
}
129
130
/// State that belongs to the current floor and resets when you leave it.
131
#[derive(Default)]
132
pub struct FloorState {
133
    pub turns: u32,
134
    pub drawer_searches: u8,
135
    pub edges: u8,
136
    pub temp_length: f64,
137
    pub teapot: bool,
138
    pub towel_stolen: bool,
139
    pub brother_told: bool,
140
    pub shopping: bool,
141
    pub meditated: bool,
142
    pub wifi_accepted: bool,
143
}
144
145
#[derive(Default)]
146
pub struct Conditions {
147
    pub peyronie: bool,
148
    pub pulled_muscle: bool,
149
    pub priapism_turns: u8,
150
}
151
152
pub struct MumVisit {
153
    pub errand: &'static str,
154
    pub nonce: String,
155
    pub strikes: u8,
156
    pub knocked: bool,
157
}
158
159
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
160
pub enum Elder {
161
    Unverified { strikes: u8 },
162
    Verified,
163
    Beaten,
164
}
165
166
#[derive(Default)]
167
pub struct Clinic {
168
    pub intake_attempts: usize,
169
    pub measured: bool,
170
    pub cured: bool,
171
}
172
173
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
174
pub enum Story {
175
    Unopened,
176
    Pending,
177
    ReadForum,
178
    ClosedTab,
179
}
180
181
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
182
pub enum Cause {
183
    Ruptured { ice_unused: bool },
184
    Caught,
185
    Opened,
186
    Banned,
187
    Degloved,
188
    Zip,
189
    Abandoned,
190
}
191
192
impl Cause {
193
    pub fn slug(self) -> &'static str {
194
        match self {
195
            Self::Ruptured { .. } => "vascular-event",
196
            Self::Caught => "caught",
197
            Self::Opened => "opened",
198
            Self::Banned => "banned",
199
            Self::Degloved => "degloved",
200
            Self::Zip => "zip",
201
            Self::Abandoned => "abandoned",
202
        }
203
    }
204
205
    pub fn detail(self) -> &'static str {
206
        match self {
207
            Self::Ruptured { ice_unused: true } => {
208
                "A vessel has exceeded its rated pressure. The run has ended. An ice pack was available and was not used."
209
            }
210
            Self::Ruptured { ice_unused: false } => {
211
                "A vessel has exceeded its rated pressure. The run has ended."
212
            }
213
            Self::Caught => {
214
                "Mum has seen enough. The run has ended. Nobody will mention it at dinner."
215
            }
216
            Self::Opened => {
217
                "Mum has stopped knocking and opened the door. The run has ended. Nobody will mention it at dinner."
218
            }
219
            Self::Banned => "Your account has been banned. The forum can tell. The run has ended.",
220
            Self::Degloved => {
221
                "The outer layer has been removed in one piece. It will not be returning. The run has ended."
222
            }
223
            Self::Zip => {
224
                "The request conflicts with the current state of the zip. The run has ended."
225
            }
226
            Self::Abandoned => "The run was abandoned.",
227
        }
228
    }
229
230
    fn status(self) -> StatusCode {
231
        match self {
232
            Self::Ruptured { .. } => StatusCode::INTERNAL_SERVER_ERROR,
233
            Self::Caught | Self::Opened | Self::Degloved | Self::Abandoned => StatusCode::GONE,
234
            Self::Banned => StatusCode::FORBIDDEN,
235
            Self::Zip => StatusCode::CONFLICT,
236
        }
237
    }
238
239
    pub fn problem(self) -> Problem {
240
        Problem::new(self.status(), self.slug(), self.detail())
241
    }
242
}
243
244
pub struct Ending {
245
    pub cause: Cause,
246
    pub turn: u32,
247
}
248
249
pub struct Pending {
250
    pub due: u32,
251
    pub length: f64,
252
    pub girth: f64,
253
}