<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
	<channel>
		<title>BlitzBasic Portal Worklogs - [C++/Lua] IRCmud</title>
		<link>https://www.blitzforum.de/worklogs/528/</link>
		<description>Worklog von hamZta</description>
		<language>de</language>
		<managingEditor>mail@blitzforum.de</managingEditor>
		<webMaster>mail@blitzforum.de</webMaster>
		<pubDate>Sun, 24 Mar 2013 17:10:09 +0100</pubDate>
		<lastBuildDate>Sun, 24 Mar 2013 17:10:09 +0100</lastBuildDate>

		<item>
			<title>Threading &amp; NPCs</title>
			<link>https://www.blitzforum.de/worklogs/528/#3668</link>
			<guid>https://www.blitzforum.de/worklogs/528/#3668</guid>
			<author>hamZta</author>
			<description>Nachdem Login/Logout (und Disconnect) jetzt automatisch Spieler l&amp;auml;dt bzw. speichert hab ich mich um ein weiteres Feature gek&amp;uuml;mmert.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;Threads&lt;/span&gt;&lt;br /&gt;Bisher wurde die mudlib aus dem Server heraus rein eventbasiert betrieben. Bei bestimmten Events (Objekt betritt/verl&amp;auml;sst Channel, Objekt sagt etwas, etc..) wurden vorher festgelegte Handler in Lua aufgerufen und das Event dann behandelt. F&amp;uuml;r eine lebendige Welt ist das allerdings zu wenig, wenn kein Spieler was macht, steht die Welt still. Aus diesem Grund gibt es jetzt &amp;quot;Threads&amp;quot; auf Basis von Lua Coroutines.&lt;br /&gt;Diese Threads laufen allerdings nicht gleichzeitig zum Hauptthread, sondern hintereinander. Jedes Objekt kann Threads starten. Jeden Server-Tick werden alle Threads aller Objekte der Reihe nach abgearbeitet. Threads verhalten sich kooperativ, d.h. es gibt keinen Scheduler der die Ausf&amp;uuml;hrung nach einer bestimmten Zeit unterbricht, sie geben die Kontrolle selbst ab.&lt;br /&gt;Daf&amp;uuml;r kann der Thread sich f&amp;uuml;r eine bestimmte Anzahl Ticks &amp;quot;schlafen legen&amp;quot; und wird erst wieder ausgef&amp;uuml;hrt, wenn diese Zeit vor&amp;uuml;ber ist.&lt;br /&gt;&lt;br /&gt;Damit lassen sich nicht nur durchgehende, im Hintergrund laufende Dinge umsetzen, sondern auch einfach Interaktionen durch Verz&amp;ouml;gerungen aufwerten:&lt;br /&gt;&lt;b&gt;Code: &lt;/b&gt;&lt;span style=&quot;font-size:0.8em; display:inline;&quot; id=&quot;showcodebox0&quot;&gt; &lt;a href=&quot;javascript&amp;#058;show_code('0')&quot;&gt;[AUSKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;span style=&quot;font-size:0.8em; display:none;&quot; id=&quot;hidecodebox0&quot;&gt; &lt;a href=&quot;javascript&amp;#058;hide_code('0')&quot;&gt;[EINKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;div id=&quot;codebox0&quot; class=&quot;codebox&quot; style=&quot;max-height: 200px;&quot; onload=&quot;check_code('0');&quot;&gt;function my_npc.quest_start&amp;#40;self, args&amp;#41;&lt;br /&gt;&amp;nbsp; args.player&amp;#58;send_privmsg&amp;#40;self, &amp;quot;Let me search in my books, that might take a while!&amp;quot;&amp;#41;&lt;br /&gt;&amp;nbsp; args.player&amp;#58;send_privmsg&amp;#40;self, &amp;quot;&amp;#91;a&amp;#93;slowly walks towards the bookshelf and pulls out a dusty tome.&amp;#91;/a&amp;#93;&amp;quot;&amp;#41;&lt;br /&gt;&amp;nbsp; self&amp;#58;pause_thread&amp;#40;5&amp;#41;&lt;br /&gt;&amp;nbsp; args.player&amp;#58;send_privmsg&amp;#40;self, &amp;quot;Ah, yes ... yes, I see. *mumbles*&amp;quot;&amp;#41;&lt;br /&gt;&amp;nbsp; self&amp;#58;pause_thread&amp;#40;5&amp;#41;&lt;br /&gt;&amp;nbsp; args.player&amp;#58;send_privmsg&amp;#40;self, &amp;quot;Wait ... what was your question?&amp;quot;&amp;#41;&lt;br /&gt;end&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Nebenbei kann der NPC weiterhin auf Events anderer Spieler reagieren.&lt;br /&gt;&lt;br /&gt;Als Beispiel, ein Thread der NPCs in Abst&amp;auml;nden S&amp;auml;tze sagen l&amp;auml;sst:&lt;br /&gt;&lt;b&gt;Code: &lt;/b&gt;&lt;span style=&quot;font-size:0.8em; display:inline;&quot; id=&quot;showcodebox1&quot;&gt; &lt;a href=&quot;javascript&amp;#058;show_code('1')&quot;&gt;[AUSKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;span style=&quot;font-size:0.8em; display:none;&quot; id=&quot;hidecodebox1&quot;&gt; &lt;a href=&quot;javascript&amp;#058;hide_code('1')&quot;&gt;[EINKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;div id=&quot;codebox1&quot; class=&quot;codebox&quot; style=&quot;max-height: 200px;&quot; onload=&quot;check_code('1');&quot;&gt;function M.thread_mutter&amp;#40;self, args&amp;#41;&lt;br /&gt;&amp;nbsp; local sleep_time = args.sleep_time&lt;br /&gt;&amp;nbsp; local variation = args.variation&lt;br /&gt;&amp;nbsp; local last_msg_id = 0&lt;br /&gt;&lt;br /&gt;&amp;nbsp; while true do&lt;br /&gt;&amp;nbsp; &amp;nbsp; local msg_id = math.random&amp;#40;1, #args.sentences&amp;#41;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; while #args.sentences &amp;gt; 1 and msg_id == last_msg_id do&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; msg_id = math.random&amp;#40;1, #args.sentences&amp;#41;&lt;br /&gt;&amp;nbsp; &amp;nbsp; end&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; last_msg_id = msg_id&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; self&amp;#58;get_channel&amp;#40;&amp;#41;&amp;#58;send_privmsg&amp;#40;self, args.sentences&amp;#91;msg_id&amp;#93;&amp;#41;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; local wait_time = math.random&amp;#40;sleep_time - variation, sleep_time + variation&amp;#41;&lt;br /&gt;&amp;nbsp; &amp;nbsp; self&amp;#58;pause_thread&amp;#40;wait_time&amp;#41;&lt;br /&gt;&amp;nbsp; end&lt;br /&gt;end&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Die Zeile &amp;quot;self:pause_thread(wait_time)&amp;quot; h&amp;auml;lt dabei den Thread an, f&amp;uuml;r eine bestimmte Zeit sleep_time mit einer Varianz variation.&lt;br /&gt;&lt;br /&gt;Im Einsatz eines NPCs sieht das dann folgenderma&amp;szlig;en aus:&lt;br /&gt;&lt;b&gt;Code: &lt;/b&gt;&lt;span style=&quot;font-size:0.8em; display:inline;&quot; id=&quot;showcodebox2&quot;&gt; &lt;a href=&quot;javascript&amp;#058;show_code('2')&quot;&gt;[AUSKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;span style=&quot;font-size:0.8em; display:none;&quot; id=&quot;hidecodebox2&quot;&gt; &lt;a href=&quot;javascript&amp;#058;hide_code('2')&quot;&gt;[EINKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;div id=&quot;codebox2&quot; class=&quot;codebox&quot; style=&quot;max-height: 200px;&quot; onload=&quot;check_code('2');&quot;&gt;mutter_args = &amp;#123;&lt;br /&gt;&amp;nbsp; sleep_time = 60,&lt;br /&gt;&amp;nbsp; variation = 10,&lt;br /&gt;&amp;nbsp; sentences = &amp;#123;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;quot;Do not litter.&amp;quot;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;quot;Citizen #17, please report to the nearest Liberation Office!&amp;quot;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;#91;a&amp;#93;drives around in circles.&amp;#91;/a&amp;#93;&amp;quot;,&lt;br /&gt;&amp;nbsp; &amp;#125;&lt;br /&gt;&amp;#125;&lt;br /&gt;robot&amp;#58;create_thread&amp;#40;&amp;quot;mutter&amp;quot;, lib.npc.thread_mutter, mutter_args&amp;#41;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Alle 60(+-10) Ticks sagt der Roboter einen zuf&amp;auml;lligen Satz aus der Liste ([a]...[/a] macht daraus eine Aktion, wie /me &amp;lt;text&amp;gt;).&lt;br /&gt;&lt;br /&gt;Das war's auch schon wieder, langsam hab ich alle Werkzeuge zusammen um mich wieder der mudlib zuwenden zu k&amp;ouml;nnen. Und vielleicht auch mal mit dem eigentlichen Spiel anzufangen ... &lt;img src=&quot;/forum/images/smiles/icon_wink.gif&quot; alt=&quot;Wink&quot; /&gt;</description>
			<pubDate>Sun, 24 Mar 2013 17:10:09 +0100</pubDate>
		</item>

		<item>
			<title>Not much to see</title>
			<link>https://www.blitzforum.de/worklogs/528/#3667</link>
			<guid>https://www.blitzforum.de/worklogs/528/#3667</guid>
			<author>hamZta</author>
			<description>Mal wieder ein Update:&lt;br /&gt;In den letzten Tagen habe ich haupts&amp;auml;chlich an der mudlib weitergeschraubt. Dazugekommen sind folgende Sachen:&lt;br /&gt;In der Welt gibt es jetzt Items. Items sind Objekte die keine Lebewesen sind. Sie k&amp;ouml;nnen in R&amp;auml;umen rumliegen, manche k&amp;ouml;nnen von Spielern aufgehoben werden, mit allen kann irgendwie interagiert werden.&lt;br /&gt;Zum Beispiel tr&amp;auml;gt jeder Spieler von Beginn an einen PDA mit sich. Benutzt er den, &amp;ouml;ffnet sich ein privater Chat (Query). Dort kann man die Funktionen des PDA &amp;uuml;ber Textbefehle nutzen (Notizen verwalten, Mails senden &amp;amp; lesen, etc). Der Besitzer eines PDAs ist dabei fix eingespeichert. Gibt man das Ding an einen anderen Spieler weiter so hat dieser Zugriff auf die Mails des eigentlichen Besitzers.&lt;br /&gt;&lt;br /&gt;Spieler k&amp;ouml;nnen sich jetzt auch zwischen R&amp;auml;umen hin- und herbewegen. Dabei gibt es anders als in alten Versionen nicht eine Liste mit anderen R&amp;auml;umen die man von dem aktuellen Raum aus erreicht, sondern man bewegt sich &amp;uuml;ber Himmelsrichtungen.&lt;br /&gt;Dazu werden im Code vorher R&amp;auml;ume miteinander verbunden. Dadurch ergeben sich auch wieder viele M&amp;ouml;glichkeiten (One-way-Verbindungen, versteckte R&amp;auml;ume, R&amp;auml;ume die eine gewisse Zugangsbeschr&amp;auml;nkung haben, ...).&lt;br /&gt;&lt;br /&gt;Dabei hat sich auch das Channelhandling ge&amp;auml;ndert. Fr&amp;uuml;her war jeder Raum direkt einem IRC-Channel zugeordnet. Hat man sich bewegt hat man einen Channel verlassen und den anderen betreten. Das hatte nat&amp;uuml;rlich zur Folge, dass die meisten IRC-Clients f&amp;uuml;r jeden Channel ein neues Fenster/einen neuen Tab &amp;ouml;ffnen und vielleicht auch nicht automatisch wieder schlie&amp;szlig;en wenn man ihn verl&amp;auml;sst. Jetzt werden alle R&amp;auml;ume auf einen IRC-Channel abgebildet. Dadurch bleibt immer nur ein Fenster offen, man muss nicht rumklicken und wird auch nicht mit Tableichen &amp;uuml;berh&amp;auml;uft.&lt;br /&gt;&lt;br /&gt;Als n&amp;auml;chstes sollte ich mich darum k&amp;uuml;mmern, alles ein wenig abzurunden, vor allem Login/Logout von Spielern. Danach geht's weiter zur Interaktion von Spielern mit NPCs. Dazwischen sollte ich mir &amp;uuml;berlegen wo ich &amp;uuml;berhaupt hin will damit das Spiel auch Spa&amp;szlig; macht &lt;img src=&quot;/forum/images/smiles/icon_wink.gif&quot; alt=&quot;Wink&quot; /&gt;</description>
			<pubDate>Wed, 20 Mar 2013 23:27:03 +0100</pubDate>
		</item>

		<item>
			<title>Look at the red cat in the huge and shiny metal box</title>
			<link>https://www.blitzforum.de/worklogs/528/#3655</link>
			<guid>https://www.blitzforum.de/worklogs/528/#3655</guid>
			<author>hamZta</author>
			<description>Ja, das Projekt gibt es noch. Ich habe vor einiger Zeit wieder angefangen daran zu arbeiten.&lt;br /&gt;&lt;br /&gt;IRCmud ist ein sogenannter MUD-Server (&lt;a href=&quot;http://de.wikipedia.org/wiki/Multi_User_Dungeon&quot; target=&quot;_blank&quot;&gt;http://de.wikipedia.org/wiki/Multi_User_Dungeon&lt;/a&gt;). Multi User Dungeons sind die Mutter aller MMORPGs. Gemeinsam mit anderen Spielern kann man durch die Welt wandern, Aufgaben l&amp;ouml;sen, k&amp;auml;mpfen oder einfach nur chatten. Im Gegensatz zu modernen MMORPGs ist hier aber alles textbasiert!&lt;br /&gt;&lt;br /&gt;Traditionelle MUDs sind zeilen- oder zeichenbasierte Server auf die man &amp;uuml;ber telnet zugreift. Wie der Name vermuten l&amp;auml;sst verwende ich einen anderen Ansatz und benutze statt telnet IRC als Protokoll, f&amp;uuml;r das viele Nerds ohnehin schon Clients installiert haben &lt;img src=&quot;/forum/images/smiles/icon_wink.gif&quot; alt=&quot;Wink&quot; /&gt; Ein Nachteil dieser Umsetzung ist, dass IRC viel weniger Freiheiten l&amp;auml;sst was Formatierung zul&amp;auml;sst.&lt;br /&gt;&lt;br /&gt;Das Projekt besteht dabei aus zwei Teilen:&lt;br /&gt;Der Server, der Verbindungen annimmt und den Netzwerktraffic handelt (IRCmud, C++) und die Spielmechanik inklusive Library (mudlib, Lua). Dazwischen liegt eine d&amp;uuml;nne Schicht in der der Server bei bestimmten Aktivit&amp;auml;ten Lua-Funktionen aufruft (Spieler verbindet sich, sagt etwas, ...). Der Server unterscheidet dabei nur zwischen drei verschiedenen Entit&amp;auml;ten: Spieler, Channel und Objekt. Objekt ist die Basisklasse, Spieler und Channel sind davon abgeleitet. Diese Klassen sind in der mudlib sichtbar und k&amp;ouml;nnen wiederrum als Basisklassen f&amp;uuml;r komplexere Konstrukte verwendet werden. Grunds&amp;auml;tzlich gilt: Everything's an object &lt;img src=&quot;/forum/images/smiles/icon_wink.gif&quot; alt=&quot;Wink&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;mudlib&lt;/b&gt;&lt;br /&gt;Die Library stellt Funktionen und Abstraktionen f&amp;uuml;r Objekte zur Verf&amp;uuml;gung. So kann sie zum Beispiel Objekten Eigenschaften und Namen zuweisen. Diese Eigenschaften und Namen werden daf&amp;uuml;r verwendet, Objekte zu identifizieren.&lt;br /&gt;&lt;br /&gt;Fr&amp;uuml;her hat man sich mit starren Befehlen durch IRCmud bewegt (z.B. &amp;quot;!look NPC&amp;quot; oder &amp;quot;!move channel&amp;quot;). Klassische MUDs setzen aber Parser ein, die komplexere, an nat&amp;uuml;rliche Sprache angelehnte Befehle verarbeiten k&amp;ouml;nnen. So einen hab ich jetzt eingebaut:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Der Parser&lt;/b&gt;&lt;br /&gt;Will man einen neuen Befehl definieren &amp;uuml;bergibt man dem Parser den Namen, ein paar Regeln und eine Callback-Funktion. Im MUD-Slang werden Befehle Verben genannt. Ein Beispiel w&amp;auml;re das Verb &amp;quot;look&amp;quot; (anschauen). Die einfachste Regel w&amp;auml;re, sich ein anderes Objekt anzusehen: &amp;quot;look at OBJ&amp;quot;. Der Parser erkennt dabei das Schl&amp;uuml;sselwort &amp;quot;OBJ&amp;quot; und akzeptiert daf&amp;uuml;r eine Liste aus Adjektiven und einen Namen. Gibt der Spieler Text ein, der mit &amp;quot;look&amp;quot; beginnt, so versucht er das eingegebene auf eine der Regeln des Verbs zu matchen.&lt;br /&gt;&lt;br /&gt;In diesem Fall k&amp;ouml;nnte der Spieler &amp;quot;look at cat&amp;quot; eingeben, der Parser w&amp;uuml;rde &amp;quot;cat&amp;quot; erkennen und den Raum in dem sich der Spieler befindet nach einem Objekt namens &amp;quot;cat&amp;quot; durchsuchen. Findet er es, ruft er die Callback-Funktion mit dem gefundenen Objekt als Parameter auf. Dazu kommt noch etwas &amp;quot;syntactic sugar&amp;quot;, damit es nat&amp;uuml;rlicher klingt wird auch &amp;quot;look at the cat&amp;quot; richtig erkannt.&lt;br /&gt;&lt;br /&gt;Was passiert jetzt, wenn sich im Raum zwei Katzen befinden? Auf ein &amp;quot;look at the cat&amp;quot; gibt der Server nur ein &amp;quot;Which cat?&amp;quot; zur&amp;uuml;ck. Daf&amp;uuml;r kommen jetzt die o.g. Eigenschaften ins Spiel. Die Katzen k&amp;ouml;nnen verschiedene Eigenschaften haben, zum Beispiel kann eine Katze schwarz und alt sein, die andere ist vielleicht wei&amp;szlig;, jung und kleiner als die andere. &lt;br /&gt;M&amp;ouml;gliche Befehle:&lt;br /&gt;&lt;b&gt;Code: &lt;/b&gt;&lt;span style=&quot;font-size:0.8em; display:inline;&quot; id=&quot;showcodebox3&quot;&gt; &lt;a href=&quot;javascript&amp;#058;show_code('3')&quot;&gt;[AUSKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;span style=&quot;font-size:0.8em; display:none;&quot; id=&quot;hidecodebox3&quot;&gt; &lt;a href=&quot;javascript&amp;#058;hide_code('3')&quot;&gt;[EINKLAPPEN]&lt;/a&gt; &lt;/span&gt;&lt;div id=&quot;codebox3&quot; class=&quot;codebox&quot; style=&quot;max-height: 200px;&quot; onload=&quot;check_code('3');&quot;&gt;Spieler&amp;gt; look at the black cat&lt;br /&gt;System&amp;#58; You see a black and old cat.&lt;br /&gt;&lt;br /&gt;Spieler&amp;gt; look at the white cat&lt;br /&gt;System&amp;#58; You see a white, young and small cat.&lt;br /&gt;&lt;br /&gt;Spieler&amp;gt; look at the white, young cat&lt;br /&gt;System&amp;#58; You see a white, young and small cat.&lt;br /&gt;&lt;br /&gt;Spieler&amp;gt; look at the black old cat&lt;br /&gt;System&amp;#58; You saw a black and old cat.&lt;br /&gt;&lt;br /&gt;Spieler&amp;gt; look at the white and small cat&lt;br /&gt;System&amp;#58; You see a white, young and small cat.&lt;br /&gt;&lt;br /&gt;Spieler&amp;gt; look at the black and small cat&lt;br /&gt;System&amp;#58; There is no black and small cat.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Man ist also ziemlich flexibel, Grammatikextras wie Kommata oder &amp;quot;and&amp;quot; als Bindewort werden erkannt und ausgefiltert. Neben Eigenschaften kann man Objekten auch noch Synonyme zuweisen, bei einer Katze w&amp;auml;re zum Beispiel das englische &amp;quot;kitten&amp;quot; m&amp;ouml;glich, was ein &amp;quot;look at the small kitten&amp;quot; zus&amp;auml;tzlich erlauben w&amp;uuml;rde.&lt;br /&gt;&lt;br /&gt;Komplexere Regeln erlauben es Spielern Objekte in anderen Objekten zu sehen: &amp;quot;look at OBJ in OBJ&amp;quot;. So k&amp;ouml;nnte ein Spieler zum Beispiel &amp;quot;look at the brown cat in the wooden box&amp;quot; ausf&amp;uuml;hren. In den Callback kommen dann weitere Abfragen, wie: Kann der Spieler die Katze &amp;uuml;berhaupt sehen? Kann der Spieler &amp;uuml;berhaupt sehen (ist er blind)? Ist der Raum zu dunkel um etwas zu sehen (hat der Spieler eine Lichtquelle in der Hand)?&lt;br /&gt;&lt;br /&gt;Neben OBJ gibt es noch andere Schl&amp;uuml;sselworte:&lt;br /&gt;DIR nimmt eine Himmelsrichtung als Eingabe, STR einen String (z.B. &amp;quot;engrave STR into OBJ&amp;quot; -&amp;gt; &amp;quot;engrave I was here into the mossy tombstone&amp;quot;), INT f&amp;uuml;r Zahlen, etc.&lt;br /&gt;&lt;br /&gt;Das ist soweit der aktuelle Stand, es gibt noch genug zu tun!&lt;br /&gt;&lt;br /&gt;hamZta</description>
			<pubDate>Thu, 07 Mar 2013 01:20:33 +0100</pubDate>
		</item>


	</channel>
</rss>
