Compare commits

...

7 Commits

17 changed files with 94 additions and 51 deletions

View File

@ -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"

15
src/bin/bitsy-parse.rs Normal file
View File

@ -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");
}

View 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());
}
}

View File

@ -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(),

View File

@ -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(),

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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()
);

View File

@ -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);

View File

@ -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);

View File

@ -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,
],
}],

View File

@ -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()),

View File

@ -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())
}
}

View File

@ -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()]);

View File

@ -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());
}
}

View File

@ -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();

View File

@ -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(),