#include "levels/level.hpp" #include "utils/config.hpp" namespace Nimbin { Level::Data Level::build_CharCopy() { return { .steps = { // ── Step 0: main scaffold ───────────────────────────────────── { .grants = { Level::TokenGrant::give("int"), Level::TokenGrant::give("main"), Level::TokenGrant::give("("), Level::TokenGrant::choice({ "void", "int", "char" }), Level::TokenGrant::give(")"), Level::TokenGrant::give("{"), Level::TokenGrant::give("return"), Level::TokenGrant::give("0"), Level::TokenGrant::give(";"), Level::TokenGrant::give("}"), }, .scene = {}, .goal = Goal::CompilePattern{ "int main ( void ) { return 0 ; }" }, .hint = "Build a working main()", .details = R"(C programs start at main(). main() returns an int and takes 'void' to declare no arguments. The body returns 0 to mean success. Goal: int main(void) { return 0; } Grab tokens and arrange them on the editor wall.)", .reset_carry = false, .max_ai_words = 3, }, // ── Step 1: copy_str signature ──────────────────────────────── { .grants = { Level::TokenGrant::give("void"), Level::TokenGrant::give("copy_str"), Level::TokenGrant::give("("), Level::TokenGrant::choice({ "char", "int", "float" }), Level::TokenGrant::give("src"), Level::TokenGrant::give("["), Level::TokenGrant::give("]"), Level::TokenGrant::give(","), Level::TokenGrant::give("char"), Level::TokenGrant::give("dst"), Level::TokenGrant::give("["), Level::TokenGrant::give("]"), Level::TokenGrant::give(")"), Level::TokenGrant::give("{"), Level::TokenGrant::give("}"), }, .scene = {}, .goal = Goal::CompilePattern{ "void copy_str ( char src [ ] , char dst [ ] ) { }" }, .hint = "Declare the copy_str function", .details = R"(Now add a function above main(). copy_str takes two char arrays — a source and a destination — and returns nothing (void). Note the brackets [ ] on each parameter — that marks them as arrays. Goal: void copy_str(char src[], char dst[]) { } int main(void) { ... } Place this BEFORE main.)", .reset_carry = false, .max_ai_words = 3, }, // ── Step 2: loop counter ────────────────────────────────────── { .grants = { Level::TokenGrant::choice({ "int", "float", "char" }), Level::TokenGrant::give("i"), Level::TokenGrant::give(";"), }, .scene = {}, .goal = Goal::CompilePattern{ "void copy_str ( char src [ ] , char dst [ ] ) { int i ; }" }, .hint = "Add a loop counter inside copy_str", .details = R"(Inside copy_str's body, declare an integer to track our position in the array. Goal (inside copy_str): int i; You only need to add ONE line. Place it between the { and } of copy_str.)", .reset_carry = false, .max_ai_words = 3, }, // ── Step 3: for loop scaffold ───────────────────────────────── { .grants = { Level::TokenGrant::give("for"), Level::TokenGrant::give("("), Level::TokenGrant::give("i"), Level::TokenGrant::give("="), Level::TokenGrant::give("0"), Level::TokenGrant::give(";"), Level::TokenGrant::give("i"), Level::TokenGrant::give("<"), Level::TokenGrant::give("strlen"), Level::TokenGrant::give("("), Level::TokenGrant::give("src"), Level::TokenGrant::give(")"), Level::TokenGrant::give(";"), Level::TokenGrant::give("i"), Level::TokenGrant::give("++"), Level::TokenGrant::give(")"), Level::TokenGrant::give("{"), Level::TokenGrant::give("}"), }, .scene = {}, .goal = Goal::CompilePattern{ "for ( i = 0 ; i < strlen ( src ) ; i ++ ) { }" }, .hint = "Loop through src", .details = R"(Add a for loop after 'int i;'. It starts at 0 and stops when i reaches the length of src. strlen() gives the length of a C string. Goal: for (i = 0; i < strlen(src); i++) { } This is the loop scaffold only — the body comes next.)", .reset_carry = false, .max_ai_words = 3, }, // ── Step 4: copy the character ──────────────────────────────── { .grants = { Level::TokenGrant::give("dst"), Level::TokenGrant::give("["), Level::TokenGrant::give("i"), Level::TokenGrant::give("]"), Level::TokenGrant::give("="), Level::TokenGrant::give("src"), Level::TokenGrant::give("["), Level::TokenGrant::give("i"), Level::TokenGrant::give("]"), Level::TokenGrant::give(";"), }, .scene = {}, .goal = Goal::CompilePattern{ "dst [ i ] = src [ i ] ;" }, .hint = "Copy one character per iteration", .details = R"(Inside the for loop body, copy src[i] into dst[i]. This single statement is the heart of the function — it copies the i-th character on each pass through the loop. Goal (inside the for loop): dst[i] = src[i];)", .reset_carry = false, .max_ai_words = 3, }, // ── Step 5: call copy_str and print ────────────────────────── { .grants = { Level::TokenGrant::give("char"), Level::TokenGrant::give("dst"), Level::TokenGrant::give("["), Level::TokenGrant::give("100"), Level::TokenGrant::give("]"), Level::TokenGrant::give(";"), Level::TokenGrant::give("copy_str"), Level::TokenGrant::give("("), Level::TokenGrant::give("\"hello\""), Level::TokenGrant::give(","), Level::TokenGrant::give("dst"), Level::TokenGrant::give(")"), Level::TokenGrant::give(";"), Level::TokenGrant::give("printf"), Level::TokenGrant::give("("), Level::TokenGrant::choice({ "\"%s\"", "\"%d\"", "\"%c\"" }), Level::TokenGrant::give(","), Level::TokenGrant::give("dst"), Level::TokenGrant::give(")"), Level::TokenGrant::give(";"), }, .scene = {}, .goal = Goal::CompilePattern{ "char dst [ 100 ] ; copy_str ( \"hello\" , dst ) ; printf ( \"%s\" , dst ) ;" }, .hint = "Call copy_str and print the result", .details = R"(In main(), do three things before 'return 0;': 1. Declare a buffer: char dst[100]; 2. Call copy_str: copy_str("hello", dst); 3. Print the result: printf("%s", dst); The buffer holds the copied characters. copy_str fills it. printf displays it. Place all three lines BEFORE the existing return.)", .reset_carry = false, .max_ai_words = 3, }, }, .name = "Char Copy", .desc = "Implement a function that copies a char array and prints the result.", .dynamic_lib = false, }; } } // namespace Nimbin