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.