atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
6619c458c23edaf053ae371f8aa0df1e866febb6
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/rest.rsRust102 lines3.4 KB
1
use super::{
2
    Notice, Outcome, Run, Story,
3
    balance::{
4
        DANGER_EQ, FRICTION_HOLD, FRICTION_MEDITATE, HOLD_EQ, MEDITATION_EQ, REFLECTION,
5
        RUPTURE_HOLD,
6
    },
7
};
8
use crate::problem::Problem;
9
use axum::http::StatusCode;
10
use serde_json::json;
11
12
impl Run {
13
    pub fn can_hold(&self) -> bool {
14
        self.body.eq > DANGER_EQ || self.body.stamina <= 2
15
    }
16
17
    pub fn hold(&mut self) -> Result<Outcome, Problem> {
18
        if self.online.story == Story::Pending {
19
            return Ok(self.branch_offer());
20
        }
21
        if self.items.kit.cage {
22
            return Err(Problem::new(
23
                StatusCode::LOCKED,
24
                "caged",
25
                "The cage is locked. The key is not in the box.",
26
            ));
27
        }
28
        self.begin_turn()?;
29
        if self.oracle.chance_not(
30
            self.decision("rupture", "The pause is uneventful"),
31
            RUPTURE_HOLD,
32
        ) {
33
            return Err(self.rupture());
34
        }
35
        if self.body.exhausted {
36
            let second_wind = self.recover();
37
            self.shed(FRICTION_HOLD);
38
            self.settle();
39
            let back = if second_wind {
40
                "The count went well past ten, and something came back that had no business coming back. Stamina is full."
41
            } else {
42
                "The count went well past ten. Some of the stamina is back."
43
            };
44
            let after = if self.body.conditions.priapism_turns > 0 {
45
                "It went down a little. Maybe. You hope."
46
            } else {
47
                "Everything else has gone quiet, and you are cold again."
48
            };
49
            return Ok(Outcome::json(
50
                StatusCode::OK,
51
                json!({ "detail": format!("{back} {after}") }),
52
            ));
53
        }
54
        if self.chance(
55
            self.decision(
56
                "reflection",
57
                "In the quiet afterwards, have you caught your own eye in the mirror?",
58
            ),
59
            REFLECTION,
60
        ) {
61
            self.body.eq = 0;
62
            self.standing.shame += 1;
63
            self.notices.push(Notice::Reflection);
64
        } else {
65
            self.body.eq = (self.body.eq - HOLD_EQ).clamp(0, 100);
66
        }
67
        self.body.stamina = (self.body.stamina + 1).min(self.max_stamina());
68
        self.shed(FRICTION_HOLD);
69
        self.settle();
70
        Ok(Outcome::empty(StatusCode::NO_CONTENT))
71
    }
72
73
    /// The breathing technique from the forum's replies. It spends no stamina and the turn is
74
    /// not the floor's, but each floor allows it once.
75
    pub(super) fn meditate(&mut self) -> Result<Outcome, Problem> {
76
        if !self.online.meditation_taught {
77
            return Err(Problem::new(
78
                StatusCode::FORBIDDEN,
79
                "technique-locked",
80
                "Somebody on a forum knows how to breathe. You have not found the reply.",
81
            ));
82
        }
83
        if self.here.meditated {
84
            return Err(Problem::new(
85
                StatusCode::CONFLICT,
86
                "already-meditated",
87
                "This floor has had its meditation.",
88
            ));
89
        }
90
        self.here.meditated = true;
91
        self.step_away();
92
        self.reset_eq(self.body.eq - MEDITATION_EQ);
93
        self.shed(FRICTION_MEDITATE);
94
        self.touch();
95
        Ok(Outcome::json(
96
            StatusCode::OK,
97
            json!({
98
                "detail": "In through the nose, out through the mouth. EQ falls by ten.",
99
            }),
100
        ))
101
    }
102
}