Spielereien vom diceman

Heißer Scheiß von übermorgen oder liebenswerte Goldies von vorvorgestern: Alles willkommen!
Antworten
Benutzeravatar
Savior
Beiträge: 13790
Registriert: Do 10. Mai 2012, 03:29
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von Savior » So 20. Sep 2020, 12:18

Bah, Du Ekelhafter!

lel

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » So 20. Sep 2020, 14:54

Clipboard01.jpg

So, es ist mir äußerst schwergefallen, aber es gibt jetzt doch eine jugendfreie Version mit ... Tadaaaa, Früchten!!1! (alle Pics unterliegen der Creative Commons License ). :wave:
Die Highscore-Liste ist implementiert, und für ein bißchen Retro-Appeal gibts sogar simulierte Scanlines und Gaußsches Rauschen. ♥
Würde ich bislang als mein "fertigstes" Projekt bezeichnen, vong polish und griffiges Gamefeel her. :)
[+] Spoiler
Die Bunny-Galerien gibts weiterhin nur auf Anfrage (the way it's meant to be played ... :P )

DOWNLOAD (via Easyupload.io)
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Mo 28. Sep 2020, 01:09

Liebes Tagebuch,

Ich bin weiter dran! Es ist nur so, daß mein Urlaub vorbei ist, und ich wieder meine Freizeit einteilen muß. Ich habe es mir dennoch zur Pflicht gemacht, jeden Tag ein paar Zeilen Code zu schreiben. Ein bißchen Pause habe ich mir dennoch gegönnt, da ich in den vergangenen Wochen derbe viel Meilensteine abgearbeitet habe und ich mich ausgebrannt gefühlt habe (deswegen auch der weiter oben dokumentierte Exkurs, den ich kurzerhand eingeschoben habe :mrgreen: - brauchte das um wieder runterzukommen und meinen Fokus neu zu justieren).

Die Woche Pause hat in soweit gut getan, daß ich einige Features, die ich implementiert habe, nüchtern überdenken konnte. Zum Beispiel hatte ich dem Ritualdolch und der Sense einen Bleed-Effekt, und der Axt und der Alien Energy Coil einen Stun-Effekt beschert - für den Blunderbuss war sogar ein Knockback-Effekt geplant! Leider ist mir bewusst geworden, daß die Effekte spielerisch nicht funktionierten - wenn sie triggerten, waren sie op, und wenn man sie so rar machte, daß sie nur noch selten in Erscheinung traten, fühlte es sich random und unbefriedigend an. Also habe ich die unvermeidliche Konsequenz gezogen, und den entsprechenden Code auskommentiert. Es tat weh, aber ich glaube es war zum besten (im Original KALAWAUM gab es dergleichen überhaupt nicht). Den kreierten Design Space habe ich jedoch beibehalten, vielleicht fällt mir in ferner Zukunft etwas vernünftiges dazu ein.

Ebenfalls rausgeflogen ist das "Covenant"-System. Die Mechaniken im Spiel sind schlicht nicht komplex genug (was ich im Übrigen als Stärke und Alleinstellungsmerkmal betrachte) um ein brauchbares Fundament für ein solches System abzugeben. Jeder Schrein bleibt aber einem bestimmten Gott gewidmet (und die Götter werden auch - wie im Original-KALAWAUM - in jedem Spiel einen zufällig zugeteilten, konstanten Charakter erhalten), nur kann man keinem Orden mehr beitreten. Was ich beibehalten habe, weil ungemein thematisch, ist die Option, daß man an Schreinen gegen einen Obulus einen permanenten Speicherpunkt anlegen kann (a.k.a. Binding Ritual). Die Kosten dafür erhöhen sich bei jeder Nutzung - die Formel hierzu liefert momentan Der Kleine Gauß (muß zugeben, bin großer Fan des Algorithmus :oops: ).

Clipboard45.png
Clipboard46.png

Was man eventuell in den Screenshots sieht (und im Spiel besser wirkt als auf einem Standbild), ist ein optionaler Retro-Effekt, der sich an- und abschalten, sowie in seiner Intensität regulieren lässt - Scanlines und prozedural generiertes Gauß'sches Rauschen, Fuck Yeah! 8-)

Ebenfalls neu (und das bleibt auf jedem Fall drinnen): auf jeder Map gibt es jetzt ZWEI Feuerstellen. Eine der beiden funktioniert wie weiter oben im Post beschrieben, die andere erhöht zwar nicht die Sichtweite, gibt aber einen "Sprint"-Credit (und einen thematischen Text). "Sprints" ist eine Mechanik, die ich mir im Original-Kalawaum öfters gewünscht habe: man startet mit einem Credit, und an jeder entsprechenden Feuerstelle, die man freischaltet (eine pro Map), erhält man einen weiteren Credit. Wenn man einen Sprint aktiviert, pausieren alle Monster für eine Runde, und man kann einen Schritt machen (keinen Angriff!), ohne daß sich Monster danach bewegen. Das hört sich nicht nach viel an, kann einem aber oft genug das Leben retten, wenn man sich in eine Ecke manövriert hat, und man genau weiß, daß man einen Treffer kassieren kann ohne zu sterben, aber man zwei Schritte braucht, um wieder aus der Ecke herauszukommen. Beide Feuerstellen werden prozedural generiert, sind also in jedem Spiel an anderen Stellen zu finden, das erhöht den Exploration Appeal gehörig.

Und dann habe ich angefangen, eine Demo-Modul zu erstellen. Das Original-KALAWAUM hatte sicher um die 50-100 Maps (geschätzt, ich habe es nie durchgespielt), ich peile fürs erste um die 10 Maps an. Dann bekommt man einen guten Eindruck, was das Spiel kann und wie es sich anfühlt.

TO DO LISTE:
- die zwei letzten Monster designen
- die Scaling Routine schreiben, welche den Schwierigkeitsgrad für jede Map bestimmt und kontinuierlich erhöht (das wird die letzte große, große Herausforderung bei dem Projekt, die nicht nur Ausdauer, sondern kiloweise Hirnschmalz abverlangt, aber ich habe bereits Ideen gewälzt und Modul-Tests geschrieben und halte euch auf dem Laufen - ich bin da was ganz Coolem auf der Spur ...)
- Effekte für die Schreine implementieren (essentiell, da Feature im Original-KALAWAUM)
- Modul mit einigen Maps fertigstellen, inklusive Tutorial-Map, die einen intuitiv mit den grundlegenden Mechaniken des Spiels vertraut macht)
- Menü designen (Funktionalität der einzelnen Punkte ist implementiert, was fehlt ist das interaktive und grafische Element)
- Sounds inzufügen (Lizenz für die 8-Bit Roguelike Sounds-Bibliothek von Oryx Design Labs liegt vor 8-) ).
- Testen, testen, testen
- Das Objective designen und coden
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » So 11. Okt 2020, 13:11

