Quickstart — Profile a Player in 5 Minutes
This guide walks you through installing @playprint/core, recording decisions during gameplay, and extracting a player's behavioural profile. No server, no API key, no backend required.
1. Install the SDK
npm install @playprint/core 2. Track Decisions During Gameplay
import { PlayprintTracker, createGhost, getArchetype } from '@playprint/core';
const tracker = new PlayprintTracker({ gameId: 'my_game' });
// Start a match
tracker.startMatch();
// Record decisions as they happen (Tier 1: just a label)
tracker.decision({ label: 'attack' }); // risk inferred: 0.7
tracker.decision({ label: 'defend' }); // risk inferred: 0.2
tracker.decision({ label: 'bluff', risk: 0.9, information: 0.3 }); // Tier 2: you set risk
// Record outcomes
tracker.outcome({ type: 'hit', delta: 0.5 });
tracker.outcome({ type: 'block', delta: -0.2 });
// End the match — returns the updated profile
const profile = await tracker.endMatch('win');
console.log(profile);
// { aggressive: 0.72, bold: 0.55, deceptive: 0.33, chaotic: 0.41, urgent: 0.68, expansive: 0.29 } You don't need to compute risk values yourself. Tier 1 input ({ label: 'attack' }) automatically infers risk from a built-in keyword map. "attack" → 0.7, "defend" → 0.2, "gamble" → 0.9, etc. You can customize with the riskMap option if needed.
3. Generate a Ghost AI Opponent
import { createGhost, mapGhostBiases } from '@playprint/core';
// Convert profile → 8 bias weights (6 core + 2 comms)
const ghost = createGhost(profile);
// { aggression: 0.72, patience: 0.28, riskTolerance: 0.65,
// consistency: 0.8, deception: 0.15, reach: 0.29,
// expressiveness: 0, provocation: 0 }
// With comms data — the ghost also knows how to talk
const ghost = createGhost(profile, commsProfile);
// { ...core biases, expressiveness: 0.57, provocation: 0.68 }
// Map biases to your game's AI parameters
const aiParams = mapGhostBiases(ghost, {
attackFrequency: { bias: 'aggression', range: [0.1, 0.9] },
retreatThreshold: { bias: 'patience', range: [0.2, 0.8] },
bluffChance: { bias: 'deception', range: [0, 0.3] },
emoteFrequency: { bias: 'expressiveness', range: [0, 0.8] },
tauntChance: { bias: 'provocation', range: [0, 0.5] },
}); 4. Classify the Player's Archetype
import { deriveTraits, generateArchetype } from '@playprint/core';
const traits = deriveTraits(profile);
const archetype = generateArchetype(traits);
// {
// coreArchetype: 'Berserker',
// styleModifier: 'Reckless',
// displayName: 'Reckless Berserker',
// tempoTag: 'Burst player',
// behaviors: ['Overwhelms with relentless speed'],
// tagline: 'Charges in hard and trusts instinct over strategy.',
// } For richer archetypes, use generateArchetype() instead — it produces 5-layer personality descriptions with 12 possible core types (Berserker, Ghost, Daredevil, Sentinel, Phantom, Purist, etc.), style modifiers, tempo tags, behaviour phrases, and taglines.
Decision Input Tiers
The SDK supports three levels of detail for recording decisions:
| Tier | Input | When to Use |
|---|---|---|
| 1 | { label } | Quick integration — risk inferred from label keywords |
| 2 | { label, risk, information } | You compute your own risk/info values (0–1) |
| 3 | Full DecisionPayload | Complete control over all fields (risk, information, tempo, intent_tags) |
Storage
By default, match data is stored in memory (lost on page reload). For persistence:
import { PlayprintTracker, LocalStorageAdapter } from '@playprint/core';
const tracker = new PlayprintTracker({
gameId: 'my_game',
storage: new LocalStorageAdapter(), // persists to browser localStorage
});
Implement the StorageAdapter interface for custom backends (database, IndexedDB, API, etc.).
Next Steps
- Read the Core Concepts to understand traits, archetypes, and ghost AI
- See the API Reference for all exported classes, functions, and types
- Check the Compliance page for privacy and data handling details