This is an old revision of the document!
Generarea personajelor și a obiectelor este una dintre cele mai utilizate tehnici în jocurile moderne, de la RPG-uri care generează milioane de iteme unice până la simulări emergente, unde NPC-urile duc “vieți” organice bazate pe reguli simple.
Un NPC este definit printr-o combinație de atribute statice (nume, clasă, aspect etc.) și atribute dinamice (viață, damage, personalitate). Cheia unui sistem bun nu este generarea de atribute pur aleatorie, ci generare aleatorie controlată (valori generate în intervale cu sens, combinate prin reguli care produc personaje coerente).
În general, clasele de NPC nu sunt echiprobabile (de exemplu, războinicii sunt mai comuni decât magicienii legendari). Distribuția ponderată permite controlul frecvenței fiecărei clase.
Fiecare clasă definește intervale de bază pentru atributele NPC-urilor. Randomizarea se aplică în interiorul acestor intervale, nu global — un Mage va fi mereu mai slab fizic decât un Warrior, indiferent de roll. Exemplu:
| Class | HP | Damage | Armor |
|---|---|---|---|
| Warrior | 80–120 | 15–25 | 10–20 |
| Mage | 40–65 | 30–50 | 2–5 |
| Rogue | 55–80 | 20–35 | 5–10 |
| Archer | 60–85 | 18–30 | 4–8 |
| Paladin | 90–130 | 12–20 | 15–25 |
Trăsătura de personalitate nu este doar cosmetică; aceasta modifică valorile de bază și va influența comportamentul în simulare. Fiecare trăsătură aplică un multiplicator pe atribute. Exemplu:
| Trăsătură | Efect pe atribute | Comportament în simulare |
|---|---|---|
| Aggressive | Damage ×1.3, HP ×0.9 | Atacă primul, preferă duelul direct |
| Coward | HP ×0.8, Armor ×0.7 | Fuge când HP < 40% |
| Brave | HP ×1.1, Damage ×1.1 | Nu fuge niciodată, protejează aliații |
| Cunning | Damage ×1.2, Armor ×1.1 | Atacă NPC-ul cu HP cel mai scăzut |
| Peaceful | HP ×1.15, Damage ×0.7 | Nu inițiază atacuri, ripostează doar |
Raritatea controlează atât puterea unui item (stat budget), cât și frecvența cu care apare. Sistemul clasic cu culori comunică vizual calitatea instantaneu. Exemplu:
| Raritate | Culoare | Probabilitate | Stat multiplier | Abilitate specială |
|---|---|---|---|---|
| Common | Alb | 55% | 1.0× | Nu |
| Uncommon | Verde | 25% | 1.3× | Nu |
| Rare | Albastru | 12% | 1.7× | Nu |
| Epic | Mov | 6% | 2.2× | Da |
| Legendary | Portocaliu | 2% | 3.0× | Da (2 abilități) |
Itemele de raritate mai mare nu au toate statisticile mai mari față de cele comune. În schimb, fiecare item primește un buget de putere total (calculat din raritate), iar acel buget este distribuit aleatoriu între atribute. Astfel, două iteme de aceeași raritate pot fi foarte diferite (de exemplu, unul poate fi axat pe damage, altul pe durabilitate).
Abilitățile speciale se adaugă peste budget pentru Epic și Legendary. A doua abilitate a unui Legendary este aleasă explicit diferit de prima: dacă prima e Poison, a doua e aleasă din restul listei (Lifesteal, FireDamage, IceSlow, Thunder).
GenerateItem(type, rarity):
budget = baseBudget * rarityMultiplier[rarity]
damage = Random(0.4, 0.7) * budget // 40-70% din budget pe damage
durabil = budget - damage // restul pe durabilitate
if rarity >= Epic:
ability = SelectRandom(specialAbilities)
if rarity == Legendary:
ability2 = SelectRandom(specialAbilities - {ability})
Abilitățile speciale sunt definite ca modificatori cu parametri proprii generați în intervale. Exemplu:
| Abilitate | Efect | Parametru generat |
|---|---|---|
| Poison | Damage over time | 3–8 damage/tick, 3–5 tick-uri |
| Lifesteal | Regenerare HP la hit | 15–30% din damage ca HP |
| Fire Damage | Bonus damage + burn | +5–15 damage, 2 tick-uri burn |
| Ice Slow | Reduce viteza țintei | 20–50% slow, 2–4 secunde |
| Thunder | Șansă de stun | 15–35% șansă, 1 secundă stun |
Simularea unei lumi este un exemplu de emergent storytelling. Pe baza unor reguli simple, se crează comportamente complexe și povești unice. Fiecare zi (tick) de simulare aplică regulile tuturor NPC-urilor în ordine, iar rezultatele se acumulează într-un jurnal narativ.
La nivelul acestui laborator, simularea poate fi împărțită în patru componente independente:
La fiecare tick, fiecare NPC parcurge în ordine un arbore de decizie cu un anumit număr de priorități. Prima condiție adevărată câștigă, restul nemaifiind evaluate.
| Prioritate | Nume Acțiune | Condiție | Descriere Acțiune |
|---|---|---|---|
| 1 | Supraviețuire | Personalitate Coward și HP < 30% | Fuge la o locație aleatoare |
| 2 | Atac | Personalitate Aggressive sau Cunning și există dușmani în locație | Atacă: Cunning alege ținta cu HP minim, Aggressive alege aleatoriu |
| 3 | Trade | Există aliați în locație și NPC-ul are iteme | 25% șansă de a da un item unui aliat |
| 4 | Explorare | — | 20% șansă de a se muta în altă locație |
| 5 | Idle | — | Nicio acțiune; relațiile cresc pasiv prin co-prezență |
Trade se verifică înaintea Attack, NPC-urile vor prefera alianțele în fața conflictului și simularea va produce povești cu mai puțini morți și mai multă acumulare de relații pozitive.
Relațiile sunt stocate ca valori float într-un anumit interval predefinit (de exemplu, intervalul [−100, +100]), unde valoarea minimă înseamnă dușmănie absolută și valoarea maximă alianță puternică. Toate relațiile dintre NPC-uri pornesc de la 0 și se modifică prin interacțiuni:
| Eveniment | Modificare relație |
|---|---|
| Atac reușit | −20 pentru cel atacat față de atacant |
| Schimb de iteme | +10 pentru ambii participanți |
| Ucidere (martori prezenți) | −30 față de ucigaș pentru toți martorii |
| Fără conflict sau orice altă interacține | +2 per tick (familiaritate pasivă) |