Tag Archives: Informatik

Einführung in BPMN

So, nachdem ich nun schon einige Artikel mit Ablaufdiagrammen gepostet habe (so zum Beipiel zur Optionsauswahl, zum allgemeinen Ablauf der KI und zur Kaufentscheidung) wurde ich nun gefragt, wie man diese eigentlich liest. Kurz gestockt, hmm, stimmt, das gehört wohl nicht zum Standardausbildungskanon ^^ Also die genutzte Notation ist die BPMN, also die Business Process Modelling Notation.

In diesem Artikel möchte ich kurz auf diese eingehen und die zentralen (also die von mir genutzten) Symbole erläutern, nach dieser kurzen Einführung sollte das Lesen der von mir geposteten Ablaufdiagramme also kein Problem mehr sein :)

Continue reading

Posted in Theory-O-Matic. Tagged with , .

Den (eigenen?) Weg finden

In diesem Artikel möchte ich einen Gedanken zur Wegfindung von NSCs mit euch teilen. Wie kann ein NSC einen Weg finden, ohne dass ein offizieller Pfad existiert? Und ohne dass – noch viel schlimmer – geskriptete Wege hinterlegt werden? Aber gleichzeitig auch ohne dass der NSC allwissend ist, die Wege besser findet als der Spieler und ohne dass er, alles bisher gewesene ignorierend, außerhalb von Städten und offiziellen Wegen rein nach Himmelsrichtungen läuft? Nun habe ich schon mehrfach das Wort offizieller Weg / Pfad genutzt, was ist eigentlich ein Weg?

“Wege entstehen dadurch, dass man sie geht.” (Franz Kafka)

Dieses schöne Zitat von Kafka war sicherlich im übertragenen Sinn gemeint, stimmt aber auch in seiner wörtlichen Bedeutung.

Continue reading

Posted in Theory-O-Matic. Tagged with , , .

Verhalten der NSCs

Ein weiteres mögliches und sehr ergiebiges neues Thema wäre die KI der NSCs. Welche Anforderungen und welche Wünsche werden an eine KI in einem Computerspiel gestellt? Ich weiß vor allem, was ich nicht möchte. Ich möchte keine “dummen Bots”. Ich möchte keine feindlichen NSCs, die nach der Uhr ihre Attacken ausführen, ich möchte keine zivilen NSCs, die zu jeder vollen Stunde ihren üblichen Weg laufen und dabei jedes Mal dieselbe Unterhaltung führen. Mehr noch: Frei nach dem Motto “Lernen ist wie Rudern gegen den Strom. Sobald man aufhört, treibt man zurück” (Benjamin Britten) ist jede KI, die sich dem Verhalten der Spieler nicht anpasst, die nicht dauerhaft von ihrer Umwelt lernt, unbefriedigend. Ich würde also erwarten, dass sich die NSCs dem Umfeld und damit auch meinen Aktionen anpassen. Das Ziel einer KI für feindliche, vor allem aber für verbündete NSCs in einem Spiel, in dem viel Zeit auch außerhalb von Kämpfen verbracht wird, sollte auch die Erhaltung und Erzeugung von Ambiente und Konsistenz beinhalten. Die NSCs sollten Aktionen nicht ausführen, weil wir das so geskriptet haben, sondern weil sie einen Grund dafür haben. Sie sollten kein Brot kaufen, weil ein Skript ihnen sagt, dass sie jeden Tag ein Brot kaufen, sondern weil sie Hunger haben und ein Brot kaufen dann eine gute Idee ist. Wenn die gesellschaftlichen Gepflogenheiten sich durch die Spieler ändern, dann sollten sie es erkennen. Wenn sich Treffpunkte heraus gebildet haben, an denen sich die Spieler vermehrt aufhalten, dann sollten die NSCs sich daran anpassen und zum Beispiel beginnen, dort Ware zu verkaufen oder nach Arbeit zu suchen. Und das alles, ohne! für jede Situation ein eigenes Skript zu schreiben. Leider bestehen die meisten KI Systeme, wie sie in Lehrbüchern stehen, nur aus immer komplexeren Skripten, die immer mehr Daten mit einrechnen. Die KI, wie ich sie mir vorstelle, ist in drei Ebenen unterteilt:

  • Ebenen der KI

    Ebenen der angedachten künstlichen Intelligenz

    Motivationsebene: Mit Hilfe einer Motivationspyramide wird bestimmt, welche Bedürfnisse den NSC motivieren, also welche Ziele angegangen werden. Je nach Archetyp des NSCs kann die Motivationspyramide entsprechend angepasst sein, bzw. die sich dahinter verbergenden konkreteren Ziele können variieren (Anerkennung kann sowohl in handwerklichem Können, in Reichtum oder auch im Krieg gesucht werden). Diese Ziele schränken die Optionen, die der nächsten Ebene gewählt werden können, stark ein. Beispiel für eine in dieser Ebene getroffene Entscheidung: Die Bedürfnisse der Art “Grundbedürfnisse” sind erfüllt, Ziele mit Zweck Bedürfniserfüllung “Sicherheit” werden nun auch verfolgt.

  • Optionsebene: Welche Handlungsoptionen stehen zur Verfügung, wie werden sie bewertet, welche werden ausgeführt? Beispiel für eine in dieser Ebene getroffene Entscheidung: Aus der Motivationsebene kamen hohe Bewertungen für die Bedürfnisse “Grundbedürfnisse” und “Sicherheit”. Es stehen also Optionen wie “Essen / Trinken bei Gastwirt y oder Bauer z besorgen” aber auch “ein Schloss bei Schmied y kaufen und einbauen” oder “eine Waffe bei Schmied x kaufen” zur Verfügung, nicht aber Optionen der Selbstverwirklichung wie “ein Bild malen”. Diese Optionen werden gewertet und eine Entscheidung für eine oder mehrere Optionen werden getroffen.
  • Situationsebene:Die Optionsebene hat eine auszuführende Handlung bestimmt. Die Situationsebene ist die konkreteste Ebene, hier geht es um Fragen wie: Wie verhalte ich mich, wenn ein “befreundeter” NSC oder Spieler vorbeiläuft, wie führe ich die eigentlich Aktion (“Waffe kaufen”) durch, wie biege ich an Kreuzung b ab, wenn mein eigentlicher Weg versperrt ist, wie reagiere ich, wenn mich jemand angreift? Beispiel für eine Entscheidung dieser Ebene: “Gib dem Schmied x Geld für die Waffe”, aber auch Reaktionen auf einen Angriff wie “die Flucht ergreifen” oder “zur Wehr setzen” und damit verbunden das Kampfverhalten (welche Schläge führe ich aus..).

Continue reading

Posted in Theory-O-Matic. Tagged with , , .

von Coding, Customizing und Daten

Ich habe in letzter Zeit häufiger mal das Stichwort Customizing genutzt und daher entschieden, mal einen kurzen Artikel über die Unterscheidung von Coding, Customizing und Daten einzustellen. Die Art der Unterscheidung die ich hier eben vorstellen möchte wird in der Praxis viel genutzt und hat dort ihre Eignung für komplexe Systemlandschaften  gezeigt, Systemlandschaften mit mehreren Produktivsystemen und pro Produktivsystemen zu mindestens ein Entwicklungssystem, wahrscheinlicher jedoch mit einem Entwicklungs- und einem Testsystem pro Produktivsystem. Wir unterscheiden also drei Arten von “Informationen”:

  • Coding: Ok, das ist wohl selbsterklärend. Coding ist alles, was der Entwickler in einer Programmiersprache (im Editor) schreibt und für die Ausführung compiliert wird. Coding kann (sollte) nur auf dem Entwicklungssystem geändert werden, nach Freigabe auf das Testsystem transportiert werden und erst nach erfolgreichen Tests auf das Produktivsystem übernommen werden.
  • Customizing: Customizing beinhaltet alle Informationen, die auf der Datenbank gespeichert werden und Einfluss auf die Ausführung des Programms haben. Im Normalfall werden Customizing Einstellungen auf dem Entwicklungssystem geändert und dann wie Coding gehandhabt: Die Änderungen werden auf das Testsystem transportiert, dort getestet und im Erfolgsfall auf das Produktivsystem übernommen. Beispiele für Customizingdaten sind zum Beispiel globale Einstellungen – ist ein Service aktiv? Wie hoch ist der Schwellwert für..? Oder in unserem Fall gehören pflanzenartspezifische Informationen wie in Fast ein Baum im Baum oder von Umweltfaktoren und ihren Auswirkungen angesprochen dazu.
  • Daten: Daten sind auch Information, die auf der Datenbank gespeichert werden, aber anders als Customizingdaten bedarfen diese Daten keinen Tests und werden daher nicht durch die Stufen der Entwicklungslandschaft transportiert. Zu Daten zählen alle Informtionen, die (im Betrieb) im Lifesystem entstehen. Sie werden nicht handisch vom Entwickler eingegeben, sondern im Normalfall importiert oder während des Lifebetriebs erhoben und direkt auf der Datenbank des Produktivsystems gespeichert. Beispiele sind Kundendaten, Bestellungen oder – in unserem Fall – Pflanzen, Vertices, Sprites und Werte von Umweltfaktoren.

So weit zur Unterscheidung, aber warum der ganze Zirkus? Eine “Informationsart” Daten zu haben ist einleuchtend – die täglich anfallenden Daten, die keiner Tests bedarfen täglich, stündlich, minütlich durch die Systeme zu transportieren ist unnötig, langsam und teuer. Dass wir Coding brauchen ist wohl auch klar – wie sonst soll das System wissen, was zu tun ist? Dass Coding nicht direkt im Betrieb geändert werden sollte ist wegen der Gefahr ovn Inkonsistenzen und Bugs auch schnell ersichtlich. Aber warum brauchen wir Customizing? Wir könnten doch einfach alles hart kodieren? Oder direkt auf dem produktivsystem ändern? Letzteres entfällt eben wieder wegen der Gefahr von Inkonsistenzen und Bugs. Zur anderen Option: Einstellungen, Schwellwerte etc. in Customizing Tabellen zu speichern anstatt sie hart im Code zu hinterlegen hat viele Vorteile. Zunächst sind mögliche Änderungen um einiges einfacher – wenn ein Schwellwert doch zu hoch oder zu niedrig ist, dann ist der (sinnvoll benamste) Wert in der Tabelle schnell geändert.  Hunderte von Codezeilen zu durchforsten ist um einiges mehr Arbeit, egal wie gut der Code geschrieben und kommentiert ist. Ein zweiter Vorteil ist die bessere Wiederverwendbarkeit von Code. In der Simulation der Umwelt folgen alle Berechnungen demselben logischen Grundmuster, unabhängig von der Pflanzenart. Alle pflanzenartspezifischen Eigenheiten werden von der Datenbank gelesen und automatisch vom Coding berücksichtigt. Ohen die Verbindung mit Datenbanktabellen müsste ich für jede Spezies eine Kindklasse einführen. Die Liste der Gründe für Customizingtabllen geht noch weiter, aber ich will eure Geduld nicht mehr als nötig strapazieren. In der Zusammenfassung: Coding sollte sich auf die Logic des programms beschränken, alle notwendigen Werte (die getestet werden sollen) gehören in Customizingtabellen. Alle Daten, die nicht getestet oder von einem Entwickler geprüft werden müssen können (direkt) auf der Datenbank des Produktivsystems gespeichert werden.

Posted in Code-O-Matic. Tagged with .

Wo gehört der Himmel hin?

