#![allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
use std::sync::Arc;
use brink_runtime::{DotNetRng, Step, Story};
fn play(source: &str, choices: usize) -> Vec<String> {
let output = brink_compiler::compile("story.ink", |_| Ok(source.to_owned()));
assert!(
output.is_ok(),
"compile failed: {:?}\n{source}",
output.as_ref().err()
);
let output = output.expect("just asserted above");
let (program, line_tables) = brink_runtime::link(&output.data).expect("link");
let mut story = Story::<DotNetRng>::new(Arc::new(program), line_tables);
let mut lines = Vec::new();
let mut made = 0;
for _ in 0..400 {
match story.continue_single().expect("runtime") {
Step::Line(l) => lines.push(l.text.trim().to_owned()),
Step::Choices(_) => {
if made == choices {
return lines;
}
made += 1;
story.choose(0).expect("choose");
}
Step::Done | Step::End | Step::Suspended => return lines,
}
}
panic!("story did not settle in 400 steps");
}
#[test]
fn sequence_leading_a_conditional_line_advances_once_per_view() {
let src = "-> k\n=== k ===\n+ [again]\n {a|b}{true:p}{c|d|e}\n -> k\n";
assert_eq!(play(src, 4), vec!["apc", "bpd", "bpe", "bpe"]);
}
#[test]
fn sequences_on_a_glued_line_advance_once_per_view() {
let src = "-> k\n=== k ===\n+ [again]\n {a|b}{c|d|e} <>\n \n -> k\n";
assert_eq!(play(src, 4), vec!["ac", "bd", "be", "be"]);
}
#[test]
fn mixed_claiming_branches_share_one_counter_stub_first() {
let src = "VAR n = 0\n-> k\n=== k ===\n+ [again]\n ~ n = n + 1\n {n mod 2 == 1:x|y<>}{c|d|e}\n -> k\n";
assert_eq!(play(src, 4), vec!["xc", "yd", "xe", "ye"]);
}
#[test]
fn mixed_claiming_branches_share_one_counter() {
let src = "VAR n = 0\n-> k\n=== k ===\n+ [again]\n ~ n = n + 1\n {n mod 2 == 1:x<>|y}{c|d|e}\n -> k\n";
assert_eq!(play(src, 4), vec!["xc", "yd", "xe", "ye"]);
}
fn plain_lines(source: &str) -> Vec<String> {
let output = brink_compiler::compile("story.ink", |_| Ok(source.to_owned())).expect("compile");
output
.data
.line_tables
.iter()
.flat_map(|t| t.lines.iter())
.filter_map(|l| match &l.content {
brink_format::LineContent::Plain(text) => Some(text.trim().to_owned()),
brink_format::LineContent::Template(_) => None,
})
.collect()
}
#[test]
fn cloned_lines_keep_whole_line_renderings_in_the_line_table() {
let lines = plain_lines("-> k\n=== k ===\n+ [again]\n {a|b}{c|d|e} <>\n \n -> k\n");
for expected in ["ac", "ad", "ae", "bc", "bd", "be"] {
assert!(
lines.contains(&expected.to_owned()),
"missing {expected} in {lines:?}"
);
}
for fragment in ["a", "b", "c", "d", "e"] {
assert!(
!lines.contains(&fragment.to_owned()),
"fragment {fragment} in {lines:?}"
);
}
let lines = plain_lines("-> k\n=== k ===\n+ [again]\n {a|b}{true:p}{c|d|e}\n -> k\n");
for expected in ["apc", "apd", "ape", "bpc", "bpd", "bpe"] {
assert!(
lines.contains(&expected.to_owned()),
"missing {expected} in {lines:?}"
);
}
}