User Tools

Site Tools


elemental_fighters

This is an old revision of the document!


Elemental Fighters

Uz zadatak je dan i izvorni kod.

Spajanjem na zadatak, otvara se izbor borca, mogući izbor su 3 borca i 3 elementa za svakog borca.

 Slika 1. - izbor borca

No, analizom koda u zadatku, može se zaključiti da zapravo ne postoji kombinacija borca koja bi ni u najsretnijem slučaju uspjela pobijediti sve neprijatelje i doći do flaga, znači da je potrebno nešto drugo napraviti jer izbor pravog borca ne postoji.

Analizom koda, zanimljiva je varijabla

s

, koja je “scale”, odnosno određuje koliko će se oslabiti ili ojačati neprijatelje.

 Slika 2 - scale varijabla

Ova varijabla se kasnije u kodu množi s atributima neprijatelja i što je manja, neprijatelji su slabiji, što je veća, neprijatelji su jači.

Također zanimljiv dio koda je player default, koji definira varijablu

player

kao

milo("ice")

, ako je

player

None.

 Slika 3. - Player default

Najključniji dio koda je funkcija kojom se inicijalizira varijabla

player

iz izbora igrača.

 Slika 4. - inicijalizacija player varijable iz igračevog izbora

Ovdje se može vidjeti da se koristi

eval

funkcija, kojom se

fighter

unos poziva kao funkcija, a

fighterType

kao argument.

Sukladno tome, može se vidjeti da su

fighteri

zapravo funkcije:

 Slika 5. - fighter funkcije

Vrijednosti

fighterType

definirane su u rječniku te se parsiraju pri pozivanju

fighter

funkcije.

To znači da se unosom

fighterType

(“Odaberite element borca”) definira argument funkcije, a unosom

fighter

(“Odaberite borca”) definira funkcija kojoj će se argument proslijediti i koja će se izvršiti s proslijeđenim argumentom u

eval

funkciji.

No svaki unos prolazi kroz

validate_input

, koja je filter koji određuje koji su unosi dozvoljeni, a koji nisu.

 Slika 6. - validate funkcija

Kako bismo provjerili da možemo pozvati proizvoljnu funkciju i argument, ako nemamo unos koji bi

validate_function

zabranio, možemo probati pozvati:

list("aaa")
Odaberite element borca (Ice, Fire, Acid): aaaa
Odaberite borca (Zorn, Krev, Milo)list

 Slika 7. - poziv list("aaa")

Vidimo da je program vratio listu u kojoj se nalaze svi znakovi iz stringa koji smo poslali kao prvi argument, te oko njih znakovi zagrada oko

fighterType

varijable (vidi sliku 4).

Slično, možemo pozvati:

len("aaa")
Odaberite element borca (Ice, Fire, Acid): aaa
Odaberite borca (Zorn, Krev, Milo)len

 Slika 8. - poziv len("aaa")

Vidimo da program vraća 5, što odgovara trima znakovima

"a"

koje smo poslali i dvama znakovima zagrada.

No flag nije zapisan niti u jednoj varijabli, nego je hardkodiran u zadnjem printu programa. Zato je potrebno osmisliti način kako pozvati odgovarajuću funkciju i argument da bi se program uspješno izvršio do kraja i ispisao flag.

Dobar pristup bio bi mijenjanje varijable

s

(vidi sliku 2), koja predstavlja skalu jačine protivnika. Ako bismo tu varijablu mogli smanjiti ili postaviti na 0, protivnici bi bili znatno slabiji. Činjenica da je input potrošen na mijenjanje varijable

s

umjesto na inicijalizaciju borca ne bi bila problem jer postoji default odabir borca (vidi sliku 3).

No cijeli unos igrača izvršava se unutar

eval

funkcije, koja je namijenjena za evaluiranje

expression

.

Expression

je izraz koji nakon izvršavanja vraća neku vrijednost — primjerice:

"2+2"

→ 4

len("(aaa)")

→ 5

Svaka vrijednost vraćena nakon izvršavanja izraza u

eval

funkciji bit će pridružena varijabli

player

(vidi sliku 4).

Potrebno je pronaći način kako mijenjati druge varijable u globalnom kontekstu programa, kao varijablu

