-
Notifications
You must be signed in to change notification settings - Fork 0
Act IV opens: The Selection (visual mode) + Inner Sanctum (inner text objects) #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| { | ||
| "id": "act4-23-the-selection", | ||
| "act": 4, "order": 23, | ||
| "title": "The Selection", | ||
| "story": "The Archives open. Before automation comes sight: press v and watch your selection glow before you commit the cut.", | ||
| "challenges": [ | ||
| { | ||
| "id": "a4-selection-c1", | ||
| "intro": "Purge the middle of the incantation — see it selected first.", | ||
| "buffer": ["purge every last echo now"], "cursor": [0, 6], | ||
| "goal": { "type": "bufferEquals", "lines": ["purge now"] }, | ||
| "par": 6, "xp": 80, | ||
| "hint": "v starts a selection; motions grow it; d cuts everything selected.", | ||
| "newKeys": ["v"], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| }, | ||
| { | ||
| "id": "a4-selection-c2", | ||
| "intro": "Echo the spell-word — select it, yank it, paste it.", | ||
| "buffer": ["the spell of binding"], "cursor": [0, 4], | ||
| "goal": { "type": "bufferEquals", "lines": ["the spell spell of binding"] }, | ||
| "par": 7, "xp": 80, | ||
| "hint": "y yanks the selection; p pastes it after the cursor.", | ||
| "newKeys": ["vy"], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| }, | ||
| { | ||
| "id": "a4-selection-c3", | ||
| "intro": "The gate must swing — select 'of iron' and rewrite it.", | ||
| "buffer": ["the gate of iron holds"], "cursor": [0, 9], | ||
| "goal": { "type": "bufferEquals", "lines": ["the gate ajar holds"] }, | ||
| "par": 8, "xp": 80, | ||
| "hint": "c cuts the selection and drops you into Insert mode.", | ||
| "newKeys": ["vc"], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| { | ||
| "id": "act4-24-inner-sanctum", | ||
| "act": 4, "order": 24, | ||
| "title": "Inner Sanctum", | ||
| "story": "Deep in the Archives, meaning nests inside delimiters. Inner objects strike whole spans: quoted words, bracketed spells, entire paragraphs.", | ||
| "challenges": [ | ||
| { | ||
| "id": "a4-sanctum-c1", | ||
| "intro": "The password is wrong. Rewrite what's inside the quotes — from anywhere.", | ||
| "buffer": ["speak \"the old password\" aloud"], "cursor": [0, 10], | ||
| "goal": { "type": "bufferEquals", "lines": ["speak \"hooray\" aloud"] }, | ||
| "par": 9, "xp": 80, | ||
| "hint": "ci\" changes everything inside the quotes, wherever the cursor sits in them.", | ||
| "newKeys": ["ci\""], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| }, | ||
| { | ||
| "id": "a4-sanctum-c2", | ||
| "intro": "The trap is armed inside the brackets. Empty them — one strike.", | ||
| "buffer": ["disarm(the trap inside) safely"], "cursor": [0, 12], | ||
| "goal": { "type": "bufferEquals", "lines": ["disarm() safely"] }, | ||
| "par": 3, "xp": 80, | ||
| "hint": "di( deletes everything inside the parentheses.", | ||
| "newKeys": ["di("], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| }, | ||
| { | ||
| "id": "a4-sanctum-c3", | ||
| "intro": "Purge the corrupted stanza — every line of it, one command.", | ||
| "buffer": ["keep this verse", "", "corrupt line one", "corrupt line two", "", "keep this verse too"], "cursor": [3, 2], | ||
| "goal": { "type": "bufferEquals", "lines": ["keep this verse", "", "", "keep this verse too"] }, | ||
| "par": 3, "xp": 80, | ||
| "hint": "dip deletes the whole paragraph under the cursor.", | ||
| "newKeys": ["dip"], | ||
| "allowedKeys": ["h", "j", "k", "l", "w", "b", "e", "0", "$", "^", "g", "G", "i", "a", "A", "I", "o", "O", "x", "d", "c", "y", "p", "P", "u", "ctrl+r", "r", "~", "J", "D", "C", "/", "n", "*", "N", "f", ";", ",", "%", ":", "v"] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -10,7 +10,7 @@ content-integrity test picks it up. | |||||
| act<ACT>-<ORDER>-<slug>.json e.g. act2-06-the-deletion-pits.json | ||||||
| ``` | ||||||
|
|
||||||
| `ACT` is 1–3 and `ORDER` is the global lesson order (lessons are sorted by `(act, order)`). | ||||||
| `ACT` is 1–4 and `ORDER` is the global lesson order (lessons are sorted by `(act, order)`). | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Update the schema example to match the new act range. The file-naming rule now says Suggested fix- "act": 2, // 1..3
+ "act": 2, // 1..4📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| Keep `order` unique and increasing across the whole game. | ||||||
|
|
||||||
| ## Schema | ||||||
|
|
@@ -81,15 +81,16 @@ gated. Omit `allowedKeys` (boss steps do) to allow everything. | |||||
|
|
||||||
| `internal/content/loader_test.go` and `solvable_test.go` will fail the build unless: | ||||||
|
|
||||||
| 1. Every lesson has a unique `id`, an act in 1–3, and `order` increasing across the game. | ||||||
| 1. Every lesson has a unique `id`, an act in 1–4, and `order` increasing across the game. | ||||||
| 2. Every challenge & boss-step `id` is globally unique. | ||||||
| 3. Every `cursor` is in bounds (`col` may equal the line length for append-at-end). | ||||||
| 4. Every `goal.type` is valid and its payload field is non-empty. | ||||||
| 5. **Every challenge and boss step has a non-empty `hint`** (the `[?]` key renders it; an | ||||||
| empty hint shows the player nothing). | ||||||
| 6. Regular challenges have `par >= 1` and `xp > 0`; bosses have `timeLimitSec >= 30`, | ||||||
| `xp > 0`, and at least one step. | ||||||
| 7. The act's final lesson (and only it) carries a `boss`. | ||||||
| 7. A `boss` may sit only on its act's final lesson; every act except the highest | ||||||
| (still under construction) must end with one. | ||||||
| 8. **Every challenge is solvable at par.** `solvable_test.go` plays an authored optimal | ||||||
| key sequence through the real engine and asserts the goal is met within par. When you | ||||||
| add a challenge, add its solution there too. | ||||||
|
|
@@ -110,7 +111,7 @@ To add a lesson teaching `t` (till char) — once the engine supports `t`: | |||||
|
|
||||||
| # Roadmap: the full curriculum | ||||||
|
|
||||||
| The target curriculum: 29 lessons across four acts — 22 shipped, 7 planned. Lesson | ||||||
| The target curriculum: 29 lessons across four acts — 24 shipped, 5 planned. Lesson | ||||||
| selection follows the consensus analysis in | ||||||
| [`LESSON-GAP-ANALYSIS.md`](LESSON-GAP-ANALYSIS.md) (vimtutor, Learn-Vim, Vim Adventures, | ||||||
| VimGolf et al.); phases mirror the original design spec | ||||||
|
|
@@ -167,19 +168,21 @@ lesson must carry the act's boss — starting Act IV boss-less broke that invari | |||||
| They live in Act III instead (where `:%s` sat in the original roadmap), and Act IV | ||||||
| stays the pure automation world.* | ||||||
|
|
||||||
| ### Act IV · The Archives — power tools (all planned) | ||||||
| ### Act IV · The Archives — power tools | ||||||
|
|
||||||
| Library/clockwork theme for automation. | ||||||
| Library/clockwork theme for automation. Under construction: until The Macro Forge | ||||||
| lands, this act has no boss and the game finale is unreachable (the content test | ||||||
| allows a boss-less final act while it grows). | ||||||
|
|
||||||
| | # | Lesson | Teaches | Engine work | | ||||||
| | --- | --- | --- | --- | | ||||||
| | 23 | The Selection | Visual `v` + `d/y/c` | medium: anchor + selection range | | ||||||
| | 24 | Inner Sanctum | `i" i( ip` text objects | small-medium: generalize `pendingInner` beyond `w` | | ||||||
| | 25 | The Echo Rite | `.` repeat | medium: record + replay the last change | | ||||||
| | 26 | Waypoints | marks `m{a-z}` `` `{a-z} `` | medium: per-buffer mark table | | ||||||
| | 27 | The Registers | `"a`–`"z` yank/paste | medium: register map through yank/delete/paste | | ||||||
| | 28 | Block Party | `Ctrl-v` + column `I/A` | larger: rectangular selection | | ||||||
| | 29 | The Macro Forge · **boss: The Archivist** | `q{reg}…q` `@{reg}` `@@` | larger: keystroke record & replay | | ||||||
| | # | Lesson | Teaches | Status | Engine work | | ||||||
| | --- | --- | --- | --- | --- | | ||||||
| | 23 | The Selection | Visual `v` + `d/y/c` | ✅ | | | ||||||
| | 24 | Inner Sanctum | `i" i( ip` text objects | ✅ | | | ||||||
| | 25 | The Echo Rite | `.` repeat | 📋 | medium: record + replay the last change | | ||||||
| | 26 | Waypoints | marks `m{a-z}` `` `{a-z} `` | 📋 | medium: per-buffer mark table | | ||||||
| | 27 | The Registers | `"a`–`"z` yank/paste | 📋 | medium: register map through yank/delete/paste | | ||||||
| | 28 | Block Party | `Ctrl-v` + column `I/A` | 📋 | larger: rectangular selection | | ||||||
| | 29 | The Macro Forge · **boss: The Archivist** | `q{reg}…q` `@{reg}` `@@` | 📋 | larger: keystroke record & replay | | ||||||
|
|
||||||
| Once command-line mode exists, `:g/pattern/d` (Learn-Vim ch13) is a natural bonus room | ||||||
| inside The Great Substitution — no extra lesson needed. | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.