better mod4 examples

This commit is contained in:
2026-06-22 00:29:22 -04:00
parent 8fc002cda1
commit d0d1a87cf5
3 changed files with 144 additions and 54 deletions

View File

@@ -1,5 +1,7 @@
#import "/lib.typ": callout, example, note, solution, tip, todo #import "/lib.typ": callout, example, note, solution, tip, todo
#let mod4 = $#h(0.5em)&(mod 4)$
= Core Mechanics <core> = Core Mechanics <core>
== Entity IDs == 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 #note[ `onGround` is only ever updated via `move`, and this branch is the *only* place that
`ItemEntity.move` is called. ] `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 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 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. 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 #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 remove that supporting block. There will be a few ticks where the item hovers in place before it
falls.] 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[ #example[
Consider this timeline. We spawn a few items, give them time to settle on the ground, then remove Suppose we spawn four items in order. For simplicity, spawn them all in the same tick so their
their support. We observe when item $O$ begins to fall, and infer when we should expect the other ages are equal, and assume no other entities spawn.
items to fall.
- `t+0`, spawn item $O$ 1. Spawn items $A$, $B$, $C$, and $D$ in order in the same tick. Let them settle on a block.
- `t+1`, spawn item $A$ 2. At tick $t=0$, remove the supporting blocks.
- `t+4`, spawn item $B$ 3. At tick $t=1$, item $B$ begins to fall.
- `t+4`, spawn item $C$
- `t+20`, remove support
- `t+22`, item $O$ begins to fall
Assuming no other entities spawn in this time period; these are the only things which increment Based on when item $B$ fell, when should we expect the other items to fall?
the counter.
At what ticks should we expect items $A$, $B$, and $C$ to begin to fall?
#solution[ #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)$. Since $B$ falls at $t=1$, the relation for $"id"^B$ must be
It can only fall when its age is $1 (mod 4)$. $ "age"_0 + "id"^B + 1 = 0 mod4 $
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.
Item $B$ spawns next, so its id must be $0 (mod 4)$. $A$ spawned right before $B$, so $"id"^A + 1 = "id"^B$. Plug that in to the relation we got for
It can only fall when its age is $0 (mod 4)$. $"id"^B$.
These are ticks `t+4`, `t+8`, `t+12`, `t+16`, `t+20`. So it falls immediately when the support $ "age"_0 + "id"^A + 1 + 1 = 0 mod4 $
is removed.
Item $C$ spawns next, so its id must be $1 (mod 4)$. *$A$ must fall at $t=2$.*
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`.
- `t+20` remove support, item $B$ falls $C$ spawned right after $B$, so its id is $"id"^C - 1= "id"^B$. Plug that in.
- `t+22` items $O$ and $A$ fall $ "age"_0 + "id"^C - 1 + 1 = 0 mod4 $
- `t+23` item $C$ falls
*$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 #example[
same for all of them, and we only need to consider the ID. 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 1. Spawn item $A$ at $t=-10$.
remove that block 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]
]

View File

@@ -50,9 +50,9 @@
#let example = callout.with(kind: "eg", label: "For example:") #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" { context if target() == "html" {
html.details({ html.details(open: open, {
html.summary(strong[Click for #label]) html.summary(strong[Click for #label])
body 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:")

View File

@@ -78,6 +78,10 @@ body {
border-width: 1px 0; border-width: 1px 0;
} }
.callout .callout {
margin-inline: 0em;
}
hr { hr {
margin: 0 -1em; margin: 0 -1em;
} }