new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Godot 4 Patterns · all subjects

anti_patterns

17 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Avoid string-based node deep paths

Don't use fragile string-based node access like get_node("/root/Main/UI/Split/Terminal/..."). Use signals, autoloads, or @onready instead.

Don't store Node references long-term

Avoid storing Node references for long periods because nodes can be freed and references become invalid. Use WeakRef or check is_instance_valid() if long-term storage is necessary.

Avoid heavy work in _process

Don't perform heavy computational work in _process(). Move to _physics_process() for 60Hz fixed updates or use signal-driven architecture instead.

Don't overuse call_deferred

Avoid using call_deferred for everything. Use it only for cross-scene calls or to avoid mid-frame state issues. Often it is unnecessary.

Avoid god-class Main

If main.gd exceeds 500 lines, split it into systems using autoloads or composition. A monolithic Main class becomes unmaintainable.

Avoid anti-patterns: global Variant types defeat purpose

Do not sprinkle Variant type annotations throughout code as this defeats the purpose of strict typing. Do not use @warning_ignore everywhere; fix the root cause instead. Do not use := blindly; if the IDE cannot show inferred type, add explicit annotation.

Anti-pattern: hardcoded story dialogue in GDScript

Do not write dialogue and narrative text directly in GDScript code. This forces designers to learn programming and creates bottlenecks. Instead, move all narrative content to data files (Yarn, JSON, CSV) that designers can edit without touching code. This enables 10× faster iteration on story and content.

Anti-pattern: single monolithic content.json file

Do not store all content in a single giant content.json file. This causes merge conflicts when multiple designers edit simultaneously and makes it hard to locate specific data. Instead, split content into separate files by type and act (locations/act1/kitchen.json, items/act1/starter_items.json, etc.). Use DirAccess to load all files from a directory pattern.

Anti-pattern: missing content schema validation

Do not skip validation of content files. Typos in IDs (missing items, wrong exit destinations) cause silent runtime bugs like null reference errors that are hard to trace. Always run a validator that checks referential integrity: all exit destinations exist, all item references exist, all required localized fields present. Add validation to CI pipeline before shipping.

Anti-pattern: localizing generated or programmatic text in code

Do not mix localization keys with programmatic text generation in GDScript (e.g., 'Player gained ' + tr('ITEM_NAME') + ' from ' + npc_name). Let designers edit localized strings in CSV files; code only references keys. Use format placeholders: store 'Player gained %s from %s' as a key in CSV, then use tr() with positional substitution. This keeps narrative and UI text in data files where designers control it.

Anti-pattern: importing artwork without aspect-ratio rules

Do not import PNG illustrations without defining aspect-ratio and size constraints. If different rooms import images at different resolutions without normalization rules, illustrations will render at inconsistent sizes, breaking visual polish and layout. Define a content import rule (e.g., all room illustrations must be 1280×720 16:9) and validate during content build.

Architectural smells and fixes

1000-line main.gd → extract systems. 5+ levels of nested if → use match or polymorphism. Hardcoded strings everywhere → centralize in const or tr(). Direct get_node("/root/Main/UI/...") access → use signals or pass refs. Same logic copy-pasted 3+ times → extract helper function. God-state Singleton → split by responsibility. Scene loading with hardcoded paths → use scene routing service.

Anti-pattern: hardcoded room descriptions in code

Do not hardcode room descriptions as string literals scattered through code. Instead, store all descriptions once in a JSON or data file and load them. This violates the three-layer principle and makes content editing require code changes.

Anti-pattern: single huge state machine for narrative flow

Avoid implementing narrative flow as a single massive state machine with a 1000-line match statement. Use rule-based or event-driven systems instead. This keeps state transitions maintainable and testable.

Anti-pattern: character-by-character input reading

Do not read user input character-by-character in a text adventure. Use LineEdit.text_submitted signal instead to read complete command strings at once.

Anti-pattern: branching without consequence

Never create dialogue choices that appear to branch but lead to identical outcomes. This disrespects the player's agency. Every significant choice must have meaningful consequences on world state, axes, or future dialogue.

Anti-pattern: hidden modifiers without transparency

Show the player what affects what. Hidden modifiers and invisible stat adjustments feel cheaty. Provide an 'honest paytable' so the player understands the mechanical rules governing choice consequences.

Give your agent this brain