Skip to content

Commit c1574f0

Browse files
committed
recursive cards
1 parent 70d7c67 commit c1574f0

File tree

3 files changed

+109
-52
lines changed

3 files changed

+109
-52
lines changed

src/cah/mod.rs

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::marker::ConstParamTy;
33
use std::ops::Index;
44
use std::sync::Arc;
55
use std::{fmt::Display, fs::read_to_string};
6-
use std::{matches, mem};
6+
use std::{matches, mem, println};
77

88
use async_trait::async_trait;
99
use discord::escape_string;
@@ -32,12 +32,18 @@ pub enum CardData {
3232
}
3333

3434
impl CardData {
35-
fn blanks(&self) -> usize {
35+
fn blanks_black(&self) -> usize {
3636
match *self {
3737
CardData::Raw(ref s) => s.chars().filter(|&c| c == '_').count().max(1),
3838
CardData::Full { pick, .. } => pick,
3939
}
4040
}
41+
fn blanks_white(&self) -> usize {
42+
match *self {
43+
CardData::Raw(ref s) => s.chars().filter(|&c| c == '_').count(),
44+
CardData::Full { pick, .. } => pick,
45+
}
46+
}
4147
fn extra_blanks(&self) -> usize {
4248
match *self {
4349
CardData::Raw(ref s) => {
@@ -79,82 +85,107 @@ pub struct Card<const TYPE: CardType> {
7985
card: u32,
8086
}
8187

82-
impl Card<{ CardType::Black }> {
88+
impl<const C: CardType> Card<C> {
89+
pub fn is_filled(
90+
self,
91+
packs: &Packs,
92+
white: impl Iterator<Item = Option<Card<{ CardType::White }>>>,
93+
) -> bool {
94+
let mut blanks = match C {
95+
CardType::White => packs[self].blanks_white(),
96+
CardType::Black => packs[self].blanks_black(),
97+
};
98+
let mut cards = 0;
99+
100+
for card in white {
101+
match card {
102+
Some(card) => {
103+
// NOTE: this already accounts for recursiveness
104+
blanks += packs[card].blanks_white();
105+
cards += 1;
106+
}
107+
None => return false,
108+
}
109+
}
110+
111+
cards == blanks
112+
}
83113
pub fn fill(
84114
self,
85115
packs: &Packs,
86-
mut white: impl Iterator<Item = Option<Card<{ CardType::White }>>>,
116+
white: &mut impl Iterator<Item = Option<Card<{ CardType::White }>>>,
87117
) -> String {
88-
let prompt = escape_string(&packs[self].to_string().replace("\\n", "\n "));
118+
let prompt: String = packs[self].to_string().into();
119+
let prompt = match C {
120+
CardType::White => prompt.trim_end_matches('.').into(),
121+
CardType::Black => escape_string(&prompt.replace("\\n", "\n ")),
122+
};
89123

90124
let mut prompt_slice = prompt.as_str();
91125
let mut filled = String::with_capacity(prompt.len());
92126

93127
while let Some(pos) = prompt_slice.find('_') {
94128
match white.next() {
95129
Some(Some(c)) => {
96-
filled.push_str(&prompt_slice[..pos - 1]);
97-
98-
// TODO: recursive
99-
filled.push_str(format!("``{}``", packs[c]).as_str());
130+
match C {
131+
CardType::White => {
132+
// trim spaces around blank
133+
filled.push_str(prompt_slice[..pos].trim_end());
134+
prompt_slice = prompt_slice[pos + 1..].trim_start();
135+
136+
filled.push_str(format!("`` ``{}`` ``", c.fill(packs, white)).as_str());
137+
}
138+
CardType::Black => {
139+
// also remove backslash
140+
filled.push_str(&prompt_slice[..pos - 1]);
141+
prompt_slice = &prompt_slice[pos + 1..];
142+
143+
filled.push_str(format!("``{}``", c.fill(packs, white)).as_str());
144+
}
145+
}
100146
}
101147
_ => {
102148
filled.push_str(&prompt_slice[..pos + 1]);
149+
prompt_slice = &prompt_slice[pos + 1..];
103150
}
104151
}
105-
prompt_slice = &prompt_slice[pos + 1..];
106152
}
107153
filled.push_str(prompt_slice);
108154

109-
let extra_cards = packs[self].extra_blanks();
110-
for _ in 0..extra_cards {
111-
if let Some(Some(c)) = white.next() {
112-
// TODO: recursive
113-
filled.push_str(format!(" ``{}``", packs[c]).as_str());
155+
match C {
156+
CardType::White => {
157+
// remove empty quotes
158+
filled = filled
159+
.trim_start_matches(&[' ', '`'])
160+
.trim_end_matches(&[' ', '`'])
161+
.into();
114162
}
115-
}
116-
117-
filled
118-
}
119-
pub fn is_filled(
120-
self,
121-
packs: &Packs,
122-
white: impl Iterator<Item = Option<Card<{ CardType::White }>>>,
123-
) -> bool {
124-
let mut blanks = packs[self].blanks();
125-
let mut cards = 0;
126-
127-
for card in white {
128-
match card {
129-
Some(card) => {
130-
// NOTE: this already accounts for recursiveness
131-
blanks += packs[card].blanks();
132-
cards += 1;
163+
CardType::Black => {
164+
let extra_cards = packs[self].extra_blanks();
165+
for _ in 0..extra_cards {
166+
if let Some(Some(c)) = white.next() {
167+
filled.push_str(format!(" ``{}``", c.fill(packs, white)).as_str());
168+
}
133169
}
134-
None => return false,
135170
}
136171
}
137172

138-
cards == blanks
173+
println!("{}", filled);
174+
filled
139175
}
140176
}
141177

142178
pub type Pack = Arc<(String, PackData)>;
143179
pub struct Packs(Vec<Pack>);
144180

145-
impl Index<Card<{ CardType::Black }>> for Packs {
181+
impl<const C: CardType> Index<Card<C>> for Packs {
146182
type Output = CardData;
147183

148-
fn index(&self, index: Card<{ CardType::Black }>) -> &Self::Output {
149-
&self.0[index.pack as usize].1.black[index.card as usize]
150-
}
151-
}
152-
153-
impl Index<Card<{ CardType::White }>> for Packs {
154-
type Output = CardData;
155-
156-
fn index(&self, index: Card<{ CardType::White }>) -> &Self::Output {
157-
&self.0[index.pack as usize].1.white[index.card as usize]
184+
fn index(&self, index: Card<C>) -> &Self::Output {
185+
match C {
186+
CardType::White => &self.0[index.pack as usize].1.white[index.card as usize],
187+
CardType::Black => &self.0[index.pack as usize].1.black[index.card as usize],
188+
}
158189
}
159190
}
160191

@@ -355,7 +386,7 @@ impl Game for CAH {
355386
}
356387

357388
let players: Vec<_> = s.players().collect();
358-
let packs = Packs(
389+
let mut packs = Packs(
359390
s.packs
360391
.0
361392
.iter()
@@ -388,7 +419,7 @@ impl Game for CAH {
388419

389420
let mut players = players.into_iter().map(Player::new).collect::<Vec<_>>();
390421

391-
let prompt = match s.packs.draw_black() {
422+
let prompt = match packs.draw_black() {
392423
Some(c) => c,
393424
None => {
394425
return ActionResponse::Error(GameMessage::new(
@@ -402,7 +433,7 @@ impl Game for CAH {
402433
};
403434

404435
for player in players.iter_mut() {
405-
if !player.draw(&mut s.packs, s.cards as usize, prompt) {
436+
if !player.draw(&mut packs, s.cards as usize, prompt) {
406437
return ActionResponse::Error(GameMessage::new(
407438
vec![Field::new(
408439
"Error",
@@ -535,6 +566,26 @@ impl Game for CAH {
535566
serde_json::from_str(read_to_string("cards/eppgroep.json").unwrap().as_str())
536567
.unwrap(),
537568
)),
569+
Arc::new((
570+
"Modifiers".into(),
571+
serde_json::from_str(read_to_string("cards/modifiers.json").unwrap().as_str())
572+
.unwrap(),
573+
)),
574+
Arc::new((
575+
"Modifiers".into(),
576+
serde_json::from_str(read_to_string("cards/modifiers.json").unwrap().as_str())
577+
.unwrap(),
578+
)),
579+
Arc::new((
580+
"Modifiers".into(),
581+
serde_json::from_str(read_to_string("cards/modifiers.json").unwrap().as_str())
582+
.unwrap(),
583+
)),
584+
Arc::new((
585+
"Modifiers".into(),
586+
serde_json::from_str(read_to_string("cards/modifiers.json").unwrap().as_str())
587+
.unwrap(),
588+
)),
538589
]),
539590
selected_packs: vec![0],
540591
bots: 0,

src/cah/read.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ impl Ingame {
5656
self.random_indices()
5757
.iter()
5858
.enumerate()
59-
.map(|(i, p)| format!("{}. {}", i + 1, self.prompt.fill(&self.packs, p.selected())))
59+
.map(|(i, p)| {
60+
format!(
61+
"{}. {}",
62+
i + 1,
63+
self.prompt.fill(&self.packs, &mut p.selected())
64+
)
65+
})
6066
.collect::<Vec<_>>()
6167
.join("\n"),
6268
));
@@ -101,7 +107,7 @@ impl Ingame {
101107
let total_points = winner.points;
102108

103109
let name = winner.kind.to_string();
104-
let answer = self.prompt.fill(&self.packs, winner.selected());
110+
let answer = self.prompt.fill(&self.packs, &mut winner.selected());
105111

106112
let points = self
107113
.players

src/cah/write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Ingame {
7171

7272
msg.fields.push(Field::new(
7373
"Answer",
74-
self.prompt.fill(&self.packs, player.selected()),
74+
self.prompt.fill(&self.packs, &mut player.selected()),
7575
));
7676
}
7777

0 commit comments

Comments
 (0)