s

, unutar

eval

funkcije, čiji se rezultat izvršavanja pridružuje varijabli

player

.

Osim

expression

u Pythonu, koji izvršava izraz i vraća vrijednost, postoji i

statement

, koji izvršava definiranu akciju, no ne vraća ništa.

statement

je, primjerice,

a = 0

, no pošto

statement

ne vraća ništa,

b = (a = 0)

je invalidan Python kod; također

eval("a = 0")

je invalidan Python kod.

Slično

eval

, postoji funkcija

exec

, koja je namijenjena za izvršavanje

statement

(ali može izvršavati i

expression

), i može definirati ili mijenjati varijable u globalnom kontekstu ako se pokreće u globalnom kontekstu.

Primjer:

exec("a=0")

Pregledom funkcije za validaciju unosa (slika 6) vidi se da

exec

funkcija nije zabranjena. Dakle,

exec

se može koristiti za mijenjanje vrijednosti varijable

s

.

Iz ovoga se može zaključiti da potencijalni način rješavanja ovog programa bi bio izvršiti:

exec(s=0)

Unos bi izgledao ovako:

Odaberite element borca (Ice, Fire, Acid): s=0
Odaberite borca (Zorn, Krev, Milo)exec

Pokretanjem ovog unosa pojavljuje se greška:

 Slika 9. - greška pri pokušaju

Greška je

invalid syntax

, koju baca parser

eval

funkcije.

Opisana ponašanja prikazana su na slici 10.

 Slika 10. - eval parser i exec funkcija

Na slici je prikazano da

eval

može izvršiti

a==3

, jer je to validan

expression

koji se evaluira u

False

.

Može se zaključiti da je cilj napisati kod koji će parser

eval

odobriti, a koji će imati logiku jednaku

s=0
statement

. Ovdje pomaže činjenica da

exec

može izvršavati

expression

, pa treba napisati

expression

koji će

eval

parser odobriti, a

exec

izvršiti i promijeniti globalnu varijablu

s

.

Način da se to postigne je korištenjem Pythonovog “walrus” operatora (

:=

), koji je

expression

. On vraća rezultat evaluacije izraza, ali također postavlja evaluiranu vrijednost u varijablu.

 Slika 11. - walrus operator

Walrus operator evaluira

expression

poput

1 == 1

, što je

True

, i to postavlja kao vrijednost varijable. Walrus operator se može koristiti za promjenu vrijednosti globalne varijable

s

unutar

eval

ili

exec

.

Ako se stave zagrade oko njega, izraz:

(a:=3)

postaje validan

expression

, što je prikazano na slici 13.

 Slika 13 - walrus operator unutar zagrada

Ovo je slučaj u kodu zadatka, jer se oko unosa dodaju zagrade (vidi sliku 14).

 Slika 14 - zagrade oko korisničkog unosa

Kada su zagrade oko unosa, unutar njih mora biti valid

expression

, što

s=0

nije (vidi sliku 15).

 Slika 15 - nevaljajuća sintaksa

Zato rješenje:

Odaberite element borca (Ice, Fire, Acid): s=0
Odaberite borca (Zorn, Krev, Milo)milo

nije moguće.

Ali walrus operator je validan

expression

i može se izvršiti unutar

eval

i

exec

, mijenjajući vrijednost globalne varijable.

 Slika 16 - walrus i eval / exec

Rješenje se može unijeti ovako:

Odaberite element borca (Ice, Fire, Acid): s:=0
Odaberite borca (Zorn, Krev, Milo)exec

Izvršava se prethodno opisani postupak, varijabla

s

postaje 0,

player

ostaje None, te se inicijalizira default borac

Milo("ice")

.

 Slika 21. - rješenje zadatka

Eval / Exec i global scope:

Kada se izvršava u global scopeu,

exec

može promijeniti vrijednost varijable

s

. U local scope funkcije to ne bi bilo moguće.

 Slika 22. - eval unutar functiona

Pri izvršavanju u global scopeu, ovo je moguće.

 Slika 23. - eval unutar global scopea

elemental_fighters.1761921222.txt.gz · Last modified: 2025/12/01 11:40 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki