[JAVA] Minecraft 1.12.2 Rückrechnung von Weltsamen aus der Weltkarte

Umgebung

Hintergrund

Was passiert, wenn der Startwert im Minecraft-Mehrspielermodus angezeigt wird? Mit einer einfachen Idee können Sie Folgendes tun.

--Listen Sie die Koordinaten aller Diamanterze in der Nähe der Mine auf

Dies erfordert nicht, dass der Client über einen MOD verfügt. Selbst wenn die Version, der MOD und die Nichtänderung des Clients auf Serverregelebene angegeben werden, können keine Gegenmaßnahmen ergriffen werden.

Es gibt eine Client-MOD-Einschränkung. ・ Wenn nur ein bestimmter Spieler den Samen auf einem Server kennt, auf dem der Samen nicht für die Öffentlichkeit zugänglich ist, und dieser Spieler den Samen verwendet, führt selbst die Angabe der Koordinaten des Diamanterzes zu einer erheblichen Zerstörung des Gleichgewichts.

Also fragte ich mich, ob ein Multi-Player-Nicht-Saba-Can-Player nach Samen suchen könnte, indem er nur die Informationen verwendet, die mit legitimen Mitteln verfügbar sind, ohne den Server zu knacken. Wenn dies möglich ist, unabhängig davon, wie sehr der Serveradministrator den Startwert privat hält, kann er physisch bekannt sein. Daher müssen ** Verhaltensüberwachung und lokale Regeln getrennt betrachtet werden **.

Regel

Kennen Sie den Keim der Welt, wenn Sie einen Minecraft 1.12.2 Java Edition-Server haben, der mit einigen Forge-MODs dasselbe Terrain wie Vanille erzeugt.

Bedingungen

Annahme

Verbot

Möglich

Strategie

Die zugrunde liegende Strategie besteht darin, "für alle möglichen Samenkandidaten zu testen, ob ein Samen ein bestimmtes Gelände erzeugt". So wie es ist, können jedoch 2 ^ 64 Samen in Betracht gezogen werden. Selbst wenn der Beurteilungsteil erheblich beschleunigt wird, wird es für einen gewöhnlichen PC in Privatbesitz ungefähr 10.000 Jahre dauern. Es scheint, dass es bald vorbei sein wird, wenn Sie einen Spacon verwenden, aber es ist schwer zu sagen, dass es möglich ist, es zu wissen.

"Probieren Sie alle möglichen Samenkandidaten aus, um festzustellen, ob ein Samen ein bestimmtes Terrain erzeugt", wird im Pseudocode wie folgt geschrieben:

for (long seed = 0; seed != 0xFFFFFFFFFFFFFFFFL; seed++) { // (1)
    if (f(seed)) System.out.println(seed);
}

/**
 *Eine Funktion, die zurückgibt, ob ein Startwert diese Welt erstellt oder nicht.
 */
abstract boolean f(long seed); // (2)

Hier sind die zu verbessernden Punkte (1) und (2). Gegenwärtig ist die Anzahl der Schleifen für (1) zu groß und dauert etwa 10.000 Jahre. Daher muss eine Schleifenmethode verwendet werden, mit der mehr Berechnungen gespeichert werden können. (2) muss durch die einfachste mögliche Formel eingegrenzt werden.

(2) kann auch mehrstufig sein.

for (long seed = 0; seed != 0xFFFFFFFFFFFFFFFFL; seed++) {
    if (f1(seed) && f2(seed) && f3(seed)) System.out.println(seed);
}

/**
 *Eine schnelle Funktion, die Kandidaten grob einschränkt
 */
abstract boolean f1(long seed);

/**
 *Mittlere Geschwindigkeitsfunktion, die die Kandidaten auf wenige einschränkt
 */
abstract boolean f2(long seed);

/**
 *Eine langsame Funktion, die die Kandidaten auf eins einschränkt
 */
abstract boolean f3(long seed);

Dieses Mal werden wir den Samen mit einer Strategie wie dieser identifizieren.

f1 Hochgeschwindigkeitsfunktion, die Kandidaten grob einschränkt

Da f1 sowieso schnell sein muss, werde ich es zu einer Funktion machen, die von GPGPU verarbeitet werden kann. Dazu müssen einige der folgenden Bedingungen erfüllt sein.

