{"id":7207,"date":"2016-02-01T07:00:23","date_gmt":"2016-02-01T06:00:23","guid":{"rendered":"https:\/\/www.herr-rau.de\/wordpress\/?p=7207"},"modified":"2023-06-12T10:16:15","modified_gmt":"2023-06-12T08:16:15","slug":"sunless-sea-fortsetzung","status":"publish","type":"post","link":"https:\/\/www.herr-rau.de\/wordpress\/2016\/02\/sunless-sea-fortsetzung.htm","title":{"rendered":"Modulares Geschichtenerz\u00e4hlen in Java, Fortsetzung"},"content":{"rendered":"<div style='text-align:right;'><small>(<a href='https:\/\/www.herr-rau.de\/wordpress\/2016\/02\/sunless-sea-fortsetzung.htm#comments'>20 Kommentare.<\/a>)<\/small> <\/div>\n<p class=\"wp-block-paragraph\">(<a href=\"https:\/\/www.herr-rau.de\/wordpress\/2016\/01\/was-ich-gerade-spiele-und-warum-sunless-sea.htm\">Fortsetzung von hier, wo ich Sunless Sea beschrieben habe.<\/a> In der ersten H\u00e4lfte geht&#8217;s ums Prinzip, in der zweiten wird es dann immer technischer.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das modulare Prinzip, nach dem in eine bestehende Spielwelt kleine Missionen oder Geschichten eingebaut werden, w\u00fcrde ich gerne f\u00fcr ein Programmierprojekt in der Schule nutzen. Dazu erschafft man gemeinsam eine Fantasy-Welt oder nimmt eine von mir vorgegebene. Die Welt besteht aus vielen Orten, zwischen denen man reisen kann, modelliert als Graph. Jeder Ort hat einen Namen und eine sch\u00f6n geschriebene Beschreibung, jede Verbindung eine Distanz, sp\u00e4ter k\u00f6nnen dann gerne noch andere Attribute dazu kommen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Au\u00dferdem sollen Sch\u00fclerinnen und Sch\u00fcler so einfach wie n\u00f6tig Geschichten schreiben k\u00f6nnen, die in dieser Welt spielen. Wenn man dann eine Klasse von 30 Sch\u00fclern hat, kriegt man sicher ein Dutzend Geschichten, die man in die Welt setzen kann, und nach und nach k\u00f6nnen es auch mehr und kompliziertere werden. Aber f\u00fcr den Anfang reichen einfache.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Letztlich ist das auch nichts anderes als das, was man vielleicht mit einem Leveleditor macht, um neue Levels f\u00fcr ein bestehendes Spiel zu erstellen. Aber hier finde ich das einfacher (und als Sprachlehrer reizvoller) dadurch, dass die geschichten vor allem aus Text bestehen und nicht aus der Platzierung von Mauern, Schatzkisten, Waffen, Monstern. Das macht das Programmieren leichter, glaube ich, und erfordert aber mehr kreatives Schreiben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Schauen wir uns dazu die im letzten Blogeintrag erw\u00e4hnte Geschichte von Mr Sacks an, dem dunklen Weihnachtsmann. &#8222;The Crimson Beast of Winter stirs in your hold&#8230;&#8220; <a href=\"http:\/\/www.richardcobbett.com\/codex\/sunless-sea-and-me-christmastide\/\">In seinem Blog stellt<\/a> der Autor der Geschichte, Richard Cobbett, sie kurz vor. (<a href=\"http:\/\/www.failbettergames.com\/welcome-to-the-empire-of-hands\/\">Hier schreibt er zur von ihm geschriebenen Affeninsel.<\/a> Und, auch interessant, <a href=\"http:\/\/www.failbettergames.com\/fallen-london-writer-guidelines-part-i\/\">hier die Writer Guidelines, <\/a>nach denen die verschiedenen Autoren Geschichten f\u00fcr die Welt von <em>Sunless Sea<\/em> schreiben.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">(Es folgen Spoiler, sollte klar sein.)<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Sobald man am Nordpol-\u00c4quivalent gewesen ist, wird bei der n\u00e4chsten Ankunft in London die Geschichte ausgel\u00f6st<\/li>\n\n\n\n<li>In London macht Mr Sacks einem ein Angebot: Man muss ihn der Reihe nach an drei Orte seiner Wahl bringen. Danach werde man belohnt, es sei aber nicht ungef\u00e4hrlich. Dazu sch\u00f6ne, kurze Prosa \u00fcber ihn als \u00fcbernat\u00fcrliche Schreckensgestalt, der Geschenke einfordert und \u00dcbel hinterl\u00e4sst. Ein einzelner Reiter der Apokalypse sozusagen.<\/li>\n\n\n\n<li>Das Angebot kann man annehmen oder nicht oder die Entscheidung vertagen.<\/li>\n\n\n\n<li>Nimmt man es an, erf\u00e4hrt man das erste Ziel. Genauer gesagt: Man hat die Wahl zwischen zwei Zielen.<\/li>\n\n\n\n<li>Bringt man Mr Sacks zu einem der beiden Orte, kann man ihn seine Geschenke dort abladen lassen oder nicht oder die Entscheidung vertagen.<\/li>\n\n\n\n<li>F\u00fchrt er seine b\u00f6se Tat aus, gibt es wieder etwas Prosa, und man erf\u00e4hrt das n\u00e4chste Ziel beziehungsweise die n\u00e4chsten zwei Zielm\u00f6glichkeiten.<\/li>\n\n\n\n<li>Bringt man Mr Sacks zu einem der beiden Orte, kann man ihn seine Geschenke dort abladen lassen oder nicht oder die Entscheidung vertagen.<\/li>\n\n\n\n<li>F\u00fchrt er seine b\u00f6se Tat aus, gibt es wieder etwas Prosa, und man erf\u00e4hrt das letzte Ziel: den Nordpol, wo man ihm bei einem Ritual helfen soll.<\/li>\n\n\n\n<li>Auf dem Weg dorthin, auf See, erh\u00e4lt man eine Nachricht vom Ministerium und eine Fl\u00fcssigkeit, mit der man das Ritual sabotieren kann.<\/li>\n\n\n\n<li>Bringt man Mr Sacks zum Nordpol, hat man die Option, ihn sein Ritual ausf\u00fchren zu lassen oder es zu sabotieren. In einem der beiden F\u00e4lle wird eine neue Geschichte ausgel\u00f6st.<\/li>\n\n\n\n<li>Beim n\u00e4chsten Besuch in London wartet ein Geschenk von Mr Sacks auf einen. (Eventuell abh\u00e4ngig vom Verhalten zuvor? Das wei\u00df ich nicht, ich habe ja nicht alle Varianten durchgespielt.)<\/li>\n\n\n\n<li>Au\u00dferdem: W\u00e4hrend dieser Mission erh\u00e4lt man, mehr oder weniger zuf\u00e4llig oder zeitabh\u00e4ngig, jedenfalls nicht bewusst vom Spieler ausgel\u00f6st, drei Besuche vom ungeduldiger werdenden Mr Sacks. Die ersten beiden Mal kann man ihn hinhalten, das dritte Mal nicht.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Geschichte riecht nach der Modellierung mit einem Zustandsdiagramm. Warum? Weil es mir sinnvoll erscheint, weil Zustandsdiagramme und deren Umsetzung im Lehrplan f\u00fcr 10 und 12 stehen, und weil ich gar so viele andere Modellierungsm\u00f6glichkeiten \u00fcberhaupt nicht kenne.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Der nackte Zustandsautomat<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein erstes Diagramm zur Modellierung der Situation oben k\u00f6nnnte so aussehen:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende.jpg\" rel=\"attachment wp-att-7222\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"401\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende-700x401.jpg\" alt=\"sunless_sea_zustaende\" class=\"wp-image-7222\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende-700x401.jpg 700w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende-150x86.jpg 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende-300x172.jpg 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_sea_zustaende.jpg 1600w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Die Bedeutung der Zust\u00e4nde:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Z0: Die Geschichte beginnt, der Auftrag steht im Raum. Man hat die Wahl, ob man ihn annimmt, ablehnt oder erst mal abwartet. Wenn man abwartet, passiert nichts; wenn man ablehnt, landet man im Zustand Z5, wenn man annimmt, in Zustand Z1.<\/li>\n\n\n\n<li>Z1: Man hat den Auftrag angenommen, aber noch nichts erf\u00fcllt. Man hat die Wahl, Mr Sacks und seine Geschenke in Ziel 1 abzuliefern oder nicht. Man hat, weil das so sein soll ist, nicht mehr die M\u00f6glichkeit, aus dem Gesch\u00e4ft auszusteigen und in Zustand Z5 zu kommen.<\/li>\n\n\n\n<li>Z2: Man hat das erste Ziel bereits erreicht, das zweite noch nicht, und hat die Wahl, Mr Sacks in Ziel 2 abzuliefern oder (erst mal) noch nicht.<\/li>\n\n\n\n<li>Z3: Man hat das zweite Ziel bereits erreicht, den Nordpol noch nicht, und hat die Wahl, Mr Sacks am Nordpol einfach abzuliefern (dann ist man in Zustand Z4) oder sein Vorhaben dort zu sabotieren (dann ist man in Zustand Z5).<\/li>\n\n\n\n<li>Z4: Man hat Mr Sacks wunschgem\u00e4\u00df abgeliefert, aber seine Belohnung &#8211; von der man noch nichts wei\u00df &#8211; noch nicht in London abgeholt. Sobald man das tut, landet man in Zustand Z5.<\/li>\n\n\n\n<li>Z5: Die Geschichte ist beendet und wird nicht mehr angezeigt. Es gibt drei M\u00f6glichkeiten, wie man in diesen Zustand gelangt.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Die Bedeutung der Zustands\u00fcberg\u00e4nge:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Von den meisten Zust\u00e4nden aus kann man in andere Zust\u00e4nde \u00fcbergehen, abh\u00e4ngig von ausl\u00f6senden Aktionen. Ich habe die Aktionen hier &#8222;annehmen, abwarten, ablehnen&#8220; und so weiter genannt.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Die schwarzen Angaben sind ausgel\u00f6ste Aktionen, die bei dem Zustands\u00fcbergang zus\u00e4tzlich oder nebenbei ausgef\u00fchrt werden:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>So soll die Furcht des Spielers um 5 steigen, wenn man den Auftrag annimmt, und wenn man den ersten Schritt ausf\u00fchrt.<\/li>\n\n\n\n<li>Die Furcht des Spielers um 10 steigen, wenn man den Auftrag ablehnt, und wenn man den zweiten Schritt ausf\u00fchrt.<\/li>\n\n\n\n<li>Die Furcht soll um 10 sinken, wenn man Mr Sacks sabotiert hat, und um 20 sinken, wenn man ihn nicht sabotiert hat.<\/li>\n\n\n\n<li>Wenn man seine Belohnung in London abholt, erh\u00e4lt man 20 Geld.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Anmerkungen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Die ausgel\u00f6sten Aktionen k\u00f6nnen wesentlich komplexer sein, die Werte\u00e4nderung ist nur ein Beispiel.<\/li>\n\n\n\n<li>Mein erster Versuch hatte \u00fcbrigens zwei Zust\u00e4nde mehr, bis ich merkte, dass es ja nur einen einzigen Endzustand braucht, egal wie man dorthin kommt.<\/li>\n\n\n\n<li>Au\u00dferdem kann man in so ein Diagramm auch noch Bedingungen einf\u00fcgen, die bei einem versuchten Zustands\u00fcbergang erf\u00fcllt sein m\u00fcssen. Dass man irgend etwas Bestimmtes mit sich f\u00fchrt, vielleicht. Die habe ich der Einfachheit halber weggelassen.<\/li>\n\n\n\n<li>Und was ist mit den drei Erscheinungen von Mr Sacks, mit der letzten, t\u00f6dlichen? Die habe ich vorerst auch weggelassen. Weglassen ist oft eine gute Idee. Aber ich w\u00fcrde sie ohnehin nicht mit einem Zustandsautomaten umsetzen. Man br\u00e4uchte dann n\u00e4mlich Z1 in zwei Varianten, also Zust\u00e4nden, f\u00fcr erste und zweite Warnung, und Z2 und Z3 ebenso, und vielleicht einen letzten Zustand f\u00fcr die dritte Warnung. Das w\u00e4re mir zu umst\u00e4ndlich, stattdessen w\u00fcrde ich ein Attribut &#8222;Mr Sacks Ungeduld&#8220; einf\u00fchren und das nach und nach erh\u00f6hen (ausgel\u00f6st von einem Timer?) und unabh\u00e4ngig von den anderen Zust\u00e4nden etwas bewirken lassen. Aber erst mal weglassen.<\/li>\n\n\n\n<li>Auch der Sabotageauftrag des Ministeriums fehlt. Den k\u00f6nnte man sicher als Zustand modellieren. Aber letztlich \u00e4ndert sich nicht wirklich etwas am Zustand, es gibt auch keine Wahlm\u00f6glichkeit f\u00fcr den Spieler, und deshalb lasse ich das sein. Das Erscheinen des Boten ist eher eine zus\u00e4tzlich ausgel\u00f6ste Aktion, die beim \u00dcbergang von Z2 nach Z3 automatisch ausgel\u00f6st wird, wenn auch mit zeitlicher Verz\u00f6gerung.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In Java w\u00fcrde man diesen Automaten so implementieren (Stoff der 10. und 12. Jahrgangsstufe am Gymnasium in Bayern, f\u00e4llt Sch\u00fclerinnen und Sch\u00fclern nicht schwer):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class MrSacks  {\n  int state = 0;\n  \/* states:\n   * 0 an offer\n   * 1 accepted\n   * 2 first package delivered \n   * 3 second package delivered\n   * 4 successful north pole\n   * 5 story finished \n   *\/\n\n  void receiveMessage(String message) {\n    if (state==0) {\n      if (message.equals(\"annehmen\")) {\n        state = 1;\n        furchtErhoehen(5); \n      }\n      else if (message.equals(\"ablehnen\")) {\n        state = 5;\n        furchtErhoehen(10);                \n      }\n    }\n    else if (state==1) {\n      if (message.equals(\"abliefern\")) {\n        state = 2;\n        furchtErhoehen(5);\n      }\n    }\n    else if (state==2) {\n      if (message.equals(\"abliefern\")) {\n        state = 3;\n        furchtErhoehen(10);\n      }\n    }\n    else if (state==3) {\n      if (message.equals(\"abliefern\")) {\n        state = 4;\n        furchtErhoehen(-20);\n      }\n      else if (message.equals(\"sabotieren\")) {\n        state = 5;\n        furchtErhoehen(-10);\n      }\n    }\n    else if (state==4) {\n      if (message.equals(\"abholen\")) {\n        state = 5;\n        geldErhoehen(20); \n      }\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn man die Methode <code>receiveMessage<\/code> jeweils mit den richtigen Argumenten aufruft, durchlebt man quasi die Stationen der Geschichte. Allerdings ist das ja nur das nackte Ger\u00fcst der Geschichte. Lebendig und verst\u00e4ndlich wird sie erst durch Text, und der fehlt noch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Der Text der Geschichte<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Wir haben: eine Methode, die abh\u00e4ngig von einer Nachricht und dem aktuellen Zustand die Zust\u00e4nde \u00e4ndert und eventuell noch anderes ausl\u00f6st.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wir brauchen: eine Methode, die abh\u00e4ngig vom aktuellen Zustand und dem aktuellen Ort dem Spieler einen bestimmten Text anzeigt und (mehrere) Entscheidungsm\u00f6glichkeiten anbietet &#8211; und wenn sich der Spieler f\u00fcr eine M\u00f6glichkeit entscheidet, muss das unserer ersten Methode kommuniziert werden, damit die Entscheidung dann auch ausgef\u00fchrt werden kann. Das wird etwas komplizierter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zentral ist f\u00fcr mich die Klasse <code>Report<\/code>. Ein Report ist der Bericht einer Geschichte zu einem bestimmten Ort im Spiel, zu einem bestimmten Zeitpunkt, also abh\u00e4ngig vom Zustand der Geschichte. Ein Report enth\u00e4lt eine kurze Beschreibung einer Situation und beliebig viele Optionen. Aus diesen Optionen werden dann sp\u00e4ter zum Beispiel die Kn\u00f6pfe, mit denen der Spieler Entscheidungen treffen kann. Eine Option (ein Knopf) erh\u00e4lt einen Text (eine Beschriftung, die der Spieler sieht) und eine Message (eine Nachricht, die der Spieler nicht sieht, die aber losgeschickt wird, sobald der Spieler sich f\u00fcr diese Option entscheidet).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7268\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report.png\" alt=\"sunless_report\" width=\"760\" height=\"304\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report.png 760w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report-150x60.png 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report-300x120.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report-700x280.png 700w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><br><small>So k\u00f6nnte der View einen Report darstellen. Oder ganz anders: Hauptsache, er hat alle n\u00f6tigen Informationen dazu.<\/small><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn der Spieler an einem Ort ankommt, werden alle mit dem Ort verbundenen Stories gebeten, einen <code>Report<\/code> abzugeben. Der kann auch mal <code>null<\/code> sein, wenn es zu diesem Zeitpunkt nichts zu sagen gibt. Alle Reports zu diesem Ort werden vom Model geb\u00fcndelt und an den View geschickt, damit der die Reports darstellen kann. Dazu hat der View eine Methode <code>showReports<\/code>. Mehr braucht es erst mal nicht. Der View legt zum Beispiel f\u00fcr jeden Report einen eigenen Absatz an, und am Ende jedes Reports wird f\u00fcr jede Option des Reports ein Knopf mit einer Nachricht dahinter angelegt, den der Spieler dr\u00fccken kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Im vereinfachten Klassendiagramm, noch ohne Darstellung der Bewegungsm\u00f6glichkeiten, sieht das so aus:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"799\" height=\"446\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_classes.png\" alt=\"sunless_classes\" class=\"wp-image-7258\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_classes.png 799w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_classes-150x84.png 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_classes-300x167.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_classes-700x391.png 700w\" sizes=\"auto, (max-width: 799px) 100vw, 799px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Und in Java w\u00e4re die Methode f\u00fcr die Geschichten-Klasse dann so:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Report createReport(String location) {\n  Report r = null;\n  if (location.equals(\"London\")) {\n    if (state==0) {\n      String message = \"Hohoho! Willst du mich an drei Orte meiner Wahl bringen?\";\n      Option o1 = new Option(\"Ja\",\"annehmen\");\n      Option o2 = new Option(\"Nein\",\"ablehnen\");                \n      Option o3 = new Option(\"Sp\u00e4ter\",\"abwarten\");                \n      r = new Report(\"Weihnachtsmonster\", message, o1, o2, o3);\n    }\n    else if (state==4) {\n      String message = \"Der Weihnachtsmann hat dir ein Geschenk dagelassen. Willst du es \u00f6ffnen?\";\n      Option o1 = new Option (\"Ja\", \"abholen\");\n      r = new Report(\"Weihnachtsmonster\", message, o1);\n    }\n  }\n  else if (location.equals(\"Anaheim\")|| location.equals(\"Argentinien\") ) {\n    if (state==1) {\n      String message = \"Hohoho! Ist es in Ordnung, wenn ich mein dunkles Geschenk hier abgebe?\";\n      Option o1 = new Option(\"Ja\",\"annehmen\");\n      Option o2 = new Option(\"Nein\",\"abwarten\");\n      r = new Report(\"Weihnachtsmonster\", message, o1, o2);\n    }\n  }\n  else if (location.equals(\"Beorns Halle\") || (location.equals(\"Britannien\"))) {\n    if (state==2) {\n      String message = \"Hohoho! Ist es in Ordnung, wenn ich mein dunkles Geschenk hier abgebe?\";\n      Option o1 = new Option(\"Ja\",\"annehmen\");\n      Option o2 = new Option(\"Nein\",\"abwarten\");\n      r = new Report(\"Weihnachtsmonster\", message, o1, o2);\n    }\n  }\n  else if (location.equals(\"Nordpol\")) {\n    if (state==3) {\n      String message = \"Du hast die Gelegenheit, dem Weihnachtsmonster zu helfen oder seine Pl\u00e4ne zu sabotieren.\";\n      Option o1 = new Option(\"Helfen\",\"abliefern\");\n      Option o2 = new Option(\"Sabotieren\",\"sabotieren\");\n      r = new Report(\"Weihnachtsmonster\", message, o1, o2);\n      }\n    }\n  return r;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nat\u00fcrlich wird die Geschichte besser, wenn man mehr Reports einbaut. Und was noch fehlt, sind Antworten des Weihnachtsmann, durch die man \u00fcberhaupt erst erf\u00e4hrt, dass man zuerst nach Anaheim oder Argentinien, danach zu Beorns Halle oder nach Britannien, und danach zum Nordpol muss. Gemach, gemach.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Soweit, wie ich das jetzt geschildert habe, existiert auch ein Prototyp. Funktioniert, einschlie\u00dflich der automatischen Anzeige von Bewegungsm\u00f6glichkeiten: f\u00fcr jeden Nachbarort einen Knopf, der einen nach dem Klick dorthin bef\u00f6rdert. Die Reports werden in einer TabbedPane angezeigt, also mit kleinen Reitern oben. (Scrollbarer Text w\u00e4re eine Alternative.) Jeder Report hat unten die Buttons mit den Optionen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mein Hauptproblem ist noch Folgendes. Ich finde es sehr unelegant, zwei verschiedene, aber doch \u00e4hnliche Methoden zu haben. Methode 1 (<code>createReport<\/code>), um dem Spieler anzubieten, was er f\u00fcr Aktionen ausl\u00f6sen kann. Methode 2 (<code>receiveMessage<\/code>), um die Entscheidung des Spielers dann umzusetzen. Das Bindeglied ist ist <code>message<\/code>, die letztlich mittelbar von Methode 1 gesendet und von Methode 2 empfangen wird:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"837\" height=\"279\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_mein_problem.png\" alt=\"sunless_mein_problem\" class=\"wp-image-7248\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_mein_problem.png 837w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_mein_problem-150x50.png 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_mein_problem-300x100.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_mein_problem-700x233.png 700w\" sizes=\"auto, (max-width: 837px) 100vw, 837px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Am liebsten h\u00e4tte ich nur eine Methode, Methode 1 (<code>createReport<\/code>), in der schon unmittelbar drinsteht, was ausgef\u00fchrt werden soll, wenn der Spieler sich f\u00fcr eine Option entscheidet. Dazu m\u00fcsste ich entweder Funktionen als Argumente \u00fcbergeben, was mit Java inzwischen wohl geht, ich aber nicht wei\u00df, ob ich das mit Sch\u00fclern machen soll. Oder ich m\u00fcsste ein Objekt einer anonymen inneren Klasse anlegen (zu einer Unterklasse von, sagen wir, <code>Result<\/code>, mit einer zu \u00fcberschreibenden execute-Methode). Dann br\u00e4uchte ich allein Methode 1 (<code>createReport<\/code>), und die Optionen, die dem Report als M\u00f6glichkeit \u00fcbergeben w\u00fcrden, s\u00e4hen dann so aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Report createReport(String location) {\n  Report r = null;\n  if (location.equals(\"London\")) {\n    if (state==0) {\n      String message = \"Hohoho! Willst du mich an drei Orte meiner Wahl bringen?\";\n      Option o1 = new Option(\"Ja\", new Result() {\n        @Override public void execute() {\n          state = 1;\n          furchtErhoehen(5);                                                \n        }\n      } );\n      Option o2 = new Option(\"Nein\", new Result() {\n        @Override public void execute() {\n          state = 5;\n          furchtErhoehen(10);                                                \n        }\n      } );\n      Option o3 = new Option(\"Sp\u00e4ter\", new Result());                \n      r = new Report(\"Weihnachtsmonster\", message, o1, o2, o3);\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ist das f\u00fcr Sch\u00fcler leichter verst\u00e4ndlich als das mit den zwei separaten Methoden? Der Report landet dann letztlich beim View, zusammen mit den verschiedenen Optionen, zu deren jeder ein Objekt der anonymen Result-Unterklasse geh\u00f6rt, und wenn der entsprechende Knopf gedr\u00fcckt wird, wird die execute-Methode dieses Objekts ausgef\u00fchrt. Der Controller wird dabei gar nicht mehr gefragt.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"757\" height=\"306\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report_alternative.png\" alt=\"sunless_report_alternative\" class=\"wp-image-7267\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report_alternative.png 757w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report_alternative-150x61.png 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report_alternative-300x121.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/sunless_report_alternative-700x283.png 700w\" sizes=\"auto, (max-width: 757px) 100vw, 757px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Mit den anonymen Unterklassen geht das ganze \u00fcbersichtlicher und f\u00fcr die Zukunft auch flexibler, deswegen gef\u00e4llt mir das besser.<br>Aber ich sehe die Gefahr, dass die Sch\u00fcler dann einfach unverstandenen Code abtippen, und das ist ja auch wieder nicht das Ziel.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">Vielleicht kann ich das Ende des Schuljahres mit meiner 10. durchspielen. Man k\u00f6nnte die typische Heldenreise damit modellieren oder die Odyssee. Weltraumfahrten oder neblichtes London, die zw\u00f6lf Heldentaten des Herakles. Eine kleine Gruppe implementiert die Welt, mit sch\u00f6nen Beschreibungen f\u00fcr jeden Ort, Bildern und Musik dazu. Die anderen schreiben Geschichten. EIne Geschichte gebe ich als Beispiel vor. Und dann vielleicht doch noch ein Handelssystem? Gegenst\u00e4nde, die der Spieler mit sich f\u00fchren kann, auch als Token daf\u00fcr, dass er schon bestimmte Dinge erledigt hat?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Nachtrag: Ja, das geht auch ohne anonyme Klassen in einer einzigen Methode! Aber die wird dadurch sehr un\u00fcbersichtlich. Auch keine L\u00f6sung.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nachtrag: <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2017\/03\/storyworld-ein-java-projekt-fuer-die-10-klasse.htm\">Hier geht es zum fertigen Projekt (2017).<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>(20 Kommentare.) (Fortsetzung von hier, wo ich Sunless Sea beschrieben habe. In der ersten H\u00e4lfte geht&#8217;s ums Prinzip, in der zweiten wird es dann immer technischer.) Das modulare Prinzip, nach dem in eine bestehende Spielwelt kleine Missionen oder Geschichten eingebaut werden, w\u00fcrde ich gerne f\u00fcr ein Programmierprojekt in der Schule nutzen. Dazu erschafft man gemeinsam [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":7222,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,195,9],"tags":[227,233,225],"class_list":["post-7207","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-informatik","category-lieblingseintraege","category-spiele","tag-informatik","tag-programmierprojekte","tag-spiele"],"_links":{"self":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/7207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/comments?post=7207"}],"version-history":[{"count":3,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/7207\/revisions"}],"predecessor-version":[{"id":58643,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/7207\/revisions\/58643"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media\/7222"}],"wp:attachment":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media?parent=7207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/categories?post=7207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/tags?post=7207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}