Hey Leute,
ich bin diese Jahr mit meinem ABI fertig geworden und hatte das Verlangen angelehnt an Port Royal ein spiel zu entwickeln. Jedoch mit meinen Vorstellungen. Es gibt schließlich einiges in dem Spiel, was man hätte besser machen können. ^^
Mein aktueller Stand ist, dass ich Spielerdaten und Co. als eine .txt Datei speicher und alles schön retro auf Texteingabe basiert.
> Jetzt kam mir aber der Gedanke, dass es evtl. praktisch sei, wenn man zu speichernde Daten in eine Datenbank speichert. Jedoch blicke ich bei all den DBs nicht durch.
Welche wäre geeignet für eine lokalen gebrauch? -Sqlite und Mysql, welche ich schonmal kenne, fallen meiner Ansicht nach weg-
> Und wegen der Textorientierung rechtfertige ich mich, indem ich einfach mal behaupte, dass später, mit Grafik, die Befehle (bzw. der Eingabetext im Textgame) durchs klicken der Maus in einem bestimmten Quadranten aufgerufen und ausgeführt werden.
In voller ungedult auf eure Antwort
Der Lebkuchen v.v
Spiel-Entwicklungs-Projekt. Angelehnt an PORT ROYAL
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
@TheLebkuchen24: Warum fallen SQLite und MySQL weg? Und was speicherst Du in den Textdateien?
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Momentan sowas hier:
Name: ich
Rang: Kapitaen
Heimatstadt: Start
Schiff: Schaluppe
Matrosen: 60
Hp: 100
Guthaben: 1000
lvl: 0
x_pos: 10
y_pos: 15
-> Aber ich möchte gerne Konvois (Gruppe von Schiffen). Das bedeutet jedoch, dass Ich für jedes einzelne Schiff in dem Konvoi Hp, Manschaft, Kanonen, Munition und Fracht speichern muss. Und da scheinen mir DB weniger Rechenleistung zu saugen.
Name: ich
Rang: Kapitaen
Heimatstadt: Start
Schiff: Schaluppe
Matrosen: 60
Hp: 100
Guthaben: 1000
lvl: 0
x_pos: 10
y_pos: 15
-> Aber ich möchte gerne Konvois (Gruppe von Schiffen). Das bedeutet jedoch, dass Ich für jedes einzelne Schiff in dem Konvoi Hp, Manschaft, Kanonen, Munition und Fracht speichern muss. Und da scheinen mir DB weniger Rechenleistung zu saugen.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich würde das Problem zunächst einmal eher von der Domänenseite her betrachten und Persistenz außen vor lassen. Überlege Dir erst einmal, *wie* Du im Programm solche Sachverhalte modellierst. Daraus ergibt sich dann ggf. auch, wie Du das alles speichern kannst.TheLebkuchen24 hat geschrieben: -> Aber ich möchte gerne Konvois (Gruppe von Schiffen). Das bedeutet jedoch, dass Ich für jedes einzelne Schiff in dem Konvoi Hp, Manschaft, Kanonen, Munition und Fracht speichern muss. Und da scheinen mir DB weniger Rechenleistung zu saugen.
Wenn Du sowieso alles im RAM halten kannst, brauchst Du evtl. gar keine Datenbank, sondern kannst alles in gängige Textformate wie JSON oder XML serialisieren.
So ein selbst definiertes Textformat ist aber auf jeden Fall keine gute Idee
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@TheLebkuchen24: Ich weiss nicht ob Rechenleistung hier das vorrangige Thema ist. Als erstes könnte man mal überlegen auf ein Standardformat wie JSON für die Textdateien umzusteigen. Dann hast Du auch gleich die Möglichkeit komplexer strukturiertere Daten als nur nur ”flache” Schlüssel/Wert-Paare zu speichern.
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Was ist denn diese JSON ?
JSONTheLebkuchen24 hat geschrieben:Was ist denn diese JSON ?
In der Standardbibliothek findest du ein passendes Modul für JSON.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hast Du denn überhaupt schon den Großteil der Domänenlogik implementiert oder modelliert? Also gibt es den "Konvoi" schon im Code? Daraus ergibt sich imho dann auch die Umsetzung in der Persistenz, die sich dann ggf. leicht über ein Mapping machen ließe, was BlackJack schon beschrieben hat.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ich vermute, dass es noch nicht mal schriftliche Anforderungen gibt. Ich brauche jetzt nicht unbedingt in UML modellierte Diagramme, aber ein gewisses Konzept sollte man zumindest in Textform niederlegen.Hyperion hat geschrieben:Hast Du denn überhaupt schon den Großteil der Domänenlogik implementiert oder modelliert?
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Joah ... öhm ... bisher habe ich mir das so vorgestellt:
- Konvoi (es soll später mehr als nur einen geben)
> Schifftyp (können mehrfach vorkommen)
Jeder Schifftyp soll Richtwerte haben. Damit nicht zu viel Ladung auf dem Schifftyp ist und es praktisch untergehen müsste.
> Fracht, welche auf die einzelnen Schifftypen per Hand aufgeteilt werden kann. (weiß aber noch nicht, was für Frachtgüter es geben wird)
Anzumerken hierbei ist, dass die Schiffe auch Schaden nehmen, die Matrosen in Schlachten sterben, Fracht ein und ausgeladen wird und und und....
Ich hoffe man versteht so langsam, was ich vorhabe ;D
Jetzt weiß ich halt nicht, wie flexibel diese Textdateien sind.
- Konvoi (es soll später mehr als nur einen geben)
> Schifftyp (können mehrfach vorkommen)
Jeder Schifftyp soll Richtwerte haben. Damit nicht zu viel Ladung auf dem Schifftyp ist und es praktisch untergehen müsste.
> Fracht, welche auf die einzelnen Schifftypen per Hand aufgeteilt werden kann. (weiß aber noch nicht, was für Frachtgüter es geben wird)
Anzumerken hierbei ist, dass die Schiffe auch Schaden nehmen, die Matrosen in Schlachten sterben, Fracht ein und ausgeladen wird und und und....
Ich hoffe man versteht so langsam, was ich vorhabe ;D
Jetzt weiß ich halt nicht, wie flexibel diese Textdateien sind.
@TheLebkuchen24: Wir verstehen schon, was Du vorhast. Du mußt Dir aber zuerst klar werden, was Du brauchst. Zum Speichern gibt es JSON, Pickle, SQlite, um nur ein paar zu nennen. Wenn man Serialisierung und Spielelogik kapselt, spielt das Format ja auch nur eine untergeordnete Rolle. Jetzt mußt Du erst einmal Spielzustände und Spielaktionen definieren.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Vergiss doch mal die Textdateien (davon abgesehen ist JSON sehr flexibel, also keine Angst!).TheLebkuchen24 hat geschrieben: Jetzt weiß ich halt nicht, wie flexibel diese Textdateien sind.
Fang erst einmal an, das ganze in Python zu entwickeln. Überlege Dir, wie Du die gerade formulierten Anforderungen umsetzen könntest.
Ich sehe da Dinge wie Fracht und Schiffe, um bei den beiden Basiselementen zu bleiben. Was muss denn ein Frachtgut haben? Ich könnte mir vorstellen, dass man anhand des Namens die Klassifizierung machen möchte, also "Bananen", "Zucker", "Rum", usw. Zudem hat jedes Gut pro Einheit ein Gewicht. Ich würde der Einfachheit halber nur ganze Einheiten zulassen. Das Gewicht würde ich fest definieren; da bei Schiffen in Tonnen gemessen wird, könnte man das als Basis nehmen, Kilogramm o.ä. wären natürlich auch möglich. Für mich wäre das einfach nur ein netter Buchstabe, aber ohne inhaltliche Bedeutung (also z.B. keinerlei Umrechnungen!). Man kann sich natürlich noch Gedanken machen, ob man verschiedene Einheiten irgend wie modellieren will? Iirc gab es dazu eine nette Python-Lib. Nun kommt schon das erste Problem: Entspricht eine Ware einem Frachtgut? Oder will man eine "Fracht" als zusätzliche Abstraktion, die ggf. die Menge beinhaltet. Ich würde wohl zunächst vom einfachen Fall ausgehen und Fracht == Ware == Gut setzen und das erst einmal versuchen in simplen Code zu gießen:
Code: Alles auswählen
class Product:
def __init__(self, name, weight = 0):
self.name = name
self.weight = weight
def __str__(self):
return "{}: {}t".format(self.name, self.weight)
Aber man kann damit schon spielen:
Code: Alles auswählen
banane = Product("Bananen", .1)
zucker = Product("Zucker", .01)
# simples Lager als Dictionary
stock = {zucker: 200, banane: 50}
for product, amount in stock.items():
print("{}t {}".format(amount * product.weight, product.name))
> 5.0t Bananen
> 2.0t Zucker
Ein Schiff muss eine Art Typ haben, den man einfach über einen String abbilden könnte. Dazu kommt noch eine maximale Kapazität an Gewicht. Ein Schiff muss irgend wie Fracht beladen und entladen können.
Wie könnte man das machen? Was passiert, wenn zu viel beladen oder entladen wird? Wie kann man elegant auf verschiedene Güter an Bord zugreifen? (Also etwa 20 Einheiten "Bananen" entladen, aber nichts vom "Zucker")
Du siehst, da gibt es eine Menge Dinge, die total unabhängig von der späteren Darstellung der Daten in einer Datei oder Datenbank sind
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
return "{}: {}t".format(self.name, self.weight)
was hat das mit den {} / {}t und der Methode format() auf sich? Sowas ist mir bisher noch nicht begegnet.
was hat das mit den {} / {}t und der Methode format() auf sich? Sowas ist mir bisher noch nicht begegnet.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Öffne eine Python-Shell und probiere es ausTheLebkuchen24 hat geschrieben:return "{}: {}t".format(self.name, self.weight)
was hat das mit den {} / {}t und der Methode format() auf sich? Sowas ist mir bisher noch nicht begegnet.
Oder lies es nach: Link zur Doku
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Deiner Idee einfach mal in meinen Augen provisorisch loszulegen hat mir gut gefallen. Somit kann ich erstmal weitermachen, obwohl ich das Gefühl habe, dass ich es später bereuen werde. Ist nur so ein Gefühl
@Hyperion: Deine Klasse habe ich etwas modifiziert. Denn ich habe mich entschieden, dass man von allem jeweils nur Tonnen kaufen kann. Deshlab musste dann das Attribut wert her. Aber ist es essenziel Quellcode auf englisch zu schreiben? Ich habe mich für die Deutschsprachigkeit im Code entschieden.
Passend dazu habe ich gleich mal eine Klasse Lager entwickelt.
Was ich bei mir etwas unglücklich finde ist die Tatsache, dass ich in der Klasse die Produktsparte initialisiere und deklariere. Aber als provisorieum gefällt mir die Klasse Lager schon ganz gut.
@Hyperion: Und du hast Recht. Schon jetzt kann man damit rumalbern ^^
Bei den Schiffen muss ich noch überlegen, wie man das provisorisch umsetzen kann.
-> Und schonmal vielen Dank für die ganze Hilfe. Ich hätte nie gedacht so schnell schon Rückmeldung zu bekommen!
@Hyperion: Deine Klasse habe ich etwas modifiziert. Denn ich habe mich entschieden, dass man von allem jeweils nur Tonnen kaufen kann. Deshlab musste dann das Attribut wert her. Aber ist es essenziel Quellcode auf englisch zu schreiben? Ich habe mich für die Deutschsprachigkeit im Code entschieden.
Code: Alles auswählen
class Produkt():
def __init__(self, name, wert):
self.name = name
self.gewicht = 1
self.wert = wert
def __str__(self):
return '{}t {} cost {}$'.format(self.gewicht, self.name, self.wert)
Code: Alles auswählen
class Lager():
def __init__(self):
self.lager = {}
self.produkte = [Produkt('Zucker', 20),
Produkt('Brot', 10),
Produkt('Getreide', 5)]
def einladen(self, name, menge):
if name in self.lager:
self.lager[name] = self.lager.get(name) + menge
else:
for produkt in self.produkte:
if name == produkt.name:
self.lager[produkt.name] = menge
def ausladen(self, name, menge):
if name in self.lager:
lagerBestand = self.lager.get(name)
if menge > lagerBestand:
print('Du hast vom Produkt "{}" nur {}t'.format(name, lagerBestand))
elif menge == lagerBestand:
del self.lager[name]
else:
self.lager[name] = self.lager.get(name) - menge
@Hyperion: Und du hast Recht. Schon jetzt kann man damit rumalbern ^^
Code: Alles auswählen
l = Lager()
l.einladen('Zucker', 10)
l.einladen('Brot', 15)
l.lager
> {'Zucker': 10, 'Brot': 15}
l.ausladen('Brot', 15)
l.lager
> {'Zucker': 10}
-> Und schonmal vielen Dank für die ganze Hilfe. Ich hätte nie gedacht so schnell schon Rückmeldung zu bekommen!
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hallo,
das Attribut "wert" habe ich jetzt nicht verstanden!
Man muss seinen Code nicht in Englisch schreiben; viele bevorzugen das, weil Englisch eben die Sprache beim Programmieren ist. D.h. Python selber hat englische Schlüsselwörter (``for``, ``while`` usw.) und auch viele Namen von Typen und Funktionen sind Englisch (``list.append``) usw. Bei allen fremden Libs wirst Du auch eher Englisch finden. Insofern kommt es früher oder später dann zu einer Mischung bei Dir im lokalen Quellcode. Und Englisch lesen können musst Du ja beim Programmieren so oder so
Ich würde Dir ans Herz legen, Dich mal mit Unit Tests auseinander zu setzen! Gerade in der Phase, in der Du jetzt bist, kannst Du alle diesen Domänen-Objekte und Funktionen prima automatisiert testen. Damit fällt es Dir leichter, Änderungen am Code vorzunehmen.
``print`` solltest Du immer von der eigentlichen Logik trennen. Wenn jemand mehr "ausladen" will, als er auf Lager hat, dann wirf eine Exception - diese kannst Du dann dort verarbeiten (z.B. durch eine Meldung), wo Du sie aufrufst.
Ich würde die Initialisierungen mit konkreten Produkten im Lager wegnehmen! Schreibe Dir eine Factory-Funktion, die Dir ein Lager mit den drei vorgesehenen Produkten generiert, also in etwa so:
Deinem "Lager" fehlt aber noch Kapselung! Aktuell muss ich auf das *interne* Attribut ``produkte`` zugreifen; das sollte man imho hinter Methoden verstecken, mit denen man Produkte hinzufügen oder entfernen kann. (LoD)
Richtig glücklich finde ich die Aufteilung aber noch nicht. Was bringt Dir die Liste ``Lager.produkte`` eigentlich? eigentlich reicht doch ein Mapping, welches ein vorhandenes Produkt (ggf. reicht der Name!) auf die im Lager definierte Menge abbildet...
Wie Du siehst, kann und muss man da eine Menge überlegen...
Aber es ist gut, dass Du mit einer Shell gleich mit Deiner API "herumspielst". Damit - und mit Unit Tests - bekommst Du ein Gefühl dafür, ob Deine API sich "gut" anfühlt oder noch etwas fehlt oder umständlich gelöst ist. Beides ist imho sehr wichtig und es ist schade, dass man User sich dem gegenüber so verschließt
das Attribut "wert" habe ich jetzt nicht verstanden!
Man muss seinen Code nicht in Englisch schreiben; viele bevorzugen das, weil Englisch eben die Sprache beim Programmieren ist. D.h. Python selber hat englische Schlüsselwörter (``for``, ``while`` usw.) und auch viele Namen von Typen und Funktionen sind Englisch (``list.append``) usw. Bei allen fremden Libs wirst Du auch eher Englisch finden. Insofern kommt es früher oder später dann zu einer Mischung bei Dir im lokalen Quellcode. Und Englisch lesen können musst Du ja beim Programmieren so oder so
Ich würde Dir ans Herz legen, Dich mal mit Unit Tests auseinander zu setzen! Gerade in der Phase, in der Du jetzt bist, kannst Du alle diesen Domänen-Objekte und Funktionen prima automatisiert testen. Damit fällt es Dir leichter, Änderungen am Code vorzunehmen.
``print`` solltest Du immer von der eigentlichen Logik trennen. Wenn jemand mehr "ausladen" will, als er auf Lager hat, dann wirf eine Exception - diese kannst Du dann dort verarbeiten (z.B. durch eine Meldung), wo Du sie aufrufst.
Ich würde die Initialisierungen mit konkreten Produkten im Lager wegnehmen! Schreibe Dir eine Factory-Funktion, die Dir ein Lager mit den drei vorgesehenen Produkten generiert, also in etwa so:
Code: Alles auswählen
def generate_stock():
stock = Stock()
stock.produkte.append(Produkt('Zucker', 20))
stock.produkte.append(Produkt('Brot', 10))
# ...
return stock
Richtig glücklich finde ich die Aufteilung aber noch nicht. Was bringt Dir die Liste ``Lager.produkte`` eigentlich? eigentlich reicht doch ein Mapping, welches ein vorhandenes Produkt (ggf. reicht der Name!) auf die im Lager definierte Menge abbildet...
Wie Du siehst, kann und muss man da eine Menge überlegen...
Aber es ist gut, dass Du mit einer Shell gleich mit Deiner API "herumspielst". Damit - und mit Unit Tests - bekommst Du ein Gefühl dafür, ob Deine API sich "gut" anfühlt oder noch etwas fehlt oder umständlich gelöst ist. Beides ist imho sehr wichtig und es ist schade, dass man User sich dem gegenüber so verschließt
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Das Attribut 'wert' ist deshlab drinnen, das jede Stadt unterschiedliche Preise zahlt und verlangt für Produkte.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Jetzt koppelst Du aber den Wert *direkt* an ein Produkt. Damit wären ja "Bananen" in zwei Städten (oder bei zwei Anbietern) zwei unterschiedliche Produkte...TheLebkuchen24 hat geschrieben:Das Attribut 'wert' ist deshlab drinnen, das jede Stadt unterschiedliche Preise zahlt und verlangt für Produkte.
Ich würde das Produkt als solches wirklich nur auf "global" gültigen Größen beschränken.
Alles variable sollte in einer separaten Struktur vorrätig sein.
Vielleicht kannst Du das über einen neuen Typen "Artikel" lösen, der eben aus einem Produkt und einem Preis besteht. Ein Händler / Markt oder der Spieler selber besitzt dann nicht eine Menge an Produkten, sondern eine Menge aus Artikeln, die sich bezüglich des Preises unterscheiden, aber bezüglich des Produktes identisch sind.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
-
- User
- Beiträge: 17
- Registriert: Sonntag 18. Mai 2014, 14:27
- Kontaktdaten:
Evtl. habe ich doch kein Talent oder man "installiert" es auf solch eine abwägige Weise, wie sie nur lang Eingesessene noch kennen. Und die Installationsanleitung ist eher knapp und für mich nichtssagend. Hilfe! :KHyperion hat geschrieben:Ich würde Dir ans Herz legen, Dich mal mit Unit Tests auseinander zu setzen!