[[http://www.siedler-games.de|{{:sg-link.jpg|}}]]
===== Zufallszahlen =====
Mit Zufallszahlen kann man manchmal tolle Sachen machen. Einige Beispiele dafür stehen weiter unten, zunächst erstmal der Weg wie man an sie rankommt.
==== Nachteile von GetRandom() ====
Für Zufallszahlen gibt es in der Scripting Referenz die Funktion GetRandom(_limit).
Diese Funktion hat zwei Nachteile:
- Die Funktion liefert Werte zwischen 0 und _limit - 1. Das ist nicht besonders praktisch, da man häufig Zahlen zwischen 1 und _limit benötigt. Man müsste also zum Rückgabewert der Funktion 1 addieren um brauchbare Werte zu erhalten.
- In jedem neuen Spiel werden exakt die gleichen Zahlen in exakt der gleichen Reihenfolge zurückgegeben. Diese Tatsache macht die Funktion praktisch unbrauchbar, da bei jedem Spiel das selbe passiert und der Zufallsfaktor entfällt.
==== Bessere Zufallszahlen ====
Glücklicherweise bietet Lua seine eigenen Funktionen für "gute" Zufallszahlen.\\
Dafür sorgt die Funktion math.random(), welche vielseitig einsetzbar ist. Damit allerdings nicht das selbe passiert wie bei GetRandom() (gleiche Zahlen, gleiche Reihenfolge) benötigt math.random() eine Art Startwert, eine Grundlage auf der die Zufallszahlen berechnet werden sollen. Dazu muss die Funktion math.randomseed() vor dem Aufruf von math.random() diesen Startwert übergeben bekommen.\\
Der Startwert sollte bei jedem neuen Spiel anders sein. Jetzt könnte man z.B. wiederum eine Zufallszahl als Startwert nehmen, das macht nur nicht sonderlich viel Sinn, da sich auch hierbei irgendwann die Ereignisse wiederholen könnten. Es gibt allerdings einen Wert, der bei jedem Spiel anders ist: die aktuelle Uhrzeit/das aktuelle Datum.\\
Die Uhrzeit erhält man mit der Funktion XGUIEng.GetSystemTime(). Die Initialisierung "schöner" Zufallszahlen sieht also so aus:
math.randomseed(XGUIEng.GetSystemTime())
FIXME Bei Multiplayer Maps sollte ein bessere Seed gefunden werden, der bei allen Spielern gleich ist! FIXME
> Chromix hatte mir mal die Spielernamen als Seed vorgeschlagen. Old McDonald
Damit ist der Grundstein gelegt. Jetzt zu den Zufallszahlen selbst.
math.random() kann auf dreierlei Arten aufgerufen werden:
-- 1. Ohne Parameter
random = math.random()
-- random ist jetzt entweder 0 oder 1
FIXME Das ist doch falsch!? random ist ein beliebiger Wert **zwischen** 0 und 1! --- //[[dedk-script-wiki@top-topics.com|Netsurfer]] 2006/11/19 14:25//
-- 2. Mit einem Parameter
random = math.random(100)
-- random ist jetzt eine Zahl im Interval [1;100]
-- 3. Mit zwei Parametern
random = math.random(200, 500)
-- random ist eine Zahl im Interval [200;500]
==== GetRandom() verbessern ====
Mit diesen Erkenntnissen kann man jetzt auch einfach die normale GetRandom() Funktion überschreiben:
function GetRandom(_min, _max)
if not gvRandomseed then
local seed = ""
gvRandomseed = true
if XNetwork and XNetwork.Manager_DoesExist() == 1 then
local humanPlayer = XNetwork.GameInformation_GetMapMaximumNumberOfHumanPlayer()
for i = 1, humanPlayer do
if XNetwork.GameInformation_IsHumanPlayerAttachedToPlayerID( i ) == 1 then
seed = seed .. tostring(XNetwork.GameInformation_GetLogicPlayerUserName( i ))
end
end
else
seed = XGUIEng.GetSystemTime()
end
math.randomseed(seed)
end
return math.random(_min, _max)
end
\\
FIXME Hier ist doch ein Fehler drin!? Da die standard GetRandom() Funktion nur einen Parameter erwartet, muss man doch den Fall abfangen, dass sie auch nur mit einem Parameter aufgerufen wird, da man ansonsten einen Fehler erhält. Ich habe das bei mir so gelöst:
function GetRandom(_min, _max)
if not _max then _max = _min _min = 1 end
if not gvRandomseed then
Dadurch wird bei Aufruf mit nur einem Parameter dieser zum Max-Wert und der Min-Wert wird auf 1 gesetzt. D.h. die Zufallszahlen, die zurückgeliefert werden, liegen zwichen 1 und dem im Aufruf übergebenen Wert.
--- //[[dedk-script-wiki@top-topics.com|Netsurfer]] 2006/11/19 14:14//
\\
\\
[[:tutorials:index|Zur Tutorial-Übersicht]]