Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

12.08.2013, 14:31

[Python] Würfelscript - Hilfe

Guten Tag,

ich versuche gerade ein Würfelscript umzusetzen, aber irgendwie fehlt mir der Denkanstoß.

Konzept:

Würfel: Würfelanzahl, Augen

Beispiel:

Würfel: 2, 8 (zwei Würfel mit je 8 Augen)
Eingabe: 2d8
Ausgabe: 8, 8

Würfel: (1)d10 (ein Würfel mit 10 Augen)
Eingabe: d10
Ausgabe: 10

Und nun würde ich die gerne verketten:

Eingabe d10 + 2d8
Ausgabe: 10, 8, 8


Meine Idee:

Erstmal einen Wurf einlesen (2d8) und diesen in einer Liste speichern ['2', 'd', '8'],
nun prüfe ich mittels if-Bedingung, ob dort ein 'd' vorkommt und mit del entferne ich es.
Die bisherige Ausgabe wäre ['2', '8']
Jetzt bin ich aber leider ahnungslos, wie ich aus ['2', '8'] -> 8, 8 mache.

Habt ihr einen Denkanstoß für mich? :)


Gruß

Imperativ

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Imperativ« (12.08.2013, 14:43)


Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

2

12.08.2013, 17:23

Auch wenn ich sonst etwas kreativer bin, stellt sich mir hier die Frage: wofür das Ganze? Was versuchst du damit zu bezwecken? Muss es denn so gemacht werden oder wäre es anders umgesetzt nicht doch etwas besser?
Eine Möglichkeit, die mir auf Anhieb einfallen würde, wären Reguläre Ausdrücke. Du könntest darüber bereits jede Würfeldefinition feststellen und könntest anhand des Ergebnis auch gleich die richtige Augenzahlen ermitteln. Allerdings stellt sich die Frage, warum du 2 8er Würfel und einen 10er Würfel nicht einfach als Auflistung entgegen nimmst ("8 8 10"). Das wäre wesentlich einfacher umzusetzen und für den Benutzer vermutlich auch etwas nachvollziehbarer.
Ich gehe allerdings davon aus, dass es evtl. einen Grund hat, warum du dir das ausgedacht hast, was du umsetzen willst, allerdings kenne ich diesen nicht und kann daher nicht sagen, wie sinnvoll oder unsinnig die bisherige Herangehensweise ist.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

3

12.08.2013, 17:55

Huhu,
es ist eine Aufgabenstellung, an die ich mich halten sollte.
Es so umsetzen, wie ich es beschrieben habe und dann daraus ein Würfelspiel zu machen ist die genaue Aufgabe.
Anders hätte ich es eventuell leichter hinkriegen können, aber
irgendwie beiße ich mir gerade die Zähne daran aus.

Gruß

Imperativ

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

4

12.08.2013, 18:31

Gibt es noch weitere Anforderungen an die Eingabe?
Vielleicht reicht es ja, wenn ich einfach nur ein paar Hinweise gebe:
Du hast bereits das Auswerten der Würfelzahlen und dir fehlt lediglich das Auswerten der +.
Warum versuchst du nicht einfach, die Eingabe so anzupassen, dass du nur noch das machen musst, was du bisher bereits umgesetzt hast?
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Tobiking

1x Rätselkönig

  • Private Nachricht senden

5

12.08.2013, 20:04

Die Würfelnotation ist (besonders bei P&P RPGs) verbreitet: http://en.wikipedia.org/wiki/Dice_notation. Daher kann es schon Sinn machen die so zu verwenden. Über den Begriff "Dice notation" finden man auch massig über Google. Mit Regex könnte z.B. http://stackoverflow.com/questions/12229…otation-parsing helfen.

6

13.08.2013, 00:02

Zunächst solltest du den funktionellen Teil (das Auswürfeln) von der Eingabe (Erzeugen von Würfelfunktionen) trennen. So lassen sich diese seperat testen (z. B. mit dem interaktiven Interpreter).

Ich werfe Dir mal ein paar Codezeilen hin, wie ich die Lösung gestalten würde.

Wie bereits erwähnt, sind regular expressions ein brauchbares Mittel und in diesem Fall auch nicht sonderlich kompliziert.

Angemerkt sei, dass ich mich nicht an das Pattern in dem verlinkten Betrag (Stackoverflow) gehalten habe, sondern der Einfachheit halber lediglich + und - für die Addition verwandt habe.

dice.py

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python3
import random
import re

PATTERN = re.compile(r'(\d+)d(\d+)([+-]\d+)?')

def Dice(count, eyes, addition_func=lambda: 0):
    def func():
        return sum([random.randint(1, eyes) for _ in range(count)]) + \
               addition_func()
    return func

def create_from_string(string):
    count, eyes, addition = [int(e or 0) for e in PATTERN.match(string).groups()]
    # TypeError if something went wrong here
    return Dice(count, eyes, lambda: addition)

Das ganze ließe sich nun so ausführen:

Quellcode

1
2
3
4
5
6
7
>>> import dice
>>> foo = dice.create_from_string("1d6")
>>> foo(), foo(), foo()
(5, 6, 5)
>>> bar = dice.Dice(2, 8, foo)
>>> [bar() for _ in range(5)]
[11, 5, 11, 10, 16]

Zitat

Ich bin nicht der Messias.
Ich sage, du bist es, Herr. Und ich muss es wissen, denn ich bin schon einigen gefolgt.

https://bitbucket.org/bwbg

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »bwbg« (13.08.2013, 01:28)


7

13.08.2013, 08:11

Ich hatte heute eine schlaflose Nacht und daher die Möglichkeit, meinen Gedanken freien Lauf zu lassen ...

Mein obiger Ansatz gefiel mir bereits eine Viertelstunde nach dem Absenden nicht mehr. Ich wollte zumindest eine einfache Form der Modifikatoren implementieren (einfache Grundrechenarten als Suffix)[1]. Es sollten einfache Konstrukte ausgewertet werden können:

Quellcode

1
2
3
4
5
6
1d6
1d6-1
1d8+10
2d8*2
2d10/2
etc.


Der Reguläre Ausdruck

Als erstes definiere ich den Regulären Ausdruck, welcher die oben aufgeführten Würfelbeschreibungen abdecken kann:

Quellcode

1
2
3
PATTERN = re.compile(r'''(\d+) d (\d+)              # count, "d", eyes
                         (?:(\+|-|\*|/?) (\d+))?    # [operator, value]
                     ''', re.X)


Modifikator-Funktionen

Nach dem Werfen der einzelnen Würfel und dem Aufsummieren deren Werte, kann dieses Ergebnis noch modifiziert werden. Dieses wird als Suffix zur Würfelnotation angegeben.
  • 1d6+3 (Zum Gesamtergebnis wird immer 3 hinzuaddiert)
  • 2d8*2 (Das Gesamtergebnis wird immer verdoppelt)
  • 2d6-1 (Vom Gesamtergebnis wird immer 1 subtrahiert)
  • etc.
Um diese Funktionen möglichst "elegant" (subjektiv) zu implementieren, habe ich mich dafür entschieden, diese mittels Funktionen höherer Ordnung zu erzeugen. Dies erlaubt es mir, jede beliebige Funktion als Modifikator zu verwenden, welche genau einen Parameter entgegen nimmt (Würfelwert) und ein (modifiziertes) Ergebnis zurück gibt.

Die vier Grundrechenarten sind wie folgt definiert:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
def Add(summand):
    return lambda a: a + summand

def Sub(subtrahend):
    return lambda a: a - subtrahend

def Mul(factor):
    return lambda a: a * factor
    
def Div(divisor):
    return lambda a: a / divisor


Diese müssen noch mit den jeweiligen Zeichen assoziiert werden, um sinnvoll genutzt werden zu können:

Quellcode

1
2
3
4
5
6
MODIFICATOR_MAPPING = {
    '+': Add,
    '-': Sub,
    '*': Mul,
    '/': Div,
    }


Würfel erzeugen

Die Funktion zum Erzeugen des/der Würfel aus meinem vorangegangenen Beitrag habe ich leicht abgeändert. Die Modifikation wird nun nicht mehr (am Ende) addiert, sondern die Modifikationsfunktion wird, wie beschrieben, mit der Summe der Würfel aufgerufen:

Quellcode

1
2
def Dice(count, eyes, mod=lambda a: a):
    return lambda: mod(sum([random.randint(1, eyes) for _ in range(count)]))


Hilfsfunktionen

Um die Zuvor definierte Notation verwenden zu können, muss aus einer Zeichenkette eine Würfelfunktion erzeugt werden.
Dies erledigt folgende Funktion:

Quellcode

1
2
3
4
5
6
7
8
def create_from_string(string):
    count, eyes, operator, value = PATTERN.match(string).groups()
        # AttributeError if something went wrong here (pattern-mismatch)
    if operator and value:
        return Dice(int(count), int(eyes),
                    MODIFICATOR_MAPPING[operator](int(value)))
    else:
        return Dice(int(count), int(eyes))


Alles zusammen ...

Den vollständigen Quelltext (dice.py) gibts im Pastebin.

Gut zu wissen (Stichworte)

Um das ganze nachvollziehen zu können, solltest Du dich mit folgenden Themen befassen:
Grüße ... bwbg (nach eine halben Kaffeemaschinenladung)

---
[1]: Die Würfelnotation scheint nicht wirklich standardisiert zu sein. Für komplexere Angaben wie 8*1d6-(1d8-1) lohnt es sich m. E. bereits einen eignen Parser nebst Grammatik zu bauen. Darauf habe ich jetzt mal verzichtet, Parserbau ist etwas, womit ich mich noch nicht eingehend beschäftigt habe.

Zitat

Ich bin nicht der Messias.
Ich sage, du bist es, Herr. Und ich muss es wissen, denn ich bin schon einigen gefolgt.

https://bitbucket.org/bwbg

Werbeanzeige