From d7c4dee0cf3da2f2f83e05031922148f22b6f034 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Mon, 22 Jun 2026 10:57:16 -0400 Subject: [PATCH] cleanup --- content/core.typ | 202 ++++++++++++++++++++++++++++------------------- lib.typ | 3 +- 2 files changed, 124 insertions(+), 81 deletions(-) diff --git a/content/core.typ b/content/core.typ index b7a210a..c73d3c0 100644 --- a/content/core.typ +++ b/content/core.typ @@ -1,6 +1,4 @@ -#import "/lib.typ": callout, example, note, solution, tip, todo - -#let mod4 = $#h(0.5em)&(mod 4)$ +#import "/lib.typ": callout, details, example, note, solution, tip, todo = Core Mechanics @@ -18,48 +16,59 @@ the game*. Typically, item entities fall to the floor and sit stationary soon after being created. Processing movement for these stationary entities would be wasteful, so an optimization was added in 1.14: if -an item is sitting stationary on a block, then only process movement every 4th tick. +an item is sitting stationary on a block, then only process movement for that item every 4th tick. -However, it would also be wasteful if every 4th tick processed _every_ item, so instead the items -are divided into four groups. Each tick stationary items from only one of the four groups check for -movement. +However, it would also be wasteful if every 4th tick processed all items, so instead the items are +divided into four staggered groups. Each tick stationary items from only one of the four groups +check for movement. #callout(kind: "tip", label: "Key Point:")[ - Stationary items can only begin to fall when their $"age" + "id"$ is a multiple of $4$. + Stationary items only begin to fall when their $"age" + "id"$ is a multiple of $4$. ] -Here is the relevant code path for the optimization: +In other words, divide the value by 4 and look at the remainder. If the remainder is 0, the item +checks for movement. That condition is written as `... % 4 == 0` in Java and as $... equiv 0 &(mod + 4)$ in math. -```java -public class ItemEntity extends Entity { - public void tick() { - ... - if (this.onGround() && !(this.getDeltaMovement().horizontalDistanceSqr() > (double)1.0E-5F) && (this.tickCount + this.getId()) % 4 != 0) { - ... - } else { - this.move(MoverType.SELF, this.getDeltaMovement()); - ... - } - ... - } -} +#tip[ + You can freely add or subtract multiples of 4 to any expression without changing the value $mod 4$. -public class Entity { - public void move(final MoverType moverType, Vec3 delta) { - ... - this.setOnGroundWithMovement(this.verticalCollisionBelow, this.horizontalCollision, movement); - ... - } + For example, $-1 equiv 3 &(mod 4)$ because $3 = -1 + 4$. +] - public void setOnGroundWithMovement(final boolean onGround, final boolean horizontalCollision, final Vec3 movement) { - this.onGround = onGround; - ... - } -} -``` -#note[ `onGround` is only ever updated via `move`, and this branch is the *only* place that - `ItemEntity.move` is called. ] +#details(label: [the relevant Java code])[ + #note[ `onGround` is only ever updated via `move`, and this branch is the *only* place that + `ItemEntity.move` is called. `tickCount` is the item's age. ] + + ```java + public class ItemEntity extends Entity { + public void tick() { + ... + if (this.onGround() && !(this.getDeltaMovement().horizontalDistanceSqr() > (double)1.0E-5F) && (this.tickCount + this.getId()) % 4 != 0) { + ... + } else { + this.move(MoverType.SELF, this.getDeltaMovement()); + ... + } + ... + } + } + + public class Entity { + public void move(final MoverType moverType, Vec3 delta) { + ... + this.setOnGroundWithMovement(this.verticalCollisionBelow, this.horizontalCollision, movement); + ... + } + + public void setOnGroundWithMovement(final boolean onGround, final boolean horizontalCollision, final Vec3 movement) { + this.onGround = onGround; + ... + } + } + ``` +] 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 @@ -86,36 +95,44 @@ of other items. Based on when item $B$ fell, when should we expect the other items to fall? #solution[ - To simplify the arithmetic, orient everything around $t=0$. So we'll let $"age"_0$ to be the + To simplify the arithmetic, orient everything around $t=0$. So we'll let $"age"_0$ 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$. - Since $B$ falls at $t=1$, the relation for $"id"^B$ must be - $ "age"_0 + "id"^B + 1 = 0 mod4 $ + Since $B$ falls at $t=1$, the relation for $"id"_B$ must be - $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 $ + $ "age"_0 + "id"_B + 1 equiv 0 & (mod 4) $ + + Item $A$ gets the ID 1 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 equiv 0 & (mod 4) $ *$A$ must fall at $t=2$.* - $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 $ + Item $C$ gets the ID 1 after $B$, so $"id"_C - 1= "id"_B$. Plug that in. + + $ "age"_0 + "id"_C - 1 + 1 equiv 0 & (mod 4) $ *$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.] + Item $D$ gets the ID 2 after $B$, so $"id"_D - 2 = "id"_B$. Plug that in. $ - "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 + "age"_0 + "id"_D - 2 + 1 & equiv 0 & (mod 4) \ + "age"_0 + "id"_D + 3 & equiv 0 & (mod 4) $ *$D$ must fall at $t=3$.* + + #callout(kind: "tip", label: "Therefore:")[ + The expected fall times are: + + - $C$ at $t=0$. + - $B$ at $t=1$. + - $A$ at $t=2$. + - $D$ at $t=3$. + ] ] #todo[Demonstration] @@ -137,22 +154,42 @@ of other items. #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$. + Let $"age"_(0, B)$ 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 $ + $ "age"_(0, B) + "id"_B + 1 equiv 0 & (mod 4) $ + + #todo[Add "gt" to the glossary] + + Item $A$ gets the ID 1 before $B$, so $"id"_A + 1 = "id"_B$. + It spawned 2gt earlier, so $"age"_(0, A) - 2= "age"_(0, B)$. Plug those in. + + $ "age"_(0, A) - 2 + "id"_A + 1 + 1 equiv 0 & (mod 4) $ - 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 $ + Item $C$ gets the ID 1 after $B$, so $"id"_C - 1 = "id"_B$. + It spawned in the same tick, so $"age"_(0, C) = "age"_(0, B)$. Plug those in. + + $ "age"_(0, C) + "id"_C - 1 + 1 equiv 0 & (mod 4) $ + *$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 $ + Item $D$ gets the ID 2 after $B$, so $"id"_D - 2 = "id"_B$. + It spawned 1gt later, so $"age"_(0, D) + 1 = "age"_(0, B)$. Plug those in. + + $ "age"_(0, D) + 1 + "id"_D - 2 + 1 equiv 0 & (mod 4) $ + *$D$ must fall at $t=0$.* + + #callout(kind: "tip", label: "Therefore:")[ + The expected fall times are: + + - $A$ at $t=0$. + - $C$ at $t=0$. + - $D$ at $t=0$. + - $B$ at $t=1$. + ] ] #todo[Demonstration] @@ -165,7 +202,7 @@ of other items. 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. + 4. 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$? @@ -175,43 +212,48 @@ of other items. The ids of $A$ and $B$ are related by - $ "id"^A + 1 + x = "id"^B $ + $ "id"_A + 1 + x = "id"_B $ - And we observe the drop delay related by + And the observed drop delays satisfy - $ "age"_0 + "id"^A + 1 = 0 mod4 $ - $ "age"_0 + "id"^B + 2 = 0 mod4 $ + $ "age"_0 + "id"_A + 1 equiv 0 & (mod 4) $ + $ "age"_0 + "id"_B + 2 equiv 0 & (mod 4) $ - Substitute $"id"^B$ and solve for $x$. + 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 \ + "age"_0 + "id"_A + 1 + x + 2 & equiv "age"_0 + "id"_A + 1 & (mod 4) \ + x + 2 & equiv 0 & (mod 4) \ + x & equiv 2 & (mod 4) \ $ - *So 2 entities must have spawned between $A$ and $B$.* (Or any number with a remainder of 2, like 6, 10, etc.) + *So the number of entities between $A$ and $B$ is $2 &(mod 4)$.* (For example, 2, 6, 10, ...) The ids of $B$ and $C$ are related by - $ "id"^B + 1 + y = "id"^C $ + $ "id"_B + 1 + y = "id"_C $ - And we observe the drop delay related related by + And the observed drop delays satisfy - $ "age"_0 + "id"^B + 2 = 0 mod4 $ - $ "age"_0 + "id"^C + 0 = 0 mod4 $ + $ "age"_0 + "id"_B + 2 equiv 0 & (mod 4) $ + $ "age"_0 + "id"_C + 0 equiv 0 & (mod 4) $ - Substitute $"id"^C$ and solve for $y$. + 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 \ + "age"_0 + "id"_B + 1 + y + 0 & equiv "age"_0 + "id"_B + 2 & (mod 4) \ + y - 1 & equiv 0 & (mod 4) \ + y & equiv 1 & (mod 4) \ $ - *So 1 entity must have spawned between $B$ and $C$.* (Or any number with a remainder of 1, like 5, 9, etc.) + *So the number of entities between $B$ and $C$ is $1 &(mod 4)$.* (For example, 1, 5, 9, ...) + + #callout(kind: "tip", label: "Therefore:")[ + The number of spawned entities must be + + - $2 &(mod 4)$ between $A$ and $B$. + - $1 &(mod 4)$ between $B$ and $C$. + ] ] #todo[Demonstration] diff --git a/lib.typ b/lib.typ index 5731ebe..969f955 100644 --- a/lib.typ +++ b/lib.typ @@ -16,9 +16,10 @@ warn: color.rgb("#a52a2a"), tip: color.rgb("#228b22"), todo: color.rgb("#ff0000"), + eg: auto, ).at(kind) block( - fill: col.transparentize(85%), + fill: if (col != auto) {col.transparentize(85%)} else {auto}, stroke: (y: col), width: 100%, outset: (x: 1em, y: 0.5em),