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.
Für Zufallszahlen gibt es in der Scripting Referenz die Funktion GetRandom(_limit). Diese Funktion hat zwei Nachteile:
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())
Bei Multiplayer Maps sollte ein bessere Seed gefunden werden, der bei allen Spielern gleich ist!
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
Das ist doch falsch!? random ist ein beliebiger Wert zwischen 0 und 1! — 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]
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
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.
— Netsurfer 2006/11/19 14:14
Zur Tutorial-Übersicht