---
name: set-crafting
title: Set World Crafting Guide
description: A guide for game developers and agents on how to use the Set World crafting and economy APIs. Covers the orb currency, rejection-sampling to target tiers, best-of-N lotteries, salvage, monster drops, and how to compose these into a progression loop for your game.
homepage: https://set.world
spec: https://set.world/api/spec
license: MIT
version: 1
methods: [GET]
auth: none
cors: open
content_type: text/markdown
canonical_paths:
  - https://set.world/craft-guide
  - https://set.world/craft-guide.md
  - https://set.world/api/craft-guide
---

# Set World Crafting Guide

This guide teaches you how to use the Set World crafting and economy APIs to build item progression into your game. The economy is denominated in a single currency, orbs, and every cost is deterministic and verifiable.

## A Note for Builders

Set computes the published generation, grading, and price formulas. Your game decides when to craft, which drops to accept, how combat works, and how balances and inventories are stored. Local game rules may use these primitives differently, but a changed local price or effect is not a change to Set's shared contract.

## The Orb Economy

Orbs are Set's single pricing unit. The guarantee prices grow geometrically; the game determines how quickly orbs are earned and what item budgets mean in play.

| System | Formula | Range |
| --- | --- | --- |
| Crafting | `5^(tier - 1)` | 1 / 5 / 25 / 125 / 625 / 3,125 / 15,625 |
| Monster drops | `round((avgStat - 6)^2 / 4) × classMultiplier × variance` | Scales with enemy strength |
| Salvage | fixed refund by grade | F–C: 0 · B: 2 · A: 40 · S: 200 |

## Crafting: Two Modes

### Mode 1: Rejection-sample to a target grade

Request a material-grade floor at its fixed price. The server samples until it reaches that floor or its effective attempt budget runs out. Check `capped` and the returned grade before treating the floor as achieved.

```sh
# Check the price
curl 'https://set.world/api/craft/cost?tier=5'
# Response: { tier: 5, orbs: 625, defaultBudget: 62500 }

# Craft a Grade B item
curl 'https://set.world/api/craft?tier=5'
# Response: { mode: "tier", item: {...}, tier: 5, tierGrade: "B", tierName: "Grade B", material: {...}, attempts: 42, capped: false }
```

**Key fields:**
- `tier=1..7` maps to Grade F through Grade S
- `capped: true` means the budget ran out before hitting the target (effectively impossible with current weights — even Grade S expects only ~679 attempts against a 1,000,000 budget — but the field is the honest answer if weights ever change)
- `seed=N` makes the result reproducible — the same operation, effective inputs, seed, and matching content/rules reproduce the generation
- `budget` reports the effective attempt cap, at most 1,000,000; a malformed supplied budget fails instead of selecting the default. Budget applies only to tier mode.

**Cost table:**

| Grade | Tier | Orb Cost | Budget (max attempts) |
| --- | --- | --- | --- |
| F | 1 | 1 | 100 |
| E | 2 | 5 | 500 |
| D | 3 | 25 | 2,500 |
| C | 4 | 125 | 12,500 |
| B | 5 | 625 | 62,500 |
| A | 6 | 3,125 | 312,500 |
| S | 7 | 15,625 | 1,000,000 |

### Mode 2: Best-of-N lottery

Spend N orbs, roll N items, keep the best one. No grade guarantee — you get the highest-tier item that luck provides.

```sh
# Spend 125 orbs on a lottery
curl 'https://set.world/api/craft?orbs=125'
# Response: { mode: "orbs", item: {...}, tier: 5, tierGrade: "B", rolls: 125, rollsExpected: { medianTier: 6, medianScore: 8.59, ... }, analysis: {...} }
```

**Expected outcomes (measured medians):**

| Orbs spent | Median tier | Median score |
| --- | --- | --- |
| 1 | 3 (Grade D) | 5.21 |
| 5 | 4 (Grade C) | 6.36 |
| 25 | 5 (Grade B) | 7.85 |
| 125 | 6 (Grade A) | 8.59 |
| 625 | 7 (Grade S) | 8.40 |
| 3,125 | 7 (Grade S) | 9.63 |
| 15,625 | 7 (Grade S) | 11.72 |

At the listed benchmark spends through 625, each 5× step raises the sampled median by a grade. The weighted model's first 50% Grade S floor chance occurs at 471 candidates; at 625 the chance is about 60.1928%. `rollsExpected` labels the nearest historical row with `referenceOrbs` and `method: "historical-sample"`; its median and score bands describe that sample. `gradeExpectations` separately returns the exact weighted-model distribution and median for the effective `rolls`. At six orbs its `medianGrade` is B, while the labeled five-orb sample retains C. Use `analysis` for the returned grade's model probability at the effective spend.

`gradeExpectations.distribution` has seven rows: `tier`, `tierGrade`, `probability`
of that exact best grade, `atLeastProbability`, and `cumulativeProbability` of that
grade or lower. Its root includes `rolls`, `medianTier`, `medianGrade`, and
`method: "exact-weighted-model"`. These analytical grade statistics require no
extra candidate rolls. Orb mode reports its effective spend, capped at 100,000.

The crafted `item` is enriched and includes the canonical `item.breakdown` slot row. Orb-mode `analysis` provides:

- `itemProbability`: the six selected factors' joint probability on one independent roll, `10^(-rarityScore)`.
- `gradeOrBetterProbability` and `gradeOrBetterCraftProbability`: the chance to reach the returned grade or better in one roll and in the actual `rolls` count. For per-roll chance `p`, the craft chance is `1 - (1 - p)^rolls`.
- `maxRarityScore`, `maxMaterialRank`, `maxOrbValue`, and `rarityFraction`: canonical ceilings and progress toward the logarithmic rarity-score ceiling. This fraction is not an item percentile.
- `factors`: the six canonical rarity contributions and their probabilities, ready to explain the outcome.

The grade odds describe reaching a material grade or better; they do not describe the probability of the exact item winning a best-of-N craft. Orb value is the guarantee-craft price for the item's grade, not its salvage refund.

## Salvage (Turning Items Back Into Orbs)

Disassembling an item destroys it and refunds orbs by grade:

```sh
# Appraise an item you hold (by its 19-number index vector)
curl 'https://set.world/api/salvage?indexes=<19-numbers>'
# Or ask by grade, or fetch the whole schedule
curl 'https://set.world/api/salvage?tier=6'
curl 'https://set.world/api/salvage'
```

| Grade | F | E | D | C | B | A | S |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Salvage | 0 | 0 | 0 | 0 | 2 | 40 | 200 |

The numbers look harsh at low grades on purpose. A 1-orb lottery craft is a fair single roll, so an expected refund of 1 orb is break-even and an expectation above 1 creates positive expected returns. Under this schedule the expectation is ≈ 0.70 orbs per roll — a ~30% sink on the tightest possible loop (the endpoint reports the live number as `expectedSalvagePerRoll`). The feel it produces: F–C items are disassembly fodder you clear by the armful, a Grade B always pays a little, an A is a 40-orb jackpot chime, and salvaging a Grade S is a 200-orb event you do on purpose.

Salvage is grading, not prescription: we score the item, and whether disassembly exists in your game is your call. Use the `guaranteedTier` drop override to inject salvage-worthy items into a zone without touching the invariant — it now yields an actual crafted item (with its salvage value) rather than just a floor.

## Monster Drops (Earning Orbs)

Monsters drop orbs based on their average stat and encounter class. This is how players fund crafting.

```sh
# Check encounter classes and multipliers
curl 'https://set.world/api/drop/classes'
# Response: { classes: [{name: "trash", multiplier: 1}, {name: "veteran", multiplier: 3}, ...] }

# Price a kill
curl 'https://set.world/api/drop?stats=12-14-10-11-13-16-12-14-11&class=elite'
# Response: { avgStat: 12.556, baseDrop: 11, classMultiplier: 10, rolledVariance: 1.0234, orbs: 112, ... }
```

**Encounter classes:**

| Class | Multiplier | Use for |
| --- | --- | --- |
| trash | 1x | Fodder mobs, abundant |
| veteran | 3x | Mini-bosses, rare spawns |
| elite | 10x | Dungeon guardians, named enemies |
| boss | 50x | End-of-zone bosses |
| world-boss | 250x | Server-wide events, raid targets |

**Optional overrides** (passed as URL-encoded JSON in the `override` query param):
- `flat`: fixed orb amount (bypasses formula)
- `multiplier`: additional multiplier on top of class
- `guaranteedTier` (1..7): requests a material-grade floor on a derived seed without disturbing the orb roll, returning an enriched `guaranteedItem` with its `salvage` value. `guaranteedItemCraft` separately carries `requestedTier`, derived `seed`, effective `budget`, `attempts`, and `capped`; inspect that outcome and the item's actual grade.
- `bonusOrbs`: `{ min, max }` range of extra orbs added

Only these override fields are accepted. Flat amounts are non-negative safe
integers; multipliers are finite in `[0,1000000]`; bonus bounds must satisfy
`0 ≤ min ≤ max ≤ 1000000000`. Flat plus the maximum bonus must remain a safe
integer. Invalid inputs return a field-specific error before generation. Repeated
query parameters use their first value; an empty optional seed means unseeded.

## Leveling Is Yours

Set grants no stat points and publishes no level curve. Your game defines progression, enemy threat, and fight frequency. `/api/drop` prices nine integer stats in [8,24] and an encounter class; multipliers scale the drop, not the enemy's health or damage. Quadratic base drops and cubic/geometric prices are ingredients for a pacing model, not a guarantee for every level-to-stat mapping.

## Building a Progression Loop

Here's how to compose these APIs into a complete gameplay loop:

### 1. Generate a starting character

```sh
curl https://set.world/api/roll/character
```

The character arrives with fifteen items, base stats, trait-reconciled `finalStats`, derived attributes, and advisory equipment values. The completed set has fixed slot capacities; it is not fifteen unconstrained ordinary item draws.

### 2. Fight monsters to earn orbs

Use the returned `finalStats` and attributes in your own combat rules. Those rules decide which enemies a character can handle. `/api/drop` prices a supplied enemy stat block and encounter class; it does not resolve a fight.

Games without rules can optionally use the experimental
[basic-lightweight-combat skill](https://set.world/basic-lightweight-combat)
and `/api/basic-lightweight-combat` for one attack or initiative opportunities.
It shares the army's physical-hit/stamina arithmetic, excludes status/weapon
effects, and keeps all state and rewards in the consumer. It is not required for
skill-based games and does not establish campaign balance.

### 3. Spend orbs on crafting

Choose a grade-floor request or an orb lottery. The current API has no slot-targeting parameter. Your inventory rules decide whether the returned slot is useful. Items supply grade, budget, and themes; equipment does not automatically raise attributes on the default character response.

### 4. Scale enemy difficulty

Average enemy stats and encounter class affect drop prices. Your game chooses difficulty, fight frequency, and progression; the price curves alone do not establish pacing.

### 5. Close the loop with salvage

If your game permits disassembly, `/api/salvage` appraises the returned item's grade. The game owns redemption and any carryover between runs. The expected sink applies to paid, unselected draws; free items or chosen favorable seeds do not enforce that spending model.

### 6. End-game

- Grade S's floor price is 15,625 orbs; inspect the guarantee's cap outcome. The lottery's first 50% S floor chance is 471 candidates, with 625 a published benchmark.
- The home UI caps orb spending at 15,625; the API caps it at 100,000. Higher lottery spends can still improve rarity. Neither cap is a guaranteed lottery outcome.

For a long campaign, model useful replacements as well as returned grades.
Fifteen Grade S crafts produce fifteen items, not necessarily a complete
fifteen-slot outfit: the current craft modes do not target a slot. Duplicate
items, retained equipment, and salvage change the amount a character needs to
spend. The optional equipment-to-stat approximation clamps at 24, so later
purchases can leave derived attributes unchanged even as equipment grades rise.
With the default bonus-off interpretation, a game must give the advisory item
budgets concrete effects before crafting changes combat strength.

The source repository's `SIMULATION.md` compares level-99 campaigns using default
gear behavior, the optional stat approximation, and a declared consumer budget
allocation. Its retained model and purchase records distinguish exact prices
from outcomes under chosen combat, recovery, and spending rules. It also studies
the local army and a separate 80-actor consumer; those calculations do not verify
HTTP behavior or commercial readiness. The optional experimental combat profile
supplies damage and initiative only. Set supplies no level curve or guarantee
of campaign balance.

### The same loop at any scale

Nothing above assumes a single hero. The API is stateless and every formula is per-entity, so the same per-entity prices can be applied to a roster or an army; this does not establish unlimited service throughput:

- **Mass battles**: derive one seed per character and call the API once per member. PWR and equipment orb value can support a game-defined roster budget, but do not prove balanced combat. Retain the complete generation recipe and snapshot to replay a roster. Before variance/flooring, forty average-stat-12 veterans price at `40 × 9 × 3 = 1,080` orbs; actual drops vary.
- **Roguelikes**: retain each generation request and the matching source/content release for replay. The game supplies dungeon generation, combat history, permadeath, and any salvage carryover.

## Grading a Whole Character

```sh
curl 'https://set.world/api/power?stats=14-12-10-11-13-16-12-14-11&skills=2'
```

`powerRating = level × 100 + (str + int + dex + agi + vit) × 10 + (wis + per + res) × 5 + luck × 2 + skills × 25`, read off the reconciled stat block. Every `/api/roll/character` response already carries `powerRating` and `powerRatingMax`; the standalone endpoint re-grades characters you store yourself. Use the sum across a roster as a salary cap; the matchmaking rule stays yours.

## Item Power Budgets

Items never ship resolved stat modifiers — what a point of power buys inside your combat math is exactly the dial your game must tune for itself. What Set grades is the budget and the theme:

```sh
curl 'https://set.world/api/modifiers?indexes=<19-numbers>'
curl 'https://set.world/api/modifiers/spec'
```

| Grade | F | E | D | C | B | A | S |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Budget | 0 | 1 | 2 | 4 | 8 | 16 | 32 |

The budget doubles per grade while guarantee price grows 5×. That is a relation between published numbers, not a bound on combat power. Name factors map to theme channels through the pinned hash/channel list; your game supplies concrete magnitudes and mechanics.

## Calculating Derived Stats

Every character has 9 base stats, but combat and movement are governed by 23 derived attributes computed from the 5 primary stats (strength, dexterity, agility, intelligence, vitality). Use these endpoints to calculate and inspect them.

```sh
# Derive all 23 attributes from a stat array
curl 'https://set.world/api/attributes?stats=14-12-10-11-13-16-12-14-11'

# See the full formula table (base, coefficients, which stats feed each attribute)
curl 'https://set.world/api/attributes/spec'

# Confirm canonical stat order and bounds before calling
curl 'https://set.world/api/stats'
```

The formula for each attribute is `base + primaryCoef × (primary - 8) + secondaryCoef × (secondary - 8)`. The spec endpoint returns every coefficient so your client can recompute attributes locally without calling the API on every stat change.

## Status Effects

The world provides 48 status-effect names with prose descriptions. Use them as vocabulary for your combat status system, buff and debuff layer, or item enchantment pool; your game defines their numerical mechanics.

```sh
# Get all status effects
curl 'https://set.world/api/effects'
```

Effects include conditions such as Burn, Poison, Bleed, Frozen, Charmed, Silenced, Haste, Berserk, Invisible, and many others. Each entry has a `name` and `description` written in the voice of the world. The mechanical interpretation belongs to you as the game developer. Apply them as damage-over-time, crowd control, buffs, debuffs, or any system your game requires.

## Reproducibility

Content revision 3 adds the experimental combat profile. Its JSON responses also
carry a separate `rulesVersion`, and optional version preconditions reject
mismatches. Existing generation draws, weights, and prices remain unchanged;
preview stamps from revision 2 or earlier need a fresh roll. Birth records are
never rewritten for the new profile.

For replay, retain the operation/mode, all effective inputs, seed, and matching content/rules snapshot. `deriveSeed(seed, i)` supplies per-character seeds using uint32 multiplication; it does not encode the rest of a game's rules or history. `contentVersion` now uses `3.<fingerprint>`: an explicit rules revision plus a compact SHA-256 fingerprint of structured generation tables, including returned prose and metadata without Unicode normalization. Output-affecting code changes require an explicit revision bump. The trait/theme hash is unchanged. Old `1.<weights>.<tables>` preview links require a fresh roll; stored births are preserved and current appraisals are labeled when provenance differs or is unknown. Drop responses echo their seed (null when unseeded). Keep full objects or the matching source/content release for historical results; the live API does not host old snapshots.

All API roll, craft, and drop creation enters the process-local forge after
validation. Nested drop crafting stays synchronous inside its parent request;
the queue does not establish fleet-wide throughput or combat rules.

## Item Scoring

Both craft modes return an enriched `item` with its raw `roll`, selected `indexes`,
and canonical `breakdown`. The response also carries `score`, `materialRank`,
`tier`, `tierGrade`, `tierName`, `material`, `seed`, and `contentVersion`.
Render grade, material, orb comparison value, and affected domains from
`item.breakdown`. Link the name to `/roll/item/<item.roll joined by dashes>`
for full inspection. Orb mode adds the `analysis` fields described above.

To re-score any item later (e.g., from a stored index vector):

```sh
curl 'https://set.world/api/rarity?indexes=0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18'
```

## Source

Full source and architecture: <https://github.com/jimmylee/set>. MIT licensed.
