an http based roguelike rpg about jelqing
Commit 2176d9a94bd9
tarball4 files changed+98-41
@@ -86,53 +86,61 @@ fn is_truth(spoken: &str) -> bool {
8686
/// Why Mum came to the door, and how she leaves once she believes you.8787
#[derive(Clone, Copy)]8888
pub struct Errand {89
+ pub(crate) arrival: &'static str,8990
pub(crate) knock: &'static str,9091
pub(crate) parting: &'static str,9192
}9293
93
-pub const HEARD_A_NOISE: Errand = Errand {94
- knock: "She heard a noise.",95
- parting: "Mum seems satisfied. It must have been the pipes.",96
-};97
-const VIRAL: Errand = Errand {98
- knock: "A neighbour has sent her something.",99
- parting: "Mum seems satisfied. She has decided not to open the attachment.",100
-};94
+macro_rules! errand {95
+ ($knock:literal, $parting:literal) => {96
+ Errand {97
+ arrival: concat!("Mum is at the door. ", $knock),98
+ knock: $knock,99
+ parting: concat!("Mum seems satisfied. ", $parting),100
+ }101
+ };102
+}103
+104
+pub const HEARD_A_NOISE: Errand = errand!("She heard a noise.", "It must have been the pipes.");105
+const VIRAL: Errand = errand!(106
+ "A neighbour has sent her something.",107
+ "She has decided not to open the attachment."108
+);101109
const BEDROOM_ERRANDS: [Errand; 4] = [102
- Errand {103
- knock: "She has brought your washing.",104
- parting: "Mum seems satisfied. She leaves the washing on the chair.",105
- },106
- Errand {107
- knock: "She wants to know if you have eaten.",108
- parting: "Mum seems satisfied. There will be a plate in the oven.",109
- },110
- Errand {111
- knock: "She needs the wifi password.",112
- parting: "Mum seems satisfied. She has written the wifi password on her hand.",113
- },114
- Errand {115
- knock: "She would like to talk about your future.",116
- parting: "Mum seems satisfied. The future can wait until dinner.",117
- },110
+ errand!(111
+ "She has brought your washing.",112
+ "She leaves the washing on the chair."113
+ ),114
+ errand!(115
+ "She wants to know if you have eaten.",116
+ "There will be a plate in the oven."117
+ ),118
+ errand!(119
+ "She wants the wifi password.",120
+ "She has written the wifi password on her hand."121
+ ),122
+ errand!(123
+ "She would like to talk about your future.",124
+ "The future can wait until dinner."125
+ ),118126
];119127
const CHRISTMAS_ERRANDS: [Errand; 4] = [120
- Errand {121
- knock: "Nan would like to see you.",122
- parting: "Mum seems satisfied. She tells Nan you are on your way.",123
- },124
- Errand {125
- knock: "Christmas dinner is in ten minutes.",126
- parting: "Mum seems satisfied. She will save you a pig in a blanket.",127
- },128
- Errand {129
- knock: "The King's speech is about to start.",130
- parting: "Mum seems satisfied. She will tell you what the King said.",131
- },132
- Errand {133
- knock: "An uncle has asked where you went.",134
- parting: "Mum seems satisfied. She tells the uncle you are helping in the kitchen.",135
- },128
+ errand!(129
+ "Nan would like to see you.",130
+ "She tells Nan you are on your way."131
+ ),132
+ errand!(133
+ "Christmas dinner is in ten minutes.",134
+ "She will save you a pig in a blanket."135
+ ),136
+ errand!(137
+ "The King's speech is about to start.",138
+ "She will tell you what the King said."139
+ ),140
+ errand!(141
+ "An uncle has asked where you went.",142
+ "She tells the uncle you are helping in the kitchen."143
+ ),136144
];137145
138146
#[derive(Default)]@@ -140,6 +148,8 @@ pub struct Household {
140148
pub(crate) mum: Option<MumVisit>,141149
/// Every excuse Mum has accepted this run. Digest Mum remembers them all.142150
pub(crate) heard: Vec<Excuse>,151
+ /// Set when the request now being answered sent Mum away, so the same turn cannot fetch her back.152
+ pub(crate) just_left: bool,143153
}144154
145155
pub struct MumVisit {@@ -227,6 +237,7 @@ impl Run {
227237
228238
/// Mum answers every request on the run until she has been given something she believes.229239
pub fn answer_door(&mut self, authorization: Option<&str>) -> Result<(), Problem> {240
+ self.household.just_left = false;230241
if self.household.mum.is_none() {231242
return Ok(());232243
}@@ -380,6 +391,7 @@ impl Run {
380391
if let Some(visit) = self.household.mum.take() {381392
self.notices382393
.push(Notice::MumSatisfied(visit.errand.parting));394
+ self.household.just_left = true;383395
}384396
self.standing.suspicion = 0;385397
self.touch();@@ -13,6 +13,7 @@ pub enum Notice {
1313
DrawerComesLoose,1414
ThreadHasReplies,1515
Reflection,16
+ MumAtTheDoor(&'static str),1617
MumSatisfied(&'static str),1718
ColdStart,1819
RunningLong(Floor),@@ -34,6 +35,7 @@ impl Notice {
3435
Self::DrawerComesLoose => "The drawer comes loose. That took a while.",3536
Self::ThreadHasReplies => "Somewhere, a forum thread from 2009 still has replies.",3637
Self::Reflection => "the count reached ten, and then the reflection started",38
+ Self::MumAtTheDoor(arrival) => arrival,3739
Self::MumSatisfied(parting) => parting,3840
Self::ColdStart => "Cold start. The server has noted this.",3941
Self::RunningLong(floor) => match floor {@@ -171,7 +171,7 @@ impl Run {
171171
172172
pub(super) fn maybe_summon_mum(&mut self) {173173
let was_below = self.standing.at_turn_start < SUSPICION_LIMIT;174
- if !self.floor.has_mum() || self.household.mum.is_some() {174
+ if !self.floor.has_mum() || self.household.mum.is_some() || self.household.just_left {175175
return;176176
}177177
let summoned = was_below && self.standing.suspicion == SUSPICION_LIMIT;@@ -190,6 +190,7 @@ impl Run {
190190
)191191
{192192
let errand = self.errand(summoned);193
+ self.notices.push(Notice::MumAtTheDoor(errand.arrival));193194
let nonce = self.fresh_nonce();194195
self.household.mum = Some(MumVisit {195196
errand,@@ -446,3 +446,45 @@ async fn a_stale_nonce_is_explained_for_free() {
446446
.await;447447
assert_eq!(current.status(), StatusCode::OK);448448
}449
+450
+#[tokio::test]451
+async fn mum_announces_herself_but_never_returns_on_the_turn_she_left() {452
+ let mut arrivals = 0;453
+ for seed in 0..200u64 {454
+ let app = app_with(Floor::Bedroom, seed, |run| {455
+ mum_at_the_door(run);456
+ run.body.eq = 60;457
+ run.here.brother_told = true;458
+ run.standing.suspicion = 4;459
+ });460
+ let excused = send(461
+ &app,462
+ "JELQ",463
+ "/runs/cafebabe?technique=stretch&intensity=10",464
+ &[("authorization", "Excuse \"homework\"")],465
+ "",466
+ )467
+ .await;468
+ assert!(469
+ excused.headers().get("www-authenticate").is_none(),470
+ "seed {seed} fetched Mum straight back"471
+ );472
+ let again = send(473
+ &app,474
+ "JELQ",475
+ "/runs/cafebabe?technique=stretch&intensity=10",476
+ &[],477
+ "",478
+ )479
+ .await;480
+ if again.headers().get("www-authenticate").is_some() {481
+ arrivals += 1;482
+ assert!(483
+ warnings(&again)484
+ .iter()485
+ .any(|w| w.contains("Mum is at the door. She"))486
+ );487
+ }488
+ }489
+ assert!(arrivals > 0, "Mum never came back at all");490
+}