an http based roguelike rpg about jelqing
| 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 | self.recover(); |
| 37 | self.shed(FRICTION_HOLD); |
| 38 | self.settle(); |
| 39 | let detail = if self.body.conditions.priapism_turns > 0 { |
| 40 | "The count went well past ten. Stamina is back. It went down a little. Maybe. You hope." |
| 41 | } else { |
| 42 | "The count went well past ten. Stamina is back. Everything else has gone quiet, and you are cold again." |
| 43 | }; |
| 44 | return Ok(Outcome::json(StatusCode::OK, json!({ "detail": detail }))); |
| 45 | } |
| 46 | if self.chance( |
| 47 | self.decision( |
| 48 | "reflection", |
| 49 | "In the quiet afterwards, have you caught your own eye in the mirror?", |
| 50 | ), |
| 51 | REFLECTION, |
| 52 | ) { |
| 53 | self.body.eq = 0; |
| 54 | self.standing.shame += 1; |
| 55 | self.notices.push(Notice::Reflection); |
| 56 | } else { |
| 57 | self.body.eq = (self.body.eq - HOLD_EQ).clamp(0, 100); |
| 58 | } |
| 59 | self.body.stamina = (self.body.stamina + 1).min(self.max_stamina()); |
| 60 | self.shed(FRICTION_HOLD); |
| 61 | self.settle(); |
| 62 | Ok(Outcome::empty(StatusCode::NO_CONTENT)) |
| 63 | } |
| 64 | |
| 65 | /// The breathing technique from the forum's replies. It spends no stamina and the turn is |
| 66 | /// not the floor's, but each floor allows it once. |
| 67 | pub(super) fn meditate(&mut self) -> Result<Outcome, Problem> { |
| 68 | if self.here.meditated { |
| 69 | return Err(Problem::new( |
| 70 | StatusCode::CONFLICT, |
| 71 | "already-meditated", |
| 72 | "This floor has had its meditation.", |
| 73 | )); |
| 74 | } |
| 75 | self.here.meditated = true; |
| 76 | self.step_away(); |
| 77 | self.reset_eq(self.body.eq - MEDITATION_EQ); |
| 78 | self.shed(FRICTION_MEDITATE); |
| 79 | self.touch(); |
| 80 | Ok(Outcome::json( |
| 81 | StatusCode::OK, |
| 82 | json!({ |
| 83 | "detail": "In through the nose, out through the mouth. EQ falls by ten.", |
| 84 | }), |
| 85 | )) |
| 86 | } |
| 87 | } |