From d0d1a87cf5ef30e042f206d3bd637abf3e9c8f87 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Mon, 22 Jun 2026 00:29:22 -0400 Subject: [PATCH] better mod4 examples --- content/core.typ | 187 ++++++++++++++++++++++++++++++++++------------- lib.typ | 7 +- static/style.css | 4 + 3 files changed, 144 insertions(+), 54 deletions(-) diff --git a/content/core.typ b/content/core.typ index 87bc88c..b7a210a 100644 --- a/content/core.typ +++ b/content/core.typ @@ -1,5 +1,7 @@ #import "/lib.typ": callout, example, note, solution, tip, todo +#let mod4 = $#h(0.5em)&(mod 4)$ + = Core Mechanics == Entity IDs @@ -59,75 +61,158 @@ public class Entity { #note[ `onGround` is only ever updated via `move`, and this branch is the *only* place that `ItemEntity.move` is called. ] -== Observable Drop Delay - The effect is that if the item is on a block and has negligible horizontal momentum, it *cannot fall* until the condition is satisfied, even if it's no longer on the ground. It can only fall early if it gains horizontal momentum or is pushed. -This means if we know the remainder of $"id" slash 4$, we can predict which ages allow it to fall. - -And the inverse: if we know which age allowed an item to fall, we can deduce the remainder of -$"id" / 4$. - -#table( - columns: (auto, auto), - $"age"$, $"id"$, - [0], [0], - [1], [3], - [2], [2], - [3], [1], -) - -This means if we know the remainder of $"age" / 4$, we can - - #todo[Falling item animation][Spawn a few items, note their ID and age. Let them settle on a block, then remove that supporting block. There will be a few ticks where the item hovers in place before it falls.] +== Observable Drop Delay + +We can't control the absolute entity ID a particular item will receive, but we can *compare* ids of +multiple entities. By observing the drop delay for a "reference" item, we can predict the behavior +of other items. + #example[ - Consider this timeline. We spawn a few items, give them time to settle on the ground, then remove - their support. We observe when item $O$ begins to fall, and infer when we should expect the other - items to fall. + Suppose we spawn four items in order. For simplicity, spawn them all in the same tick so their + ages are equal, and assume no other entities spawn. - - `t+0`, spawn item $O$ - - `t+1`, spawn item $A$ - - `t+4`, spawn item $B$ - - `t+4`, spawn item $C$ - - `t+20`, remove support - - `t+22`, item $O$ begins to fall + 1. Spawn items $A$, $B$, $C$, and $D$ in order in the same tick. Let them settle on a block. + 2. At tick $t=0$, remove the supporting blocks. + 3. At tick $t=1$, item $B$ begins to fall. - Assuming no other entities spawn in this time period; these are the only things which increment - the counter. - - At what ticks should we expect items $A$, $B$, and $C$ to begin to fall? + Based on when item $B$ fell, when should we expect the other items to fall? #solution[ - Item $O$ falls when its age is $22 = 2 (mod 4)$, so its id must be $-2 (mod 4)$ + To simplify the arithmetic, orient everything around $t=0$. So we'll let $"age"_0$ to be the + items' ages at $t=0$ and add tick offsets from there. All items spawned in the same tick, so + they all have the same $"age"_0$. - Item $A$ spawns next, so its id must be $-1 (mod 4)$. - It can only fall when its age is $1 (mod 4)$. - It checks on ticks `t+2`, `t+6`, `t+10`, `t+14`, `t+18`, but is supported for all these. - On tick `t+22`, it will no longer be supported and will begin to fall. + Since $B$ falls at $t=1$, the relation for $"id"^B$ must be + $ "age"_0 + "id"^B + 1 = 0 mod4 $ - Item $B$ spawns next, so its id must be $0 (mod 4)$. - It can only fall when its age is $0 (mod 4)$. - These are ticks `t+4`, `t+8`, `t+12`, `t+16`, `t+20`. So it falls immediately when the support - is removed. + $A$ spawned right before $B$, so $"id"^A + 1 = "id"^B$. Plug that in to the relation we got for + $"id"^B$. + $ "age"_0 + "id"^A + 1 + 1 = 0 mod4 $ - Item $C$ spawns next, so its id must be $1 (mod 4)$. - It can only fall when its age is $-1 = 3 (mod 4)$. - These are ticks `t+7`, `t+11`, `t+15`, `t+19`, `t+23`. + *$A$ must fall at $t=2$.* - - `t+20` remove support, item $B$ falls - - `t+22` items $O$ and $A$ fall - - `t+23` item $C$ falls + $C$ spawned right after $B$, so its id is $"id"^C - 1= "id"^B$. Plug that in. + $ "age"_0 + "id"^C - 1 + 1 = 0 mod4 $ + + *$C$ must fall at $t=0$.* + + $D$ spawned right after $C$, so its id is $"id"^D - 2 = "id"^B$. Plug that in. + + #tip[You can freely add or subtract 4 to either side of a mod 4 equality.] + + $ + "age"_0 + "id"^D - 2 + 1 &= 0 mod4 \ + "age"_0 + "id"^D - 1 &= 0 mod4 \ + "age"_0 + "id"^D - 1 + 4 &= 0 mod4 \ + "age"_0 + "id"^D + 3 &= 0 mod4 + $ + + *$D$ must fall at $t=3$.* ] + + #todo[Demonstration] ] -For simplicity, suppose we spawn all our items on the same tick. Then `this.tickCount` will be the -same for all of them, and we only need to consider the ID. +#example[ + Consider a variation of the previous example, but where the items do not spawn on the same tick. + Their ages will be different. Again, assume no other entities spawn. -The result of this is that if you spawn several item entities, allow them to settle on a block, then -remove that block + 1. Spawn item $A$ at $t=-10$. + 2. Spawn items $B$ and $C$ in order at $t=-8$. + 3. Spawn item $D$ at $t=-7$. Let them settle on a block. + 4. At tick $t=0$, remove the supporting blocks. + 5. At tick $t=1$, item $B$ begins to fall. + + Based on when item $B$ fell, and accounting for the different item ages, when should we expect the + other items to fall? + + #solution[ + We'll need to track the item ages separately this time, but still oriented around $t=0$. + + Let $"age"^B_0$ be item $B$'s age at $t=0$. + + We know item $B$ fell at $t=1$, so we have the relation + $ "age"^B_0 + "id"^B + 1 = 0 mod4 $ + + Item $A$ spawned just before item $B$, so $"id"^A + 1 = "id"^B$. It spawned 2gt earlier, so $"age"^A_0 - 2= "age"^B_0$. Plug those in. + $ "age"^A_0 - 2 + "id"^A + 1 + 1 = 0 mod4 $ + *$A$ must fall at $t=0$.* + + Item $C$ spawned just after item $B$, so $"id"^C - 1 = "id"^B$. It spawned in the same tick, so $"age"^C_0 = "age"^B_0$. Plug those in. + $ "age"^C_0 + "id"^C - 1 + 1 = 0 mod4 $ + *$C$ must fall at $t=0$.* + + Item $D$ spawned just after item $B$, so $"id"^D - 2 = "id"^B$. It spawned 1gt later, so $"age"^D_0 + 1 = "age"^B_0$. Plug those in. + $ "age"^D_0 + 1 + "id"^D - 2 + 1 = 0 mod4 $ + *$D$ must fall at $t=0$.* + ] + + #todo[Demonstration] +] + +#example[ + Now consider what it means if the pattern is broken. Keep the item ages the same for simplicity, + but this time do *not* assume that no other entities spawn. + + 1. Spawn items $A$, $B$, and $C$ in order in the same tick. Let them settle on a block. + 2. At tick $t=0$, remove the supporting blocks. Item $C$ begins to fall. + 3. At tick $t=1$, item $A$ begins to fall. + 3. At tick $t=2$, item $B$ begins to fall. + + What number of entities must have spawned between items $A$ and $B$? Between $B$ and $C$? + + #solution[ + Following the same conventions as before, where $x$ is the number of entities between $A$ and + $B$ and $y$ is the number of entities between $B$ and $C$. + + The ids of $A$ and $B$ are related by + + $ "id"^A + 1 + x = "id"^B $ + + And we observe the drop delay related by + + $ "age"_0 + "id"^A + 1 = 0 mod4 $ + $ "age"_0 + "id"^B + 2 = 0 mod4 $ + + Substitute $"id"^B$ and solve for $x$. + + $ + "age"_0 + "id"^A + 1 & = "age"_0 + "id"^A + 1 + x + 2 mod4 \ + 1 & = 3 + x mod4 \ + -2 & = x mod4 \ + -2 + 4 & = x mod4 \ + 2 & = x mod4 \ + $ + + *So 2 entities must have spawned between $A$ and $B$.* (Or any number with a remainder of 2, like 6, 10, etc.) + + The ids of $B$ and $C$ are related by + + $ "id"^B + 1 + y = "id"^C $ + + And we observe the drop delay related related by + + $ "age"_0 + "id"^B + 2 = 0 mod4 $ + $ "age"_0 + "id"^C + 0 = 0 mod4 $ + + Substitute $"id"^C$ and solve for $y$. + + $ + "age"_0 + "id"^B + 2 & = "age"_0 + "id"^B + 1 + y + 0 mod4 \ + 2 & = 1 + y mod4 \ + 1 & = y mod4 \ + $ + + *So 1 entity must have spawned between $B$ and $C$.* (Or any number with a remainder of 1, like 5, 9, etc.) + ] + + #todo[Demonstration] +] diff --git a/lib.typ b/lib.typ index 683dc27..5731ebe 100644 --- a/lib.typ +++ b/lib.typ @@ -50,9 +50,9 @@ #let example = callout.with(kind: "eg", label: "For example:") -#let details(body, label: "Details") = { +#let details(body, label: "Details", open: false) = { context if target() == "html" { - html.details({ + html.details(open: open, { html.summary(strong[Click for #label]) body }) @@ -64,4 +64,5 @@ } } -#let solution = details.with(label: "Solution") +// #let solution = details.with(label: "Solution") +#let solution = callout.with(kind: "solution", label: "Solution:") diff --git a/static/style.css b/static/style.css index 2527643..99c66f8 100644 --- a/static/style.css +++ b/static/style.css @@ -78,6 +78,10 @@ body { border-width: 1px 0; } +.callout .callout { + margin-inline: 0em; +} + hr { margin: 0 -1em; }