UPDATE:

Ich weiß jetzt, was damit gemeint ist, wenn Leute sagen, die letzten 5-10% eines Programmier-Projektes sind die schwierigsten. Der Code wird länger, und immer wieder kommt es vor, daß man eine Funktion hinzufügt, und deren Wechselwirkung mit einem anderen Code-Snippet nicht zuende gedacht hat ... dann heißt es, die Fehlerursache finden, und den Code weiter abstrahieren, um potentielle zukünftige Bug-Hives zu minimieren.
Aber ich bin so weit gekommen wie noch nie zuvor, und ich bleibe dran. Keine Quantensprünge mehr, aber Babysteps - ich befinde mich weiter auf der Zielgeraden!
Gestern im Nachtdienst habe ich das vorletzte Monster fertig gecodet und designt, den Star Spawn: Der Star Spawn ist das stärkste Monster im Spiel, und hat einen Knockback-Effekt. Für den Knockback konnte ich die Mechaniken der Switch-Ability des Nightgaunts verwenden: effektiv ist das ein ferngesteuerter Spieler-Move, nach dem der Spieler sofort wieder am Zug ist. Vorteil dieser Vorgehensweise ist, wie schonmal weiter oben erklärt, daß alle Effekte und Mechaniken eines normalen Spielzuges angewendet werden = emergent complexity: wenn der Spieler vor einem Loch steht und das Monster knockt ihn zurück, stürzt er in die Falle. Ebenso kann das Monster den Spieler aber auch auf ein Feld mit einem Item schubsen, welches dann sofort aufgesammelt wird. Oder der Spieler "bumpt" in ein anderes Monster, welches daraufhin aktiviert wird (und das ursprünglich deaktiviert).

Clipboard47.png
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Di 13. Okt 2020, 20:37

UPDATE:

Uuuuunnd das letzte Monster (von zehn insgesamt) ist fertig! 8-)
Das originale KALAWAUM hatte, glaube ich, acht, und von denen besaß nur der Geist so etwas wie "Persönlichkeit", alle anderen Monster unterschieden sich lediglich in den Base-Stats (Hitpoints und Schadens-Level). Bei mir hat jedes Monster mindestens eine Special-Ability, bzw. einen Trait spendiert bekommen.
Das letzte Monster, der Spectre, verhält sich wie sein Pendant (der Geist) im Original - seine Mechaniken will ich nicht spoilern, da die erste Begegnung mit ihm mit einer Überraschung aufwartet. Sobald man ihn "durchschaut" hat, ist sein Trait aber eher ein Gimmick. Trotzdem ein cooles und thematisches Monster.
Beim Design habe ich mir erlaubt, in Ansätzen den Kultisten zu recyclen ... allerdings wird der Spectre mit Alpha-Map gezeichnet, erscheint also leicht transparent:

Clipboard48.png

Prozedurale Elemente werden nicht länger beim erstmaligen Betreten einer Map berechnet, sondern einmal zu Beginn für ALLE Maps. So kann man sich keine idealen Item/Monster-Konfigurationen mehr "cheesen", indem man einen Speicherstand vor Betreten einer neuen Map anlegt, und dann solange stirbt und respawnt, bis einem die stärkste Waffe quasi vor die Füße gelegt wird. Dabei ist mir aufgefallen, daß das Berechnen einer Map bis zu 250 Millisekunden dauern konnte!
Das hört sich nicht nach viel an, und fällt bei einer einzelnen Map nicht ins Gewicht - bei einem Modul mit 25 Maps müßte man initial allerdings satte 6 Sekunden warten, bis das Spiel komplett initialisiert ist ... das ist zumutbar, aber geht besser, habe ich mir gedacht. Konnte dann auch, nach gründlicher Code-Review und Optimierung, die Zeitspanne auf unter 20 ms (pro Map) drücken! 8-) 8-) :ugeek:

Und ein zeitgemäßes QoL-Feature habe ich implementiert: wenn man eine Feuerstelle wiederholt besucht, und es befindet sich im Umkreis von (#xMax/8)+(#yMax/8) kein Monster, regenerieren die Hitpoints sofort auf maxValue. Da das Rumlaufen und Regenerieren eine zentrale Mechanik des simplen Kampfsystems darstellt, ist die Abfrage ob Monster in der Nähe sind, unbedingt notwendig - aber ansonsten besteht kein Grund, das eher stupide Auffüllen nach einem Kampf NICHT abzukürzen; dank notwendigen Besuch bei einer Feuerstelle bleibt es immerhin ein thematisch motiviertes Feature (fällt allerdings erst auf höheren Leveln wirklich ins Gewicht, wenn die eigenen Hitpoints auf den Wert 100 und drüber steigen).


--> Nächster Schritt:
Das Coden der Scaling-Routine ... davor graut es mir ein wenig, aber auch diese Herausforderung werde ich irgendwie meistern. ;)
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Fr 23. Okt 2020, 13:21

