the whole method

Nothing here
is guessed.

Every line ppand writes is traceable to something it actually read. This page is the full account of what gets read, where it comes from, and how it turns into a brief or a fighter.

The short version

There is no language model in this site. A brief is assembled by rules from live data, which is why the same subject always produces the same brief — and why every number on a fighter card can point at its source.

no accountno API keyno serverno storageno model call

Reading a codebase

Four reads against the public repository API, plus up to two manifest files fetched raw. Around five requests per run.

ReadWhat comes out of it
/repos/:owner/:repoSummary, star count, licence, topics, homepage, default branch, last push date
/repos/:owner/:repo/contentsTop level of the tree — folders and files, dotfiles filtered out
/repos/:owner/:repo/readmeOpening paragraph, and bullets that survive filtering
/repos/:owner/:repo/languagesByte counts per language, turned into percentages
Raw manifestspackage.json, requirements.txt, pyproject.toml, Cargo.toml, go.mod, composer.json, Gemfile

Turning that into a stack

Dependency names are matched against a lookup table, so next becomes Next.js and drizzle-orm becomes Drizzle ORM. Docker, Makefiles and Terraform are read off filenames and reported separately as tooling rather than dependencies. Anything unrecognised is left out instead of guessed at.

Filtering the readme

Bullet lists are the noisiest part of any readme, so a bullet is dropped when it is shorter than twenty characters, fewer than four words, a bare navigation word like Tutorial or Roadmap, a URL, or a path to a documentation file. If a Features heading exists, only bullets under it are used. If nothing survives, the section is labelled as a readme description rather than passed off as requirements.

Reading a website

The live markup is fetched through a relay chain, then parsed in your own browser with DOMParser. Three relays are tried in order so one bad gateway does not end the read.

The brief that comes out asks for your own copy and your own images. It reproduces structure, type and palette — the parts that are facts about the page — and explicitly tells the agent not to reuse the wording.

Reading a game

Three reads against the open encyclopedia API. Title search is scored, because a search for Doom will otherwise land on the franchise page instead of the 1993 release.

Where the infobox has no developer, the lead sentence is used — but only the lead sentence. Further down the article that same phrasing belongs to ports and sequels, and using it produced wrong studios during testing.

How a fighter is derived

Stats belong to the fighter, not to whatever produced it. A read maps to a seed, the seed picks the traits, and the traits set the stats over a common base of HP 120, ATK 60, DEF 40, SPD 55, CRIT 12. Each card prints its own working, and the full modifier table is in the whitepaper.

StatBaseRaised by
HP120Hair — black most, red least
ATK60Frown, ginger or red hair, headphones
DEF40Dark or grey eyes, green hair, black cap
SPD55Blue or brown eyes, blonde hair, pink ribbon
CRIT12Smile, hazel eyes, glasses, hairpin
SPNamed after the extra worn; no extra means Bare Hands

How a battle resolves

The swing factor comes from a seeded generator, and the seed is mixed from the two fighters. That is the whole trick: battles look lively but are reproducible, so a battle link shows everyone the identical fight.

The rules are also written in Solidity, in contracts/src/Bout.sol, using integer arithmetic only — no floats anywhere, and the seed mix avoids keccak precisely so the browser can reproduce it with Math.imul. The two implementations were diffed on twenty-four randomised battles and agreed on the winner and the round count every time, knockouts and thirty-round decisions alike. That is what makes an on-chain battle trustworthy: the chain cannot disagree with what you were shown.

The collection

Fighters are not drawn procedurally. They are the ppand collection, baked straight out of the source artwork into standalone trait layers and composited in your browser.

LayerVariantsExamples
Bodyfixedevery fighter shares it
Mouth5Straight, Smile, Frown, Talking, Talking (Happy)
Eyes5Grey, Brown, Hazel, Dark, Blue
Hair6Brown, Blonde, Black, Ginger, Red, Green
Extra5 + nonePink Ribbon, Headphones, Black Glasses, Black Cap, Yellow Hairpin

That is 900 distinct fighters. Which one you get is not a roll: each trait is picked from the fighter's seed using the same integer generator the battle uses, so a given subject always produces the same fighter, and the selection can be re-derived on chain from the seed alone.

The trait layers are the artwork's own pixels at its native 2048 by 2048, extracted with each variant standalone and no base garment baked underneath another. Every canvas composites those native layers at 2048, the roster grid included, and each layer is fetched only when a fighter that wears it is drawn. Checked against the artwork's own compositor, the only differences are on anti-aliased layer edges — 0.2 per cent of pixels, none of them a wrong layer, offset or order.

Where the NFT layer goes

Battles work today with no wallet and no chain. The on-chain layer is deliberately staged so nothing is spent before it earns its place.

1 · arcade — live2 · fighter as NFT — contract written, not deployed3 · on-chain battles4 · wagers

The arena economy

Free battles stay free and need no wallet. Ranked battles are the on-chain layer, and two different assets are involved on purpose.

RuleValue
Entry per ranked battle2,000 $PPAND
What happens to the entryIt is burned. The arena never holds it, never spends it and never pays it back, so entering permanently removes supply.
Reward assetUSDG, the stablecoin
Daily splitEach day's USDG pot is divided into 2,000 shares
Reward per winOne share, pot ÷ 2000, for each battle you won that day
MatchmakingA single queue. One fighter waits, the next entrant is paired against it, and the battle settles in the same transaction.
ClaimingOpens once the day has closed. Unclaimed shares stay claimable; shares never won are swept into a later pot.
RequirementYou must own the fighter you enter

Because the entry is burned and the reward is a different asset, the pot has to be funded in USDG rather than out of entries. That is honest by construction: the contract can only ever pay out USDG it actually holds, and it can never mint a reward. A win is worth one share whether you entered once or fifty times, and payout in a day can never exceed that day's pot because shares are capped at 2,000.

Verified on a local chain rather than asserted: a 2,000 $PPAND entry reduced the token's total supply by 2,000 and left the arena holding none of it, a 4,000 USDG pot produced a share of exactly 2 USDG, a claim before the day closed reverted with DayNotOver, the winner's claim moved exactly 2 USDG, and a second claim reverted with NothingToClaim.

Minting a fighter

RuleValue
Total supply900, one per trait combination, fixed in the contract
Cost to mint200,000 $PPAND, burned before the fighter is created
Protocol feeCharged in ETH on top of the burn, and forwarded to the treasury. To be announced.
LimitOne fighter per wallet, permanently
StatusNot open. The contract refuses to open the mint until the fee is set.

The burn happens first, so a failed mint cannot destroy tokens without producing a fighter, and a successful mint has always destroyed them. The one-per-wallet limit is permanent: sending your fighter elsewhere does not restore the right to mint another.

Also verified locally: minting while closed reverts with MintClosed, a mint burned exactly 200,000 $PPAND and reduced the token's total supply by the same amount, a second mint from the same wallet reverted with AlreadyMinted, and the supply counter stops at 900.

free battles — live$PPAND — stealth launch, firstmint — after the tokenUSDG rewards

How it launches

Both launches are stealth launches: no presale, no allowlist, no private allocation, no reserved supply and no advance notice of timing.

StageWhat happens
1 — $PPANDLaunches first. Minting burns $PPAND, so the token must exist before any mint is possible.
2 — Fighter mintOpens only once the ETH protocol fee is set in the contract. 900 supply, 200,000 $PPAND burned per mint, one per wallet.
3 — Ranked arenaOpens once fighters exist and the USDG reward pot is funded.

No insider gets a cheaper entry, and by the same token there is no queue and no guaranteed allocation. The whitepaper sets this out in full.

Limits and privacy