Benutzer-Werkzeuge

Webseiten-Werkzeuge


tutorials:zufallszahlen_zufallsereignisse

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:

  1. 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.
  2. 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! — 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. — Netsurfer 2006/11/19 14:14

Zur Tutorial-Übersicht

tutorials/zufallszahlen_zufallsereignisse.txt · Zuletzt geändert: 2021/09/18 19:16 (Externe Bearbeitung)