# Module 7 scenarios: Resolving rules (NOT, identity, meta-nouns) Each heading is a test name. The Rust test lives in `tests/rust/test_07.rs` and the TypeScript test in `tests/ts/test_07.test.ts`; both state exactly what is written here. The level format, `place`, `rules()` and the way a test writes a sentence (`BABA (0,0) IS (1,0) YOU (2,0)` is three text objects) are those of Module 6. This module adds the operator `NOT` to the grammar, and two harness functions: - `rules()` is still everything the text spells, before resolution, and now includes negated rules, written `"BABA IS NOT YOU"`. - `activeRules()` is the rule set after the resolution pass: sorted, normalised strings, each distinct rule once. A rule `X IS NOT Y` cancels every `X IS Y`, wherever each is written; the negated rule itself stays in the set, because it keeps overriding. A rule `X IS X` that survives cancels every `X IS Y` whose `Y` is a noun other than `X` (Baba can't convert). The base rule `TEXT IS PUSH` is in it unless `TEXT IS NOT PUSH` cancels it. - `hasProperty(id, prop)` asks whether one object has a property under the active rules. A thing is named by its noun (a `baba` object by `BABA`); a text object is named by `TEXT`. The object has the property if an active rule gives it to one of its names and no active negated rule takes it away from one of its names. `X IS NOT X` is decided here and acted on later. It cancels `X IS X` (it is the negation of that rule, like any other), so other `X IS Y` conversions work again, and it stays in `activeRules()` as the record that every `X` is to vanish. Removing the objects is part of the turn, in Module 9. The tests check the cancellation and the unlocked conversion, which the sources state; they do not check that `"BABA IS NOT BABA"` is listed in `activeRules()`, which is this course's way of recording the deletion, not something the sources describe. `NOT` in front of a complement negates that complement only: `BABA IS NOT YOU AND WIN` is `BABA IS NOT YOU` and `BABA IS WIN`. `NOT` in front of a subject is not part of the course's grammar: the sentence it stands in spells nothing. Words used: the nouns `BABA`, `ROCK`; the properties `YOU`, `PUSH`; the operators `IS`, `NOT`; the meta-noun `TEXT`. ### test_07_not_overrides - Setup: `newBaba` with an empty level 4 wide and 5 high. Place `BABA (0,0) IS (1,0) YOU (2,0)` and an object `baba` at (0,4). - Assertions 1: `hasProperty(baba, "YOU")` is true. - Action: place `BABA (0,2) IS (1,2) NOT (2,2) YOU (3,2)`. - Assertions 2: - `rules()` is exactly `["BABA IS NOT YOU", "BABA IS YOU", "TEXT IS PUSH"]`: both sentences are still on the board. - `activeRules()` is exactly `["BABA IS NOT YOU", "TEXT IS PUSH"]`: the negation overrides `BABA IS YOU`, although that rule is written above it. - `hasProperty(baba, "YOU")` is false. ### test_07_x_is_x_blocks_conversion - Setup: `newBaba` with an empty level 3 wide and 5 high. Place `BABA (0,0) IS (1,0) BABA (2,0)`, `BABA (0,2) IS (1,2) ROCK (2,2)` and `ROCK (0,4) IS (1,4) BABA (2,4)`. - Assertions: - `rules()` is exactly `["BABA IS BABA", "BABA IS ROCK", "ROCK IS BABA", "TEXT IS PUSH"]`. - `activeRules()` is exactly `["BABA IS BABA", "ROCK IS BABA", "TEXT IS PUSH"]`. `BABA IS BABA` blocks Baba from converting into anything, so `BABA IS ROCK` is not active. It doesn't block other things from converting into Baba, so `ROCK IS BABA` is. ### test_07_x_is_not_x_deletes_and_unlocks - Setup: `newBaba` with an empty level 4 wide and 5 high. Place `BABA (0,0) IS (1,0) NOT (2,0) BABA (3,0)`, `BABA (0,2) IS (1,2) BABA (2,2)` and `BABA (0,4) IS (1,4) ROCK (2,4)`. - Assertions: - `rules()` is exactly `["BABA IS BABA", "BABA IS NOT BABA", "BABA IS ROCK", "TEXT IS PUSH"]`. - `activeRules()` contains `"BABA IS ROCK"` and does not contain `"BABA IS BABA"`. `BABA IS NOT BABA` cancels the lock, so the conversion is active again. (Baba is also flagged to vanish; see the note above on what the test leaves open.) ### test_07_text_is_not_push - Setup: `newBaba` with an empty level 4 wide and 3 high. Place a text `text:ROCK` at (0,2) and an object `rock` at (3,2). - Assertions 1: - `activeRules()` is exactly `["TEXT IS PUSH"]`. - `hasProperty(rockText, "PUSH")` is true: the base rule applies to every text object. - `hasProperty(rock, "PUSH")` is false: `TEXT` names text, not the rock the text names. - Action: place `TEXT (0,0) IS (1,0) NOT (2,0) PUSH (3,0)`. - Assertions 2: - `rules()` is exactly `["TEXT IS NOT PUSH", "TEXT IS PUSH"]`. - `activeRules()` is exactly `["TEXT IS NOT PUSH"]`: the base rule is a rule like any other and NOT cancels it. - `hasProperty(rockText, "PUSH")` is false, and so is `hasProperty` of the `TEXT` text at (0,0). ### test_07_leading_not_breaks_sentence - Setup: `newBaba` with an empty level 4 wide and 2 high. Place `NOT (0,0) BABA (1,0) IS (2,0) YOU (3,0)` and an object `baba` at (0,1). - Assertions: - `rules()` and `activeRules()` are both exactly `["TEXT IS PUSH"]`. A `NOT` in front of the subject is not in the course's grammar, and the parser must not read the rest of the sentence as `BABA IS YOU`: the `NOT` is there, and dropping it would change the meaning. - `hasProperty(baba, "YOU")` is false.