Clean up element.rs
A lot of this is deleting zztext-specific functionality, such as string mappings that go beyond official names for things. It's okay, zztext will cope.
This commit is contained in:
Generated
+77
@@ -205,6 +205,28 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c"
|
||||||
|
dependencies = [
|
||||||
|
"num_enum_derive",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum_derive"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
@@ -221,6 +243,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
|
||||||
|
dependencies = [
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -258,6 +289,12 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.23"
|
version = "1.0.23"
|
||||||
@@ -362,6 +399,36 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "1.0.0+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.25.4+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_parser",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_parser"
|
||||||
|
version = "1.0.9+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
||||||
|
dependencies = [
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
@@ -514,6 +581,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
@@ -615,5 +691,6 @@ dependencies = [
|
|||||||
"codepage-437",
|
"codepage-437",
|
||||||
"insta",
|
"insta",
|
||||||
"nom",
|
"nom",
|
||||||
|
"num_enum",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ license = "MIT"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
codepage-437 = "0.1"
|
codepage-437 = "0.1"
|
||||||
nom = "8.0"
|
nom = "8.0"
|
||||||
|
num_enum = "0.7"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
+17
-286
@@ -1,5 +1,20 @@
|
|||||||
/// ZZT element types.
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
|
/// Officially supported ZZT element types.
|
||||||
|
///
|
||||||
|
/// These are all the elements for which ZZT 3.2 has handler code. In general,
|
||||||
|
/// though, the file format allows any `u8` as a tile type. And sometimes
|
||||||
|
/// out-of-range values see actual use:
|
||||||
|
///
|
||||||
|
/// - Some values don't crash ZZT right away, but instead trigger a different
|
||||||
|
/// bug where they appear as text colors besides the official seven.
|
||||||
|
/// - Some worlds intentionally crash ZZT for whatever reason.
|
||||||
|
/// - Forks of ZZT may take unused element IDs and repurpose them.
|
||||||
|
///
|
||||||
|
/// In order to provide flexibility around these cases, the `Board` struct
|
||||||
|
/// represents tile types with raw `u8`s, but this enum is still provided for
|
||||||
|
/// convenience.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Element {
|
pub enum Element {
|
||||||
Empty = 0,
|
Empty = 0,
|
||||||
@@ -57,287 +72,3 @@ pub enum Element {
|
|||||||
TextBrown = 52,
|
TextBrown = 52,
|
||||||
TextBlack = 53,
|
TextBlack = 53,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element {
|
|
||||||
/// Try to convert a u8 to an Element.
|
|
||||||
pub fn from_u8(id: u8) -> Option<Element> {
|
|
||||||
match id {
|
|
||||||
0 => Some(Element::Empty),
|
|
||||||
1 => Some(Element::BoardEdge),
|
|
||||||
2 => Some(Element::Messenger),
|
|
||||||
3 => Some(Element::Monitor),
|
|
||||||
4 => Some(Element::Player),
|
|
||||||
5 => Some(Element::Ammo),
|
|
||||||
6 => Some(Element::Torch),
|
|
||||||
7 => Some(Element::Gem),
|
|
||||||
8 => Some(Element::Key),
|
|
||||||
9 => Some(Element::Door),
|
|
||||||
10 => Some(Element::Scroll),
|
|
||||||
11 => Some(Element::Passage),
|
|
||||||
12 => Some(Element::Duplicator),
|
|
||||||
13 => Some(Element::Bomb),
|
|
||||||
14 => Some(Element::Energizer),
|
|
||||||
15 => Some(Element::Star),
|
|
||||||
16 => Some(Element::Clockwise),
|
|
||||||
17 => Some(Element::Counter),
|
|
||||||
18 => Some(Element::Bullet),
|
|
||||||
19 => Some(Element::Water),
|
|
||||||
20 => Some(Element::Forest),
|
|
||||||
21 => Some(Element::Solid),
|
|
||||||
22 => Some(Element::Normal),
|
|
||||||
23 => Some(Element::Breakable),
|
|
||||||
24 => Some(Element::Boulder),
|
|
||||||
25 => Some(Element::SliderNs),
|
|
||||||
26 => Some(Element::SliderEw),
|
|
||||||
27 => Some(Element::Fake),
|
|
||||||
28 => Some(Element::Invisible),
|
|
||||||
29 => Some(Element::BlinkWall),
|
|
||||||
30 => Some(Element::Transporter),
|
|
||||||
31 => Some(Element::Line),
|
|
||||||
32 => Some(Element::Ricochet),
|
|
||||||
33 => Some(Element::BlinkRayH),
|
|
||||||
34 => Some(Element::Bear),
|
|
||||||
35 => Some(Element::Ruffian),
|
|
||||||
36 => Some(Element::Object),
|
|
||||||
37 => Some(Element::Slime),
|
|
||||||
38 => Some(Element::Shark),
|
|
||||||
39 => Some(Element::SpinningGun),
|
|
||||||
40 => Some(Element::Pusher),
|
|
||||||
41 => Some(Element::Lion),
|
|
||||||
42 => Some(Element::Tiger),
|
|
||||||
43 => Some(Element::BlinkRayV),
|
|
||||||
44 => Some(Element::Head),
|
|
||||||
45 => Some(Element::Segment),
|
|
||||||
47 => Some(Element::TextBlue),
|
|
||||||
48 => Some(Element::TextGreen),
|
|
||||||
49 => Some(Element::TextCyan),
|
|
||||||
50 => Some(Element::TextRed),
|
|
||||||
51 => Some(Element::TextPurple),
|
|
||||||
52 => Some(Element::TextBrown),
|
|
||||||
53 => Some(Element::TextBlack),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the human-readable name for this element.
|
|
||||||
pub fn name(self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
Element::Empty => "empty",
|
|
||||||
Element::BoardEdge => "board_edge",
|
|
||||||
Element::Messenger => "messenger",
|
|
||||||
Element::Monitor => "monitor",
|
|
||||||
Element::Player => "player",
|
|
||||||
Element::Ammo => "ammo",
|
|
||||||
Element::Torch => "torch",
|
|
||||||
Element::Gem => "gem",
|
|
||||||
Element::Key => "key",
|
|
||||||
Element::Door => "door",
|
|
||||||
Element::Scroll => "scroll",
|
|
||||||
Element::Passage => "passage",
|
|
||||||
Element::Duplicator => "duplicator",
|
|
||||||
Element::Bomb => "bomb",
|
|
||||||
Element::Energizer => "energizer",
|
|
||||||
Element::Star => "star",
|
|
||||||
Element::Clockwise => "clockwise",
|
|
||||||
Element::Counter => "counter",
|
|
||||||
Element::Bullet => "bullet",
|
|
||||||
Element::Water => "water",
|
|
||||||
Element::Forest => "forest",
|
|
||||||
Element::Solid => "solid",
|
|
||||||
Element::Normal => "normal",
|
|
||||||
Element::Breakable => "breakable",
|
|
||||||
Element::Boulder => "boulder",
|
|
||||||
Element::SliderNs => "sliderns",
|
|
||||||
Element::SliderEw => "sliderew",
|
|
||||||
Element::Fake => "fake",
|
|
||||||
Element::Invisible => "invisible",
|
|
||||||
Element::BlinkWall => "blinkwall",
|
|
||||||
Element::Transporter => "transporter",
|
|
||||||
Element::Line => "line",
|
|
||||||
Element::Ricochet => "ricochet",
|
|
||||||
Element::BlinkRayH => "blink_ray_h",
|
|
||||||
Element::Bear => "bear",
|
|
||||||
Element::Ruffian => "ruffian",
|
|
||||||
Element::Object => "object",
|
|
||||||
Element::Slime => "slime",
|
|
||||||
Element::Shark => "shark",
|
|
||||||
Element::SpinningGun => "spinninggun",
|
|
||||||
Element::Pusher => "pusher",
|
|
||||||
Element::Lion => "lion",
|
|
||||||
Element::Tiger => "tiger",
|
|
||||||
Element::BlinkRayV => "blink_ray_v",
|
|
||||||
Element::Head => "head",
|
|
||||||
Element::Segment => "segment",
|
|
||||||
Element::TextBlue => "text_blue",
|
|
||||||
Element::TextGreen => "text_green",
|
|
||||||
Element::TextCyan => "text_cyan",
|
|
||||||
Element::TextRed => "text_red",
|
|
||||||
Element::TextPurple => "text_purple",
|
|
||||||
Element::TextBrown => "text_brown",
|
|
||||||
Element::TextBlack => "text_black",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the alias for parameter 1 based on element type.
|
|
||||||
pub fn p1_alias(self) -> Option<&'static str> {
|
|
||||||
match self {
|
|
||||||
Element::BlinkWall => Some("start_time"),
|
|
||||||
Element::Bear => Some("sensitivity"),
|
|
||||||
Element::Ruffian => Some("intelligence"),
|
|
||||||
Element::Object => Some("char"),
|
|
||||||
Element::Shark => Some("intelligence"),
|
|
||||||
Element::SpinningGun => Some("intelligence"),
|
|
||||||
Element::Lion => Some("intelligence"),
|
|
||||||
Element::Tiger => Some("intelligence"),
|
|
||||||
Element::Head => Some("intelligence"),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the alias for parameter 2 based on element type.
|
|
||||||
pub fn p2_alias(self) -> Option<&'static str> {
|
|
||||||
match self {
|
|
||||||
Element::Duplicator => Some("rate"),
|
|
||||||
Element::BlinkWall => Some("period"),
|
|
||||||
Element::Ruffian => Some("resting_time"),
|
|
||||||
Element::Slime => Some("speed"),
|
|
||||||
Element::SpinningGun => Some("firing_rate"),
|
|
||||||
Element::Tiger => Some("firing_rate"),
|
|
||||||
Element::Head => Some("deviance"),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the alias for parameter 3 based on element type.
|
|
||||||
pub fn p3_alias(self) -> Option<&'static str> {
|
|
||||||
match self {
|
|
||||||
Element::Passage => Some("destination"),
|
|
||||||
Element::SpinningGun => Some("firing_type"),
|
|
||||||
Element::Tiger => Some("firing_type"),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Map alias name to parameter number (1, 2, or 3) based on element type.
|
|
||||||
pub fn alias_to_param(self, alias: &str) -> Option<u8> {
|
|
||||||
if self.p1_alias() == Some(alias) {
|
|
||||||
Some(1)
|
|
||||||
} else if self.p2_alias() == Some(alias) {
|
|
||||||
Some(2)
|
|
||||||
} else if self.p3_alias() == Some(alias) {
|
|
||||||
Some(3)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resolve alias name to parameter number, with optional element context.
|
|
||||||
/// Falls back to checking all known aliases if element is None.
|
|
||||||
pub fn resolve_alias(alias: &str, element: Option<Element>) -> Option<u8> {
|
|
||||||
// If we have an element, use its specific alias mapping
|
|
||||||
if let Some(elem) = element {
|
|
||||||
if let Some(param) = elem.alias_to_param(alias) {
|
|
||||||
return Some(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: check all known aliases
|
|
||||||
// p1 aliases
|
|
||||||
if matches!(
|
|
||||||
alias,
|
|
||||||
"char" | "sensitivity" | "intelligence" | "start_time"
|
|
||||||
) {
|
|
||||||
return Some(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// p2 aliases
|
|
||||||
if matches!(
|
|
||||||
alias,
|
|
||||||
"rate" | "period" | "resting_time" | "speed" | "firing_rate" | "deviance"
|
|
||||||
) {
|
|
||||||
return Some(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// p3 aliases
|
|
||||||
if matches!(alias, "destination" | "firing_type") {
|
|
||||||
return Some(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the human-readable name for an element ID, or describe unknown elements.
|
|
||||||
pub fn element_name(id: u8) -> String {
|
|
||||||
match Element::from_u8(id) {
|
|
||||||
Some(e) => e.name().to_string(),
|
|
||||||
None => format!("unknown ({})", id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert an element name back to its ID.
|
|
||||||
/// Handles "unknown_N" format for unknown element IDs.
|
|
||||||
pub fn element_id_from_name(name: &str) -> Option<u8> {
|
|
||||||
// Handle "unknown_N" format first
|
|
||||||
if let Some(suffix) = name.strip_prefix("unknown_") {
|
|
||||||
return suffix.parse().ok();
|
|
||||||
}
|
|
||||||
// Match all known element names to their IDs
|
|
||||||
match name {
|
|
||||||
"empty" => Some(0),
|
|
||||||
"board_edge" => Some(1),
|
|
||||||
"messenger" => Some(2),
|
|
||||||
"monitor" => Some(3),
|
|
||||||
"player" => Some(4),
|
|
||||||
"ammo" => Some(5),
|
|
||||||
"torch" => Some(6),
|
|
||||||
"gem" => Some(7),
|
|
||||||
"key" => Some(8),
|
|
||||||
"door" => Some(9),
|
|
||||||
"scroll" => Some(10),
|
|
||||||
"passage" => Some(11),
|
|
||||||
"duplicator" => Some(12),
|
|
||||||
"bomb" => Some(13),
|
|
||||||
"energizer" => Some(14),
|
|
||||||
"star" => Some(15),
|
|
||||||
"clockwise" => Some(16),
|
|
||||||
"counter" => Some(17),
|
|
||||||
"bullet" => Some(18),
|
|
||||||
"water" => Some(19),
|
|
||||||
"forest" => Some(20),
|
|
||||||
"solid" => Some(21),
|
|
||||||
"normal" => Some(22),
|
|
||||||
"breakable" => Some(23),
|
|
||||||
"boulder" => Some(24),
|
|
||||||
"sliderns" => Some(25),
|
|
||||||
"sliderew" => Some(26),
|
|
||||||
"fake" => Some(27),
|
|
||||||
"invisible" => Some(28),
|
|
||||||
"blinkwall" => Some(29),
|
|
||||||
"transporter" => Some(30),
|
|
||||||
"line" => Some(31),
|
|
||||||
"ricochet" => Some(32),
|
|
||||||
"blink_ray_h" => Some(33),
|
|
||||||
"bear" => Some(34),
|
|
||||||
"ruffian" => Some(35),
|
|
||||||
"object" => Some(36),
|
|
||||||
"slime" => Some(37),
|
|
||||||
"shark" => Some(38),
|
|
||||||
"spinninggun" => Some(39),
|
|
||||||
"pusher" => Some(40),
|
|
||||||
"lion" => Some(41),
|
|
||||||
"tiger" => Some(42),
|
|
||||||
"blink_ray_v" => Some(43),
|
|
||||||
"head" => Some(44),
|
|
||||||
"segment" => Some(45),
|
|
||||||
// 46 is unused
|
|
||||||
"text_blue" => Some(47),
|
|
||||||
"text_green" => Some(48),
|
|
||||||
"text_cyan" => Some(49),
|
|
||||||
"text_red" => Some(50),
|
|
||||||
"text_purple" => Some(51),
|
|
||||||
"text_brown" => Some(52),
|
|
||||||
"text_black" => Some(53),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ mod encoding;
|
|||||||
mod error;
|
mod error;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
|
||||||
pub use elements::{Element, element_id_from_name, element_name, resolve_alias};
|
pub use elements::Element;
|
||||||
pub use encoding::{decode_multiline, decode_oneline, encode_multiline, encode_oneline};
|
pub use encoding::{decode_multiline, decode_oneline, encode_multiline, encode_oneline};
|
||||||
pub use error::ParseError;
|
pub use error::ParseError;
|
||||||
pub use parse::{Board, Program, Stat, Tile, World};
|
pub use parse::{Board, Program, Stat, Tile, World};
|
||||||
|
|||||||
Reference in New Issue
Block a user