Compare commits
7 Commits
8d5580f827
...
b5050720d8
Author | SHA1 | Date |
---|---|---|
Max Bradbury | b5050720d8 | |
Max Bradbury | f2ae43e85f | |
Max Bradbury | c05010432a | |
Max Bradbury | b47a9f3911 | |
Max Bradbury | 03fc231476 | |
Max Bradbury | bfc6fe29ea | |
Max Bradbury | 50e4530984 |
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bitsy-parser"
|
||||
version = "0.71.5"
|
||||
version = "0.71.6"
|
||||
authors = ["Max Bradbury <max@tinybird.info>"]
|
||||
edition = "2018"
|
||||
description = "A parser and utilities for working with Bitsy game data"
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
extern crate bitsy_parser;
|
||||
use bitsy_parser::game::Game;
|
||||
use std::{env, fs};
|
||||
|
||||
const SYNTAX_ERROR: &str = "Usage: `bitsy-parse input.bitsy output.bitsy`";
|
||||
|
||||
/// simply parses and re-exports a game. use to test whether output matches input.
|
||||
fn main() {
|
||||
let input = env::args().nth(1).expect(SYNTAX_ERROR);
|
||||
let output = env::args().nth(2).expect(SYNTAX_ERROR);
|
||||
|
||||
let game = Game::from(fs::read_to_string(input).unwrap()).unwrap();
|
||||
|
||||
fs::write(output, game.to_string()).expect("Failed to write output file");
|
||||
}
|
|
@ -35,7 +35,7 @@ mod test {
|
|||
use crate::colour::Colour;
|
||||
|
||||
#[test]
|
||||
fn test_colour_from_string() {
|
||||
fn colour_from_string() {
|
||||
assert_eq!(
|
||||
Colour::from("0,255,0").unwrap(),
|
||||
Colour { red: 0, green: 255, blue: 0 }
|
||||
|
@ -43,22 +43,22 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_colour_to_string() {
|
||||
fn colour_to_string() {
|
||||
assert_eq!(Colour { red: 22, green: 33, blue: 44, }.to_string(), "22,33,44".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_colour_missing_value() {
|
||||
fn colour_missing_value() {
|
||||
assert!(Colour::from("0,0").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_colour_ambiguous_value() {
|
||||
fn colour_ambiguous_value() {
|
||||
assert!(Colour::from("0,0,").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_colour_extraneous_value() {
|
||||
fn colour_extraneous_value() {
|
||||
assert!(Colour::from("0,0,0,0").is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ mod test {
|
|||
use crate::dialogue::Dialogue;
|
||||
|
||||
#[test]
|
||||
fn test_dialogue_from_string() {
|
||||
fn dialogue_from_string() {
|
||||
let output = Dialogue::from(
|
||||
"DLG h\nhello\nNAME not a dialogue name\nNAME a dialogue name".to_string()
|
||||
);
|
||||
|
@ -56,7 +56,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_dialogue_to_string() {
|
||||
fn dialogue_to_string() {
|
||||
let output = Dialogue {
|
||||
id: "y".to_string(),
|
||||
contents: "This is a bit of dialogue,\nblah blah\nblah blah".to_string(),
|
||||
|
|
|
@ -35,7 +35,7 @@ mod test {
|
|||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_ending_from_string() {
|
||||
fn ending_from_string() {
|
||||
assert_eq!(
|
||||
Ending::from_str(include_str!("test-resources/ending")).unwrap(),
|
||||
Ending {
|
||||
|
@ -46,7 +46,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_ending_to_string() {
|
||||
fn ending_to_string() {
|
||||
assert_eq!(
|
||||
Ending {
|
||||
id: "7".to_string(),
|
||||
|
|
|
@ -103,7 +103,7 @@ mod test {
|
|||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_exit_from_string() {
|
||||
fn exit_from_string() {
|
||||
assert_eq!(
|
||||
Exit::from_str("a 12,13").unwrap(),
|
||||
Exit {
|
||||
|
@ -115,7 +115,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_from_string_with_fx() {
|
||||
fn exit_from_string_with_fx() {
|
||||
assert_eq!(
|
||||
Exit::from_str("a 12,13 FX slide_u").unwrap(),
|
||||
Exit {
|
||||
|
@ -127,7 +127,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_to_string() {
|
||||
fn exit_to_string() {
|
||||
assert_eq!(
|
||||
Exit {
|
||||
room_id: "8".to_string(),
|
||||
|
@ -139,7 +139,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_to_string_with_fx() {
|
||||
fn exit_to_string_with_fx() {
|
||||
assert_eq!(
|
||||
Exit {
|
||||
room_id: "8".to_string(),
|
||||
|
|
45
src/game.rs
45
src/game.rs
|
@ -3,6 +3,7 @@ use loe::TransformMode;
|
|||
use std::str::FromStr;
|
||||
use std::collections::HashMap;
|
||||
use std::borrow::BorrowMut;
|
||||
use crate::image::Image;
|
||||
|
||||
/// in very early versions of Bitsy, room tiles were defined as single alphanumeric characters -
|
||||
/// so there was a maximum of 36 unique tiles. later versions are comma-separated.
|
||||
|
@ -662,6 +663,10 @@ impl Game {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn find_tile_with_animation(&self, animation: &Vec<Image>) -> Option<&Tile> {
|
||||
self.tiles.iter().find(|&tile| &tile.animation_frames == animation)
|
||||
}
|
||||
|
||||
/// adds a palette safely and returns the ID
|
||||
pub fn add_palette(&mut self, mut palette: Palette) -> String {
|
||||
let new_id = try_id(&self.palette_ids(), &palette.id);
|
||||
|
@ -835,7 +840,7 @@ mod test {
|
|||
use crate::image::Image;
|
||||
|
||||
#[test]
|
||||
fn test_game_from_string() {
|
||||
fn game_from_string() {
|
||||
let output = Game::from(include_str!["test-resources/default.bitsy"].to_string()).unwrap();
|
||||
let expected = crate::mock::game_default();
|
||||
|
||||
|
@ -843,19 +848,19 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_game_to_string() {
|
||||
fn game_to_string() {
|
||||
let output = crate::mock::game_default().to_string();
|
||||
let expected = include_str!["test-resources/default.bitsy"].to_string();
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tile_ids() {
|
||||
fn tile_ids() {
|
||||
assert_eq!(crate::mock::game_default().tile_ids(), vec!["a".to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_tile_id() {
|
||||
fn new_tile_id() {
|
||||
// default tile has an id of 10 ("a"), and 0 is reserved
|
||||
assert_eq!(crate::mock::game_default().new_tile_id(), "1".to_string());
|
||||
|
||||
|
@ -887,7 +892,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_tile() {
|
||||
fn add_tile() {
|
||||
let mut game = crate::mock::game_default();
|
||||
let new_id = game.add_tile(crate::mock::tile_default());
|
||||
assert_eq!(new_id, "1".to_string());
|
||||
|
@ -898,7 +903,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_arabic() {
|
||||
fn arabic() {
|
||||
let game = Game::from(include_str!("test-resources/arabic.bitsy").to_string()).unwrap();
|
||||
|
||||
assert_eq!(game.font, Font::Arabic);
|
||||
|
@ -906,14 +911,14 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_formatting() {
|
||||
fn version_formatting() {
|
||||
let mut game = crate::mock::game_default();
|
||||
game.version = Some(Version { major: 5, minor: 0 });
|
||||
assert!(game.to_string().contains("# BITSY VERSION 5.0"))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_tiles_for_room() {
|
||||
fn get_tiles_for_room() {
|
||||
assert_eq!(
|
||||
crate::mock::game_default().get_tiles_for_room("0".to_string()).unwrap(),
|
||||
vec![&crate::mock::tile_default()]
|
||||
|
@ -921,7 +926,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_item() {
|
||||
fn add_item() {
|
||||
let mut game = crate::mock::game_default();
|
||||
game.add_item(crate::mock::item());
|
||||
game.add_item(crate::mock::item());
|
||||
|
@ -934,7 +939,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge() {
|
||||
fn merge() {
|
||||
// try merging two default games
|
||||
let mut game = crate::mock::game_default();
|
||||
game.merge(crate::mock::game_default());
|
||||
|
@ -981,7 +986,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_dedupe_tiles() {
|
||||
fn dedupe_tiles() {
|
||||
let mut game = crate::mock::game_default();
|
||||
game.add_tile(crate::mock::tile_default());
|
||||
game.add_tile(crate::mock::tile_default());
|
||||
|
@ -1036,4 +1041,22 @@ mod test {
|
|||
|
||||
assert_eq!(game.tiles, vec![crate::mock::tile_default(), tile_a, tile_b]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_tile_with_animation() {
|
||||
let game = crate::mock::game_default();
|
||||
let animation = vec![Image { pixels: vec![
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
]}];
|
||||
let output = game.find_tile_with_animation(&animation);
|
||||
let expected = Some(&game.tiles[0]);
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ mod test {
|
|||
use crate::mock;
|
||||
|
||||
#[test]
|
||||
fn test_image_from_string() {
|
||||
fn image_from_string() {
|
||||
let output = Image::from(
|
||||
include_str!("test-resources/image").to_string()
|
||||
);
|
||||
|
@ -122,7 +122,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_image_to_string() {
|
||||
fn image_to_string() {
|
||||
let output = mock::image::chequers_1().to_string();
|
||||
let expected = include_str!("test-resources/image-chequers-1").to_string();
|
||||
assert_eq!(output, expected);
|
||||
|
@ -142,7 +142,7 @@ mod test {
|
|||
/// lots of Bitsy games have editor errors where pixels can be placed out of bounds
|
||||
/// check that these extraneous pixels are stripped out
|
||||
#[test]
|
||||
fn test_image_out_of_bounds() {
|
||||
fn image_out_of_bounds() {
|
||||
let output = Image::from(
|
||||
include_str!("test-resources/image-oob").to_string()
|
||||
);
|
||||
|
|
|
@ -81,14 +81,14 @@ mod test {
|
|||
use crate::mock;
|
||||
|
||||
#[test]
|
||||
fn test_item_from_string() {
|
||||
fn item_from_string() {
|
||||
let output = Item::from(include_str!("test-resources/item").to_string());
|
||||
let expected = mock::item();
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_item_to_string() {
|
||||
fn item_to_string() {
|
||||
let output = mock::item().to_string();
|
||||
let expected = include_str!("test-resources/item").to_string();
|
||||
assert_eq!(output, expected);
|
||||
|
|
|
@ -189,7 +189,7 @@ mod test {
|
|||
use crate::{ToBase36, optional_data_line, mock, segments_from_string, Quote, Unquote, new_unique_id, try_id};
|
||||
|
||||
#[test]
|
||||
fn test_to_base36() {
|
||||
fn to_base36() {
|
||||
assert_eq!((37 as u64).to_base36(), "11");
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_to_segments() {
|
||||
fn string_to_segments() {
|
||||
let output = segments_from_string(
|
||||
include_str!("./test-resources/segments").to_string()
|
||||
);
|
||||
|
@ -216,14 +216,14 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_quote() {
|
||||
fn quote() {
|
||||
let output = "this is a string.\nIt has 2 lines".to_string().quote();
|
||||
let expected = "\"\"\"\nthis is a string.\nIt has 2 lines\n\"\"\"".to_string();
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unquote() {
|
||||
fn unquote() {
|
||||
let output = "\"\"\"\nwho the fuck is scraeming \"LOG OFF\" at my house.\nshow yourself, coward.\ni will never log off\n\"\"\"".to_string().unquote();
|
||||
let expected = "who the fuck is scraeming \"LOG OFF\" at my house.\nshow yourself, coward.\ni will never log off".to_string();
|
||||
assert_eq!(output, expected);
|
||||
|
|
|
@ -136,8 +136,13 @@ pub fn tile_default() -> Tile {
|
|||
wall: None,
|
||||
animation_frames: vec![Image {
|
||||
pixels: vec![
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 1, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
],
|
||||
}],
|
||||
|
|
|
@ -53,7 +53,7 @@ mod test {
|
|||
use crate::palette::Palette;
|
||||
|
||||
#[test]
|
||||
fn test_palette_from_string() {
|
||||
fn palette_from_string() {
|
||||
let output = Palette::from("PAL 1\nNAME lamplight\n45,45,59\n66,60,39\n140,94,1".to_string());
|
||||
|
||||
let expected = Palette {
|
||||
|
@ -82,7 +82,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_palette_from_string_no_name() {
|
||||
fn palette_from_string_no_name() {
|
||||
let output = Palette::from("PAL 9\n45,45,59\n66,60,39\n140,94,1".to_string());
|
||||
|
||||
let expected = Palette {
|
||||
|
@ -111,7 +111,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_palette_to_string() {
|
||||
fn palette_to_string() {
|
||||
let output = Palette {
|
||||
id: "g".to_string(),
|
||||
name: Some("moss".to_string()),
|
||||
|
|
|
@ -42,7 +42,7 @@ mod test {
|
|||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_position_from_str() {
|
||||
fn position_from_str() {
|
||||
assert_eq!(
|
||||
Position::from_str(&"4,12").unwrap(),
|
||||
Position { x: 4, y: 12 }
|
||||
|
@ -50,7 +50,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_position_to_string() {
|
||||
fn position_to_string() {
|
||||
assert_eq!(Position { x: 4, y: 12 }.to_string(), "4,12".to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,7 +234,7 @@ mod test {
|
|||
use crate::game::{RoomType, RoomFormat};
|
||||
|
||||
#[test]
|
||||
fn test_room_from_string() {
|
||||
fn room_from_string() {
|
||||
assert_eq!(
|
||||
Room::from(include_str!("test-resources/room").to_string()),
|
||||
crate::mock::room()
|
||||
|
@ -242,7 +242,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_room_to_string() {
|
||||
fn room_to_string() {
|
||||
assert_eq!(
|
||||
crate::mock::room().to_string(RoomFormat::CommaSeparated, RoomType::Room),
|
||||
include_str!("test-resources/room").to_string()
|
||||
|
@ -250,7 +250,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_room_walls_array() {
|
||||
fn room_walls_array() {
|
||||
let output = Room::from(include_str!("test-resources/room-with-walls").to_string());
|
||||
|
||||
assert_eq!(output.walls, vec!["a".to_string(), "f".to_string()]);
|
||||
|
|
|
@ -132,7 +132,7 @@ mod test {
|
|||
use crate::sprite::Sprite;
|
||||
|
||||
#[test]
|
||||
fn test_sprite_from_string() {
|
||||
fn sprite_from_string() {
|
||||
let string = include_str!("test-resources/sprite").to_string();
|
||||
let output = Sprite::from(string).unwrap();
|
||||
let expected = mock::sprite();
|
||||
|
@ -141,7 +141,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_sprite_to_string() {
|
||||
fn sprite_to_string() {
|
||||
assert_eq!(mock::sprite().to_string(), include_str!("test-resources/sprite").to_string());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ mod test {
|
|||
use crate::mock;
|
||||
|
||||
#[test]
|
||||
fn test_tile_from_string() {
|
||||
fn tile_from_string() {
|
||||
let output = Tile::from(include_str!("test-resources/tile").to_string());
|
||||
|
||||
let expected = Tile {
|
||||
|
@ -152,7 +152,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tile_to_string() {
|
||||
fn tile_to_string() {
|
||||
let output = Tile {
|
||||
id: "7a".to_string(),
|
||||
name: Some("chequers".to_string()),
|
||||
|
@ -171,7 +171,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq() {
|
||||
fn partial_eq() {
|
||||
let tile_a = crate::mock::tile_default();
|
||||
let mut tile_b = crate::mock::tile_default();
|
||||
tile_b.id = "0".to_string();
|
||||
|
|
|
@ -30,7 +30,7 @@ mod test {
|
|||
use crate::variable::Variable;
|
||||
|
||||
#[test]
|
||||
fn test_variable_from_string() {
|
||||
fn variable_from_string() {
|
||||
assert_eq!(
|
||||
Variable::from("VAR a\n42".to_string()),
|
||||
Variable {
|
||||
|
@ -41,7 +41,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_variable_to_string() {
|
||||
fn variable_to_string() {
|
||||
let output = Variable {
|
||||
id: "c".to_string(),
|
||||
initial_value: "57".to_string(),
|
||||
|
|
Loading…
Reference in New Issue