Skip to content

Commit b1e6867

Browse files
committed
feat: add trope purity vocab and link in sitcom post
1 parent 93b8b0b commit b1e6867

File tree

7 files changed

+394
-28
lines changed

7 files changed

+394
-28
lines changed

public/posts/philosophy-101/08-nietzsche-and-nihilism.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ This leads to **[Nihilism](/vocab/nihilism)**: the belief that nothing matters.
1919
Nietzsche didn't want us to stay in Nihilism. He wanted us to overcome it.
2020
Since the universe has no inherent meaning, we are free (and obligated) to create our *own* meaning.
2121

22-
* **The [Übermensch](/vocab/ubermensch) (Overman):** The individual who overcomes the need for external validation (religion, nationalism) and creates their own life-affirming values.
22+
* **The Übermensch (Overman):** The individual who overcomes the need for external validation (religion, nationalism) and creates their own life-affirming values.
2323
* **Amor Fati (Love of Fate):** The ultimate test. Could you live your life over and over again, identically, for eternity? If you can say "Yes!" to every pain and joy, you have mastered life.
2424

2525
## Master vs. Slave Morality

public/posts/posts.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,42 @@
11
[
2+
{
3+
"slug": "side-character-conspiracy-sitcom-rant",
4+
"title": "The Side Character Conspiracy: Solving the Sitcom's Greatest Mystery",
5+
"date": "2026-03-08",
6+
"updated": "2026-03-08",
7+
"description": "A detective's deep-dive into the \"Side Character Conspiracy,\" proving why the protagonists of sitcoms are often the most boring part of the show.",
8+
"tags": [
9+
"sitcoms",
10+
"pop-culture",
11+
"rant",
12+
"side-characters",
13+
"analysis"
14+
],
15+
"category": "rant",
16+
"filename": "side-character-conspiracy-sitcom-rant.txt",
17+
"authors": [
18+
"fezcode"
19+
]
20+
},
21+
{
22+
"slug": "wave-function-collapse-explained",
23+
"title": "Wave Function Collapse: Taming Entropy in Procedural Generation",
24+
"date": "2026-03-07",
25+
"updated": "2026-03-07",
26+
"description": "An in-depth guide to the Wave Function Collapse algorithm, featuring visual explanations and implementations in JavaScript and Golang.",
27+
"tags": [
28+
"algorithms",
29+
"gamedev",
30+
"javascript",
31+
"golang",
32+
"procedural-generation"
33+
],
34+
"category": "dev",
35+
"filename": "wave-function-collapse-explained.txt",
36+
"authors": [
37+
"fezcode"
38+
]
39+
},
240
{
341
"slug": "distributed-systems-consensus-and-state",
442
"title": "The Deep End: Distributed Systems, Consensus, and State",
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# The Side Character Conspiracy: Solving the Sitcom's Greatest Mystery
2+
3+
The rain is pouring outside the office of my mind, and I’m staring at a crime scene that’s been repeated for decades. The victim? Your attention span. The perpetrator? A bland, milquetoast "Main Character" who is supposedly the reason we’re all here.
4+
5+
But I’ve been looking at the clues, and the math doesn't add up.
6+
7+
In every legendary sitcom, the "protagonist" is actually a Trojan Horse. They are a boring container used to smuggle in the real stars: the weirdos, the creeps, and the one-note wonders living in the margins.
8+
9+
## The Case File: Protagonist vs. Side Character
10+
11+
Let’s look at the evidence. Why is the person with the most screen time usually the least interesting person in the room?
12+
13+
| Attribute | The Main Character (The "Victim") | The Side Character (The "Suspect") |
14+
| :--- | :--- | :--- |
15+
| **Motive** | Wants love, a career, or "to grow." | Wants a specific sandwich or to chaos-agent. |
16+
| **Arc** | Forced to change, becoming less funny. | Stays exactly the same (Perfect). |
17+
| **Relatability** | High (and therefore exhausting). | Low (and therefore legendary). |
18+
| **Screen Time** | 80% (mostly pining/complaining). | 5% (pure, uncut comedy gold). |
19+
| **The "Hook"** | Moral compass. | Complete lack of a compass. |
20+
21+
## Exhibit A: The "Straight Man" Trap
22+
23+
The mystery begins with the **Straight Man Trap**. To have a sitcom, you need a "grounded" center. Think **Ted Mosby**, **Ross Geller**, or **Leonard Hofstadter**. These men aren't characters; they are *narrative infrastructure*. They exist to ask "Why are you doing that?" so the side character can do something funny.
24+
25+
But here is the crime: over time, the infrastructure starts to crumble. We get tired of Ted’s search for "The One." We get exhausted by Ross’s divorces.
26+
27+
### The Gravity of Interest
28+
```mermaid
29+
pie title Who are you actually laughing at?
30+
"Main Character's Romantic Problems" : 10
31+
"Side Character's Unhinged One-Liner" : 60
32+
"The Background Extra doing something weird" : 15
33+
"The Theme Song" : 15
34+
```
35+
36+
## Exhibit B: The Suspects (The Real MVPs)
37+
38+
I’ve rounded up the usual suspects. If these people weren't in their respective shows, the "Main Characters" would be standing in a silent room staring at a wall.
39+
40+
1. **Creed Bratton (The Office):** Michael Scott is the "lead," but Creed lives in a different dimension. He has four lines an episode, and three of them imply he’s committed international war crimes. He doesn't need an "arc." He needs a fake ID.
41+
2. **Jean-Ralphio & Mona-Lisa Saperstein (Parks & Rec):** Leslie Knope is the engine, but the Sapersteins are the nitro. They are human garbage, and every time they enter a frame, the show’s IQ drops by 40 points while the entertainment value triples.
42+
3. **Gunther (Friends):** While Ross and Rachel were busy "being on a break" for the 900th time, Gunther was silently pining in the background, serving coffee and harboring a dark, beautiful hatred for everyone in the room.
43+
4. **The Waitress (It's Always Sunny):** In a show about five leads, the side characters like Rickety Cricket and The Waitress provide the only metric of how truly demonic the leads are. They are the "mirrors" of the crime.
44+
45+
## The Mystery Solved: Why the "Side" is "Better"
46+
47+
After years of investigation, I’ve found the smoking gun. It’s called **[Trope Purity](/vocab/trope-purity)**.
48+
49+
A main character has to be "human." They have to suffer, they have to learn lessons (bleh), and they have to be someone the audience wants to see succeed. This **"Success Requirement"** is the death of comedy.
50+
51+
A side character has no such burden. They can be a total monster. They can be a one-dimensional caricature of a specific human flaw. Because they only appear for 30 seconds at a time, they never overstay their welcome. They are the **"Joker Cards"** of the writers' room.
52+
53+
## The Verdict
54+
55+
We don't watch sitcoms for the "journey" of the lead. We watch them for the moments when the weird guy from the apartment downstairs knocks on the door and says something so nonsensical it breaks the reality of the show.
56+
57+
**The Main Character is the steak; necessary, but heavy. The Side Character is the [MSG](/vocab/msg). And let’s be honest—we’re all just here for the [MSG](/vocab/msg).**
58+
59+
Case closed.
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
Wave Function Collapse (WFC) is one of those algorithms that feels like magic when you first see it in action. Originally popularized by Maxim Gumin, it’s a powerful tool for procedural generation that can create complex, non-repeating patterns from a small set of example tiles and adjacency rules.
2+
3+
Despite the name—which is borrowed from quantum mechanics—the algorithm itself is purely combinatorial and constraint-based.
4+
5+
## The Core Intuition
6+
7+
Imagine you are trying to fill a grid with tiles. Each tile has specific rules about what can be next to it (e.g., a "Coast" tile can be next to "Sea" or "Land", but "Sea" cannot be directly next to "Land").
8+
9+
WFC approaches this by maintaining a state of **superposition** for every cell in your grid. Initially, every cell could be *any* of the available tiles. As we make decisions, we "collapse" these possibilities until only one remains for each cell.
10+
11+
### Key Terms
12+
13+
1. **Superposition**: A state where a cell has multiple possible tiles it could be.
14+
2. **Entropy**: A measure of uncertainty. In WFC, cells with fewer possible tiles have lower entropy.
15+
3. **Collapse**: The act of picking a single tile for a cell from its list of possibilities.
16+
4. **Propagation**: The process of updating the possibilities of neighboring cells based on a newly collapsed cell.
17+
18+
## The Algorithm Loop
19+
20+
The WFC algorithm follows a simple but effective loop:
21+
22+
```mermaid
23+
graph TD
24+
A[Start] --> B[Initialize Grid: All tiles possible everywhere]
25+
B --> C{Any uncollapsed cells?}
26+
C -- Yes --> D[Select cell with Lowest Entropy]
27+
D --> E[Collapse cell: Pick 1 possible tile]
28+
E --> F[Propagate Constraints to Neighbors]
29+
F --> G{Contradiction?}
30+
G -- No --> C
31+
G -- Yes --> H[Backtrack or Restart]
32+
C -- No --> I[Finished!]
33+
```
34+
35+
1. **Observation**: Find the cell with the lowest non-zero entropy (the one with the fewest possible tiles left). If there's a tie, pick one randomly.
36+
2. **Collapse**: Pick one of the remaining possible tiles for that cell (often weighted by frequency).
37+
3. **Propagation**: Since that cell is now fixed, its neighbors might have fewer valid options. Update them. If their options change, update *their* neighbors, and so on.
38+
39+
---
40+
41+
## Visualizing Propagation
42+
43+
Imagine a 3-tile system: **Land (L)**, **Coast (C)**, and **Sea (S)**.
44+
45+
Rules:
46+
- **L** can touch **L** or **C**.
47+
- **C** can touch **L**, **C**, or **S**.
48+
- **S** can touch **C** or **S**.
49+
50+
If we collapse a cell to **Sea (S)**:
51+
1. Look at its neighbors.
52+
2. The neighbors originally could be {L, C, S}.
53+
3. Because they are next to **S**, and **L** cannot touch **S**, we remove **L** from their possibilities.
54+
4. The neighbors are now {C, S}. Their entropy has decreased.
55+
56+
---
57+
58+
## Implementation: JavaScript
59+
60+
Here is a simplified 1D implementation to demonstrate the logic. In a 1D world, "neighbors" are just left and right.
61+
62+
```javascript
63+
const TILES = ['LAND', 'COAST', 'SEA'];
64+
const RULES = {
65+
LAND: ['LAND', 'COAST'],
66+
COAST: ['LAND', 'COAST', 'SEA'],
67+
SEA: ['COAST', 'SEA'],
68+
};
69+
70+
function wfc1D(size) {
71+
// Initialize grid with all possibilities
72+
let grid = Array(size).fill(null).map(() => [...TILES]);
73+
74+
while (grid.some(cell => cell.length > 1)) {
75+
// 1. Find cell with lowest entropy (minimal length > 1)
76+
let minEntropy = Infinity;
77+
let candidates = [];
78+
79+
grid.forEach((cell, i) => {
80+
if (cell.length > 1 && cell.length < minEntropy) {
81+
minEntropy = cell.length;
82+
candidates = [i];
83+
} else if (cell.length === minEntropy) {
84+
candidates.push(i);
85+
}
86+
});
87+
88+
if (candidates.length === 0) break;
89+
90+
// 2. Collapse
91+
const index = candidates[Math.floor(Math.random() * candidates.length)];
92+
const pick = grid[index][Math.floor(Math.random() * grid[index].length)];
93+
grid[index] = [pick];
94+
95+
// 3. Propagate (Simplified 1D propagation)
96+
for (let i = 0; i < size; i++) {
97+
if (i > 0) {
98+
// Update current based on left neighbor
99+
grid[i] = grid[i].filter(t =>
100+
grid[i-1].some(prevT => RULES[prevT].includes(t))
101+
);
102+
}
103+
if (i < size - 1) {
104+
// Update current based on right neighbor (requires a second pass usually)
105+
// For simplicity, we just loop a few times or use a stack
106+
}
107+
}
108+
}
109+
return grid.map(c => c[0]);
110+
}
111+
112+
console.log(wfc1D(10).join(' -> '));
113+
```
114+
115+
---
116+
117+
## Implementation: Golang
118+
119+
In Go, we can take a more structured approach, which is better for performance and 2D grids.
120+
121+
```go
122+
package main
123+
124+
import (
125+
"fmt"
126+
"math/rand"
127+
"time"
128+
)
129+
130+
type Tile string
131+
132+
const (
133+
Land Tile = "L"
134+
Coast Tile = "C"
135+
Sea Tile = "S"
136+
)
137+
138+
var Rules = map[Tile][]Tile{
139+
Land: {Land, Coast},
140+
Coast: {Land, Coast, Sea},
141+
Sea: {Coast, Sea},
142+
}
143+
144+
type Cell struct {
145+
Possible []Tile
146+
Collapsed bool
147+
}
148+
149+
func main() {
150+
rand.Seed(time.Now().UnixNano())
151+
size := 10
152+
grid := make([]Cell, size)
153+
154+
// Initialize
155+
for i := range grid {
156+
grid[i] = Cell{Possible: []Tile{Land, Coast, Sea}}
157+
}
158+
159+
for {
160+
// Find lowest entropy
161+
minIdx := -1
162+
minEntropy := 100
163+
for i, cell := range grid {
164+
if !cell.Collapsed && len(cell.Possible) < minEntropy {
165+
minEntropy = len(cell.Possible)
166+
minIdx = i
167+
}
168+
}
169+
170+
if minIdx == -1 {
171+
break // All collapsed
172+
}
173+
174+
// Collapse
175+
c := &grid[minIdx]
176+
c.Collapsed = true
177+
pick := c.Possible[rand.Intn(len(c.Possible))]
178+
c.Possible = []Tile{pick}
179+
180+
// Propagate (1D Simple)
181+
propagate(grid)
182+
}
183+
184+
for _, c := range grid {
185+
fmt.Printf("%s ", c.Possible[0])
186+
}
187+
fmt.Println()
188+
}
189+
190+
func propagate(grid []Cell) {
191+
for i := 0; i < len(grid); i++ {
192+
if i > 0 {
193+
grid[i].Possible = filter(grid[i].Possible, grid[i-1].Possible)
194+
}
195+
if i < len(grid)-1 {
196+
// In a real WFC, this would be a stack-based propagation
197+
// that ripples through the whole grid.
198+
}
199+
}
200+
}
201+
202+
func filter(current []Tile, neighborPossibilities []Tile) []Tile {
203+
var next []Tile
204+
for _, t := range current {
205+
valid := false
206+
for _, nt := range neighborPossibilities {
207+
for _, allowed := range Rules[nt] {
208+
if t == allowed {
209+
valid = true
210+
break
211+
}
212+
}
213+
}
214+
if valid {
215+
next = append(next, t)
216+
}
217+
}
218+
return next
219+
}
220+
```
221+
222+
## Challenges: The Contradiction
223+
224+
The hardest part of WFC is the **Contradiction**. This happens when propagation removes *all* possibilities from a cell. If a cell has 0 possible tiles, the algorithm has failed.
225+
226+
There are two main ways to handle this:
227+
1. **Restart**: Throw away the progress and start from scratch (easy but slow).
228+
2. **Backtracking**: Undo the last few collapses and try different choices (complex but robust).
229+
230+
## Conclusion
231+
232+
Wave Function Collapse is a beautiful marriage of logic and creativity. While the implementation can get tricky with 2D/3D grids and complex rotation/symmetry rules, the core principle remains: **listen to your neighbors and reduce your options until the world reveals itself.**
233+
234+
Try implementing it for a 2D dungeon generator—you might be surprised how "designed" your random levels start to look!

0 commit comments

Comments
 (0)