keys 1
This commit is contained in:
+82
-8
@@ -18,25 +18,43 @@ pub const SAY_DURATION: f64 = 3.0;
|
||||
/// paired with its [`Rgba8`] color for rendering.
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct Keyring {
|
||||
/// Blue key.
|
||||
pub blue: bool,
|
||||
/// Green key.
|
||||
pub green: bool,
|
||||
/// Cyan key.
|
||||
pub cyan: bool,
|
||||
/// Red key.
|
||||
pub red: bool,
|
||||
/// Purple key.
|
||||
pub purple: bool,
|
||||
/// Orange key (custom color, not in the standard EGA palette).
|
||||
pub orange: bool,
|
||||
/// Yellow key.
|
||||
pub yellow: bool,
|
||||
/// Green key.
|
||||
pub green: bool,
|
||||
/// Blue key.
|
||||
pub blue: bool,
|
||||
/// Cyan key.
|
||||
pub cyan: bool,
|
||||
/// Purple key.
|
||||
pub purple: bool,
|
||||
/// White key.
|
||||
pub white: bool,
|
||||
}
|
||||
|
||||
impl Keyring {
|
||||
/// Sets the named key slot to `value`. Returns `false` if `name` is not a
|
||||
/// recognized color (`"blue"`, `"green"`, `"cyan"`, `"red"`, `"purple"`,
|
||||
/// `"orange"`, `"yellow"`, `"white"`).
|
||||
pub fn set_by_name(&mut self, name: &str, value: bool) -> bool {
|
||||
match name {
|
||||
"blue" => self.blue = value,
|
||||
"green" => self.green = value,
|
||||
"cyan" => self.cyan = value,
|
||||
"red" => self.red = value,
|
||||
"purple" => self.purple = value,
|
||||
"orange" => self.orange = value,
|
||||
"yellow" => self.yellow = value,
|
||||
"white" => self.white = value,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns all eight keys in display order, each paired with its color.
|
||||
///
|
||||
/// Order: blue, green, cyan, red, purple, orange, yellow, white.
|
||||
@@ -261,6 +279,7 @@ impl GameState {
|
||||
// Net change to the player's gem count from AddGems actions; applied to
|
||||
// `self` after the board borrow drops.
|
||||
let mut gem_delta: i64 = 0;
|
||||
let mut key_changes: Vec<(String, bool)> = Vec::new();
|
||||
let mut sends: Vec<(ObjectId, String, Option<ScriptArg>)> = Vec::new();
|
||||
let mut new_bubbles: Vec<SpeechBubble> = Vec::new();
|
||||
// Collected outside the board borrow so we can assign to self.active_scroll.
|
||||
@@ -362,6 +381,8 @@ impl GameState {
|
||||
}
|
||||
// Accumulated and applied to `self.player_gems` after the borrow drops.
|
||||
Action::AddGems(n) => gem_delta += n,
|
||||
// Collected and applied to `self.player_keys` after the borrow drops.
|
||||
Action::SetKey(color, present) => key_changes.push((color, present)),
|
||||
// A grab thing despawns itself from its grab() hook.
|
||||
Action::Die => {
|
||||
board.remove_object(ba.source);
|
||||
@@ -383,6 +404,11 @@ impl GameState {
|
||||
if gem_delta != 0 {
|
||||
self.player_gems = (self.player_gems as i64 + gem_delta).max(0) as u32;
|
||||
}
|
||||
for (color, present) in key_changes {
|
||||
if !self.player_keys.set_by_name(&color, present) {
|
||||
self.log.push(LogLine::error(format!("set_key: unknown color {color:?}")));
|
||||
}
|
||||
}
|
||||
for (bumped, bumper) in bumps {
|
||||
self.scripts.run_bump(bumped, bumper);
|
||||
}
|
||||
@@ -762,4 +788,52 @@ mod tests {
|
||||
}
|
||||
assert_eq!(seq, vec![47, 0xC4, 92, 0xB3, 47]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_key_gives_and_takes_keys() {
|
||||
let mut sobj = ObjectDef::new(0, 0);
|
||||
sobj.solid = false;
|
||||
sobj.script_name = Some("s".to_string());
|
||||
let board = open_board(2, 1, (1, 0), vec![sobj]);
|
||||
let scripts = HashMap::from([(
|
||||
"s".to_string(),
|
||||
"fn init() { set_key(\"blue\", true); set_key(\"red\", true); }".to_string(),
|
||||
)]);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
|
||||
assert!(game.player_keys.blue);
|
||||
assert!(game.player_keys.red);
|
||||
assert!(!game.player_keys.cyan); // cyan was not set by the script
|
||||
|
||||
// A second script can take a key.
|
||||
let mut sobj2 = ObjectDef::new(0, 0);
|
||||
sobj2.solid = false;
|
||||
sobj2.script_name = Some("t".to_string());
|
||||
let board2 = open_board(2, 1, (1, 0), vec![sobj2]);
|
||||
let scripts2 = HashMap::from([(
|
||||
"t".to_string(),
|
||||
"fn init() { set_key(\"blue\", true); set_key(\"blue\", false); }".to_string(),
|
||||
)]);
|
||||
let mut game2 = GameState::with_scripts(board2, scripts2);
|
||||
game2.run_init();
|
||||
|
||||
assert!(!game2.player_keys.blue);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_key_unknown_color_logs_error() {
|
||||
let mut sobj = ObjectDef::new(0, 0);
|
||||
sobj.solid = false;
|
||||
sobj.script_name = Some("s".to_string());
|
||||
let board = open_board(2, 1, (1, 0), vec![sobj]);
|
||||
let scripts = HashMap::from([(
|
||||
"s".to_string(),
|
||||
r#"fn init() { set_key("chartreuse", true); }"#.to_string(),
|
||||
)]);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
|
||||
assert!(game.log.iter().any(|l| l.spans.iter().any(|s| s.text.contains("set_key"))));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user