Differences

This shows you the differences between two versions of the page.

Link to this comparison view

gp:laboratoare:06 [2026/03/28 00:19]
maria_anca.balutoiu [Generarea procedurală de NPCs]
gp:laboratoare:06 [2026/04/08 09:07] (current)
maria_anca.balutoiu [Generarea procedurală de NPCs]
Line 11: Line 11:
  
 === Atribute derivate din clasă === === Atribute derivate din clasă ===
-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:+Fiecare clasă definește **intervale de bază** pentru atributele NPC-urilor. Randomizarea se aplică în interiorul acestor intervale, nu globalun Mage va fi mereu mai slab fizic decât un Warrior, indiferent de roll. Exemplu:
  
 ^ Class ^ HP ^ Damage ^ Armor ^ ^ Class ^ HP ^ Damage ^ Armor ^
Line 70: Line 70:
 | Thunder | Șansă de stun | 15–35% șansă, 1 secundă stun | | Thunder | Șansă de stun | 15–35% șansă, 1 secundă stun |
  
 +==== Simularea unei Lumi ====
 +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:​
 +  * **World Simulator:​** Componenta centrală a aplicației,​ gestionează tick-urile, crează NPC și îi poziționează în lume la începutul simulării, gestionează sfârșitul simulării
 +  * **NPC Agent:** Conține toate informațiile despre fiecare NPC; gestionează logica de decizie pentru fiecare NPC (la fiecare tick primește contextul (vecini, relații, locație) și alege o acțiune)
 +  * **Sistemul de Relații:** Stochează relațiile dintre toate perechile de NPC-uri
 +  * **Jurnal Narativ:** Toate acțiunile alese de NPC-uri sunt transformate în text prin intermediul unor template-uri
 +
 +=== Logica de Decizie per Tick ===
 +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ță |
 + 
 +<​note>​Ordinea priorităților determină caracterul lumii simulate. Dacă ''​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.</​note>​
 +
 +=== Sistemul de Relații === 
 +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ă) |
 + 
 +<​note>​Relațiile sunt **asimetrice**. Când primul NPC modifică relația față de al doilea NPC cu un delta, relația inversă se modifică cu doar un anumit procent din acel delta.</​note>​
 +
 +=== Modificatorii de Locație ===
 +Locațiile, la rândul lor, nu sunt neutre. Ele modifică statistica de damage și probabilitățile de acțiune ale NPC-urilor prezente. De exemplu, modificatorul de agresivitate se aplică multiplicativ pe damage-ul de bază al NPC-ului pentru durata tick-ului curent, apoi se restaurează:​
 +
 +^ Locație ^ Modificator de agresivitate ^ Bonus trade ^ Bonus mișcare ^
 +| Dungeon | ×1.5 | — | — |
 +| Tavernă | ×0.6 | +40% | — |
 +| Piață | ×0.4 | +60% | — |
 +| Pădure | ×1.2 | — | +20% |
 +| Câmpie | ×1.0 | — | +10% |
 +
 +=== Jurnalul narativ procedural === 
 +Fiecare acțiune va genera o linie de text prin selectarea aleatoare a unui template și substituirea variabilelor contextuale. Template-urile sunt organizate pe tipuri de acțiuni, cu multiple variante pentru fiecare acțiune pentru a evita repetiția:
 +
 +^ Variabilă ^ Semnificație ^
 +| ''​{attacker}'',​ ''​{target}''​ | Numele NPC-urilor implicate |
 +| ''​{cls}''​ | Clasa NPC-ului care acționează |
 +| ''​{loc}''​ | Numele locației curente |
 +| ''​{dmg}''​ | Damage-ul aplicat (rotunjit) |
 +| ''​{style}''​ | Derivat din personalitate:​ ''​Aggressive''​ → "​brutală",​ ''​Cunning''​ → "​calculată"​ |
 +| ''​{hp}''​ | Procentul HP curent (pentru template-urile de fugă) |
 + 
 +Pentru acest laborator, jurnalul va reține și numărul zilei curente, prefixând fiecare intrare cu ''​[Ziua N]''​. Intrările de tip ''​Idle''​ se înregistrează rar (20% din cazuri) pentru a nu polua textul.
 + 
 +<​note>​Jurnalul narativ este ceea ce transformă o simulare abstractă de date într-o poveste. Calitatea și variabilitatea template-urilor determină dacă playerul simte că asistă la o lume vie sau citește un simplu log de debug.</​note>​
 +
 +==== Implementare în Unity ====
 +=== Setup proiect ===
 +  - **Structurile de date:** Definiți enum-urile și clasele de date pentru NPC-uri, iteme și locații (la nivelul acestui laborator sunt suficiente 5 locații și 3 modificatori de locație (agresivitate,​ trade, mișcare))
 +  - **Generatorul de NPC-uri:** Fiecare NPC se generează prin selecția ponderată a clasei și aplicarea multiplicatorilor de personalitate. Pentru început, se generează numele din două liste independente,​ apoi selectează clasa, apoi se selectează personalitatea uniform aleatoriu, iar în final se generează atributele de bază din intervalele clasei și se înmulțesc cu multiplicatorii de personalitate.
 +  - **ItemGenerator:​** Pentru calculul rarității se urmează același model de selecție ponderată. După ce raritatea e determinată,​ se calculează bugetul total (''​BASE_BUDGET × rarityMultiplier''​),​ se generează un număr aleator dintr-un interval predefinit (de exemplu, [0.4, 0.7]) pentru damage, iar restul bugetului merge la durabilitate. Numele itemului se construiește procedural dintr-un prefix aleatoriu și un sufix dependent de tip. Abilitățile speciale se adaugă pentru Epic (una) și Legendary (două distincte).
 +  - **Sistemul de Relații:** Relațiile sunt stocate ca valori float într-un anumit interval predefinit (de exemplu, intervalul [−100, +100]). Relația directă se actualizează cu delta, iar relația inversă cu ''​delta × 0.7'',​ ambele cu clamp la intervalul predefinit.
 +  - **NPC Agent:** Se implementează arborele de decizie din tabelul de relații, ținând cont și de lista vecinilor, modificatorul locației curente, în ordinea exactă a priorităților. Se calculează damage-ul primit și se verifică dacă NPC-ul a murit.
 +  - **Jurnal Narativ:** Se selectează aleatoriu din template-urile existente pentru a se afișa acțiunile NPC-urilor.
 +  - **Main World Simulator:​** Sistemul așteaptă ''​tickInterval''​ secunde între tick-uri. La fiecare ''​zi''​ nouă, se iterează printre toți agenții vii, aplică damge-ul agentului, aplică decizia luată de agent. Simularea se termină când rămâne cel mult un NPC în viață sau se epuizează zilele maxime.
 ==== Tasks ==== ==== Tasks ====
   - Creați un NPC generator simplist în care:    - Creați un NPC generator simplist în care: 
     * Un NPC este definit printr-o combinație aleatoare de nume, clasă, viață, damage.     * Un NPC este definit printr-o combinație aleatoare de nume, clasă, viață, damage.
