@kradle/challenges 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,273 @@
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to LLMs when working with code in this repository.
4
+
5
+ ## ⚠️ Mandatory Documentation Updates
6
+
7
+ **ALL AGENTS MUST FOLLOW THESE RULES:**
8
+
9
+ 1. **After making any code changes**, verify that AGENTS.md and README.md accurately reflect your changes. Update them if they don't.
10
+
11
+ 2. **When adding new features**, add documentation for them in both files:
12
+ - AGENTS.md: Add to the appropriate section with implementation details - it will be used by future agents for improving this repository
13
+ - README.md: Add user-facing documentation with usage examples (more like a guide) - this is for humans, so it must be clear, concise, and follow README best practices
14
+ - LLM_README.md: Add LLM-facing documentation with exhaustive detailed usage and examples - it will be used by user agents that will leverage the API, so it should not contain implementation details
15
+
16
+ 3. **When modifying existing features**, update their documentation if the behavior changes (or anything else).
17
+
18
+ 4. **When adding new libraries or modules**, document them in the Architecture Overview section of AGENTS.md.
19
+
20
+ 5. **When changing project structure** (new folders), update the Project Structure section in README.md. It must only surface the folders, the files is too detailed.
21
+
22
+ 6. **Before completing a task**, run a quick check:
23
+ - Do AGENTS.md, README.md and FEATURES.md reflect the current state of the code?
24
+ - Are all features documented?
25
+ - Is the project structure accurate?
26
+
27
+ Failure to keep documentation up-to-date creates confusion for future agents and developers. This is a **mandatory** part of every code change.
28
+
29
+ ---
30
+
31
+ ## Architecture Overview
32
+
33
+ ### Project Structure
34
+
35
+ ```
36
+ /src
37
+ ├── index.ts # Public API exports
38
+ ├── challenge.ts # Core ChallengeBase class and createChallenge()
39
+ ├── actions.ts # Actions library (give, teleport, announce, etc.)
40
+ ├── types.ts # TypeScript type definitions
41
+ ├── constants.ts # Shared constants (objectives, selectors, built-in vars)
42
+ ├── commands.ts # Watcher integration commands
43
+ ├── api_utils.ts # Utility functions (forEveryPlayer)
44
+ ├── testmode.ts # Test/debug mode support
45
+ └── utils.ts # Internal utilities
46
+ ```
47
+
48
+ ### Key Dependencies
49
+
50
+ - **Sandstone (0.14.0-alpha.13)**: Minecraft datapack generator. Provides MCFunction, Objective, Selector, execute commands, etc. All generated code compiles to Minecraft datapacks via Sandstone's `savePack()`.
51
+
52
+ ### Core Components
53
+
54
+ #### 1. ChallengeBase Class (`challenge.ts`)
55
+
56
+ The main engine that:
57
+ - Manages variable creation and objective assignment
58
+ - Generates MCFunctions for lifecycle events (start, init, tick, end)
59
+ - Processes custom events (score-based and advancement-based)
60
+ - Handles win condition evaluation and game state management
61
+
62
+ **Key Methods:**
63
+ - `constructor(config)`: Sets up objectives, variables, and built-in score events
64
+ - `events()`: Registers lifecycle event callbacks
65
+ - `custom_events()`: Registers triggered events
66
+ - `end_condition()`: Sets game termination condition
67
+ - `win_conditions()`: Sets per-role win conditions and triggers `build()`
68
+ - `build()`: Generates all MCFunctions and calls `savePack()`
69
+
70
+ **Generated MCFunctions:**
71
+ 1. `start_challenge` - Initial setup, tags players, sets game state
72
+ 2. `init_participants` - Per-player setup (delayed 1 second via schedule)
73
+ 3. `on_tick` - Main loop: updates variables, processes events, checks end condition
74
+ 4. `end_challenge` - Announces winners, saves game state
75
+
76
+ #### 2. Actions Library (`actions.ts`)
77
+
78
+ Pre-built game operations. Each action is a function that generates Sandstone commands.
79
+
80
+ **Categories:**
81
+ - Communication: `announce`, `tellraw`
82
+ - Items: `give`, `giveLoot`, `clear`, `countItems`, `summonItem`
83
+ - Entities: `summonMultiple`, `kill`, `teleport`
84
+ - World: `setBlock`, `fill`, `setTime`, `gamerule`
85
+ - Scores: `set`, `increment`, `decrement`
86
+ - Attributes: `setAttribute`
87
+ - Custom: `custom` (arbitrary Sandstone code)
88
+ - Logging: `log_variable`
89
+
90
+ **Implementation Pattern:**
91
+ ```typescript
92
+ export const Actions = {
93
+ give: (params: { item: string; count: number; nbt?: object }) => {
94
+ give("@s", `minecraft:${params.item}`, params.count);
95
+ },
96
+ // ...
97
+ };
98
+ ```
99
+
100
+ #### 3. Variable System (`types.ts`, `challenge.ts`)
101
+
102
+ **Variable Types:**
103
+ - `individual` + specific `objective_type`: Uses Minecraft's built-in stat tracking
104
+ - `individual` + `"dummy"`: Manual/computed values per player
105
+ - `global`: Shared values stored on a constant entity
106
+
107
+ **Objective Naming:**
108
+ - Uses counter-based suffixes to ensure unique names under 16 chars
109
+ - Format: `kradle.${hash}` where hash is derived from challenge name + counter
110
+
111
+ **Updater Execution:**
112
+ - All updaters run every tick in `on_tick` MCFunction
113
+ - Updaters execute as/at each participant for individual variables
114
+ - Global updaters run once per tick
115
+
116
+ #### 4. Event System (`challenge.ts`)
117
+
118
+ **Score Events:**
119
+ - Track previous tick values to detect changes
120
+ - Fire when score reaches target (fire_once) or while condition holds (repeatable)
121
+ - Processed separately for global vs individual variables
122
+
123
+ **Advancement Events:**
124
+ - Converted to score events internally
125
+ - Advancement grants → score increment → event fires
126
+ - Advancement revoked after triggering
127
+
128
+ #### 5. Watcher Integration (`commands.ts`)
129
+
130
+ Communicates with external "Kradle Watcher" system via JSON tellraw commands:
131
+ ```json
132
+ {
133
+ "type": "kradle_command",
134
+ "command": "game_over",
135
+ "arguments": { "winners": [...], "end_state": "..." }
136
+ }
137
+ ```
138
+
139
+ ### Constants (`constants.ts`)
140
+
141
+ **Objectives:**
142
+ - `VISIBLE_OBJECTIVE` = "kradle.board" (sidebar display)
143
+ - `HIDDEN_OBJECTIVE` = hidden scoreboard for internal data
144
+
145
+ **Entity Selectors:**
146
+ - `ALL` = `@a[tag=kradle_participant]`
147
+ - `KRADLE_PARTICIPANT_TAG` = "kradle_participant"
148
+ - `WINNER_TAG` = "kradle_winner"
149
+
150
+ **Built-in Variables (8):**
151
+ 1. `death_count` - Minecraft deathCount objective
152
+ 2. `has_never_died` - 1 if alive, 0 if died
153
+ 3. `alive_players` - Global count
154
+ 4. `main_score` - Primary display score
155
+ 5. `game_timer` - Tick counter
156
+ 6. `game_state` - State enum (CREATED=0, OFF=1, ON=2)
157
+ 7. `player_count` - Total players
158
+ 8. `player_number` - Unique ID (1-N)
159
+
160
+ ### Build Process
161
+
162
+ 1. User calls `createChallenge(config)` → returns builder
163
+ 2. Chain: `.events()` → `.custom_events()` → `.end_condition()` → `.win_conditions()`
164
+ 3. `.win_conditions()` triggers `build()`:
165
+ - Creates all MCFunctions
166
+ - Generates advancements for advancement-based events
167
+ - Creates loot tables (hashed for deduplication)
168
+ - Calls `savePack()` to write datapack files
169
+
170
+ ---
171
+
172
+ ## Development Guidelines
173
+
174
+ ### Adding a New Action
175
+
176
+ 1. Add to `Actions` object in `src/actions.ts`
177
+ 2. Define parameter interface with required/optional fields
178
+ 3. Implement using Sandstone commands
179
+ 4. Update LLM_README.md with full signature and examples
180
+ 5. Update README.md with brief usage example
181
+
182
+ ### Adding a New Built-in Variable
183
+
184
+ 1. Add to `BUILTIN_VARIABLES` in `src/constants.ts`
185
+ 2. Define type, objective_type, and updater
186
+ 3. Update LLM_README.md built-in variables table
187
+ 4. Update README.md built-in variables table
188
+
189
+ ### Adding a New Event Type
190
+
191
+ 1. Update `_InputCustomEventType` in `src/types.ts`
192
+ 2. Handle in `processCustomEvents()` in `src/challenge.ts`
193
+ 3. Document in LLM_README.md Events section
194
+ 4. Add example to README.md
195
+
196
+ ### Testing Changes
197
+
198
+ ```bash
199
+ npm run build # Compile TypeScript
200
+ npm run lint # Run Biome linter
201
+ ```
202
+
203
+ Test by creating a challenge using the library and verifying generated datapack.
204
+
205
+ ---
206
+
207
+ ## Common Implementation Patterns
208
+
209
+ ### Objective Name Generation
210
+
211
+ ```typescript
212
+ private getNewObjectiveName(): string {
213
+ const hash = createHash("sha256")
214
+ .update(this.config.name + this.objectiveCounter++)
215
+ .digest("hex")
216
+ .slice(0, 8);
217
+ return `kradle.${hash}`;
218
+ }
219
+ ```
220
+
221
+ ### Variable Registration
222
+
223
+ ```typescript
224
+ // Individual with specific objective
225
+ const obj = Objective.create(name, objectiveType);
226
+ variables[varName] = obj("@s");
227
+
228
+ // Global dummy
229
+ const obj = Objective.create(name, "dummy");
230
+ variables[varName] = obj(GLOBAL_ENTITY);
231
+ ```
232
+
233
+ ### Event Processing (on_tick)
234
+
235
+ ```typescript
236
+ // 1. Update all variable values
237
+ for (const updater of updaters) {
238
+ updater(value, allVariables);
239
+ }
240
+
241
+ // 2. Process score events
242
+ for (const event of scoreEvents) {
243
+ _.if(score.greaterOrEqualThan(target), () => {
244
+ if (mode === "fire_once") {
245
+ _.if(prevScore.lowerThan(target), () => {
246
+ actions();
247
+ });
248
+ } else {
249
+ actions();
250
+ }
251
+ });
252
+ }
253
+
254
+ // 3. Update previous values
255
+ for (const [current, prev] of previousValuePairs) {
256
+ prev.set(current);
257
+ }
258
+
259
+ // 4. Check end condition
260
+ _.if(endCondition, () => {
261
+ endChallenge();
262
+ });
263
+ ```
264
+
265
+ ### Loot Table Deduplication
266
+
267
+ Loot tables are hashed by content to avoid duplicates:
268
+ ```typescript
269
+ const hash = createHash("sha256")
270
+ .update(JSON.stringify(lootTable))
271
+ .digest("hex")
272
+ .slice(0, 16);
273
+ ```
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md