Tema 3 – Liga Boților (C++)

🤖 Liga Boților - Resource Rush ⚔️

Construiește un motor de simulare pentru un joc de colectare resurse pe o hartă rectangulară (N × M) cu obstacole și power-ups. Formatul este 100% comandă-per-linie, astfel sunt posibile dueluri intre 2 jucatori.

📅 Publicare: 8.12.2025
Deadline: 22.12.2025, ora 23:59
🎯 Punctaj Total: 10p (9p teste + 1p README + până la 5p bonus clasament)
🧪 Teste: 20 scenarii automate (folder `teste/`)
🏆 Clasament Live: rezultate.eu
📝 Accept Assignment: Classroom Link

Autor: Trifu Marius-Constantin

Informații Generale

Tehnologii:

  • ✅ Limbaj: C++ (este voie cu STL)
  • ✅ Testare: 20 teste dinamice
  • ✅ Deploy: GitHub Actions
  • ✅ Clasament: rezultate.eu

Cerințe:

  • ✅ Structuri/Clase proprii pentru boți, hartă, comenzi
  • ✅ Separate `.h` / `.cpp`
  • ✅ Compilare prin `make`

1. Descriere

Jocul este un joc de colectare resurse pe hartă rectangulară 2D (N × M). Ești un jucător pe o hartă rectangulară definită printr-o matrice și te poți deplasa pentru a colecta resurse cu valori diferite. Simularea rulează pe runde (ticks), iar intrarea este o succesiune de comenzi trimise de arbitru. După fiecare comandă procesată trebuie să emiți propria ta decizie.

🎯 Obiectiv: Ajungi la punctul final înainte ca numărul de runde să se termine, colectând cât mai multe resurse pe drum. Maximizează TOTAL_SCORE = suma valorilor resurselor colectate (cu multiplicatori).

⚠️ Condiție de trecere test: Dacă numărul de runde se termină și nu ești la punctul final, testul pică (0 puncte). Dacă ajungi la punctul final înainte de terminarea rundelor și ai scorul minim necesar, testul trece.

Mecanica Jocului

Ticks și Acțiuni:

  • Un tick = o rundă în care fiecare jucător face exact o acțiune
  • Acțiuni posibile: `MOVE` (deplasare o casetă sau 2 cu superputere), `WAIT` (stai pe loc)
  • După fiecare comandă primită, trebuie să răspunzi cu exact o acțiune

Hartă:

  • Hartă rectangulară de dimensiuni `N × M` (coordonate 0-index)
  • Dimensiuni maxime: 50 × 50 (N ≤ 50, M ≤ 50)
  • Hartă definită printr-o matrice de caractere în fișierul de intrare
  • Fiecare celulă poate conține:
    • `0` = teren gol (poți merge, dar nu primești puncte)
    • `1-99` = resursă cu valoare (când ajungi, colectezi valoarea și celula devine `0`)
    • `E` = empty (gol în hartă, NU poți merge)
    • `W` = perete (zid, NU poți merge normal, dar poți sări peste cu superputere)
    • `F` = fire (perete de foc, dacă treci peste el, jocul se termină pentru tine)
    • `J` = superputere Jump (permite mișcare de 2 casete sau să sari peste W/E)
    • `D` = Double (dublează toate resursele colectate de acum încolo)
    • `T` = Triple (triplează toate resursele colectate de acum încolo)

Mișcare:

  • Te poți deplasa la coordonatele `(x, y)` folosind comanda `MOVE x y`
  • Coordonatele sunt 0-index: `x` = linia, `y` = coloana
  • Poți merge doar pe celule cu: `0`, `1-99`, `J`, `D`, `T`
  • NU poți merge pe: `E`, `W`, `F` (fără superputere)
  • Cu superputerea Jump, poți sări peste `W` sau `E` sau să te miști 2 casete