Clipboard50.png

UPDATE:
Die Scaling-Routine ist fertig! :geek: 8-)
Interessiert jemanden, was die Prozedur da oben leistet? Egal, ich erkläre es trotzdem ...
KALAWAUM hatte ein semi-Open World-Design ... nicht was Mechaniken angeht, sondern die Architektur: die Maps waren untereinander verknüpft, man hatte mehrere Optionen, wo man als nächstes hingehen wollte; in der Praxis gab es dann doch einen mehr- oder weniger optimalen Pfad, da die Bereiche dank Level-Scaling gegated waren ... das originale KALWAUM hat es sich recht einfach gemacht: die Map, welche im Editor als erstes erstellt wurde, hatte den Level 1, die zweite Map Level 2, etc. Der Level-Index ist die Blaupause für den PCG-Generator, wie stark ein Monster auf der jeweiligen Map maximal sein darf (es gibt eine min/max-Range). Das bedeutete zugleich, daß man beim Erstellen eines Moduls mit einem Plan vorgehen mußte, daß es stets einen optimalen Pfad durch den Dungeon gab, und sich der Spieler nicht in einem soft dead end wiederfand, da alle Maps um ihn herum mit Level 30+ Monstern bevölkert waren, die ihn onehitten.
Das geht besser, habe ich mir gedacht.
Eine Möglichkeit, die ich initial erwägt habe, war ein drag and drop-System, wo man das Scaling der Maps frei definieren konnte. Das erwies sich jedoch als clunky und umständlich, also war die nächste Überlegung: warum den ganzen Prozess nicht automatisieren? Im besten Falle mit variabler Komponente, so daß bei jedem Neustart andere Wege offenstehen, aber eben immer ein optimaler Pfad; mit geeigneter Ausrüstung ist es später durchaus möglich, auch höher stufige Gebiete zu erkunden, welche sich abseits der optimalen Route befinden - da der Spieler abhängig von Stärke der besiegten Feinde levelt, reguliert sich das System quasi von selbst; also wenn man es schafft, ein besonders starkes Monster früher zu besiegen, öffnen sich einem neue Pfade, während man so in niedrig-stufigen Gebieten weniger bis gar keine Erfahrung mehr erhält.

Die Antwort auf das Problem lieferte der Prim-Algorithmus, welcher bei der Generierung von perfekten Labyrinthen zum Einsatz kommt, und dessen leicht modifizierte Applikation man oben im Screenshot sehen kann:
Die Map, in welcher sich die Startposition befindet, hat automatisch immer den scalingLevel = 0. Für jede Map ist stets abfragbar, wohin globale Links (Übergange zu anderen Maps) führen. Das sind alle Informationen die man braucht!
Zu Beginn wird ein einziges dummy()-Element kreiert, welches den Index der Start-Map kennt. Außerdem wird der Index der Start-Map auf eine sogennante "closed List" gesetzt, das heißt, die Map wurde abgearbeitet und kann nicht mehr für weitere Zielgebiete ausgewählt werden.
Dann beginnt die Hauptschleife: von allen vorhandenen dummy()-Elementen (zu Beginn 1) wird eines zufällig ausgewählt - der Map-Index wird in die closedList eingetragen, und der scalingLevel auf den aktuellen Schleifen-Index gesetzt (wird in jedem Durchgang um 1 erhöht); anschließend werden sämtliche globale Links der ausgewählten Map ausgelesen, und für jeden targetIndex, welche sich noch nicht auf der closedList befindet, wird ein neues dummy()-Element angelegt,
Aktuell bearbeitetes dummy()-Element löschen, Rinse and Repeat.

Bei jedem Neustart eines Moduls gibt es einen anderen optimalen Pfad (backtracking inklusive), der gelernt werden muß. Und damit man überhaupt effektiv aus Fehlern lernen kann, habe ich einen "World Seed" implementiert: Das ist eine kleine, für das aktuelle Modul personalisierte Datei, welche bei erstmaligen Start angelegt wird, und die zuletzt erstellten Scaling-Informationen (sowie die flip/rotation-Orientierung) speichert, und bei jedem Neustart desselben Moduls das Level-Scaling und die flip/rotation-Orientierung wiederherstellt. So hat man trotz prozedural generierter Elemente bei jedem Neustart ein kleines bißchen Deja Vu, und lernt nach und nach, wie man die Welt am besten navigiert - und wenn man will, kann man im Hauptmenü natürlich ein Häkchen setzen ("reroll World Seed", bzw. händisch die worldSeed-Datei löschen) um ein komplett neues Erlebnis zu generieren. :thumbup:
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Mi 4. Nov 2020, 12:57

UPDATE:
Ich war unzufrieden mit der Performance des Star Spawns im Spiel. Die Knockback-Ability ist cool und funktioniert, ist aber spielmechanisch zu antiklimaktisch für ein Boss-Monster. Also back to the drawing board ... jetzt, also ein paar Wochen später, kann der Star Spawn Tentakel beschwören! Tentakel sind effektiv Monster, können sich nicht bewegen, geben keinen Loot, und greifen nur an, wenn der Spieler neben ihnen steht. Tentakel sind nicht besonders stark, aber sie haben jeweils einen Saving Roll, wenn gecheckt wird, ob Waffe (bei Spielerangriff) oder Schild (bei Monsterangriff) zerbrechen. Und sie können überall auf der Map spawnen! Ursprünglich hatte jeder Star Spawn auf einer Map eine Chance nach jedem Spieler-Move ein Tentakel zu beschwören, das war jedoch unmöglich zu balancen, denn wenn sich nur ein Boss auf der Map befand, war die Ability vernachlässigbar, bei 3 Sternengezüchten dagegen wurde die Map regelrecht geflutet. Also habe ich es gestreamlined, daß, solange sich mindestens ein Star Spawn auf der Map befindet, eine baseline Chance von 4.5% besteht, daß ein Tentakel beschworen wird. Und obligatorisch kommt jedesmal, wenn die Map neu betreten wird, ein neues Tentakel hinzu.
Jetzt ist es ein echtes Erfolgerlebnis, wenn man den/die Boss/e endlich gefunden und gelegt hat! :thumbup:

Clipboard51.png

Bug der Woche:
Manchmal wurden Dhole-Monster unsichtbar, nachdem sie sich ein- und wieder ausgebuddelt hatten; ebenso einige Monster, nachdem sie lokale Teleporter nutzten. Schuld war die Animations-Routine, die bei jedem Aufruf checkt, ob das Monster für den Spieler überhaupt sichtbar ist, und so entscheidet, ob sie eine Animation abspielt oder skippt. Einige Animationen haben zwei obligatorische Phasen, z.B. Ein- und Ausbuddeln und Raus- und Rein-Teleportieren. Wenn jetzt ein Monster nach solch einer Exit-Animation an einen Teil der Map teleportiert wurde, der außerhalb des Sichtfeldes lag, wurde der zweite Teil der Animation übersprungen und das Monster blieb unsichtbar - spielerisch nicht relevant, aber natürlich extrem irritierend. War der Übeltäter einmal gefunden war der Fix trivial: einfach zum Ende der Animationsroutine springen, anstatt zurück zum Requester, so daß Standard-Werte der Display-Parameter wieder hergestellt werden konnten.


