add more levels and organise them into sections

This commit is contained in:
Crispy 2024-10-10 20:51:19 +02:00
parent 172cfc9409
commit 67557832fa
12 changed files with 96 additions and 28 deletions

View file

@ -8,6 +8,7 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble
story/lore story/lore
timestamps in solutions and blueprints timestamps in solutions and blueprints
multiple input/output sets multiple input/output sets
undo/redo
tooltips tooltips
lock tile types for early levels to make it less overwhelming lock tile types for early levels to make it less overwhelming
make a gui alternative to pressing R to rotate between tile variants make a gui alternative to pressing R to rotate between tile variants
@ -79,16 +80,16 @@ blueprint rotation?
## levels ## levels
### intro, basic mechanics ### intro, basic mechanics
- output a zero - output a zero (marble, io)
- output two numbers in sequence - output multiple numbers in sequence (digits)
- output zeroes forever (looping) - output zeroes forever (looping, trigger, bag output)
- copy the input - copy the input (input)
- copy only odd input numbers - copy only odd input numbers (comparator, flipper)
### 0-terminated list processing ### 0-terminated list processing
- calculate list length - calculate list length (math, bag input)
- count instances of 5 in a list - count instances of 5 in a list
- copy the second list (ignore input until first zero) - copy the second list
- reverse a list - reverse a list (bouncing)
### user-friendly numbers ### user-friendly numbers
- convert a number to decimal ascii - convert a number to decimal ascii
- parse an ascii number - parse an ascii number

View file

@ -1,9 +1,9 @@
{ {
"id": "intro_output", "id": "output",
"sort_order": 10, "sort_order": 11,
"name": "Zero", "name": "Zero",
"description": "learn how to output data", "description": "learn how to output data",
"init_board": "o o\n \n*P \n \n \n ", "init_board": "\n o \n\n I\n\n",
"inputs": [], "inputs": [],
"outputs": [0] "outputs": [0]
} }

View file

@ -0,0 +1,9 @@
{
"id": "digits",
"sort_order": 12,
"name": "Digits",
"description": "place digits and use number keys to assign them values",
"init_board": null,
"inputs": [],
"outputs": [4, 8, 16]
}

View file

@ -0,0 +1,9 @@
{
"id": "loop",
"sort_order": 13,
"name": "Loop",
"description": "repeated output",
"init_board": "\n \n o\n\n\n\n ^ \n\n",
"inputs": [],
"outputs": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}

View file

