Dobra, spróbuję to wytłumaczyć.
1)
Cytat:I to jest zdaję się ten fragment:
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk + (20 * attacker.str) / 20
Cały def attack_effect jest odpowiedzialny za efekt końcowy obrażeń, bo później obrażenia są sprawdzane pod innym kątem, takim jak: korekta jeżeli obrażenia = 0, czy są jakieś stany (np. zatrucie) które pogłębiają efekt i czy bohater ma tarczę, czy został użyty unik itd.., nie będę wszystkiego opisywał.
2)
Cytat:I co właściwie robi self.damage? Po co ono jest?
self., czyli własny (dokładniej: Game_Battler).
damage, czyli obrażenia (według słownika).
Czyli
self.damage raczej odnosi się do obrażeń.
Obrażeń własnych, bo w późniejszych linijkach jest coś takiego:
# Substract damage from HP
self.hp -= self.damage
Dokładniej, odejmuje od
self.hp (zdrowia)
self.damage (zadane obrażenia).
3)
Cytat:Nie wiem po co to "0" ani co robi druga linijka kodu. 
To zero może dotyczyć się, czy statusy są brane pod uwagę (0 - nic się nie dzieje).
Ale co do tego trzeciego, nie jestem pewnien.
Ogółem, w tym fragmencie kodu:
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk + (20 * attacker.str) / 20
najpierw oblicza się
atk (atak), a potem obrażenia, żeby nie było że kod wygląda, hm, chaotycznie.
A i jeśli ten tekst jest trochę niespójny, to z góry przepraszam jako najnowszy użytkownik.