To-Do-Liste:
- Ein weiteres Monster designen für die momentan brachliegende Knockback-Ability .
- Den initialen Monster-Pool definieren und gemäß Scaling-Routine für jede Map kontinuierlich erweitern - selbstverständlich bekommt man zu Beginn des Spiels KEINEN Boss zu Gesicht. :o
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Do 5. Nov 2020, 01:09

UPDATE:
Abschließend hier das wirklich allerallerletzte Monster, welches ursprünglich nicht geplant war, aber aufgrund des Reworks vom Star Spawns hatte ich Design Space übrig, der genutzt werden wollte. Dies war ausschließlich kreative Arbeit, da der Code für die entsprechende Ability bereits implementiert war.

Clipboard52.png

Der Nether Hound ist ein mittelstarkes Monster mit denselben Stats wie der Nightgaunt, und kann den Spieler zurückstoßen auf eines der drei hinter ihm liegenden Felder (funktioniert auch in diagonaler Richtung!). Der Knockback ist effektiv ein ferngesteuerter Spieler-Move, mit allen zugehörigen Konsequenzen. Also aufpassen beim Angriff, wenn man eine Fallgrube im Rücken hat ... :twisted: Pusht einen der Nether Hound dagegen auf ein Feld mit einem Item, wird dieses aufgesammelt, bzw. ausgerüstet. :wtf:
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » Do 5. Nov 2020, 18:11

Hier nochmal alle Monster in der Übersicht (von oben nach unten):

• Der Spieler (mit Maske, klar!)
• Rat-Thing
• Cultist
• Nether Hound
• Deep One
• Nightgaunt
• Ghoul
• Leng-Spider
• Dhole
• Shoggoth
• Star Spawn
• Tentacle (werden vom Star Spawn beschworen)
• Spectre (wird transparent gezeichnet)


Clipboard53.png
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Benutzeravatar
diceman
Beiträge: 8994
Registriert: Mo 7. Mai 2012, 21:21
Kontaktdaten:

Re: Spielereien vom diceman

Beitrag von diceman » So 8. Nov 2020, 00:09

UPDATE:
• Die Routine fertig gestellt, welche den initialen Monster-Pool definiert und pro Map (über 5 Ebenen lang) kontinuierlich erweitert, bis alle Monster für den Generator bereit stehen. Es gibt etwas Variabilität, aber grundsätzlich will ich einen freundlichen Beginn gestalten und die Monster mit hohen Stats und komplexen Mechaniken allmählich einführen. Und selbstverständlich bekommt man in der Start-Map keinen Boss zu Gesicht ...

• Dies ist erstmal nur der Pool, aus dem der Generator theoretisch schöpfen kann; im nächsten Schritt wird dann für jede Map eine Auswahl von 5 Monstern generiert, mit unterschiedlicher Spawn-Wahrscheinlichkeit ... so bekommt jede Map etwas Charakter.

• Und dann, während ich so in der Lovecraft-Wiki blätterte, fiel mir aufeinmal auf, daß ich gar kein Mi-Go-Monster hatte!!1! :o Das geht natürlich gar nicht, also mußte tatsächlich eine weitere Kreatur her - zum Glück fiel es mir hier leicht, eine thematische Ability zu designen, und der entsprechende Code war schnell geschrieben und funktionierte umgehend.

Mi-Gos sind intelligente, Tech-affine Telepathen, und zumindest im "Arkham Horror"-Brettspiel (von dem ich mir einige subtile Cues ausgeliehen habe) sind sie mit Artefakten und Loot konnotiert. Mi-Gos werden häufig als Hybrid aus Insekt und Krebstier beschrieben und haben fledermausähnliche Schwingen, mit denen sie sich durch das Weltall fortbewegen:

Clipboard55.png

Das soll jetzt wirklich das allerallerallerletzte Monster gewesen sein ... habe, glaube ich, die wichtigsten Archetypen des Mythos vertreten. :thumbup:
"Ja, Junge, da kann man mal sehen, wie schlecht du denken kannst."
• Jean-Luc Picard

Antworten