|
| 1 | +# AGENTS.md - Wurst Standard Library 2 (pre1.29) |
| 2 | + |
| 3 | +Notes for editing `.wurst` code in the **Wurst Standard Library** repo. This is |
| 4 | +a library, not a map project: most packages here are the wrappers and |
| 5 | +abstractions that consuming map projects build on, so API shape, naming, and |
| 6 | +backwards compatibility matter more than in app code. |
| 7 | + |
| 8 | +## Branch Context: pre1.29 (legacy patch) |
| 9 | + |
| 10 | +This branch targets the **pre-1.29 Warcraft III patches**, i.e. patch **1.28 |
| 11 | +and lower**. |
| 12 | + |
| 13 | +- It intentionally does **not** contain all of the latest stdlib features. |
| 14 | + Many newer features rely on natives that only exist on patch 1.29+, so they |
| 15 | + cannot be supported here. |
| 16 | +- When adding or changing code on this branch, restrict yourself to natives and |
| 17 | + APIs available on 1.28 and earlier. Do not introduce dependencies on |
| 18 | + 1.29+-only natives. |
| 19 | +- The `master` branch tracks the latest patch and carries the newer features. |
| 20 | + |
| 21 | +## Working Rules |
| 22 | + |
| 23 | +- Prefer simple, maintainable code. Fix root causes; avoid brittle workarounds, duplicated branches, and special-case patches. |
| 24 | +- Keep packages focused and below ~500 lines; split by feature, responsibility, or data type. |
| 25 | +- Treat the public API as a contract. Avoid breaking signatures, names, or behavior of exported members without good reason. |
| 26 | +- Prefer extension functions over bare natives; prefer `group` for unit sets, `force` for player sets, and `LinkedList` for arbitrary collections. |
| 27 | +- When unsure about Wurst syntax or local APIs, inspect nearby working code before guessing. |
| 28 | +- Keep tests narrow. Add/update tests for behavior, parsing, compiletime generation, or shared utilities. |
| 29 | +- Avoid broad refactors unless they directly reduce risk or complexity for the requested change. |
| 30 | +- Fix compiler warnings unless they are intentionally suppressed. |
| 31 | + |
| 32 | +## Agent Workflow |
| 33 | + |
| 34 | +Install dependencies: |
| 35 | + |
| 36 | +```bash |
| 37 | +grill install |
| 38 | +``` |
| 39 | + |
| 40 | +After Wurst changes, run quiet checks first: |
| 41 | + |
| 42 | +```bash |
| 43 | +grill typecheck --quiet |
| 44 | +grill test --quiet |
| 45 | +``` |
| 46 | + |
| 47 | +If quiet output reports a failure, rerun narrowly using the failed file, line, package, or test name: |
| 48 | + |
| 49 | +```bash |
| 50 | +grill typecheck |
| 51 | +grill test PackageOrTestName |
| 52 | +``` |
| 53 | + |
| 54 | +Avoid full noisy reruns unless there is no target. Done means relevant errors/warnings are fixed or explicitly explained. |
| 55 | + |
| 56 | +## Wurst Essentials |
| 57 | + |
| 58 | +Every `.wurst` file starts with a package; blocks are indentation-based (tabs or 4 spaces, never mixed): |
| 59 | + |
| 60 | +```wurst |
| 61 | +package MyPackage |
| 62 | +import Wurstunit |
| 63 | +
|
| 64 | +init |
| 65 | + print("loaded") |
| 66 | +``` |
| 67 | + |
| 68 | +- Use `let` unless mutation is needed; prefer obvious type inference. Do not write Jass-style `takes` / `returns nothing`. |
| 69 | +- Package members are private by default (`public` to export); class members are public by default (`private`/`protected` to restrict). |
| 70 | +- Every package implicitly imports `Wurst` unless `NoWurst` is imported. `import public` re-exports; plain `import` does not. |
| 71 | +- Package init is top-to-bottom; imports initialize before importers. Avoid `initlater` unless breaking an unavoidable init cycle. |
| 72 | +- `continue` skips an iteration; `skip` is a no-op. Statements end at newline; continue after `(`, `[`, operators, or before `.`, `..`, `)`, `]`. |
| 73 | + |
| 74 | +Naming: packages/classes `UpperCamelCase`; tuples/functions/members/locals `lowerCamelCase`; top-level constants `UPPER_SNAKE_CASE`. |
| 75 | + |
| 76 | +## Preferred Wurst Style |
| 77 | + |
| 78 | +- Prefer extension functions for readable APIs and the `..` cascade operator for setup chains. |
| 79 | +- Prefer `vec2` tuples over `location` handles unless required. |
| 80 | +- Prefer polymorphism/data modeling over large `instanceof`/`typeId` chains. Avoid unchecked `castTo` unless proven safe. |
| 81 | +- Use the highest practical abstraction (e.g. hashmap-style over raw hashtables); drop to lower-level only in critical hot paths. |
| 82 | +- Use asset constants from asset packages instead of raw asset path strings. |
| 83 | + |
| 84 | +```wurst |
| 85 | +CreateTrigger() |
| 86 | + ..registerAnyUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER) |
| 87 | + ..addCondition(Condition(function cond)) |
| 88 | + ..addAction(function action) |
| 89 | +
|
| 90 | +public function unit.getX2() returns real |
| 91 | + return GetUnitX(this) |
| 92 | +``` |
| 93 | + |
| 94 | +Lambdas need a target type (no standalone inference). Closures capture locals by value; stored/object-backed closures often need cleanup. Lambdas used as `code` cannot take parameters or capture locals. |
| 95 | + |
| 96 | +## Classes, Tuples, Generics |
| 97 | + |
| 98 | +`new` objects generally need `destroy`. Tuples are value types and must not be destroyed. `super(...)` must be the first constructor statement; overridden methods require `override`. Interfaces declare required methods; modules (`use`) inject reusable members. |
| 99 | + |
| 100 | +Prefer `T:` generics for performance-sensitive or instance-heavy containers; old `T` generics erase through integer casts and can share storage. |
| 101 | + |
| 102 | +```wurst |
| 103 | +class Box<T:> |
| 104 | + T value |
| 105 | +``` |
| 106 | + |
| 107 | +## Compiletime and Objects |
| 108 | + |
| 109 | +Use compiletime generation for object-editor data. Prefer wrappers and ID generators so IDs stay stable and collision-free; avoid hardcoded new object IDs unless existing code intentionally does so. |
| 110 | + |
| 111 | +```wurst |
| 112 | +let value = compiletime(fac(5)) |
| 113 | +
|
| 114 | +@compiletime function createSpell() |
| 115 | + new AbilityDefinitionMountainKingThunderBolt(SPELL_ID) |
| 116 | + ..setName("Wurst Bolt") |
| 117 | +``` |
| 118 | + |
| 119 | +## Tests |
| 120 | + |
| 121 | +```wurst |
| 122 | +package MyTests |
| 123 | +import Wurstunit |
| 124 | +
|
| 125 | +@Test public function multiplicationWorks() |
| 126 | + 12.assertEquals(3 * 4) |
| 127 | +``` |
| 128 | + |
| 129 | +Tests should be small, deterministic, self-contained, and assertion-driven. If quiet output lists a failed package/test, rerun that target before expanding scope. |
| 130 | + |
| 131 | +## Formatting |
| 132 | + |
| 133 | +- spaces around binary operators (`a + b`); no space before call parentheses (`foo(1)`); no spaces around `.`/`..`; no spaces inside `(` `)` / `[` `]`. |
| 134 | +- comments use `// Comment`; doc comments `/** ... */` appear in autocomplete. |
| 135 | +- avoid manual horizontal alignment; prefix intentionally unused variables with `_`. |
| 136 | + |
| 137 | +## Pitfalls |
| 138 | + |
| 139 | +- Wurst code must be inside `package`; indentation defines blocks. |
| 140 | +- `array.length` is only the initial length. |
| 141 | +- `new` objects and stored closure objects often need `destroy`. |
| 142 | +- Lambdas need a known target type; lambdas used as `code` cannot capture locals. |
| 143 | +- Varargs are limited by Jass's 31-argument limit. |
| 144 | + |
| 145 | +## Guideline Priority |
| 146 | + |
| 147 | +When rules conflict: |
| 148 | +1. Correctness |
| 149 | +2. Performance requirements of the code path |
| 150 | +3. Readability and abstraction level |
0 commit comments