@ -1,6 +1,6 @@
{ {
"id": "intro_copy_input", "id": "copy_input",
"sort_order": 12, "sort_order": 14,
"name": "Copy Cat", "name": "Copy Cat",
"description": "read input and output the same thing", "description": "read input and output the same thing",
"init_board": null, "init_board": null,

View file

@ -0,0 +1,9 @@
{
"id": "copy_odd",
"sort_order": 15,
"name": "Odd Cat",
"description": "copy only the odd numbers from the input",
"init_board": null,
"inputs": [112, 92, 51, 79, 112, 96, 84, 59, 195, 208, 137, 196, 68, 204, 82, 148, 251, 56, 105, 38, 63, 204, 240, 220, 180, 54, 211, 17, 82, 17, 181, 43],
"outputs": [51, 79, 59, 195, 137, 251, 105, 63, 211, 17, 17, 181, 43]
}

View file

@ -1,9 +0,0 @@
{
"id": "intro_loop",
"sort_order": 11,
"name": "Loop",
"description": "repeated output",
"init_board": "o o\n \n*P \n \n \n ",
"inputs": [],
"outputs": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}

View file

@ -0,0 +1,9 @@
{
"id": "count_fives",
"sort_order": 22,
"name": "Fives",
"description": "count how many fives are in the input",
"init_board": null,
"inputs": [182, 236, 71, 5, 5, 242, 29, 99, 19, 230, 217, 5, 67, 5, 223, 224, 70, 243, 3, 74, 242, 5, 171, 31, 96, 5, 169, 70, 5, 163, 72, 5, 172, 148, 5, 208, 28, 220, 17, 184, 172, 238, 5, 105, 119, 5, 106, 100, 73, 53, 42, 221, 155, 5, 74, 100, 161, 36, 16, 239, 193, 164, 64, 162, 222, 155, 107, 14, 45, 52, 159, 31, 199, 124, 129, 0],
"outputs": [12]
}

View file

@ -0,0 +1,9 @@
{
"id": "list_length",
"sort_order": 21,
"name": "Length",
"description": "count how many numbers are in the input, until the first zero",
"init_board": null,
"inputs": [182, 236, 71, 5, 5, 242, 29, 99, 19, 230, 217, 5, 67, 5, 223, 224, 70, 243, 3, 74, 242, 5, 171, 31, 96, 5, 169, 70, 5, 163, 72, 5, 172, 148, 5, 208, 28, 220, 17, 184, 172, 238, 5, 105, 119, 5, 106, 100, 73, 53, 42, 221, 155, 5, 74, 100, 161, 36, 16, 239, 193, 164, 64, 162, 222, 155, 107, 14, 45, 52, 159, 31, 199, 124, 129, 0],
"outputs": [75]
}

View file

@ -0,0 +1,11 @@
{
"id": "null_separation",
"sort_order": 23,
"name": "Null Separation",
"description": "output everything after the first zero in the input data",
"init_board": null,
"inputs": [199, 34, 71, 209, 4, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 103, 33, 0],
"outputs": [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 103, 33],
"input_is_text": true,
"output_is_text": true
}

View file

@ -0,0 +1,11 @@
{
"id": "reverse_input",
"sort_order": 24,
"name": "Reverse",
"description": "read input until zero and output the same thing in reverse",
"init_board": null,
"inputs": [116, 110, 114, 111, 112, 109, 105, 32, 121, 114, 101, 118, 0],
"outputs": [118, 101, 114, 121, 32, 105, 109, 112, 111, 114, 110, 116],
"input_is_text": true,
"output_is_text": true
}

View file

@ -94,7 +94,7 @@ impl Game {
fn draw(&mut self, d: &mut RaylibDrawHandle) { fn draw(&mut self, d: &mut RaylibDrawHandle) {
d.clear_background(Color::new(64, 64, 64, 255)); d.clear_background(Color::new(64, 64, 64, 255));
let level_list_width = d.get_screen_width() / 3; let level_list_width = (d.get_screen_width() / 3).min(400);
let screen_height = d.get_screen_height(); let screen_height = d.get_screen_height();
d.draw_rectangle(0, 0, level_list_width, screen_height, Color::GRAY); d.draw_rectangle(0, 0, level_list_width, screen_height, Color::GRAY);
@ -230,21 +230,30 @@ impl Game {
fn get_levels() -> Vec<Level> { fn get_levels() -> Vec<Level> {
let mut levels = Vec::<Level>::new(); let mut levels = Vec::<Level>::new();
for d in read_dir("levels").unwrap().flatten() { let mut add_level = |path| {
let l = read_to_string(d.path()) let l = read_to_string(path)
.ok() .ok()
.as_deref() .as_deref()
.and_then(|s| serde_json::from_str(s).ok()); .and_then(|s| serde_json::from_str(s).ok());
if let Some(level) = l { if let Some(level) = l {
levels.push(level); levels.push(level);
} }
};
for d in read_dir("levels").unwrap().flatten() {
if d.path().is_dir() {
for d in read_dir(d.path()).unwrap().flatten() {
add_level(d.path());
}
} else {
add_level(d.path());
}
} }
levels.sort_by_key(Level::sort_order); levels.sort_by_key(Level::sort_order);
levels levels
} }
fn get_solutions() -> HashMap<String, Vec<Solution>> { fn get_solutions() -> HashMap<String, Vec<Solution>> {
let mut levels = HashMap::new(); let mut by_level = HashMap::new();
let solution_dir = userdata_dir().join("solutions"); let solution_dir = userdata_dir().join("solutions");
if let Ok(dir_contents) = read_dir(solution_dir) { if let Ok(dir_contents) = read_dir(solution_dir) {
for dir in dir_contents.flatten() { for dir in dir_contents.flatten() {
@ -263,11 +272,11 @@ fn get_solutions() -> HashMap<String, Vec<Solution>> {
} }
} }
levels.insert(level_name, solutions); by_level.insert(level_name, solutions);
} }
} }
} }
} }
levels by_level
} }