atagen

jelq

public

an http based roguelike rpg about jelqing

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