Seite 1 von 1

Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 09:38
von Jankie
Hey,
ich wollte eine Art "Lootbox" machen. Es gibt drei Kategorien: Normal, Selten, Sehr selten. Jede Kategorie soll eine bestimmte Wahrscheinlichkeit haben. Ich glaube numpy.random.choice, allerdings bekomme ich einen Fehler und weiß nicht wieso.

Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "lootbox.py", line 15, in <module>
    gegenstand = choice(gegenstände[choice(list(gegenstände.keys()))], p=wahrscheinlichkeiten.values())
  File "mtrand.pyx", line 1135, in mtrand.RandomState.choice
ValueError: object of too small depth for desired array

Code:

Code: Alles auswählen

from numpy.random import choice

gegenstände = {"Normal":["Lederhelm", "Lederhose", "Lederschuhe"],
               "Selten":["Eisenhelm", "Eisenhose", "Eisenschuhe"],
               "Sehr selten":["Stahlhelm", "Stahlhose", "Stahlschuhe"]}

wahrscheinlichkeiten = {"Normal":0.5,
                        "Selten":0.35,
                        "Sehr selten":0.15}

gegenstand = choice(gegenstände[choice(list(gegenstände.keys()))], p=wahrscheinlichkeiten.values())


print(gegenstand)

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 09:51
von /me
Du hast übersehen, dass du auch aus wahrscheinlichkeiten.values() eine Liste machen musst.

Abgesehen davon hast du dich in deinen Ebenen verlaufen. Du wendest die Wahrscheinlichkeit nicht auf die Schlüssel der Gegenstände ("Normal", "Selten", "Sehr selten") an, sondern auf den ermittelten Wert. Das merkst du spätestens dann, wenn du jeder Liste noch einen Wert hinzufügst. Mach das ganze häppchenweise, dann liest es sich leichter.

Code: Alles auswählen

    from numpy.random import choice

    things = {
        'Normal': ['Lederhelm', 'Lederhose', 'Lederschuhe'],
        'Selten': ['Eisenhelm', 'Eisenhose', 'Eisenschuhe'],
        'Sehr selten': ['Stahlhelm', 'Stahlhose', 'Stahlschuhe']
    }

    probabilities = {
        'Normal': 0.5,
        'Selten': 0.35,
        'Sehr selten': 0.15
    }

    group = choice(list(things.keys()), p=list(probabilities.values()))
    thing = choice(things[group])

    print(thing)
Im Endeffekt würde man wohl auch nur ein Dictionary verwenden um dort sowohl die Wertelisten wie auch die Wahrscheinlichkeiten unterzubringen.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 09:54
von Jankie
Okay, jetzt funktioniert es. Scheint aber so als würden die Wahrscheinlichkeit keinen Einfluss haben.


#edit:

habe es gelöst, hatte die Klammern falsch gesetzt

Code: Alles auswählen

from numpy.random import choice

gegenstände = {"Normal":["Lederhelm", "Lederhose", "Lederschuhe"],
               "Selten":["Eisenhelm", "Eisenhose", "Eisenschuhe"],
               "Sehr selten":["Stahlhelm", "Stahlhose", "Stahlschuhe"]}

wahrscheinlichkeiten = {"Normal":0.6,
                        "Selten":0.3,
                        "Sehr selten":0.1}





gegenstand = choice(gegenstände[choice(list(gegenstände.keys()), p=list(wahrscheinlichkeiten.values()))])


print(gegenstand)

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 10:21
von __blackjack__
Ich finde, zumindest für diesen Ausschnitt, `numpy` eine ziemlich heftige Abhängigkeit, wenn man doch `random.choices()` aus der Standardbibliothek nehmen könnte.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:11
von __deets__
Aber random.choices kann keine relativen Wahrscheinlichkeiten. Das kann man sich natuerlich selbst bauen, aber eine Zeile "pip install numpy" ... ;)

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:19
von __blackjack__
@__deets__: Doch `random.choices()` hat gewichtete Wahrscheinlichkeiten:

Code: Alles auswählen

In [122]: random.choices?
Signature: random.choices(population, weights=None, *, cum_weights=None, k=1)
Docstring:
Return a k sized list of population elements chosen with replacement.

If the relative weights or cumulative weights are not specified,
the selections are made with equal probability.
File:      /usr/lib/python3.6/random.py
Type:      method
Nicht zu verwechseln mit `random.choice()` ohne `s` am Ende.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:25
von Jankie
Habe jetzt die Items mit der Anzahl wie oft man Sie hat in ein dict geladen. Möchte nun aber die Ausgabe nach der Rarität sortieren, also Normal -> Selten -> Sehr selten. Ich weiß, dass ich dafür sorted und einen key brauche, allerdings weiß ich nicht wie ich den key für das sorted machen soll.

Code: Alles auswählen

        for key, value in sorted(inventar_mit_anzahl.items()):
            print(f"{key} {value}")

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:26
von __deets__
Oh, wieder was gelernt. Nett.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:27
von __deets__
@Jankie: die key-Funktion bekommt das Item. Das ist bei dir (key, value). Und sie muss den Wert nach dem sortiert werden soll liefern. Das ist die relative Wahrscheinlichkeit. Die kannst du also nachschlagen mit dem key.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:42
von Jankie
@__deets__:
Sorry aber das verstehe ich nicht so ganz. Kannst du mir bitte ein Beispiel zeigen?

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 11:54
von __deets__

Code: Alles auswählen

sorted(dinge, key=lambda item: probabilities[item[0]])

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Donnerstag 27. Juni 2019, 13:10
von __blackjack__
Wobei man sich eventuell vielleicht noch Gedanken machen möchte nach was als nächstes sortiert werden soll innerhalb der Raritätengruppen, oder ob das egal ist.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Freitag 28. Juni 2019, 06:57
von Jankie
ich bekomme es nicht hin mit

Code: Alles auswählen

        for key, value in sorted(inventar_mit_anzahl.items(), key=lambda item: wahrscheinlichkeiten[item[0]])
            print(f"{key} {value}")


@__blackjack__:

Ist es möglich die Reihenfolge genau so zu machen wie sie in

Code: Alles auswählen

gegenstände = {"Normal":["Lederhelm", "Lederhose", "Lederschuhe"],
               "Selten":["Eisenhelm", "Eisenhose", "Eisenschuhe"],
               "Sehr selten":["Stahlhelm", "Stahlhose", "Stahlschuhe"],
               "Legendär":["Diamanthelm", "Diamanthose", "Diamantschuhe"]}
steht, also dass zu erst der Helm kommt, dann Hose, Schuhe....

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Freitag 28. Juni 2019, 08:17
von __deets__
Es ging BlackJack da denke ich um etwas anderes. Wenn du mehrere items mit der gleichen Rarität hast, wie werden die untereinander sortiert?

So oder so halte ich deinen Ansatz für wenig gelungen. Das ruft nach einer objektorientierten Modellierung, und da ist Rarität eines von vielen Kriterien. Die Wahrscheinlichkeit ist ja eher beim Kauf/Fund relevant.

Und wenn es nicht geht, zeig bitte den gesamten Code und ggf Fehlermeldungen.

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Freitag 28. Juni 2019, 08:33
von Jankie
@__deets__:

Ja das meinte ich auch, also wenn man zum Beispiel nur Ledersachen hat, dass diese dann in der Reihenfolge dargestellt werden, wie sie in der value des dictionarys vorkommen. Das wäre mein Wunsch.

Hier mal der komplette Code:

Code: Alles auswählen

from numpy.random import choice
from collections import defaultdict

gegenstände = {"Normal":["Lederhelm", "Lederhose", "Lederschuhe"],
               "Selten":["Eisenhelm", "Eisenhose", "Eisenschuhe"],
               "Sehr selten":["Stahlhelm", "Stahlhose", "Stahlschuhe"],
               "Legendär":["Diamanthelm", "Diamanthose", "Diamantschuhe"]}