Superputere Jump (J):

  • Când treci peste o celulă cu `J`, primești superputerea Jump
  • Cu Jump activ, poți:
    • Să mergi 2 casete într-o direcție (ex: `MOVE x+2 y` sau `MOVE x y+2`)
    • sari peste o celulă `W` sau `E` (ex: dacă ai `W` între poziția ta și destinație, poți sări peste el)
  • Superputerea Jump rămâne activă permanent până ajungi la punctul final (nu se consumă)
  • Dacă ai deja Jump activ și treci peste alt `J`, nu se schimbă nimic (Jump-ul rămâne activ)

Power-ups Double (D) și Triple (T):

  • Când treci peste o celulă cu `D` sau `T`, activezi multiplicatorul
  • `D` = dublează toate resursele colectate de acum încolo
  • `T` = triplează toate resursele colectate de acum încolo
  • Multiplicatorii se înmulțesc (dacă ai D activ și treci peste T, ai 2×3=6x)
  • Multiplicatorii rămân activi permanent (nu se consumă)
  • Poți lua toate bonusurile (J, D, T) și se stochează - Jump rămâne activ, multiplicatorii se înmulțesc

Colectare Resurse:

  • Când te deplasezi într-o celulă cu număr `1-99`, colectezi automat valoarea
  • După colectare, celula devine `0`
  • Punctele se calculează: `valoare_resursa × multiplicatori_activi`
  • Exemplu: resursă 5, ai D activ → primești 10 puncte

Fire (F):

  • Dacă treci peste o celulă cu `F`, jocul se termină pentru tine
  • Nu poți sări peste `F` nici cu Jump
  • `F` este fatal

Punct Final:

  • La începutul jocului se definește un punct final (FINAL_X, FINAL_Y)
  • Jocul se termină când:
    • Un jucător ajunge la punctul final (câștigă automat)
    • SAU se termină numărul de runde alocate
  • IMPORTANT: Dacă se termină rundele și nu ești la punctul final, testul pică (0 puncte)
  • Dacă ajungi la punctul final înainte de terminarea rundelor și ai scorul minim necesar (din `teste/limite_minime.txt`), testul trece

Scor:

  • Primești puncte pentru fiecare resursă colectată (cu multiplicatori)
  • Dacă treci peste `F`, jocul se termină și testul pică (0 puncte)
  • Dacă nu ajungi la punctul final când se termină rundele, testul pică (0 puncte)
  • Dacă comanda `MOVE` este invalidă (destinație invalidă, perete, empty, fire, sau în afara hărții), testul pică (0 puncte)

Fluxul unei simulari

1. Citești configurarea hărții (dimensiuni, matricea hărții, poziție inițială, punct final).
2. Primești comenzi de la arbitru una câte una (mișcări ale adversarului).
3. După fiecare linie citită **trebuie** să răspunzi cu exact 1 linie care descrie acțiunea ta pentru acel tick.
4. Jocul se termină când ajungi la punctul final sau se termină numărul de runde.
5. Scriptul de verificare calculează automat scorul și verifică dacă testul a trecut sau a picat.

2. Formate Fișiere

📝 Respectă exact formatele! Fișierele de test vor fi în `teste/input/test1.txt … test20.txt`. Output-urile așteptate sunt în `teste/output/`.

2.1 Fișier de intrare (arena.txt)

arena.txt
ARENA N M ROUNDS
INITIAL_X INITIAL_Y
PLAYER2_X PLAYER2_Y
FINAL_X FINAL_Y
MAP
char11 char12 ... char1M
char21 char22 ... char2M
...
charN1 charN2 ... charNM
END_MAP
STREAM
TICK <t> <action>
TICK <t> <action>
...

Explicații:

  • `ARENA` – dimensiunile hărții (N rânduri, M coloane, 0-index), număr maxim de runde.
  • `INITIAL_X INITIAL_Y` – poziția inițială a jucătorului tău (Jucător 1).
  • `PLAYER2_X PLAYER2_Y` – poziția inițială a adversarului tău (Jucător 2).
  • `FINAL_X FINAL_Y` – punctul final pe care trebuie să-l atingi pentru a câștiga (coordonate 0-index).
  • `MAP` – matricea hărții. Fiecare linie conține M caractere separate prin spațiu.
  • `STREAM` – începe secvența de comenzi live. Liniile vin în timp real / sequential; nu există număr declarat, trebuie să citești până la sfârșitul fișierului.
  • `TICK <t> <action>` – la fiecare tick primești acțiunea adversarului. `<action>` poate fi: `WAIT` (stă pe loc) sau `MOVE x y` (s-a deplasat la coordonatele x, y, unde x=linie, y=coloană).

Notă: Cuvântul TICK este folosit în gaming pentru a desemna o unitate de timp/rundă într-o simulare. Este standard în jocuri turn-based și simulări.

Direcții disponibile: `N` (sus), `S` (jos), `E` (dreapta), `W` (stânga). NU sunt permise diagonalele.

Exemplu:

ARENA 5 5 20
0 0
3 2
4 4
MAP
0 5 W 0 10
E 3 0 W 7
0 0 J 0 0
W 2 D 4 W
0 0 F 0 15
END_MAP
STREAM
TICK 1 WAIT
TICK 2 MOVE 3 3
TICK 3 MOVE 4 3
...

2.2 Format comenzi de intrare

Comandă Semnificație
TICK t WAIT Tick-ul `t` - adversarul stă pe loc (nu se mișcă).
TICK t MOVE x y Tick-ul `t` - adversarul s-a deplasat la coordonatele (x, y), unde x=linie, y=coloană (0-index).

Observații:

  • La fiecare tick primești o linie `TICK <n> <action>` cu acțiunea adversarului.
  • `<action>` poate fi: `WAIT` (adversarul stă pe loc) sau `MOVE x y` (adversarul s-a deplasat).
  • După fiecare linie `TICK`, trebuie să răspunzi cu propria ta acțiune.
  • Nu vezi resursele colectate de adversar sau power-ups activați - doar mișcările.

2.3 Output obligatoriu (stdout)

Programul trebuie să scrie la stdout exact o linie după fiecare comandă `TICK` primită.

💡 Debug: Poți scrie mesaje de debug la stderr (ex.: `std::cerr « “msg” « std::endl;`). Scripturile de verificare nu citesc stderr, deci nu afectează verificarea testelor. Acest lucru este util pentru debugging local.

Format:

  • `MOVE x y` – te deplasezi la coordonatele (x, y), unde x=linie, y=coloană (0-index)
  • `WAIT` – stai pe loc

Reguli:

  • Exact 1 linie după fiecare comandă de intrare procesată.
  • Linia de output corespunde aceluiași tick pentru care ai primit comanda.

Exemplu output:

MOVE 0 1
MOVE 1 1
WAIT
MOVE 2 1

3. Reguli de Validare

🗺️ Mișcare

  • Poți merge doar în direcții: `N` (sus), `S` (jos), `E` (dreapta), `W` (stânga).
  • NU poți merge pe diagonală.
  • Poți merge doar pe celule cu: `0`, `1-99`, `J`, `D`, `T`.
  • NU poți merge pe: `E`, `W`, `F` (fără superputere).
  • Nu poți ieși din hartă: coordonatele trebuie să fie în `[0, N) × [0, M)`.
  • Dacă comanda `MOVE` este invalidă (destinație invalidă, perete, empty, fire, sau în afara hărții) → testul pică (0 puncte).

💎 Colectare Resurse

  • Când te deplasezi într-o celulă cu număr `1-99`, o colectezi automat.
  • După colectare, celula devine `0`.
  • Punctele = `valoare_resursa × multiplicatori_activi`.
  • Nu poți colecta resurse dacă stai pe loc (`WAIT`) - trebuie să te miști în celula cu resursă.

