--- /dev/null
+We have to give credits to the following people!
+
+Game Design and Main Programming
+
+ Benni Bärmann
+ Dominikus Scherkl
+
+Additional Programming
+
+ Jens Kurlanda
+ Olaf Ohlenmacher
+
+Graphics
+
+ Christine Bauer
+ Dominikus Scherkl
+
+Rule Proofreading
+
+ Frauke Distelrath
+
+Game Testing
+
+ Benni Bärmann
+ Christine Bauer
+ Nicolas Diederichs
+ Olaf Ohlenmacher
+ Jens Kleinschmidt
+ Jens Kurlanda
+ Dominikus Scherkl
+ Nicolas Schiller
+ Andreas Scholz
+ Ralf Zessin
+ ...
+
+Aymargeddon is based on the pbem-game Ragnaroek which was based on the
+board game with the same name. Both games where designed by Benni
+Bärmann (of course with many help of others - some of them mentioned
+here above).
+
--- /dev/null
+Hier stehen Ideen, die bei der Entwicklung von Aymargeddon aufgekommen
+sind und gegen die wir uns entschiedne haben, weil sie das Spiel zu
+kompliziert machen würden.
+
+Trotzdem sind einige davon Wert, aufgehoben zu werden, weil sie
+vielleicht mal für ein zukünftiges auf Aymargeddon basierendes Spiel
+brauchbar sind.
+
+Propheten
+---------
+
+Propheten sind Erdlingseinheiten, die:
+
+ - übers Wasser gehen können
+ - aus einem Priester erzeugt werden, wenn sie einen Bergtempel errichten
+ und dabei ganz alleine sind im Feld.
+ => Es gibt nur maximal zwei (drei) Pro Gott pro Spiel.
+ - Kampfstärke -2
+ - MOVE_MNT: Sie können den eigenen Berg mit den meisten Priestern
+ (ab 3 * FORTUNE) zu sich hin bewegen. Die Priester bleiben zurück.
+ Der Tempel bleibt erhalten
+
+Spione
+------
+
+Spione sind Erdlingseinheiten, die
+
+ - Archen klauen können
+ - sich unsichtbar auf fremdem Territorium aufhalten können
+ - keine Kämpfe auslösen
+ - Schnelligkeit und Kampfkraft wie Krieger
+ - feindliche Spione mit gewisser Wahrscheinlichkeit aufdecken können
+ wenn sie ein Feld betreten => löst Kampf aus.
+ - nur ihr direktes Feld sehen, nicht die Nachbarfelder
+ - den Widerstand in besetzten Heimatstädten organisieren:
+ - die produzierten Krieger alle zu Spionen umwandeln bevor sie
+ kämpfen.
+ - von Erdlingen aus einem oder mehreren
+ Helden und/oder Kriegern erzeugt werden
+ - wenn aus Helden: sterben immer noch für einen Gott
+ - wenn aus Kriegern: aus mehreren, sonst zu billig
+ - die DIE_ORDER des Gegners überschreiben mit der eigenen
+ (Assasinenfertigkeit)
+
+ - Problem: darf niemals send_message_to_field() benutzen
+ - Problem: Sichtrechte. Spioninfos sollten nicht an Alliierte
+ weitergegeben werden.
+
+weitere Ideen:
+--------------
+
+- Strassen: nur auf Stadt und Land (beschleunigen Bewegung _in_ das
+Feld rein), Kosten: sehr lange Bauzeit für einen (oder mehrere)
+Krieger. Anzahl Krieger, die bauen beschleunigt die Bauzeit anteilig.
+
+- ebenso für Burgen: gibt Verteidigungsbonus +2.
+
+- Artefakte: siehe altes Ragnaroek (erstnochmal da nachlesen)
+
+- Anführer: Geben Bonus pro Kämpfer wie Avatare aber bis max. +10.
+Erdlingseinheit. Kann nur aus einem Held und nur in der Heimatstadt
+ausgebildet werden. Ausbildung dauert sehr lange. Max. 1 Anführer pro
+Feld wirksam. Anführer haben keine Bindung mehr zu einem Gott und
+sterben immer als letztes. Geschwindigkeit ist die eines Kriegers.
+
+- zwei Sorten Avatare. Die einen blockieren, die anderen helfen. (Idee
+von Nicki) oder unterschiedilch starke Avatare die bestimmte
+Fähigkeiten erst mit ihrer Stärke kriegen oder auch wieder verlieren.
+Implementierung wäre durch Ausnahme in unify_mobiles() (nur noch
+Individuen) und Verwendung von COUNT für die Stärke möglich.
+
+- Hurrican: Zerstört Tempel (auch Bergtempel!), versenkt Archen,
+verhindert Bewegung. Bewegt sich selbst zufällig. Wird wie Seuchen
+durch Priester "geheilt" ansonsten wütet er ewig weiter. Archen in
+Nachbarfeldern eines Hurricans bewegen sich mit 1ZE.
+
+
+zusätzliche Ebenen
+------------------
+
+Man könnte zusätzlich zu den Ebenen Gott/Erdling noch weitere
+einführen, das macht natürlich die Balance enorm schwierig. Eine neue
+Ebene muss auf alle anderen angewiesen sein und umgekehrt. Jede Ebene
+erhöht die Anzahl der Sieger.
+
+Beispiel:
+
+Ebene Volk (Erdling wird umbenannt in Herrscher)
+
+- hat Bauern, Handwerker und Händler
+
+- Völker können koexistieren im selben Feld
+
+- Volksreligiosität verbreitet sich direkt in Reaktion auf
+Götteraktionen (positive und negative) und ähnlich wie Seuchen.
+Gläubiges Volk gibt Mana, egal wo.
+
+- Erdlinge brauchen Korn, das Bauern produzieren und Händler
+transportieren sowie Dinge, die Handwerker produzieren und Händler
+transportieren.
+
+- Händler bewegen sich so schnell wie Krieger. Bauern gar nicht
+(ausser durch Vermehrung).
+
+- Gewonnen hat, wer am Schluss am meisten Volk hat.
+
+- Volk vermehrt sich im Frieden und verringert sich bei Krieg und
+Seuche. Bei Flut wandern sie in Nachbarfelder.
+
+- Bauern auf Ebenen produzieren Korn. Bauern in Städten können zu
+Händlern werden. Händler auf Landfeldern zu Bauern.
+
+- ... so oder so ähnlich
--- /dev/null
+Diese Datei wird inzwischen im Wiki gepflegt:
+
+http://www.aymargeddon.de/wiki/index.php/TODO
--- /dev/null
+#!/bin/sh
+
+grep $1 src/*.pl src/*.pm src/FROGS/*.pm html/*.epl
--- /dev/null
+# Makefile for Aymargeddon documentation
+# TODO: BUG: macht immer alles (liegt an +* nicht im target)
+
+LYX2HTML = lyx --export html
+LYX2PDF = lyx --export pdf
+FICK2DEATH = fig2dev
+
+INSTALL_SERVER = aymargeddon.de
+INSTALL_DIR = /home/benni/aymargeddon_current/doc/
+
+DIRS =
+FILES_BIN =
+FILES_LIB =
+FILES_DOC = Regeln.lyx Techdoc.lyx ay_ein_hex.fig
+FILES_MISC =
+FILES = Makefile $(FILES_IN) $(FILES_DOC) $(FILES_MISC)
+FILES_OUT = ay_ein_hex.eps Regeln.pdf \
+ Regeln.html Techdoc.pdf Techdoc.html $(FILES_MISC)
+
+
+all: $(FILES_OUT)
+
+#Regeln.html: Regeln.tex
+# $(LATEX2HTML) $(LATEX2HTML_OPT) < Regeln.tex > Regeln.html
+#
+#Techdoc.html: Techdoc.tex
+# $(LATEX2HTML) $(LATEX2HTML_OPT) < Techdoc.tex > Techdoc.html
+
+clean:
+ rm -f $(FILES_OUT)
+ rm -rf Regeln
+ rm -rf Techdoc
+ rm -rf auto
+ rm -f *.aux
+ rm -f *.log
+ rm -f *.ps
+ rm -f *.dvi
+ rm -f *~
+ rm -f *.toc
+ rm -f *.png
+ rm -f *.ps.gz
+ rm -f *.tex
+ rm -f +*
+
+realclean: clean
+
+
+
+#release: clean have_to_make
+# @if [ -z "$(RELDIR)" ] ; then \
+# echo "Sorry, release directory is not set!" 1>&2 ; \
+# exit 1 ; \
+# fi ;\
+# if [ ! -d $(RELDIR) ] ; then mkdir $(RELDIR) ; fi ; \
+# tar cf - $(FILES) | \
+# ( cd $(RELDIR) ; tar xf - )
+# for i in $(DIRS) ; do \
+# ( cd $$i ; \
+# $(MAKE) RELDIR=../$(RELDIR)/$$i $@ ) ; \
+# done
+
+install: all
+
+# hier muss dann das angepasste push-script hin
+
+# @if [ "X$(RELEASE)" = "X" ] ; then \
+# echo "Sorry, this isn't released source" 1>&2 ; \
+# exit 1 ; \
+# fi ;\
+# for i in $(INSTALLDIRS) ; do \
+# if [ ! -d $$i ] ; then mkdir -p $$i ; fi ; \
+# done ;\
+# for i in $(FILES_DOC) ; do \
+# cp $$i $(DOCDIR)/$$i ; \
+# chmod 555 $(DOCDIR)/$$i ; \
+# chown bin:bin $(DOCDIR)/$$i ; \
+# echo "Installed $(DOCDIR)/$$i" ; \
+# done
+# for i in $(DIRS) ; do \
+# ( cd $$i ; ${MAKE} RELEASE=$$RELEASE PREFIX=$(PREFIX) install ) ; \
+# done
+
+# have_to_make:
+
+.SUFFIXES:
+.SUFFIXES: .pdf .lyx .eps .fig .html
+
+.fig.eps:
+ $(FICK2DEATH) -L ps $(FICK2DEATH_OPT) $< +$@
+
+# TeX to DVI
+#.tex.dvi:
+# $(LATEX) $< < /dev/null > /dev/null 2>&1
+# $(LATEX) $< < /dev/null > /dev/null 2>&1
+
+# DVI to PS
+#.dvi.ps:
+# $(DVIPS) -o $@ $<
+
+# PS to PDF
+#.ps.pdf:
+# $(PS2PDF) $< $@
+
+# LyX to TeX
+#.lyx.tex:
+# $(LYX2LATEX) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+# LyX to PDF
+.lyx.pdf:
+ $(LYX2PDF) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+# LyX to HTML
+.lyx.html:
+ $(LYX2HTML) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+
--- /dev/null
+german below!
+
+There is currently no rules or other documentation in english. use the
+sourcecode or ask at the mailinglist, if you want to know something.
+
+------------------------
+
+Die Dateien in diesem Verzeichnis sind nicht auf dem neuesten Stand.
+Die Regeln werden inzwischen im Wiki gepflegt:
+
+http://www.aymargeddon.de/wiki/index.php/Regeln
--- /dev/null
+#LyX 1.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 221
+\textclass article
+\language german
+\inputencoding latin1
+\fontscheme default
+\graphics default
+\paperfontsize 11
+\spacing single
+\papersize a4paper
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 0
+\use_natbib 0
+\use_numerical_citations 0
+\paperorientation portrait
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation indent
+\defskip bigskip
+\quotes_language polish
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+Die letzten Tage von Aymargeddon
+\layout Author
+
+Aymargeddon Development Team
+\layout Date
+
+17.
+ April 2005
+\layout Standard
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+tableofcontents
+\backslash
+newpage
+\end_inset
+
+
+\layout Section
+
+Einleitung
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Es ist nicht leicht, ein Gott zu sein
+\begin_inset Quotes prd
+\end_inset
+
+ (Titel eines Buches der Brüder Strugatzkij)
+\layout Standard
+
+Während in den himmlischen Sphären der entscheidende Kampf zwischen Gut
+ und Böse ausgefochten wird, kämpfen auf Erden Elfen gegen Zwerge, Menschen
+ gegen Halblinge und jeder gegen jeden.
+ Soweit das Fantasy-Klischee.
+ Doch jetzt kommen wir zum Spiel:
+\layout Standard
+
+
+\series bold
+\shape smallcaps
+Die letzten Tage von Aymargeddon
+\series default
+\shape default
+ wird von mindestens acht Spielern gespielt.
+ Höchstens ein Drittel der Spieler übernimmt die Aufgabe eines Gottes.
+ Die restlichen zwei Drittel spielen jeweils ein Volk auf der Erde.
+ Am Ende gibt es zwei Sieger: den himmlischen Sieger, der zwischen den Göttern
+ ermittelt wird, und den Sieger der Erdlinge, den die restlichen Spieler
+ zwischen sich ausmachen.
+\layout Standard
+
+
+\series bold
+Himmlischer Sieger
+\series default
+ist der Gott, der am Ende in der
+\series bold
+letzten Schlacht
+\series default
+ auf der
+\series bold
+Insel des Schicksals
+\series default
+, der
+\series bold
+Aymargeddon,
+\series default
+ am meisten Kräfte auf sich vereinigen kann.
+ Der Ort der letzten Schlacht wird einer von mehreren
+\series bold
+Manapolen
+\series default
+ sein - abgelegene Inseln, auf denen die magischen Kraftlinien zusammenlaufen.
+ In der letzten Schlacht kämpfen die
+\series bold
+Avatare
+\series default
+ der Götter, aber auch die Geister verstorbener
+\series bold
+Helden
+\series default
+ der Erdlinge.
+
+\layout Standard
+
+Der
+\series bold
+Sieger der Erdlinge
+\series default
+ ist der Spieler, der am Ende die meisten
+\series bold
+Städte
+\series default
+ sein eigen nennt.
+
+\layout Standard
+
+Zweite Plätze gibt es weder bei den Göttern noch bei den Erdlingen.
+ Es geht immer um den Kampf ums Ganze, um Alles oder Nichts.
+\layout Standard
+
+Die Interaktion zwischen den beiden Ebenen wird durch
+\series bold
+Priester
+\series default
+ und
+\series bold
+Götteraktionen
+\series default
+ möglich.
+\layout Standard
+
+Das
+\series bold
+Spiel endet,
+\series medium
+ sobald alle
+\series bold
+heiligen Berge
+\series default
+und
+\series bold
+ gesegneten Inseln mit Tempeln
+\series default
+ bebaut
+\series medium
+sind
+\series default
+.
+
+\series medium
+Die Tempel bauen die Erdlinge, Götter können sie nur zerstören.
+
+\layout Standard
+
+Je mehr Priester an einem Tempel
+\series bold
+beten
+\series default
+, um so mehr
+\series bold
+Mana
+\series default
+ erhält der jeweilige Gott und um so mehr Aktionen kann er machen.
+\layout Standard
+
+
+\series bold
+Beide Ebenen
+\series medium
+sind aufeinander angewiesen, da Götter ohne den guten Willen der Erdlinge
+ kein
+\series default
+ Mana und somit keinerlei Macht
+\series medium
+ haben und die Erdlinge die Unterstützung der Götter in ihren irdischen
+ Dingen dringend brauchen.
+ Durch diese enge Verzahnung der beiden Spielebenen ist man immer zu
+\series bold
+Verhandlungen
+\series medium
+ gezwungen.
+\layout Standard
+
+Der
+\series bold
+Glücksfaktor
+\series default
+ wird von den Spielern selbst bestimmt.
+ Kämpfe werden durch einen Zufallswert mitbestimmt.
+ Den Maximalwert des Zufalls (3 - 12) müssen die Götter bestimmen (auch
+ diese Aktion kostet sie natürlich Mana).
+
+\layout Standard
+
+Am
+\series bold
+Schluss
+\series medium
+ ist es vor allem nötig
+\series default
+,
+\series medium
+ einen Partner zu haben, der stark genug ist
+\series default
+,
+\series medium
+ um auch an einem Spielende interessiert zu sein
+\series default
+ oder schwach genug, um sich mit einem hinteren Platz zufrieden zu geben
+\series medium
+.
+ So werden treue Verbündete, mit denen man das ganze Spiel gemeinsam bestritten
+ hat, oft noch einmal kurz vor Schlu
+\series default
+ss
+\series medium
+ fallengelassen.
+\layout Standard
+
+Die
+\series bold
+Erdlinge
+\series medium
+spielen
+\series default
+mit
+\series bold
+Kriegern
+\series default
+, Helden (von Göttern erzeugt) und Priestern.
+ Üblicherweise werden nur die ersten Priester von Göttern erleuchtet, danach
+ machen die Tempel diese Arbeit.
+ Sie können Tempel bauen, Städte erobern und Archen steuern.
+\layout Standard
+
+Die
+\series bold
+Götter
+\series medium
+spielen
+\series default
+ mit ihren Avataren, können aber auch Tempel zerstören, Archen erschaffen,
+ Felder überfluten, Seuchen herbeirufen, Priester und Helden erzeugen und
+ den Glücks
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+-
+\end_inset
+
+fak
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+-
+\end_inset
+
+tor verändern.
+ Doch das alles kostet sie Mana.
+\layout Standard
+
+Die Welt ist in viele kleine sechseckige Spielfelder unterteilt.
+ Die Größe des Spielfeldes wird durch die angestrebte Spieleranzahl bestimmt.
+
+\layout Standard
+
+Gespielt wird über einen üblichen Web-Browser.
+ Es gibt keine Spielrunden, sondern jeder Befehl braucht eine gewisse Zeit,
+ bis er ausgeführt wird.
+ Die Spielgeschwindigkeit kann dabei variieren.
+\layout Standard
+
+An dieser Stelle möchten wir einmal ganz laut und deutlich allen Testspielern
+ des Brettspieles und der Pbem-Version danken, ohne die auch diese Online-Versio
+n nicht möglich geworden wäre!
+\layout Section*
+
+
+\family sans
+\series medium
+\size large
+\emph on
+WARNUNG:
+\layout Standard
+
+
+\family sans
+\emph on
+Sowohl die verschiedenen beteiligten Programme als auch diese Regeln sind
+ noch in einem Test-Stadium.
+ Wir bitten also insbesondere alle Testspieler, uns darauf hinzuweisen,
+ wenn es Unterschiede zwischen diesem Dokument und dem realen Verhalten
+ des Spiels gibt.
+ Außerdem bitten wir Euch, Euch in die Ragnarök-Mailingliste einzutragen
+ (
+\begin_inset Quotes pld
+\end_inset
+
+subscribe ragnaroek
+\begin_inset Quotes prd
+\end_inset
+
+ nach majordomo@cs.uni-frankfurt.de schicken).
+ Helft mit, dass Aymargeddon besser wird! Wer will, kann auch gerne selbst
+ programmieren helfen.
+ Der Quellcode steht in einem tla-Archiv auf www.aymargeddon.de zur Verfügung.
+\layout Section
+
+Die Welt
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wenn man eine Rolle lange genug spielte, vermischten sich langsam Fiktion
+ und Realität...
+ Rache war etwas für Götter.
+\begin_inset Quotes prd
+\end_inset
+
+ (aus:
+\begin_inset Quotes pld
+\end_inset
+
+Ragnarök
+\begin_inset Quotes prd
+\end_inset
+
+ von D.G.Compton und John Gribbin)
+\layout Standard
+
+Die Welt besteht aus Sechsecken und hat keinen Rand.
+ Man kann in jede Richtung laufen und kommt wieder zum Ausgangspunkt zurück
+ (Torus).
+ Hier ein Screenshot vom Hauptbildschirm, damit Ihr eine Vorstellung davon
+ bekommt, wie die Welt aussieht.
+\layout Standard
+\align center
+<BILD FEHLT NOCH>
+\layout Standard
+
+In dieser Welt kann man sich in sechs verschiedene Richtungen bewegen, die
+ man sich folgendermaßen vorstellen kann:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+<BILD KAPUTT>
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Graphics
+ filename +ay_ein_hex.eps
+ display monochrome
+ width 50text%
+
+\end_inset
+
+
+\layout Standard
+
+Jeder Erdling beginnt bei seiner Heimatstadt.
+ Diese ist schwerer zu erobern und produziert mehr Krieger als normale Städte.
+ Jeder Gott hat zwei heilige Berge, an denen nur er angebetet werden kann.
+\layout Standard
+
+Es dürfen immer nur Einheiten von einem Erdling in einem Feld stehen, das
+ somit einen eindeutigen Eigentümer hat.
+ Heimatstädte erinnern sich immer an ihre rechtmäßigen Herrscher.
+ Sie verteidigen sich auch ohne Krieger, und sie gehören einem wieder, sobald
+ die Besatzungsmacht abgezogen ist.
+\layout Standard
+
+Besondere Felder sind die Manapole, zu ihnen strebt das ganze Denken der
+ Götter ihrem Wesen nach.
+ Einer der Manapole ist immer die Insel des Schicksals.
+ Manapole sind immer komplett von Wasserfeldern ohne gesegnete Inseln umgeben.
+\layout Standard
+
+Außerdem gibt es noch Wasser und Inseln.
+ Inseln sind immer gesegnet, man kann dort also immer Tempel bauen, außer
+ es handelt sich um einen Manapol.
+ Über Wasser darf man sich als Erdling nur bewegen, wenn im Ausgangsfeld
+ eine Arche ist.
+ Avatare dürfen sich nur dann über Wasser bewegen, wenn ein Erdling gleichzeitig
+ die Arche steuert.
+ Die Archen bewegen sich mit den Erdlingen mit und haben ein unbegrenztes
+ Fassungsvermögen.
+ Die Götter sind also auf die Mithilfe der Erdlinge angewiesen, wenn sie
+ ihre Avatare in die letzte Schlacht, die auf der Insel des Schicksals stattfind
+et, schicken wollen.
+\layout Standard
+
+Welcher Manapol Aymargeddon ist, ändert sich im Laufe des Spiels.
+ Es ist immer der Manapol, der dem neuesten und schönsten Tempel am nächsten
+ ist.
+ Avatare bewegen sich leichter in Richtung Aymargeddon als von ihr weg.
+ Sie dürfen die Insel des Schicksals nicht verlassen, so lange sie Aymargeddon
+ ist.
+\layout Subsection*
+
+Topologie
+\layout Standard
+
+Felder haben immer zwei Koordinaten.
+ Das Spielfeld hat keinen Rand, wenn man sich in einer Richtung über den
+ vermeintlichen Rand bewegt, kommt man auf der gegenüberliegenden Seite
+ wieder raus.
+ Die folgende Karte mit den Koordinaten der Felder demonstriert das:
+\layout Standard
+\align center
+<BILD FEHLT NOCH>
+\layout Standard
+
+Eine Welt ist immer doppelt so breit wie hoch.
+ Nur so kann man in allen Richtungen immer geradeaus laufen und kommt doch
+ immer wieder am Ausgangspunkt an.
+\layout Subsection*
+
+Produktion
+\layout Standard
+
+Alle Städte erzeugen automatisch in gewissen Zeitabständen Krieger.
+ Heimatstädte erzeugen doppelt so schnell Krieger, sie tun dies manchmal
+ auch, wenn sie das Feld von feindlichen Einheiten besetzt wird, dann kommt
+ es zu Aufständen der heimatlichen Bevölkerung in regelmäßigen Abständen.
+ Normale Städte erzeugen umso häufiger Krieger, je kürzer der Zeitpunkt
+ ihres letzten Besitzerwechsels her ist.
+
+\layout Standard
+
+Tempel erzeugen in gewissen Zeitabständen Priester.
+ Es werden keine Priester erzeugt, wenn nicht schon rechtgläubige Priester
+ dort sind.
+\layout Section
+
+Aktionen
+\layout Standard
+
+Jede Aktion eines Spielers wird sofort in eine Datenbank geschrieben.
+ Die Aktionen werden jedoch erst zu einem späteren Zeitpunkt ausgeführt.
+ Wie lange das dauert, hängt von der Aktion ab (siehe Abschnitt Timing).
+ Einheiten sind wärend dieser Zeit inaktiv.
+\layout Subsection*
+
+Aktionen für alle Spieler
+\layout Subsubsection*
+
+Status ändern
+\layout Standard
+
+Mit dieser Aktion kann man seine generelle Haltung anderen Spielern gegenüber
+ - seien sie Götter oder Erdlinge - ändern.
+ Man kann andere Spieler als Freund, als Feind oder neutral ansehen.
+ Man kann ihnen Sichtrechte gewähren oder sie verweigern.
+
+\layout Standard
+
+Das hat an einigen Stellen Auswirkungen, die dort dann näher beschrieben
+ sind.
+ Zu Spielbeginn ist man allen anderen Spielern gegenüber neutral eingestellt
+ und gewährt ihnen keine Sichtrechte.
+\layout Subsection*
+
+Aktionen der Erdlinge
+\layout Standard
+
+
+\series bold
+Bewegen
+\layout Standard
+
+Dies bedeutet, dass man eine bestimmte Anzahl Krieger, Helden oder Priester
+ in ein Nachbarfeld bewegen will.
+ Dies kann zu Kampfhandlungen führen, wenn sich am Ende des Zuges noch Einheiten
+ anderer Erdlingsspieler auf dem Zielfeld aufhalten.
+
+\layout Standard
+
+Erdlinge können die Manapole nicht betreten.
+ Ihre toten Helden werden automatisch direkt nach einem Kampf zur Aymargeddon
+ transferiert.
+\layout Standard
+
+Helden bewegen sich doppelt so schnell wie Krieger und kämpfen doppelt so
+ gut.
+
+\layout Standard
+
+Wasser- und Inselfelder können nur betreten werden, wenn im Startfeld eine
+ Arche steht, die einen dorthin bringen kann.
+
+\layout Standard
+
+Archen bewegen sich immer automatisch mit Erdlingen mit außer bei der Bewegung
+ zwischen Landfeldern.
+ Wenn Erdlingseinheiten oder Avatare in einem Wasserfeld zurückbleiben,
+ aus dem sich eine Arche entfernt, ertrinken sie jämmerlich.
+ Ertrinkende Helden streiten nicht in der letzten Schlacht, ebensowenig
+ wie ertrinkende Avatare.
+ Auf Inselfeldern können sie jedoch überleben.
+\layout Standard
+
+Das Bewegen von einem Wasser- oder Inselfeld auf ein benachbartes Landfeld
+ ist immer möglich auch ohne Arche.
+
+\layout Standard
+
+Das Bewegen in das Feld eines Alliierten scheitert
+\begin_inset Foot
+collapsed true
+
+\layout Standard
+
+Böse Zungen nennen das die Olf-Bodo-Regel ;-)
+\end_inset
+
+.
+ Ebenso scheitert die Bewegung, wenn im Zielfeld bereits ein Kampf stattfindet
+ an dem ich nicht beteiligt bin.
+ So wird gewährleistet, dass an einem Erdlingskampf immer nur zwei Spieler
+ beteiligt sein können.
+ Das Bewegen scheitert allerdings erst am Schluss der Bewegung.
+ Sie müssen sich dann wieder zurück bewegen.
+
+\layout Standard
+
+Man kann somit fast lückenlos Felder übergeben.
+ Daraus ergibt sich, dass man Alliierte nicht angreifen kann, so lange sie
+ Freunde sind.
+
+\layout Subsubsection*
+
+Tempel bauen
+\layout Standard
+
+Diese Aktion erzeugt auf einem Feld einen Tempel einer Gottheit.
+ Es ist nur möglich, Tempel zu erzeugen, wenn der Spieler mindestens einen
+ Priester der passenden Gottheit dort hat und das Feld ein heiliger Berg
+ oder eine gesegnete Insel ist.
+ Wenn es ein heiliger Berg ist, darf nur ein Tempel des Gottes gebaut werden,
+ dem der Berg gewidmet ist.
+ Auf jedem Feld kann es immer nur einen Tempel geben.
+\layout Standard
+
+Tempel zu bauen geht am Anfang des Spiels recht schnell, dauert aber um
+ so länger, je mehr Tempel schon gebaut sind.
+ Jeder Erdling will schließlich den schönsten Tempel der Welt haben, und
+ das dauert natürlich seine Zeit.
+ Wenn alle Tempel gebaut sind, endet das Spiel sofort.
+
+\layout Standard
+
+Der Manapol, der dem neuesten Tempel am nächsten ist, wird zur Insel des
+ Schicksals.
+ Wenn mehrere Manapole gleich weit entfernt sind, bleibt die aktuelle Aymargeddo
+n bestehen.
+ (noch nicht implementiert)
+\layout Subsubsection*
+
+Schlachtordnung festlegen
+\layout Standard
+
+Erdlinge können angeben in welcher Schlachtordnung ihre Armeen in den Krieg
+ ziehen.
+ Es wird eine Reihenfolge angegeben in der die Einheiten aufgestellt werden.
+ Mit der Reihenfolge kann jeder Erdling angeben, welche eigenen Einheiten
+ in vorderster Front stehen und somit zuerst sterben sollen.
+ So kann man zum Beispiel zuerst Krieger sterben lassen, dann Helden und
+ dann erst die Priester.
+\layout Standard
+
+Die Reihenfolge gilt immer für die ganze Welt.
+\layout Standard
+
+Die voreingestellte Reihenfolge ist: Krieger, Helden, Priester.
+
+\layout Standard
+
+Die Reihenfolge ist allerdings nicht absolut, sondern gibt nur die Wahrscheinlic
+hkeit des Todes an.
+\layout Standard
+
+Archen befinden sich immer in der letzten Reihe der Schlachtordnung.
+ Jede Arche, die
+\begin_inset Quotes pld
+\end_inset
+
+stirbt
+\begin_inset Quotes prd
+\end_inset
+
+ wird mit einer gewissen Wahrscheinlichkeit versenkt und mit einer gewissen
+ Wahrscheinlichkeit vom Gegner erobert.
+\layout Subsection*
+
+Aktionen der Götter
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wenn Dich das nächste Mal jemand fragt, ob Du ein Gott bist, sag ja.
+\begin_inset Quotes prd
+\end_inset
+
+ (aus: Ghostbusters)
+\layout Standard
+
+Alle folgenden Aktionen kosten Mana.
+ Neues Mana erhält ein Gott, wenn seine Priester an den richtigen Tempeln
+ beten.
+ Alle zehn Zeiteinheiten gibt es pro Priester und Tempel einen Manapunkt
+ (MP).
+\layout Subsubsection*
+
+Avatar erschaffen
+\layout Standard
+
+Ein Avatare erscheint immer an dem eigenen Tempel an dem am meisten eigene
+ Priester beten.
+ Ein Avatar kostet 5 MP.
+
+\layout Subsubsection*
+
+Held weihen
+\layout Standard
+
+Ein Krieger kann nur an eigenen Tempeln zum Helden geweiht werden.
+ Das kostet 1 MP.
+\layout Description
+
+Priester
+\series medium
+
+\series bold
+erleuchten
+\layout Standard
+
+Einen Priester kann man nur aus einem Krieger erzeugen, wenn der Gott das
+ entsprechende Feld einsehen kann (siehe Sicht-Abschnitt).
+ Diese Aktion kostet 5 MP.
+
+\layout Subsubsection*
+
+Avatare bewegen
+\layout Standard
+
+Avatare dürfen sich auch auf die Insel des Schicksals begeben (allerdings
+ nicht mehr von ihr weg).
+ Das Bewegen eines Avatars geht deutlich schneller als das Bewegen der Erdlinge
+ (Eine Zeiteinheit).
+ Es kostet immer 1 MP pro Feld und Avatar.
+ Avatare reisen umsonst auf Schiffen mit.
+\layout Standard
+
+Avatare dürfen sich nicht auf Wasser- oder Inselfelder bewegen, ausser mit
+ einer Arche (von Erdlingen gesteuert).
+ Von Wasserfeldern aus, dürfen sie sich auch alleine auf Landfelder oder
+ Manapole bewegen.
+\layout Subsubsection*
+
+Verseuchen
+\layout Standard
+
+Ein Gott kann die Erde mit Seuchen überziehen.
+ Das hat unterschiedliche Auswirkungen je nach Art der Seuche.
+ Seuchen verbreiten sich mit einer gewissen Wahrscheinlichkeit auf Nachbarfelder
+ sowie bei Bewegungen von Erdlingseinheiten.
+ Die Anwesenheit von Priestern erhöht die Wahrscheinlichkeit, dass die Seuche
+ aufhört.
+ Die Kosten für Seuchen hängen von der Art der Seuche ab.
+ Zum Verseuchen benötigt man einen anwesenden Avatar und in dem Feld darf
+ gerade kein Götterkampf (s.u.) stattfinden.
+
+\layout Standard
+
+Verseucht sind immer ganze Felder, keine einzelnen Einheiten.
+ Städte stecken sich leichter an als Landfelder, Landfelder leichter als
+ Berge, Berge leichter als Inseln, Inseln leichter als Wasserfelder.
+\layout Standard
+
+Es gibt zur Zeit drei verschiedene Seuchen:
+\layout Standard
+
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="4" columns="3">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Seuche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Effekt
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Mana
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Influenza
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Städte und Tempel produzieren nicht mehr
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Pestilentia
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+50% aller Leute sterben
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+20
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Ebola
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+100% aller Leute sterben
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Wenn Leute sterben, so geschieht das nach den Regeln bei Erdlingskämpfen
+ (s.u.).
+\layout Standard
+
+Eine Seuche hat alle 20 Zeiteinheiten erneut ihren in der Tabelle beschriebenen
+ Effekt.
+\layout Subsubsection*
+
+Sintfluten
+\layout Standard
+
+Avatare können eine Ebene oder einen Berg überfluten, die an ein Wasser-
+ oder Inselfeld grenzen, wenn sie vor Ort sind und in dem Feld gerade kein
+ Götterkampf(s.u.) stattfindet.
+ Eine Sintflut kostet nur 2 MP, dauert aber 40 Zeiteinheiten.
+ Berge werden durch Überfluten zu Inseln.
+ Dadurch ändert sich ihre Exklusivität, und von nun an können auch andere
+ Götter an ihnen angebetet werden.
+ Städte und Inseln kann man nicht überfluten.
+\layout Standard
+
+Wenn zum Zeitpunkt des Flutens einer Ebene noch Einheiten im Feld sind,
+ benötigen sie eine Arche, um nicht unterzugehen.
+\layout Subsubsection*
+
+Avatarstatus ändern
+\layout Standard
+
+Jede Gruppe von Avataren eines Spielers in einem Feld hat einen Status.
+ Dieser kann
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+,
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ oder
+\series bold
+\shape smallcaps
+Ignorieren
+\series default
+\shape default
+ sein.
+ Mit
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+ hilft man befreundeten Erdlingen, wenn es zu Kämpfen kommt.
+ Mit
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ schlägt man sich mit verfeindeten Avataren, wenn diese ins Feld kommen.
+ Man kann immer nur eines von beidem gleichzeitig tun.
+
+\layout Standard
+
+Sich bewegende Avatare nehmen ihren Status mit.
+ Wenn zwei Gruppen von Avataren des selben Spielers zusammentreffen, wird
+ immer automatisch
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ vor
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+ vor
+\series bold
+\shape smallcaps
+Frieden
+\series default
+\shape default
+ für die neue gemeinsame Gruppe gewählt.
+
+\layout Subsubsection*
+
+Tempel zerstören
+\layout Standard
+
+Götter können den Tempel eines anderen Gottes auf einer gesegneten Insel
+ zerstören.
+ Dort dürfen sich keine Priester eines anderen Gottes befinden, außerdem
+ braucht man einen eigenen Avatar in dem Feld und es darf dort kein Götterkampf
+ (s.u.) stattfinden.
+ Dieser Befehl kostet 5 MP.
+ Wenn nur noch ein Tempelfeld unbebaut ist, kann man keine Tempel mehr zerstören.
+
+\layout Standard
+
+Es gibt im Wesentlichen zwei Anwendungsfälle für diesen Befehl:
+\layout Enumerate
+
+Ein Gott will eine gesegnete Insel übernehmen, damit ein
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+ver
+\backslash
+-bün
+\backslash
+-de
+\backslash
+-ter
+\end_inset
+
+ Erdling ihm dort einen Tempel errichtet.
+ Dafür muss der alte Tempel zerstört werden.
+
+\layout Enumerate
+
+Ein Gott will das drohende Spielende hinauszögern, weil er für später bessere
+ Siegchancen sieht.
+ Danach sollte man Erdlinge dazu überreden, das leere Baufeld auch zu verteidige
+n.
+ Wenn jedoch einmal der Baubefehl für den letzten Tempel gegeben ist, ist
+ es zu spät, das Ende der Welt noch aufzuhalten.
+\layout Subsubsection*
+
+Glücksfaktor verändern
+\layout Standard
+
+Mit diesem Befehl kann man angeben, ob man den globalen
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+Glücks
+\backslash
+-fak
+\backslash
+-tor
+\end_inset
+
+, der auf alle Kämpfe mit Ausnahme der letzten Schlacht angewandt wird,
+ erhöhen oder erniedrigen will.
+ Man gibt an, wie viele Manapunkte man investieren will.
+ Pro MP ändert sich der Glücksfaktor um einen Punkt auf einer Skala von
+ 3 bis 12.
+\layout Standard
+
+Der Glücksfaktor ist immer für alle Spieler gleich hoch, es gibt also nur
+ einen Glücksfaktor für alle Spieler.
+\layout Subsubsection*
+
+Arche bauen
+\layout Standard
+
+Ein Gott kann auf einem Feld, dass er sieht, eine Arche bauen.
+ Steuern kann er sie nicht.
+ Die Arche gehört dem derzeitigen Feldeigentümer.
+\layout Standard
+
+Eine Arche zu bauen kostet 5 MP und dauert 30 Zeiteinheiten.
+\layout Section
+
+Beten
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wer Gott definiert, ist schon Atheist.
+\begin_inset Quotes prd
+\end_inset
+
+ (Oswald Spengler)
+\layout Standard
+
+Die Götter erhalten alle 10 Zeiteinheiten einen MP pro Tempel und pro rechtgläub
+igem Priester an diesem Tempel ebenso ein MP.
+ Die Anzahl effektiv betender Priester pro Tempel ist allerdings auf den
+ aktuellen Glücksfaktor begrenzt.
+ An heiligen Bergen können doppelt so viele Priester effektiv beten.
+\layout Section
+
+Infos
+\layout Standard
+
+Folgende generelle Daten sind für alle Mitspieler jedezeit abrufbar.
+ Sie beziehen sich auf das ganze Spiel und nicht auf einzelne Felder.
+
+\layout Itemize
+
+Der aktuelle Glücksfaktor
+\layout Itemize
+
+Die Anzahl nicht gebauter Tempel
+\layout Itemize
+
+Die Stärke auf der Insel des Schicksals
+\layout Itemize
+
+Die Anzahl der Avatare auf den Manapolen (noch nicht implementiert)
+\layout Itemize
+
+Die Gesamtstärke jeden Erdlings (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl der lebenden Avatare jedes Gottes (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl der Priester jedes Gottes (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl Städte jedes Erdlings
+\layout Standard
+
+Dadurch kann man immer die Stärke eines anderen Spielers ungefähr einordnen
+ und sieht, wer auf dem Weg zum Sieg ist.
+\layout Standard
+
+Erdlinge sehen außerdem noch die Sterbereihenfolge ihrer Einheiten.
+ Götter sehen ihren aktuellen Manastand.
+\layout Subsection*
+
+Sichtrechte
+\layout Standard
+
+Sichtrecht hat man für folgende Felder:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="3" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Götter
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Erdlinge
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+eigene Holys
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Heimatstädte
+\end_inset
+</cell>
+</row>
+<row bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+anwesende Priester oder Avatare
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+anwesende Priester, Krieger oder Helden
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Von Bergen aus sieht man zwei Felder weit, sonst nur eins.
+\layout Standard
+
+Andere Spieler können einem Sichtrechte gewähren.
+ Dies tun sie durch den Allianzstatus
+\begin_inset Quotes pld
+\end_inset
+
+Alliiert
+\begin_inset Quotes prd
+\end_inset
+
+ oder
+\begin_inset Quotes pld
+\end_inset
+
+Verrat
+\begin_inset Quotes prd
+\end_inset
+
+.
+
+\begin_inset Quotes pld
+\end_inset
+
+Freund
+\begin_inset Quotes prd
+\end_inset
+
+ gewährt keine Sichtrechte.
+\layout Standard
+
+Als anwesend zählen auch nicht-aktive Einheiten (die sich zum Beispiel gerade
+ in der Bewegung befinden).
+\layout Standard
+
+Wenn man Sichtrecht für ein Feld hat, kann man jederzeit die Infos zu diesem
+ Feld abrufen.
+\layout Section
+
+Kampf
+\layout Standard
+
+Götter können Erdlinge nicht direkt attackieren, sie können nur andere Erdlinge
+ bei diesen Angriffen unterstützen.
+
+\layout Standard
+
+Bei jedem Kampf außer der letzten Schlacht werden die Kampfstärken der beteiligt
+en Einheiten addiert und zusätzlich ein Zufallswert zwischen eins und dem
+ Glücksfaktor dazugezählt.
+
+\layout Standard
+
+Jeder Kampf dauert eine gewisse Zeitspanne.
+ Alle in dieser Zeitspanne hinzustoßenden Einheiten nehmen am Kampf teil
+ oder werden vom Kampf ausgeschlossen.
+ In letzterem Fall kehren sie einfach wieder um.
+\layout Subsection*
+
+Erdlingskampf
+\layout Standard
+
+Ein Erdlingskampf wird ausgelöst, wenn Einheiten eines neutralen oder verfeindet
+en Erdlings - im Folgenden Angreifer genannt - ein Feld betreten, dessen
+ Eigentümer im Folgenden Verteidiger genannt wird.
+ Alle Einheiten dieser beiden Parteien, die wärend der Kampfdauer zum Kampf
+ dazu stoßen, nehmen am Kampf teil.
+ Einheiten Dritter werden vom Kampf ausgeschlossen.
+ Eine Möglichkeit, sich aus einem einmal begonnenen Kampf herauszuhalten,
+ gibt es nicht.
+\layout Standard
+
+Die Kampfstärke beider Seiten ergibt sich aus der Summe der Kampfstärken
+ der beteiligten Einheiten.
+ Beide Seiten eines Kampfes addieren einen Zufallswert, der zwischen 1 und
+ dem aktuellen Glücksfaktor liegt, zu ihrer Kampfstärke.
+
+\layout Standard
+
+Dem bisherigen Eigentümer reicht ein Unentschieden zum Sieg.
+
+\layout Standard
+
+Eine Partei, die einen Kampf verliert, muss ihre Überlebenden zurückziehen.
+ Alle Einheiten ziehen sich einzeln zurück.
+
+\layout Standard
+
+Dazu wird nach dem Zufallsprinzip eines der Nachbarfelder ausgewählt, das
+ dem Verlierer gehört oder neutral ist und in dem zum Zeitpunkt des Rückzuges
+ kein Kampf stattfindet.
+ Ein Rückzug ist wie eine normale Bewegung und braucht Zeit.
+ Archen ziehen sich immer zuerst zurück.
+ Archen auf Küstenfeldern können sich nur auf Wasser oder Inselfelder zurückzieh
+en.
+ Andere Einheiten können sich nur auf Landfelder zurückziehen oder auf solche,
+ auf die sich bereits Archen zurückgezogen haben.
+\layout Standard
+
+Es kann passieren, dass das Feld bei Ankunft der Flüchtenden auch schon
+ einem anderen Spieler gehört, dann kommt es dort direkt wieder zum Kampf.
+ Flüchtende Einheiten können also von Feld zu Feld gejagt und dabei aufgerieben
+ werden.
+ Ein gut geplanter Angriff auf breiter Front kann diese Regel bewusst ausnutzen.
+\layout Standard
+
+Natürlich kann man beim Kämpfen auch zu schaden kommen: Der Verlierer verliert
+ die Hälfte der Kampfstärke des Gewinners (ohne Avatare und Flankierung)
+ an Leuten.
+ Der Gewinner verliert ein Viertel der Kampfstärke des Verlierers.
+ Der Gewinner behält mindestens eine Person (oder Arche), der Verlierer
+ verliert mindestens eine.
+ Die Schlachtordnung bestimmt wieviele Leute welcher Art anteilig sterben.
+\layout Standard
+
+Sollte ein Spieler nach einem verlorenen Kampf keinerlei Rückzugsmöglichkeiten
+ mehr haben, sterben alle seine Einheiten in diesem Feld.
+
+\layout Standard
+
+Doch jetzt endlich zu den Kampfstärken:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Einheit
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Modifikator
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++0
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Held
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++2
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+bis zu +4
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Heimatstadt
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++2
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Arche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++3
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+pro Flankierung
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Dabei ist +0 nicht so sinnlos, wie es auf den ersten Blick aussieht: Sind
+ nur Prieser anwesend, können sie wenigstens auf ihr Würfelglück hoffen,
+ wenn sie angegriffen werden und tragen zur Avatarunterstützung bei, wenn
+ diese vorhanden ist.
+\layout Standard
+
+Avatare kämpfen natürlich nur mit, wenn sie im Status
+\begin_inset Quotes pld
+\end_inset
+
+Helfe
+\begin_inset Quotes prd
+\end_inset
+
+ sind, und Mannapunkte übrig haben (2 MP pro Kampf unabhängig von der Anzahl
+ Avatare).
+ Sie geben maximal 4 Punkte Bonus.
+ Dabei wird pro kämpfendem Erdling ein Punkt verbraucht (egal ob Krieger,
+ Held oder Priester).
+
+\layout Standard
+
+Den Flankierungsbonus erhält man für jedes benachbarte Feld, das folgende
+ Bedingungen erfüllt:
+\layout Itemize
+
+Es muss einem selbst oder einem Spieler mit dem Status
+\begin_inset Quotes pld
+\end_inset
+
+Freund
+\begin_inset Quotes prd
+\end_inset
+
+ oder
+\begin_inset Quotes pld
+\end_inset
+
+alliiert
+\begin_inset Quotes prd
+\end_inset
+
+ gehören;
+\layout Itemize
+
+der Eigentümer des Feldes muss zum Zeitpunkt des Kampfes noch aktive Einheiten
+ dort stehen haben;
+\layout Itemize
+
+es darf nicht selbst umkämpft sein.
+
+\layout Itemize
+
+Es darf kein Wasserfeld sein.
+ Inseln flankieren aber ganz normal.
+\layout Standard
+
+Dadurch kann man Gebiete, die aus zusammenhängenden benachbarten Feldern
+ bestehen, besser verteidigen.
+\layout Subsection*
+
+Avatarkampf
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Jetzt hast Du, tapferer Soldat, jetzt hast Du, streitbarer Mann, einen Ort,
+ wo Du ohne Gefahr kämpfen kannst, wo der Sieg Ruhm und der Tod Gewinn ist.
+\begin_inset Quotes prd
+\end_inset
+
+ (Bernhard von Clairveaux, 1146 n.u.Z., zum zweiten Kreuzzug aufrufend)
+\layout Standard
+
+Avatare haben immer einen von drei Zuständen.
+ Mit
+\begin_inset Quotes pld
+\end_inset
+
+Helfe
+\begin_inset Quotes prd
+\end_inset
+
+ helfen sie Erdlingen, wie oben angesprochen.
+ Mit
+\begin_inset Quotes pld
+\end_inset
+
+Block
+\begin_inset Quotes prd
+\end_inset
+
+ blockieren sie andere Avatare, um gegen sie zu kämpfen.
+ Ist ihr Zustand
+\begin_inset Quotes pld
+\end_inset
+
+Ignoriere
+\begin_inset Quotes prd
+\end_inset
+
+, wollen sie mit niemandem Streit.
+ Die Avatare eines Gottes in einem Feld können nur den gleichen Zustand
+ haben.
+
+\layout Standard
+
+Nur der Status
+\begin_inset Quotes pld
+\end_inset
+
+Block
+\begin_inset Quotes prd
+\end_inset
+
+ kann zu Avatarkämpfen führen.
+ Dies geschieht, wenn
+\layout Itemize
+
+einer der beiden den anderen als Feind betrachtet und er oder der andere
+ 'Blockieren' eingestellt hat, oder
+\layout Itemize
+
+wenn zwei Götter aufeinander treffen, die einander beide 'Neutral' gegenübersteh
+en aber beide 'Blockiere' eingestellt haben.
+\layout Standard
+
+Zu Kämpfen kann es nur dann kommen, wenn Avatare in ein Feld ziehen oder
+ wenn der Avatarstatus auf blockieren geändert wird.
+ Für jeden schon anwesenden Gott wird einzeln ermittelt, ob es zu einem
+ Kampf mit dem Neuankömmling kommt.
+ Es kann dabei durchaus zu mehreren parallel verlaufenden Kämpfen kommen,
+ die auch im Folgenden einzeln abgewickelt werden.
+ Wenn ein Avatar in ein Feld kommt, in dem er schon vertreten ist, löst
+ das nie einen Kampf aus.
+\layout Standard
+
+Avatarkämpfe kosten 2 MP unabhängig von der Anzahl der beteiligten Avatare.
+ Wenn ein Gott nicht mehr genügend MP hat, darf der Gott noch auf sein Würfelglü
+ck hofen, aber seine Avatare kämpfen nicht mehr mit.
+\layout Standard
+
+Avatarkämpfe dauern länger als die Kämpfe der Erdlinge; und da Avatare sehr
+ schnell sein können, kann man eventuell auch noch aus einiger Entfernung
+ Kräfte hinzuziehen.
+ Man darf Avatare nicht aus einem umkämpften Feld wegziehen, auch wenn man
+ an keinem der Kämpfe beteiligt ist.
+
+\layout Standard
+
+Sollte im selben Feld bereits ein Erdlingskampf stattfinden, so wird der
+ Avatarkampf bis nach dem Erdlingskampf verschoben.
+
+\layout Standard
+
+Jeder Avatar zählt +4, und es wird ganz normal gewürfelt.
+ Der Verlierer verliert die Hälfte der Avatare des Gewinners und der Gewinner
+ verliert ein Viertel der Avatare des Verlierers.
+ Bei einem unentschieden gelten beide Seiten als Verlierer.
+ Die Seelen sterbender Avatare fahren in eventuell anwesende Krieger des
+ Feldeigentümers und machen diese zu Helden.
+ Alle Avatare des Verlierers die danach noch im Feld sind werden an den
+ Ort der Avatarerschaffung zurückteleportiert.
+\layout Standard
+
+Avatare, die in einem Götterkampf beschäftigt sind, dürfen keine Erdlinge
+ bei ihren Kämpfen unterstützen.
+\layout Subsection*
+
+Die letzte Schlacht
+\layout Standard
+
+In der letzten Schlacht wird nicht gewürfelt.
+ Es zählen nur die Kampfwerte:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="3" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Einheit
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Kampfwert
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++7
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Geist eines Helden
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Für die Geister der Helden zählt der angebetete Gott.
+ Diese Helden kämpfen also immer noch für ihren Gott, auch wenn der Erdling
+ inzwischen längst vom Glauben abgefallen ist.
+\layout Section
+
+Timing
+\layout Standard
+
+Alle Aktionen dauern unterschiedlich lange.
+ Dabei gibt es in jedem Spiel eine einstellbare Spielgeschwindigkeit, mit
+ der die Werte unten multipliziert werden.
+ Die Zahlen in der Tabelle können also sowohl Minuten als auch Tage meinen,
+ je nachdem wie schnell man spielt.
+ Die Spielgeschwindigkeit kann sich auch während eines Spieles ändern.
+ Es kann zum Beispiel sinnvoll sein, das Spiel am Anfang langsamer laufen
+ zu lassen, bis eine angemessene Anzahl Mitspieler eingestiegen ist.
+ Jede Änderung der Spielgeschwindigkeit wird rechtzeitig vorher bekannt
+ gegeben und sollte nicht zu apprupt erfolgen.
+\layout Standard
+
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="17" columns="2">
+<features islongtable="true">
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Aktion
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Dauer
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+12
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Held bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Erdlingskampf
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatarkampf
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tempel bauen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+3, 6 , 9, ...
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Überfluten
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+20
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Bewegen mit Arche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger produzieren
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40 + N (20)
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester produzieren
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Glücksfaktor verändern
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatarstatus ändern
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Arche bauen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+30
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Beten
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+alle anderen Aktionen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+0
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+medskip
+\end_inset
+
+
+\layout Section
+
+Spielanfang
+\layout Standard
+
+Die Götter starten mit 33 Mana.
+ Sie sollten daher zusehen, dass sie möglichst bald Priester erzeugen, damit
+ diese Tempel bauen können, die wieder Priester produzieren und damit wieder
+ Mana.
+ Dafür ist eine Kooperation mit mindestens einem Erdling nötig.
+\layout Standard
+
+Die Erdlinge stehen am Anfang vor der Entscheidung, wo sie ihre ersten Krieger
+ hinschicken sollen.
+ Dies kann zum Beispiel auf ein Tempelfeld sein, weil man davon ausgeht,
+ dass der Krieger in einen Priester umgewandelt wird.
+ Außerdem ist es ratsam, sich früh mit seinen Nachbarn abzusprechen, wer
+ welchen Tempel baut.
+ Ansonsten kann es zu unliebsamen Überraschungen kommen, die einen gleich
+ die ersten Krieger verlieren lassen!
+\layout Standard
+
+Der Glücksfaktor ist am Anfang auf seinem Minimalwert von 3.
+\layout Standard
+
+Götter, die nachträglich einsteigen, erhalten etwas Bonusmana pro vergangener
+ Zeiteinheit.
+ Erdlinge, die neu einsteigen, profitieren davon, dass ihre Heimatstadt
+ schon die ganze Zeit Krieger produziert hat.
+\layout Section
+
+Spielende (nur teilweise implementiert)
+\layout Standard
+
+Das Spiel endet, sobald alle Tempel gebaut wurden.
+ Mit dem Baubefehl des letzten Tempels wird allen Spielern bekanntgegeben,
+ wie lange das Spiel noch dauert.
+ Dann gibt es kein Zurück mehr.
+\layout Standard
+
+Es gewinnt der Erdling, der die meisten Städte sein eigen nennt.
+ Dabei zählen besetzte feindliche Heimatstädte und verseuchte Städte mit.
+ Bei gleicher Anzahl Städte entscheidet die Gesamtkampfstärke des Erdlings.
+ Sollte die auch gleich sein, wird gewürfelt.
+
+\layout Standard
+
+Der Gott, der in der letzten Schlacht die meisten Kräfte auf sich vereint,
+ gewinnt.
+ Dabei muss kein Mana mehr ausgegeben werden und es wird auch nicht mehr
+ gewürfelt.
+ Sollte die letzte Schlacht unentschieden ausgehen, zählen die Anzahl lebender
+ Avatare.
+ Wenn diese auch gleich sind, die Anzahl der Tempel.
+ Wenn dann immer noch Gleichstand herrscht, zählt das übrige Mana.
+ Sollte wider erwarten selbst dieses gleich sein, wird am Ende doch noch
+ gewürfelt.
+\layout Standard
+
+Alle Spieler erhalten zum Abschluss eine Rangliste und den Ausgang der letzten
+ Schlacht.
+\layout Standard
+
+Mit jedem Spiel kann man Punkte für die ewige Bestenliste sammeln, allerdings
+ nur als Sieger.
+ Zweite Plätze zählen nicht.
+\layout Section
+
+FAQ
+\layout Subsection*
+
+Was bedeutet
+\shape italic
+Aymargeddon
+\shape default
+?
+\layout Standard
+
+Der Name des Spiels leitet sich von
+\shape italic
+Armageddon
+\shape default
+ her.
+ Das wiederum basiert auf dem hebräischen
+\shape italic
+Har
+\shape default
+, was
+\shape italic
+Berg
+\shape default
+ bedeutet, und der Ortschaft
+\shape italic
+Megeddon
+\shape default
+, bei der laut der Sage die letzte Schlacht geschlagen werden wird.
+ Da in unserem Spiel die letzte Schlacht auf einer Insel stattfindet, haben
+ wir
+\shape italic
+Har
+\shape default
+ durch
+\shape italic
+Ay
+\shape default
+ ersetzt, was
+\shape italic
+Insel
+\shape default
+ bedeutet.
+
+\layout Standard
+
+Das
+\begin_inset Quotes pld
+\end_inset
+
+r
+\begin_inset Quotes prd
+\end_inset
+
+ gehört da nicht wirklich hin, nein.
+ Aber wir haben das erst entdeckt, als wir die Domain schon bestellt hatten
+ und es klingt eh besser so, oder? Ausserdem gibt
+\begin_inset Quotes pld
+\end_inset
+
+Aymageddon
+\begin_inset Quotes prd
+\end_inset
+
+ unanständige Suchergebnisse bei Google.
+\layout Subsection*
+
+Heißt es
+\shape italic
+der
+\shape default
+,
+\shape italic
+die
+\shape default
+, oder
+\shape italic
+das
+\shape default
+ Aymargeddon?
+\layout Standard
+
+Kommt darauf an.
+\layout Standard
+
+Wenn die Insel des Schicksals gemeint ist, heißt es
+\shape italic
+die
+\shape default
+, wenn das Spiel gemeint ist, heißt es
+\shape italic
+das
+\shape default
+ und wenn der Server gemeint ist, heiß es
+\shape italic
+der
+\shape default
+ Aymargeddon.
+\layout Standard
+
+Das ist allerdings nur die Erdlingssicht.
+ Götter geben sich mit solch kleinlichen Geschlechterfragen nicht ab, wenn
+ es um Schicksalsfragen wie das Ende der Welt geht.
+\layout Subsection*
+
+Gibt es Vorläufer zu Aymargeddon?
+\layout Standard
+
+Das Spiel basiert auf einem - leider noch unveröffentlichten - Brettspiel
+ namens
+\shape italic
+Ragnarök
+\shape default
+ beziehungsweise dem zugehörigen Play-by-E-Mail
+\shape italic
+Ragnarök als Pbem
+\shape default
+.
+ Beide Spiele hat Benni Bärmann entwickelt.
+ Die grundlegenden Konzepte sind erhalten geblieben.
+ Aber natürlich erforderte der geänderte Zugrhythmus und die höhere Spieleranzah
+l einige Anpassungen.
+\layout Subsection*
+
+Wie viel Zeit braucht Aymargeddon?
+\layout Standard
+
+Das hängt von der Spielgeschwindigkeit ab.
+
+\layout Standard
+
+Bei niedriger Spielgeschwindigkeit braucht man sich nur gelegentlich einzuloggen
+, um zu gucken, was es Neues gibt.
+ Dafür kann sich ein Spiel dann auch schon mal ein paar Monate hinziehen.
+
+\layout Standard
+
+Bei hoher Spielgeschwindigkeit sitzt man mehr oder weniger die ganze Zeit
+ vorm Rechner, dafür ist es dann aber auch nach ein paar Stunden vorbei.
+\layout Standard
+
+Bei gleicher Spielgeschwindigkeit ist das Spiel als Gott tendenziell aufwendiger
+ als das als Erdling.
+ Als Erdling kann man fast sicher sein, nichts wichtiges zu verpassen, wenn
+ man sich so oft einloggt, wie ein Erdlingskampf dauert.
+\layout Subsection*
+
+Was brauche ich, um mitspielen zu können?
+\layout Standard
+
+Eigentlich nichts, außer einer funktionierenden E-Mail-Adresse und einem
+ üblichen Web-Browser.
+\layout Standard
+
+Was man natürlich auch noch braucht, sind Spaß am Spiel, Verhandlungsgeschick,
+ etwas Zeit und ein bisschen Glück.
+\layout Subsection*
+
+Wie sehen sinnvolle erste Züge als Erdling aus?
+\layout Standard
+
+Man sollte sich auf jeden Fall möglichst bald mit den Göttern absprechen,
+ deren heilige Orte man sieht, beziehungsweise auf die Suche nach solchen
+ Orten gehen.
+ Danach sollte man möglichst Tempel bauen für die Götter, damit diese schnell
+ Mana kriegen, mit dem sie einen dann (hoffentlich) unterstützen.
+\layout Standard
+
+Dabei ist es ratsam, auch die irdischen Nachbarn nicht zu vernachlässigen
+ und dafür zu sorgen, dass sie nicht in der Zwischenzeit alle strategisch
+ wichtigen Punkte unter sich aufteilen.
+\layout Standard
+
+Wenn man erste Städte erobert hat, muß man sich überlegen ob man sofort
+ weiterzieht oder erst abwartet, bis dort ein Krieger erzeugt wird.
+ Im ersten Fall kommt man schneller voran und kann vieleicht weitere Städte
+ vor den Nachbarn erreichen, im zweiten Fall produziert man schneller neue
+ Krieger.
+\layout Subsection*
+
+Wie sehen sinnvolle erste Züge als Gott aus?
+\layout Standard
+
+Ein Gott sollte am Anfang hauptsächlich durch Verhandlungen abklären, welche
+ Erdlinge ihm möglichst bald Tempel auf seinen exklusiven heiligen Bergen
+ errichten.
+
+\layout Standard
+
+Bald kann man dann schon Avatare und möglicherweise sogar Helden erzeugen
+ und kriegt neues Mana.
+
+\layout Standard
+
+Es kann sinnvoll sein, die wertvollen Tempel mit Avataren zu schützen, damit
+ nicht kleinliche Streitereien zwischen Erdlingen den wertvollen Manastrom
+ verringern.
+\layout Subsection*
+
+Können Erdlingsarmeen aneinander vorbeilaufen?
+\layout Standard
+
+Ja.
+
+\layout Subsection*
+
+Gibt es nicht zu unausgewogene Startpositionen?
+\layout Standard
+
+Gerade die Unausgewogenheit der Startpositionen zwingt zu Verhandlungen.
+ Deswegen werden die dafür relevanten Informationen (mit denen die Spieler
+ abschätzen können, wer führt) ja auch zur Verfügung gestellt.
+\layout Subsection*
+
+Was passiert, wenn jemand aufhört?
+\layout Standard
+
+Seine Einheiten bleiben einfach da stehen, wo sie sind, und rühren sich
+ nicht.
+ Krieger und Priester eines ausgestiegenen Erdlings werden aber noch weiterhin
+ erzeugt.
+
+\layout Standard
+
+Bei Göttern ist das lästiger als bei Erdlingen, da das Spielgleichgewicht
+ stärker beeinträchtigt wird.
+ Schön ist es natürlich in keinem Fall.
+
+\layout Standard
+
+Nichtaktive Spieler können jederzeit übernommen werden von Neueinsteigern.
+
+\layout Subsection*
+
+Was passiert, wenn ich eine Weile nicht ziehe?
+\layout Standard
+
+Wenn das lange dauert, geht der Server davon aus, dass Du nicht mehr spielen
+ willst, und gibt Deine Einheiten zur Übernahme frei.
+ (noch nicht implementiert)
+\layout Subsection*
+
+Soll ich einen Gott oder einen Erdling spielen?
+\layout Standard
+
+Die Götterrolle ist die anspruchsvollere.
+ Man muß mehr verhandeln und hat mehr Möglichkeiten.
+ Das ist Vor- und Nachteil zugleich.
+ Ganz ohne Verhandlung wird man Aymargeddon nicht gewinnen können, aber
+ Leute, die nicht allzusehr auf Verhandlungen aus sind, sollten lieber eine
+ Erdlingsrolle übernehmen.
+ Man sollte auch nur einen Gott spielen, wenn man häufig online ist, da
+ Götteraktionen im allgemeinen weniger Zeit brauchen.
+\layout Standard
+
+Beim Spielanfang kann man auch
+\begin_inset Quotes pld
+\end_inset
+
+egal
+\begin_inset Quotes prd
+\end_inset
+
+ als gewünschte Rolle angeben.
+ Dann gibt einem der Server die Rolle, die dafür sorgt, dass das Zahlenverhältni
+s 1:2 von Göttern zu Erdlingen annähernd erreicht wird.
+ Es kann auch vorkommen, dass in einem Spiel gar keine Erdlinge beziehungsweise
+ Götter mehr zugelassen sind, weil zu weit vom idealen Verhältnis abgewichen
+ wurde.
+\layout Subsection*
+
+Gehören Städte, die ich einmal in Besitz genommen habe, mir auch noch, wenn
+ ich sie wieder verlasse?
+\layout Standard
+
+Nein.
+ Alle Städte, die keine Heimatstädte sind, werden neutral, sobald kein aktiver
+ Priester, Krieger oder Held mehr in ihnen steht.
+ Heimatstädte gehören dem Spieler, dessen Heimat sie sind, jedoch auch,
+ wenn keine Einheiten dort stehen.
+ Heimatstädte verteidigen sich auch, ohne dass in ihnen Einheiten stehen
+ müssen.
+\layout Subsection*
+
+Darf man mehrere Positionen im selben Spiel besetzen?
+\layout Standard
+
+Nein, aber man darf in mehreren Spielen gleichzeitig mitspielen.
+\layout Subsection*
+
+Warum sind Avatare wasserscheu?
+\layout Standard
+
+Ist ja eigentlich schon etwas komisch, wo sie doch ansonsten so mächtig
+ sind.
+ Die Erklärung ist ganz einfach: Auf ihrer Reise zur Erde mussten sie entweder
+ in einem furchtbaren Gewitter auf einer Bergspitze erscheinen oder sich
+ von einer Insel ans nahe, rettende Ufer quälen.
+ Nach dieser Erfahrung hat niemand mehr Lust auf Wasser!
+\layout Section*
+
+Copyright
+\layout Standard
+
+(c) 2003, 2004, 2005 Aymargeddon Development Team
+\layout Standard
+
+Permission is granted to copy, distribute and/or modify this document under
+ the terms of the GNU Free Documentation License, Version 1.1 or any later
+ version published by the Free Software Foundation; with no Invariant Sections,
+ with no Front-Cover Texts, and with no Back-Cover Texts.
+ A copy of the license is available at http://www.aymargeddon.de.
+\the_end
--- /dev/null
+#LyX 1.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 221
+\textclass article
+\language english
+\inputencoding auto
+\fontscheme default
+\graphics default
+\paperfontsize default
+\spacing single
+\papersize Default
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 0
+\use_natbib 0
+\use_numerical_citations 0
+\paperorientation portrait
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation indent
+\defskip medskip
+\quotes_language english
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+Technisches zu
+\begin_inset Quotes eld
+\end_inset
+
+Die letzten Tage von Aymargeddon
+\begin_inset Quotes erd
+\end_inset
+
+
+\layout Author
+
+Aymargeddon Development Team
+\layout Date
+
+9.10.2003
+\layout Standard
+
+
+\emph on
+Warnung: Die Information in diesem Dokument ist zu nicht unerheblichen Teilen
+ veraltet.
+\layout Section
+
+Generelles Design
+\layout Standard
+
+Das Spiel besteht aus folgenden Komponenten:
+\layout Enumerate
+
+Eine Relationale Datenbank
+\layout Enumerate
+
+Ein Dämonprozess im Server
+\layout Enumerate
+
+Serverseitige Scripten zur Benutzerinteraktion
+\layout Enumerate
+
+Ein Weltengenerator
+\layout Enumerate
+
+FROGS
+\layout Enumerate
+
+Ein Programm, dass die Integrität der Datenbank überprüft
+\layout Enumerate
+
+Eine Bibliothek für gemeinsame Funktionalität
+\layout Standard
+
+Die Aufgaben dieser Komponenten stellen sich wie folgt dar:
+\layout Section
+
+Datenbank
+\layout Standard
+
+In dieser Datenbank wird der Zustand aller Spielwelten gespeichert.
+ Außerdem alle Spielerdaten, alle Spieleraktionen und alle Nachrichten an
+ Spieler.
+ Sie sorgt mittels ihrer Transaktionen dafür, dass auch bei konkurierendem
+ Zugriff die Datenintegrität immer erhalten bleibt.
+\layout Standard
+
+Wir verwenden MySQL zur Implementierung und PhpMyAdmin zur Administrierung
+ der Datenbank.
+\layout Standard
+
+Felder, die in vielen Tabellen vorkommen und immer wieder das selbe bedeuten:
+\layout Description
+
+GAME Das ist die Id des Spiels.
+ Dadurch können alle Spiele in der selben Datenbank verwaltet werden.
+ Es kann maximal max(unsigned smallint) Spiele gleichzeitig geben.
+\layout Description
+
+LOCATION Feldkoordinaten auf dem Hexraster-Torus.
+ Ein String der Form <x>_<y>.
+ Die maximale Größe der Welt ist max(unsigned smallint) für die Y-Koordinate
+ und max(unsingend smallint)*2 für die X-Koordinate.
+\layout Description
+
+PLAYER,OWNER,...
+ Spieler-Ids.
+ Die Spieler-Ids bezeichnen den Spieler
+\emph on
+unabhängig
+\emph default
+von seiner Rolle.
+ Sie gilt spielübergreifend.
+ Die maximale Anzahl Spieler ist auf max(signed smallint) beschränkt.
+\layout Subsection
+
+Bewegung und Kämpfe
+\layout Standard
+
+Einheiten, die sich bewegen, bleiben im Feld stehen, werden aber auf nicht
+ available gesetzt.
+ Am Ende des Befehls werden sie in das neue Feld gesetzt.
+ Sie werden nur wieder aktiv, nachdem alle denkbaren Kämpfe ausgeführt wurden.
+\layout Standard
+
+Kämpfe werden als Quasi-Befehl wieder in die Befehlsqueu geschrieben.
+ Erst nach Ablauf dieses Quasi-Befehls wird ausgewertet, welche Einheiten
+ auf welcher Seite am Kampf teilnehmen.
+\layout Standard
+
+Einheiten, die sich zurückziehen, werden ganz normal bewegt.
+\layout Subsection
+
+Tabelle MAP
+\layout Standard
+
+Das ist die zentrale Karte.
+ Für jedes Feld in jedem Spiel gibt es genau einen Eintrag.
+\layout Description
+
+HOME Eigentümer der Heimatstadt.
+ Das Feld ist -1, wenn es eine Heimatstadt ist, aber noch niemand spielt.
+\layout Description
+
+OCCUPANT Besitzer des Feldes
+\layout Description
+
+TERRAIN kann sein eins aus: WATER, CITY, MOUNTAIN, ISLE, PLAIN
+\layout Description
+
+PLAGUE ist das Feld verseucht? Kann eine aus einer Liste von Seuchen sein
+\layout Description
+
+ATTACKER Hier steht der leitende Erdling eines Angriffs drinnen so lange
+ gekämpft wird.
+ 0 sonst.
+ Man kann hier also auch ablesen, ob das Feld umkämpft ist.
+\layout Description
+
+LAST_PRODUCE Zu dieser Zeit wurde zu letzt ein Krieger (bei Städten) bzw.
+ ein Priester (bei Tempeln) produziert.
+ Der Dämon entscheidet anhand dieser Daten, wann neue Einheiten produziert
+ werden.
+\layout Description
+
+FLUXLINE Hier stehen die Richtungen, in die sich Avatare momentan kostenlos
+ bewegen können.
+ Die benachbarten Richtungen kosten 1 MP, alle anderen 2MP.
+ Dieses Feld wird bei einer Änderung der IdS für die gesamte Karte neu berechnet.
+\layout Description
+
+TEMPLE Steht auf 'Y', wenn dort ein Tempel gebaut wurde, auf 'N' sonst.
+\layout Subsection
+
+Tabelle MOBILE
+\layout Standard
+
+In dieser Tabelle werden alle beweglichen Objekte abgespeichert.
+ Das sind also zunächst: Krieger, Helden, Priester, Avatare und Archen.
+ Dabei gibt es nur einen Eintrag für gleichartige Einheiten im selben Feld
+ im selben Spiel.
+\layout Standard
+
+Manche Felder werden nur für manche Objekttypen benutzt.
+ Hier wird also ein bisschen Speicherplatz geopfert um die Struktur möglichst
+ einfach zu halten.
+\layout Description
+
+ID Eine eindeutige ID.
+\layout Description
+
+TYPE Ist einer aus WARRIOR, HERO, PRIEST, AVATAR, ARK
+\layout Description
+
+OWNER Der Spieler, der die Einheit steuert
+\layout Description
+
+ADORING Der Gott, den der Priester anbetet
+\layout Description
+
+COUNT Anzahl
+\layout Description
+
+AVAILABLE Wird auf 0 gesetzt, wenn die Einheit beschäftigt ist (sich also
+ z.B.
+ bewegt)
+\layout Description
+
+STATUS Eines aus HELP, BLOCK, PEACE.
+ Avatarstatus.
+\layout Subsection
+
+Tabelle COMMAND
+\layout Standard
+
+In diese Tabelle tragen die Scripten die Aktionen der Spieler ein und der
+ Dämon führt diese dann aus.
+ Zusätzlich kommen hier auch noch die Quasi-Befehle des Dämons selber rein.
+ Das ist alles, wo er sich für später dran errinnern will.
+ Zur Zeit wird dieser Mechanismus nur für Kämpfe benötigt.
+\layout Description
+
+TIME Die Zeit zu der das Kommando eingetragen wurde
+\layout Description
+
+ACK Hier wird vermerkt, dass der Dämon das Kommando zur Kenntnis genommen
+ hat, aber noch nicht ausgeführt.
+ Das ist nötig weil bei vielen Kommandos schon am Anfang Nachrichten generiert
+ werden müssen, lange bevor sie ausgeführt werden.
+ Z.B.
+ erhalten die Eigentümer eines Feldes, in das man sich bewegt, eine Nachricht,
+ schon wenn man sich auf den Weg macht.
+\layout Description
+
+DONE Hier werden abgearbeitete Befehle vermerkt
+\layout Standard
+
+Alle drei Felder sind Timestamps und müssen immer GMT enthalten!
+\layout Subsection
+
+Tabelle MESSAGE
+\layout Standard
+
+In diese Tabelle trägt der Dämon Nachrichten an die Spieler ein und die
+ Scripten zeigen diese dann an.
+ Nachrichten an Alle Spieler müssen für jeden Spieler einzeln eingetragen
+ werden.
+ Wenn man es anders machen wollte, müsste man wiederum für jeden Spieler
+ vermerken, welche Nachrichten er nicht mehr sehen will, was fast auf das
+ selbe rauskommt.
+
+\layout Description
+
+TIME Der Zeitpunkt, an dem die Nachricht generiert wurde
+\layout Description
+
+FROM Der Absender.
+ 0 bedeutet, dass es eine automatisch generierte Nachricht des Dämon ist.
+\layout Description
+
+TO Der Empfänger
+\layout Description
+
+TYPE Message, Error, Warning, ...
+\layout Description
+
+MSG Die eigentliche Meldung.
+ Bzw.
+ ein Tag, dass erst noch lokalisiert werden muss (Siehe Tabelle LOCALIZE)
+\layout Description
+
+ARG1...4 Die Argumente für die Lokalisierung.
+\layout Subsection
+
+Tabelle GAME
+\layout Standard
+
+Hier stehen allgemein Infos das Spiel betreffend.
+ Pro Spiel gibt es nur einen Eintrag.
+\layout Description
+
+SIZE Die Größe des Spiels.
+ Höhe und halbe Breite des Spielfeldes.
+ Maximale Anzahl Erdlinge.
+\layout Description
+
+FORTUNE Der Glücksfaktor
+\layout Description
+
+LAST_TEMPLE Die LOCATION des letzten fertig gestellten Tempels.
+\layout Description
+
+TEMPLE_SIZE Größe des nächsten Tempels.
+\layout Subsection
+
+Tabelle PLAYER
+\layout Standard
+
+Hier wird spielunabhängig gespeichert, was es alles über einen Spieler zu
+ wissen gibt.
+ Pro Spieler ein Eintrag.
+\layout Subsection
+
+Tabelle ALLIANCE
+\layout Standard
+
+Hier wird beschrieben welche Freunde und Feinde man hat.
+ Pro Spieler-Spieler-Relation in jedem Spiel höchstens ein Eintrag.
+ Status kann sein
+\begin_inset Quotes eld
+\end_inset
+
+FRIEND
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+FOE
+\begin_inset Quotes erd
+\end_inset
+
+ oder
+\begin_inset Quotes eld
+\end_inset
+
+NEUTRAL
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Wenn kein Eintrag vorhanden ist, wird neutraler Status angenommen.
+
+\layout Standard
+
+Man beachte dass Spieler A, Spieler B als Freund ansehen kann, wärend umgekehrt
+ Spieler B Spieler A als Feind betrachtet!
+\layout Subsection
+
+Tabelle GOD
+\layout Standard
+
+Hier werden Daten für die Götter gespeichert.
+ Pro Gott und Spiel ein Eintrag.
+\layout Description
+
+DEATH_AVATAR Die Anzahl der für diesen Gott in diesem Spiel gestorbenen
+ Avatare
+\layout Description
+
+DEATH_HERO dsgl.
+ für Helden
+\layout Description
+
+ARRIVAL Hier entstehen neue Avatare.
+ Dieser Ort wird nach jedem Tempelbau diesen Gottes neu berechnet.
+\layout Subsection
+
+Tabelle LOCALIZE
+\layout Standard
+
+Mit Hilfe dieser Tabelle kann die Darstellung in verschiedenen Sprachen
+ erfolgen.
+\layout Description
+
+TAG Der Eintrag mit dem man wiederkennt, um welche Message es sich handelt
+\layout Description
+
+LANG Die Sprache des Eintrags.
+ Zur Zeit werden nur
+\begin_inset Quotes eld
+\end_inset
+
+DE
+\begin_inset Quotes erd
+\end_inset
+
+ und
+\begin_inset Quotes eld
+\end_inset
+
+EN
+\begin_inset Quotes erd
+\end_inset
+
+ unterstützt.
+\layout Description
+
+TEXT Der Text der Nachricht in den einzelnen Sprachen.
+ Dabei wird mittels
+\begin_inset Quotes eld
+\end_inset
+
+%n
+\begin_inset Quotes erd
+\end_inset
+
+ das n.te Argument eingefügt.
+
+\begin_inset Quotes eld
+\end_inset
+
+%%
+\begin_inset Quotes erd
+\end_inset
+
+ gibt ein Prozentzeichen aus.
+
+\layout Subsection
+
+Tabelle ROLE
+\layout Standard
+
+Hier wird die Rolle eines Spielers in einem Spiel beschrieben.
+ Pro Mitspieler in jedem Spiel ein Eintrag.
+\layout Section
+
+Dämon
+\layout Standard
+
+Dieses Programm liest Spieleraktionen aus der Datenbank, berechnet die sich
+ daraus ergebenden Ereignisse und schreibt Nachrichten an die Spieler zurück
+ in die Datenbank.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementierung des Servers.
+\layout Section
+
+Scripten
+\layout Standard
+
+Sie lesen den Zustand der Welt und die Nachrichten aus der Datenbank, halten
+ Session-Informationen vor und bereiten dies alles in HTML zur Darstellung
+ mittels eines üblichen Web-Browsers auf.
+ Schließlich schreiben sie die Aktionen des Benutzers in die Datenbank und
+ verändern den Aktivitätsstatus von beweglichen Einheiten.
+\layout Standard
+
+Wir verwenden EmbPerl auf Apache zur Implementation.
+ Siehe: http://perl.apache.org/embperl/.
+ EmbPerl scheint genauso einfach und schnell zu sein wie PHP und hat für
+ uns den zusätzlichen Vorteil, dass wir gemeinsame Bibliotheken mit den
+ anderen Komponenten des Servers benutzen können.
+\layout Subsection
+
+Seiten
+\layout Standard
+
+Folgende Seitenlayouts werden benötigt.
+ Auf allen Seiten findet man ein Hauptmenu.
+ Auf Login und Home gibt es auch noch ein Aymaegeddon-Banner
+\layout Description
+
+Login Hier gibt es neben News einen kurzen Einleitungstext sowie eine Möglichkei
+t sich zu registrieren und mal in einem Fakespiel zu schnuppern.
+\layout Description
+
+Home Liste aller Spiele, pro Spiel: Liste aller Nachrichten, aller Ereignisse,
+ Statistik
+\layout Description
+
+Karte Aktuelles Feld, Beschreibung, Befehle
+\layout Description
+
+Spieler Beschreibung des Spielers
+\layout Description
+
+Rolle Beschreibung der Rolle
+\layout Standard
+
+Feldnamen/-koordinaten sind überall immer zur Karte mit dem Feld als aktuellem
+ Feld verlinkt.
+ Rollennamen sind zu der entsprechenden Rollenseite verlinkt.
+\layout Subsection
+
+Karte
+\layout Standard
+
+Zentrale Komponente der Darstellung ist eine Karte des Hex-Torus.
+ Dazu werden 3 Tabellenzellen pro Feld verwendet, nämlich so:
+\layout Standard
+\added_space_bottom 0.3cm
+<BILD FEHLT>
+\layout Standard
+
+Diese Karte ist scrollbar.
+ Ein Feld ist immer als aktuelles Feld umrandet.
+\layout Subsection
+
+Farbdarstellung
+\layout Standard
+
+Wasserfelder blau, Landfelder, Archen und Inseln in Erdfarben.
+ Dabei gibt es 5 Farbtöne für eigene, befreundete, neutrale, feindliche
+ sowie unbesiedelte Felder.
+ Tempel und Avatare werden in 5 verschiedenen Götterfarben (eher grell)
+ dargestellt, wieder je eine für eigene, befreundete, feindliche sowie neutrale
+ Götter.
+ Die
+\begin_inset Quotes eld
+\end_inset
+
+eigene
+\begin_inset Quotes erd
+\end_inset
+
+ Farbe kann auf andere Erdlinge/Götter verändert werden.
+
+\layout Subsection
+
+Icons
+\layout Standard
+
+Folgende Icons werden benötigt.
+\layout Standard
+
+Zentriert:
+\layout Itemize
+
+IdS
+\layout Itemize
+
+Eigentum auf Wasser (Schiff)
+\layout Itemize
+
+Städte
+\layout Itemize
+
+Tempel
+\layout Itemize
+
+Heimatstädte
+\layout Itemize
+
+Inseln
+\layout Itemize
+
+Berge
+\layout Standard
+
+Nicht zentriert:
+\layout Itemize
+
+Avatare (oben bis zu vier)
+\layout Itemize
+
+Archen (unten, nur eine)
+\layout Itemize
+
+Kampf (unten)
+\layout Itemize
+
+Avatarkampf (oben)
+\layout Section
+
+Weltengenerator
+\layout Standard
+
+Dieses Programm wird einmal zu Beginn eines neuen Spiels aufgerufen um eine
+ neue Welt in der Datenbank zu generieren.
+ Der Generator verteilt die verschiedenen Geländetypen: Wasser, Manapol,
+ Insel, Berg, Stadt, Heimatstadt, Land.
+ Er erhält die Anzahl der Erdlinge als Parameter und ermittelt alle anderen
+ Werte daraus.
+
+\layout Standard
+
+Die Game-ID kann automatisch als die erste Freie in der DB ermittelt werden.
+ Dieses Programm sollte als erstes entwickelt werden, damit man eine sinnvolle
+ Testumgebung für die anderen Teile des Systems hat.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+FROGS
+\layout Standard
+
+FROGS steht für
+\series bold
+F
+\series default
+ramework for
+\series bold
+R
+\series default
+ealtime
+\series bold
+O
+\series default
+nline
+\series bold
+G
+\series default
+ames of
+\series bold
+S
+\series default
+trategy.
+ Dort werden alle Funktionalitäten versammelt, die nicht nur von Aymargeddon,
+ sondern auch von anderen Browser-MMOGs verwendet werden können.
+ Das sind im einzelnen:
+\layout Itemize
+
+Nachrichtenverwaltung
+\layout Itemize
+
+Befehlsverwaltung
+\layout Itemize
+
+Spielerverwaltung
+\layout Itemize
+
+Spielverwaltung
+\layout Itemize
+
+Rollenverwaltung
+\layout Itemize
+
+Verschiedene Standardkarten (hier erstmal nur Hextorus)
+\layout Itemize
+
+Bewegliche Einheiten
+\layout Itemize
+
+Lokalisierung
+\layout Itemize
+
+Sessionhandling
+\layout Itemize
+
+Bestenlisten
+\layout Itemize
+
+Datenbank
+\layout Standard
+
+FROGS basiert dabei auf der Annahme, dass bestimmte Felder in bestimmten
+ Tabellen vorhanden sein müssen.
+ Außerdem werden die konkreten Funktionalitäten über Hooks in das Framework
+ eingehängt.
+ So wird z.B.
+ für jeden Befehl ein Name festgelegt mit drei Hooks:
+\layout Description
+
+test Diese Funktion tested, ob der Befehl überhaupt ausführbar ist.
+\layout Description
+
+ack Diese Funktion wird ausgeführt, wenn der Befehl zum ersten mal vom Dämon
+ zur Kenntnis genommen wird.
+\layout Description
+
+do Diese Funktion führt schließlich den Befehl aus.
+ Dazu sind am Anfang noch weitere tests nötig.
+\layout Standard
+
+Ziel für Frogs ist, dass man relativ einfach neue Browserspiele bauen kann.
+ Es wird auch ein Satz von Standardseiten in EmbPerl mitgeliefert mit denen
+ Funktionen wie Einloggen, Spielverwaltung, Bestenlisten etc.
+ schon vorhanden sind.
+\layout Standard
+
+Hier noch eine Liste von FROGS-Modulen und was sie tun sollen:
+\layout Description
+
+Map.pm Dies ist eine Basisklasse für alle denkbaren Topologien.
+ Jedes Modul einer abgeleiteten Klasse sollte auch eine Klasse Location
+ zur Verfügung stellen.
+ Außerdem müssen abgeleitete Klassen einige Funktionen mitbringen, damit
+ die in Map vorhandenen Funktionen funktionieren.
+\layout Description
+
+HexTorus.pm Dies ist die von Aymargeddon verwendete Topologie.
+ Kann aber auch von anderen Spielen verwendet werden.
+ Abgeleitet von Map.pm.
+ Stellt auch die Klasse Location zur Verfügung.
+\layout Description
+
+Checker.pm Hier werden die verallgemeinerbaren Funktionen des Checkers zur
+ Verfügung gestellt.
+\layout Description
+
+Scheduler.pm Hier wird die Befehlsqueu durchgegangen und die oben definierten
+ Funktionen werden aufgerufen.
+\layout Description
+
+Localize.pm Hier wird die Lokalisierung ausgeführt.
+\layout Description
+
+DataBase.pm Hier werden Basisdatenbankfunktionalitäten zur Verfügung gestellt
+\layout Description
+
+...
+ weitere Module noch unklar
+\layout Standard
+
+Auch FROGS wird in Perl 5.8 bzw.
+ EmbPerl implementiert.
+\layout Section
+
+Checker
+\layout Standard
+
+Dieses Programm überprüft, ob die Daten in der Datenbank noch konsistent
+ sind.
+ Dabei werden die Checks zu algorithmisch ähnlichen Gruppen zusammengefasst
+ und durch allgemein Funktionen ausgeführt.
+ Bisher sind folgende Funktionen identifiziert worden:
+\layout Enumerate
+
+Jeder Eintrag in Tabelle X muß auch in Tabelle Y existieren.
+
+\layout Enumerate
+
+N Einträge in der selben Tabelle müssen eine logische Beziehung erfüllen
+\layout Standard
+
+Diese allgemeinen konfigurierbaren Check-Funktionen sollten auch Teil von
+ FROGS werden.
+\layout Standard
+
+Der Checker überprüft im einzelnen (Zahlen beziehen sich auf obige Funktionslist
+e):
+\layout Itemize
+
+Jede Spielnummer muß in der Tabelle GAME zu finden sein (1).
+\layout Itemize
+
+sämtliche Spieler-IDs müssen in ROLE zum selben Spiel passen (1).
+\layout Itemize
+
+sämtliche Spieler-IDs müssen in PLAYER vorhanden sein (1).
+\layout Itemize
+
+Location muß immer in MAP vorhanden sein.
+\layout Itemize
+
+Location muß immer die kanonische Form haben (2).
+\layout Itemize
+
+HOME nur gesetzt in MAP, wenn TERRAIN = CITY (desgl.
+ für GOD_HOME und MOUNTAIN) (2).
+\layout Itemize
+
+Keine Zwei Erdlinge im selben Feld, außer es ist Kampf.
+\layout Itemize
+
+Alle Einheiten in COMMANDS müssen inaktiv sein.
+\layout Itemize
+
+Nur Priester ADORING in MOBILE (2).
+\layout Itemize
+
+AVAIABLE immer kleiner oder gleich COUNT in MOBILE (2)
+\layout Itemize
+
+Während eines Kampfes nur aktive Erdlinge eines Spielers im selben Feld.
+\layout Itemize
+
+Keine blockenden Avatare von zwei feindlichen Spielern im selben Feld ohne
+ Kampf .
+\layout Itemize
+
+Jedes Tag in MESSAGE sollte in LOCALIZE vorhanden sein.
+ Mindestens in einer Sprache.
+ Warnung, wenn nicht in jeder Sprache.
+\layout Itemize
+
+Die Anzahl der Argumente in MESSAGES sollte mit den nicht doppelten %-Zeichen
+ in LOCALIZE übereinstimmen (für jede Sprache).
+
+\layout Itemize
+
+CREATE <= EXEC <= ACK <= DONE in COMMAND
+\layout Standard
+
+Dieses Programm sollte möglichst früh entwickelt werden, da es vor allem
+ im Entwicklungsprozess benötigt wird.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+Bibliothek
+\layout Standard
+
+Hier werden alle Funktionalitäten versammelt, die von mindestens zwei der
+ Komponenten (Scripten, Generator, Dämon, Check) verwendet werden.
+
+\layout Standard
+
+Dabei bleiben in dieser Bibliothek nur Sachen, die nicht noch allgemeiner
+ sind und somit in den FROGS-Teil gehören.
+ Momentan ist noch unklar, ob da überhaupt was übrig bleibt.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+
+\lang german
+Copyright
+\layout Standard
+
+
+\lang german
+(c) 2003 Aymargeddon Development Team
+\layout Standard
+
+
+\lang german
+Permission is granted to copy, distribute and/or modify this document under
+ the terms of the GNU Free Documentation License, Version 1.1 or any later
+ version published by the Free Software Foundation; with no Invariant Sections,
+ with no Front-Cover Texts, and with no Back-Cover Texts.
+ A copy of the license is available at http://www.aymargeddon.de.
+\the_end
--- /dev/null
+#FIG 3.2
+Landscape
+Center
+Metric
+A4
+100.00
+Single
+-2
+1200 2
+2 3 0 1 0 7 100 0 -1 0.000 0 0 0 0 0 7
+ 4425 4177 5103 5348 6452 5349 7127 4177 6451 3006 5101 3009
+ 4425 4177
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 5847 2976 5895 2430
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 4742 3668 4185 3420
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 4752 4771 4050 5175
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 5796 5327 5760 6075
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 6777 4803 7398 5067
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 6823 3599 7408 3262
+4 0 0 100 0 0 12 -0.0000 4 180 1440 3285 3195 Nordwesten (NW)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1410 3105 5625 Suedwesten (SW)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1260 7065 3150 Nordosten (NO)\001
+4 0 0 50 0 0 12 0.0000 4 180 930 5490 2250 Norden (N) \001
+4 0 0 50 0 0 12 0.0000 4 180 765 5355 6390 S\374den (S)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1230 7155 5400 Suedosten (SO)\001
--- /dev/null
+#################
+Datenbankzugriffe
+#################
+
+Alles, was einen SQL-Befehl beinhaltet sollte in
+DataBase.pm. zusätzlich vielleicht auch noch sehr eng damit
+zusammenhängende Funktionen. Alles abstraktere sollte in extramodule.
+
+Generelle Frage:
+================
+
+embperl sollte nur die aktionen überhaupt zur verfügung stellen, die
+möglich sind (soweit zu diesem zeitpunkt bekannt).
+
+soll man darauf vertrauen, dass die embperlseite bestimmte sachen
+schon abgetestet hat? oder muss man die alle nochmal auf serverseite
+testen? Antwort: wohl ja, da sich zwischen eintragen in die
+befehlsqueu und ausführung des befehls der spielstand verändert haben
+kann. ausnahmen sind unten eingeklammert.
+
+Hier jetzt mal eine möglichst vollständige Liste aller
+Datenbankzugriffe, als Grundlage für Designüberlegungen.
+
+Von Serverseite:
+================
+
+- lies alle aktuellen befehle
+- schreibe message
+
+Alles, was trotz zeitverzögerung schon vorher von embperlseite
+abgeklärt hätte werden können ist eingeklammert.
+
+einzelne befehle:
+--------------------
+- passwort ändern (nicht in befehlsqueu sondern sofort?)
+ - authentifizieren
+ - schreiben in PLAYER
+
+- registrieren (nicht in befehlsqueu sondern sofort?)
+ - schreiben in PLAYER
+
+- abmelden (nicht in befehlsqueu sondern sofort?)
+ - authentifizieren
+ - löschen in PLAYER
+
+- status ändern
+ - test ob spieler vorhanden
+ - schreiben in ALLIANCE
+
+- anmelden in einzelnen spielen (nicht in befehlsqueu sondern sofort?)
+ - test ob spieler schon in spiel vorhanden
+ - schreiben in ROLE
+
+- abmelden aus spielen (nicht in befehlsqueu sondern sofort?)
+ - löschen aus ROLE
+--------------------
+- erdlingsbewegen:
+ - (test ob manapol)
+ - test ob arche auf wasser
+ - test ob kampf
+ - test wer kämpft
+ - schreiben in MOBILE
+ - schreiben in MAP
+ - schreiben in COMMAND
+
+- tempel bauen:
+ - test ob tempelfeld des gottes (kann sich ändern wg. überschwemmung)
+ - test ob richtiger priester da
+
+- sterbereihenfolge:
+ - (testen ob reihenfolge gültig)
+ - schreiben in EARTHLING [ACHTUNG: neue Tabelle!]
+
+- gott für tote helden festlegen:
+ - testen ob gott gültig
+ - schreiben in EARTHLING
+--------------------
+- bei allen gottbefehlen: testen ob manna reicht
+
+- avatar erschaffen:
+ - ort ermitteln aus MAP und MOBILE
+ - schreiben in MOBILE
+
+- held weihen
+ - testen ob held noch vorhanden (und aktiv?)
+ - schreiben in MOBILE
+
+- priester erleuchten
+ - testen ob krieger noch vorhanden (und aktiv?)
+ - testen ob sichtrecht
+ - schreiben in MOBILE
+
+- avatare bewegen
+ - ähnlich wie erdlingsbewegen nur zusätzliche tests
+ - avatarstatus beachten (evntl. verändern)
+
+- verseuchen
+ - noch unklar, weil seuchen noch unklar
+
+- sintfluten
+ - test ob benachbartes wasserfeld
+ - liest und schreibt aus MAP
+
+- avatarstatus ändern
+ - testen ob avatar da.
+
+- tempel zerstören
+ - ...
+
+- glücksfaktor verändern
+ - ...
+
+- arche bauen
+ - ...
+
+Von Clientseite:
+================
+
+- authentifizieren
+- liste aller spiele
+- liste aller spiele mit freien positionen (mit rolle)
+- liste aller spieler
+- liste aller rollen pro spiel
+- infos ueber einen spieler
+- infos ueber eine rolle eines spielers in einem spiel
+
+- karte lesen (sichtregeln beachten!)
+- infos ueber ein feld lesen (auch aus MOBILE) (sichtregeln beachten!)
+
+- liste der möglichen befehle in einem feld ermitteln
+ (vielfältige tests, viele davon stehen oben bei den serverbefehlen)
+
+- liste aller nachrichten
+- liste aller nachrichten ein feld betreffend
+
+Von create.pl:
+==============
+
+- lies das erste leere spiel aus GAME
+- schreibe in MAP
+
+Von checker.pl:
+===============
+
+- sehr spezielle einzelne zugriffe (Check.pm selbst definiert keine
+Struktur)
+
+
+
--- /dev/null
+From Martin.Spott@uni-duisburg.de Tue Jul 6 17:06:05 1999
+From: Martin Spott <Martin.Spott@uni-duisburg.de>
+Newsgroups: de.comp.os.unix.apps,de.comp.text.tex
+Subject: Re: tex -> pdf
+Date: 24 Jun 1999 18:59:57 GMT
+Organization: home
+Lines: 24
+Message-ID: <7ktv7d$p59$1@foehn.quickstep.cologne.de>
+References: <7kskei$6hb$1@narses.hrz.tu-chemnitz.de> <3771ECC7.C1F5FDA2@starship.python.net>
+NNTP-Posting-Host: foehn.quickstep.cologne.de
+X-Trace: foehn.quickstep.cologne.de 930250797 25769 192.168.48.2 (24 Jun 1999 18:59:57 GMT)
+X-Complaints-To: usenet@foehn.quickstep.cologne.de
+NNTP-Posting-Date: 24 Jun 1999 18:59:57 GMT
+X-Newsreader: TIN [UNIX 1.3 unoff BETA 970705; sun4m SunOS 5.5.1]
+Path: nntp.server.uni-frankfurt.de!grapool30.rz.uni-frankfurt.de!News.Uni-Marburg.DE!news-fra1.dfn.de!news-kar1.dfn.de!akk.uni-karlsruhe.de!news.cologne.de!quickstep.cologne.de!not-for-mail
+Xref: nntp.server.uni-frankfurt.de de.comp.os.unix.apps:2328 de.comp.text.tex:41798
+
+In de.comp.os.unix.apps Berthold H?llmann <bhoel@starship.python.net> wrote:
+
+> 7. latex ; dvipdf ?
+
+Ist das dasselbe wie das 'dvipdfm', welches ich hier rumfliegen habe ?
+
+Beim Weg ueber 'dvips' respektive ueber DVI im Allgemeinen ist vor allem
+darauf Acht zu geben, dass ausschliesslich Type1-Fonts im TeX-Dokument
+verwendet werden. Wie genau das geht, habe ich nicht mehr im Kopf, es gibt
+aber wohl irgeneinen Switch im 'dvips' und die dazugehoerigen TeX-Fonts im
+Type1-Format. Beruecksichtigt man das nicht, dann sieht das PDF-Dokument vor
+allem auf dem Bildschirm ausgesprochen haesslich aus und der Aufbau einer
+Seite im Acrobat Reader dauert ungefaehr die fuenffache Zeit vom dem, was es
+mit Type1-Fonts gebraucht haette, weil dann Bitmap-Fonts in das Dokument
+eingebaut werden. Die eignen sich vielleicht zu allem moeglichen, aber mit
+Sicherheit nicht fuer eine skalierbare Darstellung auf verschiedenen
+Ausgabemedien.
+
+Derleit haessliche Dokumente kursieren leider zuhauf ....
+
+Martin.
+--
+ Unix _IS_ user friendly - it's just selective about who its friends are !
+--------------------------------------------------------------------------
+
+
+From Martin.Spott@uni-duisburg.de Tue Jul 6 17:06:14 1999
+From: Martin Spott <Martin.Spott@uni-duisburg.de>
+Newsgroups: de.comp.os.unix.apps,de.comp.text.tex
+Subject: Re: tex -> pdf
+Date: 24 Jun 1999 20:04:25 GMT
+Organization: home
+Lines: 13
+Message-ID: <7ku309$q35$1@foehn.quickstep.cologne.de>
+References: <7kskei$6hb$1@narses.hrz.tu-chemnitz.de> <3771ECC7.C1F5FDA2@starship.python.net> <7ktv7d$p59$1@foehn.quickstep.cologne.de>
+NNTP-Posting-Host: foehn.quickstep.cologne.de
+X-Trace: foehn.quickstep.cologne.de 930254665 26725 192.168.48.2 (24 Jun 1999 20:04:25 GMT)
+X-Complaints-To: usenet@foehn.quickstep.cologne.de
+NNTP-Posting-Date: 24 Jun 1999 20:04:25 GMT
+X-Newsreader: TIN [UNIX 1.3 unoff BETA 970705; sun4m SunOS 5.5.1]
+Path: nntp.server.uni-frankfurt.de!grapool30.rz.uni-frankfurt.de!News.Uni-Marburg.DE!news-fra1.dfn.de!fu-berlin.de!news.cologne.de!quickstep.cologne.de!not-for-mail
+Xref: nntp.server.uni-frankfurt.de de.comp.os.unix.apps:2329 de.comp.text.tex:41800
+
+In de.comp.os.unix.apps Martin Spott <Martin.Spott@uni-duisburg.de> wrote:
+
+> darauf Acht zu geben, dass ausschliesslich Type1-Fonts im TeX-Dokument
+> verwendet werden. Wie genau das geht, habe ich nicht mehr im Kopf, es gibt
+> aber wohl irgeneinen Switch im 'dvips' und die dazugehoerigen TeX-Fonts im
+> Type1-Format. [...]
+
+.... oder jedenfalls die CM-Fonts,
+
+Martin.
+--
+ Unix _IS_ user friendly - it's just selective about who its friends are !
+--------------------------------------------------------------------------
+
+
--- /dev/null
+# tth -t -e2 Regeln.tex
+# mv Regeln.tex ./+Regeln.tex
+mv Regeln.html ./+Regeln.html
+mv Regeln.pdf ./+Regeln.pdf
+scp ./+Regeln.html benni@aymargeddon.de:aymargeddon/current/doc/
+scp ./+Regeln.pdf benni@aymargeddon.de:aymargeddon/current/doc/
--- /dev/null
+table,body {line-height:13pt;font-size:11pt;}
+p {margin-bottom:5pt;margin-top:5pt;}
--- /dev/null
+<html>
+<head></head>
+<body>
+[- Execute('command_frames.epl') -]
+</body></html>
--- /dev/null
+[# get command and maybe some parameters #]
+
+[-
+ use Aymargeddon;
+ $db = DataBase->new();
+ $aym = Aymargeddon->new($udat{-game},$udat{-id},$db);
+ $db->set_language($udat{-lang});
+-]
+
+[$ if $fdat{'cmd'} $] [# show form to enter the required parameters #]
+
+[-
+# my ($gname) = $db->read_game($udat{-game},'NAME');
+# my $cname = $aym->charname($udat{-id});
+
+# $out = "<strong>$gname</strong> $cname.<p>\n"
+ $out = '<form method="get" action="command.epl">';
+
+ my $cmd = $udat{-cmd} = $fdat{'cmd'};
+ $udat{-cmd_loc} = $fdat{'loc'} if $fdat{'loc'};
+
+ if($cmd eq 'SEND_MSG' and exists $fdat{'other'}){ # anybody, always
+ $udat{-cmd_args} = 'OTHER='.$fdat{'other'};
+ my $to = $aym->charname($fdat{'other'});
+ $out .= $db->loc('SEND_MESSAGE_TO',$to).
+ '<textarea name="message" cols="20" rows="20"></textarea>'
+ }elsif($cmd eq 'CH_STATUS' and exists $fdat{'other'}){ # anybody, always
+ $udat{-cmd_args} = 'OTHER='.$fdat{'other'};
+ $out .= $db->loc('CMD_CH_STATUS_MSG').' '.$aym->charname($fdat{'other'}).":<p>\n"
+ .'<input type="radio" name="status" value="ALLIED">'.$db->loc('STAT_ALLIED')."<p>\n"
+ .'<input type="radio" name="status" value="FRIEND">'.$db->loc('STAT_FRIEND')."<p>\n"
+ .'<input type="radio" name="status" value="NEUTRAL">'.$db->loc('STAT_NEUTRAL')."<p>\n"
+ .'<input type="radio" name="status" value="FOE">'.$db->loc('STAT_FOE')."<p>\n"
+ .'<input type="radio" name="status" value="BETRAY">'.$db->loc('STAT_BETRAY')."<p>\n";
+ }elsif($cmd eq 'DIE_ORDER'){ # earthling, always
+ $out .= $db->loc('CMD_DIE_ORDER_MSG').":<p>\n"
+ .'<input type="radio" name="dying" value="PKH">'.$db->loc('MOBILE_PRIEST_PL').', '.$db->loc('MOBILE_WARRIOR_PL').', '.$db->loc('MOBILE_HERO_PL')."<p>\n"
+ .'<input type="radio" name="dying" value="PHK">'.$db->loc('MOBILE_PRIEST_PL').', '.$db->loc('MOBILE_HERO_PL').', '.$db->loc('MOBILE_WARRIOR_PL')."<p>\n"
+ .'<input type="radio" name="dying" value="KPH">'.$db->loc('MOBILE_WARRIOR_PL').', '.$db->loc('MOBILE_PRIEST_PL').', '.$db->loc('MOBILE_HERO_PL')."<p>\n"
+ .'<input type="radio" name="dying" value="KHP">'.$db->loc('MOBILE_WARRIOR_PL').', '.$db->loc('MOBILE_HERO_PL').', '.$db->loc('MOBILE_PRIEST_PL')."<p>\n"
+ .'<input type="radio" name="dying" value="HPK">'.$db->loc('MOBILE_HERO_PL').', '.$db->loc('MOBILE_PRIEST_PL').', '.$db->loc('MOBILE_WARRIOR_PL')."<p>\n"
+ .'<input type="radio" name="dying" value="HKP">'.$db->loc('MOBILE_HERO_PL').', '.$db->loc('MOBILE_WARRIOR_PL').', '.$db->loc('MOBILE_PRIEST_PL')."<p>\n"
+ }elsif($cmd eq 'CH_LUCK'){ # god, always
+ $out .= $db->loc('CMD_CH_LUCK_MSG').":<p>\n"
+ . '<input type="text" name="bonus"><p>'."\n";
+ # TODO: inc/dec button
+ }elsif($cmd eq 'MOVE' and exists $fdat{'mob'} and exists $fdat{'loc'}){ # any mobile
+ $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'};
+ my ($type, $count, $adoring, $movewith) =
+ $aym->get_mobile_info($fdat{'mob'}, 'TYPE, COUNT, ADORING, MOVE_WITH');
+ $out .= $db->loc('CMD_MOVE_MSG',$aym->mobile_extended_string($type,$count,$adoring)).":<p>\n"
+ .'<input type="text" name="dir">';
+ $out .= $db->loc('CMD_COUNT').':<input type="text" name="count">'."max. $count" if $count > 1;
+ $out .= "<p>\n";
+
+ # arks cant move with other units
+ if($type ne 'ARK'){
+ # MOVE_WITH
+ my $mob = $aym->mobiles_available($fdat{'loc'});
+ my $mobcount = $#{@$mob}+1;
+ my $transporters = 0;
+ if ($mobcount > 1){
+ foreach $i (0..$mobcount-1){
+ my ($oid,$otype,$oown,$oado,$ocnt,$ostat,$omove) = @{$mob->[$i]};
+ next if($oid == $fdat{'mob'} or $otype eq 'AVATAR' );
+ next if $omove;
+ if(! $transporters){
+ $out .= $db->loc('MSG_MOVE_WITH').":<p>\n";
+ $transporters = 1;
+ }
+ if($movewith == $oid){
+ $out .= '<input type="radio" name="movewith" value="0">'.
+ $db->loc('MSG_DONT_MOVE_WITH')."<p>\n";
+ }else{
+ $out .= '<input type="radio" name="movewith" value="'.$oid.'">'.
+ $aym->mobile_extended_string($otype, $ocnt, $oado)."<p>\n";
+ }
+ }
+ }
+ }
+ #}elsif($cmd eq 'CH_ADORING' and exists $fdat{'mob'}){ # hero
+ # $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'};
+ # $out .= $db->loc('CMD_CH_ADORING_MSG').":<p>\n";
+ # my @gods = $aym->gods();
+ # for my $god (@gods){
+ # $out .= '<input type="radio" name="god" value="'.$god.'">'.$aym->charname($god)."<p>\n";
+ # }
+ }elsif($cmd eq 'CH_ACTION' and exists $fdat{'mob'}){ # avatar
+ $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'};
+ $out .= $db->loc('CMD_CH_ACTION_MSG').":<p>\n"
+ . '<input type="radio" name="action" value="BLOCK">'.$db->loc('MOBILE_BLOCK')."<p>\n"
+ . '<input type="radio" name="action" value="HELP">'.$db->loc('MOBILE_HELP')."<p>\n"
+ . '<input type="radio" name="action" value="IGNORE">'.$db->loc('MOBILE_IGNORE')."<p>\n";
+ }elsif($cmd eq 'BLESS_PRIEST' and exists $fdat{'mob'}){ # warrior
+ $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'};
+ $out .= $db->loc('CMD_BLESS_PRIEST_MSG').".<p>\n";
+ }elsif($cmd eq 'BLESS_HERO' and exists $fdat{'mob'}){ # warrior
+ $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'};
+ $out .= $db->loc('CMD_BLESS_HERO_MSG').".<p>\n";
+ $out .= ':<input type="text" name="count"><p>'."\n";
+ }elsif($cmd eq 'BUILD_TEMPLE' and exists $fdat{'mob'}){
+ # priest or prophet at mountain (of the god they adore) or isle without temple
+ $udat{-cmd_args} = 'MOBILE='.$fdat{'mob'}; # needed to change its type to priest if it was a prophet
+ $out .= $db->loc('CMD_BUILD_TEMPLE_MSG').' '.$fdat{'loc'}.".<p>\n";
+ }elsif($cmd eq 'DESTROY'){ # avatar at mountain or isle with temple
+ $out .= $db->loc('CMD_DESTROY_MSG').' '.$fdat{'loc'}.".<p>\n";
+ }elsif($cmd eq 'MOVE_MTN'){ # earthling at a mountain with more priests of one god than luck+5
+ $out .= $db->loc('FIELD_MOUNTAIN')." $loc ".$db->loc('CMD_MOVE_MTN_MSG').":<p>\n";
+ # TODO: list target locations (where prophets adoring same god are)
+ }elsif($cmd eq 'INCARNATE'){ # god at his arrival temple (temple with most priests adoring him)
+ $out .= $db->loc('CMD_INCARNATE_MSG').":<p>\n"
+ .':<input type="text" name="count"><p>'."\n";
+ }elsif($cmd eq 'BUILD_ARK'){ # god at any coast field
+ $out .= $db->loc('CMD_BUILD_ARK_MSG').' '.$fdat{'loc'}.".<p>\n";
+ }elsif($cmd eq 'PLAGUE'){ # god at any field
+ $out .= $db->loc('CMD_PLAGUE_MSG').' '.$fdat{'loc'}.":<p>\n";
+ for my $plague (@{$::conf->{-PLAGUES}}){
+ $out .= '<input type="radio" name="type" value="'.$plague.'">'."$plague<p>\n"
+ }
+ }elsif($cmd eq 'FLOOD'){ # god at any coast field (without city)
+ $out .= $db->loc('CMD_FLOOD_MSG').' '.$fdat{'loc'}.".<p>\n";
+
+ }else{
+ delete $udat{-cmd};
+ delete $udat{-cmd_loc};
+ $out = $db->loc('CMD_ERROR_MSG')."<p>\n"; # unknown, illegal or incomplete command
+ }
+
+ if(exists $udat{-cmd}){
+ $out .= '<input type="submit" value="'.$db->loc('FORM_OK_BUTTON').'"></form>';
+ $udat{-back} = $ENV{'HTTP_REFERER'};
+ }
+ $out .= '<form method="get" action="'.$ENV{'HTTP_REFERER'}.'">'
+ .'<input type="submit" value="'.$db->loc('FORM_BACK_BUTTON').'"></form><p>';
+
+ print OUT $out;
+-]
+
+[$ elsif exists $udat{-cmd} $] [# complete the command with the given form-data #]
+
+[-
+ my ($cmd) = $udat{-cmd}; delete $udat{-cmd};
+ my ($args) = $udat{-cmd_args}; delete $udat{-cmd_args} if exists $udat{-cmd_args};
+ my ($loc) = $udat{-cmd_loc}; delete $udat{-cmd_loc} if exists $udat{-cmd_loc};
+ my $failure = 0;
+
+ # global
+ if($cmd eq 'SEND_MSG'){
+ my $msg = $db->quote($fdat{'message'});
+
+ # uggly workaround necessary for Command::parse_args()
+ $msg =~ s/,/__COMMA__/g;
+ $msg =~ s/=/__EQUAL__/g;
+
+ $args .= ", MESSAGE=$msg"
+ }elsif($cmd eq 'CH_STATUS'){
+ $failure = 1 if not exists $fdat{'status'};
+ $args .= ', STATUS='.$fdat{'status'};
+ }elsif($cmd eq 'DIE_ORDER'){
+ $failure = 1 if not exists $fdat{'dying'};
+ $args = 'DYING='.$fdat{'dying'};
+ }elsif($cmd eq 'CH_LUCK'){
+ $failure = 1 if not exists $fdat{'bonus'};
+ $args = 'BONUS='.$fdat{'bonus'};
+
+ # mobile
+ }elsif($cmd eq 'MOVE'){
+ $failure = 1 if (not exists $fdat{'dir'} and not exists $fdat{'movewith'});
+ my $count = (exists $fdat{'count'}) ? $fdat{'count'} : 1;
+ if(exists $fdat{'movewith'}){
+ $cmd = 'MOVE_WITH';
+ $args .= ', COUNT='.$count.', TARGET='.$fdat{'movewith'};
+ }else{
+ $args .= ', COUNT='.$count.', DIR='.$fdat{'dir'};
+ }
+ #}elsif($cmd eq 'CH_ADORING'){
+ #$failure = 1 if not exists $fdat{'god'};
+ #$args .= ', GOD='.$fdat{'god'};
+ }elsif($cmd eq 'CH_ACTION'){
+ $failure = 1 if not exists $fdat{'action'};
+ $args .= ', ACTION='.$fdat{'action'};
+ }elsif($cmd eq 'BLESS_HERO'){
+ my $count = exists $fdat{'count'} ? $fdat{'count'} : 1;
+ $args .= ", COUNT=$count";
+ # local
+ }elsif($cmd eq 'MOVE_MTN'){
+ $failure = 1 if not exists $fdat{'target'};
+ $args = 'TARGET='.$fdat{'target'};
+ }elsif($cmd eq 'INCARNATE'){
+ my $count = (exists $fdat{'count'}) ? $fdat{'count'} : 1;
+ $args = 'COUNT='.$count;
+ }elsif($cmd eq 'PLAGUE'){
+ $failure = 1 if not exists $fdat{'type'};
+ $args = 'TYPE='.$fdat{'type'};
+ }# elsif($cmd eq 'DESTROY'){
+
+
+ my $ub = $udat{-back};
+ delete $udat{-back};
+
+ if($failure)
+ {
+ $out = $db->loc('CMD_ERROR_MSG')."<p>\n"; # unknown, illegal or incomplete command
+ $out .= '<form method="get" action="'.$ub.'">'
+ .'<input type="submit" value="'.$db->loc('FORM_BACK_BUTTON').'"></form><p>';
+ print OUT $out;
+ }else{
+ $args = '' if not $args;
+ $aym->insert_command($cmd,$args,$loc) unless $failure;
+ $db->commit();
+
+ # redirect to field
+ $http_headers_out{'Location'} = $ub;
+ }
+-]
+
+[$ else $]
+
+ Hey, kein Befehl ?!?!
+
+[$ endif $]
--- /dev/null
+# Makefile for Aymargeddon documentation
+# TODO: BUG: macht immer alles (liegt an +* nicht im target)
+
+LYX2HTML = lyx --export html
+LYX2PDF = lyx --export pdf
+FICK2DEATH = fig2dev
+
+INSTALL_SERVER = aymargeddon.de
+INSTALL_DIR = /home/benni/aymargeddon_current/doc/
+
+DIRS =
+FILES_BIN =
+FILES_LIB =
+FILES_DOC = Regeln.lyx Techdoc.lyx ay_ein_hex.fig
+FILES_MISC =
+FILES = Makefile $(FILES_IN) $(FILES_DOC) $(FILES_MISC)
+FILES_OUT = ay_ein_hex.eps Regeln.pdf \
+ Regeln.html Techdoc.pdf Techdoc.html $(FILES_MISC)
+
+
+all: $(FILES_OUT)
+
+#Regeln.html: Regeln.tex
+# $(LATEX2HTML) $(LATEX2HTML_OPT) < Regeln.tex > Regeln.html
+#
+#Techdoc.html: Techdoc.tex
+# $(LATEX2HTML) $(LATEX2HTML_OPT) < Techdoc.tex > Techdoc.html
+
+clean:
+ rm -f $(FILES_OUT)
+ rm -rf Regeln
+ rm -rf Techdoc
+ rm -rf auto
+ rm -f *.aux
+ rm -f *.log
+ rm -f *.ps
+ rm -f *.dvi
+ rm -f *~
+ rm -f *.toc
+ rm -f *.png
+ rm -f *.ps.gz
+ rm -f *.tex
+ rm -f +*
+
+realclean: clean
+
+
+
+#release: clean have_to_make
+# @if [ -z "$(RELDIR)" ] ; then \
+# echo "Sorry, release directory is not set!" 1>&2 ; \
+# exit 1 ; \
+# fi ;\
+# if [ ! -d $(RELDIR) ] ; then mkdir $(RELDIR) ; fi ; \
+# tar cf - $(FILES) | \
+# ( cd $(RELDIR) ; tar xf - )
+# for i in $(DIRS) ; do \
+# ( cd $$i ; \
+# $(MAKE) RELDIR=../$(RELDIR)/$$i $@ ) ; \
+# done
+
+install: all
+
+# hier muss dann das angepasste push-script hin
+
+# @if [ "X$(RELEASE)" = "X" ] ; then \
+# echo "Sorry, this isn't released source" 1>&2 ; \
+# exit 1 ; \
+# fi ;\
+# for i in $(INSTALLDIRS) ; do \
+# if [ ! -d $$i ] ; then mkdir -p $$i ; fi ; \
+# done ;\
+# for i in $(FILES_DOC) ; do \
+# cp $$i $(DOCDIR)/$$i ; \
+# chmod 555 $(DOCDIR)/$$i ; \
+# chown bin:bin $(DOCDIR)/$$i ; \
+# echo "Installed $(DOCDIR)/$$i" ; \
+# done
+# for i in $(DIRS) ; do \
+# ( cd $$i ; ${MAKE} RELEASE=$$RELEASE PREFIX=$(PREFIX) install ) ; \
+# done
+
+# have_to_make:
+
+.SUFFIXES:
+.SUFFIXES: .pdf .lyx .eps .fig .html
+
+.fig.eps:
+ $(FICK2DEATH) -L ps $(FICK2DEATH_OPT) $< +$@
+
+# TeX to DVI
+#.tex.dvi:
+# $(LATEX) $< < /dev/null > /dev/null 2>&1
+# $(LATEX) $< < /dev/null > /dev/null 2>&1
+
+# DVI to PS
+#.dvi.ps:
+# $(DVIPS) -o $@ $<
+
+# PS to PDF
+#.ps.pdf:
+# $(PS2PDF) $< $@
+
+# LyX to TeX
+#.lyx.tex:
+# $(LYX2LATEX) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+# LyX to PDF
+.lyx.pdf:
+ $(LYX2PDF) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+# LyX to HTML
+.lyx.html:
+ $(LYX2HTML) $< > /dev/null 2>&1 && mv -f $@ +$@
+
+
--- /dev/null
+german below!
+
+There is currently no rules or other documentation in english. use the
+sourcecode or ask at the mailinglist, if you want to know something.
+
+------------------------
+
+Die Dateien in diesem Verzeichnis sind nicht auf dem neuesten Stand.
+Die Regeln werden inzwischen im Wiki gepflegt:
+
+http://www.aymargeddon.de/wiki/index.php/Regeln
--- /dev/null
+#LyX 1.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 221
+\textclass article
+\language german
+\inputencoding latin1
+\fontscheme default
+\graphics default
+\paperfontsize 11
+\spacing single
+\papersize a4paper
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 0
+\use_natbib 0
+\use_numerical_citations 0
+\paperorientation portrait
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation indent
+\defskip bigskip
+\quotes_language polish
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+Die letzten Tage von Aymargeddon
+\layout Author
+
+Aymargeddon Development Team
+\layout Date
+
+17.
+ April 2005
+\layout Standard
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+tableofcontents
+\backslash
+newpage
+\end_inset
+
+
+\layout Section
+
+Einleitung
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Es ist nicht leicht, ein Gott zu sein
+\begin_inset Quotes prd
+\end_inset
+
+ (Titel eines Buches der Brüder Strugatzkij)
+\layout Standard
+
+Während in den himmlischen Sphären der entscheidende Kampf zwischen Gut
+ und Böse ausgefochten wird, kämpfen auf Erden Elfen gegen Zwerge, Menschen
+ gegen Halblinge und jeder gegen jeden.
+ Soweit das Fantasy-Klischee.
+ Doch jetzt kommen wir zum Spiel:
+\layout Standard
+
+
+\series bold
+\shape smallcaps
+Die letzten Tage von Aymargeddon
+\series default
+\shape default
+ wird von mindestens acht Spielern gespielt.
+ Höchstens ein Drittel der Spieler übernimmt die Aufgabe eines Gottes.
+ Die restlichen zwei Drittel spielen jeweils ein Volk auf der Erde.
+ Am Ende gibt es zwei Sieger: den himmlischen Sieger, der zwischen den Göttern
+ ermittelt wird, und den Sieger der Erdlinge, den die restlichen Spieler
+ zwischen sich ausmachen.
+\layout Standard
+
+
+\series bold
+Himmlischer Sieger
+\series default
+ist der Gott, der am Ende in der
+\series bold
+letzten Schlacht
+\series default
+ auf der
+\series bold
+Insel des Schicksals
+\series default
+, der
+\series bold
+Aymargeddon,
+\series default
+ am meisten Kräfte auf sich vereinigen kann.
+ Der Ort der letzten Schlacht wird einer von mehreren
+\series bold
+Manapolen
+\series default
+ sein - abgelegene Inseln, auf denen die magischen Kraftlinien zusammenlaufen.
+ In der letzten Schlacht kämpfen die
+\series bold
+Avatare
+\series default
+ der Götter, aber auch die Geister verstorbener
+\series bold
+Helden
+\series default
+ der Erdlinge.
+
+\layout Standard
+
+Der
+\series bold
+Sieger der Erdlinge
+\series default
+ ist der Spieler, der am Ende die meisten
+\series bold
+Städte
+\series default
+ sein eigen nennt.
+
+\layout Standard
+
+Zweite Plätze gibt es weder bei den Göttern noch bei den Erdlingen.
+ Es geht immer um den Kampf ums Ganze, um Alles oder Nichts.
+\layout Standard
+
+Die Interaktion zwischen den beiden Ebenen wird durch
+\series bold
+Priester
+\series default
+ und
+\series bold
+Götteraktionen
+\series default
+ möglich.
+\layout Standard
+
+Das
+\series bold
+Spiel endet,
+\series medium
+ sobald alle
+\series bold
+heiligen Berge
+\series default
+und
+\series bold
+ gesegneten Inseln mit Tempeln
+\series default
+ bebaut
+\series medium
+sind
+\series default
+.
+
+\series medium
+Die Tempel bauen die Erdlinge, Götter können sie nur zerstören.
+
+\layout Standard
+
+Je mehr Priester an einem Tempel
+\series bold
+beten
+\series default
+, um so mehr
+\series bold
+Mana
+\series default
+ erhält der jeweilige Gott und um so mehr Aktionen kann er machen.
+\layout Standard
+
+
+\series bold
+Beide Ebenen
+\series medium
+sind aufeinander angewiesen, da Götter ohne den guten Willen der Erdlinge
+ kein
+\series default
+ Mana und somit keinerlei Macht
+\series medium
+ haben und die Erdlinge die Unterstützung der Götter in ihren irdischen
+ Dingen dringend brauchen.
+ Durch diese enge Verzahnung der beiden Spielebenen ist man immer zu
+\series bold
+Verhandlungen
+\series medium
+ gezwungen.
+\layout Standard
+
+Der
+\series bold
+Glücksfaktor
+\series default
+ wird von den Spielern selbst bestimmt.
+ Kämpfe werden durch einen Zufallswert mitbestimmt.
+ Den Maximalwert des Zufalls (3 - 12) müssen die Götter bestimmen (auch
+ diese Aktion kostet sie natürlich Mana).
+
+\layout Standard
+
+Am
+\series bold
+Schluss
+\series medium
+ ist es vor allem nötig
+\series default
+,
+\series medium
+ einen Partner zu haben, der stark genug ist
+\series default
+,
+\series medium
+ um auch an einem Spielende interessiert zu sein
+\series default
+ oder schwach genug, um sich mit einem hinteren Platz zufrieden zu geben
+\series medium
+.
+ So werden treue Verbündete, mit denen man das ganze Spiel gemeinsam bestritten
+ hat, oft noch einmal kurz vor Schlu
+\series default
+ss
+\series medium
+ fallengelassen.
+\layout Standard
+
+Die
+\series bold
+Erdlinge
+\series medium
+spielen
+\series default
+mit
+\series bold
+Kriegern
+\series default
+, Helden (von Göttern erzeugt) und Priestern.
+ Üblicherweise werden nur die ersten Priester von Göttern erleuchtet, danach
+ machen die Tempel diese Arbeit.
+ Sie können Tempel bauen, Städte erobern und Archen steuern.
+\layout Standard
+
+Die
+\series bold
+Götter
+\series medium
+spielen
+\series default
+ mit ihren Avataren, können aber auch Tempel zerstören, Archen erschaffen,
+ Felder überfluten, Seuchen herbeirufen, Priester und Helden erzeugen und
+ den Glücks
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+-
+\end_inset
+
+fak
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+-
+\end_inset
+
+tor verändern.
+ Doch das alles kostet sie Mana.
+\layout Standard
+
+Die Welt ist in viele kleine sechseckige Spielfelder unterteilt.
+ Die Größe des Spielfeldes wird durch die angestrebte Spieleranzahl bestimmt.
+
+\layout Standard
+
+Gespielt wird über einen üblichen Web-Browser.
+ Es gibt keine Spielrunden, sondern jeder Befehl braucht eine gewisse Zeit,
+ bis er ausgeführt wird.
+ Die Spielgeschwindigkeit kann dabei variieren.
+\layout Standard
+
+An dieser Stelle möchten wir einmal ganz laut und deutlich allen Testspielern
+ des Brettspieles und der Pbem-Version danken, ohne die auch diese Online-Versio
+n nicht möglich geworden wäre!
+\layout Section*
+
+
+\family sans
+\series medium
+\size large
+\emph on
+WARNUNG:
+\layout Standard
+
+
+\family sans
+\emph on
+Sowohl die verschiedenen beteiligten Programme als auch diese Regeln sind
+ noch in einem Test-Stadium.
+ Wir bitten also insbesondere alle Testspieler, uns darauf hinzuweisen,
+ wenn es Unterschiede zwischen diesem Dokument und dem realen Verhalten
+ des Spiels gibt.
+ Außerdem bitten wir Euch, Euch in die Ragnarök-Mailingliste einzutragen
+ (
+\begin_inset Quotes pld
+\end_inset
+
+subscribe ragnaroek
+\begin_inset Quotes prd
+\end_inset
+
+ nach majordomo@cs.uni-frankfurt.de schicken).
+ Helft mit, dass Aymargeddon besser wird! Wer will, kann auch gerne selbst
+ programmieren helfen.
+ Der Quellcode steht in einem tla-Archiv auf www.aymargeddon.de zur Verfügung.
+\layout Section
+
+Die Welt
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wenn man eine Rolle lange genug spielte, vermischten sich langsam Fiktion
+ und Realität...
+ Rache war etwas für Götter.
+\begin_inset Quotes prd
+\end_inset
+
+ (aus:
+\begin_inset Quotes pld
+\end_inset
+
+Ragnarök
+\begin_inset Quotes prd
+\end_inset
+
+ von D.G.Compton und John Gribbin)
+\layout Standard
+
+Die Welt besteht aus Sechsecken und hat keinen Rand.
+ Man kann in jede Richtung laufen und kommt wieder zum Ausgangspunkt zurück
+ (Torus).
+ Hier ein Screenshot vom Hauptbildschirm, damit Ihr eine Vorstellung davon
+ bekommt, wie die Welt aussieht.
+\layout Standard
+\align center
+<BILD FEHLT NOCH>
+\layout Standard
+
+In dieser Welt kann man sich in sechs verschiedene Richtungen bewegen, die
+ man sich folgendermaßen vorstellen kann:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+<BILD KAPUTT>
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Graphics
+ filename +ay_ein_hex.eps
+ display monochrome
+ width 50text%
+
+\end_inset
+
+
+\layout Standard
+
+Jeder Erdling beginnt bei seiner Heimatstadt.
+ Diese ist schwerer zu erobern und produziert mehr Krieger als normale Städte.
+ Jeder Gott hat zwei heilige Berge, an denen nur er angebetet werden kann.
+\layout Standard
+
+Es dürfen immer nur Einheiten von einem Erdling in einem Feld stehen, das
+ somit einen eindeutigen Eigentümer hat.
+ Heimatstädte erinnern sich immer an ihre rechtmäßigen Herrscher.
+ Sie verteidigen sich auch ohne Krieger, und sie gehören einem wieder, sobald
+ die Besatzungsmacht abgezogen ist.
+\layout Standard
+
+Besondere Felder sind die Manapole, zu ihnen strebt das ganze Denken der
+ Götter ihrem Wesen nach.
+ Einer der Manapole ist immer die Insel des Schicksals.
+ Manapole sind immer komplett von Wasserfeldern ohne gesegnete Inseln umgeben.
+\layout Standard
+
+Außerdem gibt es noch Wasser und Inseln.
+ Inseln sind immer gesegnet, man kann dort also immer Tempel bauen, außer
+ es handelt sich um einen Manapol.
+ Über Wasser darf man sich als Erdling nur bewegen, wenn im Ausgangsfeld
+ eine Arche ist.
+ Avatare dürfen sich nur dann über Wasser bewegen, wenn ein Erdling gleichzeitig
+ die Arche steuert.
+ Die Archen bewegen sich mit den Erdlingen mit und haben ein unbegrenztes
+ Fassungsvermögen.
+ Die Götter sind also auf die Mithilfe der Erdlinge angewiesen, wenn sie
+ ihre Avatare in die letzte Schlacht, die auf der Insel des Schicksals stattfind
+et, schicken wollen.
+\layout Standard
+
+Welcher Manapol Aymargeddon ist, ändert sich im Laufe des Spiels.
+ Es ist immer der Manapol, der dem neuesten und schönsten Tempel am nächsten
+ ist.
+ Avatare bewegen sich leichter in Richtung Aymargeddon als von ihr weg.
+ Sie dürfen die Insel des Schicksals nicht verlassen, so lange sie Aymargeddon
+ ist.
+\layout Subsection*
+
+Topologie
+\layout Standard
+
+Felder haben immer zwei Koordinaten.
+ Das Spielfeld hat keinen Rand, wenn man sich in einer Richtung über den
+ vermeintlichen Rand bewegt, kommt man auf der gegenüberliegenden Seite
+ wieder raus.
+ Die folgende Karte mit den Koordinaten der Felder demonstriert das:
+\layout Standard
+\align center
+<BILD FEHLT NOCH>
+\layout Standard
+
+Eine Welt ist immer doppelt so breit wie hoch.
+ Nur so kann man in allen Richtungen immer geradeaus laufen und kommt doch
+ immer wieder am Ausgangspunkt an.
+\layout Subsection*
+
+Produktion
+\layout Standard
+
+Alle Städte erzeugen automatisch in gewissen Zeitabständen Krieger.
+ Heimatstädte erzeugen doppelt so schnell Krieger, sie tun dies manchmal
+ auch, wenn sie das Feld von feindlichen Einheiten besetzt wird, dann kommt
+ es zu Aufständen der heimatlichen Bevölkerung in regelmäßigen Abständen.
+ Normale Städte erzeugen umso häufiger Krieger, je kürzer der Zeitpunkt
+ ihres letzten Besitzerwechsels her ist.
+
+\layout Standard
+
+Tempel erzeugen in gewissen Zeitabständen Priester.
+ Es werden keine Priester erzeugt, wenn nicht schon rechtgläubige Priester
+ dort sind.
+\layout Section
+
+Aktionen
+\layout Standard
+
+Jede Aktion eines Spielers wird sofort in eine Datenbank geschrieben.
+ Die Aktionen werden jedoch erst zu einem späteren Zeitpunkt ausgeführt.
+ Wie lange das dauert, hängt von der Aktion ab (siehe Abschnitt Timing).
+ Einheiten sind wärend dieser Zeit inaktiv.
+\layout Subsection*
+
+Aktionen für alle Spieler
+\layout Subsubsection*
+
+Status ändern
+\layout Standard
+
+Mit dieser Aktion kann man seine generelle Haltung anderen Spielern gegenüber
+ - seien sie Götter oder Erdlinge - ändern.
+ Man kann andere Spieler als Freund, als Feind oder neutral ansehen.
+ Man kann ihnen Sichtrechte gewähren oder sie verweigern.
+
+\layout Standard
+
+Das hat an einigen Stellen Auswirkungen, die dort dann näher beschrieben
+ sind.
+ Zu Spielbeginn ist man allen anderen Spielern gegenüber neutral eingestellt
+ und gewährt ihnen keine Sichtrechte.
+\layout Subsection*
+
+Aktionen der Erdlinge
+\layout Standard
+
+
+\series bold
+Bewegen
+\layout Standard
+
+Dies bedeutet, dass man eine bestimmte Anzahl Krieger, Helden oder Priester
+ in ein Nachbarfeld bewegen will.
+ Dies kann zu Kampfhandlungen führen, wenn sich am Ende des Zuges noch Einheiten
+ anderer Erdlingsspieler auf dem Zielfeld aufhalten.
+
+\layout Standard
+
+Erdlinge können die Manapole nicht betreten.
+ Ihre toten Helden werden automatisch direkt nach einem Kampf zur Aymargeddon
+ transferiert.
+\layout Standard
+
+Helden bewegen sich doppelt so schnell wie Krieger und kämpfen doppelt so
+ gut.
+
+\layout Standard
+
+Wasser- und Inselfelder können nur betreten werden, wenn im Startfeld eine
+ Arche steht, die einen dorthin bringen kann.
+
+\layout Standard
+
+Archen bewegen sich immer automatisch mit Erdlingen mit außer bei der Bewegung
+ zwischen Landfeldern.
+ Wenn Erdlingseinheiten oder Avatare in einem Wasserfeld zurückbleiben,
+ aus dem sich eine Arche entfernt, ertrinken sie jämmerlich.
+ Ertrinkende Helden streiten nicht in der letzten Schlacht, ebensowenig
+ wie ertrinkende Avatare.
+ Auf Inselfeldern können sie jedoch überleben.
+\layout Standard
+
+Das Bewegen von einem Wasser- oder Inselfeld auf ein benachbartes Landfeld
+ ist immer möglich auch ohne Arche.
+
+\layout Standard
+
+Das Bewegen in das Feld eines Alliierten scheitert
+\begin_inset Foot
+collapsed true
+
+\layout Standard
+
+Böse Zungen nennen das die Olf-Bodo-Regel ;-)
+\end_inset
+
+.
+ Ebenso scheitert die Bewegung, wenn im Zielfeld bereits ein Kampf stattfindet
+ an dem ich nicht beteiligt bin.
+ So wird gewährleistet, dass an einem Erdlingskampf immer nur zwei Spieler
+ beteiligt sein können.
+ Das Bewegen scheitert allerdings erst am Schluss der Bewegung.
+ Sie müssen sich dann wieder zurück bewegen.
+
+\layout Standard
+
+Man kann somit fast lückenlos Felder übergeben.
+ Daraus ergibt sich, dass man Alliierte nicht angreifen kann, so lange sie
+ Freunde sind.
+
+\layout Subsubsection*
+
+Tempel bauen
+\layout Standard
+
+Diese Aktion erzeugt auf einem Feld einen Tempel einer Gottheit.
+ Es ist nur möglich, Tempel zu erzeugen, wenn der Spieler mindestens einen
+ Priester der passenden Gottheit dort hat und das Feld ein heiliger Berg
+ oder eine gesegnete Insel ist.
+ Wenn es ein heiliger Berg ist, darf nur ein Tempel des Gottes gebaut werden,
+ dem der Berg gewidmet ist.
+ Auf jedem Feld kann es immer nur einen Tempel geben.
+\layout Standard
+
+Tempel zu bauen geht am Anfang des Spiels recht schnell, dauert aber um
+ so länger, je mehr Tempel schon gebaut sind.
+ Jeder Erdling will schließlich den schönsten Tempel der Welt haben, und
+ das dauert natürlich seine Zeit.
+ Wenn alle Tempel gebaut sind, endet das Spiel sofort.
+
+\layout Standard
+
+Der Manapol, der dem neuesten Tempel am nächsten ist, wird zur Insel des
+ Schicksals.
+ Wenn mehrere Manapole gleich weit entfernt sind, bleibt die aktuelle Aymargeddo
+n bestehen.
+ (noch nicht implementiert)
+\layout Subsubsection*
+
+Schlachtordnung festlegen
+\layout Standard
+
+Erdlinge können angeben in welcher Schlachtordnung ihre Armeen in den Krieg
+ ziehen.
+ Es wird eine Reihenfolge angegeben in der die Einheiten aufgestellt werden.
+ Mit der Reihenfolge kann jeder Erdling angeben, welche eigenen Einheiten
+ in vorderster Front stehen und somit zuerst sterben sollen.
+ So kann man zum Beispiel zuerst Krieger sterben lassen, dann Helden und
+ dann erst die Priester.
+\layout Standard
+
+Die Reihenfolge gilt immer für die ganze Welt.
+\layout Standard
+
+Die voreingestellte Reihenfolge ist: Krieger, Helden, Priester.
+
+\layout Standard
+
+Die Reihenfolge ist allerdings nicht absolut, sondern gibt nur die Wahrscheinlic
+hkeit des Todes an.
+\layout Standard
+
+Archen befinden sich immer in der letzten Reihe der Schlachtordnung.
+ Jede Arche, die
+\begin_inset Quotes pld
+\end_inset
+
+stirbt
+\begin_inset Quotes prd
+\end_inset
+
+ wird mit einer gewissen Wahrscheinlichkeit versenkt und mit einer gewissen
+ Wahrscheinlichkeit vom Gegner erobert.
+\layout Subsection*
+
+Aktionen der Götter
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wenn Dich das nächste Mal jemand fragt, ob Du ein Gott bist, sag ja.
+\begin_inset Quotes prd
+\end_inset
+
+ (aus: Ghostbusters)
+\layout Standard
+
+Alle folgenden Aktionen kosten Mana.
+ Neues Mana erhält ein Gott, wenn seine Priester an den richtigen Tempeln
+ beten.
+ Alle zehn Zeiteinheiten gibt es pro Priester und Tempel einen Manapunkt
+ (MP).
+\layout Subsubsection*
+
+Avatar erschaffen
+\layout Standard
+
+Ein Avatare erscheint immer an dem eigenen Tempel an dem am meisten eigene
+ Priester beten.
+ Ein Avatar kostet 5 MP.
+
+\layout Subsubsection*
+
+Held weihen
+\layout Standard
+
+Ein Krieger kann nur an eigenen Tempeln zum Helden geweiht werden.
+ Das kostet 1 MP.
+\layout Description
+
+Priester
+\series medium
+
+\series bold
+erleuchten
+\layout Standard
+
+Einen Priester kann man nur aus einem Krieger erzeugen, wenn der Gott das
+ entsprechende Feld einsehen kann (siehe Sicht-Abschnitt).
+ Diese Aktion kostet 5 MP.
+
+\layout Subsubsection*
+
+Avatare bewegen
+\layout Standard
+
+Avatare dürfen sich auch auf die Insel des Schicksals begeben (allerdings
+ nicht mehr von ihr weg).
+ Das Bewegen eines Avatars geht deutlich schneller als das Bewegen der Erdlinge
+ (Eine Zeiteinheit).
+ Es kostet immer 1 MP pro Feld und Avatar.
+ Avatare reisen umsonst auf Schiffen mit.
+\layout Standard
+
+Avatare dürfen sich nicht auf Wasser- oder Inselfelder bewegen, ausser mit
+ einer Arche (von Erdlingen gesteuert).
+ Von Wasserfeldern aus, dürfen sie sich auch alleine auf Landfelder oder
+ Manapole bewegen.
+\layout Subsubsection*
+
+Verseuchen
+\layout Standard
+
+Ein Gott kann die Erde mit Seuchen überziehen.
+ Das hat unterschiedliche Auswirkungen je nach Art der Seuche.
+ Seuchen verbreiten sich mit einer gewissen Wahrscheinlichkeit auf Nachbarfelder
+ sowie bei Bewegungen von Erdlingseinheiten.
+ Die Anwesenheit von Priestern erhöht die Wahrscheinlichkeit, dass die Seuche
+ aufhört.
+ Die Kosten für Seuchen hängen von der Art der Seuche ab.
+ Zum Verseuchen benötigt man einen anwesenden Avatar und in dem Feld darf
+ gerade kein Götterkampf (s.u.) stattfinden.
+
+\layout Standard
+
+Verseucht sind immer ganze Felder, keine einzelnen Einheiten.
+ Städte stecken sich leichter an als Landfelder, Landfelder leichter als
+ Berge, Berge leichter als Inseln, Inseln leichter als Wasserfelder.
+\layout Standard
+
+Es gibt zur Zeit drei verschiedene Seuchen:
+\layout Standard
+
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="4" columns="3">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Seuche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Effekt
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Mana
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Influenza
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Städte und Tempel produzieren nicht mehr
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Pestilentia
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+50% aller Leute sterben
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+20
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Ebola
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+100% aller Leute sterben
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Wenn Leute sterben, so geschieht das nach den Regeln bei Erdlingskämpfen
+ (s.u.).
+\layout Standard
+
+Eine Seuche hat alle 20 Zeiteinheiten erneut ihren in der Tabelle beschriebenen
+ Effekt.
+\layout Subsubsection*
+
+Sintfluten
+\layout Standard
+
+Avatare können eine Ebene oder einen Berg überfluten, die an ein Wasser-
+ oder Inselfeld grenzen, wenn sie vor Ort sind und in dem Feld gerade kein
+ Götterkampf(s.u.) stattfindet.
+ Eine Sintflut kostet nur 2 MP, dauert aber 40 Zeiteinheiten.
+ Berge werden durch Überfluten zu Inseln.
+ Dadurch ändert sich ihre Exklusivität, und von nun an können auch andere
+ Götter an ihnen angebetet werden.
+ Städte und Inseln kann man nicht überfluten.
+\layout Standard
+
+Wenn zum Zeitpunkt des Flutens einer Ebene noch Einheiten im Feld sind,
+ benötigen sie eine Arche, um nicht unterzugehen.
+\layout Subsubsection*
+
+Avatarstatus ändern
+\layout Standard
+
+Jede Gruppe von Avataren eines Spielers in einem Feld hat einen Status.
+ Dieser kann
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+,
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ oder
+\series bold
+\shape smallcaps
+Ignorieren
+\series default
+\shape default
+ sein.
+ Mit
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+ hilft man befreundeten Erdlingen, wenn es zu Kämpfen kommt.
+ Mit
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ schlägt man sich mit verfeindeten Avataren, wenn diese ins Feld kommen.
+ Man kann immer nur eines von beidem gleichzeitig tun.
+
+\layout Standard
+
+Sich bewegende Avatare nehmen ihren Status mit.
+ Wenn zwei Gruppen von Avataren des selben Spielers zusammentreffen, wird
+ immer automatisch
+\series bold
+\shape smallcaps
+Block
+\series default
+\shape default
+ vor
+\series bold
+\shape smallcaps
+Helfe
+\series default
+\shape default
+ vor
+\series bold
+\shape smallcaps
+Frieden
+\series default
+\shape default
+ für die neue gemeinsame Gruppe gewählt.
+
+\layout Subsubsection*
+
+Tempel zerstören
+\layout Standard
+
+Götter können den Tempel eines anderen Gottes auf einer gesegneten Insel
+ zerstören.
+ Dort dürfen sich keine Priester eines anderen Gottes befinden, außerdem
+ braucht man einen eigenen Avatar in dem Feld und es darf dort kein Götterkampf
+ (s.u.) stattfinden.
+ Dieser Befehl kostet 5 MP.
+ Wenn nur noch ein Tempelfeld unbebaut ist, kann man keine Tempel mehr zerstören.
+
+\layout Standard
+
+Es gibt im Wesentlichen zwei Anwendungsfälle für diesen Befehl:
+\layout Enumerate
+
+Ein Gott will eine gesegnete Insel übernehmen, damit ein
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+ver
+\backslash
+-bün
+\backslash
+-de
+\backslash
+-ter
+\end_inset
+
+ Erdling ihm dort einen Tempel errichtet.
+ Dafür muss der alte Tempel zerstört werden.
+
+\layout Enumerate
+
+Ein Gott will das drohende Spielende hinauszögern, weil er für später bessere
+ Siegchancen sieht.
+ Danach sollte man Erdlinge dazu überreden, das leere Baufeld auch zu verteidige
+n.
+ Wenn jedoch einmal der Baubefehl für den letzten Tempel gegeben ist, ist
+ es zu spät, das Ende der Welt noch aufzuhalten.
+\layout Subsubsection*
+
+Glücksfaktor verändern
+\layout Standard
+
+Mit diesem Befehl kann man angeben, ob man den globalen
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+Glücks
+\backslash
+-fak
+\backslash
+-tor
+\end_inset
+
+, der auf alle Kämpfe mit Ausnahme der letzten Schlacht angewandt wird,
+ erhöhen oder erniedrigen will.
+ Man gibt an, wie viele Manapunkte man investieren will.
+ Pro MP ändert sich der Glücksfaktor um einen Punkt auf einer Skala von
+ 3 bis 12.
+\layout Standard
+
+Der Glücksfaktor ist immer für alle Spieler gleich hoch, es gibt also nur
+ einen Glücksfaktor für alle Spieler.
+\layout Subsubsection*
+
+Arche bauen
+\layout Standard
+
+Ein Gott kann auf einem Feld, dass er sieht, eine Arche bauen.
+ Steuern kann er sie nicht.
+ Die Arche gehört dem derzeitigen Feldeigentümer.
+\layout Standard
+
+Eine Arche zu bauen kostet 5 MP und dauert 30 Zeiteinheiten.
+\layout Section
+
+Beten
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Wer Gott definiert, ist schon Atheist.
+\begin_inset Quotes prd
+\end_inset
+
+ (Oswald Spengler)
+\layout Standard
+
+Die Götter erhalten alle 10 Zeiteinheiten einen MP pro Tempel und pro rechtgläub
+igem Priester an diesem Tempel ebenso ein MP.
+ Die Anzahl effektiv betender Priester pro Tempel ist allerdings auf den
+ aktuellen Glücksfaktor begrenzt.
+ An heiligen Bergen können doppelt so viele Priester effektiv beten.
+\layout Section
+
+Infos
+\layout Standard
+
+Folgende generelle Daten sind für alle Mitspieler jedezeit abrufbar.
+ Sie beziehen sich auf das ganze Spiel und nicht auf einzelne Felder.
+
+\layout Itemize
+
+Der aktuelle Glücksfaktor
+\layout Itemize
+
+Die Anzahl nicht gebauter Tempel
+\layout Itemize
+
+Die Stärke auf der Insel des Schicksals
+\layout Itemize
+
+Die Anzahl der Avatare auf den Manapolen (noch nicht implementiert)
+\layout Itemize
+
+Die Gesamtstärke jeden Erdlings (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl der lebenden Avatare jedes Gottes (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl der Priester jedes Gottes (noch nicht implementiert)
+\layout Itemize
+
+Die Anzahl Städte jedes Erdlings
+\layout Standard
+
+Dadurch kann man immer die Stärke eines anderen Spielers ungefähr einordnen
+ und sieht, wer auf dem Weg zum Sieg ist.
+\layout Standard
+
+Erdlinge sehen außerdem noch die Sterbereihenfolge ihrer Einheiten.
+ Götter sehen ihren aktuellen Manastand.
+\layout Subsection*
+
+Sichtrechte
+\layout Standard
+
+Sichtrecht hat man für folgende Felder:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="3" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Götter
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Erdlinge
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+eigene Holys
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Heimatstädte
+\end_inset
+</cell>
+</row>
+<row bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+anwesende Priester oder Avatare
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+anwesende Priester, Krieger oder Helden
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Von Bergen aus sieht man zwei Felder weit, sonst nur eins.
+\layout Standard
+
+Andere Spieler können einem Sichtrechte gewähren.
+ Dies tun sie durch den Allianzstatus
+\begin_inset Quotes pld
+\end_inset
+
+Alliiert
+\begin_inset Quotes prd
+\end_inset
+
+ oder
+\begin_inset Quotes pld
+\end_inset
+
+Verrat
+\begin_inset Quotes prd
+\end_inset
+
+.
+
+\begin_inset Quotes pld
+\end_inset
+
+Freund
+\begin_inset Quotes prd
+\end_inset
+
+ gewährt keine Sichtrechte.
+\layout Standard
+
+Als anwesend zählen auch nicht-aktive Einheiten (die sich zum Beispiel gerade
+ in der Bewegung befinden).
+\layout Standard
+
+Wenn man Sichtrecht für ein Feld hat, kann man jederzeit die Infos zu diesem
+ Feld abrufen.
+\layout Section
+
+Kampf
+\layout Standard
+
+Götter können Erdlinge nicht direkt attackieren, sie können nur andere Erdlinge
+ bei diesen Angriffen unterstützen.
+
+\layout Standard
+
+Bei jedem Kampf außer der letzten Schlacht werden die Kampfstärken der beteiligt
+en Einheiten addiert und zusätzlich ein Zufallswert zwischen eins und dem
+ Glücksfaktor dazugezählt.
+
+\layout Standard
+
+Jeder Kampf dauert eine gewisse Zeitspanne.
+ Alle in dieser Zeitspanne hinzustoßenden Einheiten nehmen am Kampf teil
+ oder werden vom Kampf ausgeschlossen.
+ In letzterem Fall kehren sie einfach wieder um.
+\layout Subsection*
+
+Erdlingskampf
+\layout Standard
+
+Ein Erdlingskampf wird ausgelöst, wenn Einheiten eines neutralen oder verfeindet
+en Erdlings - im Folgenden Angreifer genannt - ein Feld betreten, dessen
+ Eigentümer im Folgenden Verteidiger genannt wird.
+ Alle Einheiten dieser beiden Parteien, die wärend der Kampfdauer zum Kampf
+ dazu stoßen, nehmen am Kampf teil.
+ Einheiten Dritter werden vom Kampf ausgeschlossen.
+ Eine Möglichkeit, sich aus einem einmal begonnenen Kampf herauszuhalten,
+ gibt es nicht.
+\layout Standard
+
+Die Kampfstärke beider Seiten ergibt sich aus der Summe der Kampfstärken
+ der beteiligten Einheiten.
+ Beide Seiten eines Kampfes addieren einen Zufallswert, der zwischen 1 und
+ dem aktuellen Glücksfaktor liegt, zu ihrer Kampfstärke.
+
+\layout Standard
+
+Dem bisherigen Eigentümer reicht ein Unentschieden zum Sieg.
+
+\layout Standard
+
+Eine Partei, die einen Kampf verliert, muss ihre Überlebenden zurückziehen.
+ Alle Einheiten ziehen sich einzeln zurück.
+
+\layout Standard
+
+Dazu wird nach dem Zufallsprinzip eines der Nachbarfelder ausgewählt, das
+ dem Verlierer gehört oder neutral ist und in dem zum Zeitpunkt des Rückzuges
+ kein Kampf stattfindet.
+ Ein Rückzug ist wie eine normale Bewegung und braucht Zeit.
+ Archen ziehen sich immer zuerst zurück.
+ Archen auf Küstenfeldern können sich nur auf Wasser oder Inselfelder zurückzieh
+en.
+ Andere Einheiten können sich nur auf Landfelder zurückziehen oder auf solche,
+ auf die sich bereits Archen zurückgezogen haben.
+\layout Standard
+
+Es kann passieren, dass das Feld bei Ankunft der Flüchtenden auch schon
+ einem anderen Spieler gehört, dann kommt es dort direkt wieder zum Kampf.
+ Flüchtende Einheiten können also von Feld zu Feld gejagt und dabei aufgerieben
+ werden.
+ Ein gut geplanter Angriff auf breiter Front kann diese Regel bewusst ausnutzen.
+\layout Standard
+
+Natürlich kann man beim Kämpfen auch zu schaden kommen: Der Verlierer verliert
+ die Hälfte der Kampfstärke des Gewinners (ohne Avatare und Flankierung)
+ an Leuten.
+ Der Gewinner verliert ein Viertel der Kampfstärke des Verlierers.
+ Der Gewinner behält mindestens eine Person (oder Arche), der Verlierer
+ verliert mindestens eine.
+ Die Schlachtordnung bestimmt wieviele Leute welcher Art anteilig sterben.
+\layout Standard
+
+Sollte ein Spieler nach einem verlorenen Kampf keinerlei Rückzugsmöglichkeiten
+ mehr haben, sterben alle seine Einheiten in diesem Feld.
+
+\layout Standard
+
+Doch jetzt endlich zu den Kampfstärken:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Einheit
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Modifikator
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++0
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Held
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++2
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+bis zu +4
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Heimatstadt
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++2
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Arche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++3
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+pro Flankierung
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Dabei ist +0 nicht so sinnlos, wie es auf den ersten Blick aussieht: Sind
+ nur Prieser anwesend, können sie wenigstens auf ihr Würfelglück hoffen,
+ wenn sie angegriffen werden und tragen zur Avatarunterstützung bei, wenn
+ diese vorhanden ist.
+\layout Standard
+
+Avatare kämpfen natürlich nur mit, wenn sie im Status
+\begin_inset Quotes pld
+\end_inset
+
+Helfe
+\begin_inset Quotes prd
+\end_inset
+
+ sind, und Mannapunkte übrig haben (2 MP pro Kampf unabhängig von der Anzahl
+ Avatare).
+ Sie geben maximal 4 Punkte Bonus.
+ Dabei wird pro kämpfendem Erdling ein Punkt verbraucht (egal ob Krieger,
+ Held oder Priester).
+
+\layout Standard
+
+Den Flankierungsbonus erhält man für jedes benachbarte Feld, das folgende
+ Bedingungen erfüllt:
+\layout Itemize
+
+Es muss einem selbst oder einem Spieler mit dem Status
+\begin_inset Quotes pld
+\end_inset
+
+Freund
+\begin_inset Quotes prd
+\end_inset
+
+ oder
+\begin_inset Quotes pld
+\end_inset
+
+alliiert
+\begin_inset Quotes prd
+\end_inset
+
+ gehören;
+\layout Itemize
+
+der Eigentümer des Feldes muss zum Zeitpunkt des Kampfes noch aktive Einheiten
+ dort stehen haben;
+\layout Itemize
+
+es darf nicht selbst umkämpft sein.
+
+\layout Itemize
+
+Es darf kein Wasserfeld sein.
+ Inseln flankieren aber ganz normal.
+\layout Standard
+
+Dadurch kann man Gebiete, die aus zusammenhängenden benachbarten Feldern
+ bestehen, besser verteidigen.
+\layout Subsection*
+
+Avatarkampf
+\layout Quotation
+
+
+\emph on
+
+\begin_inset Quotes pld
+\end_inset
+
+Jetzt hast Du, tapferer Soldat, jetzt hast Du, streitbarer Mann, einen Ort,
+ wo Du ohne Gefahr kämpfen kannst, wo der Sieg Ruhm und der Tod Gewinn ist.
+\begin_inset Quotes prd
+\end_inset
+
+ (Bernhard von Clairveaux, 1146 n.u.Z., zum zweiten Kreuzzug aufrufend)
+\layout Standard
+
+Avatare haben immer einen von drei Zuständen.
+ Mit
+\begin_inset Quotes pld
+\end_inset
+
+Helfe
+\begin_inset Quotes prd
+\end_inset
+
+ helfen sie Erdlingen, wie oben angesprochen.
+ Mit
+\begin_inset Quotes pld
+\end_inset
+
+Block
+\begin_inset Quotes prd
+\end_inset
+
+ blockieren sie andere Avatare, um gegen sie zu kämpfen.
+ Ist ihr Zustand
+\begin_inset Quotes pld
+\end_inset
+
+Ignoriere
+\begin_inset Quotes prd
+\end_inset
+
+, wollen sie mit niemandem Streit.
+ Die Avatare eines Gottes in einem Feld können nur den gleichen Zustand
+ haben.
+
+\layout Standard
+
+Nur der Status
+\begin_inset Quotes pld
+\end_inset
+
+Block
+\begin_inset Quotes prd
+\end_inset
+
+ kann zu Avatarkämpfen führen.
+ Dies geschieht, wenn
+\layout Itemize
+
+einer der beiden den anderen als Feind betrachtet und er oder der andere
+ 'Blockieren' eingestellt hat, oder
+\layout Itemize
+
+wenn zwei Götter aufeinander treffen, die einander beide 'Neutral' gegenübersteh
+en aber beide 'Blockiere' eingestellt haben.
+\layout Standard
+
+Zu Kämpfen kann es nur dann kommen, wenn Avatare in ein Feld ziehen oder
+ wenn der Avatarstatus auf blockieren geändert wird.
+ Für jeden schon anwesenden Gott wird einzeln ermittelt, ob es zu einem
+ Kampf mit dem Neuankömmling kommt.
+ Es kann dabei durchaus zu mehreren parallel verlaufenden Kämpfen kommen,
+ die auch im Folgenden einzeln abgewickelt werden.
+ Wenn ein Avatar in ein Feld kommt, in dem er schon vertreten ist, löst
+ das nie einen Kampf aus.
+\layout Standard
+
+Avatarkämpfe kosten 2 MP unabhängig von der Anzahl der beteiligten Avatare.
+ Wenn ein Gott nicht mehr genügend MP hat, darf der Gott noch auf sein Würfelglü
+ck hofen, aber seine Avatare kämpfen nicht mehr mit.
+\layout Standard
+
+Avatarkämpfe dauern länger als die Kämpfe der Erdlinge; und da Avatare sehr
+ schnell sein können, kann man eventuell auch noch aus einiger Entfernung
+ Kräfte hinzuziehen.
+ Man darf Avatare nicht aus einem umkämpften Feld wegziehen, auch wenn man
+ an keinem der Kämpfe beteiligt ist.
+
+\layout Standard
+
+Sollte im selben Feld bereits ein Erdlingskampf stattfinden, so wird der
+ Avatarkampf bis nach dem Erdlingskampf verschoben.
+
+\layout Standard
+
+Jeder Avatar zählt +4, und es wird ganz normal gewürfelt.
+ Der Verlierer verliert die Hälfte der Avatare des Gewinners und der Gewinner
+ verliert ein Viertel der Avatare des Verlierers.
+ Bei einem unentschieden gelten beide Seiten als Verlierer.
+ Die Seelen sterbender Avatare fahren in eventuell anwesende Krieger des
+ Feldeigentümers und machen diese zu Helden.
+ Alle Avatare des Verlierers die danach noch im Feld sind werden an den
+ Ort der Avatarerschaffung zurückteleportiert.
+\layout Standard
+
+Avatare, die in einem Götterkampf beschäftigt sind, dürfen keine Erdlinge
+ bei ihren Kämpfen unterstützen.
+\layout Subsection*
+
+Die letzte Schlacht
+\layout Standard
+
+In der letzten Schlacht wird nicht gewürfelt.
+ Es zählen nur die Kampfwerte:
+\layout Standard
+\added_space_top 0.3cm \added_space_bottom 0.3cm \align center
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="3" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Einheit
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Kampfwert
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++7
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Geist eines Helden
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
++1
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+Für die Geister der Helden zählt der angebetete Gott.
+ Diese Helden kämpfen also immer noch für ihren Gott, auch wenn der Erdling
+ inzwischen längst vom Glauben abgefallen ist.
+\layout Section
+
+Timing
+\layout Standard
+
+Alle Aktionen dauern unterschiedlich lange.
+ Dabei gibt es in jedem Spiel eine einstellbare Spielgeschwindigkeit, mit
+ der die Werte unten multipliziert werden.
+ Die Zahlen in der Tabelle können also sowohl Minuten als auch Tage meinen,
+ je nachdem wie schnell man spielt.
+ Die Spielgeschwindigkeit kann sich auch während eines Spieles ändern.
+ Es kann zum Beispiel sinnvoll sein, das Spiel am Anfang langsamer laufen
+ zu lassen, bis eine angemessene Anzahl Mitspieler eingestiegen ist.
+ Jede Änderung der Spielgeschwindigkeit wird rechtzeitig vorher bekannt
+ gegeben und sollte nicht zu apprupt erfolgen.
+\layout Standard
+
+
+\begin_inset Tabular
+<lyxtabular version="3" rows="17" columns="2">
+<features islongtable="true">
+<column alignment="center" valignment="top" leftline="true" width="0pt">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0pt">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Aktion
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Dauer
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+12
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Held bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatar bewegen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Erdlingskampf
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatarkampf
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tempel bauen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+3, 6 , 9, ...
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Überfluten
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+20
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Bewegen mit Arche
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Krieger produzieren
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40 + N (20)
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Priester produzieren
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+40
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Glücksfaktor verändern
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Avatarstatus ändern
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Arche bauen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+30
+\end_inset
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Beten
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+alle anderen Aktionen
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+0
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\layout Standard
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash
+medskip
+\end_inset
+
+
+\layout Section
+
+Spielanfang
+\layout Standard
+
+Die Götter starten mit 33 Mana.
+ Sie sollten daher zusehen, dass sie möglichst bald Priester erzeugen, damit
+ diese Tempel bauen können, die wieder Priester produzieren und damit wieder
+ Mana.
+ Dafür ist eine Kooperation mit mindestens einem Erdling nötig.
+\layout Standard
+
+Die Erdlinge stehen am Anfang vor der Entscheidung, wo sie ihre ersten Krieger
+ hinschicken sollen.
+ Dies kann zum Beispiel auf ein Tempelfeld sein, weil man davon ausgeht,
+ dass der Krieger in einen Priester umgewandelt wird.
+ Außerdem ist es ratsam, sich früh mit seinen Nachbarn abzusprechen, wer
+ welchen Tempel baut.
+ Ansonsten kann es zu unliebsamen Überraschungen kommen, die einen gleich
+ die ersten Krieger verlieren lassen!
+\layout Standard
+
+Der Glücksfaktor ist am Anfang auf seinem Minimalwert von 3.
+\layout Standard
+
+Götter, die nachträglich einsteigen, erhalten etwas Bonusmana pro vergangener
+ Zeiteinheit.
+ Erdlinge, die neu einsteigen, profitieren davon, dass ihre Heimatstadt
+ schon die ganze Zeit Krieger produziert hat.
+\layout Section
+
+Spielende (nur teilweise implementiert)
+\layout Standard
+
+Das Spiel endet, sobald alle Tempel gebaut wurden.
+ Mit dem Baubefehl des letzten Tempels wird allen Spielern bekanntgegeben,
+ wie lange das Spiel noch dauert.
+ Dann gibt es kein Zurück mehr.
+\layout Standard
+
+Es gewinnt der Erdling, der die meisten Städte sein eigen nennt.
+ Dabei zählen besetzte feindliche Heimatstädte und verseuchte Städte mit.
+ Bei gleicher Anzahl Städte entscheidet die Gesamtkampfstärke des Erdlings.
+ Sollte die auch gleich sein, wird gewürfelt.
+
+\layout Standard
+
+Der Gott, der in der letzten Schlacht die meisten Kräfte auf sich vereint,
+ gewinnt.
+ Dabei muss kein Mana mehr ausgegeben werden und es wird auch nicht mehr
+ gewürfelt.
+ Sollte die letzte Schlacht unentschieden ausgehen, zählen die Anzahl lebender
+ Avatare.
+ Wenn diese auch gleich sind, die Anzahl der Tempel.
+ Wenn dann immer noch Gleichstand herrscht, zählt das übrige Mana.
+ Sollte wider erwarten selbst dieses gleich sein, wird am Ende doch noch
+ gewürfelt.
+\layout Standard
+
+Alle Spieler erhalten zum Abschluss eine Rangliste und den Ausgang der letzten
+ Schlacht.
+\layout Standard
+
+Mit jedem Spiel kann man Punkte für die ewige Bestenliste sammeln, allerdings
+ nur als Sieger.
+ Zweite Plätze zählen nicht.
+\layout Section
+
+FAQ
+\layout Subsection*
+
+Was bedeutet
+\shape italic
+Aymargeddon
+\shape default
+?
+\layout Standard
+
+Der Name des Spiels leitet sich von
+\shape italic
+Armageddon
+\shape default
+ her.
+ Das wiederum basiert auf dem hebräischen
+\shape italic
+Har
+\shape default
+, was
+\shape italic
+Berg
+\shape default
+ bedeutet, und der Ortschaft
+\shape italic
+Megeddon
+\shape default
+, bei der laut der Sage die letzte Schlacht geschlagen werden wird.
+ Da in unserem Spiel die letzte Schlacht auf einer Insel stattfindet, haben
+ wir
+\shape italic
+Har
+\shape default
+ durch
+\shape italic
+Ay
+\shape default
+ ersetzt, was
+\shape italic
+Insel
+\shape default
+ bedeutet.
+
+\layout Standard
+
+Das
+\begin_inset Quotes pld
+\end_inset
+
+r
+\begin_inset Quotes prd
+\end_inset
+
+ gehört da nicht wirklich hin, nein.
+ Aber wir haben das erst entdeckt, als wir die Domain schon bestellt hatten
+ und es klingt eh besser so, oder? Ausserdem gibt
+\begin_inset Quotes pld
+\end_inset
+
+Aymageddon
+\begin_inset Quotes prd
+\end_inset
+
+ unanständige Suchergebnisse bei Google.
+\layout Subsection*
+
+Heißt es
+\shape italic
+der
+\shape default
+,
+\shape italic
+die
+\shape default
+, oder
+\shape italic
+das
+\shape default
+ Aymargeddon?
+\layout Standard
+
+Kommt darauf an.
+\layout Standard
+
+Wenn die Insel des Schicksals gemeint ist, heißt es
+\shape italic
+die
+\shape default
+, wenn das Spiel gemeint ist, heißt es
+\shape italic
+das
+\shape default
+ und wenn der Server gemeint ist, heiß es
+\shape italic
+der
+\shape default
+ Aymargeddon.
+\layout Standard
+
+Das ist allerdings nur die Erdlingssicht.
+ Götter geben sich mit solch kleinlichen Geschlechterfragen nicht ab, wenn
+ es um Schicksalsfragen wie das Ende der Welt geht.
+\layout Subsection*
+
+Gibt es Vorläufer zu Aymargeddon?
+\layout Standard
+
+Das Spiel basiert auf einem - leider noch unveröffentlichten - Brettspiel
+ namens
+\shape italic
+Ragnarök
+\shape default
+ beziehungsweise dem zugehörigen Play-by-E-Mail
+\shape italic
+Ragnarök als Pbem
+\shape default
+.
+ Beide Spiele hat Benni Bärmann entwickelt.
+ Die grundlegenden Konzepte sind erhalten geblieben.
+ Aber natürlich erforderte der geänderte Zugrhythmus und die höhere Spieleranzah
+l einige Anpassungen.
+\layout Subsection*
+
+Wie viel Zeit braucht Aymargeddon?
+\layout Standard
+
+Das hängt von der Spielgeschwindigkeit ab.
+
+\layout Standard
+
+Bei niedriger Spielgeschwindigkeit braucht man sich nur gelegentlich einzuloggen
+, um zu gucken, was es Neues gibt.
+ Dafür kann sich ein Spiel dann auch schon mal ein paar Monate hinziehen.
+
+\layout Standard
+
+Bei hoher Spielgeschwindigkeit sitzt man mehr oder weniger die ganze Zeit
+ vorm Rechner, dafür ist es dann aber auch nach ein paar Stunden vorbei.
+\layout Standard
+
+Bei gleicher Spielgeschwindigkeit ist das Spiel als Gott tendenziell aufwendiger
+ als das als Erdling.
+ Als Erdling kann man fast sicher sein, nichts wichtiges zu verpassen, wenn
+ man sich so oft einloggt, wie ein Erdlingskampf dauert.
+\layout Subsection*
+
+Was brauche ich, um mitspielen zu können?
+\layout Standard
+
+Eigentlich nichts, außer einer funktionierenden E-Mail-Adresse und einem
+ üblichen Web-Browser.
+\layout Standard
+
+Was man natürlich auch noch braucht, sind Spaß am Spiel, Verhandlungsgeschick,
+ etwas Zeit und ein bisschen Glück.
+\layout Subsection*
+
+Wie sehen sinnvolle erste Züge als Erdling aus?
+\layout Standard
+
+Man sollte sich auf jeden Fall möglichst bald mit den Göttern absprechen,
+ deren heilige Orte man sieht, beziehungsweise auf die Suche nach solchen
+ Orten gehen.
+ Danach sollte man möglichst Tempel bauen für die Götter, damit diese schnell
+ Mana kriegen, mit dem sie einen dann (hoffentlich) unterstützen.
+\layout Standard
+
+Dabei ist es ratsam, auch die irdischen Nachbarn nicht zu vernachlässigen
+ und dafür zu sorgen, dass sie nicht in der Zwischenzeit alle strategisch
+ wichtigen Punkte unter sich aufteilen.
+\layout Standard
+
+Wenn man erste Städte erobert hat, muß man sich überlegen ob man sofort
+ weiterzieht oder erst abwartet, bis dort ein Krieger erzeugt wird.
+ Im ersten Fall kommt man schneller voran und kann vieleicht weitere Städte
+ vor den Nachbarn erreichen, im zweiten Fall produziert man schneller neue
+ Krieger.
+\layout Subsection*
+
+Wie sehen sinnvolle erste Züge als Gott aus?
+\layout Standard
+
+Ein Gott sollte am Anfang hauptsächlich durch Verhandlungen abklären, welche
+ Erdlinge ihm möglichst bald Tempel auf seinen exklusiven heiligen Bergen
+ errichten.
+
+\layout Standard
+
+Bald kann man dann schon Avatare und möglicherweise sogar Helden erzeugen
+ und kriegt neues Mana.
+
+\layout Standard
+
+Es kann sinnvoll sein, die wertvollen Tempel mit Avataren zu schützen, damit
+ nicht kleinliche Streitereien zwischen Erdlingen den wertvollen Manastrom
+ verringern.
+\layout Subsection*
+
+Können Erdlingsarmeen aneinander vorbeilaufen?
+\layout Standard
+
+Ja.
+
+\layout Subsection*
+
+Gibt es nicht zu unausgewogene Startpositionen?
+\layout Standard
+
+Gerade die Unausgewogenheit der Startpositionen zwingt zu Verhandlungen.
+ Deswegen werden die dafür relevanten Informationen (mit denen die Spieler
+ abschätzen können, wer führt) ja auch zur Verfügung gestellt.
+\layout Subsection*
+
+Was passiert, wenn jemand aufhört?
+\layout Standard
+
+Seine Einheiten bleiben einfach da stehen, wo sie sind, und rühren sich
+ nicht.
+ Krieger und Priester eines ausgestiegenen Erdlings werden aber noch weiterhin
+ erzeugt.
+
+\layout Standard
+
+Bei Göttern ist das lästiger als bei Erdlingen, da das Spielgleichgewicht
+ stärker beeinträchtigt wird.
+ Schön ist es natürlich in keinem Fall.
+
+\layout Standard
+
+Nichtaktive Spieler können jederzeit übernommen werden von Neueinsteigern.
+
+\layout Subsection*
+
+Was passiert, wenn ich eine Weile nicht ziehe?
+\layout Standard
+
+Wenn das lange dauert, geht der Server davon aus, dass Du nicht mehr spielen
+ willst, und gibt Deine Einheiten zur Übernahme frei.
+ (noch nicht implementiert)
+\layout Subsection*
+
+Soll ich einen Gott oder einen Erdling spielen?
+\layout Standard
+
+Die Götterrolle ist die anspruchsvollere.
+ Man muß mehr verhandeln und hat mehr Möglichkeiten.
+ Das ist Vor- und Nachteil zugleich.
+ Ganz ohne Verhandlung wird man Aymargeddon nicht gewinnen können, aber
+ Leute, die nicht allzusehr auf Verhandlungen aus sind, sollten lieber eine
+ Erdlingsrolle übernehmen.
+ Man sollte auch nur einen Gott spielen, wenn man häufig online ist, da
+ Götteraktionen im allgemeinen weniger Zeit brauchen.
+\layout Standard
+
+Beim Spielanfang kann man auch
+\begin_inset Quotes pld
+\end_inset
+
+egal
+\begin_inset Quotes prd
+\end_inset
+
+ als gewünschte Rolle angeben.
+ Dann gibt einem der Server die Rolle, die dafür sorgt, dass das Zahlenverhältni
+s 1:2 von Göttern zu Erdlingen annähernd erreicht wird.
+ Es kann auch vorkommen, dass in einem Spiel gar keine Erdlinge beziehungsweise
+ Götter mehr zugelassen sind, weil zu weit vom idealen Verhältnis abgewichen
+ wurde.
+\layout Subsection*
+
+Gehören Städte, die ich einmal in Besitz genommen habe, mir auch noch, wenn
+ ich sie wieder verlasse?
+\layout Standard
+
+Nein.
+ Alle Städte, die keine Heimatstädte sind, werden neutral, sobald kein aktiver
+ Priester, Krieger oder Held mehr in ihnen steht.
+ Heimatstädte gehören dem Spieler, dessen Heimat sie sind, jedoch auch,
+ wenn keine Einheiten dort stehen.
+ Heimatstädte verteidigen sich auch, ohne dass in ihnen Einheiten stehen
+ müssen.
+\layout Subsection*
+
+Darf man mehrere Positionen im selben Spiel besetzen?
+\layout Standard
+
+Nein, aber man darf in mehreren Spielen gleichzeitig mitspielen.
+\layout Subsection*
+
+Warum sind Avatare wasserscheu?
+\layout Standard
+
+Ist ja eigentlich schon etwas komisch, wo sie doch ansonsten so mächtig
+ sind.
+ Die Erklärung ist ganz einfach: Auf ihrer Reise zur Erde mussten sie entweder
+ in einem furchtbaren Gewitter auf einer Bergspitze erscheinen oder sich
+ von einer Insel ans nahe, rettende Ufer quälen.
+ Nach dieser Erfahrung hat niemand mehr Lust auf Wasser!
+\layout Section*
+
+Copyright
+\layout Standard
+
+(c) 2003, 2004, 2005 Aymargeddon Development Team
+\layout Standard
+
+Permission is granted to copy, distribute and/or modify this document under
+ the terms of the GNU Free Documentation License, Version 1.1 or any later
+ version published by the Free Software Foundation; with no Invariant Sections,
+ with no Front-Cover Texts, and with no Back-Cover Texts.
+ A copy of the license is available at http://www.aymargeddon.de.
+\the_end
--- /dev/null
+#LyX 1.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 221
+\textclass article
+\language english
+\inputencoding auto
+\fontscheme default
+\graphics default
+\paperfontsize default
+\spacing single
+\papersize Default
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 0
+\use_natbib 0
+\use_numerical_citations 0
+\paperorientation portrait
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation indent
+\defskip medskip
+\quotes_language english
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+Technisches zu
+\begin_inset Quotes eld
+\end_inset
+
+Die letzten Tage von Aymargeddon
+\begin_inset Quotes erd
+\end_inset
+
+
+\layout Author
+
+Aymargeddon Development Team
+\layout Date
+
+9.10.2003
+\layout Standard
+
+
+\emph on
+Warnung: Die Information in diesem Dokument ist zu nicht unerheblichen Teilen
+ veraltet.
+\layout Section
+
+Generelles Design
+\layout Standard
+
+Das Spiel besteht aus folgenden Komponenten:
+\layout Enumerate
+
+Eine Relationale Datenbank
+\layout Enumerate
+
+Ein Dämonprozess im Server
+\layout Enumerate
+
+Serverseitige Scripten zur Benutzerinteraktion
+\layout Enumerate
+
+Ein Weltengenerator
+\layout Enumerate
+
+FROGS
+\layout Enumerate
+
+Ein Programm, dass die Integrität der Datenbank überprüft
+\layout Enumerate
+
+Eine Bibliothek für gemeinsame Funktionalität
+\layout Standard
+
+Die Aufgaben dieser Komponenten stellen sich wie folgt dar:
+\layout Section
+
+Datenbank
+\layout Standard
+
+In dieser Datenbank wird der Zustand aller Spielwelten gespeichert.
+ Außerdem alle Spielerdaten, alle Spieleraktionen und alle Nachrichten an
+ Spieler.
+ Sie sorgt mittels ihrer Transaktionen dafür, dass auch bei konkurierendem
+ Zugriff die Datenintegrität immer erhalten bleibt.
+\layout Standard
+
+Wir verwenden MySQL zur Implementierung und PhpMyAdmin zur Administrierung
+ der Datenbank.
+\layout Standard
+
+Felder, die in vielen Tabellen vorkommen und immer wieder das selbe bedeuten:
+\layout Description
+
+GAME Das ist die Id des Spiels.
+ Dadurch können alle Spiele in der selben Datenbank verwaltet werden.
+ Es kann maximal max(unsigned smallint) Spiele gleichzeitig geben.
+\layout Description
+
+LOCATION Feldkoordinaten auf dem Hexraster-Torus.
+ Ein String der Form <x>_<y>.
+ Die maximale Größe der Welt ist max(unsigned smallint) für die Y-Koordinate
+ und max(unsingend smallint)*2 für die X-Koordinate.
+\layout Description
+
+PLAYER,OWNER,...
+ Spieler-Ids.
+ Die Spieler-Ids bezeichnen den Spieler
+\emph on
+unabhängig
+\emph default
+von seiner Rolle.
+ Sie gilt spielübergreifend.
+ Die maximale Anzahl Spieler ist auf max(signed smallint) beschränkt.
+\layout Subsection
+
+Bewegung und Kämpfe
+\layout Standard
+
+Einheiten, die sich bewegen, bleiben im Feld stehen, werden aber auf nicht
+ available gesetzt.
+ Am Ende des Befehls werden sie in das neue Feld gesetzt.
+ Sie werden nur wieder aktiv, nachdem alle denkbaren Kämpfe ausgeführt wurden.
+\layout Standard
+
+Kämpfe werden als Quasi-Befehl wieder in die Befehlsqueu geschrieben.
+ Erst nach Ablauf dieses Quasi-Befehls wird ausgewertet, welche Einheiten
+ auf welcher Seite am Kampf teilnehmen.
+\layout Standard
+
+Einheiten, die sich zurückziehen, werden ganz normal bewegt.
+\layout Subsection
+
+Tabelle MAP
+\layout Standard
+
+Das ist die zentrale Karte.
+ Für jedes Feld in jedem Spiel gibt es genau einen Eintrag.
+\layout Description
+
+HOME Eigentümer der Heimatstadt.
+ Das Feld ist -1, wenn es eine Heimatstadt ist, aber noch niemand spielt.
+\layout Description
+
+OCCUPANT Besitzer des Feldes
+\layout Description
+
+TERRAIN kann sein eins aus: WATER, CITY, MOUNTAIN, ISLE, PLAIN
+\layout Description
+
+PLAGUE ist das Feld verseucht? Kann eine aus einer Liste von Seuchen sein
+\layout Description
+
+ATTACKER Hier steht der leitende Erdling eines Angriffs drinnen so lange
+ gekämpft wird.
+ 0 sonst.
+ Man kann hier also auch ablesen, ob das Feld umkämpft ist.
+\layout Description
+
+LAST_PRODUCE Zu dieser Zeit wurde zu letzt ein Krieger (bei Städten) bzw.
+ ein Priester (bei Tempeln) produziert.
+ Der Dämon entscheidet anhand dieser Daten, wann neue Einheiten produziert
+ werden.
+\layout Description
+
+FLUXLINE Hier stehen die Richtungen, in die sich Avatare momentan kostenlos
+ bewegen können.
+ Die benachbarten Richtungen kosten 1 MP, alle anderen 2MP.
+ Dieses Feld wird bei einer Änderung der IdS für die gesamte Karte neu berechnet.
+\layout Description
+
+TEMPLE Steht auf 'Y', wenn dort ein Tempel gebaut wurde, auf 'N' sonst.
+\layout Subsection
+
+Tabelle MOBILE
+\layout Standard
+
+In dieser Tabelle werden alle beweglichen Objekte abgespeichert.
+ Das sind also zunächst: Krieger, Helden, Priester, Avatare und Archen.
+ Dabei gibt es nur einen Eintrag für gleichartige Einheiten im selben Feld
+ im selben Spiel.
+\layout Standard
+
+Manche Felder werden nur für manche Objekttypen benutzt.
+ Hier wird also ein bisschen Speicherplatz geopfert um die Struktur möglichst
+ einfach zu halten.
+\layout Description
+
+ID Eine eindeutige ID.
+\layout Description
+
+TYPE Ist einer aus WARRIOR, HERO, PRIEST, AVATAR, ARK
+\layout Description
+
+OWNER Der Spieler, der die Einheit steuert
+\layout Description
+
+ADORING Der Gott, den der Priester anbetet
+\layout Description
+
+COUNT Anzahl
+\layout Description
+
+AVAILABLE Wird auf 0 gesetzt, wenn die Einheit beschäftigt ist (sich also
+ z.B.
+ bewegt)
+\layout Description
+
+STATUS Eines aus HELP, BLOCK, PEACE.
+ Avatarstatus.
+\layout Subsection
+
+Tabelle COMMAND
+\layout Standard
+
+In diese Tabelle tragen die Scripten die Aktionen der Spieler ein und der
+ Dämon führt diese dann aus.
+ Zusätzlich kommen hier auch noch die Quasi-Befehle des Dämons selber rein.
+ Das ist alles, wo er sich für später dran errinnern will.
+ Zur Zeit wird dieser Mechanismus nur für Kämpfe benötigt.
+\layout Description
+
+TIME Die Zeit zu der das Kommando eingetragen wurde
+\layout Description
+
+ACK Hier wird vermerkt, dass der Dämon das Kommando zur Kenntnis genommen
+ hat, aber noch nicht ausgeführt.
+ Das ist nötig weil bei vielen Kommandos schon am Anfang Nachrichten generiert
+ werden müssen, lange bevor sie ausgeführt werden.
+ Z.B.
+ erhalten die Eigentümer eines Feldes, in das man sich bewegt, eine Nachricht,
+ schon wenn man sich auf den Weg macht.
+\layout Description
+
+DONE Hier werden abgearbeitete Befehle vermerkt
+\layout Standard
+
+Alle drei Felder sind Timestamps und müssen immer GMT enthalten!
+\layout Subsection
+
+Tabelle MESSAGE
+\layout Standard
+
+In diese Tabelle trägt der Dämon Nachrichten an die Spieler ein und die
+ Scripten zeigen diese dann an.
+ Nachrichten an Alle Spieler müssen für jeden Spieler einzeln eingetragen
+ werden.
+ Wenn man es anders machen wollte, müsste man wiederum für jeden Spieler
+ vermerken, welche Nachrichten er nicht mehr sehen will, was fast auf das
+ selbe rauskommt.
+
+\layout Description
+
+TIME Der Zeitpunkt, an dem die Nachricht generiert wurde
+\layout Description
+
+FROM Der Absender.
+ 0 bedeutet, dass es eine automatisch generierte Nachricht des Dämon ist.
+\layout Description
+
+TO Der Empfänger
+\layout Description
+
+TYPE Message, Error, Warning, ...
+\layout Description
+
+MSG Die eigentliche Meldung.
+ Bzw.
+ ein Tag, dass erst noch lokalisiert werden muss (Siehe Tabelle LOCALIZE)
+\layout Description
+
+ARG1...4 Die Argumente für die Lokalisierung.
+\layout Subsection
+
+Tabelle GAME
+\layout Standard
+
+Hier stehen allgemein Infos das Spiel betreffend.
+ Pro Spiel gibt es nur einen Eintrag.
+\layout Description
+
+SIZE Die Größe des Spiels.
+ Höhe und halbe Breite des Spielfeldes.
+ Maximale Anzahl Erdlinge.
+\layout Description
+
+FORTUNE Der Glücksfaktor
+\layout Description
+
+LAST_TEMPLE Die LOCATION des letzten fertig gestellten Tempels.
+\layout Description
+
+TEMPLE_SIZE Größe des nächsten Tempels.
+\layout Subsection
+
+Tabelle PLAYER
+\layout Standard
+
+Hier wird spielunabhängig gespeichert, was es alles über einen Spieler zu
+ wissen gibt.
+ Pro Spieler ein Eintrag.
+\layout Subsection
+
+Tabelle ALLIANCE
+\layout Standard
+
+Hier wird beschrieben welche Freunde und Feinde man hat.
+ Pro Spieler-Spieler-Relation in jedem Spiel höchstens ein Eintrag.
+ Status kann sein
+\begin_inset Quotes eld
+\end_inset
+
+FRIEND
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+FOE
+\begin_inset Quotes erd
+\end_inset
+
+ oder
+\begin_inset Quotes eld
+\end_inset
+
+NEUTRAL
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Wenn kein Eintrag vorhanden ist, wird neutraler Status angenommen.
+
+\layout Standard
+
+Man beachte dass Spieler A, Spieler B als Freund ansehen kann, wärend umgekehrt
+ Spieler B Spieler A als Feind betrachtet!
+\layout Subsection
+
+Tabelle GOD
+\layout Standard
+
+Hier werden Daten für die Götter gespeichert.
+ Pro Gott und Spiel ein Eintrag.
+\layout Description
+
+DEATH_AVATAR Die Anzahl der für diesen Gott in diesem Spiel gestorbenen
+ Avatare
+\layout Description
+
+DEATH_HERO dsgl.
+ für Helden
+\layout Description
+
+ARRIVAL Hier entstehen neue Avatare.
+ Dieser Ort wird nach jedem Tempelbau diesen Gottes neu berechnet.
+\layout Subsection
+
+Tabelle LOCALIZE
+\layout Standard
+
+Mit Hilfe dieser Tabelle kann die Darstellung in verschiedenen Sprachen
+ erfolgen.
+\layout Description
+
+TAG Der Eintrag mit dem man wiederkennt, um welche Message es sich handelt
+\layout Description
+
+LANG Die Sprache des Eintrags.
+ Zur Zeit werden nur
+\begin_inset Quotes eld
+\end_inset
+
+DE
+\begin_inset Quotes erd
+\end_inset
+
+ und
+\begin_inset Quotes eld
+\end_inset
+
+EN
+\begin_inset Quotes erd
+\end_inset
+
+ unterstützt.
+\layout Description
+
+TEXT Der Text der Nachricht in den einzelnen Sprachen.
+ Dabei wird mittels
+\begin_inset Quotes eld
+\end_inset
+
+%n
+\begin_inset Quotes erd
+\end_inset
+
+ das n.te Argument eingefügt.
+
+\begin_inset Quotes eld
+\end_inset
+
+%%
+\begin_inset Quotes erd
+\end_inset
+
+ gibt ein Prozentzeichen aus.
+
+\layout Subsection
+
+Tabelle ROLE
+\layout Standard
+
+Hier wird die Rolle eines Spielers in einem Spiel beschrieben.
+ Pro Mitspieler in jedem Spiel ein Eintrag.
+\layout Section
+
+Dämon
+\layout Standard
+
+Dieses Programm liest Spieleraktionen aus der Datenbank, berechnet die sich
+ daraus ergebenden Ereignisse und schreibt Nachrichten an die Spieler zurück
+ in die Datenbank.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementierung des Servers.
+\layout Section
+
+Scripten
+\layout Standard
+
+Sie lesen den Zustand der Welt und die Nachrichten aus der Datenbank, halten
+ Session-Informationen vor und bereiten dies alles in HTML zur Darstellung
+ mittels eines üblichen Web-Browsers auf.
+ Schließlich schreiben sie die Aktionen des Benutzers in die Datenbank und
+ verändern den Aktivitätsstatus von beweglichen Einheiten.
+\layout Standard
+
+Wir verwenden EmbPerl auf Apache zur Implementation.
+ Siehe: http://perl.apache.org/embperl/.
+ EmbPerl scheint genauso einfach und schnell zu sein wie PHP und hat für
+ uns den zusätzlichen Vorteil, dass wir gemeinsame Bibliotheken mit den
+ anderen Komponenten des Servers benutzen können.
+\layout Subsection
+
+Seiten
+\layout Standard
+
+Folgende Seitenlayouts werden benötigt.
+ Auf allen Seiten findet man ein Hauptmenu.
+ Auf Login und Home gibt es auch noch ein Aymaegeddon-Banner
+\layout Description
+
+Login Hier gibt es neben News einen kurzen Einleitungstext sowie eine Möglichkei
+t sich zu registrieren und mal in einem Fakespiel zu schnuppern.
+\layout Description
+
+Home Liste aller Spiele, pro Spiel: Liste aller Nachrichten, aller Ereignisse,
+ Statistik
+\layout Description
+
+Karte Aktuelles Feld, Beschreibung, Befehle
+\layout Description
+
+Spieler Beschreibung des Spielers
+\layout Description
+
+Rolle Beschreibung der Rolle
+\layout Standard
+
+Feldnamen/-koordinaten sind überall immer zur Karte mit dem Feld als aktuellem
+ Feld verlinkt.
+ Rollennamen sind zu der entsprechenden Rollenseite verlinkt.
+\layout Subsection
+
+Karte
+\layout Standard
+
+Zentrale Komponente der Darstellung ist eine Karte des Hex-Torus.
+ Dazu werden 3 Tabellenzellen pro Feld verwendet, nämlich so:
+\layout Standard
+\added_space_bottom 0.3cm
+<BILD FEHLT>
+\layout Standard
+
+Diese Karte ist scrollbar.
+ Ein Feld ist immer als aktuelles Feld umrandet.
+\layout Subsection
+
+Farbdarstellung
+\layout Standard
+
+Wasserfelder blau, Landfelder, Archen und Inseln in Erdfarben.
+ Dabei gibt es 5 Farbtöne für eigene, befreundete, neutrale, feindliche
+ sowie unbesiedelte Felder.
+ Tempel und Avatare werden in 5 verschiedenen Götterfarben (eher grell)
+ dargestellt, wieder je eine für eigene, befreundete, feindliche sowie neutrale
+ Götter.
+ Die
+\begin_inset Quotes eld
+\end_inset
+
+eigene
+\begin_inset Quotes erd
+\end_inset
+
+ Farbe kann auf andere Erdlinge/Götter verändert werden.
+
+\layout Subsection
+
+Icons
+\layout Standard
+
+Folgende Icons werden benötigt.
+\layout Standard
+
+Zentriert:
+\layout Itemize
+
+IdS
+\layout Itemize
+
+Eigentum auf Wasser (Schiff)
+\layout Itemize
+
+Städte
+\layout Itemize
+
+Tempel
+\layout Itemize
+
+Heimatstädte
+\layout Itemize
+
+Inseln
+\layout Itemize
+
+Berge
+\layout Standard
+
+Nicht zentriert:
+\layout Itemize
+
+Avatare (oben bis zu vier)
+\layout Itemize
+
+Archen (unten, nur eine)
+\layout Itemize
+
+Kampf (unten)
+\layout Itemize
+
+Avatarkampf (oben)
+\layout Section
+
+Weltengenerator
+\layout Standard
+
+Dieses Programm wird einmal zu Beginn eines neuen Spiels aufgerufen um eine
+ neue Welt in der Datenbank zu generieren.
+ Der Generator verteilt die verschiedenen Geländetypen: Wasser, Manapol,
+ Insel, Berg, Stadt, Heimatstadt, Land.
+ Er erhält die Anzahl der Erdlinge als Parameter und ermittelt alle anderen
+ Werte daraus.
+
+\layout Standard
+
+Die Game-ID kann automatisch als die erste Freie in der DB ermittelt werden.
+ Dieses Programm sollte als erstes entwickelt werden, damit man eine sinnvolle
+ Testumgebung für die anderen Teile des Systems hat.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+FROGS
+\layout Standard
+
+FROGS steht für
+\series bold
+F
+\series default
+ramework for
+\series bold
+R
+\series default
+ealtime
+\series bold
+O
+\series default
+nline
+\series bold
+G
+\series default
+ames of
+\series bold
+S
+\series default
+trategy.
+ Dort werden alle Funktionalitäten versammelt, die nicht nur von Aymargeddon,
+ sondern auch von anderen Browser-MMOGs verwendet werden können.
+ Das sind im einzelnen:
+\layout Itemize
+
+Nachrichtenverwaltung
+\layout Itemize
+
+Befehlsverwaltung
+\layout Itemize
+
+Spielerverwaltung
+\layout Itemize
+
+Spielverwaltung
+\layout Itemize
+
+Rollenverwaltung
+\layout Itemize
+
+Verschiedene Standardkarten (hier erstmal nur Hextorus)
+\layout Itemize
+
+Bewegliche Einheiten
+\layout Itemize
+
+Lokalisierung
+\layout Itemize
+
+Sessionhandling
+\layout Itemize
+
+Bestenlisten
+\layout Itemize
+
+Datenbank
+\layout Standard
+
+FROGS basiert dabei auf der Annahme, dass bestimmte Felder in bestimmten
+ Tabellen vorhanden sein müssen.
+ Außerdem werden die konkreten Funktionalitäten über Hooks in das Framework
+ eingehängt.
+ So wird z.B.
+ für jeden Befehl ein Name festgelegt mit drei Hooks:
+\layout Description
+
+test Diese Funktion tested, ob der Befehl überhaupt ausführbar ist.
+\layout Description
+
+ack Diese Funktion wird ausgeführt, wenn der Befehl zum ersten mal vom Dämon
+ zur Kenntnis genommen wird.
+\layout Description
+
+do Diese Funktion führt schließlich den Befehl aus.
+ Dazu sind am Anfang noch weitere tests nötig.
+\layout Standard
+
+Ziel für Frogs ist, dass man relativ einfach neue Browserspiele bauen kann.
+ Es wird auch ein Satz von Standardseiten in EmbPerl mitgeliefert mit denen
+ Funktionen wie Einloggen, Spielverwaltung, Bestenlisten etc.
+ schon vorhanden sind.
+\layout Standard
+
+Hier noch eine Liste von FROGS-Modulen und was sie tun sollen:
+\layout Description
+
+Map.pm Dies ist eine Basisklasse für alle denkbaren Topologien.
+ Jedes Modul einer abgeleiteten Klasse sollte auch eine Klasse Location
+ zur Verfügung stellen.
+ Außerdem müssen abgeleitete Klassen einige Funktionen mitbringen, damit
+ die in Map vorhandenen Funktionen funktionieren.
+\layout Description
+
+HexTorus.pm Dies ist die von Aymargeddon verwendete Topologie.
+ Kann aber auch von anderen Spielen verwendet werden.
+ Abgeleitet von Map.pm.
+ Stellt auch die Klasse Location zur Verfügung.
+\layout Description
+
+Checker.pm Hier werden die verallgemeinerbaren Funktionen des Checkers zur
+ Verfügung gestellt.
+\layout Description
+
+Scheduler.pm Hier wird die Befehlsqueu durchgegangen und die oben definierten
+ Funktionen werden aufgerufen.
+\layout Description
+
+Localize.pm Hier wird die Lokalisierung ausgeführt.
+\layout Description
+
+DataBase.pm Hier werden Basisdatenbankfunktionalitäten zur Verfügung gestellt
+\layout Description
+
+...
+ weitere Module noch unklar
+\layout Standard
+
+Auch FROGS wird in Perl 5.8 bzw.
+ EmbPerl implementiert.
+\layout Section
+
+Checker
+\layout Standard
+
+Dieses Programm überprüft, ob die Daten in der Datenbank noch konsistent
+ sind.
+ Dabei werden die Checks zu algorithmisch ähnlichen Gruppen zusammengefasst
+ und durch allgemein Funktionen ausgeführt.
+ Bisher sind folgende Funktionen identifiziert worden:
+\layout Enumerate
+
+Jeder Eintrag in Tabelle X muß auch in Tabelle Y existieren.
+
+\layout Enumerate
+
+N Einträge in der selben Tabelle müssen eine logische Beziehung erfüllen
+\layout Standard
+
+Diese allgemeinen konfigurierbaren Check-Funktionen sollten auch Teil von
+ FROGS werden.
+\layout Standard
+
+Der Checker überprüft im einzelnen (Zahlen beziehen sich auf obige Funktionslist
+e):
+\layout Itemize
+
+Jede Spielnummer muß in der Tabelle GAME zu finden sein (1).
+\layout Itemize
+
+sämtliche Spieler-IDs müssen in ROLE zum selben Spiel passen (1).
+\layout Itemize
+
+sämtliche Spieler-IDs müssen in PLAYER vorhanden sein (1).
+\layout Itemize
+
+Location muß immer in MAP vorhanden sein.
+\layout Itemize
+
+Location muß immer die kanonische Form haben (2).
+\layout Itemize
+
+HOME nur gesetzt in MAP, wenn TERRAIN = CITY (desgl.
+ für GOD_HOME und MOUNTAIN) (2).
+\layout Itemize
+
+Keine Zwei Erdlinge im selben Feld, außer es ist Kampf.
+\layout Itemize
+
+Alle Einheiten in COMMANDS müssen inaktiv sein.
+\layout Itemize
+
+Nur Priester ADORING in MOBILE (2).
+\layout Itemize
+
+AVAIABLE immer kleiner oder gleich COUNT in MOBILE (2)
+\layout Itemize
+
+Während eines Kampfes nur aktive Erdlinge eines Spielers im selben Feld.
+\layout Itemize
+
+Keine blockenden Avatare von zwei feindlichen Spielern im selben Feld ohne
+ Kampf .
+\layout Itemize
+
+Jedes Tag in MESSAGE sollte in LOCALIZE vorhanden sein.
+ Mindestens in einer Sprache.
+ Warnung, wenn nicht in jeder Sprache.
+\layout Itemize
+
+Die Anzahl der Argumente in MESSAGES sollte mit den nicht doppelten %-Zeichen
+ in LOCALIZE übereinstimmen (für jede Sprache).
+
+\layout Itemize
+
+CREATE <= EXEC <= ACK <= DONE in COMMAND
+\layout Standard
+
+Dieses Programm sollte möglichst früh entwickelt werden, da es vor allem
+ im Entwicklungsprozess benötigt wird.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+Bibliothek
+\layout Standard
+
+Hier werden alle Funktionalitäten versammelt, die von mindestens zwei der
+ Komponenten (Scripten, Generator, Dämon, Check) verwendet werden.
+
+\layout Standard
+
+Dabei bleiben in dieser Bibliothek nur Sachen, die nicht noch allgemeiner
+ sind und somit in den FROGS-Teil gehören.
+ Momentan ist noch unklar, ob da überhaupt was übrig bleibt.
+\layout Standard
+
+Wir verwenden Perl 5.8 zur Implementation.
+\layout Section
+
+
+\lang german
+Copyright
+\layout Standard
+
+
+\lang german
+(c) 2003 Aymargeddon Development Team
+\layout Standard
+
+
+\lang german
+Permission is granted to copy, distribute and/or modify this document under
+ the terms of the GNU Free Documentation License, Version 1.1 or any later
+ version published by the Free Software Foundation; with no Invariant Sections,
+ with no Front-Cover Texts, and with no Back-Cover Texts.
+ A copy of the license is available at http://www.aymargeddon.de.
+\the_end
--- /dev/null
+#FIG 3.2
+Landscape
+Center
+Metric
+A4
+100.00
+Single
+-2
+1200 2
+2 3 0 1 0 7 100 0 -1 0.000 0 0 0 0 0 7
+ 4425 4177 5103 5348 6452 5349 7127 4177 6451 3006 5101 3009
+ 4425 4177
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 5847 2976 5895 2430
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 4742 3668 4185 3420
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 4752 4771 4050 5175
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 5796 5327 5760 6075
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 6777 4803 7398 5067
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 150.00 120.00
+ 6823 3599 7408 3262
+4 0 0 100 0 0 12 -0.0000 4 180 1440 3285 3195 Nordwesten (NW)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1410 3105 5625 Suedwesten (SW)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1260 7065 3150 Nordosten (NO)\001
+4 0 0 50 0 0 12 0.0000 4 180 930 5490 2250 Norden (N) \001
+4 0 0 50 0 0 12 0.0000 4 180 765 5355 6390 S\374den (S)\001
+4 0 0 100 0 0 12 -0.0000 4 180 1230 7155 5400 Suedosten (SO)\001
--- /dev/null
+#################
+Datenbankzugriffe
+#################
+
+Alles, was einen SQL-Befehl beinhaltet sollte in
+DataBase.pm. zusätzlich vielleicht auch noch sehr eng damit
+zusammenhängende Funktionen. Alles abstraktere sollte in extramodule.
+
+Generelle Frage:
+================
+
+embperl sollte nur die aktionen überhaupt zur verfügung stellen, die
+möglich sind (soweit zu diesem zeitpunkt bekannt).
+
+soll man darauf vertrauen, dass die embperlseite bestimmte sachen
+schon abgetestet hat? oder muss man die alle nochmal auf serverseite
+testen? Antwort: wohl ja, da sich zwischen eintragen in die
+befehlsqueu und ausführung des befehls der spielstand verändert haben
+kann. ausnahmen sind unten eingeklammert.
+
+Hier jetzt mal eine möglichst vollständige Liste aller
+Datenbankzugriffe, als Grundlage für Designüberlegungen.
+
+Von Serverseite:
+================
+
+- lies alle aktuellen befehle
+- schreibe message
+
+Alles, was trotz zeitverzögerung schon vorher von embperlseite
+abgeklärt hätte werden können ist eingeklammert.
+
+einzelne befehle:
+--------------------
+- passwort ändern (nicht in befehlsqueu sondern sofort?)
+ - authentifizieren
+ - schreiben in PLAYER
+
+- registrieren (nicht in befehlsqueu sondern sofort?)
+ - schreiben in PLAYER
+
+- abmelden (nicht in befehlsqueu sondern sofort?)
+ - authentifizieren
+ - löschen in PLAYER
+
+- status ändern
+ - test ob spieler vorhanden
+ - schreiben in ALLIANCE
+
+- anmelden in einzelnen spielen (nicht in befehlsqueu sondern sofort?)
+ - test ob spieler schon in spiel vorhanden
+ - schreiben in ROLE
+
+- abmelden aus spielen (nicht in befehlsqueu sondern sofort?)
+ - löschen aus ROLE
+--------------------
+- erdlingsbewegen:
+ - (test ob manapol)
+ - test ob arche auf wasser
+ - test ob kampf
+ - test wer kämpft
+ - schreiben in MOBILE
+ - schreiben in MAP
+ - schreiben in COMMAND
+
+- tempel bauen:
+ - test ob tempelfeld des gottes (kann sich ändern wg. überschwemmung)
+ - test ob richtiger priester da
+
+- sterbereihenfolge:
+ - (testen ob reihenfolge gültig)
+ - schreiben in EARTHLING [ACHTUNG: neue Tabelle!]
+
+- gott für tote helden festlegen:
+ - testen ob gott gültig
+ - schreiben in EARTHLING
+--------------------
+- bei allen gottbefehlen: testen ob manna reicht
+
+- avatar erschaffen:
+ - ort ermitteln aus MAP und MOBILE
+ - schreiben in MOBILE
+
+- held weihen
+ - testen ob held noch vorhanden (und aktiv?)
+ - schreiben in MOBILE
+
+- priester erleuchten
+ - testen ob krieger noch vorhanden (und aktiv?)
+ - testen ob sichtrecht
+ - schreiben in MOBILE
+
+- avatare bewegen
+ - ähnlich wie erdlingsbewegen nur zusätzliche tests
+ - avatarstatus beachten (evntl. verändern)
+
+- verseuchen
+ - noch unklar, weil seuchen noch unklar
+
+- sintfluten
+ - test ob benachbartes wasserfeld
+ - liest und schreibt aus MAP
+
+- avatarstatus ändern
+ - testen ob avatar da.
+
+- tempel zerstören
+ - ...
+
+- glücksfaktor verändern
+ - ...
+
+- arche bauen
+ - ...
+
+Von Clientseite:
+================
+
+- authentifizieren
+- liste aller spiele
+- liste aller spiele mit freien positionen (mit rolle)
+- liste aller spieler
+- liste aller rollen pro spiel
+- infos ueber einen spieler
+- infos ueber eine rolle eines spielers in einem spiel
+
+- karte lesen (sichtregeln beachten!)
+- infos ueber ein feld lesen (auch aus MOBILE) (sichtregeln beachten!)
+
+- liste der möglichen befehle in einem feld ermitteln
+ (vielfältige tests, viele davon stehen oben bei den serverbefehlen)
+
+- liste aller nachrichten
+- liste aller nachrichten ein feld betreffend
+
+Von create.pl:
+==============
+
+- lies das erste leere spiel aus GAME
+- schreibe in MAP
+
+Von checker.pl:
+===============
+
+- sehr spezielle einzelne zugriffe (Check.pm selbst definiert keine
+Struktur)
+
+
+
--- /dev/null
+From Martin.Spott@uni-duisburg.de Tue Jul 6 17:06:05 1999
+From: Martin Spott <Martin.Spott@uni-duisburg.de>
+Newsgroups: de.comp.os.unix.apps,de.comp.text.tex
+Subject: Re: tex -> pdf
+Date: 24 Jun 1999 18:59:57 GMT
+Organization: home
+Lines: 24
+Message-ID: <7ktv7d$p59$1@foehn.quickstep.cologne.de>
+References: <7kskei$6hb$1@narses.hrz.tu-chemnitz.de> <3771ECC7.C1F5FDA2@starship.python.net>
+NNTP-Posting-Host: foehn.quickstep.cologne.de
+X-Trace: foehn.quickstep.cologne.de 930250797 25769 192.168.48.2 (24 Jun 1999 18:59:57 GMT)
+X-Complaints-To: usenet@foehn.quickstep.cologne.de
+NNTP-Posting-Date: 24 Jun 1999 18:59:57 GMT
+X-Newsreader: TIN [UNIX 1.3 unoff BETA 970705; sun4m SunOS 5.5.1]
+Path: nntp.server.uni-frankfurt.de!grapool30.rz.uni-frankfurt.de!News.Uni-Marburg.DE!news-fra1.dfn.de!news-kar1.dfn.de!akk.uni-karlsruhe.de!news.cologne.de!quickstep.cologne.de!not-for-mail
+Xref: nntp.server.uni-frankfurt.de de.comp.os.unix.apps:2328 de.comp.text.tex:41798
+
+In de.comp.os.unix.apps Berthold H?llmann <bhoel@starship.python.net> wrote:
+
+> 7. latex ; dvipdf ?
+
+Ist das dasselbe wie das 'dvipdfm', welches ich hier rumfliegen habe ?
+
+Beim Weg ueber 'dvips' respektive ueber DVI im Allgemeinen ist vor allem
+darauf Acht zu geben, dass ausschliesslich Type1-Fonts im TeX-Dokument
+verwendet werden. Wie genau das geht, habe ich nicht mehr im Kopf, es gibt
+aber wohl irgeneinen Switch im 'dvips' und die dazugehoerigen TeX-Fonts im
+Type1-Format. Beruecksichtigt man das nicht, dann sieht das PDF-Dokument vor
+allem auf dem Bildschirm ausgesprochen haesslich aus und der Aufbau einer
+Seite im Acrobat Reader dauert ungefaehr die fuenffache Zeit vom dem, was es
+mit Type1-Fonts gebraucht haette, weil dann Bitmap-Fonts in das Dokument
+eingebaut werden. Die eignen sich vielleicht zu allem moeglichen, aber mit
+Sicherheit nicht fuer eine skalierbare Darstellung auf verschiedenen
+Ausgabemedien.
+
+Derleit haessliche Dokumente kursieren leider zuhauf ....
+
+Martin.
+--
+ Unix _IS_ user friendly - it's just selective about who its friends are !
+--------------------------------------------------------------------------
+
+
+From Martin.Spott@uni-duisburg.de Tue Jul 6 17:06:14 1999
+From: Martin Spott <Martin.Spott@uni-duisburg.de>
+Newsgroups: de.comp.os.unix.apps,de.comp.text.tex
+Subject: Re: tex -> pdf
+Date: 24 Jun 1999 20:04:25 GMT
+Organization: home
+Lines: 13
+Message-ID: <7ku309$q35$1@foehn.quickstep.cologne.de>
+References: <7kskei$6hb$1@narses.hrz.tu-chemnitz.de> <3771ECC7.C1F5FDA2@starship.python.net> <7ktv7d$p59$1@foehn.quickstep.cologne.de>
+NNTP-Posting-Host: foehn.quickstep.cologne.de
+X-Trace: foehn.quickstep.cologne.de 930254665 26725 192.168.48.2 (24 Jun 1999 20:04:25 GMT)
+X-Complaints-To: usenet@foehn.quickstep.cologne.de
+NNTP-Posting-Date: 24 Jun 1999 20:04:25 GMT
+X-Newsreader: TIN [UNIX 1.3 unoff BETA 970705; sun4m SunOS 5.5.1]
+Path: nntp.server.uni-frankfurt.de!grapool30.rz.uni-frankfurt.de!News.Uni-Marburg.DE!news-fra1.dfn.de!fu-berlin.de!news.cologne.de!quickstep.cologne.de!not-for-mail
+Xref: nntp.server.uni-frankfurt.de de.comp.os.unix.apps:2329 de.comp.text.tex:41800
+
+In de.comp.os.unix.apps Martin Spott <Martin.Spott@uni-duisburg.de> wrote:
+
+> darauf Acht zu geben, dass ausschliesslich Type1-Fonts im TeX-Dokument
+> verwendet werden. Wie genau das geht, habe ich nicht mehr im Kopf, es gibt
+> aber wohl irgeneinen Switch im 'dvips' und die dazugehoerigen TeX-Fonts im
+> Type1-Format. [...]
+
+.... oder jedenfalls die CM-Fonts,
+
+Martin.
+--
+ Unix _IS_ user friendly - it's just selective about who its friends are !
+--------------------------------------------------------------------------
+
+
--- /dev/null
+# tth -t -e2 Regeln.tex
+# mv Regeln.tex ./+Regeln.tex
+mv Regeln.html ./+Regeln.html
+mv Regeln.pdf ./+Regeln.pdf
+scp ./+Regeln.html benni@aymargeddon.de:aymargeddon/current/doc/
+scp ./+Regeln.pdf benni@aymargeddon.de:aymargeddon/current/doc/
--- /dev/null
+<html>
+<head><link rel="stylesheet" type="text/css" href="aymargeddon.css">
+</head>
+<body>
+[$ if exists $fdat{'x'} and exists $fdat{'y'} $]
+ [- $udat{-loc} = $fdat{'x'}.'_'.$fdat{'y'}; -]
+[$ endif $]
+
+[$ if exists $udat{-id} and exists $udat{-game} and $udat{-loc} $]
+
+[-
+ use FROGS::HexTorus;
+ use Aymargeddon;
+
+ my $game = $udat{-game};
+ my $user = $udat{-id};
+ my $loc = $udat{-loc};
+
+ my $db = DataBase->new();
+ my $aym = Aymargeddon->new($game,$user,$db);
+ $db->set_language($udat{-lang});
+
+ # maybe you cant see this field (for hackers, which try to look direct
+ # in the field via url)
+ unless ($aym->sight_of_field($loc)){
+ print OUT "Mogeln gildet nich!\n";
+ } else {
+
+ my ($ter,$own,$occ,$temple,$plague) =
+ $aym->read_field('TERRAIN,HOME,OCCUPANT,TEMPLE,PLAGUE',$loc);
+
+ #####################
+ # general field info
+ #####################
+
+ $out .= $db->loc('FIELD_'.$ter).' '.Location::pretty($loc).' '.
+ $db->loc('PREP_IS_SG').' ';
+ if ($occ) {
+ $out .= $db->loc('OCCUPIED').' ';
+ if ($occ==$user) {
+ # it is our own field
+ $out .= $db->loc( ($aym->gender($occ) eq 'PLURAL') ?
+ 'PPRO_DAT3_PL' : 'PPRO_DAT3_SG' );
+ } else {
+ # the field belongs to someone else
+ $out .= $db->loc('ART_DAT_PL').' ' if $aym->gender($occ) eq 'PLURAL';
+ $out .= $aym->charname($occ).' (<a href="command.epl?cmd=CH_STATUS&other='.
+ $occ.'">'.$aym->relation_string($occ).
+ '</a>, <a href="command.epl?cmd=SEND_MSG&other='.$occ.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+ } else {
+ $out .= $db->loc('NOT_OCCUPIED');
+ }
+ $out .= ".\n";
+
+ if ($own > 0) {
+ # some fields have some specials
+ if ($ter eq 'CITY') {
+ $out .= $db->loc('HOMECITY');
+ } elsif ($temple eq 'Y') {
+ $out .= $db->loc('TEMPLE');
+ } elsif ($ter eq 'MOUNTAIN') {
+ $out .= $db->loc('HOMEHOLY');
+ }
+ if($ter ne 'ISLE' or $temple eq 'Y'){
+ $out .= ' '.$db->loc('PREP_OWN_SG').' ';
+ if ($own==$user) {
+ $out .= $db->loc( ($aym->gender($own) eq 'PLURAL') ?
+ 'PPRO_DAT3_PL' : 'PPRO_DAT3_SG' );
+ } elsif ($occ == $own) {
+ my $gen = $aym->gender($own);
+ $out .= $db->loc( ($gen eq 'PLURAL') ? 'PPRO_DAT_PL' :
+ (($gen eq 'MALE') ? 'PPRO_DAT_M' : 'PPRO_DAT_F') );
+ } else {
+ $out .= $db->loc('ART_DAT_PL').' ' if $aym->gender($own) eq 'PLURAL';
+ $out .= $aym->charname($own).' (<a href="command.epl?cmd=CH_STATUS&other='.
+ $own.'">'.$aym->relation_string($own).
+ '</a>, <a href="command.epl?cmd=SEND_MSG&other='.$own.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+ $out .= '.';
+ }
+ }
+ $out .= $db->loc('PLAGUE_IN_FIELD',lc($plague)) if $plague;
+ $out .= "<p>\n";
+
+ ###################
+ # show the mobiles
+ ###################
+
+ $mob = $aym->mobiles_available($loc);
+ $mobcount = $#{@$mob}+1;
+
+ if ($mobcount) {
+ $out .= $db->loc('ADJ_HERE').' ';
+ $out .= $db->loc( ($mobcount == 1 and @{$mob->[0]}[4] == 1) ?
+ 'PREP_IS_SG' : 'PREP_IS_PL' );
+
+ $out .= ($mobcount > 1) ? ":\n<p>" : ' ';
+ foreach $i (0..$mobcount-1) {
+ my ($oid,$otype,$oown,$oado,$ocnt,$ostat,$omove) = @{$mob->[$i]};
+ # check for MOVE_WITH
+ next if $omove;
+ $out .= $aym->mobile_to_html( $loc,$own,$occ,$temple,$ter, @{$mob->[$i]});
+
+ my $transports = 0;
+ foreach $j (0..$mobcount-1) {
+ ($xid,$xtype,$xown,$xado,$xcnt,$xstat,$xmove) = @{$mob->[$j]};
+ if ($xmove == $oid) {
+ if (!$transports) {
+ $out .= ', '.$db->loc('MSG_TRANSPORTS').":<ul>\n";
+ $transports = 1;
+ }
+ $out .= '<li>'.
+ $aym->mobile_to_html( $loc,$own,$occ,$temple,$ter, @{$mob->[$j]})."</li>\n";
+ }
+ }
+ if ($transports) {
+ $out .= '</ul>';
+ } else {
+ $out .= ($i < $mobcount-1) ? ',' : '.';
+ $out .= "\n<p>";
+ }
+ } # end foreach $mobcount
+ }
+
+ ##################################
+ # general commands for this field:
+ ##################################
+
+ if ($aym->is_earthling($user)) {
+ $out .= "\n<p><a href=\"command.epl?cmd=DIE_ORDER\">".
+ $db->loc('CMD_DIE_ORDER').'</a>';
+ }
+ if ($aym->is_god($user)) {
+ if ($aym->is_arrival($loc)) {
+ $out .= "\n<p><a href=\"command.epl?cmd=INCARNATE&loc=$loc\">".
+ $db->loc('CMD_INCARNATE').'</a>';
+ }
+ if($aym->is_coast($loc)){
+ $out .= "\n<p><a href=\"command.epl?cmd=BUILD_ARK&loc=$loc\">".
+ $db->loc('CMD_BUILD_ARK').'</a>';
+ if($ter ne 'CITY'){
+ $out .= "\n<p><a href=\"command.epl?cmd=FLOOD&loc=$loc\">".
+ $db->loc('CMD_FLOOD').'</a>';
+ }
+ }
+ $out .= "\n<p><a href=\"command.epl?cmd=PLAGUE&loc=$loc\">".
+ $db->loc('CMD_PLAGUE').'</a>';
+ $out .= "\n<p><a href=\"command.epl?cmd=CH_LUCK\">".$db->loc('CMD_CH_LUCK').'</a>';
+ }
+
+ #############################
+ # show events for this field
+ #############################
+
+ $events = $aym->field_events($loc);
+ #use Data::Dumper;
+ #print OUT Dumper $events;
+ $out .= "\n<p><strong>".$db->loc('PLAYER_EVENTS')."</strong><p>\n" if %$events;
+ for my $ev ( keys %$events) {
+ $out .= $aym->show_event($ev, 0) .'<p>';
+ }
+
+ ############################
+ # show unavailable units
+ ############################
+
+ # mobile info:
+ #$mob = $aym->mobiles_available($loc,-1);
+ #$mobcount = $#{@$mob}+1;
+
+ #if ($mobcount) {
+ # $out .= '<p>';
+ # $out .= '<strong> '.$db->loc('UNAVAILABLE_UNITS').":</strong><p>";
+ # foreach $i (0..$mobcount-1) {
+ # ($oid,$otype,$oown,$oado,$ocnt,$ostat) = @{$mob->[$i]};
+ # $out .= $ocnt.' ';
+ # if ($oown == $user) {
+ # $out .= $db->loc('PREP_OWN_PL').' '.$aym->mobile_string($otype,2);
+ # if ($otype eq 'PRIEST' or $otype eq 'PROPHET') {
+ # $out .= $db->loc('ADJ_ADORING').' '.$aym->charname($oado);
+ # } elsif ($otype eq 'HERO') {
+ # $out .= $db->loc('ADJ_ADORING');
+ # $out .= $aym->charname($oado).'</a>';
+ # } elsif ($otype eq 'AVATAR') {
+ # $out .= $aym->mobile_string($ostat,1);
+ # }
+ # } else {
+ # $out .= $aym->mobile_string($otype, $ocnt);
+ # if ($otype ne 'ARK') {
+ # $out .= ' '.$db->loc('PREP_OWN_SG').' ';
+ # $out .= $db->loc('ART_DAT_PL').' ' if $aym->gender($oown) eq 'PLURAL';
+ # $out .= $aym->charname($oown);
+ # }
+ # if ($otype eq 'PRIEST' or $otype eq 'PROPHET'or $otype eq 'HERO') {
+ # $out .= $db->loc('ADJ_ADORING').' ';
+ # if ($oado == $user) {
+ # $out .= $db->loc( ($aym->gender($user) eq 'PLURAL') ?
+ # 'PPRO_DAT3_PL' : 'PPRO_DAT3_SG');
+ # } else {
+ # $out .= $aym->charname($oado);
+ # }
+ # }
+ # }
+ # $out .= ($i < $mobcount-1) ? ',' : '.';
+ # $out .= "\n<p>";
+ # } # end foreach $mobcount
+ #}
+
+ print OUT $out;
+ } # unless sight
+ -]
+
+[$ else $]
+
+ To view an Aymargeddon field, you must first <a href="login.epl" target="_top">login</a>,
+ because we need to know which game to display and for whom.
+
+[$ endif $]
+</body></html>
--- /dev/null
+[- use HTML::Embperl::Session;
+
+-]
+
+<html><body>Hallo Spieler mit der Nummer
+[+
+ $udat{-id}
+
+ +]
+
+hier <a href="mapframe.html">zur Karte </a>
+</body></html>
\ No newline at end of file
--- /dev/null
+<html>
+<head>
+ <title>Aymargeddon</title>
+</head>
+<body>
+[-
+
+ use FROGS::Config;
+
+ $udat{-current} = 'index.epl';
+ Execute("menu.epl");
+
+ $udat{-lang} = $::conf->{-DEFAULT_LANGUAGE} unless exists $udat{-lang};
+
+ if($udat{-lang} eq 'EN'){
+ Execute("welcome_english.html");
+ }elsif($udat{-lang} eq 'DE'){
+ Execute("welcome_german.html");
+ }else{
+ Execute("welcome_english.html");
+ }
+-]
+
+</body>
+</html>
+
--- /dev/null
+<html>
+<head></head>
+<body>
+[-
+ use FROGS::DataBase;
+ $db = DataBase->new();
+-]
+
+[$ if exists $fdat{'lang'} $]
+
+[-
+ $udat{-lang} = $fdat{'lang'};
+ $db->set_language($udat{-lang});
+
+ #set language in Database in PLAYER.LANGUAGE
+ my $player = $udat{-id};
+ $db->update_hash('PLAYER',"PLAYER=$player",{'LANGUAGE' => $fdat{'lang'}});
+ $db->commit();
+
+ # redirect to original page
+ $http_headers_out{'Location'} = $udat{-current};
+
+-]
+
+[$ else $]
+
+[-
+ $db->set_language($udat{-lang});
+ Execute("menu.epl");
+-]
+
+<hr>
+<form method="get" action="language.epl">
+
+ [+ $db->loc('LANG_WELCOME') +]:<p>
+
+ <input type="radio" name="lang" value="EN">[+ $db->loc('LANG_ENGLISH') +]<p>
+ <input type="radio" name="lang" value="DE">[+ $db->loc('LANG_GERMAN') +]<p>
+ <input type="submit" value="[+ $db->loc('FORM_OK_BUTTON') +]">
+
+</form>
+
+[$ endif $]
+
+</body></html>
--- /dev/null
+<html>
+<head></head>
+<body>
+[-
+ $udat{-current} = 'login.epl';
+
+ use FROGS::DataBase;
+ $db = DataBase->new();
+ $db->set_language($udat{-lang}) if exists $udat{-lang};
+
+ if(exists $udat{-id}){ # we are logged in, so log out (deleting user-data)
+ delete $udat{-id};
+ delete $udat{-game};
+ }
+
+ Execute("menu.epl");
+
+ $escmode = 0;
+-]
+<hr>
+
+[$ if $fdat{'mode'} eq 'register' $] [# register form #]
+
+ [+ $db->loc('LOGIN_REG_FORM_HEAD') +]<p>
+ <form method="get" action="login.epl">
+ [+ $db->loc('LOGIN_USERNAME') +]: <input type="text" name="newlogin" size="20" maxlength="20"><p>
+ [+ $db->loc('LOGIN_REALNAME') +]: <input type="text" name="realname" size="30" maxlength="30"><p>
+ [+ $db->loc('LOGIN_EMAIL') +]: <input type="text" name="email" size="40" maxlength="40"><p>
+ <input type="submit" value="[+ $db->loc('FORM_OK_BUTTON') +]">
+ </form>
+
+[$ elsif defined $fdat{'newlogin'} $] [# validate data from register form #]
+
+ [- $new_passwd = $db->new_account($fdat{'newlogin'},
+ $fdat{'realname'},
+ $fdat{'email'},
+ $udat{-lang}); -]
+ [$ if $new_passwd $]
+
+ [+ $db->loc('LOGIN_REG_OK_HEAD',$lang) +]<p>
+ [+ $db->loc('LOGIN_USERNAME') +]: [+ $fdat{'newlogin'} +]<p>
+ [+ $db->loc('LOGIN_REALNAME') +]: [+ $fdat{'realname'} +]<p>
+ [+ $db->loc('LOGIN_EMAIL') +]: [+ $fdat{'email'} +]<p>
+ [+ $db->loc('LOGIN_REG_OK_TAIL') +]
+
+ [$ else $]
+
+ [+ $db->loc('LOGIN_REG_ERROR') +]<p>
+
+ [$ endif $]
+
+ <p><a href="login.epl">[+ $db->loc('LOGIN_REG_RETURN') +]</a>
+
+[$ else $] [# ask for login-data or register #]
+
+ [+ $db->loc('LOGIN_WELCOME') +]<p>
+ <form method="get" action="player.epl">
+ [+ $db->loc('LOGIN_USERNAME') +]: <input type="text" name="login"
+ size="20" maxlength="20">
+ [+ $db->loc('LOGIN_PASSWORD') +]: <input type="password" name="passwd"
+ size="20" maxlength="20">
+ <p>
+ [+ $db->loc('CHANGE_PASSWORD') +]:
+ <input name="passwd2" type="password" size="20" maxlength="20">
+ <input name="passwd3" type="password" size="20" maxlength="20">
+ <p>
+ <input type="submit" value="[+ $db->loc('FORM_OK_BUTTON') +]">
+ </form>
+ [+ $db->loc('LOGIN_REG_MSG') +]
+ <a href="login.epl?mode=register">[+$db->loc('LOGIN_REG_LINK')+]</a>.
+
+[$ endif $]
+
+</body>
+</html>
--- /dev/null
+<html><head>
+ <title>Aymargeddon Map</title>
+</head><body>
+
+[$ if exists $udat{-id} and exists $udat{-game} $]
+
+[-
+
+ # TODO: center relocation
+ # TODO: bug/feature setting y did not work with local variables
+
+ use FROGS::DataBase;
+ use Aymargeddon;
+ use DBI;
+ my $game = $udat{-game};
+ my $user = $udat{-id};
+
+ # look at MAP
+ my $db = Aymargeddon->new($game,$user);
+ my $dat = $db->get_map();
+
+ # create $map
+ # map[x][y][0] = background-color
+ # map[x][y][1] = occupant-color
+ # map[x][y][2] = type
+ # map[x][y][3] = owner-color
+ # map[x][y][4] = avatar-case
+ # map[x][y][5] = god-fight
+ # map[x][y][6] = earthling-fight /foreign earthling units approaching /plague
+ # map[x][y][7] = arc present
+
+ $xmax = 0; $ymax = 0;
+ for my $row (@$dat){
+ my ($loc,$ter,$own,$occ,$temple,$plague) = @$row;
+
+ $loc =~ /^(\d+)_(\d+)$/;
+ ($x,$y) = ($1,$2);
+ $xmax = $x if $x > $xmax;
+ $ymax = $y if $y > $ymax;
+
+ if(!$db->sight($loc)){
+ $map[$x][$y][0] = 'B';
+ $map[$x][$y][1] = 'B';
+ $map[$x][$y][2] = '';
+ $map[$x][$y][3] = '';
+ $map[$x][$y][4] = 'X';
+ next;
+ }
+
+ if($ter eq 'POLE' or $ter eq 'AYMARGEDDON'){
+ $map[$x][$y][1] = 'P';
+ }elsif($occ==$user){
+ $map[$x][$y][1] = 'O';
+ }elsif($db->get_relation($occ) eq 'FRIEND' or $db->get_relation($occ) eq 'ALLIED'){
+ $map[$x][$y][1] = 'F';
+ }elsif($db->get_relation($occ) eq 'FOE' or $db->get_relation($occ) eq 'BETRAY'){
+ $map[$x][$y][1] = 'E';
+ }elsif($occ){
+ $map[$x][$y][1] = 'N';
+ }else{
+ $map[$x][$y][1] = 'U';
+ }
+
+ $map[$x][$y][0] = ($ter eq 'WATER' or $ter eq 'ISLE')
+ ? 'W' : $map[$x][$y][1];
+
+ if($temple eq 'Y'){
+ $map[$x][$y][2] = ($ter eq 'ISLE')?'I':'M';
+ }elsif($ter eq 'CITY'){
+ $map[$x][$y][2] = 'C';
+ }elsif($ter eq 'ISLE' or $ter eq 'WATER'){
+ $map[$x][$y][2] = 'W';
+ }else{
+ $map[$x][$y][2] = 'L';
+ }
+
+ $map[$x][$y][3] = 'U';
+
+ if($ter eq 'AYMARGEDDON'){
+ $map[$x][$y][3] = 'A';
+ }elsif($ter eq 'MOUNTAIN' or $ter eq 'ISLE' or $ter eq 'CITY'){
+ if($map[$x][$y][2] eq 'W'){
+ $map[$x][$y][3] = 'N'; # Isles without temple are always neutral
+ }elsif(!$own){
+ $map[$x][$y][3] = 'B'; # Cities without owner are non-homecities
+ }elsif($own eq $user){
+ $map[$x][$y][3] = 'O';
+ }elsif($db->get_relation($own) eq 'FRIEND' or $db->get_relation($own) eq 'ALLIED'){
+ $map[$x][$y][3] = 'F';
+ }elsif($db->get_relation($own) eq 'FOE' or $db->get_relation($own) eq 'BETRAY'){
+ $map[$x][$y][3] = 'E';
+ }elsif($own){
+ $map[$x][$y][3] = 'N';
+ }
+ }
+
+ $map[$x][$y][5] = $db->god_fight($loc) ? 'G':'U';
+ $map[$x][$y][6] = $db->earthling_fight($loc) ? 'E': 'U';
+ $map[$x][$y][7] = (($ter ne 'WATER' or !$occ) and $db->arc_present($loc)) ? 'A':'U';
+ my $fea = $db->foreign_earthling_approaching($loc,$occ) ? 'F':'U';
+ $map[$x][$y][6] = $map[$x][$y][6] eq 'E' ? 'E' : $fea;
+ if($map[$x][$y][6] eq 'U' and $plague){
+ $map[$x][$y][6] = 'P';
+ }
+
+ $avatars = $db->avatar_present($loc);
+ ($own_avatar,$friend_avatar,$neutral_avatar,$enemy_avatar) = (0,0,0,0);
+ for my $a (@$avatars){
+ $a = $a->[0];
+ if($a == $user){
+ $own_avatar = 1;
+ }
+ elsif($db->get_relation($a) eq 'FOE' or $db->get_relation($a) eq 'BETRAY'){
+ $enemy_avatar = 1;
+ }
+ elsif($db->get_relation($a) eq 'FRIEND' or $db->get_relation($a) eq 'ALLIED'){
+ $friend_avatar = 1;
+ }
+ else{
+ $neutral_avatar = 1;
+ }
+ }
+
+ if($own_avatar){
+ if($enemy_avatar){
+ $map[$x][$y][4] = '0';
+ }elsif($neutral_avatar){
+ $map[$x][$y][4] = '1';
+ }elsif($friend_avatar){
+ $map[$x][$y][4] = '2';
+ }else{
+ $map[$x][$y][4] = '3';
+ }
+ }elsif($friend_avatar){
+ if($enemy_avatar){
+ $map[$x][$y][4] = '4';
+ }elsif($neutral_avatar){
+ $map[$x][$y][4] = '5';
+ }else{
+ $map[$x][$y][4] = '6';
+ }
+ }elsif($enemy_avatar){
+ if($neutral_avatar){
+ $map[$x][$y][4] = '7';
+ }else{
+ $map[$x][$y][4] = '8';
+ }
+ }elsif($neutral_avatar){
+ $map[$x][$y][4] = '9';
+ }else{
+ $map[$x][$y][4] = ($map[$x][$y][5] eq 'U' and $map[$x][$y][6] eq 'U' and $map[$x][$y][7] eq 'U')
+ ? 'X' : 'U'; # don't use overlay icons if all are empy (to save space)
+ }
+
+ }
+
+ $xmax++;$ymax++;
+
+ $xoff = $udat{-xoff};
+ $yoff = $udat{-yoff};
+
+-]
+
+ <table border="0" cellspacing="0" cellpadding="0">
+ [$ foreach $yy (0..($ymax-1)) $]
+ <tr><td><img src="map/SB[+ $map[$xoff][($yy+$yoff)%$ymax][0] +].png"></td>
+ [$ foreach $xx (0..($xmax-1)) $]
+ [- $x = ($xx +$xoff) % $xmax; -]
+ [$ if not $xx % 2 $]
+ [- $y = ($yy +$yoff -($xx / 2)) % $ymax; -]
+ [$ if $map[$x][$y][4] eq 'X' $]
+ [$ if $map[$x][$y][1] eq 'B' $]
+ <th rowspan="2"><img src="map/CB.png"></th>
+ [$ else $]
+ <th rowspan="2"><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/C[+ $map[$x][$y][1].$map[$x][$y][2].$map[$x][$y][3] +].png"></a></th>
+ [$ endif $]
+ [$ else $]
+ <th rowspan="2" background="map/C[+ $map[$x][$y][1].$map[$x][$y][2].$map[$x][$y][3] +].png"><table cellpadding="0" cellspacing="0" border="0">
+ <tr><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][4] +].png"></a></td><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][5] +].png"></a></td></tr>
+ <tr><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][6] +].png"></a></td><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][7] +].png"></a></td></tr></table></th>
+ [$ endif $]
+ [$ if not $yy $]
+ <td><img src="map/BB[+$map[$x][$y][0]+].png"></td>
+ [$ else $]
+ <td><img src="map/B[+$map[($x+1)%$xmax][($y-1)%$ymax][0].$map[$x][$y][0]+].png"></td>
+ [$ endif $]
+ [$ else $]
+ [$ if not $yy $]
+ <td><img src="map/HB.png"></td>
+ [$ if $xx==$xmax-1 $]
+ <td><img src="map/SBB.png"></td>
+ [$ else $]
+ <td><img src="map/SB[+$map[($x+1)%$xmax][($y-1)%$ymax][0]+].png"></td>
+ [$ endif $]
+ [$ else $]
+ [$ if $xx==$xmax-1 $]
+ <td><img src="map/S[+$map[$x][($y-1)%$ymax][0]+]B.png"></td>
+ [$ else $]
+ <td><img src="map/S[+$map[$x][($y-1)%$ymax][0].$map[($x+1)%$xmax][($y-1)%$ymax][0]+].png"></td>
+ [$ endif $]
+ [$ endif $]
+ [$ endif $]
+ [$ endforeach $]
+ </tr><tr>
+ <td><img src="map/B[+$map[$xoff][($yy+$yoff)%$ymax][0]+]B.png"></td>
+ [$ foreach $xx (0..($xmax-1)) $]
+ [$ if not $xx % 2 $]
+ [- $x = ($xx +$xoff +1)%$xmax; $y = ($yy +$yoff -($xx/2))%$ymax; -]
+ <td><img src="map/S[+$map[($x-1)%$xmax][$y][0].$map[$x][$y][0]+].png"></td>
+ [$ if $map[$x][$y][4] eq 'X' $]
+ [$ if $map[$x][$y][1] eq 'B' $]
+ <th rowspan="2"><img src="map/CB.png"></th>
+ [$ else $]
+ <th rowspan="2"><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/C[+ $map[$x][$y][1].$map[$x][$y][2].$map[$x][$y][3] +].png"></a></th>
+ [$ endif $]
+ [$ else $]
+ <th rowspan="2" background="map/C[+ $map[$x][$y][1].$map[$x][$y][2].$map[$x][$y][3] +].png"><table cellpadding="0" cellspacing="0" border="0">
+ <tr><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][4] +].png"></a></td><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][5] +].png"></a></td></tr>
+ <tr><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][6] +].png"></a></td><td><a href="field.epl?x=[+$x+]&y=[+$y+]" target="field"><img border="0" src="map/I[+ $map[$x][$y][7] +].png"></a></td></tr></table></th>
+ [$ endif $]
+ [$ if $xx==$xmax-2 $]
+ <td><img src="map/BB[+$map[$x][$y][0] +].png"></td>
+ [$ else $]
+ <td><img src="map/B[+$map[($x+1)%$xmax][($y-1)%$ymax][0].$map[$x][$y][0] +].png"></td>
+ [$ endif $]
+ [$ endif $]
+ [$ endforeach $]
+ </tr>
+ [$ endforeach $]
+ <tr>
+ <td><img src="map/SBB.png"></td>
+ [$ foreach $xx (0..($xmax-1)) $]
+ [$ if $xx % 2 $]
+ [- $x = ($xx + $xoff) % $xmax; $y = ($ymax +$yoff -($xx/2))% $ymax; -]
+ <td><img src="map/HB.png"></td>
+ <td><img src="map/B[+ $map[$x][$y][0] +]B.png"></td>
+ <td><img src="map/S[+ $map[$x][$y][0] +]B.png"></td>
+ [$ endif $]
+ [$ endforeach $]
+ </tr></table>
+
+[$ else $]
+
+ To view an Aymargeddon world-map, you must first <a href="login.epl" target="_top">login</a>,
+ because we need to know which game to display and for whom.
+
+[$ endif $]
+
+</body></html>
--- /dev/null
+Die Dateinamen sind so Computer-lesbar wie moeglich:
+
+Alle die mit B anfangen sind "Backslashes", die mit S
+"Slashes", die mit C "Center" und die mit I "Icons".
+bei den / und \ Bildern stehen die folgenden beiden
+Buchstaben fuer
+
+B Schwarz
+P Pol
+W Wasser
+U Unbesetzt
+N Neutral
+O Eigene
+F Freunde
+E Feinde
+
+(der erste Buchstabe gibt die "obere" der zweite die "untere" Farbe an).
+
+Bei den Center-Bildern steht der zweite Buchstabe fuer den
+Erdling der drin ist (wie oben), der dritte Buchstabe ist
+L Land, Manapol oder Berg ohne Tempel
+C Stadt bzw. Heimatstadt
+W Wasser bzw. Insel ohne Tempel
+I Insel mit Tempel
+M Berg mit Tempel
+
+der Letzte Buchstabe ist der Owner (B steht bei Heimatstaedten fuer
+NICHT-HEIMATSTADT also Stadt und U steht bei Bergen fuer NICHT-HEILIG
+also Plain). Der auserwaehlte Pol hat ein A als letzten Buchstaben.
+
+Bei den Icons steht das zweite Zeichen fuer
+
+0 es sind eigene und feindliche Avatare anwesend
+ (und vielleicht noch befreundete und/oder neutrale)
+1 es sind eigene und neutrale Avatare anwesend
+ (und vielleicht noch befreundete)
+2 es sind eigene und befreundete Avatare anwesend
+3 es sind nur eigene Avatare anwesend
+4 es sind befreundete und feindliche Avatare anwesend
+ (und vielleicht noch neutrale)
+5 es sind befreundete und neutrale Avatare anwesend
+6 es sind nur befreundete Avatare anwesend
+7 es sind feindliche und neutrale Avatare anwesend
+8 es sind nur feindliche Avatare anwesend
+9 es sind nur neutrale Avatare anwesend
+A es sind Archen im Feld
+E es findet gerade ein Erdlingskampf statt
+G es findet gerade ein Avatar-Kampf statt
+U leeres Icon (wir in allen vier Ecken als Fuellsel benoetigt)
+
+So, jetzt das komplette Set - ein paar Namen haben sich noch
+geaendert, weil mir ein Fehler unterlaufen war. Wirf das alte
+Verzeichnis also besser vorher weg.
+
+Fuer die Karte ohne Spieler werden nur 31 von den 214 Bildchen
+gebraucht, naemlich:
+
+CPLU Manapol
+CPLA Aymargeddon
+CUWU Wasser
+CUWN Insel
+CULU Ebene
+CULN Berg
+CUCU Heimatstadt
+CUCB Stadt
+
+BBP, BPB, SBP, SPB Manapol am Rand
+BWP, BPW, SWP, SPW zwischen Manapol und Wasser
+BBW, BWB, SBW, SWB Wasser am Rand
+BWW, SWW zwischen Wasserfeldern
+BWU, BUW, SWU, SWW zwischen Land und Wasser
+BBU, BUB, SBU, SUB Land am Rand
+BUU, SUU zwischen Landfeldern
+
+Drei von den Bildchen sollten bei konsistenten Daten eigentlich
+nie benoetigt werden, naemlich COLO, COMO und COIO (die selbe
+ID kann nie an einen Gott und einen Erdling gleichzeitig vergeben
+sein). Zu Testzwecken sind sie dennoch vorhanden.
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+ "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+ <head>
+ <title>Aymargeddon</title>
+ </head>
+
+ [- $udat{-current} = 'mapframe.epl'; -]
+
+ <frameset rows="34,*">
+ <frame src="menu_frames.epl" name="menu" />
+ <frameset cols="*,200">
+ <frame src="map.epl" name="map" />
+ <frame src="field.epl?x=0,y=0" name="field" />
+ </frameset>
+ <noframes>
+ keine frames
+ </noframes>
+ </frameset>
+</html>
--- /dev/null
+[-
+ use FROGS::Game;
+ use Aymargeddon;
+ use FROGS::DataBase;
+
+ # my ($aym,$gamename);
+ $db = DataBase->new();
+ $db->set_language($udat{-lang});
+ if($udat{-game} and $udat{-id}){
+ $aym = Aymargeddon->new($udat{-game},$udat{-id},$db);
+ $game = $aym;
+ $db->set_language($udat{-lang});
+ ($gamename) = $db->read_game($udat{-game},'NAME');
+ }
+
+-]
+<table width=100% border=0><tr>
+<td align="left">
+<a href="index.epl" target="_top">[+ $db->loc('PAGE_START') +]</a> |
+<a href="ruleframe.epl" target="_top">[+ $db->loc('PAGE_RULES') +]</a> |
+<a href="reference.epl" target="_top">[+ $db->loc('PAGE_REFERENCE') +]</a> |
+[$ if $udat{-id} $]
+ <a href="player.epl" target="_top">[+ $db->loc('PAGE_PLAYER') +]</a> |
+ [$ if $udat{-game} and ($udat{-id}==-1 or $game->read_role($udat{-id},'NICKNAME')) $]
+ <a href="mapframe.epl" target="_top">[+ $db->loc('PAGE_MAP') +]</a> |
+ [$ endif $]
+ <a href="login.epl" target="_top">[+ $db->loc('PAGE_LOGOUT') +]</a> |
+[$ else $]
+ <a href="login.epl" target="_top">[+ $db->loc('PAGE_LOGIN') +]</a> |
+[$ endif $]
+<a href="language.epl" target="_top">[+ $db->loc('PAGE_LANGUAGE') +]</a>
+</td><td align="right">
+[$ if(defined $aym) $]
+[# TODO: this does not work during character-generation #]
+ <strong>[+ $gamename +]</strong>, [+ $aym->role_string($udat{-id}) +],
+ [+ $aym->charname($udat{-id}) +]<p>
+[$ endif $]
+</td>
+</tr></table>
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="aymargeddon.css">
+<title>
+Aymargeddon - Menubar
+</title>
+</head>
+<body>[- Execute('menu.epl') -]
+</body>
+</html>
--- /dev/null
+Die Dateinamen sind so Computer-lesbar wie moeglich:
+
+Alle die mit B anfangen sind "Backslashes", die mit S
+"Slashes", die mit C "Center" und die mit I "Icons".
+bei den / und \ Bildern stehen die folgenden beiden
+Buchstaben fuer
+
+B Schwarz
+P Pol
+W Wasser
+U Unbesetzt
+N Neutral
+O Eigene
+F Freunde
+E Feinde
+
+(der erste Buchstabe gibt die "obere" der zweite die "untere" Farbe an).
+
+Bei den Center-Bildern steht der zweite Buchstabe fuer den
+Erdling der drin ist (wie oben), der dritte Buchstabe ist
+L Land, Manapol oder Berg ohne Tempel
+C Stadt bzw. Heimatstadt
+W Wasser bzw. Insel ohne Tempel
+I Insel mit Tempel
+M Berg mit Tempel
+
+der Letzte Buchstabe ist der Owner (B steht bei Heimatstaedten fuer
+NICHT-HEIMATSTADT also Stadt und U steht bei Bergen fuer NICHT-HEILIG
+also Plain). Der auserwaehlte Pol hat ein A als letzten Buchstaben.
+
+Bei den Icons steht das zweite Zeichen fuer
+
+0 es sind eigene und feindliche Avatare anwesend
+ (und vielleicht noch befreundete und/oder neutrale)
+1 es sind eigene und neutrale Avatare anwesend
+ (und vielleicht noch befreundete)
+2 es sind eigene und befreundete Avatare anwesend
+3 es sind nur eigene Avatare anwesend
+4 es sind befreundete und feindliche Avatare anwesend
+ (und vielleicht noch neutrale)
+5 es sind befreundete und neutrale Avatare anwesend
+6 es sind nur befreundete Avatare anwesend
+7 es sind feindliche und neutrale Avatare anwesend
+8 es sind nur feindliche Avatare anwesend
+9 es sind nur neutrale Avatare anwesend
+A es sind Archen im Feld
+E es findet gerade ein Erdlingskampf statt
+G es findet gerade ein Avatar-Kampf statt
+U leeres Icon (wir in allen vier Ecken als Fuellsel benoetigt)
+
+So, jetzt das komplette Set - ein paar Namen haben sich noch
+geaendert, weil mir ein Fehler unterlaufen war. Wirf das alte
+Verzeichnis also besser vorher weg.
+
+Fuer die Karte ohne Spieler werden nur 31 von den 214 Bildchen
+gebraucht, naemlich:
+
+CPLU Manapol
+CPLA Aymargeddon
+CUWU Wasser
+CUWN Insel
+CULU Ebene
+CULN Berg
+CUCU Heimatstadt
+CUCB Stadt
+
+BBP, BPB, SBP, SPB Manapol am Rand
+BWP, BPW, SWP, SPW zwischen Manapol und Wasser
+BBW, BWB, SBW, SWB Wasser am Rand
+BWW, SWW zwischen Wasserfeldern
+BWU, BUW, SWU, SWW zwischen Land und Wasser
+BBU, BUB, SBU, SUB Land am Rand
+BUU, SUU zwischen Landfeldern
+
+Drei von den Bildchen sollten bei konsistenten Daten eigentlich
+nie benoetigt werden, naemlich COLO, COMO und COIO (die selbe
+ID kann nie an einen Gott und einen Erdling gleichzeitig vergeben
+sein). Zu Testzwecken sind sie dennoch vorhanden.
+
--- /dev/null
+[- use FROGS::Config qw($conf); -]
+<html>
+<head><link rel="stylesheet" type="text/css" href="aymargeddon.css">
+<title>Aymargeddon</title></head>
+[-
+ $| = 1;
+ $udat{-current} = 'player.epl';
+
+ use Aymargeddon;
+ use Data::Dumper;
+ $db = DataBase->new();
+ $id = 0;
+ if($udat{-id}){
+ $id = $udat{-id};
+ }else{
+ $id = $db->authenticate($fdat{'login'},$fdat{'passwd'},
+ $fdat{'passwd2'},$fdat{'passwd3'});
+ }
+ if($udat{-lang}){
+ $db->set_language($udat{-lang});
+ #set language in Database in PLAYER.LANGUAGE
+ $db->update_hash('PLAYER',"PLAYER=$id",{'LANGUAGE' => $udat{-lang}});
+ $db->commit();
+ }else{
+ # set language according to PLAYER.LANGUAGE
+ # read_player() returns the first DB line in ARRAY format
+ ($udat{-lang}) = $db->read_player($id,'LANGUAGE');
+ }
+
+ $escmode = 0;
+
+ # TODO: klappt nich :-(
+ # $out = '<body style="font-size:10pt" bgcolor="'.$conf->{-COLOR}->{-EMPTY}.'">';
+ $out = '<body style="line-height:12pt;font-size:10pt">';
+-]
+[+$out+]
+
+[$ if $id $] [# logged in - show game list, messages, etc. pp. #]
+
+ [-
+ $udat{-id} = $id;
+
+ # switch game-id
+ $udat{-game} = $fdat{'game'} if exists $fdat{'game'};
+ $aym = Aymargeddon->new($udat{-game},$id,$db) if exists $udat{-game};
+
+ if(exists $fdat{'game'}){
+ $udat{-loc} = $aym->startfield();
+ $udat{-loc} =~ /^(\d+)\_(\d+)$/;
+ my ($x,$y) = ($1, $2);
+ my $size = $aym->get_size();
+ $udat{-xoff} = $x -$size;
+ $udat{-yoff} = $y;
+ }
+
+
+
+ # register for selected role in game
+ if($fdat{'role'} and $fdat{'charname'}){
+ my $return = $aym->new_role($fdat{'role'},
+ $fdat{'charname'},
+ $fdat{'gender'});
+ # $fdat{'description'});
+ unless($return){
+ print OUT "<strong>Error: cant register role.</strong><p>";
+ }
+ }
+
+ # delete all messages if wanted.
+ # TODO: write timestamp in link and delete only to this time
+ if($fdat{delete_all_messages} == 1){
+ $aym->delete_all_messages($fdat{time});
+ $db->commit();
+ }
+
+ Execute("menu.epl");
+
+ $own_games = $db->games_of_player($id);
+ $open_games = $db->open_games("HOME=-1");
+
+ %such = ();
+ for my $og (@$own_games){
+ $such{$og->[0]} = 1;
+ }
+
+ @real_open_games = ();
+ for $og (@$open_games){
+ push @real_open_games, $og unless exists $such{$og->[0]};
+ }
+
+ ($rn) = $db->read_player($id, 'REALNAME') unless exists $udat{-game};
+ -]
+
+ [$ if not exists $udat{-game} $]
+ <hr>
+ [+ $db->loc('PLAYER_WELCOME').' Aymargeddon '.$rn +]!<p>
+ [$ endif $]
+
+ <hr>
+ <table width=100% border=0><colgroup><col width="200"><col></colgroup>
+ <tr><td valign="top" bgcolor="#b8a266">
+ <p>[+ $db->loc('PLAYER_OWN_GAMES') +]<p>
+ [$ foreach $og (@$own_games) $]
+ [- $og = $og->[0]; ($og_name) = $db->read_game($og,'NAME'); -]
+ <a href="player.epl?game=[+$og+]">[+$og_name+]</a><p>
+ [$ endforeach $]
+ [$ if $#{@$own_games} < 0 $]
+ [+ $db->loc('PLAYER_GAMES_NONE') +]<p>
+ [$ endif $]
+ <hr>
+ <p>[+ $db->loc('PLAYER_OPENGAMES') +]:<p>
+ [$ foreach $og (@real_open_games) $]
+ [- $og=$og->[0]; ($og_name) = $db->read_game($og,'NAME'); -]
+ <a href="player.epl?game=[+$og+]">[+$og_name+]</a><p>
+ [$ endforeach $]
+ [$ if $#{@real_open_games} < 0 $]
+ [+ $db->loc('PLAYER_GAMES_NONE') +]<p>
+ [$ endif $]
+ <hr></td>
+ <td valign="top" bgcolor="#fcffd9">
+ [$ if not exists $udat{-game} $]
+
+ [+ $db->loc('PLAYER_CHOOSE_GAME') +]
+
+ [$ elsif exists $fdat{'cmd'} $]
+ [- Execute('command_frames.epl') -]
+ [$ elsif $such{$udat{-game}} $]
+ <center>
+
+ [# [-
+ ($gn) = $db->read_game($udat{-game},'NAME');
+ my @list = $aym->charname($udat{-id});
+ $cn = $list[0];
+ -]
+ [+ $db->loc('PLAYER_WELCOME') +] <strong>[+ $gn +]</strong>, [+ $cn +].<p>
+ <hr> #]
+
+
+ [-
+ $messages = $aym->read_messages();
+ $now = $db->now();
+ -]
+ <strong>[+ $db->loc('PLAYER_MESSAGES_HEADING') +]</strong><p>
+ <a href="player.epl?delete_all_messages=1&time=[+$now+]">
+ [+ $db->loc('PLAYER_DELETE_MESSAGES')+]</a><p>
+ [$ foreach $msg (@$messages) $]
+ [+ $aym->show_message($msg->[0]) +]<br>
+ [$ endforeach $]
+ [$ if $#{@$messages} < 0 $]
+ [+ $db->loc('PLAYER_NO_MESSAGE') +]
+ [$ endif $]
+ <p>
+[# we dont show events in a global list any more
+ <strong>[+ $db->loc('PLAYER_EVENTS') +]</strong><p>
+ [-
+ $events = $aym->role_events();
+ -]
+ [$ foreach $e (@$events) $]
+ [+ $aym->show_event($e->{'ID'}) +]<p>
+ [$ endforeach $]
+ [$ if $#{@$events} < 0 $]
+ [+ $db->loc('PLAYER_NO_EVENTS') +]<p>
+ [$ endif $]
+#]
+ <strong>[+ $db->loc('PLAYER_STATISTIC') +]</strong><p>
+ [+ $aym->show_statistic() +]
+ <p><a href="mapframe.epl">[+ $db->loc('PLAYER_TO_MAP') +]</a>
+ </center>
+ [$ else $]
+ [- Execute('role_select.epl'); -]
+ [$ endif $]
+ </td></tr></table>
+[$ else $] [# wrong login #]
+
+ [- Execute("menu.epl"); -]
+ <p><p>[+ $db->loc('LOGIN_FAILED') +]<p>
+ [- print OUT $db->loc('ERROR_NO_LOGIN'); -]
+
+[$ endif $]
+</body></html>
+
+
--- /dev/null
+<html>
+<head>
+ <title>Aymargeddon</title>
+</head>
+
+[-
+
+ use FROGS::Config;
+ $udat{-current} = 'reference.epl';
+ Execute("menu.epl");
+-]
+<hr>
+[-
+ $udat{-lang} = $::conf->{-DEFAULT_LANGUAGE} unless exists $udat{-lang};
+
+ if($udat{-lang} eq 'EN'){
+ Execute("table_english.html");
+ }elsif($udat{-lang} eq 'DE'){
+ Execute("table_german.html");
+ }
+-]
+
+
+</body>
+</html>
+
--- /dev/null
+[$ if exists $udat{-id} and exists $udat{-game} $]
+
+[-
+ use Aymargeddon;
+ $db = DataBase->new();
+ $aym = Aymargeddon->new($udat{-game},$udat{-id},$db);
+ $db->set_language($udat{-lang});
+
+ # open for earthlings?
+ $open_earthling = $aym->is_open('CITY');
+ # open for gods?
+ $open_god = $aym->is_open('MOUNTAIN');
+
+ # open for observers?
+ ($open_observer) = $db->read_player($udat{-id},'SECURITY');
+ $open_observer = 0 if $open_observer eq 'USER';
+
+ ($gn) = $db->read_game($udat{-game},'NAME');
+
+-]
+
+<form method="get" action="player.epl">
+
+ [+ $db->loc('PLAYER_CREATE_CHAR').' '.$gn +]:<p>
+
+ [+ $db->loc('NOM_CHARNAME') +]: <input type="text" name="charname" size="20" maxlength="20"><p>
+
+ [+ $db->loc('NOM_ROLE') +]:
+ [$ if $open_earthling $]
+ <input type="radio" name="role" value="EARTHLING">[+ $db->loc('ROLE_EARTHLING') +]
+ [$ endif $]
+ [$ if $open_god $]
+ <input type="radio" name="role" value="GOD">[+ $db->loc('ROLE_GOD') +]
+ [$ endif $]
+ [$ if $open_observer $]
+ <input type="radio" name="role" value="OBSERVER">[+ $db->loc('ROLE_OBSERVER') +]
+ [$ endif $]
+ <p>
+
+ [+ $db->loc('NOM_GENDER') +]: <input type="radio" name="gender" value="MALE">[+ $db->loc('GEN_MALE') +]
+ <input type="radio" name="gender" value="FEMALE">[+ $db->loc('GEN_FEMALE') +]
+ <input type="radio" name="gender" value="PLURAL" checked>[+ $db->loc('GEN_PLURAL') +]<p>
+[# [+ $db->loc('NOM_DESCRIPTION') +]: <input type="text" name="description"><p> #]
+ <input type="submit" value="[+ $db->loc('FORM_OK_BUTTON') +]">
+
+</form>
+
+[$ else $]
+
+ [- print OUT $db->loc('ERROR_NO_LOGIN'); -]
+
+[$ endif $]
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+ "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+ <head>
+ <title>Frameset for the rules</title>
+ </head>
+
+ [- $udat{-current} = 'ruleframe.epl'; -]
+
+ <frameset rows="34,*">
+ <frame src="menu_frames.epl" name="menu" />
+ <frame src="/wiki/index.php/Regeln" name="rules" />
+ <noframes>
+ keine frames
+ </noframes>
+ </frameset>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<html>
+<head>
+ <meta http-equiv="CONTENT-TYPE"
+ content="text/html; charset=windows-1252">
+ <title>Fakten_deu</title>
+ <meta name="GENERATOR" content="OpenOffice.org 1.0.1 (Win32)">
+ <meta name="AUTHOR" content="Christine Bauer">
+ <meta name="CREATED" content="20050322;22401092">
+ <meta name="CHANGEDBY" content="Christine Bauer">
+ <meta name="CHANGED" content="20050323;12460082">
+</head>
+<body lang="de-DE">
+<table><tr valign="top"><td><p><span style="font-weight: bold;"></span><font
+ face="Albany, sans-serif"><font style="font-size: 11pt;" size="2"><b>
+campaign<br>
+</b></font></font></p>
+<table style="page-break-before: always;" border="1" cellpadding="2"
+ cellspacing="0" width="285">
+ <col width="98"> <col width="80"> <col width="93"> <tbody>
+ <tr>
+ <th bgcolor="#e6e6e6" width="98">
+ <p><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="80">
+ <p><font style="font-size: 9pt;" size="2">fighting power</font></p>
+ </th>
+ <th bgcolor="#e6e6e6" width="93">
+ <p><font style="font-size: 9pt;" size="2">time units movement</font></p>
+ </th>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">warrior</font>
+ </p>
+ </th>
+ <td sdval="1" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">hero</font></p>
+ </th>
+ <td width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td sdval="6" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">6</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">priest</font></p>
+ </th>
+ <td sdval="0" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ <td sdval="12" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">12</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">avatar</font></p>
+ </th>
+ <td width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">up to +
+4</font></p>
+ </td>
+ <td sdval="1" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">ark</font></p>
+ </th>
+ <td sdval="3" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">3</font></p>
+ </td>
+ <td sdval="5" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">home city</font></p>
+ </th>
+ <td sdval="2" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">flanking</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table></td><td rowspan="2">
+<p style="page-break-after: avoid;"><font
+ face="Albany, sans-serif"><font style="font-size: 11pt;" size="2"><b>divine actions</b></font></font></p>
+<table border="1" cellpadding="4" cellspacing="0" width="291">
+ <col width="149"> <col width="48"> <col width="68"> <thead> <tr
+ valign="top">
+ <th bgcolor="#e6e6e6" width="149">
+ <p align="center"><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">mana</font></p>
+ </th>
+ <th bgcolor="#e6e6e6" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">time units</font></p>
+ </th>
+ </tr>
+ </thead> <tbody>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">bless hero</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">bless priest</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">build ark</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="30" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">30</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">summon avatar</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">move avatar</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">avatar fight</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2 per fight</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">avatar help in fight of earthlings</font></p>
+ </th>
+ <td bgcolor="#ffffcc" valign="top" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2 per
+fight</font></p>
+ </td>
+ <td bgcolor="#ffffcc" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">flood</font></p>
+ </th>
+ <td sdval="2" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td valign="top" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">destroy temple</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">plague:
+influentia </font> </p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">plague:
+pestilenzia</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ <td sdval="20" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Plague:
+ebola</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ <td sdval="30" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Change luck</font></p>
+ </th>
+ <td valign="top" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1 per point</font></p>
+ </td>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table></td></tr><tr><td>
+<p><font style="font-size: 11pt;" size="2"><b>miscellanous timing</b></font>
+</p>
+<table border="1" cellpadding="4" cellspacing="0" width="242">
+ <col width="148"> <col width="76"> <thead> <tr valign="top">
+ <th bgcolor="#e6e6e6" width="148">
+ <p><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="76">
+ <p><font style="font-size: 9pt;" size="2">time units</font></p>
+ </th>
+ </tr>
+ </thead> <tbody>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">build temple</font></p>
+ </th>
+ <td valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">3, 6,
+9....</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">earthlings fight</font></p>
+ </th>
+ <td sdval="6" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">6</font></p>
+ </td>
+ </tr>
+ <tr valign="top">
+ <th width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">warrior production</font></p>
+ </th>
+ <td width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">40 + 4 * PEACE</font></p>
+ </td>
+ </tr>
+ <tr valign="top">
+ <th width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">warrior production homecity</font></p>
+ </th>
+ <td width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">priest production</font></p>
+ </th>
+ <td sdval="40" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">mana
+produktion</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</td></tr></table>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<html>
+<head>
+ <meta http-equiv="CONTENT-TYPE"
+ content="text/html; charset=windows-1252">
+ <title>Fakten_deu</title>
+ <meta name="GENERATOR" content="OpenOffice.org 1.0.1 (Win32)">
+ <meta name="AUTHOR" content="Christine Bauer">
+ <meta name="CREATED" content="20050322;22401092">
+ <meta name="CHANGEDBY" content="Christine Bauer">
+ <meta name="CHANGED" content="20050323;12460082">
+</head>
+<body lang="de-DE">
+<table><tr valign="top"><td><p><span style="font-weight: bold;"></span><font
+ face="Albany, sans-serif"><font style="font-size: 11pt;" size="2"><b>
+Feldzüge<br>
+</b></font></font></p>
+<table style="page-break-before: always;" border="1" cellpadding="2"
+ cellspacing="0" width="285">
+ <col width="98"> <col width="80"> <col width="93"> <tbody>
+ <tr>
+ <th bgcolor="#e6e6e6" width="98">
+ <p><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="80">
+ <p><font style="font-size: 9pt;" size="2">Kampfstärke</font></p>
+ </th>
+ <th bgcolor="#e6e6e6" width="93">
+ <p><font style="font-size: 9pt;" size="2">Zeiteinheiten Bewegung</font></p>
+ </th>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Krieger </font>
+ </p>
+ </th>
+ <td sdval="1" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Held</font></p>
+ </th>
+ <td width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td sdval="6" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">6</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Priester</font></p>
+ </th>
+ <td sdval="0" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ <td sdval="12" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">12</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Avatar</font></p>
+ </th>
+ <td width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">bis zu +
+4</font></p>
+ </td>
+ <td sdval="1" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Arche</font></p>
+ </th>
+ <td sdval="3" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">3</font></p>
+ </td>
+ <td sdval="5" sdnum="1031;" width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Heimatstadt</font></p>
+ </th>
+ <td sdval="2" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th width="98">
+ <p align="left"><font style="font-size: 9pt;" size="2">Flankierung</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" width="80">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td width="93">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table></td><td rowspan="2">
+<p style="page-break-after: avoid;"><font
+ face="Albany, sans-serif"><font style="font-size: 11pt;" size="2"><b>Götteraktionen</b></font></font></p>
+<table border="1" cellpadding="4" cellspacing="0" width="291">
+ <col width="149"> <col width="48"> <col width="68"> <thead> <tr
+ valign="top">
+ <th bgcolor="#e6e6e6" width="149">
+ <p align="center"><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">Mana</font></p>
+ </th>
+ <th bgcolor="#e6e6e6" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">Zeiteinheiten</font></p>
+ </th>
+ </tr>
+ </thead> <tbody>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Helden
+weihen</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Priester
+erleuchten</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Arche bauen</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="30" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">30</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Avatar
+erschaffen</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Avatar
+bewegen</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">1</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Avatarkampf</font></p>
+ </th>
+ <td sdval="1" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2 pro Kampf</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffffcc" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffffcc" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Avatar-
+Hilfe im Erdlingskampf</font></p>
+ </th>
+ <td bgcolor="#ffffcc" valign="top" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2 pro
+Kampf</font></p>
+ </td>
+ <td bgcolor="#ffffcc" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">--</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Sintflut</font></p>
+ </th>
+ <td sdval="2" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">2</font></p>
+ </td>
+ <td valign="top" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Tempel
+zerstören</font></p>
+ </th>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">5</font></p>
+ </td>
+ <td sdval="0" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Seuche:
+Influentia </font> </p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Seuche:
+Pestilenzia</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ <td sdval="20" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th bgcolor="#ffcc99" valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Seuche:
+Ebola</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ <td sdval="30" sdnum="1031;" bgcolor="#ffcc99" valign="bottom"
+ width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="149">
+ <p align="left"><font style="font-size: 9pt;" size="2">Glücksfaktor
+ändern</font></p>
+ </th>
+ <td valign="top" width="48">
+ <p align="center"><font style="font-size: 9pt;" size="2">1 pro
+Punkt</font></p>
+ </td>
+ <td sdval="5" sdnum="1031;" valign="bottom" width="68">
+ <p align="center"><font style="font-size: 9pt;" size="2">0</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table></td></tr><tr><td>
+<p><font style="font-size: 11pt;" size="2"><b>Sonstiges Timing </b></font>
+</p>
+<table border="1" cellpadding="4" cellspacing="0" width="242">
+ <col width="148"> <col width="76"> <thead> <tr valign="top">
+ <th bgcolor="#e6e6e6" width="148">
+ <p><br>
+ </p>
+ </th>
+ <th bgcolor="#e6e6e6" width="76">
+ <p><font style="font-size: 9pt;" size="2">Zeiteinheiten</font></p>
+ </th>
+ </tr>
+ </thead> <tbody>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Tempelbau</font></p>
+ </th>
+ <td valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">3, 6,
+9....</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Erdlingskampf</font></p>
+ </th>
+ <td sdval="6" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">6</font></p>
+ </td>
+ </tr>
+ <tr valign="top">
+ <th width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Krieger
+Produktion</font></p>
+ </th>
+ <td width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">40 + 4 * PEACE</font></p>
+ </td>
+ </tr>
+ <tr valign="top">
+ <th width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Krieger
+Produktion Heimatstadt</font></p>
+ </th>
+ <td width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">20</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Priester
+Produktion</font></p>
+ </th>
+ <td sdval="40" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">40</font></p>
+ </td>
+ </tr>
+ <tr>
+ <th valign="top" width="148">
+ <p align="left"><font style="font-size: 9pt;" size="2">Mana
+Produktion</font></p>
+ </th>
+ <td sdval="10" sdnum="1031;" valign="bottom" width="76">
+ <p align="center"><font style="font-size: 9pt;" size="2">10</font></p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</td></tr></table>
+</body>
+</html>
--- /dev/null
+<hr>
+<h2>The last days of Aymargeddon</h2>
+
+This is the homepage of the game "The last days of Aymargeddon". The game is still under development. It will be a multi-player-browser-game and it is a successor of the
+Pbem <a href="http://ragnaroek.home.pages.de/"> Ragnarök </a>.
+<p>
+The next Beta-Test will start in the beginning of june.
+<p>
+You can <a href="login.epl">participate</a> if you are willing to help in the
+development with your bug reports.
+In this case please subscribe to the mailinglist (see below).
+<p>
+Unfortunatly the Rules are in german only in the moment, sorry).
+<hr>
+You have read-access to the sourcecode via
+<a href="http://www.gnu.org/software/gnu-arch/">Gnu Arch</a>.
+
+<p>Archiv
+coordinates:
+<pre>
+ archive: benni@obda.de--2003-A
+ location: http://aymargeddon.de/ARCHIVES/2003-A
+ project: aymargeddon--main--0.2
+</pre>
+
+<p>
+ Aymargeddon is <a href="http://www.gnu.org/philosophy/free-sw.html">free software</a>;
+you can redistribute it and/or modify it
+ under the terms of the <a href="src/COPYING">GNU General Public
+License</a>.
+
+<strong>Warning:</strong> MS-IE-Explorer cant display transparent
+png's, therefore this program cant be used to play this game. In the
+moment the best browser for playing Aymargeddon is one derived from Mozilla (Netscape, Firefox, ...).
+
+<hr>If you are interested in the game you should subscribe to the mailinglist. Please send a mail to
+
+<pre>
+majordomo@informatik.uni-frankfurt.de
+</pre>
+
+with the following content:
+
+<pre>
+subscribe ragnaroek
+</pre>
+
+If you want to get rid of the mails you send
+
+<pre>
+unsubscribe ragnaroek
+</pre>
+
+<hr>
+ A Screenshot of the last game:
+<img src="pic/Screenshot.png">
+
+<hr>
+<a href="http://www.informatik.uni-frankfurt.de/~benni/hello.html">
+Bennis Homepage</a>
+
--- /dev/null
+<hr>
+<h2>Die letzen Tage von Aymargeddon</h2>
+Dies ist die Homepage des Spiels "Die letzten Tage von Aymargeddon".
+Das Spiel ist noch in der Entwicklung. Es soll ein
+Browser-Multi-Player-Spiel werden und ist eine Weiterentwicklung des
+Pbem <a href="http://ragnaroek.home.pages.de/"> Ragnarök </a>.
+<p>
+Der nächste Beta-Test startet Anfang Juni.
+<p>
+Du kannst gerne daran <a
+href="login.epl">teilnehmen</a>, wenn Du Lust hast uns mit
+Fehlerberichten dabei zu helfen, das Spiel zu entwickeln. In diesem
+Fall solltest Du Dich auf die Mailingliste eintragen (siehe unten).
+<p>
+<hr>
+Den Quellcode kann man lesend zugreifen über
+<a href="http://www.gnu.org/software/gnu-arch/">Gnu Arch</a>.
+
+<p>Archiv
+koordinaten:
+<pre>
+ archive: benni@obda.de--2003-A
+ location: http://aymargeddon.de/ARCHIVES/2003-A
+ project: aymargeddon--main--0.2
+</pre>
+
+<p>
+ Aymargeddon is <a href="http://www.gnu.org/philosophy/free-sw.html">free software</a>;
+you can redistribute it and/or modify it
+ under the terms of the <a href="src/COPYING">GNU General Public
+License</a>.
+<hr>
+
+<strong>Warnung:</strong> Der MS-Internet-Explorer kann transparente
+PNGs nicht korrekt anzeigen und ist deswegen unbrauchbar. Momentan
+funktioniert am Besten Mozilla und abgeleitete Browser (Netscape oder
+Firefox z.B.). Generell soll Aymargeddon aber für alle Browser
+spielbar sein.
+
+<hr>Wer interesse an dem Spiel hat, sollte sich auf die Mailingliste
+eintragen. Dazu bitte eine Mail an
+
+<pre>
+majordomo@informatik.uni-frankfurt.de
+</pre>
+
+mit folgendem Inhalt:
+
+<pre>
+subscribe ragnaroek
+</pre>
+
+Solltet ihr wieder von dieser Liste runter wollen, schickt ihr einfach
+ein:
+
+<pre>
+unsubscribe ragnaroek
+</pre>
+
+<hr>
+Hier ein Screenshot vom letzten Test:
+<img src="pic/Screenshot.png">
+<hr>
+<a href="http://www.informatik.uni-frankfurt.de/~benni/hello.html">
+Bennis Homepage</a>
+
--- /dev/null
+#!/bin/sh
+
+echo "Lines of Code:"
+
+echo "Embedded Perl:"
+cat html/*.epl | wc -l
+
+echo "FROGS:"
+cat src/FROGS/*.pm src/FROGS/*.pl | wc -l
+
+echo "other Perl:"
+cat src/*.pl src/*.pm | wc -l
+
+echo "SQL:"
+cat var/RAGNAROEK.sql var/LOCALIZE.sql | wc -l
+
+echo "scripts:"
+cat var/delete_game linecount var/do_sql var/extract_structure_and_localize var/backup var/from_scratch \
+ agrep push doc/push_rules src/FROGS/speed_scheduler src/FROGS/start_scheduler | wc -l
+
+echo "------------------"
+echo "total:"
+cat var/delete_game html/*.epl src/FROGS/*.pm src/FROGS/*.pl src/*.pl src/*.pm \
+ linecount var/do_sql var/extract_structure_and_localize var/backup var/from_scratch \
+ agrep push doc/push_rules src/FROGS/speed_scheduler src/FROGS/start_scheduler \
+ var/RAGNAROEK.sql var/LOCALIZE.sql | wc -l
--- /dev/null
+Die Dateinamen sind so Computer-lesbar wie moeglich:
+
+Alle die mit B anfangen sind "Backslashes", die mit S
+"Slashes", die mit C "Center" und die mit I "Icons".
+bei den / und \ Bildern stehen die folgenden beiden
+Buchstaben fuer
+
+B Schwarz
+P Pol
+W Wasser
+U Unbesetzt
+N Neutral
+O Eigene
+F Freunde
+E Feinde
+
+(der erste Buchstabe gibt die "obere" der zweite die "untere" Farbe an).
+
+Bei den Center-Bildern steht der zweite Buchstabe fuer den
+Erdling der drin ist (wie oben), der dritte Buchstabe ist
+L Land, Manapol oder Berg ohne Tempel
+C Stadt bzw. Heimatstadt
+W Wasser bzw. Insel ohne Tempel
+I Insel mit Tempel
+M Berg mit Tempel
+
+der Letzte Buchstabe ist der Owner (B steht bei Heimatstaedten fuer
+NICHT-HEIMATSTADT also Stadt und U steht bei Bergen fuer NICHT-HEILIG
+also Plain). Der auserwaehlte Pol hat ein A als letzten Buchstaben.
+
+Bei den Icons steht das zweite Zeichen fuer
+
+0 es sind eigene und feindliche Avatare anwesend
+ (und vielleicht noch befreundete und/oder neutrale)
+1 es sind eigene und neutrale Avatare anwesend
+ (und vielleicht noch befreundete)
+2 es sind eigene und befreundete Avatare anwesend
+3 es sind nur eigene Avatare anwesend
+4 es sind befreundete und feindliche Avatare anwesend
+ (und vielleicht noch neutrale)
+5 es sind befreundete und neutrale Avatare anwesend
+6 es sind nur befreundete Avatare anwesend
+7 es sind feindliche und neutrale Avatare anwesend
+8 es sind nur feindliche Avatare anwesend
+9 es sind nur neutrale Avatare anwesend
+A es sind Archen im Feld
+E es findet gerade ein Erdlingskampf statt
+G es findet gerade ein Avatar-Kampf statt
+U leeres Icon (wir in allen vier Ecken als Fuellsel benoetigt)
+
+So, jetzt das komplette Set - ein paar Namen haben sich noch
+geaendert, weil mir ein Fehler unterlaufen war. Wirf das alte
+Verzeichnis also besser vorher weg.
+
+Fuer die Karte ohne Spieler werden nur 31 von den 214 Bildchen
+gebraucht, naemlich:
+
+CPLU Manapol
+CPLA Aymargeddon
+CUWU Wasser
+CUWN Insel
+CULU Ebene
+CULN Berg
+CUCU Heimatstadt
+CUCB Stadt
+
+BBP, BPB, SBP, SPB Manapol am Rand
+BWP, BPW, SWP, SPW zwischen Manapol und Wasser
+BBW, BWB, SBW, SWB Wasser am Rand
+BWW, SWW zwischen Wasserfeldern
+BWU, BUW, SWU, SWW zwischen Land und Wasser
+BBU, BUB, SBU, SUB Land am Rand
+BUU, SUU zwischen Landfeldern
+
+Drei von den Bildchen sollten bei konsistenten Daten eigentlich
+nie benoetigt werden, naemlich COLO, COMO und COIO (die selbe
+ID kann nie an einen Gott und einen Erdling gleichzeitig vergeben
+sein). Zu Testzwecken sind sie dennoch vorhanden.
+
--- /dev/null
+#!/bin/sh
+
+# copy aymargeddon documentation to the webserver.
+scp -r doc/*.html doc/*.pdf aymargeddon.de:public_html/aymargeddon/
+
--- /dev/null
+
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+# Aymargeddon specific command clsses used by the scheduler
+# generic FROGS-Command is in FROGS/Command.pm
+#
+
+use strict;
+use FROGS::Util;
+use FROGS::HexTorus;
+use Data::Dumper;
+
+##########################################################
+#
+# Base Class for Aymargeddon specific commands
+#
+
+package AymCommand;
+use Data::Dumper;
+@AymCommand::ISA = qw(Command);
+
+sub end_of_the_game{
+ my $self = shift;
+
+ $self->{-context}->send_message_to_all({'MFROM' => 0,
+ 'MSG_TAG' => 'END_OF_GAME'});
+
+ Util::log("*****************************\n" .
+ "*** End of the Game! ***\n" .
+ "*****************************",0);
+
+ $self->{-db}->update_hash('GAME',
+ "GAME=$self->{-game}",
+ {'RUNNING' => 'N'});
+
+}
+
+# just a wrapper
+sub avatar_available{
+ my ($self,$loc,$god) = @_;
+ $god = $self->{-player} unless defined $god;
+ return $self->{-context}->avatar_available($loc,$god,$self->{-class});
+}
+
+# just another wrapper
+sub get_neighbours{
+ my ($self,$loc) = @_;
+ $loc = $self->{-dbhash}->{'LOCATION'} unless defined $loc;
+
+ my $map = HexTorus->new($self->{-context}->get_size());
+ my $location = Location->from_string($loc);
+ my @neighbours = $map->neighbours($location);
+ return map {$_ = $_->to_string();} @neighbours;
+}
+
+# FIGHT_EARTHLING and Pestilenz
+sub casualties{
+ my ($self,$victim,$death_count,$no_conquer) = @_;
+ $self->{-looser} = $victim unless defined $self->{-looser};
+ my $other;
+ unless(defined $no_conquer){
+ $other = ($victim != $self->{-winner}) ? $self->{-winner} : $self->{-looser};
+ }
+
+ Util::log("death_count for $victim: $death_count",1);
+
+ $self->{-dead}->{$victim} = {'A' => 0,
+ 'H' => 0,
+ 'P' => 0,
+ 'K' => 0,
+ 'C' => 0}; # conquered arks
+
+ return unless $death_count;
+
+ my $dying = $::conf->{-DEFAULT_DYING};
+ unless($self->{-looser} < 0){
+ my $earthling = $self->{-db}->single_hash_select('EARTHLING',
+ "PLAYER=$self->{-looser} AND ".
+ "GAME=$self->{-game}");
+ $dying = $earthling->{'DYING'};
+ }
+ $dying .= 'A';
+ my $big_dying = {'P' => 'PRIEST',
+ 'K' => 'WARRIOR',
+ 'H' => 'HERO',
+ 'A' => 'ARK'};
+
+ # print Dumper $dying;
+
+ # rearrange mobiles in a hash
+ # TODO PERFORMANCE,DESIGN: we should have read $self->{-mobiles}
+ # as a hash from database earlier, should be better in all cases.
+ my %victims_mobiles = ();
+ for my $mob (@{$self->{-mobiles}}){
+ my ($id,$type,$own,$count,$stat) = @$mob;
+ next unless $own == $victim;
+ $victims_mobiles{$id} = $mob;
+ }
+
+ # print Dumper \%victims_mobiles;
+
+ my ($row, $carry, $share, $conquered_arks) = (0,0,0,0);
+ my $to_kill = $death_count;
+ my @small_dying = split //,$dying;
+ while(int($to_kill) > 0 and %victims_mobiles){
+ my $small_dying = $small_dying[$row];
+ # for my $small_dying (split //,$dying){
+ $carry += $death_count * $::conf->{-DEATH_SHARE_ROW}->[$row];
+ $share = int($carry);
+ $carry -= $share;
+ $share = $to_kill if($share > $to_kill);
+
+ Util::log("type: $small_dying, share: $share, carry: $carry, to_kill: $to_kill",2);
+
+ while( my ($key,$value) = each %victims_mobiles){
+ my ($id,$type,$own,$count,$stat) = @$value;
+ # next unless $own == $victim;
+ next unless $type eq $big_dying->{$small_dying};
+ Util::log("id: $id, count: $count, share: $share, ".
+ "carry: $carry, to_kill: $to_kill",2);
+
+ my $dead_men = Util::min($count,$share);
+ $self->{-dead}->{$victim}->{$small_dying} += $dead_men;
+ if($small_dying eq 'H'){
+ # dead heros fights for gods in last battle
+ my ($god) = $self->{-context}->get_mobile_info($id,'ADORING');
+ Util::log("adored god: $god",1);
+ my ($actual) = $self->{-db}->single_select("SELECT DEATH_HERO FROM GOD WHERE ".
+ "GAME=$self->{-game} AND ".
+ "PLAYER=$god");
+ Util::log("HERO dying: adds $dead_men heros ".
+ "to last-battle-strength of $god",1);
+ $self->{-db}->update_hash('GOD',
+ "GAME=$self->{-game} AND PLAYER=$god",
+ {'DEATH_HERO' => $actual + $dead_men});
+ }elsif($small_dying eq 'A' and $victim == $self->{-looser}
+ and not defined $no_conquer){
+ # special case ark (can change owner)
+ my $random_value = rand($dead_men);
+ Util::log("random value of $dead_men: $random_value",1);
+ $conquered_arks = int($random_value+0.5);
+ # $dead_men -= $conquered_arks;
+ Util::log("ark in battle: $conquered_arks change owner to $other, ".
+ "$dead_men arks sinking or conquered.",1);
+ $self->{-dead}->{$victim}->{'C'} += $conquered_arks;
+ }
+
+ if($count > $dead_men){
+ my $new_count = $count - $dead_men;
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$id",
+ {'COUNT' => $new_count});
+ $victims_mobiles{$id}->[3] = $new_count;
+ Util::log("Mobile $id ($small_dying) looses $dead_men people ".
+ "and have now $new_count.",1);
+ $to_kill -= $dead_men;
+ last;
+ }else{
+ $share -= $count;
+ $to_kill -= $count;
+ $self->{-db}->delete_from('MOBILE',"ID=$id");
+ $self->{-db}->update_hash('MOBILE',
+ "MOVE_WITH=$id",
+ {'MOVE_WITH' => 0});
+ Util::log("Mobile $id ($small_dying) with $dead_men people is deleted",1);
+ delete $victims_mobiles{$id};
+ }
+ }
+
+ $carry += $share;
+ $row = ($row + 1)%4;
+ }
+
+ unless(defined $no_conquer){
+ my $total_conquered_arks = $self->{-dead}->{$victim}->{'C'};
+ if($total_conquered_arks){
+ # now conquered arks are (re-)created
+ my $mob = {'ID' => $self->{-db}->find_first_free('MOBILE','ID'),
+ 'GAME' => $self->{-game},
+ 'LOCATION' => $self->{-location},
+ 'TYPE' => 'ARK',
+ 'OWNER' => $self->{-winner},
+ 'COUNT' => $self->{-dead}->{$victim}->{'C'},
+ 'AVAILABLE' => 'Y',
+ 'COMMAND_ID' => $self->{-id},
+ };
+ $self->{-mob} = $mob;
+ my %mobcopy = (%$mob);
+ $self->{-db}->insert_hash('MOBILE',\%mobcopy);
+ $self->unify_mobiles($mob,$self->{-location},$self->{-winner});
+ Util::log("$total_conquered_arks conquered arks for $self->{-winner}.",1);
+ $self->{-dead}->{$victim}->{'A'} -= $total_conquered_arks;
+ }
+ }
+
+ $self->change_priest_on_temple($self->{-location});
+}
+
+sub move_with{
+ my ($self,$id,$target,$count) = @_;
+
+ # read mobile
+ my $mobile = $self->{-db}->single_hash_select('MOBILE',"ID=$id");
+
+ # split mobile
+ $self->conditional_split_mobile($mobile,$count,
+ {'MOVE_WITH' => $target},1);
+ Util::log("$count mobiles from id $id now moves with mobile $target",1);
+
+ # reread mobile, because split destroys it
+ $mobile = $self->{-db}->single_hash_select('MOBILE',"ID=$id");
+
+ # all mobiles which already move with this now move with the target
+ if($target != 0){
+ my $mob = $self->{-context}->mobiles_available($mobile->{'LOCATION'});
+ my $mobcount = $#{@$mob}+1;
+ for my $i (0..$mobcount-1){
+ my ($oid,$otype,$oown,$oado,$ocnt,$ostat,$omove) = @{$mob->[$i]};
+ next if($omove != $id);
+ $self->{-db}->update_hash('MOBILE',"ID=$oid",
+ {'MOVE_WITH' => $target});
+ Util::log("therefor all mobiles from id $oid now moves with mobile $target",1);
+ }
+ }
+
+ # unify
+ $self->unify_mobiles($mobile,$mobile->{'LOCATION'});
+}
+
+# this function is called, if an earthling leave an field and let it possible empty
+sub empty_field{
+ my ($self,$loc,$player) = @_;
+ $player = $self->{-player} unless defined $player;
+ my $db = $self->{-db};
+ my $aym = $self->{-context};
+ my $oim = $aym->own_in_mobile($loc,$player,1);
+
+ my ($home,$ter,$occ,$temple) =
+ $aym->read_field('HOME,TERRAIN,OCCUPANT,TEMPLE',$loc);
+ $home=0 if $ter eq 'MOUNTAIN';
+
+ unless(@$oim){
+ my $keep_owner = 0;
+ $keep_owner = 1 if $home==$occ and $ter eq 'CITY' and $::conf->{-HOMECITY_KEEP_OWNER};
+ $keep_owner = 1 if exists $::conf->{-KEEP_OWNER}->{$ter};
+ $keep_owner = 1 if $::conf->{-TEMPLE_KEEP_OWNER} and $temple eq 'Y';
+
+ if($keep_owner){
+ Util::log("leaving occupant $occ in field $loc",1);
+ }else{
+ Util::log("reset old occupant $home in field $loc.",1);
+ # delete all PRODUCE and PRAY-Commands if any
+ $self->{-db}->delete_from('COMMAND',
+ "(COMMAND=PRODUCE OR COMMAND=PRAY) AND ".
+ "LOCATION=$loc AND GAME=$self->{-game}");
+ # delete all PRODUCE-EVENTS
+ $self->{-db}->delete_from('EVENT',
+ "(TAG=EVENT_PRODUCE_WARRIOR OR TAG=EVENT_PRODUCE_PRIEST)".
+ " AND LOCATION=$loc AND GAME=$self->{-game}");
+ $db->update_hash('MAP',
+ "LOCATION=$loc AND GAME=$self->{-game}",
+ {'OCCUPANT' => $home});
+ }
+ }
+ $self->change_priest_on_temple($loc);
+}
+
+# this check, if there is still a priest on a temple
+# and if there is a new priest on temple
+sub change_priest_on_temple{
+ my ($self,$loc) = @_;
+ my $aym = $self->{-context};
+
+ my ($home,$temple,$occ) = $aym->read_field('HOME,TEMPLE,OCCUPANT',$loc);
+ return unless $temple eq 'Y';
+
+ my $produce = $self->{-db}->count('COMMAND',
+ "LOCATION=$loc AND GAME=$self->{-game} AND ".
+ "COMMAND=PRODUCE");
+
+ my $priests = $self->{-db}->count('MOBILE',
+ "LOCATION=$loc AND GAME=$self->{-game} AND ".
+ "TYPE=PRIEST AND ADORING=$home AND ".
+ "AVAILABLE=Y");
+
+ Util::log("priests: $priests, produce: $produce",1);
+
+ if($priests and not $produce){
+ $aym->insert_command('PRODUCE', "ROLE=$occ", $loc);
+ }
+
+ if(not $priests and $produce){
+ Util::log("delete produce-command and event",1);
+ # delete all PRODUCE -Commands if any
+ $self->{-db}->delete_from('COMMAND',
+ "COMMAND=PRODUCE AND ".
+ "LOCATION=$loc AND GAME=$self->{-game}");
+ # delete all PRODUCE-EVENTS
+ $self->{-db}->delete_from('EVENT',
+ "(TAG=EVENT_PRODUCE_PRIEST)".
+ " AND LOCATION=$loc AND GAME=$self->{-game}");
+ }
+}
+
+# do we fight? do we conquer? do we join?
+# TODO: turn_around if no ark and terrain==water
+# TODO: could happen if location is flooded during movement.
+sub enter_field{
+ my ($self,$loc,$ignore_friend) = @_;
+ $ignore_friend = 0 unless defined $ignore_friend;
+
+ Util::log("enter_field($loc,$ignore_friend)",2);
+
+ # print "LOC: $loc\n";
+ my ($occ,$att,$temple,$home,$terrain) =
+ $self->{-context}->read_field('OCCUPANT,ATTACKER,TEMPLE,HOME,TERRAIN',$loc);
+ $self->{-occupant} = $occ;
+
+ my $relation = $self->{-context}->get_relation($occ);
+
+ $relation = 'FOE' if $ignore_friend;
+
+ # if there is allready an ongoing fight
+ if($att){
+ # do nothing if we are allready involved
+ if($self->{-player} == $occ or $self->{-player} == $att){
+
+ Util::log("join the ongoing fight in $loc",1);
+ delete $self->{-multimove};
+ return;
+ }else{
+ # turn around otherwise
+ Util::log("in $loc: There is allready a fight between $occ and $att ".
+ "... turn around.",1);
+ $self->turn_around($loc);
+ delete $self->{-multimove};
+ return;
+ }
+ }
+
+ if($relation eq 'FRIEND' or $relation eq 'ALLIED'){
+ # a friend has allready occupied this place, just turn around.
+ Util::log("in $loc: $occ is a friend of $self->{-player} ... turn around.",1);
+ $self->turn_around($loc);
+ delete $self->{-multimove};
+ return;
+ }
+
+ if($self->is_new_earthling_fight($loc,$relation,$terrain)){
+ Util::log("new fight between earthlings in $loc:".
+ " attacker $self->{-player}, defender $occ",1);
+
+ # we are the attacker
+ $self->do_earthling_fight($loc);
+ delete $self->{-multimove};
+ return;
+ }
+
+ if($occ == $self->{-player}){
+ # was already our field
+ Util::log("$loc is allready field of $occ.",2);
+ $self->unify_mobiles($self->{-mob},$loc) unless defined $self->{-multimove};
+ }else{
+ # we are the new occupant
+ $self->conquer($loc,$self->{-player});
+ }
+
+ $self->change_priest_on_temple($loc);
+}
+
+# peoples without arks drown
+sub drowning{
+ my ($self,$loc) = @_;
+
+ # dont drown on islands or land
+ my ($terrain) = $self->{-context}->read_field('TERRAIN',$loc);
+ return unless $terrain eq 'WATER';
+
+ # is there still an active ark?
+ my $arks = $self->{-context}->read_mobile('TYPE','ARK',$loc,1);
+ # print Dumper $arks;
+ my @aa = @$arks;
+ return if $#aa >= 0;
+
+ # get active mobiles
+ my $mobs = $self->{-context}->read_mobile('ID,TYPE,COUNT,OWNER','',$loc,1);
+
+ my ($id,$type,$count,$owner);
+ for my $mob (@$mobs){
+ ($id,$type,$count,$owner) = @$mob;
+
+ next if $type eq 'ARK' or $type eq 'PROPHET';
+
+ # drown mobile
+ $self->{-db}->delete_from('MOBILE',"ID=$id");
+ Util::log("No ark: $count $type from $owner drowned in $loc.",1);
+
+ $self->{-context}
+ ->send_message_to($owner,
+ {'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_MOBILE_DRAWN',
+ 'ARG1' => $count,
+ 'ARG2' => $self->{-context}->mobile_string($type,$count),
+ 'ARG3' => $self->{-context}->charname($owner),
+ 'ARG4' => $loc});
+ }
+ $self->empty_field($loc,$owner) if $owner;
+}
+
+sub conquer{
+ my ($self,$loc,$player) = @_;
+
+ Util::log("$player conquers $loc.",1);
+ $self->{-db}->update_hash('MAP',"LOCATION=$loc AND GAME=$self->{-game}",
+ {'OCCUPANT' => $player});
+
+ # conquer existing arks
+ $self->{-db}->update_hash('MOBILE',"LOCATION=$loc AND GAME=$self->{-game} AND TYPE=ARK",
+ {'OWNER' => $player});
+
+ # insert new PRODUCE-command and delete existent one and PRODUCE-events
+ my ($terrain,$temple,$home) = $self->{-context}->read_field('TERRAIN,TEMPLE,HOME',$loc);
+
+ if ((not $home and $terrain eq 'CITY')){
+ $self->{-db}->delete_from('COMMAND', "COMMAND=PRODUCE AND LOCATION=$loc".
+ " AND GAME=$self->{-game}");
+ $self->{-db}->delete_from('EVENT',"TAG=EVENT_PRODUCE_WARRIOR AND LOCATION=$loc ".
+ "AND GAME=$self->{-game}");
+ $self->{-context}->insert_command('PRODUCE', "ROLE=$player", $loc);
+ }
+
+ #if ($temple eq 'Y'){
+ # PRAY at temples
+ # $self->{-db}->delete_from('COMMAND', "COMMAND=PRAY AND LOCATION=$loc".
+ #" AND GAME=$self->{-game}");
+ #
+ # }
+}
+
+sub enter_field_avatar{
+ my ($self,$loc,$mob) = @_;
+
+ Util::log("enter_field_avatar() in $loc",1);
+ # print Dumper $mob;
+
+ # if we are in Aymargeddon, do nothing special
+ my ($terrain) = $self->{-context}->read_field('TERRAIN',$loc);
+ if($terrain eq 'AYMARGEDDON'){
+ Util::log("enter_field_avatar(AYMARGEDDON): do nothing",1);
+ delete $self->{-multimove};
+ return;
+ }
+
+ # mob can be ID or hash
+ $mob = $self->{-db}->read_single_mobile($mob) unless ref($mob);
+ # print Dumper $mob;
+ # get all avatars allready here from me and other owners
+ my $avatars = $self->{-context}->read_mobile_condition('ID,OWNER,STATUS',
+ "LOCATION=$loc ".
+ "AND TYPE=AVATAR ".
+ "AND AVAILABLE=Y");
+ # print Dumper $avatars;
+
+ # restructure data
+ my $own_avatars_here = 0;
+ my $own_avatar_status = 'IGNORE';
+ my %other_avatar_owner = ();
+ my %other_avatar_status = ();
+ for my $a (@$avatars){
+ my ($id,$own,$stat) = @$a;
+ next if($id == $mob->{'ID'});
+ # print "own: $own\n";
+ if($own == $mob->{'OWNER'}){
+ $own_avatars_here = $id;
+ $own_avatar_status = $stat;
+ }elsif(!defined $other_avatar_owner{$own}){
+ $other_avatar_owner{$own} = 1;
+ $other_avatar_status{$own} = $stat;
+ Util::log("found other avatar-owner $own in $loc",1);
+ }else{
+ Util::log("other avatar-owner $own allready found in $loc",1);
+ }
+ }
+
+ # if we are there allready with other avatars:
+ if($own_avatars_here){
+ # set STATUS of newcomer to the STATUS in the field
+ if ($own_avatar_status ne $mob->{'STATUS'}){
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$mob->{'ID'}",
+ {'STATUS' => $own_avatar_status});
+ }
+ Util::log("enter_field_avatar():Avatars (ID:$mob->{'ID'}) ".
+ "have to join other avatars with status $own_avatar_status in $loc.",1);
+ $self->unify_mobiles($mob);
+ }else{
+ # for each other avatar-owner
+ for my $other (keys %other_avatar_owner){
+ my $oas = $other_avatar_status{$other};
+ # read alliance to each other owner (and vice versa)
+ my $allianceA = $self->{-context}
+ ->simplyfied_single_relation($other,$mob->{'OWNER'});
+ my $allianceB = $self->{-context}
+ ->simplyfied_single_relation($mob->{'OWNER'},$other);
+ # insert FIGHT-command, if necessary
+ if($self->is_avatar_fight($allianceA,$allianceB,$mob->{'STATUS'},$oas)){
+ $self->{-context}->insert_command('FIGHT_GOD',
+ "A=$other, B=$mob->{'OWNER'}",
+ $loc);
+ Util::log("enter_field_avatar():Avatars from $mob->{'OWNER'} ".
+ "have to fight with $other in $loc.",1);
+ delete $self->{-multimove};
+ }
+ }
+ }
+}
+
+sub is_avatar_fight{
+ my ($self,$allA,$allB,$statA,$statB) = @_;
+
+ Util::log("is_avatar_fight(): ".
+ "allA: $allA, allB: $allB, statA: $statA, statB: $statB",1);
+
+ return 0 unless $statA eq 'BLOCK' or $statB eq 'BLOCK';
+ my $status = 'NEUTRAL';
+ if(($allA eq 'FOE') or ($allB eq 'FOE')){
+ $status = 'FOE';
+ }elsif(($allA eq 'FRIEND') or ($allB eq 'FRIEND')){
+ $status = 'FRIEND';
+ }
+
+ return 1 if ($status eq 'FOE');
+ return 1 if ($status eq 'NEUTRAL') and $statA eq 'BLOCK' and $statB eq 'BLOCK';
+ return 0;
+}
+
+# unify identical mobiles
+# $mob still exists after function. all other of same
+# TYPE, MOVE_WITH, ADORING will be deleted.
+sub unify_mobiles{
+ my ($self,$mob,$location,$owner) = @_;
+
+ # mob can be ID or hash
+ $mob = $self->{-db}->read_single_mobile($mob) unless ref($mob);
+
+ $location = $mob->{'LOCATION'} unless defined $location;
+ $owner = $self->{-player} unless defined $owner;
+
+ Util::log("unify_mobiles() in $location for mobile $mob->{'ID'} of $owner",1);
+
+ return if $self->{-db}->count('COMMAND',
+ "MOBILE=$mob->{'ID'} AND ID != $self->{-dbhash}->{'ID'}");
+
+ my $type = $mob->{'TYPE'};
+
+ my $mobs = $self->{-context}->read_mobile('ID,COUNT,ADORING,OWNER,MOVE_WITH',
+ $type,
+ # $mob->{'LOCATION'},
+ $location,
+ 1
+ );
+
+ my $count = $mob->{'COUNT'};
+ for my $m (@$mobs){
+ my ($oid,$ocount,$oado,$oown,$omove) = @$m;
+
+ next if $oown ne $owner; # and $type ne 'ARK';
+ next if $oid eq $mob->{'ID'};
+ if(Util::is_in($type,'PRIEST','PROPHET','HERO')){
+ next if $oado ne $mob->{'ADORING'};
+ }
+
+ next if(defined $mob->{'MOVE_WITH'} and $mob->{'MOVE_WITH'} ne $omove);
+
+ next if $self->{-db}->count('COMMAND',"MOBILE=$oid");
+
+ $count += $ocount;
+
+ $self->{-db}->delete_from('MOBILE',"ID=$oid");
+
+ # set new MOVE_WITH, if deleted unit has some companions
+ $self->{-db}->update_hash('MOBILE',
+ "MOVE_WITH=$oid",
+ {'MOVE_WITH' => $mob->{'ID'}});
+
+ }
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$mob->{'ID'}",
+ {'COUNT' => $count}) if $count != $mob->{'COUNT'};
+
+ # rekursion for every companion of $mob
+ my $companions = $self->{-context}->read_mobile_condition('ID,OWNER',
+ "LOCATION=$location ".
+ "AND MOVE_WITH=$mob->{'ID'}");
+ for my $m (@$companions){
+ my ($mid,$mown) = @$m;
+ # does it still exist?
+ my $comp = $self->{-db}->read_single_mobile($mid);
+ next unless defined $comp;
+ $self->unify_mobiles($comp,$location,$mown);
+ }
+}
+
+# the move-command will be set up again in the oposite direction
+sub turn_around{
+ my ($self,$loc) = @_;
+
+ # first we have to check, if we are here because of an MOVE-COMMAND
+ # or out of some other reason
+ if($self->{-dbhash}->{'COMMAND'} eq 'MOVE'){
+ my $mob = $self->{-mob};
+ my $dir = $self->{-args}->{'DIR'};
+ my $rev = {'S' => 'N',
+ 'N' => 'S',
+ 'SW' => 'NE',
+ 'NE' => 'SW',
+ 'SE' => 'NW',
+ 'NW' => 'SE',};
+ $dir = $rev->{uc($dir)};
+ Util::log("we ($mob->{'ID'} in $loc) are friends ".
+ "and come from $dir. we turn around...",1);
+ $self->{-context}->insert_command('MOVE',
+ "DIR=$dir, MOBILE=$mob->{'ID'}, ".
+ "COUNT=$mob->{'COUNT'}, AUTO=1",$loc);
+ }else{
+ #
+ }
+}
+
+# do we start a fight here?
+sub is_new_earthling_fight{
+ my ($self,$location,$relation,$terrain) = @_;
+ my $mob = $self->{-mob};
+ my $attacker = $self->{-player};
+ my $occupant = $self->{-occupant};
+
+ # no fight on some neutral territories
+ return 0 unless $occupant or exists $::conf->{-FIGHTS_WITHOUT_OWNER}->{$terrain};
+
+ # no new fight, if allready one started
+ return 0 if $self->{-context}->earthling_fight($location);
+
+ return 0 if $attacker == $occupant or
+ $relation eq 'FRIEND' or
+ $relation eq 'ALLIED';
+
+ my $qloc = $self->{-db}->quote($location);
+ $self->{-db}->update_hash('MAP',"GAME=$self->{-game} AND LOCATION=$qloc",
+ {'ATTACKER' => $attacker});
+
+}
+
+# start a fight!
+sub do_earthling_fight{
+ my ($self,$loc) = @_;
+
+ # write the fight command
+
+ $self->{-context}->insert_command('FIGHT_EARTHLING',
+ "ATTACKER=$self->{-player}, ".
+ "DEFENDER=$self->{-occupant}",
+ $loc);
+}
+
+# enough mana available?
+sub test_mana{
+ my ($self,$action,$factor,$god) = @_;
+ $factor = 1 unless defined $factor;
+ $god = $self->{-player} unless defined $god;
+
+ my $mana = $self->{-context}->get_mana($god);
+ my $mana_needed = $::conf->{-MANA}->{"-$action"} * $factor;
+
+ Util::log("$god needs $mana_needed mana from his $mana mana to do $action",1);
+
+ # dirty workaround: we fake our identity.
+ my $player = $self->{-player};
+ $self->{-player} = $god;
+ unless($self->test(sub{ $mana >= $mana_needed },
+ 'MSG_NOT_ENOUGH_MANA',
+ $action,
+ $self->{-location} ? $self->{-location} : 'GLOBAL')){
+ $self->{-player} = $player;
+ return 0;
+ }
+ $self->{-player} = $player;
+
+ $self->{-mana} = $mana - $mana_needed;
+ $self->{-mana_paid} = $mana_needed;
+ return 1;
+}
+
+sub use_mana{
+ my ($self,$god) = @_;
+ $god = $self->{-player} unless defined $god;
+ $self->{-db}->update_hash('GOD',"PLAYER=$god AND GAME=$self->{-game}",
+ {'MANA' => $self->{-mana}});
+ Util::log("$god pays $self->{-mana_paid} mana ".
+ "and has still $self->{-mana} left.",1);
+ #TODO?: Message
+}
+
+# this returns the used mana and did not test before
+sub instant_use_mana{
+ my ($self,$mana,$god) = @_;
+ $god = $self->{-player} unless defined $god;
+
+ my $mana_available = $self->{-context}->get_mana($god);
+
+ if ($mana_available < $mana)
+ {
+ # not enough mana
+ $mana = $mana_available;
+ }
+ my $newmana = $mana_available - $mana;
+
+ $self->{-db}->update_hash(
+ 'GOD',
+ "PLAYER=$god AND GAME=$self->{-game}",
+ {'MANA' => $newmana}
+ );
+ Util::log("$god pays $mana mana ".
+ "and has still $newmana left.",1);
+ return $mana;
+}
+
+#
+# End of AymCommand
+#
+####################################################
+
+##########################################################
+#
+# Use this template to generate new commands
+#
+
+package AymCommandTemplate;
+@AymCommandTemplate::ISA = qw(AymCommand);
+
+# ... arguments in $self->{-args}
+# ... player in $self->{-player}
+# ... game in $self->{-game}
+# ... context object in $self->{-context}
+# ... database object in $self->{-db}
+# ... basic duration from Config in $self->{-duration}
+# ... command from database in $self->{-dbhash}
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+ my @required_arguments = ();
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ # ... here your code
+
+ return 1;
+}
+
+# this is called from Scheduler, when he see the command the
+# first time, some commands execute here immidiatly.
+# AymCommand
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # ... here your code
+
+ return 1;
+}
+
+# this is called from scheduler when the command will be executed.
+# AymCommand
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # ... here your code
+
+ return 1;
+}
+
+#
+# End of template
+#
+####################################################
+
+#
+# CH_STATUS: Change the player alliance status
+#
+
+package CH_STATUS;
+@CH_STATUS::ISA = qw(AymCommand);
+
+sub is_valid{
+ my ($self) = @_;
+
+ my @required_arguments = ('OTHER','STATUS');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ # exist OTHER still in game?
+ if($self->{-args}->{'OTHER'} != -1){
+ my $role = $self->{-context}->read_role($self->{-args}->{'OTHER'},'PLAYER');
+ return 0 unless $self->test(sub{$role},
+ 'MSG_NO_SUCH_ROLE');
+ }
+
+ # is STATUS valid?
+ my $status = $self->{-args}->{'STATUS'};
+ return 0 unless $self->test(sub{Util::is_in($status,
+ 'FRIEND',
+ 'FOE',
+ 'NEUTRAL',
+ 'BETRAY',
+ 'ALLIED')},
+ 'MSG_STATUS_INVALID',
+ $status);
+ return 1;
+}
+
+# CH_STATUS
+sub first_phase{
+ my $self = shift;
+ return 0 unless $self->is_valid();
+
+ my $tag = 'MSG_CH_STATUS';
+ my $other = $self->{-args}->{'OTHER'};
+ my $status = $self->{-args}->{'STATUS'};
+ # ($status,$tag) = $self->{-db}->quote_all($status,$tag);
+ $self->{-db}->insert_or_update_hash(
+ 'ALLIANCE',
+ "PLAYER=$self->{-player} ".
+ "AND OTHER=$other ".
+ "AND GAME=$self->{-game}",
+ {'GAME' => $self->{-game},
+ 'PLAYER' => $self->{-player},
+ 'OTHER' => $other,
+ 'STATUS' => $status}
+ );
+
+ #$self->{-context}->send_message_to_me({'MFROM' => 0,
+ # 'MSG_TAG' => $tag,
+ # 'ARG1' => $self->{-context}->charname($other),
+ # 'ARG2' => $status,
+ # });
+
+ $self->setDuration(0);
+ return 0;
+};
+
+sub second_phase{
+ my $self = shift;
+ Util::log("Warning: We should not reach phase 2 with command CH_STATUS",0);
+ return 0;
+};
+
+#
+# END of CH_STATUS
+#
+################################################################
+
+################################################################
+#
+# MOVE: Move mobiles
+#
+
+package MOVE;
+use Data::Dumper;
+# use FROGS::HexTorus;
+@MOVE::ISA = qw(AymCommand);
+
+sub is_valid {
+ my $self = shift;
+
+ my $db = $self->{-db};
+ my $args = $self->{-args};
+ my $aym = $self->{-context};
+ my $phase = $self->{-phase};
+
+ my @required_arguments = ('MOBILE','COUNT','DIR');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ my $mob_id = $args->{'MOBILE'};
+ my $count = $args->{'COUNT'};
+
+ return 0 unless $count =~ /^\s*\d+\s*$/;
+
+ return 0 unless $self->validate_mobile($self->{-args}->{'MOBILE'});
+ my $mob = $self->{-mob};
+
+ my ($owner,$loc_string,$type) = ($mob->{'OWNER'},
+ $mob->{'LOCATION'},
+ $mob->{'TYPE'},
+ );
+ # print "LOCATION: $loc_string\n";
+ $self->{-loc_string} = $loc_string;
+
+ # enough mobiles avaiable?
+ if ($phase == 1) {
+ return 0 unless $self->test(sub {$count <= $mob->{'COUNT'} and
+ $mob->{'AVAILABLE'} eq 'Y'},
+ 'MSG_NOT_ENOUGH_MOBILES',
+ 'MOVE',
+ $count,
+ $loc_string);
+ }
+ # get target field
+
+ my ($size) = $db->read_game($self->{-game},'SIZE');
+ $self->{-size} = $size;
+ my $map = HexTorus->new($size);
+ $self->{-map} = $map;
+
+ my $loc = Location->from_string($loc_string);
+ $self->{-loc} = $loc;
+
+ # MULTIMOVE: extract first direction and rest of string
+ my $direction = $args->{'DIR'};
+ $direction =~ s/^\s*(\S*)\s*$/$1/; # removing leading/trailing whitespace
+ $direction =~ /^(\S*)\s+(.*)$/; # split up first direction
+ my ($first_direction,$other_directions) = ($1,$2);
+ if($other_directions){
+ $self->{-multimove} = $other_directions;
+ $direction = $first_direction;
+ Util::log("MULTIMOVE: now $first_direction, later $other_directions",1);
+ }
+
+ my $target = $map->get_neighbour($loc,$direction);
+
+ # target correct?
+ return 0 unless $self->test(sub{$target},
+ 'MSG_MOVE_NO_TARGET',
+ $loc_string,
+ $args->{'DIR'});
+ $self->{-target} = $target;
+ my $target_string = $target->to_string();
+
+ # get terrain of loc and target
+ my ($terrain,$attacker,$god_attacker,$plague) =
+ $aym->read_field('TERRAIN,ATTACKER,GOD_ATTACKER,PLAGUE',$loc_string);
+ $plague = '' unless defined $plague;
+ my ($target_terrain,$target_occupant) =
+ $aym->read_field('TERRAIN,OCCUPANT',$target_string);
+ $self->{-target_occupant} = $target_occupant;
+
+ # you can only MOVE_WITH on water, except you are an ARK
+ return 0 unless $self->test(sub{Util::is_in($target_terrain,
+ 'PLAIN',
+ 'CITY',
+ 'MOUNTAIN',
+ 'AYMARGEDDON',
+ 'POLE') or $type eq 'ARK'},
+ 'MSG_CANT_SWIM',
+ 'CMD_MOVE',
+ $loc_string,
+ "MOBILE_$type\_PL");
+ # $self->{-context}->mobile_string($type,2));
+
+
+
+ # role specific tests
+ my $role = $self->{-role};
+
+ # return 0 unless $self->validate_role('GOD','EARTHLING');
+ #if ($mob->{'TYPE'} eq 'ARK') {
+ # Util::log("Impossible Situation: ARK has got a MOVE-Command",1);
+ if ($role eq 'GOD') {
+ # gods can only move avatars
+ return 0 unless $self->test(sub{$type eq 'AVATAR'},
+ 'MSG_GOD_CANT_MOVE_TYPE',
+ $self->{-context}->mobile_string($type,2));
+
+ # dont move if $loc is Aymargeddon
+ return 0 unless $self->test(sub{$terrain ne 'AYMARGEDDON'},
+ 'MSG_CANT_LEAVE_AYMARGEDDON',
+ $loc_string);
+
+
+ # dont move, if ongoing FIGHT_GOD
+ if($phase == 1){
+ return 0 unless $self->test(sub{not $god_attacker},
+ 'MSG_CANT_MOVE_ATTACKED',
+ $mob->{'LOCATION'},
+ $self->{-context}->mobile_string($type,2));
+ }
+
+ # if targetfield water/isle, than dont move directly (only MOVE_WITH)
+ #if ($phase == 1 and (Util::is_in($target_terrain,'WATER','ISLE') # or
+ # Util::is_in($terrain,'WATER','ISLE'))
+ # )) {
+
+ # TODO: Errormessage
+
+ # return 0;
+
+ #}
+
+ # avatars can go on land, if ark available
+ #if ($phase==1 and Util::is_in($terrain,'ISLE','WATER') and
+ # not Util::is_in($target_terrain,'ISLE','WATER')) {
+ # my $arks = $self->{-context}->read_mobile('ID','ARK',$loc_string,1);
+ # my $ark_count = $#{@$arks}+1;
+ # return 0 unless $self->test(sub{$ark_count},
+ # 'MSG_CANT_SWIM',
+ # 'MOVE',
+ # $loc_string,
+ # $self->{-context}->mobile_string($type,2));
+ #}
+ } elsif ($role eq 'EARTHLING' or $owner == -1) {
+ # read companions
+ $self->{-companions} = $self->{-context}->
+ read_mobile_condition('TYPE,COUNT,OWNER,ID',
+ "MOVE_WITH=$self->{-args}->{'MOBILE'}");
+
+ # do not move if field is attacked or tuberculosis
+ if ($phase == 1) {
+ return 0 unless $self->test(sub{not $attacker},
+ 'MSG_CANT_MOVE_ATTACKED',
+ $mob->{'LOCATION'},
+ $self->{-context}->mobile_string($type,2));
+ return 0 unless $self->test(sub{ $plague !~ /TUBERCULOSIS/
+ or exists $self->{-args}->{'AUTO'}},
+ 'MSG_CANT_MOVE_PLAGUE',
+ $mob->{'LOCATION'},
+ $self->{-context}->mobile_string($type,2),
+ 'Tuberculosis');
+ }
+ # eartlings can only move this types
+ return 0 unless $self->test(sub{Util::is_in($type,
+ 'WARRIOR',
+ 'PRIEST',
+ 'HERO',
+ 'PROPHET',
+ 'ARK')},
+ 'MSG_EARTHLING_CANT_MOVE_TYPE',
+ $self->{-context}->mobile_string($type,2));
+
+ # dont move if target field is Pole
+ return 0 unless $self->test(sub{$target_terrain ne 'AYMARGEDDON' and
+ $target_terrain ne 'POLE'},
+ 'MSG_CANT_MOVE_TO_POLE',
+ 'MOVE', $target_string);
+
+ # dont move ark from land to land
+ if($type eq 'ARK'){
+ return 0 unless $self->test(sub{Util::is_in($terrain,'WATER','ISLE') or
+ Util::is_in($target_terrain,'WATER','ISLE')},
+ 'MSG_CANT_MOVE_ARK',
+ 'MOVE', $target_string);
+ $self->{-active_ark} = $self->{-args}->{'MOBILE'};
+ }
+
+ # automatic ark-moving
+ # if ($type ne 'ARK' and $phase == 1 and
+ # (Util::is_in($target_terrain,'WATER','ISLE'))){
+ # # or Util::is_in($terrain,'WATER','ISLE'))) {
+ # my $arks = $aym->read_mobile('ID,COUNT','ARK',$loc_string,1);
+ # # print Dumper $arks;
+ # my ($ark,$active);
+ # if (defined $arks->[0]) {
+ # ($ark,$active) = (@{$arks->[0]});
+ # } else {
+ # ($ark,$active) = (0,0);
+ # }
+ # return 0 unless $self->test(sub {$active or $type eq 'PROPHET'},
+ # 'MSG_CANT_SWIM',
+ # 'MOVE',
+ # $loc_string,
+ # $self->{-context}->mobile_string($type,2));
+ # $self->{-active_ark} = $ark;
+ # Util::log("We take ark $ark with us.",1);
+ # }
+
+ } else {
+ Util::log("impossible situation. I could not be $role",0);
+ return 0;
+ }
+
+ # dont move without mana
+ if ($phase == 1) {
+ if ($role eq 'GOD') {
+ unless($self->test_mana('MOVE_AVATAR',$count)){
+ $db->update_hash('MOBILE',
+ "ID=$mob_id",
+ {
+ 'AVAILABLE' => 'Y'});
+ return 0;
+ }
+ } else {
+ # for all avatar-companions: pay or stay (if not on ark)!
+ if ($type ne 'ARK'){
+ my $deleted = 0;
+ for my $comp (@{$self->{-companions}}) {
+ my ($ctype,$ccount,$cown,$cid) = @$comp;
+ next unless $ctype eq 'AVATAR';
+ unless($self->test_mana('MOVE_AVATAR',$ccount,$cown) and not $god_attacker){
+ $db->update_hash('MOBILE',
+ "ID=$cid",
+ {'AVAILABLE' => 'Y',
+ 'MOVE_WITH' => 0});
+ $self->unify_mobiles($cid,0,$cown);
+ $deleted = 1;
+ }
+ }
+ # re-read companions
+ $self->{-companions} = $self->{-context}->
+ read_mobile_condition('TYPE,COUNT,OWNER,ID',
+ "MOVE_WITH=$self->{-args}->{'MOBILE'}")
+ if $deleted;
+
+ }
+ }
+ }
+
+ return 1;
+}
+
+# MOVE
+sub first_phase{
+ my ($self) = @_;
+
+ return 0 unless $self->is_valid();
+
+ my $db = $self->{-db};
+ my $type = $self->{-mob}->{'TYPE'};
+ my $mob = $self->{-mob};
+ my $aym = $self->{-context};
+
+ # split it, if neccessary
+ # the moving unit get the old ID!
+
+ my $count = $self->{-args}->{'COUNT'};
+ #print "conditional split with $count count and mob=\n";
+ #print Dumper $mob;
+ #print Dumper $self;
+ return 0 unless
+ $self->conditional_split_mobile($mob,$count,
+ {'COMMAND_ID' => $self->{-dbhash}->{'ID'},
+ 'MOVE_WITH' => 0},0);
+
+ # if ark needed, move it together with us
+ #if($type ne 'ARK' and $self->{-active_ark}){
+
+ # $self->move_with($self->{-active_ark},$self->{-args}->{'MOBILE'},1);
+
+ # set owner of ark
+ # $self->{-db}->update_hash('MOBILE',
+ # "ID=$self->{-active_ark}",
+ # {'OWNER' => $self->{-player}});
+ #}
+
+ # collect mobiles with MOVE_WITH in same location
+ my $companions = $self->{-companions};
+
+ # calculate duration
+ my $d = $::conf->{-DURATION};
+ my $dur = $d->{"-MOVE_$type"};
+
+ # if moved with ark use -MOVE_ARK else use slowest
+ if($self->{-active_ark}){
+ $dur = $d->{'-MOVE_ARK'};
+ }else{
+ for my $m (@$companions){
+ my ($mtype) = @$m;
+ $dur = $d->{"-MOVE_$mtype"} if $d->{"-MOVE_$mtype"} > $dur;
+ }
+ }
+ $self->setDuration($dur);
+
+ # set all companions inactive
+ $self->{-db}->update_hash('MOBILE',
+ "LOCATION=$mob->{'LOCATION'} ".
+ "AND MOVE_WITH=$self->{-args}->{'MOBILE'}",
+ {'AVAILABLE' => 'N'});
+
+ # remove OCCUPANT in MAP, if we are an earthling
+ # and there are no more own active (if it was our field)
+ # mobiles left and if it is no homecity
+ if($aym->is_earthling()){
+ $self->empty_field($mob->{'LOCATION'});
+ # avatar-companions: pay now
+ if($type ne 'ARK'){
+ for my $comp (@$companions){
+ my ($ctype,$ccount,$cown,$cid) = @$comp;
+ next unless $ctype eq 'AVATAR';
+ $self->use_mana($cown);
+ }
+ }
+ }elsif($aym->is_god()){
+ $self->use_mana();
+ }
+
+ # events
+ if($type eq 'ARK' or $self->{-active_ark}){
+ $self->event($self->{-target}->to_string(),
+ 'EVENT_ARK_APPROACHING',
+ $mob->{'LOCATION'},
+ $mob->{'COUNT'});
+ }else{ #elsif($type ne 'ARK'){
+ my $player = $self->{-player};
+ my $count = $self->{-args}->{'COUNT'};
+ my $typetag = $count > 1 ? "MOBILE_$type".'_PL' : "MOBILE_$type";
+ $self->event($self->{-target}->to_string(),
+ 'EVENT_MOBILE_APPROACHING',
+ $mob->{'LOCATION'},
+ $count,
+ # $self->{-context}->mobile_string($type,$count));
+ $typetag);
+
+ # TODO Bug: if avatar moves with hero, the wrong player is in the event-message.
+
+ for my $m2 (@$companions){
+ my ($mtype,$c,$mo) = @$m2;
+ $self->{-player} = $mo;
+ $typetag = $c > 1 ? "MOBILE_$mtype".'_PL' : "MOBILE_$mtype";
+ $self->event($self->{-target}->to_string(),
+ 'EVENT_MOBILE_APPROACHING',
+ $mob->{'LOCATION'},
+ $c,
+ # $self->{-context}->mobile_string($mtype,$c))
+ $typetag);
+ }
+ $self->{-player} = $player;
+ }
+
+ return $dur;
+}
+
+# MOVE
+sub second_phase{
+ my ($self) = @_;
+
+ return 0 unless $self->is_valid();
+
+ my $db = $self->{-db};
+ my $mob = $self->{-mob};
+ my $count = $self->{-args}->{'COUNT'};
+ my $target_location = $self->{-target}->to_string();
+ my $old_location = $mob->{'LOCATION'};
+
+ # move mobile and all moving with it.
+ $db->update_hash('MOBILE',"ID=$mob->{'ID'} OR MOVE_WITH=$mob->{'ID'}",
+ {'LOCATION' => $target_location,
+ 'AVAILABLE' => 'Y',
+ });
+
+ # TODO: distribute plagues
+
+ # Bug?
+ # $self->{-db}->update_hash('MOBILE',
+ # "TYPE=ARK AND MOVE_WITH=$mob->{'ID'}",
+ # {'MOVE_WITH' => 0});
+
+ # should we do a godfight?
+ my $companions = $self->{-companions};
+ if($mob->{'TYPE'} eq 'AVATAR'){
+ $self->enter_field_avatar($target_location,$mob);
+ }else{
+ for my $m (@$companions){
+ my ($mtype,$mc,$mo,$mid) = @$m;
+ next unless $mtype eq 'AVATAR';
+ $self->enter_field_avatar($target_location,$mid);
+ }
+ }
+
+ $self->enter_field($target_location) if $self->{-role} eq 'EARTHLING';
+ # $self->enter_field_avatar($target_location,$mob) if $self->{-role} eq 'GOD';
+ $self->drowning($old_location);
+
+ # MULTIMOVE
+ if(defined $self->{-multimove}){
+ $self->{-context}->insert_command('MOVE',
+ "ROLE=$self->{-player}, ".
+ "DIR=$self->{-multimove}, ".
+ "MOBILE=$mob->{'ID'}, ".
+ "COUNT=$mob->{'COUNT'}",
+ $mob->{'LOCATION'});
+ }else{
+ $self->unify_mobiles($mob,$target_location);
+ }
+
+# TODO: maybe we should give a message only to the player of the unit
+# ... but its difficult, because of MOVE_WITH
+
+# $self->{-context}
+# ->send_message_to_field
+# ($target_location,
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_MOBILE_ARRIVES',
+# 'ARG1' => $count,
+# 'ARG2' => $self->{-context}->mobile_string($self->{-mob}->{'TYPE'},
+# $self->{-mob}->{'COUNT'}),
+# 'ARG3' => $self->{-context}->charname($self->{-player}),
+# 'ARG4' => $target_location});
+
+# for my $m (@$companions){
+# my ($mtype,$mc,$mo,$mid) = @$m;
+# $self->{-context}
+# ->send_message_to_field
+# ($target_location,
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_MOBILE_ARRIVES',
+# 'ARG1' => $mc,
+# 'ARG2' => $self->{-context}->mobile_string($mtype,$mc),
+# 'ARG3' => $self->{-context}->charname($mo),
+# 'ARG4' => $target_location});
+# }
+
+
+ return 1;
+}
+
+#
+# End of MOVE
+#
+####################################################
+
+##########################################################
+#
+# BLESS_PRIEST
+#
+
+package BLESS_PRIEST;
+@BLESS_PRIEST::ISA = qw(AymCommand);
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('MOBILE');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_mobile($self->{-args}->{'MOBILE'});
+
+ return 0 unless $self->validate_role('GOD');
+
+ my $mobtype = $self->{-mob}->{'TYPE'};
+ my $mobloc = $self->{-mob}->{'LOCATION'};
+
+ # don't bless unassigned units
+ return 0 unless $self->test(sub{$self->{-mob}->{'OWNER'} > 0},
+ 'MSG_CANT_BLESS_UNASSIGNED',
+ $mobloc);
+
+ # only bless warriors
+ return 0 unless $self->test(sub{$self->{-mob}->{'TYPE'} eq 'WARRIOR'},
+ 'MSG_WRONG_TYPE',
+ $self->{-context}->mobile_string($mobtype,1),
+ $mobloc);
+
+ return 0 unless $self->test_mana('BLESS_PRIEST');
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# BLESS_PRIEST
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $id = $self->{-mob}->{'ID'};
+ my $newid = $self->conditional_split_mobile($self->{-mob},
+ 1,
+ {'ADORING' => $self->{-player},
+ 'TYPE' => 'PRIEST',
+ 'COMMAND_ID' => $self->{-dbhash}->{'ID'}},
+ 'beforeafter');
+
+ # companions move with the remaining warriors, not with the new priest
+ $self->{-db}->update_hash('MOBILE',
+ "MOVE_WITH = $id",
+ {'MOVE_WITH' => $newid}) if $id != $newid;
+
+ # reread mobile, because split destroys it
+ $self->{-mob} = $self->{-db}->single_hash_select('MOBILE',"ID=$id");
+ $self->unify_mobiles($self->{-mob},
+ $self->{-mob}->{'LOCATION'},
+ $self->{-mob}->{'OWNER'});
+
+ $self->change_priest_on_temple($self->{-mob}->{'LOCATION'});
+
+# $self->{-context}
+# ->send_message_to_field
+# ($self->{-mob}->{'LOCATION'},
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_BLESS_PRIEST',
+# 'ARG1' => $self->{-context}->charname($self->{-player}),
+# 'ARG2' => $self->{-context}->charname($self->{-mob}->{'OWNER'}),
+# 'ARG3' => $self->{-mob}->{'LOCATION'}});
+
+
+ $self->use_mana();
+ $self->setDuration(0);
+
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("BLESS_PRIEST should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of BLESS_PRIEST
+#
+####################################################
+
+##########################################################
+#
+# BUILD_TEMPLE
+#
+
+package BUILD_TEMPLE;
+use Data::Dumper;
+@BUILD_TEMPLE::ISA = qw(AymCommand);
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('MOBILE');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_mobile($self->{-args}->{'MOBILE'});
+
+ my $mobtype = $self->{-mob}->{'TYPE'};
+ my $mobloc = $self->{-mob}->{'LOCATION'};
+ my $god = $self->{-mob}->{'ADORING'};
+
+ # only priests can build temples
+ return 0 unless $self->test(sub{$self->{-mob}->{'TYPE'} eq 'PRIEST'},
+ 'MSG_WRONG_TYPE',
+ $self->{-context}->mobile_string($mobtype,1),
+ $mobloc);
+
+ # is this a valid building place?
+ # my($loc,$terrain,$temple) = $self->{-context}->read_map('TERRAIN,TEMPLE');
+ my ($terrain,$temple) =
+ $self->{-context}->read_field('TERRAIN,TEMPLE',$mobloc);
+ return 0 unless $self->test(sub{$temple ne 'Y'
+ and Util::is_in($terrain,'MOUNTAIN','ISLE')},
+ 'MSG_CANT_BUILD_HERE',
+ $mobloc);
+
+ # is the priest adoring a fitting god?
+ #return 0 unless $self->test(sub{($terrain eq 'MOUNTAIN' and
+ # $self->{-mob}->{'ADORING'} eq $god) or
+ # $terrain eq 'ISLE'},
+ # 'MSG_ADORING_WRONG_GOD',
+ # $mobloc,
+ # $self->{-mob}->{'ADORING'},
+ # $self->{-context}->charname($god));
+
+ # is there allready a BUILD_TEMPLE Command
+ if($self->{-phase} == 1){
+ return 0 unless $self->test(sub{! $self->{-context}->search_event('BUILD_TEMPLE',
+ $mobloc)},
+ 'MSG_CANT_BUILD_HERE',
+ $mobloc);
+ }
+
+ # dont build more than MAX_MOUNTAIN temples on mountains
+ if($terrain eq 'MOUNTAIN'){
+ my $ret = $self->test(sub{$self->{-db}->count('MAP',
+ "GAME=$self->{-game} AND ".
+ "TEMPLE=Y AND ".
+ "HOME=$god AND ".
+ "OCCUPANT=$self->{-player} AND ".
+ "TERRAIN=MOUNTAIN")
+ < $::conf->{-MAX_MOUNTAINS}},
+ 'MSG_CANT_BUILD_HERE',
+ $mobloc);
+ if(not $ret and $self->{-phase} == 2){
+ # we have to set priest active, if we tryed to build in first phase
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$self->{-mob}->{'ID'}",
+ {'AVAILABLE' => 'Y'});
+ }
+ return 0 unless $ret;
+ }
+
+ return 1;
+}
+
+# this is called from Scheduler, if he sees the command the
+# first time, some commands execute here immidiatly.
+# BUILD_TEMPLE
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ $self->conditional_split_mobile($self->{-mob},
+ 1,
+ {'COMMAND_ID' => $self->{-dbhash}->{'ID'},
+ 'MOVE_WITH' => 0},
+ 0);
+
+ # delete all MOVE_WITH the priest
+ # BUG?: uninitialized value in this line??? maybe split is wrong in a way?
+ $self->{-db}->update_hash('MOBILE',
+ "MOVE_WITH = $self->{-mob}->{'ID'}",
+ {'MOVE_WITH' => 0});
+
+ $self->empty_field($self->{-mob}->{'LOCATION'});
+
+ my ($size) = $self->{-db}->read_game($self->{-game},'TEMPLE_SIZE');
+
+ # set new temple size
+ $size++;
+ $self->{-db}->update_hash('GAME',
+ "GAME=$self->{-game}",
+ {'TEMPLE_SIZE' => $size});
+ Util::log("New temple size: $size",1);
+
+ # calculate duration
+ $self->setDuration($size * $::conf->{-DURATION}->{-BUILD_TEMPLE});
+
+ $self->event($self->{-mob}->{'LOCATION'},
+ 'EVENT_BUILD_TEMPLE',
+ $self->{-context}->charname($self->{-mob}->{'ADORING'}),
+ $size);
+
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed.
+# BUILD_TEMPLE
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $loc = $self->{-mob}->{'LOCATION'};
+ $self->{-db}->update_hash('MAP',
+ "GAME=$self->{-game} AND LOCATION=$loc",
+ {'TEMPLE' => 'Y',
+ 'HOME' => $self->{-mob}->{'ADORING'}});
+
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$self->{-mob}->{'ID'}",
+ {'AVAILABLE' => 'Y'});
+
+ # insert new PRODUCE-command
+ $self->{-context}->insert_command('PRODUCE', "ROLE=$self->{-player}",
+ $self->{-mob}->{'LOCATION'});
+
+ # insert new PRAY-command
+ $self->{-context}->insert_command('PRAY','',$loc);
+
+ # this deletes and reinsert commands, if we conquer with building
+ $self->enter_field($loc,1);
+
+ #change aymargeddon to nearest pole
+ my $poles = $self->{-db}->select_array('MAP',
+ 'LOCATION,TERRAIN',
+ "GAME=$self->{-game} AND ".
+ "(TERRAIN=POLE OR TERRAIN=AYMARGEDDON)");
+ my $min_distance = $::conf->{-MANY};
+ my $Loc = Location->from_string($loc);
+ my ($new_aym,$old_aym) = ('','');
+ for my $pol (@$poles){
+ my ($loc2,$ter) = @$pol;
+ $old_aym = $loc2 if $ter eq 'AYMARGEDDON';
+ my $map = HexTorus->new($self->{-context}->get_size());
+ my $Loc2 = Location->from_string($loc2);
+ my $dist = $map->distance($Loc,$Loc2);
+ Util::log("distance from $loc to $loc2: $dist",1);
+ $new_aym = $loc2 if $dist < $min_distance and $ter eq 'POLE';
+ }
+ if($new_aym){
+ Util::log("change aymargeddon from $old_aym to $new_aym",1);
+ $self->{-db}->update_hash('MAP',
+ "GAME=$self->{-game} AND LOCATION=$new_aym",
+ {'TERRAIN' => 'AYMARGEDDON'});
+ $self->{-db}->update_hash('MAP',
+ "GAME=$self->{-game} AND LOCATION=$old_aym",
+ {'TERRAIN' => 'POLE'});
+ $self->{-context}
+ ->send_message_to_all
+ ({'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_CHANGE_AYMARGEDDON',
+ 'ARG1' => $self->{-context}->charname($self->{-player})});
+ #'ARG2' => $old_aym,
+ #'ARG3' => $new_aym});
+ }
+
+ # is this the end of the game?
+ my $unbuild = $self->{-context}->unbuild();
+
+ $self->end_of_the_game() unless $unbuild;
+
+ return 0;
+}
+
+#
+# End of BUILD_TEMPLE
+#
+####################################################
+
+##########################################################
+#
+# PRODUCE
+#
+
+package PRODUCE;
+use Data::Dumper;
+@PRODUCE::ISA = qw(AymCommand);
+
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('ROLE');
+ # TODO: Open question: is this redundant information? allready
+ # in PLAYER of COMMAND?
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 1;
+}
+
+# PRODUCE
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my ($ter,$home,$occ,$temple) =
+ $self->{-context}->read_field('TERRAIN,HOME,OCCUPANT,TEMPLE',
+ $self->{-dbhash}->{'LOCATION'});
+
+ my ($type, $duration);
+ $type = $temple eq 'Y' ? 'PRIEST' : 'WARRIOR';
+
+ my $d = $::conf->{-DURATION};
+ my $peace = $self->{-args}->{'PEACE'};
+ $peace = 0 unless defined $peace;
+ if($type eq 'PRIEST'){
+ Util::log("Produce a priest at ",-1);
+ if ($ter eq 'MOUNTAIN'){
+ Util::log("mountain.",1);
+ $duration = $d->{-PRODUCE_PRIEST_HOME};
+ }else{
+ Util::log("isle.",1);
+ $duration = $d->{-PRODUCE_PRIEST};
+ }
+ $self->setDuration($duration);
+ $self->event($self->{-location},
+ 'EVENT_PRODUCE_PRIEST');
+ }else{
+ Util::log("Produce a warrior at ",-1);
+ if ($occ == $home){
+ Util::log("homecity.",1);
+ $duration = $d->{-PRODUCE_WARRIOR_HOME};
+ }else{
+ Util::log("normal city.",1);
+ $duration = $d->{-PRODUCE_WARRIOR} + $d->{-PRODUCE_WARRIOR_CHANGE} * $peace;
+ }
+ $self->setDuration($duration);
+ $self->event($self->{-location},
+ 'EVENT_PRODUCE_WARRIOR');
+ }
+
+ return $duration;
+}
+
+# this is called from scheduler when the command will be executed.
+# PRODUCE
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $loc = $self->{-dbhash}->{'LOCATION'};
+ my ($temple,$home,$occ,$plague) =
+ $self->{-context}->read_field('TEMPLE,HOME,OCCUPANT,PLAGUE',$loc);
+ my $type = $temple eq 'Y' ? 'PRIEST' : 'WARRIOR';
+
+ # fields with influenza do not produce
+ if(not defined $plague or not $plague =~ 'INFLUENZA'){
+
+ # dont produce priests at temples, if no other priests are there
+ if ($type eq 'PRIEST'){
+ my $mobiles = $self->{-context}
+ ->read_mobile_condition('ID',
+ "TYPE=PRIEST AND AVAILABLE=Y AND ADORING=$home",$loc);
+ if(!@$mobiles){
+ Util::log("No priests, no new priests!",1);
+ $self->do_it_again();
+ return 0;
+ }
+ }
+
+ my $mob = {'ID' => $self->{-db}->find_first_free('MOBILE','ID'),
+ 'TYPE' => $type,
+ 'LOCATION' => $loc,
+ 'COUNT' => 1,
+ 'AVAILABLE' => 'Y',
+ 'OWNER' => $self->{-args}->{'ROLE'},
+ 'GAME' => $self->{-game},
+ 'MOVE_WITH' => 0,
+ };
+
+ # print Dumper $mob;
+
+ $mob->{'ADORING'} = $home if $type eq 'PRIEST';
+
+ my %mobcopy = (%$mob);
+ $self->{-mob} = \%mobcopy;
+ $self->{-db}->insert_hash('MOBILE',
+ $mob);
+
+ $self->enter_field($loc,1);
+ } # endif no influenza
+ else{
+ Util::log("No production in $loc due to INFLUENZA!",1);
+ }
+
+ # re-insert command
+ my $new_peace = $self->{-args}->{'PEACE'};
+ $new_peace = 0 unless defined $new_peace;
+ $new_peace++;
+ $self->do_it_again({'PEACE' => $new_peace});
+
+ return 1;
+}
+
+#
+# End of PRODUCE
+#
+####################################################
+
+##########################################################
+#
+# PRAY
+#
+
+package PRAY;
+use Data::Dumper;
+@PRAY::ISA = qw(AymCommand);
+
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ();
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ $self->{-loc} = $self->{-dbhash}->{'LOCATION'};
+ my ($temple,$home) = $self->{-context}->read_field('TEMPLE,HOME',
+ $self->{-loc});
+ # TODO: use test() instead
+ return 0 unless $temple eq 'Y';
+
+ $self->{-god} = $home;
+
+ return 1;
+}
+
+# PRAY
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ return $self->{-duration};
+}
+
+# PRAY
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # count number of active orthodox priests
+ my $priests = 0;
+ my $oim = $self->{-context}->own_in_mobile($self->{-loc},
+ $self->{-god},
+ 'available');
+
+ for my $om (@$oim){
+ my ($id) = @$om;
+ my $mob = $self->{-db}->read_single_mobile($id);
+ $priests += $mob->{'COUNT'} if($mob->{'TYPE'} eq 'PRIEST');
+ }
+
+ # reduce effective priests if necessary
+ my $fortune = $self->{-context}->read_fortune();
+ my $oldpriests = $priests;
+
+ my ($terrain) = $self->{-context}->read_field('TERRAIN',$self->{-loc});
+ if($terrain eq 'MOUNTAIN'){
+ if($priests > $::conf->{-FORTUNE_FAKTOR_MOUNTAIN} * $fortune){
+ $priests = $::conf->{-FORTUNE_FAKTOR_MOUNTAIN} * $fortune;
+ }
+ }elsif($terrain eq 'ISLE'){
+ if($priests > $::conf->{-FORTUNE_FAKTOR_ISLAND} * $fortune){
+ $priests = $::conf->{-FORTUNE_FAKTOR_ISLAND} * $fortune;
+ }
+ }else{
+ Util::log("ERROR: PRAY in terrain $terrain",0);
+ }
+
+ Util::log("reduce praying priests from $oldpriests to".
+ " $priests in $self->{-loc} ($terrain, fortune: $fortune)",1)
+ if $oldpriests > $priests;
+
+ # add priests + 1 mana to $self->{-god}
+ my $mana = $self->{-context}->get_mana($self->{-god});
+ my $newmana = $mana + $priests + $::conf->{-MANA_FOR_TEMPLE};
+
+ $self->{-db}->update_hash('GOD',
+ "PLAYER=$self->{-god} AND GAME=$self->{-game}",
+ {'MANA' => $newmana});
+ Util::log("$priests priests pray for $self->{-god} ".
+ "in $self->{-loc} and he got ". ($newmana - $mana) ." mana",1);
+
+ # TODO: Message?
+
+ # re-insert command
+ $self->do_it_again();
+
+ return 1;
+}
+
+#
+# End of PRAY
+#
+####################################################
+
+##########################################################
+#
+# BUILD_ARK
+#
+
+package BUILD_ARK;
+use Data::Dumper;
+@BUILD_ARK::ISA = qw(AymCommand);
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ # my @required_arguments = ('');
+ return 0 unless $self->Command::is_valid();
+
+ return 0 unless $self->validate_role('GOD');
+
+ return 1;
+}
+
+# this is called from Scheduler, if he sees the command the
+# first time, some commands execute here immidiatly.
+# BUILD_ARK
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+ return 0 unless $self->test_mana('BUILD_ARK');
+
+ # calculate duration
+ $self->setDuration($::conf->{-DURATION}->{-BUILD_ARK});
+
+ $self->event($self->{-location},
+ 'EVENT_BUILD_ARK');
+
+ $self->use_mana();
+
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed.
+# BUILD_ARK
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # owner should be occupant
+ my ($occ) = $self->{-context}->read_field('OCCUPANT',$self->{-location});
+ $occ = -1 unless $occ;
+
+ my $mob = {'ID' => $self->{-db}->find_first_free('MOBILE','ID'),
+ 'TYPE' => 'ARK',
+ 'LOCATION' => $self->{-location},
+ 'COUNT' => 1,
+ 'AVAILABLE' => 'Y',
+ 'OWNER' => $occ,
+ 'GAME' => $self->{-game},
+ };
+ my %mobcopy = (%$mob);
+ $self->{-db}->insert_hash('MOBILE',$mob);
+
+ # merge multiple ARKs in one mobile, if same owner
+ $self->unify_mobiles(\%mobcopy,$self->{-location},$occ);
+
+ # $self->{-db}->commit();
+
+# $self->{-context}
+# ->send_message_to_field
+# ($self->{-location},
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_BUILD_ARK',
+# 'ARG1' => $self->{-context}->charname($self->{-player}),
+# 'ARG2' => $self->{-location}});
+
+ return 0;
+}
+
+#
+# End of BUILD_ARK
+#
+####################################################
+
+####################################################
+#
+# INCARNATE: Create an Avatar
+#
+
+package INCARNATE;
+@INCARNATE::ISA = qw(AymCommand);
+
+sub is_valid{
+ my ($self) = @_;
+
+ my @required_arguments = ('COUNT');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ # you need a temple to create an avatar
+ $self->{-arrival} = $self->{-context}->incarnation_place();
+ return 0 unless $self->test(sub{$self->{-arrival};},
+ 'MSG_ERROR_NO_ARRIVAL');
+
+ # TODO: maybe with variing cost (distance to Aymargeddon)
+ return 0 unless $self->test_mana('INCARNATE', $self->{-args}->{'COUNT'});
+
+ return 1;
+}
+
+# INCARNATE
+sub first_phase{
+ my $self = shift;
+ return 0 unless $self->is_valid();
+
+ # create mobile (or join)
+ my $mob = {'ID' => $self->{-db}->find_first_free('MOBILE','ID'),
+ 'GAME' => $self->{-game},
+ 'LOCATION' => $self->{-location},
+ 'TYPE' => 'AVATAR',
+ 'OWNER' => $self->{-player},
+ 'COUNT' => $self->{-args}->{'COUNT'},
+ 'AVAILABLE' => 'Y',
+ 'STATUS' => 'IGNORE',
+ 'COMMAND_ID' => $self->{-id},
+ };
+ $self->{-mob} = $mob;
+ my %mobcopy = (%$mob);
+ $self->{-db}->insert_hash('MOBILE',\%mobcopy);
+
+ $self->enter_field_avatar($self->{-location},$mob);
+ $self->unify_mobiles($mob,$self->{-location});
+
+ $self->use_mana();
+
+ # TODO: count count
+# $self->{-context}
+# ->send_message_to_field
+# ($self->{-location},
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_INCARNATE',
+# 'ARG1' => $self->{-context}->charname($self->{-player}),
+# 'ARG2' => $self->{-location}});
+
+ $self->setDuration(0);
+ return 1;
+};
+
+sub second_phase{
+ my $self = shift;
+ Util::log("Warning: We should not reach phase 2 with command INCARNATE",0);
+ return 0;
+};
+
+#
+# END of INCARNATE
+#
+################################################################
+
+##########################################################
+#
+# FIGHT_EARTHLING
+#
+
+package FIGHT_EARTHLING;
+use Data::Dumper;
+use Date::Parse qw(str2time);
+use Date::Calc qw(Time_to_Date);
+@FIGHT_EARTHLING::ISA = qw(AymCommand);
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('ATTACKER','DEFENDER');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_role('EARTHLING');
+ return 0 unless $self->validate_this_role($self->{-args}->{'ATTACKER'},'EARTHLING');
+ my $def = $self->{-args}->{'DEFENDER'};
+ if($def > 0){
+ return 0 unless $self->validate_this_role($self->{-args}->{'DEFENDER'},'EARTHLING');
+ }
+
+ return 1;
+}
+
+# this is called from Scheduler, if he sees the command the
+# first time, some commands execute here immidiatly.
+# FIGHT_EARTHLING
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # calculate duration
+ $self->setDuration($::conf->{-DURATION}->{-FIGHT_EARTHLING});
+
+ $self->event($self->{-location},
+ 'FIGHT_EARTHLING');
+
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed.
+# FIGHT_EARTHLING
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # read map info
+ my ($terrain,$home,$occupant) = $self->{-context}->
+ read_field('TERRAIN,HOME,OCCUPANT',$self->{-location});
+
+ my $attacker = $self->{-args}->{'ATTACKER'};
+ my $defender = $self->{-args}->{'DEFENDER'};
+
+ # get all mobiles
+ my $mobiles = $self->{-context}->read_mobile('ID,TYPE,OWNER,COUNT,STATUS',
+ 0, $self->{-location}, 1);
+ $self->{-mobiles} = $mobiles;
+ # print Dumper $mobiles;
+
+ #my $efoa = {"$attacker" => 0}; # earthling friends of attacker
+ #my $efod = {"$defender" => 0}; # earthling friends of defender
+ #$self->{-efoa} = $efoa;
+ #$self->{-efod} = $efod;
+
+ my ($gfoa, $gfod); # god friends ...
+
+ # calculate strength of both sides
+ my ($attack_strength, $defend_strength,$attack_avatar,$defend_avatar) = (0,0,0,0);
+ my ($people_attacker, $people_defender) = (0,0);
+ for my $mob (@$mobiles){
+ my ($id,$type,$own,$count,$stat) = @$mob;
+
+ # next if $own <= 0;
+ if(exists($gfod->{$own})){
+ # could be reached with differen MOVE_WITH
+ $defend_avatar += $count * $self->strength('AVATAR');
+ $gfod->{$own} += $count;
+ Util::log("(1)mobile $id: $count $type from $own fights for $defender in $self->{-location}",1);
+ }elsif(exists($gfoa->{$own})){
+ # could be reached with differen MOVE_WITH
+ $attack_avatar += $count * $self->strength('AVATAR');
+ $gfoa->{$own} += $count;
+ Util::log("(2)mobile $id: $count $type from $own fights for $attacker in $self->{-location}",1);
+ }else{
+ # TODO Performance (in the case of earthling this is not necessary)
+ my ($att_rel,$def_rel,$foa,$fod) = (0,0,0,0);
+
+ # Avatars dont fight sometimes (no mana or no help or no friend)
+ if($type eq 'AVATAR'){
+ # if(not $godfight){
+ $att_rel = $self->{-context}->read_single_relation($own,$attacker);
+ $def_rel = $self->{-context}->read_single_relation($own,$defender);
+
+ $foa = 1 if Util::is_in($att_rel,'FRIEND','ALLIED');
+ $fod = 1 if Util::is_in($def_rel,'FRIEND','ALLIED');
+
+ # defender has support if in doubt
+ $foa = 0 if $foa and $fod;
+ $fod = 1 if not $foa and not $fod;
+
+ $gfoa->{$own} += $count if $foa;
+ $gfod->{$own} += $count if $fod;
+
+ # if you dont have enough mana for all your avatars no one fights!
+ if($stat eq 'HELP' and $self->test_mana('FIGHT_AVATAR',1,$own)){
+ $self->use_mana($own);
+ }else{
+ ($foa, $fod) = (0,0);
+ $gfod->{$own} = 0;
+ $gfoa->{$own} = 0;
+ }
+ # }
+ }else{
+ # earthlings are simpel: no friends in field
+ $foa = 1 if $own == $attacker;
+ $fod = 1 if $own == $defender;
+ }
+
+ if($foa){
+ Util::log("(3)mobile $id: $count $type from $own fights for ".
+ "$attacker in $self->{-location}",1);
+ if($type eq 'AVATAR'){
+ # count maximum avatarpower
+ $attack_avatar += $count * $self->strength('AVATAR');
+ }else{
+ # count earthling_strength
+ $attack_strength += $count * $self->strength($type);
+ $people_attacker += $count;
+ }
+ }elsif($fod){ # same for defender
+ Util::log("(4)mobile $id: $count $type from $own fights for ".
+ "$defender in $self->{-location}",1);
+ if($type eq 'AVATAR'){
+ $defend_avatar += $count * $self->strength('AVATAR');
+ }else{
+ $defend_strength += $count * $self->strength($type);
+ $people_defender += $count;
+ }
+ }else{
+ Util::log("(5)mobile $id: $own dont fight with $count $type ".
+ "in $self->{-location}",1);
+ }
+ }
+ }
+
+ # terrain-bonus
+ if($terrain eq 'CITY'){
+ # bonus for home city
+ if($home == $attacker){
+ Util::log("homecity fights for $attacker",1);
+ $attack_strength += $::conf->{-FIGHT}->{-HOME};
+ }elsif($home == $defender and $home){
+ Util::log("homecity fights for $defender",1);
+ $defend_strength += $::conf->{-FIGHT}->{-HOME};
+ }
+ }elsif($terrain eq 'ISLE'){
+ # bonus for isle
+ if($occupant == $attacker){
+ Util::log("isle fights for $attacker",1);
+ $attack_strength += $::conf->{-FIGHT}->{-ISLE};
+ }elsif($occupant == $defender){
+ Util::log("isle fights for $defender",1);
+ $defend_strength += $::conf->{-FIGHT}->{-ISLE};
+ }else{
+ Util::log("impossible situation: isle fights for no one!",0);
+ }
+ }
+
+ Util::log("earthling strength attacker($attacker): ".
+ "$attack_strength, defender($defender): $defend_strength"
+ ,1);
+
+ my $pure_attack_strength = $attack_strength;
+ my $pure_defend_strength = $defend_strength;
+
+ #my $attacker_death_count = $attack_strength;
+ #my $defender_death_count = $defend_strength;
+
+ my $attacker_death_count = $people_attacker;
+ my $defender_death_count = $people_defender;
+
+ Util::log("$people_attacker people fight for attacker $attacker",1);
+ Util::log("$people_defender people fight for defender $defender",1);
+
+ my $attacker_godpower = Util::min($people_attacker,$attack_avatar);
+ my $defender_godpower = Util::min($people_defender,$defend_avatar);
+
+ Util::log("Gods supports attacker($attacker) with $attacker_godpower",1);
+ Util::log("Gods supports defender($defender) with $defender_godpower",1);
+
+ $attack_strength += $attacker_godpower;
+ $defend_strength += $defender_godpower;
+
+ # FLANKING
+ # if landbattle: look, for all neighbour fields,
+ # add flanking power of allies
+ my ($flanking_attack,$flanking_defend) = (0,0);
+ # if(not $self->{-see_battle} and not $self->{-island_battle}){
+ my @neighbours = $self->get_neighbours($self->{-location});
+ # COMMENT IN FOR NEW RULE my ($att_neighbours,$def_neighbours) = (0,0);
+ # print "neighbours: @neighbours\n";
+ for my $n (@neighbours){
+ # my $n_string = $n->to_string();
+ my ($ter,$occ,$att) = $self->{-context}->
+ read_field('TERRAIN,OCCUPANT,ATTACKER',$n);
+ next if $ter eq 'WATER'; # dont flank from see
+ next if $att > 0; # dont flank from war
+ my $attacker_relation = $self->{-context}->read_single_relation($occ,$attacker);
+ my $defender_relation = $self->{-context}->read_single_relation($occ,$defender);
+ Util::log("flanking ($n): $attacker_relation, $defender_relation, ".
+ "$ter, $occ, $att",1);
+ if($occ != $defender and
+ ($occ == $attacker or (Util::is_in($attacker_relation,'FRIEND','ALLIED') and not
+ Util::is_in($defender_relation,'FRIEND','ALLIED')))){
+ # COMMENT IN FOR NEW RULE $att_neighbours++;
+ # COMMENT IN FOR NEW RULE $flanking_attack += $::conf->{-FIGHT}->{-FLANKING} * $att_neighbours;
+ $flanking_attack += $::conf->{-FIGHT}->{-FLANKING};
+ Util::log("$n flanks for attacker($attacker)",1);
+ }elsif($occ and ($occ != $attacker and
+ ($occ == $defender or
+ (not Util::is_in($attacker_relation,'FRIEND','ALLIED')
+ and Util::is_in($defender_relation,'FRIEND','ALLIED'))))){
+ # COMMENT IN FOR NEW RULE $def_neighbours++;
+ # COMMENT IN FOR NEW RULE $flanking_defend += $::conf->{-FIGHT}->{-FLANKING} * $def_neighbours;
+ $flanking_defend += $::conf->{-FIGHT}->{-FLANKING};
+ Util::log("$n flanks for defender($defender)",1);
+ }
+ }
+ Util::log("sum of flanking: $flanking_attack for attacker($attacker) and ".
+ "$flanking_defend for defender($defender) and ",1);
+ $attack_strength += $flanking_attack;
+ $defend_strength += $flanking_defend;
+ #}
+
+ Util::log("sum strength without fortune: $attack_strength for attacker($attacker) ".
+ "and $defend_strength for defender($defender)",1);
+
+ # add random value (1 to GAME.FORTUNE)
+ my $fortune = $self->{-context}->read_fortune();
+ my $asf = int(rand($fortune))+1;
+ my $dsf = int(rand($fortune))+1;
+ $attack_strength += $asf;
+ $defend_strength += $dsf;
+ Util::log("strength with fortune attacker($attacker): ".
+ "$attack_strength, defender($defender): $defend_strength",1);
+
+ # my @loosers;
+
+ if($attack_strength > $defend_strength){
+ $self->{-winner} = $attacker;
+ $self->{-looser} = $defender;
+ $self->{-winner_death_count} = Util::min($people_attacker - 1,
+ int(0.5 + $defender_death_count /
+ $::conf->{-WINNER_DEATH_COUNT_FRACTION}));
+ $self->{-looser_death_count} = Util::max(1,int(0.5 + $attacker_death_count /
+ $::conf->{-LOOSER_DEATH_COUNT_FRACTION}));
+ Util::log("Attackers($attacker) won!",1);
+ $self->conquer($self->{-location},$attacker);
+ }else{
+ $self->{-winner} = $defender;
+ $self->{-looser} = $attacker;
+ $self->{-winner_death_count} = Util::min($people_defender - 1,
+ int(0.5 + $attacker_death_count /
+ $::conf->{-WINNER_DEATH_COUNT_FRACTION}));
+ $self->{-looser_death_count} = Util::max(1,int(0.5 + $defender_death_count /
+ $::conf->{-LOOSER_DEATH_COUNT_FRACTION}));
+ # $self->{-looser} = $efoa;
+ # $self->{-master_looser} = $attacker;
+ Util::log("Defenders($defender) won!",1);
+ }
+
+ # loosers and helpers run away or die
+ $self->run_or_die();
+
+ # erase MAP.ATTACKER
+ $self->{-db}->update_hash('MAP',
+ "LOCATION=$self->{-location} AND GAME=$self->{-game}",
+ {'ATTACKER' => 0});
+
+ # reread mobiles
+ # $self->{-mobiles} = $self->{-context}->read_mobile('ID',
+ # 0, $self->{-location}, 1);
+
+ # unify the mobiles, which are still here
+ for my $mob_arr (@$mobiles){
+ my ($id,$type,$owner,$count,$status) = @$mob_arr;
+ next if exists $self->{-run_or_die}->{$id};
+ my $mob = $self->{-db}->read_single_mobile($id);
+ $self->unify_mobiles($mob,$self->{-location},$owner) if $mob;
+ }
+
+ # sometimes the last ark is gone in battle
+ if($terrain eq 'WATER'){
+ $self->drowning($self->{-location});
+ }
+
+ # send battle-report
+ my $name_of_attacker = $self->{-context}->charname($attacker);
+ my $name_of_defender = $self->{-context}->charname($defender);
+ my $name_of_winner = $self->{-context}->charname($self->{-winner});
+
+ my $text = <<END_OF_TEXT;
+ <strong>BATTLE_REPORT $self->{-location}</strong><br>
+ <table><tr><th></th><th>$name_of_attacker</th><th>$name_of_defender</th></tr>
+ <tr><td>PEOPLE</td><td>$people_attacker</td>
+ <td>$people_defender</td></tr>
+ <tr><td>FIGHTING_STRENGTH</td><td>$pure_attack_strength</td>
+ <td>$pure_defend_strength</td></tr>
+ <tr><td>FLANKING</td><td>$flanking_attack</td><td>$flanking_defend</td></tr>
+ <tr><td>GODS_HELP</td><td>$attacker_godpower</td><td>$defender_godpower</td></tr>
+ <tr><td>LUCK</td><td>$asf</td><td>$dsf</td></tr>
+ <tr><td>SUM_OF_STRENGTH</td><td>$attack_strength</td><td>$defend_strength</td></tr>
+ <tr><td>DEAD_WARRIORS</td><td>$self->{-dead}->{$attacker}->{'K'}</td>
+ <td>$self->{-dead}->{$defender}->{'K'}</td></tr>
+ <tr><td>DEAD_HEROS</td><td>$self->{-dead}->{$attacker}->{'H'}</td>
+ <td>$self->{-dead}->{$defender}->{'H'}</td></tr>
+ <tr><td>DEAD_PRIESTS</td><td>$self->{-dead}->{$attacker}->{'P'}</td>
+ <td>$self->{-dead}->{$defender}->{'P'}</td></tr>
+ <tr><td>SUNKEN_ARKS</td><td>$self->{-dead}->{$attacker}->{'A'}</td>
+ <td>$self->{-dead}->{$defender}->{'A'}</td></tr>
+ <tr><td>CONQUERED_ARKS</td><td>$self->{-dead}->{$defender}->{'C'}</td>
+ <td>$self->{-dead}->{$attacker}->{'C'}</td></tr>
+ </table>
+ <strong>WINNER_IS $name_of_winner</strong>.
+END_OF_TEXT
+
+ # TODO: we should make shure, that attacker and defender are receivers.
+ # could happen, if all dying and no other unit in the neighbourhood
+ my @gods = (keys %$gfoa, keys %$gfod);
+ $self->{-context}
+ ->send_message_to_field
+ ($self->{-location},{'MFROM' => 0,
+ 'MSG_TEXT' => $text}
+ # 'ARG1' => $self->{-context}->charname($attacker),
+ # 'ARG2' => $self->{-context}->charname($defender),
+ # 'ARG3' => $self->{-context}->charname($self->{-winner}),
+ # 'ARG4' => $self->{-location}}
+ );
+ #,$attacker,$defender,@gods);
+
+ return 0;
+}
+
+# FIGHT_EARTHLING
+sub run_or_die{
+ my($self) = @_;
+
+ # some people have to die
+ $self->casualties($self->{-winner},$self->{-winner_death_count});
+ $self->casualties($self->{-looser},$self->{-looser_death_count});
+
+ # print Dumper $self->{-dead};
+
+ # reread mobiles
+ $self->{-mobiles} = $self->{-context}->read_mobile('ID,TYPE,OWNER,COUNT,STATUS',
+ 0, $self->{-location}, 1);
+
+ # the survivors run
+ # TODO: no retreat if no survivors
+ $self->retreat();
+
+}
+
+sub find_retreat_field{
+ my ($self,$retreat_fields) = @_;
+
+ my @retreat_fields = @$retreat_fields;
+
+ # chose one retreat-field
+ return $retreat_fields[rand($#retreat_fields +1)];
+}
+
+sub retreat_unit{
+ my ($self,$unit,$count,$retreat,$type) = @_;
+
+ my $looser = $self->{-looser};
+
+ # calculate direction
+ my $dir = $self->{-context}->is_in_direction_from($retreat,
+ $self->{-location});
+
+ # retreat via MOVE_WITH if retreat with ark
+ if($type ne 'ARK' and exists $self->{-retreat_arks}->{$retreat}){
+ my $ark = $self->{-retreat_arks}->{$retreat};
+ $self->{-db}->update_hash('MOBILE',
+ "ID=$unit",
+ {'MOVE_WITH' => $ark,
+ 'AVAILABLE' => 'N'});
+ Util::log("retreat via $ark (MOVE_WITH)",1);
+ }else{
+ # TODO?: insert event
+ $self->{-context}->insert_command('MOVE',
+ "DIR=$dir, MOBILE=$unit, ".
+ "COUNT=$count, AUTO=1",
+ $self->{-location},
+ $looser);
+ Util::log("retreat via MOVE_COMMAND",1);
+ }
+ Util::log("$looser retreats from $self->{-location} to $retreat ".
+ "in direction $dir with $count people(or ark). Mobile-ID: $unit",1);
+ $self->{-run_or_die}->{$unit} = 1;
+
+ $self->{-context}
+ ->send_message_to_list
+ ({'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_FIGHT_RETREAT',
+ 'ARG1' => $self->{-context}->charname($looser),
+ 'ARG2' => 'PEOPLE_OR_ARK',
+ 'ARG3' => $self->{-location},
+ 'ARG4' => $count},$looser,$self->{-winner});
+
+ return $retreat;
+}
+
+sub retreat{
+ my ($self) = @_;
+
+ my $looser = $self->{-looser};
+ Util::log("checking retreats for looser $looser ...",1);
+
+ # remove MOVE_WITH if any
+ $self->{-db}->update_hash('MOBILE',
+ "OWNER=$looser AND LOCATION=$self->{-location} AND ".
+ "AVAILABLE=Y",
+ {'MOVE_WITH' => 0});
+
+ # search for retreat-possibilities
+ my ($local_terrain) = $self->{-context}->read_field('TERRAIN',$self->{-location});
+ my @possible_retreat = $self->{-context}->own_neighbours($self->{-location},$looser);
+ my @retreat_fields = ();
+ my @retreat_water_fields = ();
+ if ($local_terrain eq 'WATER' or $local_terrain eq 'ISLE'){
+ @retreat_water_fields = @possible_retreat;
+ Util::log("retreat from water: @possible_retreat",1);
+ }else{
+ Util::log("check retreat for ...",-1);
+ for my $field (@possible_retreat){
+ Util::log("\n$field ",-1);
+ my ($terrain) = $self->{-context}->read_field('TERRAIN',$field);
+ if ($terrain eq 'WATER' or $terrain eq 'ISLE'){
+ Util::log("... accepted water retreat to $terrain!",1);
+ push @retreat_water_fields, $field;
+ }else{
+ Util::log("... accepted land retreat to $terrain!",1);
+ push @retreat_fields, $field;
+ }
+ }
+ }
+ # $self->{-retreat_fields} = \@retreat_fields;
+ # $self->{-retreat_water_fields} = \@retreat_fields;
+
+ # retreat own arks
+
+ my $have_ark = 0;
+ my %arks = ();
+ if($#retreat_water_fields >= 0){
+ $self->{-retreat_arks} = {}; # TODO Performance: use only hashes, no arrays
+ for my $m (@{$self->{-mobiles}}){
+ my ($id,$type,$own,$count,$stat) = @$m;
+ next unless $type eq 'ARK' and ($own == $self->{-looser});
+
+ my $retreat_field = $self->find_retreat_field(\@retreat_water_fields);
+ Util::log("found ark $id from $own for retreat to $retreat_field",1);
+
+ $self->{-retreat_arks}->{$retreat_field} = $id;
+ $arks{$id} = $retreat_field;
+
+ if (not Util::is_in($retreat_field,@retreat_fields)){
+ push @retreat_fields, $retreat_field;
+ Util::log("... accepted retreat through ark $id to $retreat_field!",1);
+ }
+ }
+ }else{
+ # all arks change owner to winner
+ $self->{-db}->update_hash('MOBILE',
+ "GAME=$self->{-game} AND ".
+ "LOCATION=$self->{-location} AND ".
+ "TYPE=ARK",
+ {'OWNER' => $self->{-winner}});
+ Util::log("All arks in $self->{-location} change owner to $self->{-winner}",1);
+ }
+
+
+ # for every unit of this looser
+ for my $mob (@{$self->{-mobiles}}){
+ my ($id,$type,$own,$count,$stat) = @$mob;
+ next unless $own == $looser;
+ next if $type eq 'ARK';
+
+ # if there is a way out
+ if($#retreat_fields >= 0){
+ my $field = $self->find_retreat_field(\@retreat_fields);
+ Util::log("checking retreat for mobile $id ".
+ "(own: $own, type: $type, count: $count, field: $field)",1);
+ $self->retreat_unit($id,$count,$field,$type);
+ }else{
+ # die!
+ $self->{-db}->delete_from('MOBILE',"ID=$id");
+ $self->{-run_or_die}->{$id} = 1;
+
+ $self->{-context}
+ ->send_message_to_field
+ ($self->{-location},
+ {'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_FIGHT_RETREAT_DIE',
+ 'ARG1' => $self->{-context}->charname($looser),
+ 'ARG2' => $type,
+ 'ARG3' => $self->{-location},
+ 'ARG4' => $count});#,$looser,$self->{-winner});
+ Util::log("$looser looses $count $type in $self->{-location}".
+ " because there is no place to retreat.",1);
+ }
+ }
+ # MOVE COMMANDS for arks came last because others move with them
+ for my $mob (@{$self->{-mobiles}}){
+ my ($id,$type,$own,$count,$stat) = @$mob;
+ next unless $own == $looser;
+ next unless $type eq 'ARK';
+ Util::log("checking retreat for mobile $id ".
+ "(own: $own, type: $type, count: $count, ".
+ "via ark $id to field: $arks{$id})",1);
+
+ $self->retreat_unit($id,$count,$arks{$id},$type);
+ }
+}
+
+sub strength{
+ my($self,$type) = @_;
+
+ # return $::conf->{-SEE_FIGHT}->{"-$type"} if $self->{-naval_battle};
+ # return $::conf->{-ISLAND_FIGHT}->{"-$type"} if $self->{-island_battle};
+ return $::conf->{-FIGHT}->{"-$type"};
+}
+
+#
+# End of FIGHT_EARTHLING
+#
+####################################################
+
+##########################################################
+#
+# BLESS_HERO
+#
+
+package BLESS_HERO;
+@BLESS_HERO::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('MOBILE','COUNT');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_mobile($self->{-args}->{'MOBILE'});
+
+ return 0 unless $self->validate_role('GOD');
+
+ my $mobtype = $self->{-mob}->{'TYPE'};
+ my $mobloc = $self->{-mob}->{'LOCATION'};
+ my $mobcount = $self->{-mob}->{'COUNT'};
+
+ return 0 unless $self->test(sub{$self->{-mob}->{'TYPE'} eq 'WARRIOR'},
+ 'MSG_WRONG_TYPE',
+ $self->{-context}->mobile_string($mobtype,1),
+ $mobloc);
+
+ $self->{-count} = $self->{-args}->{'COUNT'} > $mobcount ?
+ $mobcount : $self->{-args}->{'COUNT'};
+
+ return 0 unless $self->test_mana('BLESS_HERO',$self->{-count});
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# BLESS_HERO
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+
+ my $id = $self->{-mob}->{'ID'};
+ $self->conditional_split_mobile($self->{-mob},
+ $self->{-count},
+ {'ADORING' => $self->{-player},
+ 'TYPE' => 'HERO',
+ 'COMMAND_ID' => $self->{-dbhash}->{'ID'}},
+ 'beforeafter');
+
+ # reread mobile, because split destroys it
+ $self->{-mob} = $self->{-db}->single_hash_select('MOBILE',"ID=$id");
+ $self->unify_mobiles($self->{-mob},
+ $self->{-mob}->{'LOCATION'},
+ $self->{-mob}->{'OWNER'});
+
+# $self->{-context}
+# ->send_message_to_field
+# ($self->{-mob}->{'LOCATION'},
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_BLESS_HERO',
+# 'ARG1' => $self->{-context}->charname($self->{-player}),
+# 'ARG2' => $self->{-context}->charname($self->{-mob}->{'OWNER'}),
+# 'ARG3' => $self->{-mob}->{'LOCATION'}});
+
+ $self->use_mana();
+ $self->setDuration(0);
+
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("BLESS_HERO should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of BLESS_HERO
+#
+####################################################
+
+##########################################################
+#
+# CH_ACTION
+#
+
+package CH_ACTION;
+@CH_ACTION::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('ACTION','MOBILE');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_mobile($self->{-args}->{'MOBILE'});
+
+ return 0 unless $self->validate_role('GOD');
+
+ my $mobtype = $self->{-mob}->{'TYPE'};
+ my $mobloc = $self->{-mob}->{'LOCATION'};
+
+ return 0 unless $self->test(sub{$mobtype eq 'AVATAR'},
+ 'MSG_WRONG_TYPE',
+ $self->{-context}->mobile_string($mobtype,1),
+ $mobloc);
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# CH_ACTION
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $mob = $self->{-mob};
+ my $loc = $mob->{'LOCATION'};
+ my $own = $self->{-player};
+ my $action = $self->{-args}->{'ACTION'};
+
+ # all avatars in the field get the new status
+ $self->{-db}->update_hash('MOBILE',
+ "LOCATION=$loc AND TYPE=AVATAR AND OWNER=$own ".
+ "AND GAME=$self->{-game} AND AVAILABLE=Y",
+ {'STATUS' => $action});
+
+ $mob->{'STATUS'} = $action;
+ $self->enter_field_avatar($loc,$mob) if $action eq 'BLOCK';
+
+# $self->{-context}
+# ->send_message_to_field
+# ($self->{-mob}->{'LOCATION'},
+# {'MFROM' => 0,
+# 'MSG_TAG' => 'MSG_CH_ACTION',
+# 'ARG1' => $self->{-args}->{'ACTION'},
+# 'ARG2' => $self->{-mob}->{'LOCATION'}});
+
+ $self->setDuration(0);
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("CH_ACTION should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of CH_ACTION
+#
+####################################################
+
+####################################################
+#
+# DIE_ORDER: Change the order of mobiletypes which dies in battle
+#
+
+package DIE_ORDER;
+@DIE_ORDER::ISA = qw(AymCommand);
+
+sub is_valid{
+ my ($self) = @_;
+
+ my @required_arguments = ('DYING');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_role('EARTHLING');
+
+ # TODO: use test with message
+ return 0 unless Util::is_in($self->{-args}->{'DYING'},
+ 'PKH','PHK','KPH','KHP','HKP','HPK');
+
+ return 1;
+}
+
+# DIE_ORDER
+sub first_phase{
+ my $self = shift;
+ return 0 unless $self->is_valid();
+
+ my $dying = $self->{-args}->{'DYING'};
+
+ $self->{-db}->update_hash('EARTHLING',
+ "GAME=$self->{-game} AND ".
+ "PLAYER=$self->{-player}",
+ {'DYING' => $dying});
+
+ $self->{-context}->send_message_to_me({'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_DIE_ORDER',
+ 'ARG1' => $dying
+ });
+ Util::log("New die order for player $self->{-player}: $dying",1);
+
+ $self->setDuration(0);
+ return 1;
+};
+
+sub second_phase{
+ my $self = shift;
+ Util::log("Warning: We should not reach phase 2 with command DIE_ORDER",0);
+ return 0;
+};
+
+#
+# END of DIE_ORDER
+#
+################################################################
+
+
+##########################################################
+#
+# CH_LUCK
+#
+
+package CH_LUCK;
+@CH_LUCK::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('BONUS');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_role('GOD');
+
+ return 1 if $self->{-phase} == 2;
+
+ return 0 unless $self->test_mana('CH_LUCK',
+ abs($self->{-args}->{'BONUS'} * $::conf->{-MANA}->{-CH_LUCK}));
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# CH_LUCK
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ $self->use_mana();
+
+ return $self->setDuration($::conf->{-DURATION}->{-CH_LUCK});
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ return 0 unless $self->is_valid();
+ my $oldfortune = $self->{-context}->read_fortune();
+
+ my $change = $self->{-args}->{'BONUS'};
+
+ my $newfortune = $oldfortune + $change;
+ if($newfortune > $::conf->{-MAX_LUCK}){
+ $newfortune = $::conf->{-MAX_LUCK};
+ }elsif($newfortune < $::conf->{-MIN_LUCK}){
+ $newfortune = $::conf->{-MIN_LUCK};
+ }
+
+ $self->{-db}->update_hash('GAME',
+ "GAME=$self->{-game}",
+ {'FORTUNE' => $newfortune});
+
+ $self->{-context}
+ ->send_message_to_all
+ ({'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_CHANGE_FORTUNE',
+ 'ARG1' => $self->{-context}->charname($self->{-player}),
+ 'ARG2' => $oldfortune,
+ 'ARG3' => $newfortune});
+
+
+ return 0;
+}
+
+#
+# End of CH_LUCK
+#
+####################################################
+
+##########################################################
+#
+# FLOOD
+#
+
+package FLOOD;
+@FLOOD::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+ my $db = $self->{-db};
+ my $context = $self->{-context};
+ my $loc = $self->{-location};
+
+ my @required_arguments = ();
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_role('GOD');
+
+ # only PLAIN and MOUNTAIN can be flooded
+ my ($terrain) = $context->read_field('TERRAIN', $loc);
+ return 0 unless $self->test(sub{Util::is_in($terrain,'PLAIN','MOUNTAIN');},
+ 'MSG_CANT_FLOOD_TERRAIN',
+ $loc,
+ $terrain);
+ $self->{-terrain} = $terrain;
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# FLOOD
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $loc = $self->{-location};
+
+ # need own avatar to flood
+ return 0 unless $self->avatar_available($loc);
+ return 0 unless $self->test_mana('FLOOD');
+ $self->use_mana();
+
+ $self->setDuration($::conf->{-DURATION}->{-FLOOD});
+
+ $self->event($self->{-location},
+ 'EVENT_FLOOD',
+ $self->{-player});
+
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed.
+# FLOOD
+sub second_phase{
+ my $self = shift;
+ my $loc = $self->{-location};
+ my $db = $self->{-db};
+
+ return 0 unless $self->is_valid();
+
+ # mountain -> isle, plain -> water
+ my $new = $self->{-terrain} eq 'MOUNTAIN' ? 'ISLE' : 'WATER';
+ $db->update_hash('MAP',"LOCATION=$loc AND GAME=$self->{-game}",
+ {'TERRAIN' => $new});
+
+ # drowning of mobiles if necessary
+ $self->drowning($loc);
+
+ # Message
+ $self->{-context}
+ ->send_message_to_field
+ ($loc,{'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_FLOOD',
+ 'ARG1' => $self->{-context}->charname($self->{-player}),
+ 'ARG2' => $loc,
+ 'ARG3' => $self->{-terrain},
+ 'ARG4' => $new,});
+
+ return 0;
+}
+
+#
+# End of FLOOD
+#
+####################################################
+
+##########################################################
+#
+# DESTROY
+#
+
+package DESTROY;
+@DESTROY::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+ my $db = $self->{-db};
+ my $context = $self->{-context};
+ my $loc = $self->{-location};
+
+ my @required_arguments = ();
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 0 unless $self->validate_role('GOD');
+
+ return 0 unless $self->test_mana('DESTROY');
+
+ # we cant destroy if there is only one temple unbuild
+ # TODO: wrong. should be cant destroy, if last temple is under construction
+ my $unbuild = $db->count('MAP',
+ "(TERRAIN=ISLE OR TERRAIN=MOUNTAIN) ".
+ "AND TEMPLE=N AND GAME=$self->{-game}");
+ return 0 unless $self->test(sub{$unbuild > $::conf->{-MAX_UNBUILD_DESTROY}},
+ 'MSG_CANT_RESCUE_WORLD',
+ $unbuild,
+ $loc);
+
+ # need own avatar to destroy
+ return 0 unless $self->avatar_available($loc);
+
+ # there sould be no foreign priests
+ my $foreign_priests = $db->count('MOBILE',
+ "GAME=$self->{-game} AND ".
+ "LOCATION=$loc AND TYPE=PRIEST AND ".
+ "ADORING!=$self->{-player} AND ".
+ "AVAILABLE=Y");
+ return 0 unless $self->test(sub{$foreign_priests == 0},
+ 'MSG_CANT_DESTROY_DEFENDED',
+ $loc);
+
+ my ($terrain,$temple,$home) = $context->read_field('TERRAIN,TEMPLE,HOME',
+ $loc);
+
+ # only if temple exists
+ return 0 unless $self->test(sub{$temple eq 'Y'},
+ 'MSG_NO_TEMPLE_TO_DESTROY',
+ $loc);
+
+ # only destroy foreign temples
+ return 0 unless $self->test(sub{$home != $self->{-player}},
+ 'MSG_CANT_DESTROY_OWN',
+ $loc);
+ $self->{-oldgod} = $home;
+
+ # only on islands
+ return 0 unless $self->test(sub{$terrain eq 'ISLE'},
+ 'MSG_CANT_DESTROY_MOUNTAINS',
+ $loc);
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# DESTROY
+sub first_phase{
+ my $self = shift;
+ my $loc = $self->{-location};
+
+ return 0 unless $self->is_valid();
+
+ $self->use_mana();
+
+ $self->{-db}->update_hash('MAP',
+ "LOCATION=$loc AND GAME=$self->{-game}",
+ {'TEMPLE' => 'N',
+ 'HOME' => 0});
+
+ # delete PRAY- and PRODUCE-commands and PRODUCE-PRIEST event
+ $self->{-db}->delete_from('COMMAND',
+ "(COMMAND=PRODUCE OR COMMAND=PRAY) ".
+ "AND LOCATION=$loc AND GAME=$self->{-game}");
+ $self->{-db}->delete_from('EVENT',
+ "TAG=EVENT_PRODUCE_PRIEST ".
+ "AND LOCATION=$loc AND GAME=$self->{-game}");
+
+ $self->{-context}
+ ->send_message_to_field
+ ($loc,
+ {'MFROM' => 0,
+ 'MSG_TAG' => 'MSG_TEMPLE_DESTROYD',
+ 'ARG1' => $loc,
+ 'ARG2' => $self->{-context}->charname($self->{-oldgod}),
+ 'ARG3' => $self->{-context}->charname($self->{-player})
+ });
+
+ Util::log("Temple of $self->{-oldgod} destroyed in $self->{-location}",1);
+
+ $self->setDuration(0);
+
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("DESTROY should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of DESTROY
+#
+####################################################
+
+##########################################################
+#
+# MOVE_WITH
+#
+
+package MOVE_WITH;
+@MOVE_WITH::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('MOBILE','COUNT','TARGET');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ my $args = $self->{-args};
+ my $count = $args->{'COUNT'};
+
+ # TODO: more messages
+ # read mobile
+ return 0 unless $self->validate_mobile($args->{'MOBILE'});
+ my $mob = $self->{-mob};
+
+ # arks cant move with other units
+ return 0 if $self->{-mob}->{'TYPE'} eq 'ARK';
+
+ return 0 unless $self->test(sub {$count <= $mob->{'COUNT'} and
+ $mob->{'AVAILABLE'} eq 'Y'},
+ 'MSG_NOT_ENOUGH_MOBILES',
+ 'MOVE',
+ $count,
+ $mob->{'LOCATION'});
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# MOVE_WITH
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $args = $self->{-args};
+
+ $self->move_with($args->{'MOBILE'},$args->{'TARGET'},$args->{'COUNT'});
+
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("MOVE_WITH should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of MOVE_WITH
+#
+####################################################
+
+##########################################################
+#
+# SEND_MSG
+#
+
+# TODO: should be in FROGS/Command.pm
+
+package SEND_MSG;
+@SEND_MSG::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('OTHER','MESSAGE');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# MOVE_WITH
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $args = $self->{-args};
+
+ Util::log("send message from $self->{-player} to $args->{'OTHER'}.",1);
+
+ my $msg = $args->{'MESSAGE'};
+
+ # uggly workaround necessary for Command::parse_args()
+ $msg =~ s/__COMMA__/,/g;
+ $msg =~ s/__EQUAL__/=/g;
+ # newline should be in html
+ $msg =~ s/\\r\\n/<br>/g;
+
+ $self->{-context}->send_message_to($args->{'OTHER'},
+ {'MFROM' => $self->{-player},
+ 'MSG_TEXT' => $msg});
+
+ return 0;
+}
+
+# this is called from scheduler when the command will be executed
+sub second_phase{
+ my $self = shift;
+ Util::log("SEND_MSG should not have a second phase!",0);
+ return 0;
+}
+
+#
+# End of SEND_MSG
+#
+####################################################
+
+##########################################################
+#
+# FIGHT_GOD
+#
+
+package FIGHT_GOD;
+use Data::Dumper;
+@FIGHT_GOD::ISA = qw(AymCommand);
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('A','B');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ my $A = $self->{-args}->{'A'};
+ my $B = $self->{-args}->{'B'};
+ my $loc = $self->{-dbhash}->{'LOCATION'};
+
+ # dont accept a new FIGHT_GOD if there is allready a fight between the same gods
+ my $fights = $self->{-db}->select_array('COMMAND','ARGUMENTS',
+ "GAME=$self->{-game} AND ".
+ "COMMAND=FIGHT_GOD AND ".
+ "ID != $self->{-dbhash}->{'ID'} AND ".
+ "LOCATION=$loc");
+ for my $f (@$fights){
+ my $args = $self->parse_args($f->[0]);
+
+ if( $args->{'A'} == $A and $args->{'B'} == $B){
+ Util::log("there is allready such a fight between $A and $B in $loc.",1);
+ return 0;
+ }
+ }
+
+ # could not work, command can be inserted from earthling.
+ # return 0 unless $self->validate_role('GOD');
+
+ # return 0 unless $self->validate_this_role($self->{-args}->{'A'},'GOD');
+ # return 0 unless $self->validate_this_role($self->{-args}->{'B'},'GOD');
+
+ return 1;
+}
+
+# this is called from Scheduler, if he sees the command the
+# first time, some commands execute here immidiatly.
+# FIGHT_GOD
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # calculate duration
+ $self->setDuration($::conf->{-DURATION}->{-FIGHT_GOD});
+
+ # set GOD_ATTACKER in MAP to COMMAND.ID
+ $self->{-db}->update_hash('MAP',
+ "LOCATION=$self->{-location} AND ".
+ "GAME=$self->{-game}",
+ {'GOD_ATTACKER' => $self->{-dbhash}->{'ID'}});
+
+ $self->event($self->{-location},
+ 'EVENT_FIGHT_GOD',
+ $self->{-context}->charname($self->{-args}->{'A'}),
+ $self->{-context}->charname($self->{-args}->{'B'}),
+ );
+
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed.
+# FIGHT_GOD
+sub second_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ # read info from map
+ my ($earthlingfight,$earthling);
+ ($earthlingfight, $self->{-god_attacker}, $earthling) =
+ $self->{-context}->read_field(
+ 'ATTACKER,GOD_ATTACKER,OCCUPANT', $self->{-location}
+ );
+
+ # suspend FIGHT until end of FIGHT_GOD if any
+ # REWRITE: suspend of avatar fight have to be encapsulated
+ if($earthlingfight){
+ ## REWRITE: SQL: sort events up to time, limit output to ONE
+ # read all earthling-events for this field.
+ my @events = @{$self->{-db}->select_array('EVENT','ID,TIME',
+ "GAME=$self->{-game} AND ".
+ "LOCATION=$self->{-location} AND ".
+ "TAG=FIGHT_EARTHLING")};
+ # which one is the latest?
+ my ($late_time, $late_id) = (0,0);
+ for my $ev (@events){
+ my ($id, $time) = @$ev;
+ my $ev_time = &::str2time($time,'GMT');
+ Util::log("found FIGHT_EARTHLING with time $time",1);
+ ($late_time, $late_id) = ($ev_time, $id) if $ev_time > $late_time;
+ }
+
+ # insert new godfight with one second more.
+ # TODO: use here the new AFTER-System instead
+ my ($year,$month,$day, $hour,$min,$sec) = &::Time_to_Date($late_time + 1);
+ $late_time = sprintf ("%04u-%02u-%02u %02u:%02u:%02u",
+ $year,$month,$day, $hour,$min,$sec);
+ Util::log("found earthling fight! suspend godfight until $late_time",1);
+ $self->{-context}->insert_command('FIGHT_GOD',
+ "A=$self->{-args}->{'A'}, ".
+ "B=$self->{-args}->{'B'}",
+ $self->{-location},
+ $self->{-player},
+ $late_time);
+ $self->{-db}->update_hash('EVENT',
+ "COMMAND_ID=$self->{-dbhash}->{'ID'}",
+ {'TIME' => $late_time});
+ $self->stop_fight();
+ return 0;
+ }
+
+ # get all mobiles here
+ my $mobiles = $self->{-context}->read_mobile_condition(
+ 'ID,OWNER,COUNT,TYPE',
+ "LOCATION=$self->{-location} "."AND AVAILABLE=Y"
+ );
+ $self->{-mobiles} = $mobiles;
+
+ my $A = $self->{-args}->{'A'};
+ my $B = $self->{-args}->{'B'};
+ my ($avatars_A, $avatars_B) = (0,0);
+
+ # for every avatar-unit in the field
+ # REWRITE: this block tries to count the opposing avatars: simplify!
+ for my $a (@$mobiles){
+ my ($id,$own,$count,$type) = @$a;
+ next unless $type eq 'AVATAR';
+
+ Util::log("found $count avatar(s) from $own with id $id",1);
+
+ # determine side of owner
+ my $side = $self->which_side($own);
+
+ # calculate strength_of_side
+ if($side eq 'A'){
+ $avatars_A += $count;
+ }elsif($side eq 'B'){
+ $avatars_B += $count;
+ }
+ }
+
+ my $mana = $::conf->{-MANA}->{-FIGHT_AVATAR};
+ my $mana_A = $self->instant_use_mana($mana,$A);
+ my $mana_B = $self->instant_use_mana($mana,$B);
+ my $strength_A = $avatars_A * $::conf->{-FIGHT}->{-AVATAR};
+ my $strength_B = $avatars_B * $::conf->{-FIGHT}->{-AVATAR};
+
+ # TODO?: message in this case
+ unless($mana_A >= $mana){
+ Util::log("$A has not enough mana left to fight",1);
+ $strength_A = 0;
+ };
+ unless($mana_B >= $mana){
+ Util::log("$B has not enough mana left to fight",1);
+ $strength_B = 0;
+ };
+
+ # swl: Strength_Without_Luck strenght_X: Strenght_with_luck
+ my ($swlA,$swlB) = ($strength_A,$strength_B);
+
+ # add random value (1 to GAME.FORTUNE)
+ my $fortune = $self->{-context}->read_fortune();
+ Util::log("avatarfight in $self->{-location}: strength without fortune player $A: ".
+ "$strength_A, player $B: $strength_B",1);
+ $strength_A += int(rand($fortune))+1;
+ $strength_B += int(rand($fortune))+1;
+ Util::log("strength with fortune player $A: ".
+ "$strength_A, player $B: $strength_B",1);
+
+ # how much avatars should die?
+ my ($dead_A,$dead_B) = (0,0);
+ my ($winner,$looser) = (0,0);
+
+ if( ($strength_A > $strength_B && $mana_A) or
+ $mana_A && !$mana_B )
+ {
+ Util::log("$A wins!",1);
+ $winner = $A; $looser = $B;
+ ($dead_A, $dead_B) = _calc_dead_avatars($avatars_A, $avatars_B);
+ }
+ elsif( ($strength_B > $strength_A && $mana_B) or
+ $mana_B && !$mana_A )
+ {
+ Util::log("$B wins!",1);
+ $winner = $B; $looser = $A;
+ ($dead_B, $dead_A) = _calc_dead_avatars($avatars_B, $avatars_A);
+ }
+ else
+ {
+ Util::log("Both sides looses!",1);
+ ($dead_A, $dead_B) = _calc_dead_avatars($avatars_A, $avatars_B, 'drawn');
+ }
+
+ my ($new_heros_A, $new_heros_B) = (0,0);
+ $new_heros_A = $self->die($A, $dead_A, $earthling) if $dead_A;
+
+ # re-read mobiles
+ $self->{-mobiles} = $self->{-context}->
+ read_mobile_condition('ID,OWNER,COUNT,TYPE',
+ "LOCATION=$self->{-location} ".
+ "AND AVAILABLE=Y");
+
+ $new_heros_B = $self->die($B,$dead_B,$earthling) if $dead_B;
+
+ # surviving loosers go home
+ if($looser){
+ $self->teleport($looser);
+ }else{
+ # both sides are looser!
+ $self->teleport($A);
+ $self->teleport($B);
+ }
+
+ $self->stop_fight();
+
+ my $earthling_name = $self->{-context}->charname($earthling);
+ my $name_of_A = $self->{-context}->charname($A);
+ my $name_of_B = $self->{-context}->charname($B);
+ my $asf = $strength_A - $swlA;
+ my $dsf = $strength_B - $swlB;
+ $winner = $winner ? $self->{-context}->charname($winner) : 'NOBODY';
+
+ my $text = <<END_OF_TEXT;
+ <strong>BATTLE_REPORT $self->{-location}</strong><br>
+ <table><tr><th></th><th>$name_of_A</th><th>$name_of_B</th></tr>
+ <tr><td>MOBILE_AVATAR_PL</td><td>$avatars_A</td><td>$avatars_B</td></tr>
+ <tr><td>FIGHTING_STRENGTH</td><td>$swlA</td>
+ <td>$swlB</td></tr>
+ <tr><td>LUCK</td><td>$asf</td><td>$dsf</td></tr>
+ <tr><td>SUM_OF_STRENGTH</td><td>$strength_A</td><td>$strength_B</td></tr>
+ <tr><td>DEAD_AVATARS</td><td>$dead_A</td>
+ <td>$dead_B</td></tr>
+ <tr><td>NEW_HEROS $earthling_name</td><td>$new_heros_A</td>
+ <td>$new_heros_B</td></tr>
+ </table>
+ <strong>WINNER_IS $winner</strong>.
+END_OF_TEXT
+
+ $self->{-context}->send_message_to_field(
+ $self->{-location},
+ {'MFROM' => 0, 'MSG_TEXT' => $text}
+ );
+}
+
+# _calc_dead_avatars
+# Calculates number of dead avatars on winner's and looser's side.
+#
+# Parameters:
+# - # winner avatars
+# - # looser avatars
+# - drawn [OPTIONAL, boolean]
+#
+# Returns:
+# - # dead winner avatars
+# - # dead looser avatars
+#
+sub _calc_dead_avatars
+{
+ my ($winner, $looser, $drawn) = @_;
+ my ($dead_winner, $dead_looser) = (0,0);
+
+ # the winner counts as looser if the fight is drawn!
+ if (defined $drawn && $drawn)
+ {
+ $dead_winner = Util::max(
+ 1,
+ int(0.5 + $looser / $::conf->{-LOOSER_AVATARS_DYING_FRACTION})
+ );
+ }
+ else
+ {
+ $dead_winner = Util::min(
+ $winner - 1,
+ int(0.5 + $looser / $::conf->{-WINNER_AVATARS_DYING_FRACTION})
+ );
+ }
+
+ $dead_looser = Util::max(
+ 1,
+ int(0.5 + $winner / $::conf->{-LOOSER_AVATARS_DYING_FRACTION})
+ );
+
+ # ensure that there not dying more avatars than existing
+ $dead_looser = $dead_looser > $looser ? $looser : $dead_looser;
+ $dead_winner = $dead_winner > $winner ? $winner : $dead_winner;
+
+ return ($dead_winner, $dead_looser);
+}
+
+
+
+# set MAP.GOD_ATTACKER to 0, if there is our own command-ID
+sub stop_fight{
+ my($self) = @_;
+
+ my $own_command = $self->{-dbhash}->{'ID'};
+ if($own_command == $self->{-god_attacker}){
+ $self->{-db}->update_hash('MAP',
+ "LOCATION=$self->{-location} AND ".
+ "GAME=$self->{-game}",
+ {'GOD_ATTACKER' => 0});
+ }
+}
+
+
+# teleports all of $god from $loc to location of avatar-creation
+sub teleport{
+ my($self,$god) = @_;
+ my $loc = $self->{-location};
+
+ # teleport surviving avatars of looser to home
+ my $home = $self->{-context}->incarnation_place($god);
+ Util::log("We teleport all Avatars of $god from $loc to $home.",1);
+
+ $self->{-db}->update_hash('MOBILE',
+ "TYPE=AVATAR AND OWNER=$god AND AVAILABLE=Y AND ".
+ "LOCATION=$self->{-location}",
+ {'LOCATION' => $home});
+
+ # get all avatar there
+ my $avatars = $self->{-context}->read_mobile_condition('ID',
+ "LOCATION=$home ".
+ "AND OWNER=$god ".
+ "AND TYPE=AVATAR ".
+ "AND AVAILABLE=Y");
+ # dont call this more than one time!
+ #for my $avat (@$avatars){
+ my ($id) = $avatars->[0]->[0];
+ $self->enter_field_avatar($home,$id);
+ #}
+}
+
+
+# kills $to_kill avatars of owner in location and create heros for earthling,
+# if possible
+sub die{
+ my ($self,$owner,$to_kill,$earthling) = @_;
+ Util::log("$to_kill avatars from $owner dying.",1);
+
+ my $loc = $self->{-location};
+ my $mobiles = $self->{-mobiles};
+
+ my $to_hero = $to_kill;
+ my $real_to_hero = 0;
+ for my $a (@$mobiles){
+ my ($id,$own,$count,$type) = @$a;
+ if($own eq $owner and $to_kill){
+ if($count <= $to_kill){
+ $self->{-db}->delete_from('MOBILE', "ID=$id");
+ $to_kill -= $count;
+ # last unless $to_kill > 0;
+ }else{
+ $self->{-db}->update_hash('MOBILE', "ID=$id", {'COUNT' => ($count - $to_kill)});
+ $to_kill = 0;
+ # last;
+ }
+ # add the strength of the death avatar to gods last battle
+ #my ($actual) = $self->{-db}->single_select("SELECT DEATH_AVATAR FROM GOD WHERE ".
+ #"GAME=$self->{-game} AND ".
+ # # "PLAYER=$owner");
+ # Util::log("AVATAR dying: adds strength to last-battle-strength of $owner",1);
+ # $self->{-db}->update_hash('GOD',
+ # "GAME=$self->{-game} AND PLAYER=$owner",
+ # {'DEATH_AVATAR' => $actual + 1});
+
+ # $self->{-context}
+ # ->send_message_to
+ # ($loc,$owner,
+ # {'MFROM' => 0,
+ # 'MSG_TAG' => 'MSG_AVATAR_DEAD',
+ # 'ARG1' => $loc,
+ # 'ARG2' => $self->{-context}->charname($owner)});
+ # Util::log("One avatar of $owner died in $loc.",1);
+ # last;
+ }elsif($own eq $earthling and $type eq 'WARRIOR' and $to_hero){
+ if($count <= $to_hero){
+ $self->{-db}->delete_from('MOBILE', "ID=$id");
+ $to_hero -= $count;
+ $real_to_hero += $count;
+ # last unless $to_hero > 0;
+ }else{
+ $self->{-db}->update_hash('MOBILE', "ID=$id", {'COUNT' => $count-$to_hero});
+ $real_to_hero += $to_hero;
+ $to_hero = 0;
+ # last;
+ }
+ }
+ last if $to_kill <= 0 and $to_hero <= 0;
+ }
+
+ if($real_to_hero){
+ my $id = $self->{-db}->find_first_free('MOBILE','ID');
+ my $mob = {'ID' => $id,
+ 'GAME' => $self->{-game},
+ 'LOCATION' => $self->{-location},
+ 'TYPE' => 'HERO',
+ 'OWNER' => $earthling,
+ 'COUNT' => $real_to_hero,
+ 'ADORING' => $owner,
+ 'AVAILABLE' => 'Y',
+ 'COMMAND_ID' => $self->{-dbhash}->{'ID'},
+ };
+ # $self->{-mob} = $mob;
+ my %mobcopy = (%$mob);
+ $self->{-db}->insert_hash('MOBILE',\%mobcopy);
+ $self->unify_mobiles($id,$self->{-location},$earthling);
+ Util::log("$real_to_hero warriors from $earthling blessed to hero",1);
+ }
+ return $real_to_hero;
+}
+
+# this function decides on which side other gods fight
+# TODO: do we really need this complicated stuff
+sub which_side{
+ my($self,$own) = @_;
+
+ my $A = $self->{-args}->{'A'};
+ my $B = $self->{-args}->{'B'};
+
+ my $side = '0';
+ $side = 'A' if $own == $A;
+ $side = 'B' if $own == $B;
+
+ if ($side eq '0') {
+ my $allA = $self->{-context}->simplyfied_single_relation($own,$A);
+ my $allB = $self->{-context}->simplyfied_single_relation($own,$B);
+ if ($allA eq $allB) {
+ $side = '0';
+ } elsif ($allA eq 'FRIEND') {
+ $side = 'A';
+ } elsif ($allB eq 'FRIEND') {
+ $side = 'B';
+ } elsif ($allA eq 'FOE') {
+ $side = 'B';
+ } elsif ($allB eq 'FOE') {
+ $side = 'A';
+ }
+ }
+ return $side;
+}
+
+#
+# End of FIGHT_GOD
+#
+####################################################
+
+##########################################################
+#
+# PLAGUE
+#
+
+package PLAGUE;
+@PLAGUE::ISA = qw(AymCommand);
+use Data::Dumper;
+
+# this is called to see if the command is executable.
+# it should be called from first_phase() and from second_phase().
+# it is not called from the scheduler
+sub is_valid {
+ my $self = shift;
+
+ my @required_arguments = ('TYPE');
+ return 0 unless $self->Command::is_valid(@required_arguments);
+
+ # test role god
+ return 0 unless $self->validate_role('GOD');
+
+ # test known plagues
+ unless(Util::is_in($self->{-args}->{'TYPE'},@{$::conf->{-PLAGUES}})){
+ Util::log("wrong type of plague: $self->{-args}->{'TYPE'}",0);
+ return 0;
+ }
+
+ return 1;
+}
+
+# this is called from Scheduler, if he see the command the
+# first time, some commands execute here immidiatly.
+# PLAGUE
+sub first_phase{
+ my $self = shift;
+
+ return 0 unless $self->is_valid();
+
+ my $args = $self->{-args};
+ my $loc = $self->{-dbhash}->{'LOCATION'};
+ my $type = $args->{'TYPE'};
+ my $spread = $args->{'SPREAD'};
+ my $context = $self->{-context};
+
+ my ($plague,$terrain) = $context->read_field('PLAGUE,TERRAIN', $loc);
+ $plague = '' unless defined $plague;
+
+ Util::log("old plague: $plague",1);
+
+ # if plagu not allready here
+ unless($plague =~ /$type/){
+
+ if(not $spread){
+ # need own avatar to plague
+ return 0 unless $self->avatar_available($loc);
+
+ if($self->test_mana($type,1)){
+ $self->use_mana();
+ }else{
+ return 0;
+ }
+ }
+ Util::log("new plague in $loc: $type",1);
+
+ # set plague in MAP
+ my $new_plague = $plague ? "$plague,$type" : $type;
+ $self->{-db}->update_hash('MAP',
+ "GAME=$self->{-game} AND ".
+ "LOCATION=$loc",
+ {'PLAGUE' => $new_plague});
+ }else{
+ Util::log("plague $type is allready in $loc.",1);
+ # stop if there is another plague command in location of same type.
+ # TODO: simplify this with a LIKE-clause,
+ # but: we have to rewrite quote_condition() first :-(
+ my $commands = $self->{-db}->select_array('COMMAND',
+ 'ARGUMENTS,ID',
+ "COMMAND=PLAGUE AND ".
+ "GAME=$self->{-game} AND ".
+ "LOCATION=$loc AND ".
+ "ID != $self->{-dbhash}->{'ID'}");
+ for my $c (@$commands){
+ my ($args,$id) = @$c;
+ # next if $id == $self->{-dbhash}->{'ID'};
+ if($args =~ /$type/){
+ Util::log("There is allready another PLAGUE-command of $type in $loc",1);
+ return 0;
+ }
+ }
+ }
+
+ $self->setDuration($::conf->{-DURATION}->{-PLAGUE});
+ return $self->{-duration};
+}
+
+# this is called from scheduler when the command will be executed
+# PLAGUE
+sub second_phase{
+ my $self = shift;
+ my $loc = $self->{-dbhash}->{'LOCATION'};
+ my $type = $self->{-args}->{'TYPE'};
+ my $context = $self->{-context};
+
+ # heal plague with priests
+ my $priests = $context->count_mobile('PRIEST',$loc);
+ my $heal_prob = $priests ? 1 - 1/$priests * $::conf->{-HEAL_PLAGUE} : 0;
+ Util::log("Heal probability: $heal_prob",1);
+ if($heal_prob > rand(1)){
+ Util::log("heal plague of type $type in $loc",1);
+ my ($plague) = $context->read_field('PLAGUE,TERRAIN', $loc);
+ if(defined $plague){
+ $plague =~ s/$type//;
+ $self->{-db}->update_hash('MAP',
+ "GAME=$self->{-game} AND LOCATION=$loc",
+ {'PLAGUE' => $plague});
+ }
+ }else{
+ # spread plague to neighbour-fields
+ my @neighbours = $self->get_neighbours();
+ for my $field (@neighbours){
+ my ($terrain,$owner) = $context->read_field('TERRAIN,OCCUPANT',$field);
+ # $self->{-occ} = $owner;
+ if(rand(1) < $::conf->{-SPREAD_PLAGUE}->{$terrain}){
+ Util::log("spread $type from $loc to $field",1);
+ $context->insert_command('PLAGUE',"TYPE=$type, SPREAD=1",$field);
+ }
+ }
+
+ $self->effect();
+ $self->do_it_again({'SPREAD' => 1});
+ }
+
+ return 0;
+}
+
+# PLAGUE
+sub effect{
+ my $self = shift;
+ my $context = $self->{-context};
+
+ my $type = $self->{-args}->{'TYPE'};
+ Util::log("Do effect of type $type.",1);
+
+ my $loc = $self->{-dbhash}->{'LOCATION'};
+
+ # effect of INFLUENZA is done in PRODUCE
+ if($type eq 'PESTILENTIA'){
+ my ($vic) = $context->read_field('OCCUPANT',$loc);;
+
+ # count people of owner in field
+ my $people = $context->count_people($loc,$vic);
+ $people = 0 unless defined $people;
+ Util::log("$people people from $vic counted in $loc.",1);
+ my $victims = int($people * $::conf->{-PESTILENTIA_DEATH_SHARE});
+ Util::log("$victims from them have to die.",1);
+ return unless $victims;
+
+ $self->{-mobiles} = $context->read_mobile('ID,TYPE,OWNER,COUNT,STATUS',
+ 0, $self->{-location}, 1);
+
+ $self->casualties($vic,$victims,1);
+
+ # send message
+ my $name_of_victim = $context->charname($vic);
+ my $text = <<END_OF_TEXT;
+ <strong>CASUALTIES_OF_PESTILENTIA $self->{-location} $name_of_victim</strong><br>
+ <table><tr><th></th><th></th></tr>
+ <tr><td>DEAD_WARRIORS</td><td>$self->{-dead}->{$vic}->{'K'}</td></tr>
+ <tr><td>DEAD_HEROS</td><td>$self->{-dead}->{$vic}->{'H'}</td></tr>
+ <tr><td>DEAD_PRIESTS</td><td>$self->{-dead}->{$vic}->{'P'}</td></tr>
+ <tr><td>SUNKEN_ARKS</td><td>$self->{-dead}->{$vic}->{'A'}</td></tr>
+ </table>
+END_OF_TEXT
+
+ $context->send_message_to_field
+ ($self->{-location},{'MFROM' => 0,
+ 'MSG_TEXT' => $text}
+ # 'ARG1' => $self->{-context}->charname($attacker),
+ # 'ARG2' => $self->{-context}->charname($defender),
+ # 'ARG3' => $self->{-context}->charname($self->{-winner}),
+ # 'ARG4' => $self->{-location}}
+ );
+ #,$attacker,$defender,@gods);
+ }else{
+ Util::log("no effect",1);
+ }
+}
+
+#
+# End of PLAGUE
+#
+####################################################
+# vim: set ts=4
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+# generell Aymargeddon-specific functions
+#
+
+
+# TODO: move color calculation from map.epl in this module
+
+
+use strict;
+use FROGS::Game;
+use FROGS::HexTorus;
+
+package Aymargeddon;
+use Data::Dumper;
+@Aymargeddon::ISA = qw(Game);
+
+sub new{
+ my ($class,$game,$user,$db,$lang) = @_;
+
+ my $self = Game->new($game,$user,$db);
+
+ bless($self,$class);
+}
+
+sub get_map{
+ my $self = shift;
+
+ unless (exists $self->{-map}){
+ $self->{-map} = $self->read_map("TERRAIN,HOME,OCCUPANT,TEMPLE,PLAGUE,HOME");
+ }
+ return $self->{-map};
+}
+
+sub get_size{
+ my $self = shift;
+
+ unless ($self->{-size}){
+ my @size = $self->{-db}->read_game($self->{-game},'SIZE');
+ $self->{-size} = $size[0] ? $size[0] : die "could not find size";
+ }
+ return $self->{-size};
+}
+
+sub get_relation{
+ my ($self, $other) = @_;
+
+ unless ($self->{-rel}){
+ # print "bindrin\n";
+ # $self->{-rel} = $self->read_player_relations($self->{-game}, $self->{-user});
+ $self->{-rel} = $self->read_player_relations($self->{-user});
+ }
+ # print Dumper $self->{-rel};
+ my $stat = $self->{-rel}->{$other}->{'STATUS'};
+ return $stat ? $stat : 'NEUTRAL';
+}
+
+# FRIEND, ALLIED => FRIEND ; FOE, BETRAY => FOE
+sub simplyfied_single_relation{
+ my ($self,$me,$you) = @_;
+ my $rel = $self->read_single_relation($me,$you);
+
+ return 'FRIEND' if Util::is_in($rel,'FRIEND','ALLIED');
+ return 'FOE' if Util::is_in($rel,'FOE','BETRAY');
+ return 'NEUTRAL';
+}
+
+
+sub god_fight{
+ my ($self,$loc_str) = @_;
+ my @ret = $self->read_field('GOD_ATTACKER',$loc_str);
+ return $ret[0] ? 1 : 0;
+}
+
+sub earthling_fight{
+ my ($self,$loc_str) = @_;
+ my @ret = $self->read_field('ATTACKER',$loc_str);
+ return $ret[0] ? 1 : 0;
+}
+
+sub arc_present{
+ my ($self,$loc_str) = @_;
+ my $arks_ref = $self->read_mobile('ID','ARK',$loc_str,1);
+ my @arks = @$arks_ref;
+ return $#arks+1;
+}
+
+sub avatar_present{
+ my ($self,$loc_str) = @_;
+ return $self->read_mobile('OWNER','AVATAR',$loc_str,1);
+}
+
+sub mobiles_available{
+ my ($self,$loc_str,$avail) = @_;
+ $avail = 1 unless defined $avail;
+ my $fields = 'ID, TYPE, OWNER, ADORING, COUNT, STATUS, MOVE_WITH';
+ return $self->read_mobile($fields,'',$loc_str, $avail);
+}
+
+
+#
+# sight stuff
+#
+# TODO: maybe the generell sight-stuff could go to Game.pm
+
+# ATTENTION: this function generates the whole sight-matrix, if necessary.
+# it could be very time-consuming
+sub player_see_field{
+ my ($self,$loc) = @_;
+
+ my @players = $self->get_all_roles();
+
+ my @ret = ();
+ for my $player (@players){
+ # ($player) = @$player;
+ my $players_aym = new Aymargeddon($self->{-game},$player,
+ $self->{-db},$self->{-lang});
+ if ($players_aym->sight_of_field($loc)){
+ push @ret, $player;
+ # print "$player sees $loc.\n";
+ }
+ }
+ return @ret;
+}
+
+# this two functions reads sight directly from database
+sub sight_of_field{
+ my ($self,$loc) = @_;
+
+ return 1 if $self->role($self->{-user}) eq 'OBSERVER'; # admin sees all
+
+ my $player = $self->{-user};
+ my $map = HexTorus->new($self->get_size());
+ return 1 if $self->sight_of_field_of_player($loc,$player,$map);
+
+ # read all players, which give us informations
+ my $rel = $self->reverse_player_relations();
+ for my $friend (keys %$rel){
+ my $status = $rel->{$friend}->{'STATUS'};
+ if($status eq 'ALLIED' or $status eq 'BETRAY'){
+ if($self->is_earthling($friend) or $::conf->{-GODS_SHOW_EARTHLINGS}){
+ return 1 if $self->sight_of_field_of_player($loc,$friend,$map);
+ }
+ }
+ }
+ return 0;
+}
+
+sub sight_of_field_of_player{
+ my ($self,$loc,$player,$map) = @_;
+
+ my ($ter,$own,$occ,$temple) = $self->read_field('TERRAIN,HOME,OCCUPANT,TEMPLE',$loc);
+
+ return 1 if($own == $player or $occ == $player);
+ return 1 if @{$self->own_in_mobile($loc,$player)};
+
+ my $location = Location->from_string($loc);
+ my $dist = 2;
+ my @neighbours = $map->distant_neighbours($location,$dist);
+ # Util::log("neighbours: ",-2);
+ for my $l (@neighbours){
+ my $d = $map->distance($location,$l);
+ my $locstring = $l->to_string();
+ # Util::log(" $locstring ($d),",-2);
+
+ my ($neighbour_ter,$neighbour_home) = $self->read_field('TERRAIN,HOME',$locstring);
+ next if ($d > 1 && $neighbour_ter ne 'MOUNTAIN');
+ return 1 if $neighbour_home == $player;
+ return 1 if $neighbour_ter eq 'MOUNTAIN' and
+ $neighbour_home <= 0 and $self->is_god($player);
+ return 1 if @{$self->own_in_mobile($locstring,$player)};
+ }
+ # Util::log("",2);
+ return 0;
+}
+
+# this function generates the whole sight if called
+sub sight{
+ my ($self,$loc_str) = @_;
+
+ return 1 if $self->role($self->{-user}) eq 'OBSERVER'; # admin sees all
+
+ $self->generate_sight() unless $self->{-sight_map};
+
+ return 1 if $self->{-sight_map}->{$loc_str};
+}
+
+# overloads the function from Game-Class
+sub seen_locations{
+ my $self = shift;
+
+ # TODO-PERFORMANCE: make map a self-constructing member of class (like size)
+ my $map = HexTorus->new($self->get_size());
+
+ my @ret = ();
+ for my $loc ($map->get_all()){
+ my $ls = $loc->to_string();
+ push @ret, $ls if $self->sight($ls);
+ }
+ return @ret;
+}
+
+sub generate_sight{
+ my ($self) = @_;
+
+ delete $self->{-sight_map};
+
+ my $rel = $self->reverse_player_relations();
+
+ $self->sight_of_player($self->{-user});
+ for my $player (keys %$rel){
+ my $status = $rel->{$player}->{'STATUS'};
+ if($status eq 'ALLIED' or $status eq 'BETRAY'){
+ if($self->is_earthling($player) or $::conf->{-GODS_SHOW_EARTHLINGS}){
+ $self->sight_of_player($player);
+ }
+ }
+ }
+
+ # print Dumper $self->{-sight_map};
+}
+
+sub sight_of_player{
+ my ($self,$player) = @_;
+
+ my $map = HexTorus->new($self->get_size());
+
+ my $selfmap = $self->get_map();
+
+ for my $row (@$selfmap){
+ my ($loc,$ter,$own,$occ,$temple,$plague,$home) = @$row;
+
+ if($own == $player or $occ == $player
+ or @{$self->own_in_mobile($loc,$player)}
+ or ($self->is_god($player) and $ter eq 'MOUNTAIN' and $home <= 0)){
+ $self->{-sight_map}->{$loc} = 1;
+ my $location = Location->from_string($loc);
+ my $dist = 1;
+ $dist = 2 if $ter eq 'MOUNTAIN';
+ my @neighbours = $map->distant_neighbours($location,$dist);
+ for my $l (@neighbours){
+ $self->{-sight_map}->{$l->to_string()} = 1;
+ }
+ }
+ }
+}
+
+sub is_coast{
+ my ($self,$loc_str) = @_;
+ my ($ter) = $self->read_field('TERRAIN',$loc_str);
+ return 0 if($ter ne 'PLAIN' and $ter ne 'CITY' and $ter ne 'MOUNTAIN');
+
+ my $map = HexTorus->new($self->get_size());
+ my @neighbours = $map->neighbours(Location->from_string($loc_str));
+ for my $loc (@neighbours){
+ ($ter) = $self->read_field('TERRAIN',$loc->to_string());
+ return 1 if($ter eq 'ISLE' or $ter eq 'WATER');
+ }
+ return 0;
+}
+
+sub is_arrival{
+ my ($self, $loc_str) = @_;
+
+ return 1 if $loc_str eq $self->incarnation_place();
+
+ return 0;
+}
+
+sub is_god{
+ my ($self,$player) = @_;
+ $player = $self->{-user} unless defined $player;
+ return ($self->role($player) eq 'GOD');
+}
+
+sub is_earthling{
+ my ($self,$player) = @_;
+ $player = $self->{-user} unless defined $player;
+ return ($self->role($player) eq 'EARTHLING');
+}
+
+sub gods{
+ my ($self) = @_;
+ return $self->get_all_roles('GOD');
+}
+
+sub earthlings{
+ my ($self) = @_;
+ return $self->get_all_roles('EARTHLING');
+}
+
+sub get_mana{
+ my ($self,$player) = @_;
+ $player = $self->{-user} unless defined $player;
+ return 0 if $player < 1;
+
+ my $stmt = "SELECT MANA from GOD where GAME=$self->{-game} AND PLAYER=$player";
+ my ($mana) = $self->{-db}->single_select($stmt);
+ return $mana ? $mana : 0;
+}
+
+sub gender{
+ my ($self,$player) = @_;
+ return 0 if $player < 1;
+ my @gen = $self->read_role($player, 'GENDER');
+ return $gen[0];
+}
+
+
+sub field_string{
+ my ($self, $type) = @_;
+ return $self->{-db}->loc('FIELD_'.$type);
+}
+
+sub relation_string{
+ my ($self, $other) = @_;
+ my $rel = $self->get_relation($other);
+ # print Dumper $rel;
+ $rel = 'NEUTRAL' if not $rel;
+ return $self->{-db}->loc('STAT_'.$rel);
+}
+
+sub mobile_string{
+ my ($self, $type, $num) = @_;
+ my $tag = 'MOBILE_'.$type;
+ $tag .= '_PL' if $num != 1;
+ return $self->{-db}->loc($tag);
+}
+
+sub mobile_extended_string{
+ # count + localised type + adored god if any
+ my ($self, $type, $num, $adoring) = @_;
+ my $out = $num.' '.$self->mobile_string($type, $num);
+ if($type eq 'PRIEST' or $type eq 'PROPHET' or $type eq 'HERO'){
+ $out .= ' '.$self->{-db}->loc('ADJ_ADORING').' '.$self->charname($adoring);
+ }
+ return $out;
+}
+
+sub role_string{
+ my ($self, $player) = @_;
+ my $role = $self->role($player);
+ $role = 'UNDEFINED' unless defined $role;
+ my $tag = "ROLE_$role";
+ return $self->{-db}->loc($tag);
+}
+
+
+sub new_role{
+ my($self,$role,$name,$gender,$desc) = @_;
+ $desc = 'none' unless defined $desc;
+ my $db = $self->{-db};
+
+# my ($qname, $qgender, $qdesc, $qrole)
+# = $db->quote_all($name, $gender, $desc, $role);
+
+ my $cond = 'GAME='.$self->{-game}." AND NICKNAME=$name";
+ return 0 if @{$db->select_array('ROLE','GAME',$cond)}; # error: dublicate name
+
+ my @homes; # all possible homes for this role
+ if($role ne 'OBSERVER'){
+ @homes = $self->open_homes($role);
+ return 0 if $#homes<0; # error: no home free
+ }
+
+ # dont allow names only in uppercase
+ return 0 if $name =~ /^\s*[A-Z_]{3,}\s*$/;
+
+ # write in ROLE
+ $db->insert_hash('ROLE',{'GAME' => $self->{-game},
+ 'PLAYER' => $self->{-user},
+ 'NICKNAME' => $name,
+ 'ROLE' => $role,
+ 'GENDER' => $gender,
+ 'DESCRIPTION' => $desc}
+ );
+ if($role eq 'OBSERVER'){
+ $db->commit();
+ return 1;
+ }
+
+ # choose home:
+ my $home = $homes[rand($#homes + 1)]->[0];
+
+ if($role eq 'GOD'){
+ # read actual default manapool from GAME
+ my ($mana,$ts) = $db->read_game($self->{-game},'START_MANA,TEMPLE_SIZE');
+ $mana += $ts * 2;
+
+ # write GAME, PLAYER, MANA in GOD
+ $db->insert_hash('GOD',{'GAME' => $self->{-game},
+ 'PLAYER' => $self->{-user},
+ 'MANA' => $mana});
+
+ # choose second and third home
+ # my $home2 = $home;
+ # my $home3 = $home;
+ # if($#homes > 0){
+ # while($home2 eq $home or $home3 eq $home or $home2 eq $home3){
+ # $home2 = $homes[rand($#homes + 1)]->[0];
+ # $home3 = $homes[rand($#homes + 1)]->[0];
+ # }
+ # }
+
+ # # change OWNER in MAP where LOCATION=$home or LOCATION=$home2
+ # # ($home,$home2) = $db->quote_all($home,$home2);
+ # $db->update_hash('MAP',
+ # "GAME=$self->{-game} AND".
+ # " (LOCATION=$home OR LOCATION=$home2 OR LOCATION=$home3)",
+ # {'HOME' => $self->{-user}});
+
+ }else{ # eartling
+ # write GAME, PLAYER in EARTHLING
+ $db->insert_hash('EARTHLING',{'GAME' => $self->{-game},
+ 'PLAYER' => $self->{-user}});
+
+ # change OCCUPANT, OWNER in MAP where LOCATION=$home
+ # ($home) = $db->quote_all($home);
+ $db->update_hash('MAP',
+ "GAME=$self->{-game} AND LOCATION=$home",
+ {'HOME' => $self->{-user},
+ 'OCCUPANT' => $self->{-user}});
+
+ # change PLAYER of WARRIORS OR PRIESTs in MOBILE where LOCATION=$home
+ $db->update_hash('MOBILE',
+ "GAME=$self->{-game} AND LOCATION=$home AND OWNER=-1",
+ {'OWNER' => $self->{-user}});
+
+ # give additional start-warriors
+ my $warriors = $db->select_array('MOBILE',
+ 'ID,COUNT',
+ "GAME=$self->{-game} AND LOCATION=$home ".
+ "AND OWNER=$self->{-user} AND TYPE=WARRIOR");
+ my @w = @$warriors;
+ if($#w > -1){
+ $db->update_hash('MOBILE',
+ "ID=$w[0]->[0]",
+ {'COUNT' => "COUNT + $::conf->{-START_WARRIORS}"},
+ 'noquote');
+ }else{
+ $db->insert_hash('MOBILE',
+ {'ID' => $db->find_first_free('MOBILE','ID'),
+ 'GAME' => $self->{-game},
+ 'LOCATION' => $home,
+ 'TYPE' => 'WARRIOR',
+ 'COUNT' => $::conf->{-START_WARRIORS},
+ 'OWNER' => $self->{-user},
+ 'AVAILABLE' => 'Y'});
+ }
+
+ # modify PRODUCE Command
+ $db->update_hash('COMMAND',
+ "GAME=$self->{-game} AND COMMAND=PRODUCE ".
+ "AND LOCATION=$home",
+ # TODO: open question: is this redundant information?
+ {'PLAYER' => $self->{-user},
+ 'ARGUMENTS' => "ROLE=$self->{-user}"});
+
+ }
+
+ # TODO: write MESSAGE to all members of this game: new player with role!
+
+
+ $db->commit();
+ return 1;
+}
+
+sub startfield{
+ my ($self) = @_;
+
+ my $cond = "GAME=$self->{-game} AND ";
+ if($self->role($self->{-user}) eq 'OBSERVER'){
+ $cond .= 'TERRAIN='.$self->{-db}->quote('AYMARGEDDON');
+ }else{
+ $cond .= "HOME=$self->{-user}";
+ }
+ # TODO: what happens if both mountains are flooded?
+ return $self->{-db}->select_array('MAP','LOCATION',$cond)->[0]->[0];
+}
+
+
+sub open_homes{
+ my ($self,$role) = @_;
+ my $terrain = ($role eq 'GOD') ? 'MOUNTAIN' : 'CITY';
+ # ($terrain) = $self->{-db}->quote_all($terrain);
+ my $cond = 'GAME='.$self->{-game}." AND HOME=-1 AND TERRAIN=$terrain";
+ return @{$self->{-db}->select_array('MAP','LOCATION',$cond)};
+}
+
+sub is_open{
+ my ($self,$terrain) = @_;
+
+ my $cond = "GAME=$self->{-game} AND HOME=-1";
+ if($terrain){
+ $terrain = $self->{-db}->quote($terrain);
+ $cond .= "AND TERRAIN=$terrain";
+ }
+ my $unused = $self->{-db}->select_array('MAP','LOCATION','',$cond);
+ my @arr = @$unused;
+
+ return $#arr+1;
+}
+
+# TODO performance: we can do this whole function in one sophisticated SQL-statement.
+sub incarnation_place{
+ my ($self,$player) = @_;
+ $player = $self->{-user} unless defined $player;
+
+ my $temples = $self->{-db}->select_array('MAP','LOCATION',
+ "TEMPLE='Y' AND HOME=$player");
+
+ my $place;
+ my $max_priests = 0;
+ for my $temple (@$temples){
+ my $loc = $temple->[0];
+ Util::log("check for $loc...",1);
+ # my ($qloc,$type,$yes) = $self->{-db}->quote_all($loc,'PRIEST','Y');
+ my $priests = $self->{-db}->single_hash_select('MOBILE',
+ "ADORING=$player AND ".
+ "LOCATION=$loc AND ".
+ "TYPE=PRIEST AND ".
+ "AVAILABLE=Y AND ".
+ "GAME=$self->{-game}");
+
+ if(defined $priests and $priests->{'COUNT'} > $max_priests){
+ $place = $loc;
+ $max_priests = $priests->{'COUNT'};
+ }
+ }
+ return $place;
+}
+
+sub read_fortune{
+ my $self = shift;
+
+ my ($fortune) = $self->{-db}->read_game($self->{-game},
+ 'FORTUNE');
+ return $fortune;
+}
+
+# returns also empty neighbours, but no attacked neighbours
+sub own_neighbours{
+ my ($self,$loc,$player) = @_;
+ $player = $self->{player} unless defined $player;
+
+ # print "own_neighbours($loc,$player)\n";
+ my $map = HexTorus->new($self->get_size());
+ my $location = Location->from_string($loc);
+ my @neighbours = $map->neighbours($location);
+ my @own_neighbours;
+ for my $n (@neighbours){
+ my $n_string = $n->to_string();
+ my ($occ,$att,$terrain) = $self->read_field('OCCUPANT,ATTACKER,TERRAIN',$n_string);
+ Util::log("$n_string occupied by $occ, attacked by $att",2);
+ next if $att;
+ next if $::conf->{-FIGHTS_WITHOUT_OWNER}->{$terrain} and not $occ;
+ push @own_neighbours, $n_string if $occ == $player or $occ <= 0;
+ }
+ # print Dumper \@own_neighbours;
+ Util::log("own_neighbours($loc,$player): @own_neighbours",2);
+ return @own_neighbours;
+}
+
+sub is_in_direction_from{
+ my($self,$to,$from) = @_;
+
+ my $map = HexTorus->new($self->get_size());
+ my $to_location = Location->from_string($to);
+ my $from_location = Location->from_string($from);
+
+ return $map->get_direction($from_location,$to_location);
+}
+
+sub show_statistic{
+ my($self) = @_;
+ my $db = $self->{-db};
+
+ my @earthlings = $self->get_all_roles('EARTHLING');
+ my @gods = $self->get_all_roles('GOD');
+
+ # show for god: own mana,
+ my $out = '';
+ if($self->is_god()){
+ # own mana
+ $out .= $db->loc('OWN_MANA',$self->get_mana());
+ }
+
+ # show for all: #priests of god (?), #citys of earthling, #temples to build,
+ # speed of game, fortune, last battle, fighting strength of earthlings
+ # #temples of god
+
+ # strength of every god in last battle
+ $out .= $db->loc('LAST_BATTLE_HEADING') . '<p>';
+ for my $god (@gods){
+ # my $god = $god->[0];
+
+ my $strength=$self->strength_in_last_battle($god);
+ $out .= $db->loc('LAST_BATTLE_LINE',$self->charname($god),$strength) . '<br>';
+
+ # TODO?: count priests
+ }
+
+ # count citys
+ $out .= '<p>' . $db->loc('CITY_HEADING'). '<p>';
+ for my $player (@earthlings){
+ # $player = $player->[0];
+ my $citys = $db->count('MAP',
+ "GAME=$self->{-game} AND OCCUPANT=$player AND TERRAIN=CITY");
+ $out .= $db->loc('STATISTIC_EARTHLING_CITY',
+ $self->charname($player),
+ $citys).'<br>';
+ }
+ $out .= '<p>';
+
+ # count temples to build for the end of the world
+ $out .= $db->loc('STATISTIC_UNBUILD', $self->unbuild()). " " .
+ $db->loc('STATISTIC_NEW_TEMPLES', $self->under_construction())."<p>\n";
+
+ my $game = $db->single_hash_select('GAME',
+ "GAME=$self->{-game}");
+ my $fortune = $game->{'FORTUNE'};
+ $out .= $db->loc('STATISTIC_FORTUNE',$fortune);
+
+ my $speed = $game->{'SPEED'};
+ $out .= $db->loc('STATISTIC_SPEED',"$speed sec");
+
+ return $out;
+}
+
+# returns number of places for temples
+sub building_places{
+ my $self = shift;
+ return $self->{-db}->count('MAP',
+ "(TERRAIN=ISLE OR TERRAIN=MOUNTAIN) ".
+ "AND GAME=$self->{-game}");
+}
+
+# returns number of unbuild temples
+sub unbuild{
+ my $self = shift;
+ return $self->{-db}->count('MAP',
+ "(TERRAIN=ISLE OR TERRAIN=MOUNTAIN) ".
+ "AND TEMPLE=N AND GAME=$self->{-game}");
+}
+
+# returns number of temples or arks which are currently under construction
+sub under_construction{
+ my ($self,$type) = @_;
+ $type = 'TEMPLE' unless defined $type;
+ return $self->{-db}->count('EVENT',
+ "TAG=EVENT_BUILD_$type");
+
+}
+
+sub strength_in_last_battle{
+ my($self,$god) = @_;
+ $god = $self->{-player} unless defined $god;
+ my $db = $self->{-db};
+
+ my $god_hash =
+ $db->single_hash_select('GOD',
+ "GAME=$self->{-game} AND PLAYER=$god");
+
+ my $aymargeddon =
+ $db->single_hash_select('MAP',
+ "GAME=$self->{-game} AND".
+ " TERRAIN=AYMARGEDDON")->{'LOCATION'};
+ my $avatars = $self->count_mobile('AVATAR',$aymargeddon,$god);
+
+ my $strength = $::conf->{-LAST_BATTLE}->{-AVATAR} * $avatars +
+ $::conf->{-LAST_BATTLE}->{-DEATH_AVATAR} * $god_hash->{'DEATH_AVATAR'} +
+ $::conf->{-LAST_BATTLE}->{-DEATH_HERO} * $god_hash->{'DEATH_HERO'};
+
+ return $strength;
+
+}
+
+sub mobile_to_html{
+ my ($self, $loc,$own,$occ,$temple,$ter,
+ $oid,$otype,$oown,$oado,$ocnt,$ostat,$omove) = @_;
+# field infos:
+# loc: location of the field
+# own: the owner of the field (for cities and temples) (HOME)
+# occ: the occupant of the field
+# temple: wether there is a temple or not
+# ter: terrain of field
+# mobile infos:
+# oid: id of the mobile
+# otype: type of the mobile
+# oown: owner of the mobile
+# oado: which god the mobile adores
+# ocnt: mobile count
+# ostat: status of the mobile (BLOCK, IGNORE or HELP)
+# omove: the id of the mobile to move with (unused here)
+
+ my $user = $self->{-user};
+ my $db = $self->{-db};
+ my $aym = $self;
+
+ my $out = $ocnt.' ';
+ if($oown == $user){
+ $out .= $db->loc('PREP_OWN_PL').' '.$aym->mobile_string($otype,2);
+ if($otype eq 'PRIEST' or $otype eq 'PROPHET'){
+ $out .= $db->loc('ADJ_ADORING').' '.$aym->charname($oado);
+ if($own != $oado){
+ $out .= ' (<a href="command.epl?cmd=CH_STATUS&other='.$oado.'">'.
+ $aym->relation_string($oado).
+ '</a>, <a href="command.epl?cmd=SEND_MSG&other='.$oado.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+ if(($ter eq 'ISLE' or $ter eq 'MOUNTAIN') and $temple eq 'N'){
+ $out .=' (<a href="command.epl?cmd=BUILD_TEMPLE&mob='.$oid.'&loc='.$loc.'">';
+ $out .= $db->loc('CMD_BUILD_TEMPLE').'</a>)';
+ }
+ }elsif($otype eq 'HERO'){
+ $out .= $db->loc('ADJ_ADORING');#.' <a href="command.epl?cmd=CH_ADORING&mob='.
+ # $oid.'">';
+ $out .= ' ' . $aym->charname($oado); #.'</a>';
+ if($own != $oado){
+ $out .= ' (<a href="command.epl?cmd=CH_STATUS&other='.$oado.'">'.
+ $aym->relation_string($oado).
+ '</a>, <a href="command.epl?cmd=SEND_MSG&other='.$oado.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+ }elsif($otype eq 'AVATAR'){
+ $out .= ' (<a href="command.epl?cmd=CH_ACTION&mob='.$oid.'">'.
+ $aym->mobile_string($ostat,1).'</a>)';
+ if($temple eq 'Y'){
+ $out .= " (<a href=\"command.epl?cmd=DESTROY&loc=$loc\">".
+ $db->loc('CMD_DESTROY').'</a>)';
+ }
+ }
+ $out .= ' (<a href="command.epl?cmd=MOVE&mob='.$oid.'&loc='.$loc.'">'.
+ $db->loc('CMD_MOVE').'</a>)';
+
+ }else{
+ $out .= $aym->mobile_string($otype, $ocnt);
+
+ $out .= ' '.$db->loc('PREP_OWN_SG').' ';
+ $out .= $db->loc('ART_DAT_PL').' ' if $aym->gender($oown) eq 'PLURAL';
+ $out .= $aym->charname($oown);
+ if($own != $oown and $occ != $oown){
+ $out .= ' (<a href="command.epl?cmd=CH_STATUS&other='.$oown.'">'.
+ $aym->relation_string($oown).'</a>,'.
+ '<a href="command.epl?cmd=SEND_MSG&other='.$oown.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+
+ if($otype eq 'PRIEST' or $otype eq 'PROPHET'or $otype eq 'HERO'){
+ $out .= $db->loc('ADJ_ADORING').' ';
+ if($oado == $user){
+ $out .= $db->loc( ($aym->gender($user) eq 'PLURAL') ?
+ 'PPRO_DAT3_PL' : 'PPRO_DAT3_SG');
+ }else{
+ $out .= $aym->charname($oado);
+ if($own != $oown and $occ != $oown){
+ $out .= ' (<a href="command.epl?cmd=CH_STATUS&other='.$oado.'">'.
+ $aym->relation_string($oado).
+ '</a>, <a href="command.epl?cmd=SEND_MSG&other='.$oado.'">'.
+ $db->loc('SEND_MESSAGE').'</a>)';
+ }
+ }
+ }elsif($otype eq 'WARRIOR' and $aym->is_god($user)){
+ $out .= ' (<a href="command.epl?cmd=BLESS_PRIEST&mob='.$oid.'">'.
+ $db->loc('CMD_BLESS_PRIEST').'</a>)';
+ if($own==$user and $temple eq 'Y'){
+ $out .= ' (<a href="command.epl?cmd=BLESS_HERO&mob='.$oid.'">'.
+ $db->loc('CMD_BLESS_HERO').'</a>)';
+ }
+ }
+ }
+ return $out;
+}
+
+# this overloads the same function in Game.pm
+# we dont look on arks, that is special for Aymargeddon
+#sub own_in_mobile{
+# my($self,$loc,$player,$active) = @_;
+# my $cond = "GAME=$self->{-game} AND LOCATION=$loc".
+# " AND TYPE!=ARK AND (OWNER=$player OR ADORING=$player)";
+# if(defined $active){
+# # my $y = $self->{-db}->quote('Y');
+# $cond .= " AND AVAILABLE='Y'";
+# }
+# return $self->{-db}->select_array('MOBILE','ID',$cond);
+#}
+
+
+# returns true if foreign eartlings approach to field
+sub foreign_earthling_approaching{
+ my ($self,$loc,$earthling) = @_;
+
+ # TODO BUG: if $earthling < 1 => different names in different languages...
+ my $name = $self->charname($earthling);
+ my $ret = $self->{-db}->count('EVENT',
+ "LOCATION=$loc AND ".
+ "(TAG=EVENT_MOBILE_APPROACHING OR ".
+ "TAG=EVENT_ARK_APPROACHING) AND ".
+ "ARG1 != $name AND ".
+ "ARG4 != MOBILE_AVATAR AND ".
+ "ARG4 != MOBILE_AVATAR_PL");
+
+ return $ret;
+}
+
+# returns true if own avatar is there and if no god-fight is running
+sub avatar_available{
+ my ($self,$loc,$god,$command) = @_;
+
+ my $avatars = $self->own_in_mobile($loc,$god,1);
+ my @avatars = @$avatars;
+
+ my ($godfight) = $self->read_field('GOD_ATTACKER',$loc);
+
+ unless($#avatars >= 0 and not $godfight){
+ $self->send_message_to($god,
+ {'MSG_TAG' => "MSG_$command\_NEED_AVATAR",
+ 'ARG1' => $loc}) if defined $command;
+ return 0;
+ }
+
+ return 1;
+}
+
+1;
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+use strict;
+use FROGS::DataBase;
+
+#
+# Here some generell functionality to check the integrity of
+# the underlying database is checked.
+
+package Check;
+use Data::Dumper;
+
+sub new{
+ my $class = shift;
+ my $self = {};
+ $self->{-db} = DataBase->new(@_);
+ bless ($self,$class);
+}
+
+# do a check, there can be different TYPE of checks:
+# A_IN_B, LOGIC, UNIVERSAL
+#
+# - A in B checks if corresponding fields in different tables exists
+#
+# - LOGIC checks with a function for some fields in a table
+#
+# - UNIVERSAL checks with an arbitrary function
+#
+# - TODO: LOCATION should check with a function for every location
+
+sub check_all{
+ my $self = shift;
+ my $checks = shift;
+
+ my $db = $self->{-db};
+
+ while(my ($k,$v) = each %$checks){
+ print "check $k... ";
+ my $type = $v->[0];
+ if($type eq 'A_IN_B'){
+ my $table_A = $v->[1]->[0];
+ my $field_A = $v->[1]->[1];
+ my $table_B = $v->[1]->[2];
+ my $field_B = $v->[1]->[3];
+
+ # TODO BUG: dont use single_select!
+ my @data = $db->single_select("select distinct $field_A from $table_A");
+ my @datb = $db->single_select("select distinct $field_B from $table_B");
+
+ print Dumper \@datb;
+ my %schnitt;
+ for my $d (@datb){
+ print "hab $d\n";
+ $schnitt{$d} = 1;
+ }
+ my $failed = 0;
+ for my $d (@data){
+ if(not exists($schnitt{$d})){
+ print "FAILED with $field_A = $d!\n";
+ $failed = 1;
+ last;
+ }
+ }
+ next if $failed;
+ print "OK.\n";
+ }elsif($type eq 'LOGIC'){
+ my $table = $v->[1]->[0];
+ my $fields = $v->[1]->[1];
+ my $function = $v->[1]->[2];
+ local $" = ', ';
+ my $command = "select @$fields from $table";
+ # TODO: single_select correct? we need the whole table and
+ # TODO: there is no condition???
+ my @dat = $db->single_select($command);
+ # print Dumper $dat;
+
+ my $failed = 0;
+ for my $d (@dat){
+ my $ret = &$function($d);
+ $failed = 1 unless $ret;
+ }
+ $failed ? print "FAILED!\n" : print "OK.\n";
+ }elsif($type eq 'UNIVERSAL'){
+ my $function = $v->[1];
+ my $ret = &$function($db);
+ $ret ? print "FAILED: $ret\n" : print "OK.\n";
+ }else{
+ print "FAILED (Type of check - $type - not avaiable)\n";
+ }
+ }
+}
+
+1;
+
+
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+# basic command object used by the scheduler
+use strict;
+use Date::Parse qw(str2time);
+use Date::Calc qw(Time_to_Date);
+use FROGS::DataBase;
+use FROGS::Config qw ($conf);
+require "$::conf->{-GAME_NAME}.pm";
+
+package Command;
+use Data::Dumper;
+
+sub new {
+ my ($type, $dbhash, $dbobj) = @_;
+
+ Util::log("$type->new()",2);
+
+ my $self = {-dbhash => $dbhash,
+ -db => $dbobj,
+ -player => $dbhash->{'PLAYER'},
+ -game => $dbhash->{'GAME'},
+ -id => $dbhash->{'ID'},
+ -location => $dbhash->{'LOCATION'},
+ -class => $type,
+ };
+ bless( $self, $type );
+
+ # create an GAME_NAME context object
+ $self->{-context} = $::conf->{-GAME_NAME}->new($dbhash->{'GAME'},
+ $dbhash->{'PLAYER'},
+ $dbobj);
+
+ $self->{-speed} = $self->{-context}->get_speed();
+
+ # end of the game?
+ if($self->{-speed} < 0){
+ Util::log("Game over, no commands anymore!",1);
+ $self->done();
+ return 0;
+ }
+
+ # set language according to PLAYER.LANGUAGE
+ my ($lang) = $dbobj->read_player($self->{-player},'LANGUAGE');
+ $dbobj->set_language($lang);
+
+ $self->{-args} = $self->parse_args( $self->{-dbhash}->{'ARGUMENTS'} );
+
+ if (defined $self->{-dbhash}->{'ACK'} and
+ $self->{-dbhash}->{'ACK'} ne '0000-00-00 00:00:00'){
+ $self->{-phase} = 2;
+ }else{
+ $self->{-phase} = 1;
+ $self->{-duration} = $::conf->{-DURATION}->{"-$type"} || 0;
+ }
+
+ if(not $::conf->{-MESSAGE_IN_LOG} and $type eq 'SEND_MSG'){
+ Util::log('',1);
+ }else{
+ my $logstring = "\nCommand $type (ID: $self->{-dbhash}->{'ID'}): ".
+ "Phase $self->{-phase}, ".
+ "Player $self->{-dbhash}->{'PLAYER'}, ".
+ "Game $self->{-dbhash}->{'GAME'}, ".
+ "Arguments $self->{-dbhash}->{'ARGUMENTS'}";
+ $logstring .= ", Location $self->{-dbhash}->{'LOCATION'}, "
+ if defined $self->{-dbhash}->{'LOCATION'};
+ Util::log($logstring,1);
+ }
+
+ return $self;
+}
+
+sub is_valid {
+ my ($self, @required_args) = @_;
+
+ # all arguments avaiable?
+ # TODO PERFORMANCE: maybe this check only in phase1?
+ return 0 unless $self->required_args($self->{-args}, @required_args);
+
+ # does the player still exists?
+ if($self->{-player} == -1){
+ $self->{-role} = $self->{-context}->charname(-1);
+ }else{
+ my ($id,$role) = $self->{-context}->read_role($self->{-player},'PLAYER,ROLE');
+ if($id != $self->{-player}){
+ Util::log("COMMAND->is_valid: Player $self->{-player} does not exist!\n",0);
+ return 0;
+ }
+ # set role for later use
+ # print "ROLE(is_valid): $role\n";
+ $self->{-role} = $role;
+ }
+ return 1;
+}
+
+sub isSecond {
+ my $self = shift;
+ return 2 == $self->{-phase};
+}
+
+sub isFirst {
+ my $self = shift;
+ return 1 == $self->{-phase};
+}
+
+sub execute {
+ my $self = shift;
+ my $db=$self->{-db};
+
+ #if($self->{-speed} < 0){
+ # Util::log('*',-1);
+ # $self->done();
+ # return;
+ #}
+ # determine phase of command and do it.
+ if ($self->isFirst() ) {
+ $db->update_hash("COMMAND","ID = $self->{-dbhash}->{'ID'}",{ 'ACK' => $db->now() });
+ my $ret = $self->first_phase();
+
+ if ($self->getDuration() > 0 and $ret > 0) {
+ my $exec = $self->getPhase2exec();
+ if($self->{-end_of_game}){
+ $self->done();
+ }else{
+ $db->update_hash("COMMAND",
+ "ID = $self->{-dbhash}->{'ID'}",
+ { 'EXEC' => $exec });
+ }
+ }elsif ($self->getDuration() == 0 or $ret == 0){
+ $self->done();
+ } else {
+ # in this case the command has set its EXEC by itself. we do nothing
+ $self->done() if $self->{-end_of_game};
+ }
+ } elsif ($self->isSecond() ) {
+ $self->second_phase();
+ $self->done();
+ } else {
+ Util::log("command->execute ($self->{-class}) : Unknown or undefined Command phase",0);
+ die;
+ }
+}
+
+sub done {
+# a command will use this func to declare it's terminated
+# it is called by Scheduler after secondPhase anyway, so a
+# command has to use it only explicitley in a member if it wants to
+# terminate NOW! (but still have to exit action for itself)
+ my $self = shift;
+ my $db=$self->{-db};
+
+ my $id = $self->{-id};
+
+ $db->update_hash("COMMAND","ID = $id",{ 'DONE' => $db->now() });
+ if ($::conf->{-DEBUG} == 0 or $::conf->{-DELETE_OLD_COMMANDS}) {
+ $db->delete_from("COMMAND","ID=$id");
+ Util::log(ref($self)."-Command $id deleted.",1);
+ # TODO: dont delete PRODUCE-Command if game not runnning, but waiting
+ }
+ # TODO?: send messages
+}
+
+sub setDuration {
+# sets the duration of the command in units. Sheduler will schedule
+# the Phase 2 then for gametime+units*pace(game).
+# this function will have to be called explicitely during phase 1 by the
+# implementation of the command
+# If it is not called at least once (or set to 0), Scheduler will assume the command has
+# no second phase and will call done() after completion of firstPhase().
+ my $self = shift;
+ $self->{-duration} = shift;
+}
+
+sub getDuration {
+# get command duration in units
+ my $self = shift;
+ return $self->{-duration};
+}
+
+sub getDurationInSec{
+# get command duration in secs according to the *current* gamespeed
+ my $self = shift;
+
+ my $ret = $self->getDuration() * $self->{-speed};
+
+ Util::log("Duration in sec: $ret",1) unless defined $self->{-duration_logged};
+ $self->{-duration_logged} = 1;
+
+ $self->{-end_of_game} = 1 unless $ret >= 0;
+ return $ret;
+}
+
+sub getPhase2exec {
+ # only valid during phase 1 returns start of phase 2 in game
+ # time, GMT (YYYY-MM-DD HH:MM:SS). If Duration wasn't set, or
+ # phase is wrong it returns undef.
+ my $self = shift;
+ if ($self->getDuration() == 0 || $self->isSecond() ) {
+ return undef;
+ }
+ my $firstExecTimeUnix = &::str2time($self->{-dbhash}->{'EXEC'},'GMT');
+# my $firstExecTimeUnix = &::str2time($self->{-dbhash}->{'EXEC'});
+ $firstExecTimeUnix += $self->getDurationInSec();
+ my ($year,$month,$day, $hour,$min,$sec) = &::Time_to_Date($firstExecTimeUnix);
+ return sprintf ("%04u-%02u-%02u %02u:%02u:%02u",$year,$month,$day, $hour,$min,$sec);
+}
+
+
+#############################################
+#
+# Tools to be used by concrete commands
+#
+
+# TODO: Bug mit messages
+sub parse_args {
+ my ( $self, $arg_string ) = @_;
+
+ my @key_value_pairs = split /,/, $arg_string; # TODO: wrong for messages
+
+ # remove leading/trailing whitespace
+ @key_value_pairs = map { $_ =~ s/^\s*(\S*)\s*$/$1/; $_ } @key_value_pairs;
+
+ my %hash;
+ for my $kv (@key_value_pairs) {
+ my ( $k, $v ) = split /=/, $kv; # TODO: wrong for messages
+
+ # remove leading/trailing whitespace again
+ ( $k, $v ) = map { $_ =~ s/^\s*(\S*)\s*$/$1/; $_ } ( $k, $v );
+
+ $hash{$k} = $v;
+ }
+ # use Data::Dumper; print Dumper \%hash;
+ return \%hash;
+}
+
+sub required_args {
+ my ( $self, $args, @ra ) = @_;
+
+ for my $a (@ra) {
+ unless ( exists $args->{$a} ) {
+ Util::log("We need argument $a",1);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+# general testfunction.
+# sends error message and return false
+# unless &$cond() gives true
+
+sub test{
+ my ($self, $cond, $tag, @args) = @_;
+
+ unless(&$cond()){
+ # (@args) = $self->{-db}->quote_all(@args);
+
+ my $sendhash = {'MFROM' => 0,
+ 'MSG_TAG' => $tag};
+ # TODO: localize command-strings!
+ $sendhash->{'ARG1'} = $self->{-class};
+ for my $a (1..($#args+1)){
+ $sendhash->{"ARG$a"} = $args[$a-1];
+ }
+
+ $self->{-context}->send_message_to($self->{-player},$sendhash);
+
+ Util::log("Test failed: $tag, args @args",1);
+
+ return 0;
+ }
+ return 1;
+}
+
+#sub test{
+# my ($self, @all) = @_;
+#
+# if($self->test_without_done(@all)){
+# return 1;
+# }else{
+# # delete me from database
+# $self->done();
+# return 0;
+# }
+#}
+
+# set a mobilehash if available, sends errormessage otherwise
+sub validate_mobile{
+ my ($self,$mob_id) = @_;
+
+ my $mob = $self->{-db}->read_single_mobile($mob_id);
+
+ # mobile correct?
+ if($self->{-phase} == 1){
+ return 0 unless $self->test(sub {defined $mob},
+ 'MSG_NO_SUCH_MOBILE',
+ $mob_id);
+ }
+ $self->{-mob} = $mob;
+ return 1;
+}
+
+# errormessage unless one of valid roles
+sub validate_role{
+ my ($self, @valid_roles) = @_;
+
+ return 1 if $self->{-player} < 0;
+
+ Util::log("validate_role($self->{-role})",2);
+
+ unless(Util::is_in($self->{-role},@valid_roles)){
+ return 0 unless $self->test(sub {0},
+ 'MSG_ROLE_CANT_DO',
+ $self->{-role},
+ ref($self));
+ }
+ return 1;
+}
+
+sub validate_this_role{
+ my($self,$player,@valid_roles) = @_;
+
+ # fake identity
+ my $role = $self->{-role};
+ my ($id,$r) = $self->{-context}->read_role($player,'PLAYER,ROLE');
+ $self->{-role} = $r;
+ my $ret = $self->validate_role(@valid_roles);
+ $self->{-role} = $role;
+ return 0 unless $ret;
+ return 1;
+}
+
+# takes a mobile_hash, a count and a diff_hash. creates another mobile
+# with count members in the database with the different fields given
+# in diff_hash. if $available, than the new mob is available
+
+# returns
+# ID of newmob (newmob is in some sense really the old mob, because
+# diff is apllied to old mob) , returns the new ID (of the old mob).
+
+sub split_mobile{
+ my ($self, $mob, $count, $diff, $available) = @_;
+ my $db = $self->{-db};
+ Util::log(ref($self).": split mobile $mob->{'ID'}",1);
+
+ # create new mobile
+ my %newmob = %$mob;
+ my $newmob = \%newmob;
+ $newmob->{'ID'} = $self->{-db}->find_first_free('MOBILE','ID');
+ my $newid = $newmob->{'ID'};
+
+ %$mob = (%$mob,%$diff);
+ # print Dumper $mob; exit;
+ # %$newmob = (%$oldmob, %$newmob);
+
+ # calculate new count and available
+ $mob->{'COUNT'} = $count;
+ $mob->{'AVAILABLE'} = $available ? 'Y' : 'N';
+
+ my $id = $mob->{'ID'};
+ delete $mob->{'ID'};
+ # print Dumper $mob;
+ $self->{-db}->update_hash('MOBILE',"ID=$id",$mob);
+ Util::log("mobile $id updated",1);
+
+ # reduce count of old one
+ $newmob->{'COUNT'} -= $count;
+
+ # print Dumper $newmob;
+ $self->{-db}->insert_hash('MOBILE',$newmob);
+ Util::log("new mobile $newid",1);
+
+ return $newid;
+}
+
+# this function splits a mobile if it necessary, update else.
+# usage of parameters: see split_mobile
+# returns the new ID of the old mob (see split_mobile)
+sub conditional_split_mobile{
+ my ($self, $mob, $count, $diff, $available) = @_;
+
+ # print "count: $count\n";
+ # print Dumper $mob;
+
+ my $db = $self->{-db};
+
+ # split it, if neccessary
+ if($count < $mob->{'COUNT'}){
+
+ return $self->split_mobile($mob,$count,$diff,$available);
+
+ }elsif($count == $mob->{'COUNT'}){
+ $diff->{'AVAILABLE'} = $available ? 'Y' : 'N';
+ $db->update_hash('MOBILE',
+ "ID=$mob->{'ID'}",
+ $diff);
+ return $mob->{'ID'};
+ }else{
+ Util::log("SPLIT MOBILE: Error! impossible case. not enough mobiles. ".
+ "we need $count and have only $mob->{'COUNT'}",0);
+ return 0;
+ }
+}
+
+sub event{
+ my ($self, $loc, $tag, @args) = @_;
+
+ # read execution time
+ my $exec_time = $self->getPhase2exec();
+
+ unless($exec_time){
+ my $cmd = $self->{-db}->single_hash_select('COMMAND',
+ "ID=$self->{-dbhash}->{'ID'}");
+ $exec_time = $cmd->{'EXEC'};
+ }
+
+ my $event = {'TAG' => $tag,
+ 'LOCATION' => $loc,
+ 'GAME' => $self->{-game},
+ 'TIME' => $exec_time,
+ 'COMMAND_ID' => $self->{-dbhash}->{'ID'},
+ };
+ $event->{'ARG1'} = $self->{-context}->charname($self->{-player});
+ for my $a (0..$#args){
+ $event->{'ARG'.($a+2)} = $args[$a];
+ }
+ $self->{-db}->write_event($event);
+}
+
+# this function re-inserts the same command in the queue again
+sub do_it_again{
+ my ($self,$arguments) = @_;
+
+ my $now = $self->{-db}->now();
+ # we need a new ID
+ delete $self->{-dbhash}->{'ID'};
+ # reset timestamps
+ $self->{-dbhash}->{'SUBMIT'} = $now;
+ $self->{-dbhash}->{'EXEC'} = $now;
+ $self->{-dbhash}->{'ACK'} = 'NULL'; # TODO: wrong way to insert NULL?
+ $self->{-dbhash}->{'DONE'} = 'NULL';
+ if (defined $arguments){
+ # these arguments are allready there in the database
+ my $hash = $self->parse_args($self->{-dbhash}->{'ARGUMENTS'});
+ # we put some additional ones into hash
+ for my $k (keys %$arguments){
+ $hash->{$k} = $arguments->{$k};
+ }
+ # rearrange hash into string
+ my $new_string = '';
+ my ($key,$value);
+ while (($key,$value) = each %$hash){
+ $new_string .= "$key=$value, ";
+ }
+ $new_string =~ s/, $//;
+ $self->{-dbhash}->{'ARGUMENTS'} = $new_string;
+ }
+ # write new command to database
+ $self->{-db}->insert_hash('COMMAND', $self->{-dbhash});
+}
+
+1;
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+# TODO: seperate FROGS-config from Aymargeddon-config in different files
+
+# change this file to configure your game
+
+use strict;
+package Config;
+require Exporter;
+@::ISA = qw(Exporter);
+@::EXPORT_OK = qw($conf);
+
+$::conf = {
+ # FROGS stuff
+ -DB_SOURCE => 'mysql:RAGNAROEK',
+ -DB_USER => 'aymargeddon',
+ -DB_SECRETS => '/home/benni/aymargeddon/current/+secrets',
+ -COMMANDS => 'AymCommand.pm',
+ -GAME_NAME => 'Aymargeddon',
+ -DEFAULT_LANGUAGE => 'EN',
+ -LOG_TIME_IN_LOOP => 1000, # loops until next time output in log
+ -DEBUG => 1,
+ -EPL_DEBUG => 0,
+ -MESSAGE_IN_LOG => 0,
+ -FULL_DEBUG_FILE => '/home/benni/aymargeddon/current/src/FROGS/+out',
+ -SCHEDULER_SLEEP => 2,
+ -DELETE_OLD_EVENTS => 1, # dont touch this, it will not work!
+ -DELETE_OLD_COMMANDS => 1, # dont touch this, it will not work!
+ -SEND_MESSAGE_TO_FIELD => 1, # set to 0 to stop slow messages
+ -MAX_ARGS => 4, # maximum arguments for localisation tags
+ # (hardcoded in database-structure)
+ -MANY => 99999,
+
+ # Aymargeddon stuff... you maybe dont need this for other games
+
+ -START_MANA => 33,
+ -START_FORTUNE => 3,
+ -START_WARRIORS => 2,
+ -MAX_MOUNTAINS => 1, # mountains per god/earthling-combination
+ -MIN_DISTANCE_HOME => 3, # minimal distance between homecitys
+ -NEIGHBOUR_CITIES => 2, # number of citys in the neighbourhood of a home
+ -MIN_DISTANCE_MOUNTAIN => 2,
+ -WANTED_DISTANCE_MOUNTAIN => 3,
+ -MIN_DISTANCE_MOUNTAIN_FROM_WATER => 2,
+ -MIN_LUCK => 3,
+ -MAX_LUCK => 12,
+ -MANA_FOR_TEMPLE => 1,
+ -FORTUNE_FAKTOR_ISLAND => 1,
+ -FORTUNE_FAKTOR_MOUNTAIN => 2,
+ -MAX_UNBUILD_DESTROY => 1,
+ # -ARK_RETREAT_POSSIBILITY => 0.5, (in the moment hardcoded)
+ -WINNER_DEATH_COUNT_FRACTION => 5,
+ -LOOSER_DEATH_COUNT_FRACTION => 3,
+ -WINNER_AVATARS_DYING_FRACTION => 4,
+ -LOOSER_AVATARS_DYING_FRACTION => 2,
+ -DEATH_SHARE_ROW => [0.4, 0.3, 0.2, 0.1], # should sum to 1
+ -DEFAULT_DYING => 'KHP',
+
+ -PLAGUES => ['INFLUENZA','PESTILENTIA','TUBERCULOSIS'],
+ -PESTILENTIA_DEATH_SHARE => 0.5,
+ -SPREAD_PLAGUE => {'CITY' => 0.1,
+ 'PLAIN' => 0.05,
+ 'MOUNTAIN' => 0.03,
+ 'ISLE' => 0.02,
+ 'WATER' => 0},
+ -HEAL_PLAGUE => 0.4,
+
+ # can gods give earthlings right to see?
+ -GODS_SHOW_EARTHLINGS => 0,
+
+ # which fields keep there owner without units?
+ -HOMECITY_KEEP_OWNER => 1,
+ -TEMPLE_KEEP_OWNER => 1,
+ -KEEP_OWNER => {'CITY' => 1},
+
+ # which fields fight without owner?
+ -FIGHTS_WITHOUT_OWNER => {'CITY' => 1},
+
+ # which fields fights without units?
+ #-HOMECITY_FIGHTS => 1,
+ #-FIGHTS_WITHOUT_UNIT => {'CITY' => 1},
+
+ -DURATION => {
+
+ -MOVE_AVATAR => 1,
+ -MOVE_HERO => 8,
+ -MOVE_WARRIOR => 10,
+ -MOVE_PRIEST => 6,
+ # -MOVE_PROPHET => 6, # 12
+ -MOVE_ARK => 5,
+ -FIGHT_EARTHLING => 6,
+ -FIGHT_GOD => 10, #10
+ -BUILD_TEMPLE => 3, # 50
+ -FLOOD => 40, # 40
+ -CH_ADORING => 20,
+ -CH_LUCK => 5,
+ -PRODUCE_WARRIOR => 40, # 40
+ -PRODUCE_WARRIOR_HOME => 20, # 20
+ -PRODUCE_WARRIOR_CHANGE => 0,
+ -PRODUCE_PRIEST => 40, # 40
+ -PRODUCE_PRIEST_HOME => 40, # 40
+ -BUILD_ARK => 30, #30
+ -PLAGUE => 20,
+ -PRAY => 10, # 10
+ },
+
+ -FIGHT => {
+ -PRIEST => 0,
+ -WARRIOR => 1,
+ -HERO => 2,
+ -PROPHET => 0,
+ -AVATAR => 4, # maximum
+ -HOME => 2,
+ -ISLE => 2,
+ -ARK => 1,
+ -FLANKING => 1,
+ },
+ #-SEE_FIGHT => {
+ # -PRIEST => 0,
+ # -WARRIOR => 0,
+ # -HERO => 1,
+ # -PROPHET => 0,
+ #-AVATAR => 0,
+ #-HOME => 0,
+ #-ARK => 3,
+ #-FLANKING => 0,
+ #},
+ # -ISLAND_FIGHT => {
+ # -PRIEST => 0,
+ # -WARRIOR => 1,
+ # -HERO => 2,
+ # -PROPHET => 0,
+ #-AVATAR => 4, # maximum
+ #-HOME => 2,
+ #-ARK => 3,
+ #-FLANKING => 0,
+ #},
+
+ -LAST_BATTLE => {
+ -DEATH_HERO => 1,
+ -DEATH_AVATAR => 0,
+ -AVATAR => 7,
+ },
+ -MANA => {
+ -MOVE_AVATAR => 1,
+ -FIGHT_AVATAR => 2,
+ -DESTROY => 7,
+ -FLOOD => 4,
+ -CH_LUCK => 1,
+ -BUILD_ARK => 7,
+ -BLESS_PRIEST => 7,
+ -BLESS_HERO => 2,
+ -INCARNATE => 5,
+ # plagues:
+ -INFLUENZA => 10,
+ -PESTILENTIA => 20,
+ -TUBERCULOSIS => 40,
+ },
+
+ -COLOR => {
+ -EMPTY => '#fcffd9',
+ -NEUTRAL => '#b8a266',
+ },
+ };
+
+# read password from secrets-file. password should not be included in source!
+
+my $conf = $::conf->{-DB_SECRETS};
+
+# substitute "~" (UNIX only!) from Perl Cookbook 7.3 not really useful
+# here, because HOME is different in webserver and in user context
+$conf =~ s{ ^ ~ ( [^/]* ) }{ $1 ? (getpwnam($1))[7] : ($ENV{HOME}||$ENV{LOGDIR}||
+ (getpwuid($<))[7])}ex;
+
+open(CONFIG,$conf) or die "could not open config file $conf: $!\n";
+
+while(<CONFIG>){
+ chop $_;
+ next if /^\s*$/;
+ next if /^\s*\#.*$/;
+ $::conf->{-DB_PASSWD} = $_;
+}
+close CONFIG or die "could not close config file $conf: $!\n";
+
+1;
+
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+# Generell database methods are gathered here.
+use strict;
+use DBI;
+use POSIX qw(floor);
+use FROGS::Config qw($conf);
+use FROGS::Util;
+use Date::Parse qw(str2time);
+use Date::Calc qw(Time_to_Date Delta_DHMS);
+
+package DataBase;
+
+# the constructor connects to the DB
+sub new{
+ my ($class,$dbh) = @_;
+ my $self = {};
+ if (defined $dbh){
+ $self->{-dbh} = $dbh;
+ }else{
+ $self->{-dbh} = DBI->connect("dbi:$::conf->{-DB_SOURCE}",
+ $::conf->{-DB_USER},
+ $::conf->{-DB_PASSWD},
+ {'RaiseError' => 1, 'AutoCommit' => 0}
+ );
+ }
+ #TODO: should specify iso date and time format explicitly for the session!!
+
+ $self->{-lang} = $self->{-dbh}->quote($::conf->{-DEFAULT_LANGUAGE});
+
+ bless ($self,$class);
+}
+
+sub commit{
+ my $self = shift;
+ unless(defined $self->{-nowrite}){
+ $self->{-dbh}->commit();
+ Util::log('committed.',2);
+ }
+}
+
+sub nowrite{
+ my $self = shift;
+ Util::log("DataBase: nowrite activated!",1);
+ $self->{-nowrite} = 1;
+}
+
+# automaticly called destructor
+sub DESTROY{
+ my $self = shift;
+ $self->{-dbh}->disconnect();
+}
+
+# wrapper for database functions:
+
+sub quote{
+ my ($self, $text) = @_;
+ return $self->{-dbh}->quote($text);
+}
+
+sub quote_all{
+ my ($self, @plain) = @_;
+ my @quoted;
+ for my $s (@plain){
+ push @quoted, $self->{-dbh}->quote($s);
+ }
+ return @quoted;
+}
+
+# this does not support any possible SQL-conditions
+# just a small subset
+# TODO: this function is really ugly :-(
+# TODO: just use an escape-character in calls to mark, which fields should be
+# TODO: quoted
+sub quote_condition{
+ my ($self, $cond) = @_;
+
+ Util::log("condition: $cond",2);
+
+ my @bracket = ('(',')');
+ my @bool = ('AND', 'OR');
+ my @ops = ('=', '!=');
+ my @noops = ('<'); # forbidden substrings of pairs. ugly workaround for "time < now()"
+
+ # split string at boolean operators
+ my $splitstring = '';
+ for my $bool (@bool){
+ $splitstring .= '\b'.$bool.'\b|';
+ }
+ $splitstring =~ s/(.*)\|/$1/;
+
+ #Util::log("splitstring: $splitstring\n",2);
+
+ my @pairs = split /\s$splitstring\s/, $cond;
+
+ Util::log("pairs: @pairs",2);
+
+ my $opstring = '';
+ for my $o (@ops){
+ $opstring .= "$o|";
+ }
+ $opstring =~ s/(.*)\|/$1/;
+
+ my $noopstring = '';
+ for my $no (@noops){
+ $noopstring .= "$no|";
+ }
+ $noopstring =~ s/(.*)\|/$1/;
+
+ # quote right hand of operator if necessary
+ for my $pair (@pairs){
+ next if $pair =~ /$noopstring/;
+ my ($left,$right) = split /$opstring/, $pair;
+ #Util::log("1 left: $left, right: $right",2);
+ $right =~ s/^\(*-?([\w\s].*)$/$1/; # remove leading brackets
+ #Util::log("2 left: $left, right: $right",2);
+ $right =~ s/-?(.*[\w\s])\)*$/$1/; # remove trailing brackets
+ #Util::log("3 left: $left, right: $right",2);
+ $right =~ s/^\s*-?(\S.*)/$1/; # remove leading whitespace
+ #Util::log("4 left: $left, right: $right",2);
+ $right =~ s/(.*\S)\s*$/$1/; # remove trailing whitespace
+ #Util::log("5 left: $left, right: $right",2);
+
+ next if $right =~ /^\d+$/;
+ # this could be misfunctional in some SQL-Dialect. We assume single-quotes
+ my $qright = ($right =~ /^\'.*\'/) ? $right : $self->quote($right);
+
+ # Util::log("qright: $qright",2);
+ next if $cond =~ /$qright/;
+ $cond =~ s/($opstring\s*)$right/$1$qright/;
+ }
+ Util::log("new condition: $cond",2);
+ return $cond;
+}
+
+# assumes that a single row is returned from database
+# returns a list of selected columns
+sub single_select{
+ my ($self,$stmt) = @_;
+
+ Util::log("single_select: $stmt",2);
+ my $dat = $self->{-dbh}->selectall_arrayref($stmt);
+ return () if not defined $dat or not defined $dat->[0];
+ return @{$dat->[0]};
+}
+
+sub single_hash_select{
+ my ($self,$table,$cond) = @_;
+
+ $cond = $self->quote_condition($cond);
+ my $stmt = "SELECT * FROM $table where $cond";
+ Util::log("single_hash_select: $stmt",2);
+ return $self->{-dbh}->selectrow_hashref($stmt);
+}
+
+sub select_hash{
+ my ($self, $table, $key, $fields, $cond) = @_;
+
+ my $stmt = $fields ? "SELECT $key, $fields FROM $table"
+ : "SELECT $key FROM $table";
+ $stmt .= " WHERE $cond" if $cond;
+ return $self->{-dbh}->selectall_hashref($stmt, $key);
+}
+
+sub select_array{
+ my ($self, $table, $fields, $cond, $order) = @_;
+ my $stmt = "SELECT $fields FROM $table";
+ if( $cond){
+ $cond = $self->quote_condition($cond);
+ $stmt .= " WHERE $cond";
+ if(defined $order){
+ $stmt .= " ORDER BY $order";
+ }
+ }
+
+ Util::log("select_array: $stmt",2);
+ return $self->{-dbh}->selectall_arrayref($stmt);
+}
+
+# returns number of fields with given condition
+sub count{
+ my ($self, $table, $cond) = @_;
+ my $array = $self->select_array($table,'*',$cond);
+ my @a = @$array;
+ my $count = $#a + 1;
+ Util::log("counted $cond in $table: $count",1);
+ return $count;
+}
+
+# insert a row in one table of the database
+#
+# parameterlist:
+# table: the database-table we work on
+# hash: give here a hash with the new values
+# noquote: if hash, than dont quote all keys which are in this hash,
+# if no hash but defined, than we dont quote all the new values
+# (useful for things simmilar to COUNT = COUNT + 1)
+sub insert_hash{
+ my ($self, $table, $hash,$noquote) = @_;
+ my $noquote_type = ref($noquote);
+ my $noquote_global = 1 if defined $noquote and not $noquote_type eq 'HASH';
+ my $noquote_hash = 1 if $noquote_type eq 'HASH';
+
+ my $insert = "INSERT INTO $table (";
+ for my $key (keys %$hash){
+ # $key = $self->{-dbh}->quote_identifier($key);
+ $insert .= "$key,";
+ }
+ chop($insert);
+ $insert .=") VALUES (";
+ while( my ($k,$val) = each %$hash){
+ $val = $self->quote($val) if not $noquote_global or
+ ($noquote_hash and exists $noquote->{$k});
+ $insert .= "$val,";
+ }
+ chop($insert);
+ $insert .= ')';
+
+ Util::log("INSERT: $insert",2);
+ my $h = $self->{-dbh}->prepare($insert);
+ $h->execute();
+ $h->finish();
+}
+
+# parameter: see insert_hash() and update_hash()
+sub insert_or_update_hash{
+ my ($self, $table, $cond, $hash, $noquote) = @_;
+ $cond = $self->quote_condition($cond);
+ my @row = $self->single_select("SELECT * FROM $table WHERE $cond");
+ use Data::Dumper;
+ if($#row >= 0){
+ $self->update_hash($table,$cond,$hash,$noquote);
+ }else{
+ $self->insert_hash($table,$hash,$noquote);
+ }
+}
+
+# update a set of rows in one table of the database
+#
+# parameterlist:
+# table: the database-table we work on
+# cond: only rows are effected, which evaluates this condition as true
+# hash: give here a hash with the new values
+# noquote: if hash, than dont quote all keys which are in this hash,
+# if no hash but defined, than we dont quote all the new values
+# (useful for things simmilar to COUNT = COUNT + 1)
+sub update_hash{
+ my ($self, $table, $cond, $hash, $noquote) = @_;
+ my $noquote_type = ref($noquote);
+ my $noquote_global = 1 if defined $noquote and not $noquote_type eq 'HASH';
+ my $noquote_hash = 1 if $noquote_type eq 'HASH';
+
+ my $stmt = "UPDATE $table SET ";
+ while( my ($k,$v) = each %$hash){
+ $v = $self->quote($v) if not $noquote_global or
+ ($noquote_hash and exists $noquote->{$k});
+ $stmt .= "$k=$v,";
+ }
+ chop($stmt);
+
+ $stmt .= " WHERE ". $self->quote_condition($cond);
+
+ Util::log("update_hash: $stmt",2);
+ my $h = $self->{-dbh}->prepare($stmt);
+ $h->execute();
+ $h->finish();
+}
+
+sub delete_from{
+ my ($self,$table,$cond) = @_;
+
+ die "do you really want to delete a complete table?" unless $cond;
+
+ my $sql = "DELETE FROM $table";
+ if($cond){
+ $cond = $self->quote_condition($cond);
+ $sql .= " WHERE $cond";
+ }
+ Util::log($sql,2);
+ my $dbh = $self->{-dbh};
+ my $h = $dbh->prepare($sql);
+ $h->execute();
+ $h->finish();
+}
+
+sub find_first_free{
+ my ($self,$table,$field) = @_;
+
+ my $t = $self->select_array($table, $field);
+ my @ids = sort {$a <=> $b} (map {$_->[0]} @$t);
+
+ my $id = 1;
+ for my $try (@ids){
+ next if $try < 0; # unfortunately some tabels contain the id -1 and id 0 is free :-(
+ last if $id < $try;
+ $id = $try + 1;
+ }
+ return $id;
+}
+
+sub read_game{
+ my ($self,$game,$field) = @_;
+ my $stmt = "SELECT $field from GAME where GAME=$game";
+ return $self->single_select($stmt);
+}
+
+# localisation
+
+sub set_language{
+ my ($self, $lang) = @_;
+ $self->{-lang} = $self->{-dbh}->quote($lang) if $lang;
+}
+
+# returns the localisation of a tag.
+# if the result contains tags again, localize these too.
+sub loc{
+ my ($self, $tag, @args) = @_;
+
+ Util::log("args: @args",2);
+
+ $tag = $self->{-dbh}->quote($tag);
+ my $stmt = 'SELECT TEXT FROM LOCALIZE WHERE LANGUAGE='.$self->{-lang}." AND TAG=$tag";
+ my ($text) = $self->single_select($stmt);
+
+ # replace %x with arg[x]
+ while($text =~ /\%(\d+)/){
+ my $nr = $1;
+ Util::log("found $nr in $text",2);
+ $text =~ s/(\%$nr)/$args[$nr-1]/g;
+ }
+
+ return $text =~ /^\s*$/ ? "Error: Tag $tag not defined for language $self->{-lang}."
+ : $self->localize_string($text);
+}
+
+# calls loc() for all uppercase-only-words and returns new string
+# TODO: allow arguments in brackets after uppercase-words with length >= 3
+sub localize_string{
+ my ($self,$string) = @_;
+
+ $string =~ s/(\b[^\Wa-z0-9]{3,}\b)/$self->loc($1)/ge;
+ return $string;
+}
+
+# game management:
+
+sub new_account{
+ my ($self,$login,$name,$email,$lang) = @_;
+
+ my ($qlogin,$qname,$qemail) = $self->quote_all($login,$name,$email);
+
+ my $cond = "LOGIN=$qlogin OR REALNAME=$qname OR EMAIL=$qemail";
+ my $habschon = $self->select_array('PLAYER','PLAYER',$cond);
+ my @habschon = @$habschon;
+ return 0 if @habschon;
+
+ # generate new password
+ my $pwd = '';
+ my $allowed = '2345679ACDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
+ for my $i (0..7){
+ $pwd .= substr($allowed, POSIX::floor(rand(72)), 1);
+ }
+ my $qpwd = $self->{-dbh}->quote($pwd);
+
+ # search first free player ID
+ my $player = $self->find_first_free('PLAYER','PLAYER');
+
+ # write new player
+ $self->insert_hash('PLAYER', {PLAYER => $player,
+ REALNAME => $name,
+ LOGIN => $login,
+ EMAIL => $email,
+ PASSWORD => $pwd,
+ LANGUAGE => $lang,
+ });
+ $self->commit();
+
+ my $mail = "From: registration\@aymargeddon.de\nTo: $name <$email>\n"
+ . "Subject: ".$self->loc('REGISTER_MAIL_SUBJECT')."\n\n"
+ . $self->loc('REGISTER_MAIL_TEXT', $name, $login, $pwd)."\n";
+
+ # print $mail;
+
+ open(SENDMAIL, "|mail $email") or Util::log("Can't fork for sendmail: $!",0);
+ print SENDMAIL $mail;
+ close(SENDMAIL) or Util::log("sendmail didn't close nicely",0);
+
+ return $pwd;
+}
+
+sub authenticate{
+ my ($self, $user, $pwd, $pwd2, $pwd3 ) = @_;
+
+ my $admin = $self->quote('admin');
+ # you can log into any account with adminpassword
+ my ($adminpwd) = $self->single_select("SELECT PASSWORD FROM PLAYER ".
+ "WHERE LOGIN=$admin");
+ ($user,$pwd,$adminpwd) = $self->quote_all($user,$pwd,$adminpwd);
+
+
+ Util::log("Adminpassword: $adminpwd, password: $pwd",2);
+
+ my ($player, $sec);
+ if($adminpwd eq $pwd){
+ my $stmt = "SELECT PLAYER,SECURITY FROM PLAYER WHERE ".
+ "LOGIN=$user";
+ ($player, $sec) = $self->single_select($stmt);
+ }else{
+ my $stmt = "SELECT PLAYER,SECURITY FROM PLAYER WHERE ".
+ "LOGIN=$user AND PASSWORD=$pwd";
+ ($player, $sec) = $self->single_select($stmt);
+ }
+
+ if($player){
+ if($pwd2 and $pwd3 and $pwd2 eq $pwd3){
+ # change password!
+ $self->update_hash('PLAYER',
+ "LOGIN=$user",
+ {'PASSWORD' => $pwd2});
+ Util::log("password changed!",0); # todo: localize and aufhübschen
+ }
+ # TODO: write last_login
+ return $player;
+ }
+ return 0;
+}
+
+sub write_event{
+ my ($self, $content) = @_;
+
+ $self->insert_hash('EVENT', $content);
+}
+
+sub read_event{
+ my ($self, $id) = @_;
+
+ my $e = $self->single_hash_select('EVENT',"ID=$id");
+ my @args;
+ for my $a (1..($::conf->{-MAX_ARGS})){
+ Util::log("search for ARG$a...",2);
+ push @args, $e->{"ARG$a"};
+ }
+
+ Util::log("args in read_event: @args",2);
+
+ my ($loc,$to);
+ $to = $e->{'LOCATION'} || 'Game';
+
+ return ($to,$e->{'TIME'},$self->loc($e->{'TAG'},@args));
+}
+
+sub delete_event{
+ my ($self, $id) = @_;
+ $self->delete_from('EVENT',"ID=$id");
+}
+
+sub send_message{
+ my ($self, $msg_hash) = @_;
+
+ $msg_hash->{'TIME'} = $self->now();
+ $self->insert_hash('MESSAGE',$msg_hash);
+}
+
+sub read_message{
+ my ($self, $id) = @_;
+
+ my $stmt = "SELECT TIME, MFROM, MSG_TAG, MSG_TEXT, ARG1, ARG2, ARG3, ARG4 ".
+ "FROM MESSAGE WHERE ID=$id";
+ my ($time, $from, $tag, $text, @args) = $self->single_select($stmt);
+
+ # localize it
+ if($tag){
+ # print "tag!";
+ $text = $self->loc($tag, @args);
+ return ($time, $from, $text, @args);
+ }elsif($text){
+ # print "text!";
+ $text = $self->localize_string($text) unless $from;
+ return ($time, $from, $text);
+ }else{
+ return (0, 'unknown message type error in DataBase');
+ }
+}
+
+sub delete_message{
+ my ($self, $id) = @_;
+
+ $self->delete_from('MESSAGE',"ID=$id");
+}
+
+sub read_player{
+ my ($self,$player,$field) = @_;
+ my $stmt = "SELECT $field from PLAYER where PLAYER=$player";
+ return $self->single_select($stmt);
+}
+
+# returns all games for id -1 (admin)
+sub games_of_player{
+ my ($self,$player) = @_;
+
+ if($player > 0){
+ return $self->select_array('ROLE','GAME',"PLAYER=$player");
+ }else{
+ return $self->select_array('GAME','GAME');
+ }
+}
+
+sub open_games{
+ my ($self,$cond) = @_;
+ my $games = $self->select_array('GAME','GAME');
+ # return $games;
+
+ my @log;
+ for my $game (@$games){
+ my $c = "GAME=$game";
+ $c .= "AND $cond" if $cond;
+
+ my $unused = $self->select_array('MAP','LOCATION','',$c);
+
+ push @log, $game if $#{@$unused} + 1;
+ }
+ return \@log;
+}
+
+sub read_single_mobile{
+ my($self,$id) = @_;
+
+ return $self->single_hash_select('MOBILE',"ID=$id");
+}
+
+sub now{
+ my $self = shift;
+ my ($ret) = $self->single_select("SELECT NOW()");
+ return $ret;
+}
+
+# generates a relative time string from an absolute time
+sub relative{
+ my ($self, $absolute) = @_;
+
+ my $now = $self->now();
+ # print "now: $now\nabsolute: $absolute\n";
+
+ my $now_unix = Date::Parse::str2time($now,'GMT');
+ my $absolute_unix = Date::Parse::str2time($absolute,'GMT');
+ # print "now_unix: $now_unix\nabsolute_unix: $absolute_unix\n";
+ my $diff = $absolute_unix - $now_unix;
+
+ if($diff > 0){
+
+ my ($days,$hours,$minutes,$seconds) =
+ Date::Calc::Delta_DHMS(1970,1,1,0,0,0,Date::Calc::Time_to_Date($diff));
+
+ if($days){
+ return $self->loc('TIME_WITH_DAYS',$days,$hours,$minutes,$seconds);
+ }elsif($hours){
+ return $self->loc('TIME_WITH_HOURS',$hours,$minutes,$seconds);
+ }elsif($minutes){
+ return $self->loc('TIME_WITH_MINUTES',$minutes,$seconds);
+ }else{
+ return $self->loc('TIME_WITH_SECONDS',$seconds);
+ }
+ }else{ # $diff <= 0
+ return '';
+ }
+}
+
+1;
+
+
--- /dev/null
+=head1 NAME B<FROGS>
+
+
+B<F>ramework for B<R>ealtime B<O>nline B<G>ames of B<S>trategy
+
+=head1 DESCRIPTION
+
+
+This is a Framework for programming Massive Multiplayer Browsergames
+(MMBG).
+
+The generell idea is to have a SQL-Database, which is accessed over
+DBI, some scripts to do the work at the server and some
+EmbPerl-Scripts to do the user interaction. The wide area of games is
+to different to give the scripts itself, so instead we choose to
+provide some modules which includes the generell function of a MMBG
+and you will program some scripts to do the game-specific
+part. Normally you need:
+
+=over 4
+
+=item create.pl
+
+A script, which generates a world in the database.
+
+=item scheduler.pl
+
+A script which do the commands and deliver the messages. It should run
+as a daemon.
+
+=item check.pl
+
+A script, which checks the logical integrity of the database of your
+game.
+
+=item *.epl
+
+A bunch of Templates for the user-interaction. For instance a
+login.epl to manage the user-authentification and a map.epl to draw a
+graphical map.
+
+=back
+
+As a start you can look at the scripts provided by the Aymargeddon
+project (www.aymargeddon.de), which is based upon FROGS. You should
+maybe use the *.epl-templates from it, because they do much generell
+work and some of them will maybe included in later versions of FROGS.
+
+FROGS consists of the following parts:
+
+=over 4
+
+=item B<FROGS::Map>
+
+An generell baseclass for maps. Includes a generell baseclass for
+locations.
+
+=item B<FROGS::HexTorus>
+
+A special Map derived from FROGS::Map. It is a Torus consisting of
+Hex-Fields.
+
+=item B<FROGS::Check>
+
+This provides generell checking ability for the underlying database.
+
+=item B<FROGS::DataBase>
+
+Here the structur of the Database is defined. You should normally not
+use direct DBI-access to the Database. Use this module instead
+whenever possible.
+
+=item B<FROGS::Config>
+
+You have to change this to configure your Game. See the comments in
+the file.
+
+=back
+
+Look in the perldoc of the parts if you want to know more.
+
+=head1 DATABASE
+
+You also need to provide a FROGS-conform database. Your game database
+can have more tables and fields than this, but the following
+tables/fields are a must have:
+
+=over 4
+
+=item MAP
+
+Fields: LOCATION, GAME
+
+=item COMMANDS
+
+Fields: COMMAND, GAME, PLAYER
+
+=item MESSAGES
+
+Fields: GAME, MESSAGE, PLAYER, FROM
+
+=item LOCALIZE
+
+=item ROLE
+
+=item PLAYER
+
+=back
+
+Look at the database definition in Aymargeddon to get a clue. For
+later versions we will provide a database definition of this minimal
+database to simplify things.
+
+=head1 VERSION
+
+This is Version 0.1 of the FROGS.
+
+=head1 LICENSE
+
+FROGS is Free Software (GPL).
+
+=head1 AUTHOR
+
+FROGS was written by the Aymargeddon development team. Most work done by:
+
+ Benni Baermann (benni AT obda DOT de)
+
+ Dominikus Scherkl
+
+ Jens Kurlanda
+
+Contact us at ragnaroek AT informatik DOT uni-frankfurt DOT de.
+
+=cut
--- /dev/null
+#!/usr/bin/perl -w
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+# generell Game-specific functions
+#
+
+use strict;
+use FROGS::DataBase;
+use FROGS::Util;
+
+package Game;
+use Data::Dumper;
+
+sub new{
+ my ($class,$game,$user,$db) = @_;
+
+ my $self = {};
+
+ # create database-object, if not given with call
+ if (defined $db) {
+ $self->{-db} = $db;
+ } else {
+ $self->{-db} = DataBase->new();
+ }
+ # $db->set_language($lang);
+
+ $self->{-game} = $game;
+ $self->{-user} = $user;
+
+ bless($self,$class);
+}
+
+sub insert_command{
+ my ($self,$cmd,$args,$loc,$player,$exec) = @_;
+ $player = $self->{-user} unless defined $player;
+ my $db = $self->{-db};
+
+ my ($now) = $db->single_select("SELECT NOW()");
+
+ # insert MOBILE Argument in the database-field if any
+ my $mobile = 0;
+ if($args =~ /MOBILE\s*=\s*(\d+)/){
+ $mobile = $1;
+ }
+
+ my $hash = {'GAME' => $self->{-game},
+ 'SUBMIT' => $now,
+ 'PLAYER' => $player,
+ 'COMMAND' => $cmd,
+ 'ARGUMENTS' => $args,
+ 'MOBILE' => $mobile,
+ };
+ if(defined $exec){
+ # insert a phase-2 command
+ $hash->{'EXEC'} = $exec;
+ $hash->{'ACK'} = $now;
+ }else{
+ $hash->{'EXEC'} = $now;
+ }
+ $hash->{'LOCATION'} = $loc if defined $loc;
+ $db->insert_hash('COMMAND',$hash);
+ Util::log("command inserted: $cmd, $args, $loc, $player",1);
+}
+
+sub read_map{
+ my ($self, $fields) = @_;
+ # $fields should NOT be empty
+ return $self->{-db}->select_array('MAP',"LOCATION,$fields","GAME=$self->{-game}");
+}
+
+#
+# Message handling
+#
+
+sub read_messages{
+ my ($self, $fields) = @_;
+ $fields = ','.$fields if $fields;
+ $fields = 'ID'.$fields;
+ my $cond = "GAME=$self->{-game} AND (MTO=0 OR MTO=$self->{-user})";
+ return $self->{-db}->select_array('MESSAGE', $fields, $cond, 'TIME desc');
+}
+
+# sends a raw text, if $hash is not a hash. if it is one, it generates
+# a tag with arguments usable by DataBase::long_loc()
+sub send_message_to{
+ my($self,$user,$hash) = @_;
+
+ $hash->{'MTO'} = $user;
+ $hash->{'GAME'} = $self->{-game};
+
+ $self->{-db}->send_message($hash);
+
+}
+
+sub send_message_to_me{
+ my ($self,$hash) = @_;
+
+ $self->send_message_to($self->{-user},$hash);
+}
+
+sub send_message_to_list{
+ my ($self,$msg_hash,@list) = @_;
+
+ Util::log("send_message_to_list(@list)",2);
+
+ for my $user (@list) {
+ my %copy = (%$msg_hash);
+ $self->send_message_to($user,\%copy);
+ }
+}
+
+sub send_message_to_all{
+ my ($self,$hash) = @_;
+
+ my @roles = $self->get_all_roles();
+ $self->send_message_to_list($hash,@roles);
+}
+
+sub show_message{
+ my ($self,$id) = @_;
+
+ my ($time, $from, $text, @args) = $self->{-db}->read_message($id);
+
+ my $other = $from;
+ # lookup sender
+ $from = $from == 0 ? "Server" : $self->charname($from);
+
+ my $return = "<strong>$from $time:</strong> $text";
+ $return .= ' <a href="player.epl?cmd=SEND_MSG&other='.$other
+ .'">reply</a>' unless $other == 0;
+ return $return;
+}
+
+sub delete_all_messages{
+ my ($self,$time) = @_;
+ # $::conf->{-EPL_DEBUG} = 2;
+ # print "time: $time<p>";
+ $self->{-db}->delete_from('MESSAGE',"GAME=$self->{-game} AND MTO=$self->{-user}".
+ " AND TIME < '$time'");
+ # $::conf->{-EPL_DEBUG} = 0;
+}
+
+# send message to all players, who see this field
+sub send_message_to_field{
+ my($self,$loc,$hash) = @_;
+
+ return unless $::conf->{-SEND_MESSAGE_TO_FIELD};
+
+ my @players = $self->player_see_field($loc);
+ $self->send_message_to_list($hash,@players);
+}
+
+#
+# events
+#
+
+# returns a ref to a list of Event-IDs for a role
+# it includes all game-events and all events on locations seen by the role
+# TODO: accept additional parameter N to return the N newest events
+sub role_events{
+ my $self = shift;
+
+ my $db = $self->{-db};
+ my @loc = $self->seen_locations();
+
+ my $k = $db->select_hash('EVENT','LOCATION','ID',"GAME=$self->{-game}");
+
+ my @ret = ();
+ for my $l (@loc) {
+ push @ret, $k->{$l} if (defined $k->{$l});
+
+ }
+ # print "@ret";
+ return \@ret;
+}
+# returns a ref to a list of Event-IDs for a field
+# it includes all events on locations
+sub field_events{
+ my ($self, $loc) = @_;
+ my $db = $self->{-db};
+ my $qloc = $db->quote($loc);
+ return $db->select_hash('EVENT','ID',0,"GAME=$self->{-game} AND LOCATION=$qloc");
+}
+
+sub show_event{
+ my ($self, $id, $show_field) = @_;
+
+ $show_field = 1 unless defined $show_field and $show_field == 0;
+
+ my ($from, $time, $text, @args) = $self->{-db}->read_event($id);
+
+ # lookup sender
+ if ($from != 'Game') {
+ $from = '<a href ="mapframe.epl?field='.$from.'">'."$from</a>";
+ }
+
+
+ $time = $self->{-db}->relative($time);
+ $from = "" unless $show_field;
+ return "<strong>$from $time:</strong> $text";
+}
+
+sub search_event{
+ my ($self,$tag,$location) = @_;
+
+ $tag = 'EVENT_' . $tag;
+ ($tag,$location) = $self->{-db}->quote_all($tag,$location);
+ return $self->{-db}->single_hash_select('EVENT',"TAG=$tag and LOCATION=$location");
+}
+
+#
+#
+#
+
+# Should be overloaded by derived class
+sub seen_locations{
+ my ($self) = @_;
+ return ();
+}
+
+sub read_field{
+ my ($self,$field,$loc) = @_;
+ $loc = $self->{-db}->quote($loc);
+ my $stmt = "SELECT $field from MAP where GAME=$self->{-game} AND LOCATION=$loc";
+ return $self->{-db}->single_select($stmt);
+}
+
+sub read_player_relations{
+ my ($self, $user) = @_;
+ $user = $self->{-user} unless defined $user;
+
+ # print "user: $user\n";
+ my $r = $self->{-db}->select_hash('ALLIANCE', 'OTHER', 'STATUS',
+ "GAME=$self->{-game} AND PLAYER=$user");
+ # print Dumper $r;
+ return $r;
+}
+
+sub read_single_relation{
+ my ($self,$me,$you) = @_;
+ my $hash = $self->{-db}->single_hash_select('ALLIANCE',
+ "GAME=$self->{-game} AND ".
+ "PLAYER=$me AND ".
+ "OTHER=$you");
+ my $ret = $hash->{'STATUS'};
+ return $ret ? $ret : 'NEUTRAL';
+}
+
+
+sub reverse_player_relations{
+ my ($self) = @_;
+ return $self->{-db}->select_hash('ALLIANCE', 'PLAYER', 'STATUS',
+ "GAME=$self->{-game} AND OTHER=$self->{-user}");
+}
+
+sub read_mobile {
+ my ($self,$fields,$type,$loc,$only_available) = @_;
+ $only_available = 0 unless defined $only_available;
+ # print "read_mobile($fields,$type,$loc,$only_available)\n";
+ my $cond = "GAME=$self->{-game} AND LOCATION=$loc";
+ if ($only_available > 0) {
+ $cond .= " AND AVAILABLE=Y";
+ } elsif ($only_available < 0) {
+ $cond .= " AND AVAILABLE=N";
+ }
+ $cond .= " AND TYPE=$type" if $type;
+ return $self->{-db}->select_array('MOBILE', $fields, $cond);
+}
+
+sub read_mobile_condition{
+ my ($self,$fields,$cond,$loc) = @_;
+ $cond = "GAME=$self->{-game} AND $cond";
+ $cond .= " AND LOCATION=$loc" if defined $loc;
+ $self->{-db}->select_array('MOBILE',$fields,$cond);
+}
+
+# counts available mobiles of TYPE and OWNER (or all owners) in LOCATION
+# TODO: we can do this in SQL with "select sum(COUNT) from MOBILE where ..."
+sub count_mobile{
+ my ($self,$type,$loc,$owner) = @_;
+
+ my $mobs = $self->read_mobile('COUNT,OWNER',$type,$loc,1);
+ my $count = 0;
+ for my $mob (@$mobs) {
+ my $nr = $mob->[0];
+ if (defined $owner) {
+ $count += $nr if $mob->[1] == $owner;
+ } else {
+ $count += $nr;
+ }
+ }
+ return $count;
+}
+
+# count all people in $loc from $player
+sub count_people{
+ my($self,$loc,$player) = @_;
+ $player = $self->{-user} unless defined $player;
+
+ my $cond = $self->{-db}->quote_condition("GAME=$self->{-game} ".
+ "AND OWNER=$player ".
+ "AND AVAILABLE=Y ".
+ "AND LOCATION=$loc");
+ my $stmt = "select sum(COUNT) from MOBILE where $cond";
+ my ($ret) = $self->{-db}->single_select($stmt);
+ return $ret;
+}
+ # stupid, GAME not necessary: ID is unique between different games
+sub get_mobile_info {
+ my ($self, $mob_id, $fields) = @_;
+ my $stmt = "SELECT $fields from MOBILE where GAME=$self->{-game} AND ID=$mob_id";
+ return $self->{-db}->single_select($stmt);
+}
+
+# WARNING: in Aymargeddon, this is overloaded in Aymargeddon.pm
+sub own_in_mobile{
+ my($self,$loc,$player,$active) = @_;
+ # $loc = $self->{-db}->quote($loc);
+ my $cond = "GAME=$self->{-game} AND LOCATION=$loc".
+ " AND (OWNER=$player OR ADORING=$player)";
+ if (defined $active) {
+ # my $y = $self->{-db}->quote('Y');
+ $cond .= " AND AVAILABLE=Y";
+ }
+ return $self->{-db}->select_array('MOBILE','ID',$cond);
+}
+
+sub read_role{
+ my ($self,$player,$field) = @_;
+ my $stmt = "SELECT $field from ROLE where GAME=$self->{-game} AND PLAYER=$player";
+ return $self->{-db}->single_select($stmt);
+}
+
+sub get_all_roles{
+ my ($self,$role) = @_;
+
+ my $cond = "GAME=$self->{-game}";
+ if (defined $role) {
+ # $role = $self->{-db}->quote($role);
+ $cond .= " AND ROLE=$role";
+ }
+ my @roles = @{$self->{-db}->select_array('ROLE','PLAYER',$cond)};
+ for my $i (0..$#roles) {
+ $roles[$i] = $roles[$i]->[0];
+ }
+ return @roles;
+}
+
+sub get_speed {
+ my $self = shift;
+ my ($ret,$run) = $self->{-db}->single_select("select SPEED, RUNNING from GAME".
+ " where GAME = $self->{-game} ");
+ return $run eq 'Y' ? $ret : - $ret;
+}
+
+sub charname{
+ my ($self,$player,$do) = @_;
+ return $self->{-db}->loc('UNASSIGNED') if $player < 1;
+ my @list = $self->read_role($player, 'NICKNAME');
+ return $list[0];
+}
+
+sub role{
+ my ($self,$player) = @_;
+ return 'OBSERVER' if $player < 1;
+ my @role = $self->read_role($player, 'ROLE');
+ return $role[0];
+}
+
+1;
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+use strict;
+use POSIX qw(ceil floor);
+
+use FROGS::Config;
+use FROGS::Map;
+
+# We define two classes, which gives an implementation of Maps as a
+# HexTorus.
+
+# TODO: selects to DataBase.pm
+
+#
+# Location. This is a class with two coordinates.
+#
+package Location;
+
+sub new{
+ my ($class,$x,$y) = @_;
+
+ my $self = { -x => $x, -y => $y };
+ bless($self, $class);
+}
+
+sub get{
+ my $self = shift;
+
+ return ($self->{-x},$self->{-y});
+}
+
+sub equal{
+ my ($self, $loc) = @_;
+ my ($x,$y) = $loc->get();
+ return ($x == $self->{-x} and $y == $self->{-y});
+}
+
+sub to_string{
+ my $self = shift;
+ return $self->{-x} . '_' . $self->{-y};
+}
+
+sub from_string{
+ my ($class, $string) = @_;
+
+ # print "CLASS: $class, STRING: $string\n";
+
+ $string =~ /^(\d+)_(\d+)$/;
+ my ($x, $y) = ($1,$2);
+ # print "x: $x, y: $y\n";
+ my $self = { -x => $1,
+ -y => $2,};
+
+ bless($self, $class);
+}
+
+sub pretty{
+ my $loc = shift;
+ $loc =~ s/^(\d+)_(\d+)$/\($1, $2\)/;
+ return $loc;
+}
+
+sub is_wellformed{
+ my $string = shift;
+ return 1 if $string =~ /^(\d+)\_(\d+)$/;
+ return 0;
+}
+
+#
+# Map. Hextorus.
+#
+package HexTorus;
+@HexTorus::ISA = qw(Map);
+
+sub new{
+ my $class = shift;
+ my ($n) = @_;
+
+ my $self = {
+ -size => $n
+ };
+
+ bless($self, $class);
+}
+
+
+# returns a list of neighbours of field x,y in
+# an hex-torus with size 2n * n
+# this function is more effective than the generalised
+# distant_neighbours from Map.pm
+# TODO BUG: dont return doubbles in turn-around
+sub neighbours{
+ my $self = shift;
+ my ($loc) = @_;
+
+ my $n = $self->{-size};
+ my ($x,$y) = $loc->get();
+
+ return (new Location($x,($y-1)%$n),
+ new Location($x,($y+1)%$n),
+ new Location(($x-1)%($n*2),$y),
+ new Location(($x+1)%($n*2),$y),
+ new Location(($x+1)%($n*2),($y-1)%$n),
+ new Location(($x-1)%($n*2),($y+1)%$n));
+}
+
+# returns the neighbour in the given direction.
+# direction can be one of qw(NW N NE S SW SE)
+sub get_neighbour{
+ my ($self, $loc, $dir) = @_;
+ my ($x,$y) = $loc->get();
+
+ $dir = uc($dir);
+ my ($xx,$yy) = ($x,$y);
+ my $n = $self->{-size};
+ if($dir eq 'N'){
+ $yy = ($yy - 1) % $n;
+ }elsif($dir eq 'S'){
+ $yy = ($yy + 1) % $n;
+ }elsif($dir eq 'SW'){
+ $xx = ($xx - 1) % ($n * 2);
+ $yy = ($yy + 1) % $n;
+ }elsif($dir eq 'SE'){
+ $xx = ($xx + 1) % ($n * 2);
+ }elsif($dir eq 'NW'){
+ $xx = ($xx - 1) % ($n * 2);
+ }elsif($dir eq 'NE'){
+ $xx = ($xx + 1) % ($n * 2);
+ $yy = ($yy - 1) % $n;
+ }else{
+ Util::log("HexTorus::get_neighbour(): unknown direction: $dir\n",0);
+ return 0;
+ }
+ return Location->new($xx,$yy);
+}
+
+# returns the direction from $from to $to (assumes they are neighbours)
+sub get_direction{
+ my($self,$from,$to) = @_;
+
+ # print "get_direction(".$from->to_string().", ".$to->to_string().")\n";
+
+ for my $dir (qw(NW N NE S SW SE)){
+ my $neighbour = $self->get_neighbour($from,$dir);
+ # print "test $dir from ".$from->to_string().": ".$neighbour->to_string()."\n";
+ return $dir if $to->equal($neighbour);
+ }
+ return 0;
+}
+
+# returns the distance between two fields in
+# an hex-torus with size 2n * n
+sub distance{
+ my $self = shift;
+ my ($loc1,$loc2) = @_;
+
+ my $n = $self->{-size};
+ my ($xx,$yy) = $loc1->get();
+ my ($x,$y) = $loc2->get();
+
+ if($xx > $n * 2 or $x > $n * 2 or $yy > $n or $y > $n){
+ print "range error in distance ($n,$xx,$x,$yy,$y) !\n";
+ return 0;
+ }
+
+ return 0 if($xx == $x and $yy == $y);
+
+ my $xd = abs($x-$xx);
+ $xd = 2 * $n - $xd if $xd > $n;
+ my $sd = abs($x-$xx+$y -$yy) % $n;
+ $sd = $n - $sd if 2* $sd > $n;
+ my $yd = abs($y-$yy);
+ $yd = $n - $yd if 2 * $yd > $n;
+
+ if($xd+$yd+$sd == $n){
+
+ if(2*$xd == $n) # this occures only for even n
+ {
+ # there must be some easier way to distinguish
+ # fields in se/nw direction from those in sw/ne
+ # but this works.
+ my $xp = abs($x-$xx+1);
+ $xp = 2 * $n - $xp if $xp > $n;
+ my $sp = abs($x -$xx +$y -$yy +1) % $n;
+ $sp = $n - $sp if 2* $sp > $n;
+ return $xd if $xp+$sp != $xd+$sd;
+ }
+ $yd = $sd if $sd > $yd;
+ return $n-$yd;
+ }
+ return $xd if 2 * $xd > $n;
+ return ($xd+$yd+$sd)/2;
+}
+
+# returns a random location
+sub random{
+ my $self = shift;
+ my $n = $self->{-size};
+
+ my $x = POSIX::floor(rand($n*2));
+ my $y = POSIX::floor(rand($n));
+
+ my $loc = new Location($x,$y);
+ return $loc;
+}
+
+# iterator for all locations
+sub next{
+ my $self = shift;
+ my $loc = shift;
+ my $n = $self->{-size};
+
+ my ($x, $y) = $loc->get();
+ if(++$x > $n * 2)
+ {
+ $x = 0;
+ $y = 0 if(++$y > $n);
+ }
+ return new Location($x, $y);
+}
+
+# returns all locations for which $code evals to true
+sub grep{
+ my $self = shift;
+ my $code = shift;
+
+ my $n = $self->{-size};
+
+ my @result;
+ for my $x (0..($n*2-1)){
+ for my $y (0..($n-1)){
+ my $loc = new Location($x,$y);
+ # print $loc->to_string() . "\n";
+ if(&$code($loc)){
+ push @result, $loc;
+ }
+ }
+ }
+ return @result;
+}
+
+
+sub fill_array{
+ my $self = shift;
+ my @mapping = @_;
+
+ my @array;
+ for my $terrain (@mapping){
+ for my $xy (@{$terrain->[0]}){
+ my ($x,$y) = $xy->get();
+ $array[$x][$y] = $terrain->[1],
+ }
+ }
+ return \@array;
+}
+
+# TODO: use FROGS::DataBase.pm
+sub write_db{
+ my ($self, $dbh, $game_id, $game_name, $game_speed, $default, @mapping) = @_;
+ $default = $dbh->quote($default);
+ $game_name = $dbh->quote($game_name);
+
+ my $n = $self->{-size};
+
+ # create game
+ my $insert_game = "INSERT INTO GAME (GAME,NAME,SIZE,SPEED,FORTUNE,START_MANA) VALUES".
+ " ($game_id,$game_name,$n,$game_speed,".
+ "$::conf->{-START_FORTUNE},$::conf->{-START_MANA})";
+ print $insert_game ."\n";
+ my $h = $dbh->prepare($insert_game);
+ $h->execute();
+ $h->finish();
+
+ my @db_map = @{$self->fill_array(@mapping)};
+
+ # fill map
+ for my $y (0..($n - 1)){
+ for my $x ( 0 .. ($n*2-1)){
+ my $insert_map;
+ my $loc = new Location($x,$y);
+ my $loc_string = $dbh->quote($loc->to_string());
+ if(defined $db_map[$x][$y]){
+
+ $insert_map = "INSERT INTO MAP (GAME,LOCATION,TERRAIN)".
+ "VALUES ($game_id,$loc_string,".
+ $dbh->quote($db_map[$x][$y]).")";
+ }else{
+
+ $insert_map = "INSERT INTO MAP (GAME,LOCATION,TERRAIN)".
+ "VALUES ($game_id,$loc_string,$default)";
+ }
+ # print "$insert_map\n";
+
+ $dbh->do($insert_map);
+ }
+ }
+}
+
+sub write_string{
+ my $self = shift;
+ my $default = shift;
+ my $default_string = shift;
+ my @mapping = @_;
+
+ my @ascii_map = @{$self->fill_array(@mapping)};
+
+ my $n = $self->{-size};
+ my $out = "\n";
+ for my $y (0..($n - 1)){
+ for my $x ( 0 .. ($n*2-1)){
+ if(defined $ascii_map[$x][$y]){
+ $out .= $ascii_map[$x][$y] ;
+ }else{
+ $out .= $default;
+ }
+ $out .= " ";
+ }
+ $out .= "\n" . (' ' x ($y +1));
+ }
+ $out .= "\n";
+
+ $out .= "Legend:\n";
+ $out .= "$default_string: \t$default\n";
+ for my $terrain (@mapping){
+ $out .= $terrain->[2] . ": \t" .
+ $terrain->[1] . "\n";
+ }
+ return $out;
+}
+
+return 1;
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+# This file holds a baseclass for the topology of the game.
+# All methods here are independent of a concrete topology.
+# but they require, that such dependent functions exists,
+# so this base class did not work if there is no derived class.
+#
+# Derived classes have to implement the following functions
+#
+# grep() - return a list of all locations with true evaluation of sub
+# neighbours() - returns a list of all neigbours of location
+# distance() - returns the distance between two locations
+#
+# have a look at HexTorus.pm to see an example
+
+
+package Map;
+
+use strict;
+
+# returns all locations
+sub get_all{
+ my $self = shift;
+
+ return $self->grep(sub{1;});
+}
+
+# returns all locations with distance <= dist arround loc
+sub distant_neighbours{
+ my ($self,$loc,$dist) = @_;
+
+ # for performance reason
+ # TODO: do this only, if neighbours() is avaiable in the derived class
+ return $self->neighbours($loc) if $dist == 1;
+
+ return $self->grep(sub{
+ my $loc2 = shift;
+ return $self->distance($loc,$loc2) <= $dist;});
+
+}
+
+1;
+
+
--- /dev/null
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+# Here we gather some utility-functions
+#
+
+use strict;
+use FROGS::DataBase;
+use FROGS::Config qw ($conf);
+
+package Util;
+use Data::Dumper;
+
+# parse the command-line (or any other string-array)
+# and overwrites $::conf with the new values
+# example: ./scheduler.pl -DURATION-PRAY=1000 -MANA-BLESS_PRIEST=10
+sub overwrite_config{
+ my @arr = @_;
+ for my $arg (@arr){
+ my ($left,$right) = split /=/,$arg;
+ my @parts = split /-/, $left;
+
+ # TODO: generalization
+ if($parts[2]){
+ $::conf->{"-$parts[1]"}->{"-$parts[2]"} = $right;
+ }else{
+ $::conf->{"-$parts[1]"} = $right;
+ }
+ }
+}
+
+# returns 1 if $scalar is in @list
+sub is_in{
+ my ($scalar, @list) = @_;
+
+ for my $le (@list) {
+ return 1 if $le eq $scalar;
+ }
+ return 0;
+}
+
+# returns all elements of @$A which are _not_ in @$B
+# in an array reference
+sub without{
+ my ($A, $B) = @_;
+
+ my %h = ();
+ for my $b (@$B){
+ $h{$b} = 1;
+ }
+
+ my @A_without_B = ();
+ for my $a (@$A){
+ push @A_without_B, $a unless exists $h{$a};
+ }
+ return \@A_without_B;
+}
+
+sub log{
+ my ($string,$level) = @_;
+
+ my $abslevel = $level;
+ my $do = 0;
+
+ # TODO: dirty hack, use caller() instead
+ if($0 eq '-e'){
+ $string .= "<p>";
+ $do = 1 if $::conf->{-EPL_DEBUG} >= $abslevel;
+ }else{
+ $do = 1 if $::conf->{-DEBUG} >= $abslevel;
+
+ if($::conf->{-FULL_DEBUG_FILE}){
+ # FULL_LOG in file
+ if($level >= 0){
+ print FULL_LOG "$string\n";
+ }else{
+ print FULL_LOG "$string";
+ }
+ }
+ }
+ # negativ values for level prints no newline
+ if($do){
+ if($level >= 0){
+ print "$string\n";
+ }else{
+ print "$string";
+ }
+ }
+}
+
+sub open_log{
+ my $file = $::conf->{-FULL_DEBUG_FILE};
+ open(FULL_LOG,">$file") or die "can't open $file: $!";
+}
+
+sub close_log{
+ close FULL_LOG;
+}
+
+sub min{
+ my @list = @_;
+
+ my $min = 99999999;
+ for my $elem (@list){
+ $min = $elem if $elem < $min;
+ }
+ return $min;
+}
+
+sub max{
+ my @list = @_;
+
+ my $max = -99999999;
+ for my $elem (@list){
+ $max = $elem if $elem > $max;
+ }
+ return $max;
+}
+
+# returns a shuffled list
+sub shuffle {
+ my $array_ref = shift;
+
+ my @shuffled = sort { int(rand(3)) - 1 } @$array_ref;
+
+ return \@shuffled;
+}
+
+1;
+
--- /dev/null
+#!/usr/bin/perl -w
+#########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of
+# "FROGS" = Framework for Realtime Online Games of Strategy
+#
+# FROGS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# FROGS is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+# scheduler daemon
+#
+# usage:
+# ./scheduler.pl [conf-parameter]=[value] ...
+# example:
+# ./scheduler.pl -DURATION-PRAY=1000 -DURATION-PRODUCE=1000
+
+use strict;
+use lib qw(..);
+use FROGS::DataBase;
+use FROGS::Command;
+use FROGS::Config qw ($conf);
+use Data::Dumper;
+
+$|=1;
+
+Util::open_log();
+
+# read command line
+Util::overwrite_config(@ARGV);
+
+my $KEYCOL="SUBMIT";
+
+my $db= new DataBase;
+# $db->nowrite();
+require $::conf->{-COMMANDS};
+my $now = $db->now();
+Util::log("\n$now Scheduler started...",0);
+loop();
+exit;
+
+sub loop {
+ # read next using our db connection (complicated due to poor SQL
+ # implemention of MYSQL :-/
+ my $nulldate = $db->quote('0000-00-00 00:00:00'); # TODO: ugly and unportable :-(
+ my $nullcond = "(DONE IS NULL OR DONE=$nulldate)";
+ my $count = 0;
+ while (1) {
+ $count++;
+ $db->commit(); # ??? WHY IS THIS NECESSARY TO SEE COMMANDS FROM CLIENTS ???
+ my ($minexec) = $db ->single_select("SELECT min( exec ) FROM COMMAND ".
+ "WHERE $nullcond and EXEC <= NOW()");
+ $minexec = $db ->quote($minexec);
+ my ($id) = $db ->single_select("SELECT min(id) FROM COMMAND ".
+ "WHERE $nullcond and EXEC = $minexec");
+ $id= $db ->quote($id);
+ my $command_entry = $db ->single_hash_select("COMMAND",
+ "EXEC = $minexec and ID = $id ");
+
+ # delete outdated events
+ $db->delete_from('EVENT','TIME < NOW()') if $::conf->{-DELETE_OLD_EVENTS};
+
+ if (! defined $command_entry ) {
+ # sleep if no command in db
+ sleep ($::conf->{-SCHEDULER_SLEEP});
+ Util::log('.',-1);
+
+ if($count % $::conf->{-LOG_TIME_IN_LOOP} == 0){
+ my $now = $db->now();
+ Util::log("\n###\n### $now: counted $count loops\n###\n",1);
+ }
+ next;
+ }
+
+ # create command object
+ my $command = $command_entry->{"COMMAND"}->new($command_entry,$db);
+ # execute command
+ if($command){
+ $command->execute();
+ $db->commit;
+ }
+ }
+};
+
--- /dev/null
+ ./scheduler.pl -DURATION-PRAY=1000 -DURATION-PRODUCE_PRIEST=1000 \
+ -DURATION-PRODUCE_WARRIOR_HOME=1000 \
+-DURATION-PRODUCE_PRIEST_HOME=1000 \
+-DURATION-MOVE_WARRIOR=1 \
+-DURATION-MOVE_PRIEST=1 \
+-DURATION-MOVE_HERO=1 \
+-DURATION-MOVE_ARK=1 \
+-DURATION-FIGHT_EARTHLING=1 \
+-DURATION-FIGHT_GOD=1000 \
+-DURATION-PLAGUE=1000 \
+-DURATION-PRODUCE_WARRIOR=1000 \
+-DURATION-FLOOD=1 \
+-DURATION-BUILD_TEMPLE=1 \
+-DURATION-BUILD_ARK=1 # -SEND_MESSAGE_TO_FIELD=0
+
--- /dev/null
+killall scheduler.pl
+nohup /home/benni/aymargeddon/current/src/FROGS/scheduler.pl >> /home/benni/aymargeddon/current/src/FROGS/++out 2>&1 &
--- /dev/null
+#!/usr/bin/perl -w
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+#
+# checks the integrity of the database.
+#
+# usage: ./check.pl [-l] [list of checks]
+# no args: do all checks
+# -l: lists all avaiable checks
+# -h: help
+# list of checks: do only this checks
+
+use strict;
+$|=1;
+use DBI;
+use Data::Dumper;
+use POSIX qw(floor ceil);
+use Term::ReadLine;
+
+use FROGS::HexTorus;
+use FROGS::Check;
+use FROGS::Config;
+
+$::conf->{-FULL_DEBUG_FILE} = 0;
+# Util::open_log();
+
+#
+# Aymargeddon-specific behaviour
+#
+
+# TODO: should also check, if the location is valid in this map
+my $location_wellformed_check = sub {
+ my $loc = shift;
+ my $wf = Location::is_wellformed($loc);
+ print "$loc is in bad form! " unless $wf;
+ return $wf;
+};
+
+my $fight_and_occupant = sub {
+ my $db = shift;
+ my $dbh = $db->{-dbh};
+
+ my $stmt = 'SELECT GAME,LOCATION,OCCUPANT,ATTACKER,TERRAIN,HOME FROM MAP WHERE 1';
+ my $map = $dbh->selectall_arrayref($stmt);
+
+ # for every field in MAP
+ for my $field (@$map){
+ my ($game,$loc,$occ,$att,$terrain,$home) = @$field;
+ Util::log("testing field $loc, game $game: occupant $occ, attacker: $att",1);
+
+ # read all earthling mobiles in field
+ my $cond = "LOCATION='$loc' AND GAME=$game AND AVAILABLE='Y'".
+ " AND (TYPE='WARRIOR' OR TYPE='PRIEST' OR TYPE='HERO' OR TYPE='PROPHET')";
+ # my $qcond = $db->quote_condition($cond);
+ $stmt = "SELECT OWNER FROM MOBILE WHERE $cond";
+ my $mobiles = $dbh->selectall_arrayref($stmt);
+
+ # search for earthlings
+ my @earthlings = ();
+ my $earthlings = {};
+ for my $mob (@$mobiles){
+ my ($own) = @$mob;
+ next if exists $earthlings->{$own};
+ $earthlings->{$own} = 1;
+ push @earthlings, $own;
+ }
+ # print Dumper \@earthlings;
+
+ if($occ){
+ return "game $game: no earthlings in field $loc with occupant $occ.\n"
+ if ($#earthlings == -1 and not ($terrain eq 'CITY' and $home));
+ }else{
+ return "game $game: earthlings in field $loc without occupant.\n"
+ if $#earthlings > -1;
+ }
+
+ if($att){
+ return "game $game: only one earthling in field $loc from $occ, ".
+ "attacked from $att\n" if $#earthlings == 0;
+ }else{
+ return "game $game: more than one earthling in peaceful field $loc."
+ if $#earthlings > 0;
+ next if $#earthlings < 0;
+ return "game $game: occupant $occ is not the only earthling $earthlings[0]".
+ " in field $loc"
+ if $occ != $earthlings[0];
+ }
+ }
+ return 0;
+};
+
+
+# list of checks
+# every check consists of ID,behaviour
+# behaviour is one of A_IN_B, LOGIK or UNIVERSAL
+
+my $check = {
+ -GAME_EXISTS_FOR_MAP =>
+ ['A_IN_B', ['MAP','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_ALLIANCE =>
+ ['A_IN_B', ['ALLIANCE','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_COMMAND =>
+ ['A_IN_B', ['COMMAND','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_GOD =>
+ ['A_IN_B', ['GOD','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_GOD =>
+ ['A_IN_B', ['GOD','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_MESSAGE =>
+ ['A_IN_B', ['MESSAGE','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_ROLE =>
+ ['A_IN_B', ['ROLE','GAME','GAME','GAME']],
+ -GAME_EXISTS_FOR_MOBILE =>
+ ['A_IN_B', ['MOBILE','GAME','GAME','GAME']],
+
+ -LOCATION_WELLFORMED_IN_MAP =>
+ ['LOGIC',['MAP',['LOCATION'],$location_wellformed_check]],
+ -LOCATION_WELLFORMED_IN_MOBILE =>
+ ['LOGIC',['MOBILE',['LOCATION'],$location_wellformed_check]],
+ # TODO?: implement write last_temple
+ # -LAST_TEMPLE_WELLFORMED_IN_GAME =>
+ # ['LOGIC',['GAME',['LAST_TEMPLE'],$location_wellformed_check]],
+
+ -FIGHT_AND_OCCUPANT =>
+ ['UNIVERSAL', $fight_and_occupant],
+
+ };
+
+my $checker = Check->new();
+$checker->check_all($check);
+
+
--- /dev/null
+#!/usr/bin/perl -w
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+#
+# creates the world to destroy
+#
+# usage: ./create.pl [number of eartlings]
+#
+#
+
+# TODO: use FROGS/DataBase.pm instead of DBI.pm
+
+use strict;
+
+$| = 1;
+
+use DBI;
+use Data::Dumper;
+use POSIX qw(floor ceil);
+use Term::ReadLine;
+ my $t = Term::ReadLine->new('test');
+
+use FROGS::HexTorus;
+use FROGS::Config qw($conf);
+use FROGS::DataBase;
+use FROGS::Game;
+
+Util::open_log();
+
+my $earthlings = $ARGV[0] || 10; # number of earthlings
+
+my $dont_ask = defined $ARGV[1] ? 1 : 0;
+
+my $db_source = $::conf->{-DB_SOURCE};
+my $db_user = $::conf->{-DB_USER};
+my $db_passwd = $::conf->{-DB_PASSWD};
+
+my $ascii = {-pole => '@',
+ -city => '+',
+ -home => '#',
+ -water => '~',
+ -island => '°',
+ -mountain => '^',
+ -plain => '\''};
+
+# set to 0 to not change size of world during generation
+# set to positive value to set the number of itterations need to pumpup
+my $pump_up_world = 10;
+
+# TODO: maybe to small?
+my $n = ceil(sqrt($earthlings * 7)); # size of world
+
+my $pole_count = floor(sqrt($n));
+my $min_pole_distance = ceil($n/2);
+my $water_count = floor($n*$n/2);
+#TODO: number of islands should depend on players, not on size
+my $island_count = floor($water_count/3);
+my $min_home_distance = $::conf->{-MIN_DISTANCE_HOME};
+my $min_mountain_distance = $::conf->{-MIN_DISTANCE_MOUNTAIN};
+my $wanted_mountain_distance = $::conf->{-WANTED_DISTANCE_MOUNTAIN};
+my $min_water_distance = $::conf->{-MIN_DISTANCE_MOUNTAIN_FROM_WATER};
+my $city_count = $earthlings * 4;
+my $mountain_count = floor($earthlings);
+
+my $nn = 0;
+my $map;
+while (1) {
+ if ($pump_up_world and $nn > $pump_up_world) {
+ $n++;
+ print "*** World to small! Make it bigger! New size $n.***\n";
+ $nn = 0;
+ }
+ my $not_enough_room = 0;
+ $map = new HexTorus($n);
+ $pole_count = floor(sqrt($n));
+ $min_pole_distance = ceil($n/2);
+ $water_count = floor($n*$n/2);
+ $island_count = floor($water_count/3);
+
+ # TODO: uggly structure
+ my $print = 0;
+ print "generate poles ...\n";
+ my @pole = distribute($pole_count,$min_pole_distance,
+ $min_pole_distance,$min_pole_distance);
+ $not_enough_room = 1 unless $pole[0];
+ my (@water,@islands,@home,@mountains,@not_cities,@cities);
+ unless ($not_enough_room){
+ print "generate water ...\n";
+ @water = flood($water_count,@pole);
+ }
+ unless ($not_enough_room){
+ print "generate islands ...\n";
+ @islands = vulcano($island_count, \@water, \@pole);
+ }
+ unless ($not_enough_room){
+ print "generate mountains ...\n";
+ @mountains = distribute($mountain_count,$min_water_distance,
+ $min_mountain_distance,$wanted_mountain_distance,[],@water);
+ $not_enough_room = 1 unless $mountains[0];
+ }
+ # print print_list(@mountains);
+ unless ($not_enough_room){
+ print "generate homecitys ...\n";
+
+ for my $i (1..50){
+ @home = homeland(@mountains,@pole,@water,@islands);
+ # $print = 1 unless $#home<$#mountains;
+ last unless $#home<$#mountains;
+ print " RETRY...\n";
+ my $mref = Util::shuffle(\@mountains);
+ @mountains = @$mref;
+ }
+ print "\n";
+ $not_enough_room = 1 if $#home<$#mountains;
+ }
+
+ unless ($not_enough_room){
+ print "generate citys ...\n";
+ @not_cities = (@water,@pole,@mountains,@islands,@home);
+ @cities = build($city_count,\@home,\@not_cities);
+ $not_enough_room = 1 unless $cities[0];
+ }
+
+
+ if (not $not_enough_room or $print) {
+ #print "Pole: " . print_list(@pole);
+ #print "Water: " . print_list(@water);
+ #print "Islands: " . print_list(@islands);
+ #print "Mountains: " . print_list(@mountains);
+ #print "Cities: " . print_list(@cities);
+ #print "Homes: " . print_list(@home);
+
+ print "Earthlings: $earthlings\n".
+ "Gods: " . ($earthlings/2) . "\n".
+ "Size of world: $n\n".
+ "Number of poles: $pole_count\n".
+ "Minimum pole distance: $min_pole_distance\n".
+ "Water: $water_count\n".
+ "Islands: $island_count\n".
+ "Citys: $city_count\n".
+ "Plain: " . ( ($n * $n * 2) - ($water_count + $pole_count +
+ $earthlings + $city_count)) . "\n";
+
+ print $map->write_string($ascii->{-plain},"Plain",
+ [\@pole,$ascii->{-pole},"Pole"],
+ [\@water,$ascii->{-water},"Water"],
+ [\@islands,$ascii->{-island},"Islands"],
+ [\@home,$ascii->{-home},"Home"],
+ [\@mountains,$ascii->{-mountain},"Mountains"],
+ [\@cities,$ascii->{-city},"Cities"]);
+ die if $print;
+ } else {
+ $nn++;
+ print "\nNot enough room! Try again ...\n";
+ next;
+ }
+
+ my $r = $dont_ask ? 'y' :
+ $t->readline('Wrote this world to database? (n/q/[name_of_game])');
+
+ if ($r =~ /^q$/i) {
+ exit;
+ } elsif ($r =~ /^n$/i) {
+ next;
+ } else {
+ my $speed = $dont_ask ? 3600 :
+ $t->readline('Speed of game in seconds per game step: ');
+
+ my $dbh = DBI->connect("dbi:$db_source",$db_user,$db_passwd,
+ {
+ 'RaiseError' => 1,'AutoCommit' => 0});
+
+ # TODO: use DataBase::find_first_free("GAME","GAME")
+
+ my $table = $dbh->selectall_arrayref("select GAME from GAME");
+ my @game_ids = sort {$a <=> $b} (map {$_->[0]} @$table);
+
+ my $game = 1;
+ for my $try (@game_ids) {
+ last if $game < $try;
+ $game = $try + 1;
+ }
+
+ print "Erste Freie Game ID: $game\n";
+ my $db = DataBase->new($dbh);
+ my $aymgame = Game->new($game,-1,$db);
+
+ $map->write_db($dbh,$game,$r,$speed,'PLAIN',
+ [\@pole,"POLE"],
+ [\@water,"WATER"],
+ [\@islands,"ISLE"],
+ [\@home,"CITY"],
+ [\@mountains,"MOUNTAIN"],
+ [\@cities,"CITY"]);
+
+ # mark home cities and holy mountains
+ for my $home (@home, @mountains) {
+ my $lo = $dbh->quote($home->to_string());
+ my $cmd = "UPDATE MAP SET HOME=-1 where GAME=$game AND LOCATION=$lo";
+ $dbh->do($cmd);
+ }
+
+ # set home cities occupied
+ # insert PRODUCE Commands for Homecitys
+ for my $home (@home) {
+ my $l = $dbh->quote($home->to_string());
+ my $c = "UPDATE MAP SET OCCUPANT=-1 where GAME=$game AND LOCATION=$l";
+ $dbh->do($c);
+
+ $aymgame->insert_command('PRODUCE','ROLE=-1',$home->to_string());
+ }
+
+ # make one of the poles startup aymargeddon
+ my $aym = $pole[rand($#pole + 1)];
+ my $ter = $dbh->quote('AYMARGEDDON');
+ my $loc = $dbh->quote($aym->to_string());
+ my $comd = "UPDATE MAP SET TERRAIN=$ter where GAME = $game AND LOCATION=$loc";
+ $dbh->do($comd);
+
+ # check some values
+ $::conf->{-DEBUG} = 0;
+ print "Check in the database:\n";
+ my $m_count = $db->count('MAP', "GAME=$game AND TERRAIN=MOUNTAIN");
+ my $h_count = $db->count('MAP', "GAME=$game AND TERRAIN=CITY AND HOME=-1");
+ my $o_count = $db->count('MAP', "GAME=$game AND OCCUPANT=-1");
+ print "Mountains: " . $m_count;
+ print "\nCitys: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=CITY");
+ print "\nHomes: " . $h_count;
+ print "\nIslands: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=ISLE");
+ print "\nPoles: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=POLE");
+ print "\nAymargeddon: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=AYMARGEDDON");
+ print "\nWater: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=WATER");
+ print "\nPlain: " . $db->count('MAP',
+ "GAME=$game AND TERRAIN=PLAIN");
+ print "\nOccupied: " . $o_count;
+ print "\n";
+
+ if($o_count != $h_count or $h_count != $m_count or $m_count != $o_count){
+ print "homes: ". print_list(@home) . "\nmountains: ".
+ print_list(@mountains) . "\ncities: " . print_list(@cities) . "\n";
+ my $boesewichter = $db->select_array('MAP',
+ 'LOCATION',
+ "GAME=$game AND HOME=-1 AND ".
+ "OCCUPANT=0 AND TERRAIN=CITY");
+ print "boesewichter: "; print map $_->[0] . ", ", @$boesewichter;print "\n";
+ }
+
+ $dbh->commit();
+ $dbh->disconnect();
+
+
+ exit;
+ }
+}
+
+# distributes homecitys near mountains
+sub homeland{
+ my @mountains = @_;
+
+ my %mountains = ();
+ for my $m (@mountains){
+ $mountains{$m->to_string()} = 1;
+ }
+
+ my %homes = ();
+ for my $m (@mountains){
+ my @neighbours = $map->neighbours($m);
+
+ my $home;
+ while($#neighbours >= 0){
+ my $rand = rand($#neighbours + 1);
+ $home = $neighbours[$rand];
+ my @home_neighbours = $map->neighbours($home);
+ my ($m_count,$h_count) = (0,0);
+ for my $hn (@home_neighbours){
+ $h_count++ if exists $homes{$hn->to_string()};
+ $m_count++ if exists $mountains{$hn->to_string()};
+ }
+ if($h_count == 0 and $m_count == 1){
+ my $valid = 1;
+ for my $h (keys %homes){
+ my $d = $map->distance(Location->from_string($h),$home);
+ if($d < $::conf->{-MIN_DISTANCE_HOME}){
+ $valid = 0;
+ }
+ }
+ if($valid){
+ $homes{$home->to_string()} = 1;
+ print "#";
+ last;
+ }
+ }
+ splice @neighbours,$rand,1;
+ }
+ last unless $#neighbours >= 0;
+ }
+ my @ret = ();
+ for my $h (keys %homes){
+ push @ret, Location->from_string($h);
+ }
+ return @ret;
+}
+
+sub build{
+ my ($count,$homes,$exclude) = @_;
+
+ my %ex;
+ if ($exclude) {
+ for my $f (@$exclude) {
+ $ex{$f->to_string()} = 1;
+ }
+ }
+
+ # build two cities in neihgbourhood of each home
+ my %cities = ();
+ for my $home (@$homes){
+ # print "build citys for " . $home->to_string() . ": ";
+ my @neighbours = $map->neighbours($home);
+
+ # exclude non buildable terrain
+ my $i = 0;
+ for my $n (@neighbours){
+ my $nstr = $n->to_string();
+ if($ex{$nstr}){
+ splice @neighbours,$i,1;
+ }
+ $i++;
+ }
+
+ # build citys
+ my $cities = $::conf->{-NEIGHBOUR_CITIES};
+ while($cities){
+ my $r = rand($#neighbours+1);
+ my $rstr = $neighbours[$r]->to_string();
+ # print " build city in $rstr\n";
+ $cities{$rstr} = 1;
+ $ex{$rstr} = 1;
+ splice @neighbours,$r,1;
+ $cities--;
+ }
+
+ # exclude all remaining neighbours
+ for my $n (@neighbours){
+ $ex{$n->to_string()} = 1;
+ }
+ }
+
+ # distribute the remaining cities to fields, which are not neighbours of a home
+ while($count){
+ my $random = $map->random()->to_string();
+ unless(exists $ex{$random}){
+ $ex{$random} = 1;
+ $cities{$random} = 1;
+ $count--;
+ }
+ }
+
+ # TODO: clustering check, no more than n in 2distance
+
+ return map Location->from_string($_), keys %cities;
+}
+
+# DEPRECATED, this function is no longer in use!
+# returns all fields, which are plain and have
+# - 4 or more neighbours ISLAND or WATER
+# - no city as neighbour
+# - more than 2 citys as neighbour
+# - more than 7 citys with distance 2
+sub bad_home{
+ my($water,$islands,$pole,$cities,$mountains) = @_;
+
+ print "look for bad home locations ...\n";
+
+ # my @m = @$mountains; print "mountains: $#m\n";
+
+ # reorganize data into hashes
+ my %ex;
+ for my $f (@$water,@$islands,@$pole){
+ $ex{$f->to_string()} = 1;
+ }
+ my %cit;
+ for my $c (@$cities){
+ $cit{$c->to_string()} = 1;
+ }
+ my %mount;
+ for my $m (@$mountains){
+ $mount{$m->to_string()} = 1;
+ }
+
+ # for all fields
+ my %ret;
+ for my $x (0..($n*2-1)){
+ for my $y (0..($n-1)){
+ my $lstring = "$x\_$y";
+ next if exists $ex{$lstring};
+ next if exists $cit{$lstring};
+ print ".";
+ my $loc = new Location($x,$y);
+
+ # look in the neighboorhood
+ my @neighbours = $map->neighbours($loc);
+ my ($city,$water,$mount) = (0,0,0);
+ for my $n (@neighbours){
+ $city++ if exists $cit{$n->to_string()};
+ $water++ if exists $ex{$n->to_string()};
+ # $mount++ if exists $mount{$n->to_string()};
+ }
+ # $ret{$lstring} = 'no mountain in neighbourhood' if $mount == 0;
+ $ret{$lstring} = 'no city in neighbourhood' if $city == 0;
+ $ret{$lstring} = 'more than 3 cities in neighbourhood' if $city > 3;
+ $ret{$lstring} = 'to much water in neighbourhood' if $water > 3;
+ next if $ret{$lstring};
+
+ # look in distance 2
+ my @dist_neigh = $map->distant_neighbours($loc,2);
+ $city = 0; $mount = 0;
+ for my $n (@dist_neigh){
+ $city++ if exists $cit{$n->to_string()};
+ $mount++ if exists $mount{$n->to_string()};
+ }
+ # print "m: $mount, c: $city\n";
+ $ret{$lstring} = 'more than 7 cities in distance 2' if $city > 7;
+ $ret{$lstring} = 'less than 2 cities in distance 2' if $city < 2;
+ $ret{$lstring} = 'no mountain in distance 2' unless $mount;
+ }
+ }
+ print "\n";
+ my @ret;
+ my %stat;
+ for my $r (keys %ret){
+ $stat{$ret{$r}}++;
+ push @ret, Location->from_string($r);
+ }
+ print Dumper \%stat;
+ return @ret;
+}
+
+sub vulcano{
+ my ($count, $w,$p) = @_;
+ my @w = @$w;
+ my @p = @$p;
+
+ my @islands;
+
+ while ($count) {
+ my $water_field = floor(rand($#w) + 1);
+ my $wf = $w[$water_field];
+
+ my $to_close = 0;
+ for my $p (@p) {
+ $to_close = 1 if($map->distance($p,$wf) < 2);
+ }
+ next if $to_close;
+
+ splice @w,$water_field,1;
+ push @islands, $wf;
+ $count--;
+ }
+ return @islands;
+}
+
+sub flood{
+ my ($count, @w) = @_;
+ # print "flood($count,@w)\n";
+
+ # flood neighbours
+ my @new_w;
+ for my $pole (@w) {
+ push @new_w, $map->neighbours($pole);
+ }
+ $count -= $#new_w + 1;
+ return @new_w unless $count > 0;
+
+ my %w;
+ for my $w (@w,@new_w) {
+ $w{$w->to_string()} = 1;
+ }
+ @w = @new_w;
+
+ while ($count) {
+ # print "$count ";
+ # get a random water field
+ my $water_field = floor(rand($#w) + 1);
+ my $wf = $w[$water_field];
+ # get neigbours without water
+ my @nb = $map->neighbours($wf);
+ my @nb_new;
+ for my $nb (@nb) {
+ unless (exists $w{$nb->to_string()}) {
+ push @nb_new, $nb;
+ }
+ }
+ @nb = @nb_new;
+
+ if ($#nb > 0) {
+ # get a random neigbour
+ my $rn = floor(rand($#nb) + 1);
+ my $rnr = $nb[$rn];
+ push @w,$rnr;
+ $w{$rnr->to_string()} = 1;
+ $count --;
+ }
+ }
+ return @w;
+}
+
+# distributes $count locations at the map in minimal distance from
+# fields not at exclude
+# TODO: should be in Map.pm.
+# TODO: should incorporate build() and vulcano()
+# TODO: make shure there is really no field left.
+sub distribute{
+ my ($count,$dist,$min_selfdist,$wanted_selfdist,$exclude,@fields) = @_;
+ my $fields_distance = 2;
+ my $selfdist = $wanted_selfdist;
+
+ # print "minself: $min_selfdist, wantedself: $wanted_selfdist\n";
+
+ # print "fields: @fields\n";
+
+ #print "Exclude: " . print_list(@$exclude);
+
+ my @return_fields;
+
+ my %ex;
+ if ($exclude) {
+ for my $f (@$exclude) {
+ $ex{$f->to_string()} = 1;
+ }
+ }
+
+ my $loop = $earthlings * 10;
+ my $maxloop = $loop;
+ my $short_allowed = 0;
+ while ($loop and $count) {
+ # while($count){
+ my $r = $map->random();
+ my $valid = 1;
+ # if ($valid) {
+ for my $xy (@fields) {
+ my $d = $map->distance($r,$xy);
+ my ($x,$y) = $xy->get();
+
+ if ($d < $dist) {
+ $valid = 0;
+ last;
+ }
+ }
+ my $short_count = 0;
+ for my $xy (@return_fields) {
+ my $d = $map->distance($r,$xy);
+ my ($x,$y) = $xy->get();
+
+ if ($d < $selfdist) {
+ if($d >= $selfdist - 1 and $short_count < 1 and $short_allowed){
+ $short_count++;
+ print $short_count;
+ }else{
+ $valid = 0;
+ last;
+ }
+ }
+ }
+ for my $x (@$exclude){
+ if($r->to_string() eq $x->to_string()){
+ $valid = 0;
+ last;
+ }
+ }
+ # }
+
+ if ($valid) {
+ # push @fields, $r;
+ push @return_fields, $r;
+ $count--;
+ print "+";
+ } else {
+ $loop--;
+ # print "-";
+ if($loop <= 0 and ($selfdist > $min_selfdist)){
+ $loop = $maxloop;
+ # $selfdist--;
+ # print $selfdist;
+ $short_allowed = 1;
+ print "S";
+ }
+
+ next;
+ }
+ # print "c: $count, l: $loop\n";
+ # }
+ }
+
+ print "\n";
+ unless($loop){
+ print "need still room for $count locations\n";
+ return 0;
+ }
+ return @return_fields;
+}
+
+sub print_list{
+ my @f = @_;
+ my $string;
+ for my $l (@f){
+ $string .= $l->to_string() . ', ';
+ }
+ $string .= "\n";
+ return $string;
+}
+
--- /dev/null
+#!/usr/local/bin/perl -w
+##########################################################################
+#
+# Copyright (c) 2003 Aymargeddon Development Team
+#
+# This file is part of "Last days of Aymargeddon"
+#
+# Aymargeddon is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# Aymargeddon is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 675
+# Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+
+#
+#
+# creates the world to destroy
+#
+# usage: ./create.pl [number of eartlings]
+#
+#
+
+# TODO: use FROGS/DataBase.pm instead of DBI.pm
+
+use strict;
+
+use DBI;
+use Data::Dumper;
+use POSIX qw(floor ceil);
+use Term::ReadLine;
+
+use FROGS::HexTorus;
+
+my $n = 16;
+my $map = new HexTorus($n);
+my $out = "\n";
+for my $y (0..($n - 1)){
+ for my $x ( 0 .. ($n*2-1)){
+
+ my $d =
+ $map->distance(Location->new(5,0),
+ Location->new($x,$y));
+ $d = "0$d" if $d < 10;
+ $out .= "$d ";
+ }
+ $out .= "\n" . (' ' x ($y +1));
+}
+$out .= "\n";
+
+print $out;
--- /dev/null
+use FROGS::DataBase;
+# use Aymargeddon;
+# use DBI;
+use strict;
+use Data::Dumper;
+use Date::Calc qw(Time_to_Date);
+
+use FROGS::Command;
+
+use FROGS::Config qw($conf);
+
+$| = 1;
+
+my $d = DataBase->new();
+# $d->nowrite();
+
+my $dbhash =
+# {'LOCATION' => '2_0',
+# 'COMMAND' => 'BUILD_TEMPLE',
+# 'ARGUMENTS' => 'MOBILE=1',
+# 'PLAYER' => 1,
+# 'GAME' => 1,
+# 'ID' => 1007
+# };
+ {'LOCATION' => '11_3',
+ 'COMMAND' => 'PRODUCE',
+ 'ARGUMENTS' => 'ROLE=-1',
+ 'PLAYER' => -1,
+ 'GAME' => 4,
+ 'ID' => 1007,
+ };
+
+
+# print Dumper $dbhash;
+
+require "AymCommand.pm";
+
+my $c = $dbhash->{'COMMAND'}->new($dbhash,$d);
+
+# print "is valid\n" if $c->is_valid();
+$c->{-phase} = 1;
+my $fp = $c->first_phase();
+
+if ($fp){
+ print "first phase correct. duration: $c->{-duration}\n";
+ $c->{-phase} = 2;
+ print "second phase correct\n" if $c->second_phase();
+}else{
+ print "no second phase\n";
+}
+
+$d->commit();
+
+# $d->{-dbh}->disconnect();
+
+# print Dumper $c;
+
+
+
+
+
+
--- /dev/null
+use strict;
+use FROGS::DataBase;
+use Data::Dumper;
+use Aymargeddon;
+
+$| = 1;
+
+use FROGS::Config qw($conf);
+
+$::conf->{-DEBUG} = 2;
+
+# $::conf->{-DEBUG} = 2;
+
+my $db = new DataBase();
+
+$db->update_hash('MOBILE',
+ "LOCATION=0_1",
+ {'COUNT' => 'COUNT + 1'},'noquote');
+
+$db->commit();
+
+# print $db->relative("2004-05-13 03:40:37") ."\n";
+
+#my $aym = new Aymargeddon(1,3,$db,'DE');
+
+#print $aym->show_statistic();
+
+# print $aym->read_single_relation(1,2). "\n";
+
+#print "place is: $place.\n";
+
+# print Dumper $::conf;
+# exit;
+
+#my $d = DataBase->new();
+#$d->nowrite();
+
--- /dev/null
+-- MySQL dump 9.09
+--
+-- Host: localhost Database: RAGNAROEK
+-- ------------------------------------------------------
+-- Server version 4.0.16-log
+
+--
+-- Table structure for table `LOCALIZE`
+--
+
+DROP TABLE IF EXISTS LOCALIZE;
+CREATE TABLE LOCALIZE (
+ TAG varchar(25) NOT NULL default '',
+ LANGUAGE enum('DE','EN') NOT NULL default 'DE',
+ TEXT text NOT NULL,
+ PRIMARY KEY (TAG,LANGUAGE)
+) TYPE=InnoDB;
+
+--
+-- Dumping data for table `LOCALIZE`
+--
+
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ADJ_ADORING','DE',', Anbeter von');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ADJ_ADORING','EN',' adoring');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ADJ_HERE','DE','Hier');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ADJ_HERE','EN','Here');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ART_DAT_PL','DE','den');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ART_DAT_PL','EN','the');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('BATTLE_REPORT','DE','Kampfbericht für');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('BATTLE_REPORT','EN','Battle report for');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('BUILD_ARK','DE','Arche bauen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('BUILD_ARK','EN','build ark');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CASUALTIES_OF_PESTILENTIA','DE','Opfer der Pestilentia');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CASUALTIES_OF_PESTILENTIA','EN','Casualties of pestilentia');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CHANGE_PASSWORD','DE','Wenn Du Dein Passwort ändern willst, gib das neue Passwort bitte hier zweimal ein.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CHANGE_PASSWORD','EN','If you want to change your password, please insert it here two times.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CH_LUCK','DE','Glücksfaktor ändern');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CH_LUCK','EN','change fortune');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CH_STATUS','DE','Status ändern');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CH_STATUS','EN','change status');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CITY_HEADING','DE','Rangfolge der Erdlinge:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CITY_HEADING','EN','Ranking of earthlings:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_HERO','DE','Held weihen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_HERO','EN','bless hero');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_HERO_MSG','DE','Anzahl neue Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_HERO_MSG','EN','Number of new heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_PRIEST','DE','Priester weihen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_PRIEST','EN','bless priest');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_PRIEST_MSG','DE','Weihe einen neuen Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BLESS_PRIEST_MSG','EN','Bless a new priest');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_ARK','DE','Arche bauen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_ARK','EN','build ark');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_ARK_MSG','DE','Baue Arche in');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_ARK_MSG','EN','Build ark in');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_TEMPLE','DE','Tempel bauen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_TEMPLE','EN','build temple');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_TEMPLE_MSG','DE','Baue einen Tempel in');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_BUILD_TEMPLE_MSG','EN','build temple in');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_ACTION_MSG','DE','Wähle neue Avatar-Aktion');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_ACTION_MSG','EN','Choose new avatar action');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_ADORING_MSG','DE','Deine Helden beten jetzt zu');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_ADORING_MSG','EN','Your heros now adoring');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_LUCK','DE','Glücksfaktor ändern');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_LUCK','EN','change luck');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_LUCK_MSG','DE','Verändere den Glücksfaktor um');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_LUCK_MSG','EN','Change luck-factor about');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_STATUS_MSG','DE','Setze deine neue Beziehung zu');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_CH_STATUS_MSG','EN','Set your new relation to');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_COUNT','DE','Anzahl');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_COUNT','EN','Number');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DESTROY','DE','Tempel zerstören');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DESTROY','EN','destroy temple');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DESTROY_MSG','DE','Zerstöre den Tempel in');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DESTROY_MSG','EN','Destroy the temple at');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DIE_ORDER','DE','Sterbereihenfolge ändern');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DIE_ORDER','EN','change die-order');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DIE_ORDER_MSG','DE','Wähle die neue Sterbe-Reihenfolge deiner Einheiten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_DIE_ORDER_MSG','EN','Choose the new die-order of your units');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_ERROR_MSG','DE','unvollständiger Befehl');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_ERROR_MSG','EN','incomplete command');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_FLOOD','DE','überfluten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_FLOOD','EN','flood');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_FLOOD_MSG','DE','Überflute');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_FLOOD_MSG','EN','flood');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_INCARNATE','DE','Avatare erschaffen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_INCARNATE','EN','create avatars');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_INCARNATE_MSG','DE','Anzahl der neuen Avatare');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_INCARNATE_MSG','EN','Number of new avatars');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE','DE','bewegen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE','EN','move');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MSG','DE','bewege %1 in Richtung <br>Mögliche Richtungen: <br> <table>\r\n<tr><td></td><td>N</td><td></td></tr>\r\n<tr><td>NW</td><td></td><td>NE</td></tr>\r\n<tr><td>SW</td><td></td><td>SE</td></tr>\r\n<tr><td></td><td>S</td><td></td></tr>\r\n</table>\r\n');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MSG','EN','move %1 in direction <br>Possible directions:<br><table>\r\n<tr><td></td><td>N</td><td></td></tr>\r\n<tr><td>NW</td><td></td><td>NE</td></tr>\r\n<tr><td>SW</td><td></td><td>SE</td></tr>\r\n<tr><td></td><td>S</td><td></td></tr>\r\n</table>\r\n');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MTN','DE','Berg versetzten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MTN','EN','move mountain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MTN_MSG','DE','soll versetzt werden nach');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_MOVE_MTN_MSG','EN','should be moved to');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_PLAGUE','DE','verseuchen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_PLAGUE','EN','init plague');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_PLAGUE_MSG','DE','Wähle Seuche für');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CMD_PLAGUE_MSG','EN','Choose plague for');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CONQUERED_ARKS','DE','Eroberte Archen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('CONQUERED_ARKS','EN','Conquered arks');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_AVATARS','DE','Tote Avatare');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_AVATARS','EN','dead avatars');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_HEROS','DE','Gefallene Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_HEROS','EN','Dead heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_PRIESTS','DE','Gefallene Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_PRIESTS','EN','Dead priests');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_WARRIORS','DE','Gefallene Krieger');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('DEAD_WARRIORS','EN','Dead warriors');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('END_OF_GAME','DE','Das Spiel ist aus! Die Gewinner entnehmt ihr bitte der Statistik.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('END_OF_GAME','EN','The game is over! For winners look in the statistic section.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ERROR_NO_LOGIN','DE','Um diese Aymargeddon-Seite anzusehen, müssen Sie sich erst <a href=\"login.epl\">einloggen</a>, da der Inhalt für jeden Spieler verschieden ist.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ERROR_NO_LOGIN','EN','To view this aymargeddon page you first need to <a href=\"login.epl\">login</a>, because it\'s content is different for each player.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_ARK_APPROACHING','DE','Von %1 kommt eine Arche.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_ARK_APPROACHING','EN','An ark comes from %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_BUILD_ARK','DE','Spieler %1 baut eine Arche.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_BUILD_ARK','EN','Player %1 builds an ark.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_BUILD_TEMPLE','DE','Ein Tempel für den Gott %2 der Größe %3 wird fertig.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_BUILD_TEMPLE','EN','A temple for god %2 with size %3 will be finished.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_FIGHT_GOD','DE','Hier findet ein Avatarkampf zwischen %2 und %3 statt.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_FIGHT_GOD','EN','Here is an avatar fight between %2 and %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_FLOOD','DE','Der Gott %1 hat die Sintflut herbeigerufen! ');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_FLOOD','EN','The god %1 will flood this aerea!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_MOBILE_APPROACHING','DE','Aus %2 kommen %3 %4 von Spieler %1 hier an.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_MOBILE_APPROACHING','EN','From field %2 will come %3 %4 from player %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_PRODUCE_PRIEST','DE','Ein Priester beendet seine Ausbildung.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_PRODUCE_PRIEST','EN','A priest finish his training.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_PRODUCE_WARRIOR','DE','Ein Krieger beendet seine Ausbildung.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('EVENT_PRODUCE_WARRIOR','EN','A warrior finish his training.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_AYMARGEDDON','DE','Aymargeddon');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_AYMARGEDDON','EN','Aymargeddon');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_CITY','DE','Die Stadt');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_CITY','EN','The city');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_ISLE','DE','Die Insel');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_ISLE','EN','The island');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_MOUNTAIN','DE','Der Berg');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_MOUNTAIN','EN','The mountain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_PLAIN','DE','Die Ebene');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_PLAIN','EN','The plain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_POLE','DE','Der Manapol');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_POLE','EN','The mana pole');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_WATER','DE','Das Wasserfeld');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIELD_WATER','EN','The water field');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHTING_STRENGTH','DE','Kampfstärke');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHTING_STRENGTH','EN','Fighting strength');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHT_AVATAR','DE','Avatarkampf');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHT_AVATAR','EN','avatar fight');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHT_EARTHLING','DE','%1 versucht dieses Feld zu erobern.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FIGHT_EARTHLING','EN','%1 trys to conquer this field.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FLANKING','DE','Flankierungsbonus');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FLANKING','EN','Flanking');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FORM_BACK_BUTTON','DE','zurück');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FORM_BACK_BUTTON','EN','back');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FORM_OK_BUTTON','DE','senden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('FORM_OK_BUTTON','EN','submit');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_FEMALE','DE','Frau');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_FEMALE','EN','Woman');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_MALE','DE','Mann');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_MALE','EN','Man');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_PLURAL','DE','Gruppe');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GEN_PLURAL','EN','Group');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GLOBAL','DE','allen Feldern');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GLOBAL','EN','all places');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GOD','DE','Gott');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GOD','EN','god');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GODS_HELP','DE','Göttlicher Unterstützung');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('GODS_HELP','EN','Help of gods');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HERO','DE','Held');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HERO','EN','Hero');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HKP','DE','Helden - Krieger - Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HKP','EN','Heros - Warriors - Priests');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HOMECITY','DE','Es ist die Heimatstadt');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HOMECITY','EN','It\'s the home town');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HOMEHOLY','DE','Es ist ein heiliger Berg');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HOMEHOLY','EN','It\'s a holy mountain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HPK','DE','Helden - Priester - Krieger');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('HPK','EN','Heros - Priests - Warriors');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('INCARNATE','DE','Avatar erschaffen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('INCARNATE','EN','create avatar');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ISLE','DE','Insel');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ISLE','EN','Isle');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('KHP','DE','Krierger - Helden - Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('KHP','EN','Warrior - Heros - Priests');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('KPH','DE','Krieger - Priester - Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('KPH','EN','Warrior - Priests - Heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_ENGLISH','DE','Englisch');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_ENGLISH','EN','English');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_GERMAN','DE','Deutsch');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_GERMAN','EN','German');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_WELCOME','DE','Wählen Sie ihre bevorzugte Sprache');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LANG_WELCOME','EN','Choose your favorite language');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LAST_BATTLE_HEADING','DE','Derzeitige Kampfstärken der Götter in der letzten Schlacht:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LAST_BATTLE_HEADING','EN','Actual fighting power of gods for the last battle:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LAST_BATTLE_LINE','DE','%1 kämpft mit Stärke %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LAST_BATTLE_LINE','EN','%1 fights with strength %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_EMAIL','DE','e-Mail Adresse');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_EMAIL','EN','email');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_FAILED','DE','Login fehlgeschlagen. Falsches Passwort oder unbekannter Benutzername.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_FAILED','EN','Login failed. Wrong password or unknown username.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_PASSWORD','DE','Passwort');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_PASSWORD','EN','password');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REALNAME','DE','richtiger Name');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REALNAME','EN','real name');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_ERROR','DE','Die Anmeldung ist fehlgeschlagen. Vielleicht ist der Benutzername schon vergeben. Nicht vergessen: Jeder Benutzer darf nur <strong>einen</strong> Account bei uns haben!!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_ERROR','EN','We couldn\'t register you. Maybe the login name is already in use. Always remember: any user is only allowed <strong>one</strong> account on this server!!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_FORM_HEAD','DE','Suchen sie sich einen Benutzernamen aus:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_FORM_HEAD','EN','Choose your login name:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_LINK','DE','anmelden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_LINK','EN','register');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_MSG','DE','Wenn Du noch keinen Aymargeddon-Account hast, solltest Du dich');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_MSG','EN','If you don\'t have an aymargeddon account, you should');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_OK_HEAD','DE','Die Anmeldung hat geklappt.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_OK_HEAD','EN','You are now registered.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_OK_TAIL','DE','Das Passwort für den Account wird an die angegebene Adresse geschickt.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_OK_TAIL','EN','The password for your account will be sent to your email adress.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_RETURN','DE','zurück zum Eingang');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_REG_RETURN','EN','back to the login');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_USERNAME','DE','Benutzername');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_USERNAME','EN','Username');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_WELCOME','DE','Der Eingang zu <strong>Aymargeddon</strong>!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LOGIN_WELCOME','EN','The Entrance to <strong>Aymargeddon</strong>!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LUCK','DE','Gewürfelt');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('LUCK','EN','Dice roll');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_ARK','DE','Arche');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_ARK','EN','ark');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_ARK_PL','DE','Archen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_ARK_PL','EN','arks');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_AVATAR','DE','Avatar');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_AVATAR','EN','avatar');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_AVATAR_PL','DE','Avatare');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_AVATAR_PL','EN','avatars');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_BLOCK','DE','blockieren');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_BLOCK','EN','block');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HELP','DE','helfen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HELP','EN','help');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HERO','DE','Held');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HERO','EN','hero');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HERO_PL','DE','Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_HERO_PL','EN','heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_IGNORE','DE','ignorieren');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_IGNORE','EN','ignore');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PRIEST','DE','Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PRIEST','EN','priest');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PRIEST_PL','DE','Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PRIEST_PL','EN','priests');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PROPHET','DE','Prophet');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PROPHET','EN','prophet');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PROPHET_PL','DE','Propheten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_PROPHET_PL','EN','prophets');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_WARRIOR','DE','Krieger');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_WARRIOR','EN','warrior');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_WARRIOR_PL','DE','Krieger');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOBILE_WARRIOR_PL','EN','warriors');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOUNTAIN','DE','Berg');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOUNTAIN','EN','mountain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOVE','DE','bewegen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MOVE','EN','move');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_AVATAR_DEAD','DE','In %1 starb ein Avatar von %2 im Kampf. Er kämpft jetzt in der letzten Schlacht für seinen Gott.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_AVATAR_DEAD','EN','In %1 died an avatar of %2. He fights now in the last battle for his god.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BLESS_HERO','DE','Der Gott %1 hat in %3 einen Krieger gesegnet, so daß dieser fortan heroische Kräfte entfalten kann.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BLESS_HERO','EN','The god %1 has blessed a warrior from %2 in %3. He is from now on called \'HERO\'!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BLESS_PRIEST','DE','%1 hat einen Krieger von %2 in %3 zum Priester geweiht.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BLESS_PRIEST','EN','%1 blessed a warrior from %2 in %3. It is now a priest.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BUILD_ARK','DE','%1 hat in %2 eine Arche gebaut.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BUILD_ARK','EN','%1 has build an ark in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BUILD_TEMPLE','DE','%1 hat in %3 einen Tempel zu Ehren von %2 errichtet. Es ist der größte Tempel weit und breit!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_BUILD_TEMPLE','EN','%1 has build a temple to pray to %3 in %2. It is the largest temple in the world!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_ATTACK_ALLIE','DE','Fehler bei Verarbeitung von Befehl %1: Du kannst Deinen Verbündeten %2 nicht angreifen in Feld %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_ATTACK_ALLIE','EN','Error during process of command %1: You cant yttack your allie %2 in field %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_BUILD_HERE','DE','Fehler bei Verarbeitung von Befehl %1: Das kann man auf Feld %2 nicht bauen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_BUILD_HERE','EN','Error during process of command %1: You cant build this in field %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_DEFENDED','DE','Du kannst den Tempel in %1 nicht zerstören, weil er von Priestern eines anderen Gottes beschützt wird.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_DEFENDED','EN','You cant destroy the temple in %1. The temple is defended by unorthodox priests.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_MOUNTAIN','DE','Du kannst den Tempel auf dem Berg %1 nicht zerstören.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_MOUNTAIN','EN','You cant destroy the temple on mountain %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_OWN','DE','Du kannst den Tempel in %1 nicht zerstören da er Dir selbst gehört.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_DESTROY_OWN','EN','You cant destroy your very own temple in %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_FLOOD_TERRAIN','DE','Du kannst %1 nicht überfluten: Falsches Terrain %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_FLOOD_TERRAIN','EN','You cant flood %1: Wrong terrain %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_LEAVE_AYMARGEDDO','DE','Fehler bei Verarbeitung von Befehl %1: Du kannst die Aymargeddon in Feld %2 nicht verlassen!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_LEAVE_AYMARGEDDO','EN','Error during process of command %1: You cant leave Aymargeddon in field %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_ARK','DE','Du kannst keine Arche nach %1 bewegen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_ARK','EN','You cant move an ark to %1');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_ATTACKED','DE','Du kannst keine %2 aus %1 bewegen, so lange dort gekämpft wird.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_ATTACKED','EN','You cant move %2 from %1 during fight.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_PLAGUE','DE','%2 können sich in %1 nicht bewegen, weil sie von der %3 betroffen sind.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_PLAGUE','EN','%2 cant move in %1 because of %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_TO_POLE','DE','Fehler bei Verarbeitung von Befehl %1: Du kannst Dich nicht auf den Pol %2 bewegen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_MOVE_TO_POLE','EN','Error during process of command %1: You cant move to pole %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_RESCUE_WORLD','DE','Du kannst den Tempel in %2 nicht mehr zerstören, weil nur noch %1 Tempelbauplätze unbesetzt sind. Das Ende der Welt ist unaufhaltsam!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_RESCUE_WORLD','EN','You cant destroy the temple in %2. There are only %1 unbuild temples left. The end of the world is irresistible.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_SWIM','DE','Fehler bei Verarbeitung von Befehl %1: %3 können nicht schwimmen in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CANT_SWIM','EN','Error during process of command %1: %3 cant swim in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CHANGE_AYMARGEDDON','DE','%1 hat die Aymargeddon von %2 nach %3 verschoben');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CHANGE_AYMARGEDDON','EN','%1 has moved Aymargeddon from %2 to %3');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CHANGE_FORTUNE','DE','%1 hat den Glücksfaktor von %2 auf %3 geändert.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CHANGE_FORTUNE','EN','%1 changed the fortune from %2 to %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CH_ACTION','DE','Die Avatare in %2 haben jetzt den Status %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CH_ACTION','EN','The avatars in %2 now have the status %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CH_STATUS','DE','Dein neuer Status gegenüber %1 ist jetzt %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_CH_STATUS','EN','Your new status regarding %1 is now %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DESTROY_NEED_AVATAR','DE','Du brauchst einen Avatar um den Tempel in %1 zerstören zu können.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DESTROY_NEED_AVATAR','EN','You need an avatar to destroy the temple in %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DIE_ORDER','DE','Du hast Deine Sterbereihenfolge geändert. Sie lautet jetzt: %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DIE_ORDER','EN','You changed your die order to %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DONT_MOVE_WITH','DE','Nicht mehr mitbewegen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_DONT_MOVE_WITH','EN','Don\'t move with any mobile.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_EARTHLING_CANT_MOVE_T','DE','Fehler bei Verarbeitung von Befehl %1: Du als Erdling kannst keine %2 bewegen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_EARTHLING_CANT_MOVE_T','EN','Error during process of command %1: Earthlings cant move %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_DIE','DE','Ein %2 von %1 in %3 stirbt.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_DIE','EN','A %2 from %1 in %3 dies.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_END','DE','Die Horden von %1 griffen %2 in %4 an. %3 gewann.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_END','EN','The army of %1 attacked %2 in %4. %3 won the battle.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_RETREAT','DE','%4 %2 von %1 ziehen sich aus %3 zurück.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_RETREAT','EN','%4 %2 from %1 retreats from %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_RETREAT_DIE','DE','%4 %2 von %1 sterben in %3 weil sie keine Rückzugsmöglichkeit haben.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FIGHT_RETREAT_DIE','EN','%4 %2 from %1 die in %3: No way to retreat.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FLOOD','DE','%1 hat das Feld %2 überflutet. Aus %3 wurde %4.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FLOOD','EN','%1 has flooded %2. The old terrain %3 is now %4.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FLOOD_NEED_AVATAR','DE','Zum Überfluten von %1 braucht man einen Avatar.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_FLOOD_NEED_AVATAR','EN','You need an avatar in %1 to flood this field.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_GOD_CANT_MOVE_TYPE','DE','Fehler bei Verarbeitung von Befehl %1: Als Gott kannst Du keine %2 bewegen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_GOD_CANT_MOVE_TYPE','EN','Error during process of command %1: Gods cant move type %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_INCARNATE','DE','%1 inkarnierte einen Avatar in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_INCARNATE','EN','%1 incarnates an avatar in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOBILE_ARRIVES','DE','%1 %2 von %3 sind in %4 angekommen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOBILE_ARRIVES','EN','%1 %2 from %3 arrived in %4.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOBILE_DRAWN','DE','%1 %2 von %3 sind in %4 jämmerlich ersoffen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOBILE_DRAWN','EN','%1 %2 from %3 drawn in %4.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOVE_NO_TARGET','DE','Fehler bei Verarbeitung von Befehl %1: Von Feld %2 gibt es kein Feld in Richtung %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOVE_NO_TARGET','EN','Error during process of command %1: There is no field in direction %3 from field %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOVE_WITH','DE','Bewegt sich mit');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_MOVE_WITH','EN','Moves with');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NOT_ENOUGH_MANA','DE','Dir fehlt Mana um den Befehl \"%1\" in %2 auszuführen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NOT_ENOUGH_MANA','EN','You lack mana to execute the command \"%1\" in %2.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NOT_ENOUGH_MOBILES','DE','Fehler bei Verarbeitung von Befehl %1: %2 sind zu wenige in Feld %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NOT_ENOUGH_MOBILES','EN','Error during process of command %1: %2 is not enough in field %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_SUCH_MOBILE','DE','Fehler: Eine Einheit mit der ID %1 konnte nicht gefunden werden.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_SUCH_MOBILE','EN','Error: Cant find mobile with ID %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_SUCH_ROLE','DE','Fehler bei Verarbeitung des Befehls %1: Du kannst Deinen Status gegenüber jemandem, den es nicht gibt, wohl kaum ändern.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_SUCH_ROLE','EN','Error during process of command %1: You cant change your status to unknown players.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_TEMPLE_TO_DESTROY','DE','Du kannst in %1 keinen Tempel zerstören: Es ist keiner da.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_NO_TEMPLE_TO_DESTROY','EN','You cant destroy an non existent temple in %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_STATUS_INVALID','DE','Fehler bei Verarbeitung von Befehl %1: Unbekannter Status \"%2\"');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_STATUS_INVALID','EN','Error during process of command %1: Unknown status \"%2\"');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_TEMPLE_DESTROYD','DE','%3 hat in %1 einen Tempel, der %2 geweiht war, zerstört.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_TEMPLE_DESTROYD','EN','%3 destroyd the temple of god %2 in %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_TRANSPORTS','DE','reist zusammen mit');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_TRANSPORTS','EN','travels with');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_WRONG_TYPE','DE','Fehler bei Verarbeitung von Befehl %1: Falscher Typ %2 in Feld %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('MSG_WRONG_TYPE','EN','Error during process of command %1: Wrong Type %2 in field %3.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NEW_HEROS','DE','Neue Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NEW_HEROS','EN','new heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOBODY','DE','niemand');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOBODY','EN','nobody');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_CHARNAME','DE','Charaktername');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_CHARNAME','EN','Character name');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_DESCRIPTION','DE','Beschreibung');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_DESCRIPTION','EN','Description');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_GENDER','DE','Geschlecht');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_GENDER','EN','Gender');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_ROLE','DE','Rolle');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOM_ROLE','EN','Role');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOT_OCCUPIED','DE','unbesetzt');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('NOT_OCCUPIED','EN','not occupied');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('OCCUPIED','DE','besetzt von');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('OCCUPIED','EN','occupied by');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('OWN_MANA','DE','Du hast %1 Mana zur Verfügung.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('OWN_MANA','EN','You have %1 mana.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LANGUAGE','DE','Sprache');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LANGUAGE','EN','Language');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LOGIN','DE','Einloggen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LOGIN','EN','Login');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LOGOUT','DE','Ausloggen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_LOGOUT','EN','Logout');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_MAP','DE','Karte');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_MAP','EN','Map');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_PLAYER','DE','Spieler');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_PLAYER','EN','Player');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_REFERENCE','DE','Kurzreferenz');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_REFERENCE','EN','short reference');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_RULES','DE','Regeln');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_RULES','EN','Rules');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_START','DE','Start');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PAGE_START','EN','Start');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PEOPLE','DE','Leute');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PEOPLE','EN','People');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PEOPLE_OR_ARK','DE','Leute (oder Archen)');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PEOPLE_OR_ARK','EN','people (or arks)');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PHK','DE','Priester - Helden - Krieger');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PHK','EN','Priests - Heros - Warriors');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PKH','DE','Priester - Krieger - Helden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PKH','EN','Priests - Warriors - Heros');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAGUE_IN_FIELD','DE','Hier grassiert die %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAGUE_IN_FIELD','EN','Here rampant %1.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAIN','DE','Ebene');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAIN','EN','plain');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_CHOOSE_GAME','DE','Du musst erst ein Spiel wählen, bevor es mehr zu sehen gibt.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_CHOOSE_GAME','EN','You must choose a game if you want to see more.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_CREATE_CHAR','DE','Erschaffe deinen Charakter für');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_CREATE_CHAR','EN','Create your character for');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_DELETE_MESSAGES','DE','Alle nachrichten löschen.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_DELETE_MESSAGES','EN','Delete all messages.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_EVENTS','DE','Ereignisse');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_EVENTS','EN','Events');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_GAMES_NONE','DE','keine');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_GAMES_NONE','EN','none');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_MESSAGES','DE','Folgende Nachrichten sind für dich eingetroffen:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_MESSAGES','EN','You got the following new messages:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_MESSAGES_HEADING','DE','Nachrichten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_MESSAGES_HEADING','EN','Messages');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_NO_EVENTS','DE','Keine bekannten Ereignisse für Dich.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_NO_EVENTS','EN','No known events');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_NO_MESSAGE','DE','Es gibt keine neuen Nachrichten für dich.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_NO_MESSAGE','EN','There are no new messages for you.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_OPENGAMES','DE','<strong>offene Spiele</strong>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_OPENGAMES','EN','<strong>open games</strong>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_OWN_GAMES','DE','<strong>eigene Spiele</strong>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_OWN_GAMES','EN','<strong>own games</strong>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_STATISTIC','DE','Statistik');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_STATISTIC','EN','Statistics');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_TO_MAP','DE','Zur Karte');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_TO_MAP','EN','To the map');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_WELCOME','DE','Willkommen bei');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PLAYER_WELCOME','EN','Welcome to');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT3_PL','DE','euch');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT3_PL','EN','you');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT3_SG','DE','dir');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT3_SG','EN','you');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_F','DE','ihr');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_F','EN','her');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_M','DE','ihm');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_M','EN','him');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_PL','DE','ihnen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_DAT_PL','EN','them');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_F','DE','ihr');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_F','EN','her');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_M','DE','sein');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_M','EN','his');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_PL','DE','ihr');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PPRO_GEN_PL','EN','their');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_IS_PL','DE','sind');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_IS_PL','EN','are');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_IS_SG','DE','ist');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_IS_SG','EN','is');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_OWN_PL','DE','deiner');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_OWN_PL','EN','of your');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_OWN_SG','DE','von');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PREP_OWN_SG','EN','of');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PRIEST','DE','Priester');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('PRIEST','EN','Priest');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('REGISTER_MAIL_SUBJECT','DE','Willkommen bei Aymargeddon!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('REGISTER_MAIL_SUBJECT','EN','Welcome to Aymargeddon!');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('REGISTER_MAIL_TEXT','DE','Hallo %1,\r\n\r\nHerzlich willkommen bei Aymargeddon. Dein Login lautet %2 und Dein Paswort lautet %3.\r\n\r\nBitte trage Dich auch auf die Mailingliste ein. Das geht so: Schicke eine Mail an \r\n\r\nmajordomo@informatik.uni-frankfurt.de\r\n\r\nmit folgendem Inhalt:\r\n\r\nsubscribe ragnaroek\r\n\r\nSolltet ihr wieder von dieser Liste runter wollen, schickt ihr einfach ein:\r\n\r\nunsubscribe ragnaroek\r\n\r\nViel Spaß wünscht das Aymargeddon Development Team');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('REGISTER_MAIL_TEXT','EN','Hello %1,\r\n\r\nWelcome to Aymargeddon. Your login is %2 and your password is %3.\r\n\r\nYou should also subscribe to the mailing list:\r\n\r\nPlease send a mail to\r\n\r\nmajordomo@informatik.uni-frankfurt.de\r\n\r\nwith the following content:\r\n\r\nsubscribe ragnaroek\r\n\r\nIf you want to get rid of the mails you send\r\n\r\nunsubscribe ragnaroek\r\n\r\n\r\nHave fun!\r\n\r\nThe Aymargeddon Development Team');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_EARTHLING','DE','Erdling');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_EARTHLING','EN','earthling');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_GOD','DE','Gott');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_GOD','EN','god');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_OBSERVER','DE','Beobachter');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_OBSERVER','EN','observer');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_UNDEFINED','DE','noch keine Rolle');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('ROLE_UNDEFINED','EN','no role');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SEND_MESSAGE','DE','kontaktieren');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SEND_MESSAGE','EN','contact');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SEND_MESSAGE_TO','DE','Nachricht an %1:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SEND_MESSAGE_TO','EN','Message to %1:');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_EARTHLING_CITY','DE','%1 hat %2 Städte.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_EARTHLING_CITY','EN','%1 has %2 citys.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_FORTUNE','DE','Der Glücksfaktor ist %1.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_FORTUNE','EN','Fortune is %1.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_NEW_TEMPLES','DE','Es sind zur Zeit %1 Tempel in Bau');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_NEW_TEMPLES','EN','%1 temples will be build.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_SPEED','DE','Spielgeschwindigkeit: Eine Zeiteinheit dauert %1.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_SPEED','EN','Game speed: One time intervall is %1.<p>');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_UNBUILD','DE','%1 Tempel sind noch nicht gebaut.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STATISTIC_UNBUILD','EN','%1 temples are unbuild.');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_ALLIED','DE','Alliiert');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_ALLIED','EN','allied');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_BETRAY','DE','Verrat');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_BETRAY','EN','betray');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_FOE','DE','Feind');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_FOE','EN','enemy');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_FRIEND','DE','Freund');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_FRIEND','EN','friend');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_NEUTRAL','DE','Neutral');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('STAT_NEUTRAL','EN','neutral');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SUM_OF_STRENGTH','DE','Gesamtstärke');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SUM_OF_STRENGTH','EN','Total strength');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SUNKEN_ARKS','DE','Gesunkene Archen');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('SUNKEN_ARKS','EN','Sunken arks');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TEMPLE','DE','Hier steht ein Tempel');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TEMPLE','EN','Here is a temple');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TEST_TAG','DE','ich %1, dass %2! Prozent: %% hier nochmal: %2 %1');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_DAYS','DE','In %1 Tagen, %2 Stunden, %3 Minuten und %4 Sekunden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_DAYS','EN','In %1 days, %2 hours, %3 minutes and %4 seconds');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_HOURS','DE','In %1 Stunden, %2 Minuten und %3 Sekunden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_HOURS','EN','In %1 hours, %2 minutes and %3 seconds');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_MINUTES','DE','In %1 Minuten und %2 Sekunden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_MINUTES','EN','In %1 minutes and %2 seconds');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_SECONDS','DE','In %1 Sekunden');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('TIME_WITH_SECONDS','EN','In %1 seconds');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('UNASSIGNED','DE','nicht vergebene Position');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('UNASSIGNED','EN','unassigned position');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('UNAVAILABLE_UNITS','DE','beschäftigte Einheiten');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('UNAVAILABLE_UNITS','EN','unavailable units');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('WATER','DE','Wasser');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('WATER','EN','water');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('WINNER_IS','DE','Sieger ist');
+INSERT INTO LOCALIZE (TAG, LANGUAGE, TEXT) VALUES ('WINNER_IS','EN','Winner is');
+
--- /dev/null
+-- MySQL dump 9.09
+--
+-- Host: localhost Database: RAGNAROEK
+-- ------------------------------------------------------
+-- Server version 4.0.16-log
+
+--
+-- Table structure for table `ALLIANCE`
+--
+
+DROP TABLE IF EXISTS ALLIANCE;
+CREATE TABLE ALLIANCE (
+ GAME smallint(5) unsigned NOT NULL default '0',
+ PLAYER smallint(5) NOT NULL default '0',
+ OTHER smallint(5) NOT NULL default '0',
+ STATUS enum('NEUTRAL','ALLIED','FRIEND','FOE','BETRAY') NOT NULL default 'NEUTRAL',
+ PRIMARY KEY (GAME,PLAYER,OTHER)
+) TYPE=InnoDB COMMENT='friend or foe?';
+
+--
+-- Table structure for table `COMMAND`
+--
+
+DROP TABLE IF EXISTS COMMAND;
+CREATE TABLE COMMAND (
+ ID mediumint(9) NOT NULL auto_increment,
+ GAME smallint(5) unsigned NOT NULL default '0',
+ EXEC datetime NOT NULL default '0000-00-00 00:00:00',
+ SUBMIT datetime NOT NULL default '0000-00-00 00:00:00',
+ PLAYER smallint(5) NOT NULL default '0',
+ COMMAND enum('SEND_MSG','MOVE_WITH','PRAY','PRODUCE','FIGHT_EARTHLING','FIGHT_GOD','CH_STATUS','MOVE','BUILD_TEMPLE','CH_ADORING','CH_ACTION','BLESS_PRIEST','BLESS_HERO','DIE_ORDER','MOVE_MTN','INCARNATE','BUILD_ARK','PLAGUE','FLOOD','DESTROY','CH_LUCK') NOT NULL default 'CH_STATUS',
+ LOCATION varchar(7) default NULL,
+ MOBILE mediumint(8) unsigned NOT NULL default '0',
+ ARGUMENTS text NOT NULL,
+ ACK datetime default NULL,
+ DONE datetime default NULL,
+ PRIMARY KEY (ID),
+ KEY EXEC (EXEC)
+) TYPE=InnoDB COMMENT='here the commands of players are stored';
+
+--
+-- Table structure for table `EARTHLING`
+--
+
+DROP TABLE IF EXISTS EARTHLING;
+CREATE TABLE EARTHLING (
+ GAME smallint(6) NOT NULL default '0',
+ PLAYER smallint(6) NOT NULL default '0',
+ DYING enum('PKH','PHK','HPK','HKP','KPH','KHP') NOT NULL default 'KHP',
+ HERO smallint(6) NOT NULL default '0',
+ PRIMARY KEY (GAME,PLAYER)
+) TYPE=InnoDB COMMENT='info special for each earthling';
+
+--
+-- Table structure for table `EVENT`
+--
+
+DROP TABLE IF EXISTS EVENT;
+CREATE TABLE EVENT (
+ ID mediumint(9) unsigned NOT NULL auto_increment,
+ GAME smallint(6) NOT NULL default '0',
+ LOCATION char(5) NOT NULL default '',
+ TAG char(30) NOT NULL default '',
+ ARG1 char(25) NOT NULL default '',
+ ARG2 char(25) NOT NULL default '',
+ ARG3 char(25) NOT NULL default '',
+ ARG4 char(25) NOT NULL default '',
+ COMMAND_ID mediumint(9) NOT NULL default '0',
+ TIME datetime NOT NULL default '0000-00-00 00:00:00',
+ PRIMARY KEY (ID)
+) TYPE=InnoDB;
+
+--
+-- Table structure for table `GAME`
+--
+
+DROP TABLE IF EXISTS GAME;
+CREATE TABLE GAME (
+ GAME smallint(5) unsigned NOT NULL default '0',
+ NAME varchar(20) NOT NULL default '',
+ SIZE smallint(5) unsigned NOT NULL default '0',
+ SPEED int(11) NOT NULL default '1800',
+ FORTUNE tinyint(3) unsigned NOT NULL default '0',
+ LAST_TEMPLE varchar(7) NOT NULL default '',
+ TEMPLE_SIZE smallint(3) unsigned NOT NULL default '1',
+ START_MANA smallint(5) unsigned NOT NULL default '20',
+ RUNNING enum('Y','N') NOT NULL default 'Y',
+ PRIMARY KEY (GAME)
+) TYPE=InnoDB COMMENT='here some generell global information is stored';
+
+--
+-- Table structure for table `GOD`
+--
+
+DROP TABLE IF EXISTS GOD;
+CREATE TABLE GOD (
+ GAME smallint(5) unsigned NOT NULL default '0',
+ PLAYER smallint(5) NOT NULL default '0',
+ MANA smallint(5) unsigned NOT NULL default '0',
+ DEATH_HERO smallint(5) unsigned NOT NULL default '0',
+ DEATH_AVATAR smallint(5) unsigned NOT NULL default '0',
+ ARRIVAL char(7) NOT NULL default '',
+ PRIMARY KEY (GAME,PLAYER)
+) TYPE=InnoDB COMMENT='here some god-related stuff is stored';
+
+--
+-- Table structure for table `LOCALIZE`
+--
+
+DROP TABLE IF EXISTS LOCALIZE;
+CREATE TABLE LOCALIZE (
+ TAG varchar(25) NOT NULL default '',
+ LANGUAGE enum('DE','EN') NOT NULL default 'DE',
+ TEXT text NOT NULL,
+ PRIMARY KEY (TAG,LANGUAGE)
+) TYPE=InnoDB;
+
+--
+-- Table structure for table `MAP`
+--
+
+DROP TABLE IF EXISTS MAP;
+CREATE TABLE MAP (
+ GAME smallint(6) unsigned NOT NULL default '0',
+ LOCATION varchar(7) NOT NULL default '',
+ HOME smallint(6) NOT NULL default '0',
+ OCCUPANT smallint(6) NOT NULL default '0',
+ TERRAIN enum('PLAIN','WATER','CITY','MOUNTAIN','ISLE','POLE','AYMARGEDDON') NOT NULL default 'PLAIN',
+ TEMPLE enum('Y','N') NOT NULL default 'N',
+ PLAGUE set('PESTILENTIA','INFLUENZA','TUBERCULOSIS') default NULL,
+ LAST_PRODUCE timestamp(14) NOT NULL,
+ ATTACKER smallint(5) unsigned default '0',
+ GOD_ATTACKER smallint(5) unsigned default '0',
+ NAME varchar(20) NOT NULL default '',
+ FLUXLINE set('N','S','SW','NW','SE','NE') NOT NULL default '',
+ PRIMARY KEY (GAME,LOCATION)
+) TYPE=InnoDB COMMENT='This is the main map of the world';
+
+--
+-- Table structure for table `MESSAGE`
+--
+
+DROP TABLE IF EXISTS MESSAGE;
+CREATE TABLE MESSAGE (
+ ID mediumint(8) unsigned NOT NULL auto_increment,
+ GAME smallint(5) unsigned NOT NULL default '0',
+ TIME datetime NOT NULL default '0000-00-00 00:00:00',
+ MFROM smallint(5) NOT NULL default '0',
+ MTO smallint(5) NOT NULL default '0',
+ LOCATION varchar(7) NOT NULL default '',
+ TYPE enum('MESSAGE','ERROR','WARNING') NOT NULL default 'MESSAGE',
+ MSG_TEXT text NOT NULL,
+ MSG_TAG varchar(25) NOT NULL default '',
+ ARG1 varchar(25) NOT NULL default '',
+ ARG2 varchar(25) NOT NULL default '',
+ ARG3 varchar(25) NOT NULL default '',
+ ARG4 varchar(25) NOT NULL default '',
+ PRIMARY KEY (ID),
+ KEY TIME (TIME)
+) TYPE=InnoDB COMMENT='here messages to the players are stored';
+
+--
+-- Table structure for table `MOBILE`
+--
+
+DROP TABLE IF EXISTS MOBILE;
+CREATE TABLE MOBILE (
+ ID mediumint(8) unsigned NOT NULL default '0',
+ GAME smallint(5) unsigned NOT NULL default '0',
+ LOCATION char(7) NOT NULL default '',
+ TYPE enum('WARRIOR','HERO','PRIEST','PROPHET','AVATAR','ARK') NOT NULL default 'WARRIOR',
+ OWNER smallint(5) NOT NULL default '0',
+ ADORING smallint(5) unsigned NOT NULL default '0',
+ COUNT smallint(5) unsigned NOT NULL default '0',
+ AVAILABLE enum('Y','N') NOT NULL default 'Y',
+ STATUS enum('BLOCK','HELP','IGNORE') NOT NULL default 'BLOCK',
+ COMMAND_ID mediumint(9) NOT NULL default '0',
+ MOVE_WITH mediumint(6) unsigned default '0',
+ PRIMARY KEY (ID)
+) TYPE=InnoDB COMMENT='Here all mobile objects are stored';
+
+--
+-- Table structure for table `PLAYER`
+--
+
+DROP TABLE IF EXISTS PLAYER;
+CREATE TABLE PLAYER (
+ PLAYER smallint(5) NOT NULL default '0',
+ REALNAME varchar(30) NOT NULL default '',
+ EMAIL varchar(40) NOT NULL default '',
+ SECURITY enum('USER','FRIEND','TRUSTED') NOT NULL default 'USER',
+ DESCRIPTION text NOT NULL,
+ PICTURE blob NOT NULL,
+ EARTHLING_SCORE smallint(6) NOT NULL default '0',
+ GOD_SCORE smallint(6) NOT NULL default '0',
+ BLOCKED enum('N','Y') NOT NULL default 'N',
+ LANGUAGE char(2) NOT NULL default '',
+ LOGIN varchar(20) NOT NULL default '',
+ PASSWORD varchar(20) NOT NULL default '',
+ GAMES_PLAYED_EARTHLING smallint(5) unsigned NOT NULL default '0',
+ GAMES_PLAYED_GOD smallint(5) unsigned NOT NULL default '0',
+ PRIMARY KEY (PLAYER),
+ UNIQUE KEY PLAYER (PLAYER),
+ UNIQUE KEY LOGIN (LOGIN),
+ UNIQUE KEY EMAIL (EMAIL)
+) TYPE=InnoDB COMMENT='information for players, which are not related to a game';
+
+--
+-- Table structure for table `ROLE`
+--
+
+DROP TABLE IF EXISTS ROLE;
+CREATE TABLE ROLE (
+ GAME smallint(5) unsigned NOT NULL default '0',
+ PLAYER smallint(5) NOT NULL default '0',
+ NICKNAME varchar(20) default NULL,
+ ROLE enum('OBSERVER','EARTHLING','GOD') NOT NULL default 'EARTHLING',
+ GENDER enum('MALE','FEMALE','PLURAL') NOT NULL default 'PLURAL',
+ DESCRIPTION text,
+ PICTURE blob,
+ PRIMARY KEY (GAME,PLAYER)
+) TYPE=InnoDB COMMENT='which player plays which role?';
+
--- /dev/null
+In RAGNAROEK.sql, is the export from the testing-database,
+generated with the script extract_structure_and_localize
+
+In LOCALIZE.sql the same but only for table LOCALIZE.
+
+The script backup generates a backup in ./+RAGNAROEK_BACKUP.sql
+
+The script from_scratch generates a complete empty database but with
+the old PLAYER and LOCALIZE tables.
+
+The script do_sql executes his first command with mysql
+
+in my.cnf is my configuration file for mysql to work with
+InnoDB tabletype. make shure InnoDB tabletype works for you. mysql
+sets default tabletype to MyISAM if it does not work without
+complaining! But FROGS and Aymargeddon wont work without the
+transaction-capability from InnoDB
+
--- /dev/null
+mysqldump -u aymargeddon -p`cat ../+secrets` -c --add-drop-table \
+ RAGNAROEK > ./+RAGNAROEK_BACKUP.sql
+
--- /dev/null
+# usage: delete_game <game-number> | ./do_sql
+
+echo "delete from GAME where GAME = $1;"
+echo "delete from MOBILE where GAME = $1;"
+echo "delete from COMMAND where GAME = $1;"
+echo "delete from MAP where GAME = $1;"
+echo "delete from ROLE where GAME = $1;"
+echo "delete from MESSAGE where GAME = $1;"
+echo "delete from EVENT where GAME = $1;"
+echo "delete from ALLIANCE where GAME = $1;"
+echo "delete from GOD where GAME = $1;"
+echo "delete from EARTHLING where GAME = $1;"
+
--- /dev/null
+mysql -u aymargeddon -p`cat ../+secrets` RAGNAROEK
+
--- /dev/null
+mysqldump -u aymargeddon -p`cat ../+secrets` -d --add-drop-table \
+ RAGNAROEK > RAGNAROEK.sql
+mysqldump -u aymargeddon -p`cat ../+secrets` -c --add-drop-table RAGNAROEK LOCALIZE \
+ > LOCALIZE.sql
--- /dev/null
+mysqldump -u aymargeddon -p`cat ../+secrets` -c --add-drop-table RAGNAROEK LOCALIZE \
+ > LOCALIZE.sql
+mysqldump -u aymargeddon -p`cat ../+secrets` -c --add-drop-table RAGNAROEK PLAYER \
+ > ./+PLAYER.sql
+
+./do_sql < RAGNAROEK.sql
+./do_sql < LOCALIZE.sql
+./do_sql < ./+PLAYER.sql
--- /dev/null
+# You can copy this to one of:
+# /etc/mysql/my.cnf to set global options,
+# mysql-data-dir/my.cnf to set server-specific options (in this
+# installation this directory is /var/lib/mysql) or
+# ~/.my.cnf to set user-specific options.
+#
+# One can use all long options that the program supports.
+# Run the program with --help to get a list of available options
+
+# This will be passed to all mysql clients
+[client]
+#password = my_password
+port = 3306
+socket = /var/run/mysqld/mysqld.sock
+
+# Here is entries for some specific programs
+# The following values assume you have at least 32M ram
+
+[safe_mysqld]
+err-log = /var/log/mysql/mysql.err
+
+[mysqld]
+user = mysql
+pid-file = /var/run/mysqld/mysqld.pid
+socket = /var/run/mysqld/mysqld.sock
+port = 3306
+#
+# You can also put it into /var/log/mysql/mysql.log but I leave it in /var/log
+# for backward compatibility. Both location gets rotated by the cronjob.
+#log = /var/log/mysql/mysql.log
+log = /var/log/mysql.log
+basedir = /usr
+datadir = /var/lib/mysql
+tmpdir = /tmp
+language = /usr/share/mysql/english
+skip-locking
+#
+# The skip-networkin option will no longer be set via debconf menu.
+# You have to manually change it if you want networking i.e. the server
+# listening on port 3306. The default is "disable" - for security reasons.
+skip-networking
+set-variable = key_buffer=16M
+set-variable = max_allowed_packet=1M
+set-variable = thread_stack=128K
+#
+# Here you can see queries with especially long duration
+#log-slow-queries = /var/log/mysql/mysql-slow.log
+#
+# The following can be used as easy to replay backup logs or for replication
+#server-id = 1
+#log-bin = /var/log/mysql/mysql-bin.log
+#binlog-do-db = include_database_name
+#binlog-ignore-db = include_database_name
+#
+
+#
+# AB HIER WICHTIGES INNO ZEUGS
+#
+
+
+# Read the manual if you want to enable InnoDB!
+# skip-innodb
+skip-bdb
+
+# You can write your other MySQL server options here
+# ...
+# Datafile(s) must be able to
+# hold your data and indexes.
+# Make sure you have enough
+# free disk space.
+innodb_data_file_path = ibdata1:10M:autoextend
+# Set buffer pool size to
+# 50 - 80 % of your computer's
+# memory
+set-variable = innodb_buffer_pool_size=70M
+set-variable = innodb_additional_mem_pool_size=10M
+# Set the log file size to about
+# 25 % of the buffer pool size
+set-variable = innodb_log_file_size=20M
+set-variable = innodb_log_buffer_size=8M
+# Set ..flush_log_at_trx_commit
+# to 0 if you can afford losing
+# some last transactions
+innodb_flush_log_at_trx_commit=1
+
+#
+# BIS HIER WICHTIGES INNO-ZEUGS
+#
+
+[mysqldump]
+quick
+set-variable = max_allowed_packet=1M
+
+[mysql]
+#no-auto-rehash # faster start of mysql but no tab completition
+
+[isamchk]
+set-variable = key_buffer=16M