-    * Fiecare NPC va avea și o trasătură aleatoare de personalitate,​ care îi va afecta comportamentul.+    ​* Clasa este selectată prin distribuție ponderată. 
 +    ​* Fiecare NPC va avea și o trasătură aleatoare de personalitate,​ care modifică numeric atributele de bază.
     * Pe baza clasei asociate, fiecare NPC va avea un portret afișat pe ecran.     * Pe baza clasei asociate, fiecare NPC va avea un portret afișat pe ecran.
     * Se generează un nou NPC și se afișează pe ecran la apăsarea unui buton.     * Se generează un nou NPC și se afișează pe ecran la apăsarea unui buton.
   - Creați un generator de armură și arme în care:   - Creați un generator de armură și arme în care:
-    * Un item este definit printr-un tip, o raritate, damage și durabilitate. +    * Un item este definit printr-un tip, o raritate, damage și durabilitate ​generate din **stat budget**
-    * Item-ele mai rare au și câte o abilitate specială precum ​poison, lifesteal, fire damage, ice slow.+    * Itemele Epic și Legendary au abilități speciale cu parametri proprii generați în intervale (exemple abilități: ​poison, lifesteal, fire damage, ice slow).
     * Se generează un nou item și se afișează pe ecran la apăsarea unui buton.     * Se generează un nou item și se afișează pe ecran la apăsarea unui buton.
 +    * Numele itemului se generează procedural (prefix + tip).
     * În funcție de raritatea item-ului, scrisul de pe ecran va avea altă culoare.     * În funcție de raritatea item-ului, scrisul de pe ecran va avea altă culoare.
 +  - Implementați simularea unei lumi procedurale:​
 +    * Generați 4–6 NPC-uri și distribuiți-le aleatoriu în 5 locații predefinite.
 +    * La apăsarea butonului ''​Advance Day'',​ fiecare NPC execută o acțiune bazată pe personalitate,​ HP curent și relațiile cu vecinii din aceeași locație.
 +    * Sistemul de relații [−100, +100] se actualizează după fiecare interacțiune și influențează deciziile viitoare.
 +    * Fiecare acțiune generează o linie de text narativ din template-uri cu minim 3 variante per tip.
 +    * Simularea se oprește când rămâne un singur NPC în viață sau după 10 zile și afișează un sumar procedural.
   - **Bonus 1.** Creați un meniu prin care să puteți scrola prin toate personajele și obiectele generate. Rezultatele generări se vor salva pentru a fi accesibile și la rulări ulterioare ale aplicației. Jucătorul va putea redenumi NPCs și item-urile generate.   - **Bonus 1.** Creați un meniu prin care să puteți scrola prin toate personajele și obiectele generate. Rezultatele generări se vor salva pentru a fi accesibile și la rulări ulterioare ale aplicației. Jucătorul va putea redenumi NPCs și item-urile generate.
   - **Bonus 2.** Pentru fiecare item afișați "​rarity stars" în dreptul numelui. Adăugați un efect de animație pentru cel mai rar tip de item.   - **Bonus 2.** Pentru fiecare item afișați "​rarity stars" în dreptul numelui. Adăugați un efect de animație pentru cel mai rar tip de item.
 +  - **Bonus 3.** Adăugați o hartă vizuală simplă (grid sau icoane) care arată locația curentă a fiecărui NPC și se actualizează la fiecare tick.
gp/laboratoare/06.1774649944.txt.gz · Last modified: 2026/03/28 00:19 by maria_anca.balutoiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0