Ich möchte heute mal ein Problemchen ansprechen, das sicher viele von uns kennen und sich auch in meiner neueren Erfahrung als dankbares (Party-) Gesprächsthema erwiesen hat – zumindestens unter Informatikern ;) Die Situation ist folgende: Man proggt (oder konzeptioniert) fröhlich vor sich hin und im aktuellen Konzept gibt es eine Variable, vielleicht ein Customizingwert oder aber auch die Instanz einer Handlerklasse *hust*, die an unglaublich vielen Stellen verfügbar sein muss. An uuuunglaublich vielen Stellen. So, und was nu? Da gibt es doch einiges, was man tun könnte, spontan fallen mir ein:

  • Die Variable durchreichen, von Objekt zu Objekt, von Methode zu Methode, auf dass sie überall verfügbar ist, wo es notwendig ist.
  • Eine global genutzte Vaterklasse mit entsprechender Instanzvariablen erstellen, von der alle anderen genutzten Klassen (oder zumindestens alle, in denen die Variable benötigt wird), erben.
  • Eine globale Variable erstellen.

Wie finden wir das? Das kommt ganz drauf an, wen man fragt und für welche Situation :) Ich persönlich nutze die erste Variante, solange es genügend Programmzweige / Klassen / Methoden gibt, in denen die Variable nicht genutzt wird und in denen das vor allem auch nicht geplant ist. In der Umweltsimulation ist vor Kurzem der Zeitpunkt gekommen, in dem ich diese Variante unschön geworden ist. Da der Datenbankhandler auch sämtliche gepufferten Daten verwaltet, kann es nun vorkommen, dass auf recht niedriger Ebene Änderungen auftreten, durch die die Kenntnis der Handlerklasse notwendig wird. Dadurch wird eine Änderung von allen Methoden in der Aufrufhistorie notwendig, bis man zu einer ersten Methode gekommen ist, die die entsprechende Instanz kennt. Dann bleiben also noch zwei Möglichkeiten übrig. Tendenziell, wenn die Variable tatsächlich im gesamten Programm verfügbar sein darf und muss, gefällt mir die Möglichkeit einer globalen Variable besser. In der Simulation der Umwelt habe ich mich auch für diesen Teil entschieden. Der Programmieraufwand, diese beiden Möglichkeiten ineinander zu überführen ist glücklicherweise gering, da die Änderung sich beschränkt auf die Headerdateien der vorhandenen Vaterklassen und eben die globals.cpp beziehungsweise die (sehr kurze) neue Vaterklasse, von der alle erben sollen. Warum sich für eine Variante entscheiden um direkt im Anschluss über einen Übergang zur anderen Variante nachzudenken? Die Variante über die Vererbung hat den Vorteil, dass man die Kenntnis auf Programmteile beschränken kann. Momentan ist nicht geplant, dass andere Teile der Offtime Berechnungen in das Programm zur Simulation der Umwelt aufgenommen werden. Wenn wir uns doch dafür entscheiden sollten und die neu hinzukommenen Programmteile die Instanz der Handlerklasse nicht benötigen, würde ich einen Wechsel zur Vererbungsvariante in Erwägung ziehen.

Ach, was der Titel hiermit zu tun hat? In der Simulation der Umwelt hat fast jede Klasse eine 1-1 Entsprechung in der realen Welt, die ich auch so wenig wie möglich zu verletzen versuche. Auch dies war ein Grund für die Entscheidung für eine globale Variable. Die Handlerklasse ist – finde ich – wie der Himmel oder die Luft in dieser Entsprechung – immer da, wird von überall genutzt und ist überall bekannt. Den Himmel im Methodenaufruf weiterzureichen oder ihn als Attribut zu vererben stört diese Realwelt-Entsprechungen.

Posted in Code-O-Matic. Tagged with , .

Ordnung schaffen: eine Datenbank Handlerklasse