Zum Beispiel ist "x-> x + 700 == 4" einfach, also ist es okay. x-> Math.sin (x * 0.001) == 1 muss etwas gegen Math.sin unternehmen. x-> world.getBiome (neue BlockPos (x, 65, 0)) == Biome.FOREST ist nicht möglich.

Aparapi wird für die GP-GPU verwendet.

Ich habe dies für die GPU verwendet.

Mit einer besseren GPU kann noch weiter gekürzt werden.


Hier wird die Position der Dorfgeneration für f1 verwendet.

--Minecraft 1.12.2 Algorithmus zur Bestimmung der Dorfkoordinaten - Qiita https://qiita.com/MirrgieRiana/items/0a3baee86bb661dc5f99

Mit den vom Dorf generierten Koordinaten können Sie die Kandidaten durch das folgende Verfahren grob eingrenzen.

Ob ein Weltsamen ein Dorf an einer bestimmten Blockkoordinate erzeugt oder nicht, wird durch die folgende Funktion "Test" berechnet.

int distance = 32;

boolean test(long seed, int chunkX, int chunkZ)
{
	seed += (long) getRegionIndex(chunkX) * 341873128712L + (long) getRegionIndex(chunkZ) * 132897987541L + 10387312L;
	seed = seed ^ 0x5DEECE66DL;
	seed = next(seed);
	if (!test2(seed, chunkX)) return false;
	seed = next(seed);
	if (!test2(seed, chunkZ)) return false;
	return true;
}

boolean test2(long s, int chunkIndex)
{
	return (s >> 17) % 24 == getChunkIndexInRegion(chunkIndex);
}

int getRegionIndex(int chunkIndex)
{
	if (chunkIndex < 0) chunkIndex -= 31;
	return chunkIndex / 32;
}

int getChunkIndexInRegion(int chunkIndex)
{
	return chunkIndex - getRegionIndex(chunkIndex) * 32;
}

long next(long s)
{
	return (s * 0x5DEECE66DL + 0xBL) & 0xffffffffffffL;
}

long prev(long s)
{
	return ((s - 0xBL) * 0xdfe05bcb1365L) & 0xffffffffffffL;
}

Dieser Code erstreckt sich innerhalb von Random. Weiter unten finden Sie Informationen zur internen Verarbeitung von Random.

Diese Funktion ist von Aparapi verfügbar, da sie unabhängig von der JRE- oder Minecraft-Instanz ist.

Im Folgenden wird davon ausgegangen, dass der Abstand auf 32 festgelegt ist, was die Standardeinstellung ist. Dann gibt es 24 verschiedene Dorfgenerierungskoordinaten im Gebiet pro Koordinatenachse.


Sie können die Samen grob eingrenzen, indem Sie die obige Funktion für die Anzahl der untersuchten Dörfer aufrufen.

Aufgrund der Kürzung der oberen 16 Bits von Random kann diese Funktion die Anzahl der Startkandidaten jedoch im Prinzip nicht auf eins beschränken, unabhängig davon, wie stark das Dorf untersucht wird. Also werde ich mich wie folgt auf ungefähr 1000 von 2 ^ 48 Möglichkeiten eingrenzen und dann wieder ungefähr 65536 * 1000 Kandidaten eingrenzen.

for (long seed = 0; seed != 0xFFFFFFFFFFFFL; seed++) {
    if (!test(seed, -16, -18)) continue; //Dorfplatzierung von Samen 1251341
    if (!test(seed, 12, -49)) continue;
    if (!test(seed, -77, 19)) continue;
    if (!test(seed, 21, -80)) continue;
    System.out.println(seed);
}

Unter der Annahme, dass 2 ^ 64 Wege 10.000 Jahre dauern, dauern 2 ^ 48 ≒ 2.8E + 14 Wege nach einfacher Berechnung etwa 50 Tage. Die anschließende Eingrenzung von 65536000 ≒ 6.5E + 7 Möglichkeiten ist weitaus geringer.

(1) Optimierung des Schleifenteils

Ich konnte die Anzahl der Berechnungen auf ungefähr 50 Tage reduzieren, aber es ist immer noch schwer zu sagen, dass es möglich ist, zu berechnen. Es gibt jedoch tatsächlich eine einfache Möglichkeit, dies auf 1/24 zu reduzieren. Verwenden Sie dazu den oben aufgeführten Algorithmus zur Dorfgenerierung und die zufälligen Spezifikationen. Die generierten Koordinaten eines Dorfes haben eine Verengungsleistung von 1 / (24 * 24) für ein Dorf und 1/24 für nur eine Seite der Koordinaten. Der folgende Code ist eine Zusammenstellung von "test" und "test2". Hier kann der Keim zum Zeitpunkt von (3) bis zu einem gewissen Grad vorhergesagt werden.

boolean test(long seed, int chunkX, int chunkZ)
{
	seed += (long) getRegionIndex(chunkX) * 341873128712L + (long) getRegionIndex(chunkZ) * 132897987541L + 10387312L;
	seed = seed ^ 0x5DEECE66DL;
	seed = next(seed);
	// (3)
	if (!((seed >> 17) % 24 == getChunkIndexInRegion(chunkX))) return false; // (4)
	seed = next(seed);
	if (!((seed >> 17) % 24 == getChunkIndexInRegion(chunkZ))) return false;
	return true;
}

Wenn der Teil "getChunkIndexInRegion (chunkX)" 20 wäre, wäre die Beurteilungsformel in (4) "(Startwert >> 17)% 24 == 20". Verschieben Sie nach rechts 17 und suchen Sie nach Zahlen, bei denen der durch 24 geteilte Wert 20 beträgt.

Die Bitstruktur des Seeds ist wie folgt.

-------- -------- 00000000 00000000 00000000 0000000? ???????? ????????

Hier ist - der Teil, der von Randoms Spezifikationen ignoriert wird (dies hat keinen Einfluss auf die Platzierung des Dorfes), und? Ist der Teil, der von der rechten 17-Schicht verworfen wird (er beeinflusst die Platzierung des Dorfes, aber das Stück X des ersten Dorfes). Betrifft nicht). Um den Block X des ersten Dorfes zu reparieren, sollte der Rest der verbleibenden "0" geteilt durch 24 ein bestimmter Wert sein. Der ? Teil kann auch alles sein, also schleife nach innen, so dass es 17 Bits Freiheit gibt. Die codierte Version lautet wie folgt.

int chunkX1 = 20;
int chunkZ1 = 20;

for (long j = getChunkIndexInRegion(chunkX1); j <= 0x7FFFFFFFL; j += 24) {
    for (long i = 0; i <= 0x1FFL; i++) {
        long s = (j << 17) | i; // (5)
        
    }
}

** Nachtrag: for (long i = 0; i <= 0x1FFL; i ++) { ist ein Rätsel. Es gibt eine Theorie, dass for (long i = 0; i <= 0x1FFFFL; i ++) { korrekt ist. ** **.

chunkX1 und chunkZ1 sind die Chunk-Koordinaten des ersten Dorfes in der Dorfkoordinatenliste.

Das "s" in (5) repräsentiert jedoch den "Samen" zum Zeitpunkt von (3), so dass Sie ein wenig rechnen müssen, um den Samen der Welt selbst zu erhalten. So ändern Sie "s" in "seed":

long seed = s;
seed = prev(seed);
seed = seed ^ 0x5DEECE66DL;
seed -= (long) getRegionIndex(chunkX1) * 341873128712L + (long) getRegionIndex(chunkZ1) * 132897987541L + 10387312L;
seed = seed & 0xFFFFFFFFFFFFL;

Jetzt können wir den Keim der Welt schleifen, in der das Dorf an einer bestimmten X-Koordinate in einem bestimmten Gebiet erzeugt wird. Dies bringt die Anzahl der Schleifen auf 2 ^ 48/24. Es ist eine Berechnung, die ungefähr zwei Tage dauert, also realistisch genug. In dem Experiment wurden die Koordinaten von acht Dörfern untersucht, die Berechnung wurde in ungefähr 27 Stunden unter Verwendung der GPGPU (mit schlechter Leistung) abgeschlossen, und die unteren 48-Bit-Muster konnten auf ungefähr 250 Kandidaten eingegrenzt werden.

f2 Mittelgeschwindigkeitsfunktion, die die Kandidaten auf wenige einschränkt

Vorwissen

In dieser Funktion gibt f1 bis zu einem Kandidaten unter den unteren 48 Bits an, was auf ungefähr 1000 Kandidaten eingegrenzt ist.

In dem Experiment wurden 8 Dörfer untersucht, daher sollte es eine Verengungsleistung (73 Bit) von 24 ^ (2 * 8) geben, aber in Wirklichkeit wurden ungefähr 250 Kandidaten geboren. Daher ist es zweifelhaft, dass f1 bis zu eins identifizieren kann. Es wird angenommen, dass eine große Anzahl niedrigerer 48-Bit-Muster einer Anordnung entspricht.

f2 wird verwendet, um das untere 48-Bit-Muster als eins zu identifizieren. f2 scheint so viele Fähigkeiten zu haben. Wenn Sie hunderte Male mehr Zeit mit f3 verbringen, brauchen Sie f2 nicht, aber f3 ist ziemlich schwer, deshalb möchte ich es speichern.

Strategie

Wir werden auch hier Dörfer benutzen, aber dieses Mal werden wir uns eher auf Struktur als auf Platzierung konzentrieren.

--Minecraft 1.12.2 Algorithmus zur Bestimmung der Dorfkoordinaten - Qiita https://qiita.com/MirrgieRiana/items/0a3baee86bb661dc5f99 --Minecraft 1.12.2 Village Building List --Qiita https://qiita.com/MirrgieRiana/items/b5d56b4d78c503ddb7a0

Das Dorf besteht aus anderen Teilen als Gebäuden wie Brunnen, Straßen und Wegen und Gebäudeteilen wie Häusern, Feldern und Kirchen. Hier achten wir auf die Anzahl der Gebäude, die optisch leicht verständlich sind.

Das folgende Dorf besteht beispielsweise aus den folgenden Gebäuden.

2018-09-22_22.03.33.png

--Haus1 3 Bücherregalhäuser --Haus2 2 Schmiede --House3 Dance Hall 1 --House4Garden Cube 6 Stück --WoodHut 5 Toiletten

Ordnen wir dies beispielsweise von unten an und zeigen es mit einem Hashwert von 0x422356123L an. Das Problem ist einfach, da die Struktur des Dorfes als Hash-Wert basierend auf der Anzahl der Gebäude ausgedrückt wird, da mit "==" beurteilt werden kann, ob die Formen fast gleich sind. Darüber hinaus ist es einfach, Informationen zu sammeln, da diese leicht aus den Informationen berechnet werden können, die visuell bestätigt werden können, indem die Anzahl der Gebäude im Dorf angegeben wird. Trotzdem hat es die Möglichkeit, das Muster der unteren 48 Bits des Samens bei einer Untersuchung von 1 oder 2 Dörfern von 1000 auf 1 einzugrenzen.

Da die erzeugten Blockkoordinaten dieses Dorfes -16, -18 sind, wird dies als "* Seed 1251341 erzeugt ein Dorf von 0x422356123L bei Blockkoordinaten -16, -18 *" bezeichnet.


Die Zufallszahlen, die die Struktur des Dorfes bestimmen, werden von "MapGenBase # generate" generiert, von "MapGenStructure # recursiveGenerate" leicht modifiziert und in "MapGenVillage.Start # new" verwendet. Wenn dies in einen Code umgewandelt wird, sieht es so aus.

World worldIn =Weltinstanz von irgendwoher gegeben;
int size = 1;

Random rand = new Random(getSeedInChunk(1251341, -16, -18));
rand.nextInt();
new MapGenVillage.Start(worldIn, rand, -16, -18, size);

/**
 *Eine Funktion, die einen Startwert für eine Dorfstruktur bei gegebenen Weltsamen- und Dorfblockkoordinaten zurückgibt
 */
long getSeedInChunk(long seed, long chunkX, long chunkZ)
{
    Random rand = new Random(seed);
    long j = rand.nextLong();
    long k = rand.nextLong();
    (chunkX * j) ^ (chunkZ * k) ^ seed;
}

MapGenVillage.Start # new berücksichtigt auch die Welt-, Basisblockkoordinaten und die Dorfgröße. Die Dorfgröße beträgt standardmäßig 1.

Die Struktur des Dorfes hängt vom Keim der Welt und den erzeugten Blockkoordinaten ab. Es sieht so aus, als gäbe es im Gegensatz zur Netherfestung keine Musterschleife.

--Minecraft 1.12.2 Algorithmus zur Bestimmung der Spawnkoordinaten für die Netherfestung --Qiita https://qiita.com/MirrgieRiana/items/e01a3db6fd7bf183fbbb

Der Hash-Wert der Dorfstruktur wird berechnet, indem das Innere von "MapGenVillage.Start # new" simuliert wird. Dieser Konstruktor ist jedoch ungefähr wie folgt.

List<structurecomponent> components = new ArrayList<>();

MapGenVillage.Start(World worldIn, Random rand, int x, int z, int size)
{
    List<PieceWeight> list =Eine Methode zum Abrufen einer Liste von Gebäudetypen, Gewichten und Obergrenzenpaaren();
    StructureVillagePieces.Start start = new StructureVillagePieces.Start(
        worldIn.getBiomeProvider(), 0, rand, (x << 4) + 2, (z << 4) + 2, list, size);
    components.add(start); // (7)
    start.buildComponent(start, components, rand); // (8)
    List<StructureComponent> list1 = start.pendingRoads;
    List<StructureComponent> list2 = start.pendingHouses;

    while (!list1.isEmpty() || !list2.isEmpty()) { // (9)
        if (list1.isEmpty()) {
            int i = rand.nextInt(list2.size());
            StructureComponent structurecomponent = list2.remove(i);
            structurecomponent.buildComponent(start, components, rand);
        } else {
            int j = rand.nextInt(list1.size());
            StructureComponent structurecomponent2 = list1.remove(j);
            structurecomponent2.buildComponent(start, components, rand);
        }
    }

    // (6)
}

Zum Zeitpunkt von (6) enthält "Komponenten" eine Liste von Teilen, aus denen das Dorf besteht. StructureVillagePieces.Start # new scheint die erste Vertiefung darzustellen, die in (7) zu components hinzugefügt wurde. In (8) scheint "buildComponent" vier aus dem Bohrloch abgeleitete Pfade zu generieren. Während die in (9) nacheinander erzeugte Struktur abgeleitet wird, taucht sie dann in "Komponenten" ein. Es wird abgeschlossen sein, wenn es endlich zu (6) kommt. Eigentlich wird der Prozess danach fortgesetzt, aber er wird nicht zur Berechnung des Hashwerts verwendet. Ignorieren Sie ihn daher.

Um (6) herum, wenn Sie den Inhalt von "Komponenten" durchsuchen, die Gebäude zählen und den Code schreiben, um den Hashwert zu erstellen und zurückzugeben, haben Sie eine Funktion, die die Struktur des dort erzeugten Dorfes aus Zufalls- und Blockkoordinaten zurückgibt. .. Diese Funktion kann jedoch nicht in main platziert werden, da sie von der Welt abhängt, für die eine Minecraft-Initialisierungsverarbeitung erforderlich ist. Diese Funktion kann aus dem Code in Minecraft aufgerufen werden, der World zur Verfügung steht. Sie können beispielsweise Code schreiben, der diese Funktion aufruft, indem Sie die Rechtsklick-Verarbeitung des Pfeils überschreiben.

Durch die bisherige Diskussion haben wir eine "Funktion erstellt, die den Hash-Wert der Dorfstruktur unter Berücksichtigung der Seed- und Chunk-Koordinaten zurückgibt". F2 wird abgeschlossen, indem dies in die Bedingung "Erzeugt ein Startwert ein Dorf mit einem Hashwert an einer bestimmten Blockkoordinate?" Umgeschrieben wird. Infolgedessen erreicht der Startwert den Punkt, an dem die oberen 16 Bits unbekannt sind und die unteren 48 Bits bestätigt werden. Dies kann durch Vermessung von höchstens einem oder zwei Dörfern erfolgen. Die Berechnungszeit beträgt einige Sekunden in einem einzelnen Thread.

f3 Langsame Funktion, die die Kandidaten auf eins einschränkt

Hier werden die Startkandidaten von 65536 Mustern für die oberen 16 Bits auf ein Muster eingegrenzt. Verwenden Sie dazu das Biom. Der bedingte Ausdruck "Erzeugt der Samen ein bestimmtes Biom an einer bestimmten XZ-Koordinate?"

Das Dorf ignoriert die oberen 16 Bits, aber das Biom scheint es zu sehen. Ich kenne den Algorithmus zur Bestimmung des Bioms nicht, aber es reicht aus, das Biom der Koordinaten mit getBiome zu kennen, das von BiomeProvider bereitgestellt wird, das von WorldInfo abgeleitet ist, das von World erhalten wurde.

Das Problem hierbei ist, wie der Startwert an BiomeProvider übergeben wird. Dies kann durch Umschreiben des Felds "randomSeed" erfolgen, das WorldInfo privat an den BiomeProvider-Konstruktor übergibt. Da randomSeed jedoch privat ist, muss es öffentlich umgeschrieben werden.

Dieser Prozess erfordert auch Welt. Als ich Minecraft selbst initialisierte und World generierte, ohne Minecraft richtig zu starten, schien es, dass ein etwas anderes Terrain generiert wurde und es nicht erfolgreich war. Daher ändert diese Funktion auch die Rechtsklick-Verarbeitung eines Uhrelements oder etwas anderem, so dass es darin aufgerufen wird.

Die Liste der Koordinaten und Biome, die diesen Prozess durchlaufen sollen, muss sorgfältig erstellt werden. Da die Vermessung des Geländes von Menschen betrieben wird, bin ich immer noch besorgt, daher möchte ich die Koordinaten möglichst in der Mitte des Bioms messen. Anstatt zu versuchen, alle 10 zu vergleichen, wenn 10 weitere bestanden werden, möchte ich mit der Arbeit fortfahren, während ich eine sequentielle Bestätigung wie das Auflisten und Sortieren von 8 oder mehr Übereinstimmungen durchführe.

In diesem Prozess ist es uns im Experiment gelungen, 65536 Muster zu 1 Muster zu identifizieren, indem wir 10 Biome durchlaufen, die Koordinaten in der Nähe des Zentrums aufschreiben und sie in die Funktion einfüllen. Die Angabe dauert einige Minuten.


Währenddessen konnten wir anhand der Koordinaten von acht Dörfern, des strukturellen Hashwerts eines Dorfes und der zehn Biomes einen einzelnen Startwert im 64-Bit-Bereich identifizieren. In meiner Umgebung dauerte dies ungefähr 27 Stunden.

Zusammenfassung

** Minecraft 1.12.2 Java Edition Vanillas Standard-Terrain-Generierungswelt kann genügend Informationen sammeln, um Samen zurückzurechnen, indem sie einfach über die Oberfläche läuft. Sie können diese Informationen dann verwenden, um den Samen in höchstens zwei Tagen zurückzurechnen. ** Wenn die Weltkarte und die Position des Ursprungs angegeben werden, ohne sich tatsächlich anzumelden, werden die Informationen von selbst gesammelt.

Diesmal dauerte die Berechnung 2 Tage, da angenommen wurde, dass sich der Samen im Fernbereich befand (2 ^ 64). Wenn der Samen jedoch auf int gesetzt war, dauerte die Suche etwa 4 Sekunden, wenn die Koordinaten für 4 Dörfer bekannt waren. Ist fertig. Object # hashCode () ist der Rückgabewert von int. Wenn Sie also einen Startwert aus einer Zeichenfolge angeben, sieht dies folgendermaßen aus.

Es ist effektiv, die Parameter für die Geländegenerierung für diesen Angriff ein wenig zu ändern. Da der Keim der Welt jedoch verschiedene Orte betrifft, ist es weiterhin möglich, mit anderen als den diesmal verwendeten Teilen rückwärts zu berechnen. Der entscheidende Faktor ist diesmal die Tatsache, dass die oberen 16 Bits des von java.util.Random angegebenen Startwerts abgeschnitten werden. In dem Moment, in dem Sie den Startwert in Random setzen, gibt es nur 2 ^ 48 Muster auf der Welt. Wenn Sie bereits 50 Tage Zeit haben, können Sie zu diesem Zeitpunkt eine vollständige Suche durchführen, sodass Sie problemlos mit mehreren Computern rechnen können.

Gegenwärtig ist ** in einer Welt, die bereits die Bedingungen für die Rückrechnung erfüllt, theoretisch schlampig, unabhängig davon, wie viel Aufmerksamkeit auf die Sicherheit des Servers gelegt wird **.

Recommended Posts

Minecraft 1.12.2 Rückrechnung von Weltsamen aus der Weltkarte
Rückrechnung des Übergangs von Randoms internem Seed