wahrscheinlichkeiten = {"Normal":0.55,
                        "Selten":0.3,
                        "Sehr selten":0.1,
                        "Legendär":0.05}




class Spieler:
    def __init__(self):
        self.inventar = []
        self.guthaben = 10

    def gebe_x_zufällige_items(self,anzahl):
        if self.guthaben > 0 and (self.guthaben - anzahl) >= 0:
            self.guthaben -= anzahl
            for _ in range(0, anzahl):
                gegenstand = choice(gegenstände[choice(list(gegenstände.keys()), p=list(wahrscheinlichkeiten.values()))])
                self.inventar.append(gegenstand)
                print(f"Du öffnest eine Kiste und bekommst {gegenstand}!")
        else:
            print(f"Nicht genug Guthaben, du hast nur {self.guthaben} Guthaben.")

    def zeige_inventar(self):
        inventar_mit_anzahl = defaultdict(int)
        for item in self.inventar:
            inventar_mit_anzahl[item] += 1
        for key, value in sorted(inventar_mit_anzahl.items(), key=item: wahrscheinlichkeiten[item[0]]):
            print(f"{key:<{max(map(len, gegenstände))}}     {value}")


def main():
    spieler = Spieler()
    while True:
        auswahl = int(input("""
Was möchtest du tun?

1 - Kisten öffnen
2 - Inventar anzeigen

>"""))
        if auswahl == 1:
            anzahl_kisten = int(input("Wie viele Kisten willst du öffnen?: "))
            spieler.gebe_x_zufällige_items(anzahl_kisten)
        elif auswahl == 2:
            spieler.zeige_inventar()

main()

und die Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\xxx\Desktop\lootbox.py", line 56, in <module>
    main()
  File "C:\Users\xxx\Desktop\lootbox.py", line 54, in main
    spieler.zeige_inventar()
  File "C:\Users\xxx\Desktop\lootbox.py", line 36, in zeige_inventar
    for key, value in sorted(inventar_mit_anzahl.items(), key=lambda item: wahrs
cheinlichkeiten[item[0]]):
  File "C:\Users\xxx\Desktop\lootbox.py", line 36, in <lambda>
    for key, value in sorted(inventar_mit_anzahl.items(), key=lambda item: wahrs
cheinlichkeiten[item[0]]):
KeyError: 'Lederschuhe'

Hier mal ein Beispiel wie das ganze ca. dargestellt werden soll (nach 100 Kisten geöffnet habe ich folgende Anzahl:

Code: Alles auswählen

Diamanthelm     03
Diamanthose     02
Eisenhelm       09
Eisenhose       11
Eisenschuhe     14
Lederhelm       18
Lederhose       18
Lederschuhe     20
Stahlhelm       01
Stahlhose       01
Stahlschuhe     03

und würde es gerne hinbekommen, dass es am Ende so aussieht:

Code: Alles auswählen

Lederhelm       18
Lederhose       18
Lederschuhe     20
Eisenhelm       09
Eisenhose       11
Eisenschuhe     14
Stahlhelm       01
Stahlhose       01
Stahlschuhe     03
Diamanthelm     03
Diamanthose     02

Re: Item aus Liste ausgeben mit bestimmter Wahrscheinlichkeit

Verfasst: Freitag 28. Juni 2019, 08:37
von __deets__
Das ist genau das was ich ansprach: du sortierst eben nicht loot Boxen, sondern beliebig viel Krempel, der in deinem inventory rumliegt. Und dazu musst du anders vorgehen: du musst im inventory Objekte haben. Die haben eben Rarität als Eigenschaft, und danach kannst du sortieren. Doch sie können und müssen noch viele andere Eigenschaften haben: wie stark schützen denn die Lederschuhe? Welchen attackwert hat ein Schwert? Etc.