Eigentlich wollte ich am Wochenende dafür sorgen, dass endlich mal ein paar Screenshots von einem ganzen Wald (noch ohne schöne Texturen, aber immerhin..) online kommen. Dafür notwendig waren ein paar Änderungen, die das Langzeitverhalten der Wuchsform der Bäume betreffen. Uneigentlich.. ist mir mein stiefmütterliches Behandeln der Datenbankzugriffe auf den Kopf gefallen.. Irgendwo schreibt eine Methode Werte auf die Datenbank, die ich zu dem Zeitpunkt da noch nicht drin haben will. Aber wo? Es war immer geplant, dass ich das Coding nochmal aufräume, aber ich hatte gehofft es verschieben zu können bis alle Grundfunktionalitäten stehen. Und dann gründlich aufzuräumen, ohne die Funktionsweise zu schädigen. Aber statt mich durch den Code zu wühlen und den “schuldigen” Datenbankzugriff händisch rauszusuchen, ziehe ich zu mindestens dieses Schritt des Aufräumens vor und implementiere ein zentrales Handling der Datenbankzugriffe.

Folgende Anforderungen an das Handling habe ich mir gestellt:

  • Sämtliche Datenbankzugriffe laufen über die Methoden der Handlerklasse, außerhalb von dieser ist die Verbindung zu Datenbank nicht bekannt.
  • Die Handlerklasse ist verantwortlich für die Datenkonsistenz innerhalb des Programmaufrufs und für die Verwaltung entsprechender Sperreinträge auf der Datenbank.
  • Die Handlerklasse dient als Puffer zwischen Datenbank und Programm.
  • Programmteile brauchen die Berechtigung, um Datensätze des Puffers auslesen oder schreiben zu dürfen.
  • Alle Datenbankzugriffe werden mitgeloggt.
UML Buffer

UML Buffer

Nebenstehend ein Diagramm, das den groben Ablauf des Handlings der Datenbankabfragen zeigt. Jede Datenanfrage der Umweltsimulation wird an den Datenbankhandler gestellt. Dieser prüft, ob die Berechtigung vorhanden ist, ansonsten wird abgebrochen. Wenn diese Daten noch nicht geladen wurden, werden sie aus der Datenbank geladen. Es wird geprüft, ob die Daten einen Sperrvermerk haben, ansonsten werden die entsprechenden Datensätze ausgelesen und mit einem Sperrvermerk versehen. Die ermittelten Daten werden in die benötigten Strukturen überführt und in den Puffer geschrieben. In beiden Fällen werden die Informationen aus dem Puffer an die Simulation zurück gegeben. Jede Änderungsanfrage der Umweltsimulation wird ebenfalls an den Datenbankhandler gestellt. Dieser prüft, ob die Berechtigung vorhanden ist, ansonsten wird abgebrochen. Wenn die Berechtigung vorhanden ist, werden die Daten im Puffer geändert. Zusätzlich können aus der Simulation heraus das Committen oder Verwerfen der Änderungen angestoßen werden.

Posted in Code-O-Matic. Tagged with , , , .

Mein NSC versteht mich nicht..

Wäre das nicht imba, wenn dein Lieblings NSC dich nicht nur nett anlächeln könnte oder wortlos mit dir handeln könnte, sondern dich verstehen, dir antworten und sich vielleicht sogar an die Gamersprache gewöhnen könnte? Wenn du einen Söldner NSC ansprichst mit “Hey, LFM Torlahöhle, Interesse?” und der antwortet mit “Alles FFA?” – ich fände es toll :) Und klar, Gamersprache ist in einem RP nicht gewollt, aber auch dort gibt es genug Anwendungsfälle, in denen das nice ist: andere Namen für Orte, sprachliche Umgangsformen..

Aber ist das umsetzbar? Nach den ersten Kapiteln aus “The Handbook of Computational Linguistics and Natural Language Processing” von A. Clark, Ch. Fox, Sh. Lappin (Beute aus meinem letzten Unibib Raid) lautet meine vorläufige Antwort leider “Nein”. Aber so schnell lasse ich mich nicht entmutigen..

Posted in Theory-O-Matic. Tagged with , , .