🚀 Superputere Jump

  • Când treci peste o celulă cu `J`, primești Jump (rămâne activ permanent).
  • Cu Jump activ, poți:
    • Să mergi 2 casete: `MOVE x+2 y` sau `MOVE x y+2` (te miști 2 casete într-o direcție)
    • Să sari peste `W` sau `E`: dacă ai `W` între poziția ta și destinație, poți sări peste el (celula de după trebuie să fie validă)
  • NU poți sări peste `F` (fire).
  • Jump rămâne activ permanent până ajungi la punctul final (nu se consumă).

⚡ Power-ups Double și Triple

  • Când treci peste `D` sau `T`, activezi multiplicatorul permanent.
  • `D` = 2x pentru toate resursele viitoare.
  • `T` = 3x pentru toate resursele viitoare.
  • Multiplicatorii se înmulțesc (D + T = 6x).
  • Poți lua toate bonusurile (J, D, T) și se stochează - Jump rămâne activ, multiplicatorii se înmulțesc.
  • Rămân activi până la finalul jocului.

🔥 Fire (F)

  • Dacă treci peste o celulă cu `F`, jocul se termină pentru tine.
  • Nu poți sări peste `F` nici cu Jump.
  • Primești 0 puncte dacă treci peste `F`.

🏁 Punct Final

  • Trebuie să ajungi la punctul final (FINAL_X, FINAL_Y) înainte ca numărul de runde să se termine.
  • Dacă ajungi la punctul final → câștigă jocul (indiferent de scor).
  • Dacă se termină rundele și NU ești la punctul final → testul pică (0 puncte, fail).
  • Verificarea se face la fiecare tick: dacă poziția ta este (FINAL_X, FINAL_Y), jocul se termină; continui să primești doar liniile `TICK` până la finalul rundelor sau până ajungi la punctul final.

⏱️ Sincronizare

  • Pentru fiecare `TICK t` trebuie să setezi contextul curent.
  • În testele oficiale, comenzile `TICK` vin întotdeauna în ordine crescătoare secvențială (TICK 1, TICK 2, TICK 3, TICK 4, … fără gap-uri între ele).

🪙 Scoring logic

  • Scorul se calculează ca suma valorilor resurselor colectate, cu multiplicatorii aplicați.
  • Fiecare resursă colectată se înmulțește cu multiplicatorul activ (1x, 2x pentru D, 3x pentru T, 6x pentru D+T).
  • Condiții de trecere test:
    • Dacă ajungi la punctul final înainte de terminarea rundelor ȘI ai scorul minim necesar (din `teste/limite_minime.txt`) → testul trece
    • Dacă se termină rundele și NU ești la punctul final → testul pică (0 puncte)
    • Dacă treci peste `F` → jocul se termină și testul pică (0 puncte)

4. Punctaj

⚠️ IMPORTANT - Anti-copiere: Dacă se detectează teme copiate sau cod plagiat, se acordă 0 puncte pentru întreaga temă, indiferent de rezultatele testelor/bonusuri.

⚠️ IMPORTANT - Notare: Dacă tema nu compilează sau nu trece niciun test, tema este notată direct cu 0 puncte, nu se primeste nici bonus.

4.1 Teste automate (9p)

  • 20 teste × 0.45p.
  • Fiecare test are limită minimă în `teste/limite_minime.txt`.
  • Timeout: Fiecare test are un timeout de 5 secunde pentru rulare
  • Unele teste includ dueluri simulate (output → input). Programul trebuie să rămână consistent.

4.2 README (1p)

  • Nume + grupă.
  • Descrierea programului: Explică cum funcționează programul tău, cum ai gândit implementarea, ce structuri de date folosești și de ce.
  • Structura codului: Descrie organizarea fișierelor și claselor (ce face fiecare clasă/funcție).
  • Format: README.md în format Markdown standard (titluri, liste, cod, etc.).

4.3 Bonus Clasament

  • Bonus acordat în funcție de poziția în clasamentul duelurilor:
    • Loc 1: +6p
    • Loc 2-3: +5p
    • Loc 4-5: +4p
    • Loc 6-10: +3p
    • Loc 11-20: +2p
    • Loc 21-25: +1p
  • Clasamentul se calculează din duelurile între teme; bonusul se acordă în plus față de punctele din teste/README.
  • În tabelul cu scoruri există un buton care deschide pagina cu clasamentul duelurilor; acolo poți vedea și animația/replay-ul fiecărui duel.

5. Depunctări

Depunctări dacă:

  • Nu redenumești corect repository-ul: -0.5p
  • Codul nu trece verificarea cu Valgrind (se verifică manual la final): -1p
  • Codul nu este împărțit în fișiere separate (.h / .cpp): -0.5p
  • Cod scris fără comentarii minime/structură clară, variabile numite aleator: până la -1p
  • Folosești AI (ChatGPT/Copilot etc.) fără să menționezi clar în README ce porțiuni au fost generate sau dacă depășești 30% din cod generat de AI: până la -6p

Foarte important: după accept, redenumește repository-ul în formatul:

  • `tema3-32XAB-Nume-Prenume`
  • Exemplu: `tema3-322AB-Trifu-Marius`

Cum redenumești pe GitHub:

1. Intră în repository
2. Click pe Settings
3. Secțiunea General → Repository name
4. Schimbă în `tema3-32XAB-Nume-Prenume`
5. Click Rename

6. Încărcare și Testare

Comenzi Make:

make              # compilează și rulează toate testele din teste/input
make build        # doar compilare
make test5        # rulează doar testul 5
make test-all     # rulează toate testele (test1-test20)

7. Exemplu Simplificat

Scenariu: Hartă 5×5, tu (Jucător 1) ești la (0,0), adversarul (Jucător 2) la (3,2), punctul final la (4,4). Hartă cu resurse, pereți și power-ups. Trebuie să ajungi la (4,4) înainte de 10 de runde.

Input
ARENA 5 5 10
0 0
3 2
4 4
MAP
0 5 W 0 10
E 3 0 W 7
0 0 J 0 0
W 2 0 4 W
0 0 F 0 0
END_MAP
STREAM
TICK 1 WAIT
TICK 2 MOVE 3 3
TICK 3 MOVE 2 3
TICK 4 MOVE 2 4
TICK 5 MOVE 1 4
TICK 6 MOVE 0 4
TICK 7 WAIT
TICK 8 WAIT
TICK 9 WAIT
TICK 10 WAIT
Output
MOVE 0 1
MOVE 0 2
MOVE 1 2
MOVE 2 2
MOVE 3 2
MOVE 3 3
MOVE 4 3
MOVE 4 4

Explicație:

  • Obiectiv: Ajungi la punctul final (4,4) înainte de 10 runde, colectând cât mai multe resurse.
  • Tick 1: Primești `TICK 1 WAIT` - adversarul stă pe loc. Răspunzi cu `MOVE 0 1`.
  • Tick 2: Primești `TICK 2 MOVE 3 3` - adversarul s-a mutat la (3,3). Te miști la (0,1) cu `MOVE 0 2`.
  • Tick 3: Primești `TICK 3 MOVE 2 3` - adversarul s-a mutat la (2,3). Continui să te miști spre est la (0,2) cu `MOVE 1 2`.
  • Continui să te miști și colectezi resurse, iar la Tick 9 ajungi la (4,4) - punctul final cu `MOVE 4 4`.
  • Dacă ajungi la (4,4) înainte de 10 runde și ai scorul minim necesar → testul trece!
  • Dacă se termină rundele și nu ești la (4,4) → testul pică (0 puncte).

8. Reguli Dueluri

8.1 Format și hartă

  • Duelurile folosesc aceeași logică de joc, pe harta de referință de mai jos (duel.txt); în pagina de dueluri poți vizualiza animația/replay-ul fiecărui duel (buton din tabelul de scoruri).
duel.txt
ARENA 12 21 200
0 9
0 11
11 10
MAP
0 0 0 0 W 15 0 0 E 0 E 0 E W 0 0 0 0 0 21 22
J 21 0 W 12 21 17 13 E 0 0 0 E 12 12 19 J 0 12 13 12
W 0 0 12 18 0 J 0 F E 0 E 15 17 W 0 13 0 D 14 W
18 0 F 12 21 0 J 12 W 19 22 0 0 W 12 W 0 17 W 15 0
15 21 13 0 0 J 13 17 13 16 17 J 15 0 0 0 15 W 12 18 W
0 F 0 W 14 0 18 W 0 18 0 13 0 W 16 13 0 17 16 18 17
14 0 14 15 0 13 0 14 12 13 0 19 15 15 21 12 0 12 0 13 16
0 20 22 12 22 0 W W 0 0 0 18 0 0 21 J 17 21 19 F 0
15 0 0 0 20 16 0 12 18 F F F 0 16 W J 12 19 J 21 0
13 0 16 16 0 17 W F 0 0 13 0 J 20 21 0 15 15 19 12 20
J 19 19 0 0 T 22 0 13 F E F 18 19 0 0 14 0 0 0 0
W 0 14 0 0 0 20 15 22 F 0 F 12 W 0 0 16 12 0 21 0
END_MAP
STREAM
  • Perspective jucători: fișierul de mai sus este din perspectiva Player 1 (P1); în pagina de dueluri se poate vedea animația/replay-ul duelului (buton din pagina de scoruri).
ARENA 12 21 200
0 9        # start P1
0 11       # start P2
11 10      # FINAL_X FINAL_Y
  • Dacă joci ca Player 2 (inversare roluri), liniile de start devin:
ARENA 12 21 200
0 11       # start P1 (era P2)
0 9        # start P2 (era P1)
11 10
  • Harta rămâne identică; doar liniile de start se schimbă pentru a vedea duelul din perspectiva celuilalt jucător. La fiecare push nou (submit score), se rulează automat dueluri între tema ta și toate celelalte teme eligibile; rezultatele și animațiile (replay) apar în pagina de dueluri (buton din pagina de scoruri).
  • Fiecare duel are 2 jucători (tema ta vs tema altui student), cu tick-uri trimise secvențial.

8.2 Ordinea mutărilor și simultaneitate

  • La fiecare `TICK`, fiecare jucător primește poziția anterioară a adversarului (nu poziția rezultată după mutarea curentă).
  • Dacă ambii aleg o destinație și ajung simultan în aceeași celulă, resursa se anulează (nu primește nimeni puncte) și celula devine `0`.
  • Dacă celula este `F` (fire), jucătorul care intră pierde instant; celălalt poate continua (dacă are tick-uri).

8.3 Finalul pentru un jucător

  • Când un jucător ajunge la punctul final, procesul lui se oprește; pentru restul tick-urilor i se trimite automat `WAIT`.
  • Celălalt jucător continuă să joace până ajunge la final sau se termină tick-urile disponibile.
  • Dacă se termină tick-urile și jucătorul nu e la final, duelul se încheie pentru el cu starea curentă (fără puncte suplimentare).

8.4 Scor și afișare

  • Scorul din duel este suma resurselor colectate (cu multiplicatori) până la încheierea individuală a fiecărui jucător.
  • Clasamentul duelurilor folosește suma totală a acestor scoruri; bonusurile de clasament se acordă separat conform regulilor din secțiunea Punctaj.

9. Tips & Checklist

  • ✅ Asigură-te că output-ul tău nu are spații în plus.
  • ⛔ Nu amesteca logică de I/O cu logica de simulare – folosește stderr pentru debug.
  • ✅ Verifică întotdeauna dacă destinația este validă înainte de mișcare.
  • ✅ Gestionează corect Jump (rămâne activ permanent, nu se consumă).
  • ✅ Calculează corect multiplicatorii (se înmulțesc).
poo-is-ab/tema/2025/03.txt · Last modified: 2025/12/11 18:00 by marius.trifu
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