Anno 1800 Seed Finder and Visualizer
Le Finder passe par toutes les graines pour trouver ceux qui ont les scores les plus élevés. La notation par défaut est le nombre de carreaux de terrain à constructeur. Pour accélérer les choses, cela permet également une liste d'îles indésirables. Ces îles peuvent ne pas apparaître dans leur monde respectif. Le choix évident ici sont des îles avec des rivières.
Le type de carte, la taille de la carte, la taille de l'île et la difficulté de l'île peuvent être ajustés. Le Finder fonctionne en deux itérations, le filtrage de base, puis une étape de raffinement des graines rapides. Les deux font la même chose, mais ils ont toujours leur but.
- La ligne de base filtrant les forces brutes à travers toutes les graines de 2147483648 possibles pour éliminer les îles universellement mauvaises (par exemple avec les rivières). Les résultats sont enregistrés sur le disque. Les performances sont d'environ 1 million de graines par seconde par noyau de processeur, ce qui signifie un temps d'exécution confortable de 2,5 minutes sur un 5950x. Si aucune île indésirable n'est définie, les temps d'exécution sont environ 4 fois plus longs. La base de référence sans rivière pour les cinq cartes du vieux monde est déjà incluse.
- Le raffinement des graines charge les graines créées à l'étape 1 à partir du disque. Parce que relativement peu de graines sont laissées, le raffinement ne prend qu'une seconde pour courir. Cela permet de visualiser facilement plusieurs graines ou de modifier les exigences. En particulier, le nombre de PNJ et de pirates n'a qu'un petit impact sur le score et aucun impact sur le fait que les îles ont des rivières ou non, de sorte que la même ligne de base peut être utilisée pour toute combinaison NPC / Pirate.
Le Finder essaiera agressivement de réutiliser des fichiers de base, donc si vous avez changé les îles indésirables et que vous souhaitez créer une ligne de base à partir de zéro, vous devez accéder au dossier Seeds et supprimer manuellement le fichier de base existant.
Le Finder visualisera également la carte avec les îles et les PNJ. Cette carte contient l'ancien monde, la région du cap et le nouveau monde, car ce sont les mondes où la graine a un impact.
Installation
- Vous devez avoir Python: https://www.python.org/downloads/ faites l'opposé des recommandations d'installation: activez la case à cocher le chemin et n'installez pas pour tous les utilisateurs.
- Les packages Python peuvent être installés à partir d'une fenêtre CMD avec: Pip Installer Numpy Pandas Matplotlib oreiller
- Si PIP n'est pas trouvé, vous n'avez pas sélectionné la case à cocher le chemin et vous devez définir votre variable d'environnement (ou simplement réinstaller).
- S'il échoue en raison des autorisations, Python a été installé pour tous les utilisateurs et non dans le répertoire utilisateur, CMD doit donc être exécuté à partir du mode Admin (ou simplement réinstaller).
- Cliquez avec le bouton droit sur le fichier main.py et choisissez Modifier avec le ralenti. Ajustez les paramètres au besoin et appuyez sur F5 pour exécuter.
Notes
Le chercheur ne peut filtrer que par la sélection de l'île. Les choses qui ne peuvent pas être filtrées sont: la rotation de l'île; position de l'île; fertilités; machines à sous minage.
Les fertilités et les créneaux miniers en particulier sont un problème assez difficile car ils arrivent à la fin de la création de l'île. Pour mettre les choses en perspective, toute l'île + le placement et la rotation du PNJ se font avec les 70 premiers nombres aléatoires du Mersenne Twister. Ensuite, le jeu dessine environ 18 000 numéros de plus avant que les fertilités et les créneaux miniers ne soient décidés. Il y a beaucoup de code de jeu supplémentaire à déchiffrer et le filtrage serait assez lent même lors de l'utilisation uniquement des graines de référence.
Si vous souhaitez exécuter les scripts de récupération vous-même (Copypics.py, Maptemplatestocsv.py, Maptocsv.py), ils s'attendent à ce que le référentiel ait deux dossiers voisins, un pour le parier filed et un pour tous les actifs de jeu comme extrait avec le RDAExplorer. C'est-à-dire que les dossiers ../filedBeader et ../data doivent exister.
Le code C est essentiellement une version très rationalisée (et dépouillée) de la création de carte dans util.py. Ce dernier ne rejette pas tôt et est écrit principalement dans Python, ce qui ne donne que 25 graines par seconde par noyau, donc même travailler avec des données de base sans autre rejet serait assez lente.
Le flux de code global pour chaque monde (par exemple Old World, New World, Cape) est le suivant:
- Initialisez un générateur de nombres aléatoires Mersenne Twister à partir de la bibliothèque standard (STD :: MT19937) avec la graine qui a été donnée par l'utilisateur.
- À partir de Data / Config / Export / Main / Asset / Assets.xml, chargez tous les éléments Maptemplates. Comparez l'entrée réelle de l'utilisateur (type de carte, taille de carte, ...) avec ces éléments et gardez uniquement les éléments qui correspondent. Sélectionnez au hasard l'un de ces éléments (std :: uniforme_int_distribution). (Il se trouve qu'il n'y a exactement qu'un seul élément pour chacun de ces paramètres, sauf lorsque le type de carte "aléatoire" a été sélectionné. Seul le nouveau monde a plusieurs.) C'est ce que le Maptemplatestocsv.py récupère.
- Le modèle de carte sélectionné contient un chemin d'accès à un fichier A7T, qui ne nous intéresse pas. Mais il est à côté d'un fichier A7tinfo, qui a des informations sur la taille du monde et a également les créneaux d'île. Une fente d'île a des coordonnées et de la taille et aussi de type et d'identification. La génération de cartes plus tard consiste à faire correspondre les créneaux avec des îles compatibles (en termes de taille et de type et d'identification). Maptocsv.py récupère ces données A7tinfo.
- Indépendamment de la carte, toutes les îles sont chargées. L'Assets.xml a des entrées Randalisland qui spécifient Filepath (à A7M), région, difficulté, IslandType (qui est en fait l'ID pour correspondre à la fente.id). Cependant, aucune taille. Le Assets.xml a également une entrée d'IslandSizes, qui nous dit que les petites îles ne dépassent pas 192 carreaux par x et y, les îles moyennes sont 272, les grandes îles sont 384. Les tailles d'îles réelles se trouvent dans les fichiers A7minfo à côté de A7M Fichier, où ActiveMaprect contient les valeurs x0, y0, x1, y1. Nous récupérons xsize = x1-x0 et ysize = y1-y0 et à partir de cela peut identifier la taille de l'île. Créez une liste séparée pour chaque taille de l'île et conservez également uniquement les îles avec l'ID <= 3 (normale; îles de démarrage uniquement). Triez chaque liste par filepath.
- Shuffle (std :: shuffle) Tous les emplacements de démarrage (machines à sous avec id == 1).
- Ajoutez les emplacements de démarrage mélangés à la fin des emplacements normaux (fentes avec id == 0 et type == 1).
- Mélanger le résultat.
- Triez le résultat par ID dans l'ordre descendant, afin que les emplacements de démarrage soient en haut.
- Pour chaque emplacement:
- Remplacez son ID par 1 << ID.
- Obtenez des îles de la même taille que la fente.
- Créez une liste d'îles compatibles. Pour être compatible, l'identifiant de l'île doit être compatible avec l'ID de la machine à sous (Island.id & slot.id) et la région de l'île doit être compatible avec la région du monde et la difficulté de l'île doit être compatible avec le cadre de l'utilisateur et l'île GameMode doit être compatible avec le paramètre utilisateur. (Tous les vérifications sauf que l'identification peut être poussée loin de la boucle, mais ce n'est pas ainsi que le jeu le fait.)
- Sélectionnez au hasard une île pour cette fente (std :: uniforme_int_distribution). Sélectionnez au hasard une rotation (valeurs de 0 à 3, 90 degrés chacune, std :: uniforme_int_distribution). Retirez l'île et sa variante River / River non-River des îles disponibles pour ce monde.
- Mercer tous les pirates (ne faites rien) et tous les emplacements de pirate (id == 4) et placez le pirate sur la première fente. Dessiner une rotation.
- Ajoutez les emplacements pirates inutilisés à la fin des emplacements NPC (id == 3).
- Mercer tous les PNJ, mais trier alors que Archibald Blake arrive en premier. Cape a les mêmes PNJ que l'ancien monde sauf Archibald Blake.
- Mercer toutes les machines à sous et placer les PNJ sur les premières créneaux. Dessiner des rotations.
- Tanker les emplacements inutilisés jusqu'à présent, triez-les pour que ID == 3 soit en premier et les traitez comme des machines à sous normales (id = 0). Ensuite, étape 9) avec eux.
Le Cape World mélange également les PNJ de l'ancien monde (mais sans Archibald Blake) mais il n'y a pas de créneaux de PNJ du tout, donc le placement de l'île n'est pas affecté. Je pense que les fertilités et les créneaux de mines à Cape seront différents selon que vous avez sélectionné ou non les deux PNJ de l'ancien monde. (Le shuffle ne dessine pas de nombres aléatoires s'il y a moins de 2 éléments à mélange, donc 0 NPC et 1 PNJ ne font pas avancer le RNG.)
Outils utilisés
- x64dbg: outil principal pour suivre le code. Le jeu a quelques chaînes utiles pour la journalisation, par exemple "Création de carte de départ, MapGenerator Seed: {}" qui donne une bonne idée de ce qui se passe.
- Ghidra: La définition des structures était très utile. Malheureusement, il ne voulait pas communiquer avec X64DBG et son débogueur intégré est coincé.
- Rdaexplorer
- Pain de file d'attente