@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 +273 -0
- package/CLAUDE.md +1 -0
- package/LLM_README.md +1380 -0
- package/README.md +498 -1
- package/dist/actions.d.ts +31 -21
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +77 -85
- package/dist/actions.js.map +1 -1
- package/dist/challenge.js +12 -12
- package/dist/challenge.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -6
- package/dist/constants.js.map +1 -1
- package/dist/types.d.ts +2 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/actions.ts +86 -94
- package/src/challenge.ts +12 -12
- package/src/constants.ts +4 -6
- package/src/types.ts +2 -3
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
|