Problem mit Kampfskript

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Problem mit Kampfskript

Beitragvon Bamba » Dienstag 31. Oktober 2006, 08:56

Hallo,

ich bin noch ein ziehmlicher Anfänger und habe da gerade ein Problem:

bei einen Skript, dass Kämpfe einfachster Art lösen soll, ist irgendwo ein Fehler. Ich finde ihn nicht. Hier das Skript:

Code: Alles auswählen

def fight():
    while a <= k.Kampfliste1[-1]:
        if k.Kampfliste1==[]:
            del k.Kampfliste1[0:-1]
            del k.Kampfliste3[0:-1]
            break
        else:
            k.Kampfliste1[a]=k.Kampfliste1[a]-k.Kampfliste4[a]
            k.Kampfliste3[a]=k.Kampfliste3[a]-k.Kampfliste2[a]
        if k.Kampfliste1[a] <= 0:
            del k.Kampfliste1[a]
        if k.Kampfliste3[a] <= 0:
            del k.Kampfliste3[a]
        a+=1
        print k.Kampfliste1,k.Kampfliste2,k.Kampfliste3,k.Kampfliste4


in Kampfliste1 sind die LP eines Kämpfers von Team1 gespeichert, in Kampfliste 2 der Schaden eines Kämpfers von Team1. Kampfliste3 und 4 speichern das gleiche nur für TEam 2.

Ich bedanke mich schon mal im vorraus.

Bamba

Edit (Leonidas): Code in Python-Tags gesetzt.
Bamba
BlackJack

Beitragvon BlackJack » Dienstag 31. Oktober 2006, 09:14

Was ist denn das Problem? Zufällig ein `NameError` das `a` oder `k` nicht gefunden werden?

Drück mal in Worten aus was die ``while``-Bedingung prüfen soll und das was sie *jetzt* gerade prüft. Ich habe den Verdacht das ist was anderes.

Wenn man ein Element in einer Liste löscht, dann rücken alle danach einen Listenplatz nach vorne, also wird auch ihr Index um eins kleiner. Falls Du einen `IndexError` bekommst und scheinbar nur jeder zweite Kämpfer berücksichtigt wird, dann solltest Du da mal darüber nachdenken.

Und warum kannst Du den einzelnen Listen nicht gleich vernünftige Namen geben? So muss man immer auf die Ziffer am Ende schauen und nachdenken wofür die eigentlich steht.

Wenn man mehrere Listen auf diese Weise parallel behandelt, dann ist das ein Zeichen das man eigentlich eine Liste haben möchte mit Zusammengesetzten Werten, also in diesem Fall eine Liste mit einem Eintrag pro Kämpfer der LP *und* Schadenspunkte enthält.

Falls ich die Kampfregeln richtig interpretiert habe (ungetestet):

Code: Alles auswählen

class Fighter(object):
    def __init__(self, life, damage):
        self.life = life
        self.damage = damage
   
    def is_dead(self):
        return self.life <= 0


def fight(team_a, team_b):
    while team_a and team_b:
        fighter_a = team_a[0]
        fighter_b = team_b[0]
        fighter_a.life -= fighter_b.damage
        fighter_b.life -= fighter_a.damage
        if fighter_a.is_dead():
            team_a.pop(0)
        if fighter_b.is_dead():
            team_b.pop(0)
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 09:28

Hallo,

ich habe das einfach in diese vier Listen aufgeteilt, warum weiß ich auch nicht. Eigentlich soll es ungefähr so ablaufen: Das Element a der 1. LIste wird um das Element a der 4. Liste verringert, genauso bei der 3. und 2. Liste.

Wenn ich die Funkltion das erste mal laufen lasse, erhalte ich folgende Ausgabe:
[2, 3, 3] [1, 1, 1] [3, 4, 4] [1, 1, 1]
[2, 2, 3] [1, 1, 1] [3, 3, 4] [1, 1, 1]
[2, 2, 2] [1, 1, 1] [3, 3, 3] [1, 1, 1]
Danach:
[1, 2, 2] [1, 1, 1] [2, 3, 3] [1, 1, 1]
[1, 1, 2] [1, 1, 1] [2, 2, 3] [1, 1, 1]
[1, 1, 1] [1, 1, 1] [2, 2, 2] [1, 1, 1] was auch noch richtig ist
aber danach:
[1, 1] [1, 1, 1] [1, 2, 2] [1, 1, 1]
[1] [1, 1, 1] [1, 1, 2] [1, 1, 1]
Hier sollte LIste 1 eigentlich komplett leer sein, während Liste 3 nur noch 1sen haben dürfte.
Und wenn ich dann noch laufen lasse, erhatle ich IndexError: list index out of range. WAs heißt, dass meine if-Abfrage vollkommen falsch ist, aber ich kapier das irgendwie nicht.

Bamba
Bamba
BlackJack

Beitragvon BlackJack » Dienstag 31. Oktober 2006, 10:25

Bamba hat geschrieben:ich habe das einfach in diese vier Listen aufgeteilt, warum weiß ich auch nicht. Eigentlich soll es ungefähr so ablaufen: Das Element a der 1. LIste wird um das Element a der 4. Liste verringert, genauso bei der 3. und 2. Liste.

Wenn ich die Funkltion das erste mal laufen lasse, erhalte ich folgende Ausgabe:
[2, 3, 3] [1, 1, 1] [3, 4, 4] [1, 1, 1]
[2, 2, 3] [1, 1, 1] [3, 3, 4] [1, 1, 1]
[2, 2, 2] [1, 1, 1] [3, 3, 3] [1, 1, 1]


Na dann habe ich schonmal die Kampfregeln falsch interpretiert. :-)

Danach:
[1, 2, 2] [1, 1, 1] [2, 3, 3] [1, 1, 1]
[1, 1, 2] [1, 1, 1] [2, 2, 3] [1, 1, 1]
[1, 1, 1] [1, 1, 1] [2, 2, 2] [1, 1, 1] was auch noch richtig ist
aber danach:
[1, 1] [1, 1, 1] [1, 2, 2] [1, 1, 1]
[1] [1, 1, 1] [1, 1, 2] [1, 1, 1]
Hier sollte LIste 1 eigentlich komplett leer sein, während Liste 3 nur noch 1sen haben dürfte.
Und wenn ich dann noch laufen lasse, erhatle ich IndexError: list index out of range. WAs heißt, dass meine if-Abfrage vollkommen falsch ist, aber ich kapier das irgendwie nicht.


Das sie nicht leer ist liegt daran das Du das letzte Element mit -1 nicht erwischt:

Code: Alles auswählen

In [30]: a = range(5)

In [31]: a
Out[31]: [0, 1, 2, 3, 4]

In [32]: a[0:-1]
Out[32]: [0, 1, 2, 3]

In [33]: del a[0:-1]

In [34]: a
Out[34]: [4]


Wenn Du die Grenzen einfach weglässt, dann wird die gesamte Liste geleert:

Code: Alles auswählen

In [35]: a = range(5)

In [36]: a
Out[36]: [0, 1, 2, 3, 4]

In [37]: del a[:]

In [38]: a
Out[38]: []


Aber kommen wir nochmal auf den Anfang zurück: Was *soll* die ``while``-Bedingung prüfen und was prüft sie in Wirklichkeit?

Und nochmal: wenn Du ein Element in einer Liste löschst, dann rücken alle nachfolgenden eins nach vorne. Wenn Du `a` erhöhst, dann hast Du einen Kämpfer übersprungen, der ja jetzt an die Stelle des verstorbenen getreten ist.

Und was macht Deine Funktion wenn das zweite Team komplett tot ist? Das sieht auch nach `IndexError` aus.

Wenn Du immer den n. Kämpfer aus Team A gegen den n. Kämpfer aus Team B antreten lassen willst, dann ist die sauberste Methode wohl die jeweiligen Partner mit der `zip()` Funktion zu paaren. Diesmal getestet:

Code: Alles auswählen

class Fighter(object):
    def __init__(self, life, damage):
        self.life = life
        self.damage = damage
   
    def __repr__(self):
        return 'Fighter(%r, %r)' % (self.life, self.damage)
   
    def is_dead(self):
        return self.life <= 0


def filter_dead_fighters(fighters):
    return [fighter for fighter in fighters if not fighter.is_dead()]


def fight(team_a, team_b):
    for fighter_a, fighter_b in zip(team_a, team_b):
        fighter_a.life -= fighter_b.damage
        fighter_b.life -= fighter_a.damage
    return map(filter_dead_fighters, (team_a, team_b))


def main():
    team_a = [Fighter(life, damage)
              for (life, damage) in ((2,1), (3, 1), (3, 1))]
    team_b = [Fighter(life, damage)
              for (life, damage) in ((3,1), (4, 1), (4, 1))]
   
    while team_a and team_b:
        print 'A:', team_a
        print 'B:', team_b
        print '-' * 20
        team_a, team_b = fight(team_a, team_b)

    if team_a:
        winner_name = 'A'
        winner_team = team_a
    else:
        winner_name = 'B'
        winner_team = team_b
    print 'Winner is %s: %r' % (winner_name, winner_team)


if __name__ == '__main__':
    main()


Ausgabe ist:

Code: Alles auswählen

A: [Fighter(2, 1), Fighter(3, 1), Fighter(3, 1)]
B: [Fighter(3, 1), Fighter(4, 1), Fighter(4, 1)]
--------------------
A: [Fighter(1, 1), Fighter(2, 1), Fighter(2, 1)]
B: [Fighter(2, 1), Fighter(3, 1), Fighter(3, 1)]
--------------------
A: [Fighter(1, 1), Fighter(1, 1)]
B: [Fighter(1, 1), Fighter(2, 1), Fighter(2, 1)]
--------------------
Winner is B: [Fighter(1, 1), Fighter(2, 1)]
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 10:39

Vielen Dank. ICh werde das gleich ausprobieren.

Bamba
Bamba
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 10:55

VIelen Dank, das funktioniert tadellos! Jedoch stellt sich da ein weiteres Problem auf: Ich habe eine Funktion vorgesehen, in der man sich einen Kämpfer ausbilden kann, dieser wird nach meiner alten Weise an eine LIste angehängt. Und mit einer Funkltion namens verteilen() (falls man sich entschließt ihn in dem Kampf zuschicken) an meine alte Kampfliste angehängt. Wie muss ich den Code jetzt umschreiben, wenn die Funkltion verteilen() aus einer Liste von Kämpfern einen nimmt und ihn an die main() Funktion (siehe oben) anhängt.
Es bringt jetzt nichts den Code zu posten, da er komplett auf den alten Funktionen beruht.
Bamba
Bamba
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 11:38

So, mit

Code: Alles auswählen

def new_fighter():
    k=Fighter(3,1)
    Liste1.append(k)
    print Liste1


wird ein neuer Kämpfer erstellt. Und (wenn man ihn in dem Kampf schicken will) mit

Code: Alles auswählen

def verteilen():
    Wahl=raw_input("Wie viele Kämpfer sollen in den Kampf: ")
    team_b.extend(Liste1[0:Wahl])


in den Kampf geschickt. Warum funktioniert verteilen() nicht und wie kann ich gleichzeitig die in den Kampf geschickten KÄmpfer aus Liste1 löschen?

Vielen Dank

Bamba
Zuletzt geändert von Bamba am Dienstag 31. Oktober 2006, 14:58, insgesamt 2-mal geändert.
Bamba
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 12:31

Hallo noch mal,

ich hab noch ein paar Sachen umgeändert, erhalte aber trotdem Fehler:

verteilen() funktioniert jetzt. Allerdings erhalte ich jetzt bei dem etwas umgeänderten mein() part eine Fehlermeldung:

Code: Alles auswählen

def main():
    while team_a and team_b:
        print 'A:', team_a
        print 'B:', team_b
        print '-' * 20
        team_a, team_b = fight(team_a, team_b)

    if team_a:
        winner_name = 'A'
        winner_team = team_a
    else:
        winner_name = 'B'
        winner_team = team_b
    print 'Winner is %s: %r' % (winner_name, winner_team)

if __name__ == '__main__':
    global team_a
    team_a = [Fighter(life, damage)
              for (life, damage) in ((2,1), (3, 1), (3, 1))]
    global team_b
    team_b = [Fighter(life, damage)
              for (life, damage) in ((3,1), (4, 1), (4, 1))]


Hat jemand eine Ahnung, woran das liegt?

Bamba
Zuletzt geändert von Bamba am Dienstag 31. Oktober 2006, 14:57, insgesamt 2-mal geändert.
Bamba
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

re

Beitragvon keppla » Dienstag 31. Oktober 2006, 12:47

Du hast vergessen, die Fehlermeldung mitzuteilen (und die Pythontags).
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 12:51

UnboundLocalError: local variable 'team_a' referenced before assignment

WAs meinst Du mit Pythontags?

Bamba
Bamba
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Dienstag 31. Oktober 2006, 14:26

mit pythontags meinte ich, dass du, damit der code hier im forum syntaxhighlited und korrekt eingerückt wird, diese BB-tag-geschichte nutzt.

Es ist meist günstiger, wenn du die ganze Fehlermeldung, so mit Traceback und so, angbist, zumindest aber mit der Zeilenzahl.

Die Fehlermeldung bedeutet, dass du lesend auf eine variable zugreifst, die noch nicht existiert. Wenn du die Zeile sagst, kann man da sicher mehr rausfinden.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 31. Oktober 2006, 14:27

Bamba hat geschrieben:WAs meinst Du mit Pythontags?

Die Python-Tags die der Leonidas in deinem ersten Posting hinzugefügt hat, und die du übersehen hast. Du hast vielleicht gemerkt, dass wenn du den Code einfach nur so reinklatscht, die Formatierung weg ist und damit der Programm nicht mehr funktioniert.

Also bitte deine Posts nochmal editieren und Code-Tags hinzufügen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Bamba
User
Beiträge: 62
Registriert: Dienstag 31. Oktober 2006, 08:48

Beitragvon Bamba » Dienstag 31. Oktober 2006, 14:35

Also hier noch mal der Code:

Code: Alles auswählen

class Fighter(object):
    def __init__(self, life, damage):
        self.life = life
        self.damage = damage
   
    def __repr__(self):
        return 'Fighter(%r, %r)' % (self.life, self.damage)
   
    def is_dead(self):
        return self.life <= 0

def nSoldatLevel1():
        k=Fighter(3,1)
        Liste1.append(k)
        print Liste1
        menue()

def verteilen():
    print len(Liste1),"Kaempfer stehen zur Verfuegung"
    Wahl=input("Wahl: ")
    team_b.extend(Liste1[0:Wahl])
           
def filter_dead_fighters(fighters):
    return [fighter for fighter in fighters if not fighter.is_dead()]

def fight(team_a, team_b):
    for fighter_a, fighter_b in zip(team_a, team_b):
        fighter_a.life -= fighter_b.damage
        fighter_b.life -= fighter_a.damage
    return map(filter_dead_fighters, (team_a, team_b))


def main():
    while team_a and team_b:
        print 'A:', team_a
        print 'B:', team_b
        print '-' * 20
        team_a, team_b = fight(team_a, team_b)

    if team_a:
        winner_name = 'A'
        winner_team = team_a
    else:
        winner_name = 'B'
        winner_team = team_b
    print 'Winner is %s: %r' % (winner_name, winner_team)

if __name__ == '__main__':
    global team_a
    team_a = [Fighter(life, damage)
              for (life, damage) in ((2,1), (3, 1), (3, 1))]
    global team_b
    team_b = [Fighter(life, damage)
              for (life, damage) in ((3,1), (4, 1), (4, 1))]
Zuletzt geändert von Bamba am Dienstag 31. Oktober 2006, 14:59, insgesamt 1-mal geändert.
Bamba
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 31. Oktober 2006, 14:42

Leonidas hat geschrieben:Also bitte deine Posts nochmal editieren und Code-Tags hinzufügen.

Nein, ich sag nix mehr -.-
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Dienstag 31. Oktober 2006, 15:08

und jetzt vielleich noch die genaue Fehlermeldung, mit zeile und traceback, und man könnte dir vielleicht sogar helfen.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder