atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
f16ab17c8ff6e8e90a8d6658a1fa79039509d7d7
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/drawer.rsRust161 lines5.6 KB
1
use super::{
2
    Floor, Item, Notice, Outcome, Run,
3
    balance::{BATHROOM_VASELINE, DRAWER_JAMS, GREGS_LOCKER, KEY_IN_DRAWER, RULER_IN_DRAWER},
4
};
5
use crate::problem::Problem;
6
use axum::http::{StatusCode, header};
7
use serde_json::json;
8
9
fn nothing() -> Result<Outcome, Problem> {
10
    Ok(Outcome::empty(StatusCode::NO_CONTENT))
11
}
12
13
impl Run {
14
    pub(super) fn found(&self, item: Item, detail: &str) -> Outcome {
15
        Outcome::json(StatusCode::FOUND, json!({ "detail": detail })).header(
16
            header::LOCATION,
17
            self.path(&format!("/inventory/{}", item.slug())),
18
        )
19
    }
20
21
    pub fn search_drawer(&mut self) -> Result<Outcome, Problem> {
22
        self.touch();
23
        self.end_kitchen_visit();
24
        if self.items.kit.cage {
25
            return Ok(self.rummage_for_key());
26
        }
27
        let first = !self.here.drawer.searched;
28
        self.here.drawer.searched = true;
29
        match self.floor {
30
            Floor::Bedroom => self.search_bedroom(first),
31
            Floor::Bathroom if first => Ok(self.search_bathroom()),
32
            Floor::ChangingRoom => self.search_locker(first),
33
            Floor::Nans if first => {
34
                self.items.grant(Item::Cage);
35
                self.standing.shame += 5;
36
                Ok(self.found(
37
                    Item::Cage,
38
                    "A small box. Inside was a cage. It is now on. The key is not in the box.",
39
                ))
40
            }
41
            Floor::Hotel if first => {
42
                for item in [Item::DndSign, Item::IcePack, Item::IcePack, Item::Lotion] {
43
                    self.items.grant(item);
44
                }
45
                Ok(self.found(
46
                    Item::DndSign,
47
                    "A Do Not Disturb sign, two ice packs from the machine down the hall, and a complimentary lotion.",
48
                ))
49
            }
50
            Floor::Forum if first => {
51
                self.items.grant(Item::Spreadsheet);
52
                Ok(self.found(
53
                    Item::Spreadsheet,
54
                    "Your own spreadsheet. Every line is flat.",
55
                ))
56
            }
57
            Floor::Clinic => Err(Problem::new(
58
                StatusCode::FORBIDDEN,
59
                "doctors-drawer",
60
                "That is the doctor's drawer.",
61
            )),
62
            _ => nothing(),
63
        }
64
    }
65
66
    fn search_bedroom(&mut self, first: bool) -> Result<Outcome, Problem> {
67
        let ruler_here = self.chance(
68
            self.decision("ruler", "Is there a ruler hiding in the drawer?"),
69
            RULER_IN_DRAWER,
70
        );
71
        if !first || self.items.kit.ruler || !ruler_here {
72
            return nothing();
73
        }
74
        self.items.grant(Item::Ruler);
75
        self.standing.shame += 10;
76
        Ok(self.found(
77
            Item::Ruler,
78
            "You now know. This is the first honest measurement of the run.",
79
        ))
80
    }
81
82
    fn search_bathroom(&mut self) -> Outcome {
83
        self.items.grant(Item::DoorLock);
84
        let vaseline = self.chance(
85
            self.decision(
86
                "bathroom-vaseline",
87
                "Is it the vaseline behind the door lock, rather than the lotion?",
88
            ),
89
            BATHROOM_VASELINE,
90
        );
91
        let (lube, detail) = if vaseline {
92
            (
93
                Item::Vaseline,
94
                "A door lock, which works once, and a tub of vaseline behind it.",
95
            )
96
        } else {
97
            (
98
                Item::Lotion,
99
                "A door lock, which works once, and a bottle of lotion behind it.",
100
            )
101
        };
102
        self.items.grant(lube);
103
        self.found(Item::DoorLock, detail)
104
    }
105
106
    fn search_locker(&mut self, first: bool) -> Result<Outcome, Problem> {
107
        let open = first
108
            && self.chance(
109
                self.decision("gregs-locker", "Has Greg left his locker open?"),
110
                GREGS_LOCKER,
111
            );
112
        if open {
113
            self.items.grant(Item::BabyOil);
114
            return Ok(self.found(
115
                Item::BabyOil,
116
                "Greg has left his locker open. The baby oil is yours now, legally speaking.",
117
            ));
118
        }
119
        self.standing.shame += 3;
120
        Err(Problem::new(
121
            StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS,
122
            "not-your-locker",
123
            "That locker belongs to Greg. The server cannot serve this request for legal reasons.",
124
        ))
125
    }
126
127
    /// Searching while caged is noisy, costs the floor turn, and the key only turns up some of
128
    /// the time. A jammed drawer takes a whole turn to work loose.
129
    pub(super) fn rummage_for_key(&mut self) -> Outcome {
130
        self.begin_turn();
131
        self.add_suspicion(1);
132
        self.maybe_summon_mum();
133
        if self.here.drawer.jammed {
134
            self.here.drawer.jammed = false;
135
            self.notices.push(Notice::DrawerComesLoose);
136
            return Outcome::empty(StatusCode::NO_CONTENT);
137
        }
138
        if !self.chance(
139
            self.decision("key", "Does the drawer finally give up the cage key?"),
140
            KEY_IN_DRAWER,
141
        ) {
142
            if self.chance(
143
                self.decision("drawer-jams", "Has the drawer jammed on its runners?"),
144
                DRAWER_JAMS,
145
            ) {
146
                self.here.drawer.jammed = true;
147
                self.notices.push(Notice::DrawerJammed);
148
            }
149
            return Outcome::empty(StatusCode::NO_CONTENT);
150
        }
151
        self.items.grant(Item::CageKey);
152
        Outcome::json(
153
            StatusCode::OK,
154
            json!({ "detail": "The key was in the drawer. The cage is off." }),
155
        )
156
    }
157
158
    pub fn drawer_worth_searching(&self) -> bool {
159
        !self.here.drawer.searched || self.items.kit.cage
160
    }
161
}