Buscador y visualizador de semillas de anno 1800
El buscador pasa por todas las semillas para encontrar aquellos con los puntajes más altos. La puntuación predeterminada es el número de fichas de tierra edificables. Para acelerar las cosas, también permite una lista de islas no deseadas. Estas islas pueden no aparecer en su mundo respectivo. La elección obvia aquí son las islas con ríos.
El tipo de mapa, el tamaño del mapa, el tamaño de la isla y la dificultad de la isla se pueden ajustar. El buscador trabaja en dos iteraciones, filtrado de línea de base y luego un paso de refinamiento de semillas rápidas. Ambos hacen lo mismo pero aún tienen su propósito.
- La línea de base filtraba fuerzas brutas a través de todas las semillas posibles 2147483648 para descartar islas universalmente malas (por ejemplo, con ríos). Los resultados se guardan en el disco. El rendimiento es de aproximadamente 1 millón de semillas por segundo por núcleo de CPU, lo que significa un cómodo tiempo de ejecución de 2.5 minutos en un 5950X. Si no se definen islas no deseadas, los tiempos de ejecución son aproximadamente 4 veces más largos. La línea de base sin río para los cinco mapas del Viejo Mundo ya está incluida.
- El refinamiento de semillas carga las semillas creadas en el paso 1 desde el disco. Debido a que quedan relativamente pocas semillas, el refinamiento tarda solo un segundo en correr. Esto hace que sea fácil visualizar múltiples semillas o ajustar los requisitos. En particular, el número de NPC y piratas solo tiene un pequeño impacto en el puntaje y no tiene impacto en si las islas tienen ríos o no, por lo que se puede usar la misma línea de base para cualquier combinación de NPC/pirata.
El buscador intentará reutilizar agresivamente archivos de línea de base, por lo que si cambió las islas no deseadas y desea crear una línea de base desde cero, debe ingresar a la carpeta Seeds y eliminar manualmente el archivo de referencia existente.
El buscador también visualizará el mapa con islas y NPC. Ese mapa contiene el Viejo Mundo, el Área del Cabo y el Nuevo Mundo, porque estos son los mundos donde la semilla tiene un impacto.
Instalación
- Debe tener Python: https://www.python.org/downloads/ Haga lo opuesto a las recomendaciones de instalación: active la casilla de verificación de ruta y no instale para todos los usuarios.
- Los paquetes de Python se pueden instalar desde una ventana CMD con: PIP Instale Numpy Pandas Matplotlib Pillow
- Si no se encuentra PIP, no seleccionó la casilla de verificación de ruta y necesita establecer su variable de entorno (o simplemente reinstalar).
- Si falla debido a los permisos, entonces Python se instaló para todos los usuarios y no en el directorio de usuario, por lo que CMD debe ejecutarse desde el modo de administración (o simplemente reinstalar).
- Haga clic derecho en el archivo Main.py y elija Editar con Idle. Ajuste la configuración según sea necesario y presione F5 para ejecutar.
Notas
El buscador solo puede filtrar a través de la selección de la isla. Las cosas que no se pueden filtrar son: rotación de la isla; posición de la isla; fertilidad; Ranuras mineras.
Las fertilidades y las ranuras mineras en particular son un problema bastante difícil porque llegan al final de la creación de la isla. Para poner las cosas en perspectiva, toda la colocación y rotación de la isla+NPC se realiza con los primeros 70 números aleatorios del Twister de Mersenne. Luego, el juego atrae alrededor de 18000 números más antes de que se decidan las fertilidades y las ranuras mineras. Hay mucho código de juego adicional para descifrar y el filtrado sería bastante lento incluso cuando se usa solo las semillas de base.
Si desea ejecutar los scripts de recuperación usted mismo (Copypics.py, maptemplatestocsv.py, maptocsv.py), esperan que el repositorio tenga dos carpetas vecinas, una para el pan de pizarra y otro para todos los activos de juego como se extrae con el RDaexplorer. Es decir, las carpetas ../filedbreader y ../Data debería existir.
El código C es básicamente una versión muy optimizada (y despojada) de la creación de mapas en Util.py. Este último no rechaza temprano y está escrito principalmente en Python, produciendo solo 25 semillas por segundo por núcleo, por lo que incluso trabajar solo con datos de referencia sin un mayor rechazo sería bastante lento.
El flujo de código general para cada mundo (por ejemplo, el Viejo Mundo, New World, Cape) es el siguiente:
- Inicialice un generador de números aleatorios de Mersenne Twister de la biblioteca estándar (STD :: MT19937) con la semilla que el usuario dio.
- Desde datos/config/export/main/asset/assets.xml, cargue todos los elementos maptemplate. Compare la entrada real del usuario (tipo de mapa, tamaño del mapa, ...) con estos elementos y mantenga solo los elementos que coincidan. Seleccione aleatoriamente uno de estos elementos (std :: uniform_int_distribution). (Sucede que solo hay exactamente un elemento para cada una de estas configuraciones, excepto cuando se seleccionó el tipo de mapa "aleatorio". Solo el nuevo mundo tiene múltiples). Esto es lo que recupera el Maptemplatestocsv.py.
- La plantilla de mapa seleccionada contiene una ruta a un archivo A7T, que no nos interesa. Pero está al lado de un archivo A7Tinfo, que tiene información sobre el tamaño del mundo y también tiene las ranuras de la isla. Una ranura de la isla tiene coordenadas y tamaño y también tipo e ID. La generación de mapas más adelante se trata de ranuras coincidentes con islas compatibles (en términos de tamaño y tipo e ID). MapTocsv.py recupera estos datos de A7Tinfo.
- Independientemente del mapa, todas las islas están cargadas. El Assets.xml tiene entradas aleatorias que especifican FilePath (a A7M), región, dificultad, IslandType (que en realidad es la identificación para que coincida con el slot.id). Sin embargo, no hay tamaño. El Assets.xml también tiene una entrada de Islandsize, que nos dice que las islas pequeñas no son más de 192 mosaicos por x e y, las islas medianas son 272, las islas grandes son 384. Los tamaños de las islas reales están en los archivos A7Minfo al lado del A7M. Archivo, donde ActiveMapRect contiene los valores x0, y0, x1, y1. Recuperamos xsize = x1-x0 e ysize = y1-y0 y de eso puede identificar el tamaño de la isla. Cree una lista separada para cada tamaño de la isla y también mantenga solo islas con la ID <= 3 (normal; solo islas de inicio). Ordene cada lista por FilePath.
- Shuffle (std :: shuffle) Todas las ranuras de inicio (ranuras con id == 1).
- Agregue las ranuras de inicio barajadas al final de las ranuras normales (ranuras con id == 0 y tipo == 1).
- Barajar el resultado.
- Ordene el resultado por ID en orden descendente, de modo que las ranuras de inicio están en la parte superior.
- Para cada ranura:
- Reemplace su ID por 1 << id.
- Obtenga islas con el mismo tamaño que la ranura.
- Cree una lista de islas compatibles. Para ser compatible, la identificación de la isla debe ser compatible con la identificación de la ranura (isla.id & slot.id) y la región de la isla debe ser compatible con la región del mundo y la dificultad de la isla debe ser compatible con la configuración del usuario y la isla GameMode debe ser compatible con la configuración del usuario. (Todos los cheques excepto ID se pueden empujar muy lejos del bucle, pero no es así como lo hace el juego).
- Seleccione al azar una isla para esta ranura (std :: uniform_int_distribution). Seleccione aleatoriamente una rotación (valores de 0 a 3, 90 grados cada uno, std :: uniform_int_distribution). Retire la isla y su variante de río/río de las islas disponibles para este mundo.
- Arrastra a todos los piratas (no hacer nada) y todas las ranuras piratas (id == 4) y coloque el pirata en la primera ranura. Dibujar rotación.
- Agregue las ranuras piratas no utilizadas al final de las ranuras NPC (id == 3).
- Baraja todos los NPC, pero luego ordene para que Archibald Blake sea primero. Cabo tiene los mismos NPC que el Viejo Mundo, excepto Archibald Blake.
- Arrobable todas las ranuras y coloque los NPC en las primeras ranuras. Dibujar rotaciones.
- Arrastra todas las ranuras no utilizadas hasta ahora, ordenarlas para que ID == 3 llegue primero y trátalas como ranuras normales (id = 0). Luego haz el paso 9) con ellos.
El mundo del Cabo también baraja los NPC del Viejo Mundo (pero sin Archibald Blake), pero no hay espacios NPC en absoluto, por lo que la colocación de la isla no se ve afectada. Creo que las fertilidades y las ranuras de la mina en Cape serán diferentes dependiendo de si hayas seleccionado a los NPC del Viejo Mundo o no. (El Shuffle no dibuja números aleatorios si hay menos de 2 elementos para barajar, por lo que 0 NPC y 1 NPC no avanzan el RNG).
Herramientas utilizadas
- X64DBG: herramienta principal para seguir el código. El juego tiene algunas cadenas útiles para el registro, por ejemplo, la creación de mapas ", la semilla de MapGenerator: {}" que dan una buena idea de lo que está sucediendo.
- Ghidra: definir estructuras fue muy útil. Lamentablemente, no quería comunicarse con X64DBG y su depurador construido se atasca.
- RdAExplorer
- Pan de archivo