Identificar la ascendencia de un proyecto de software a menudo se complica por el hecho de que los desarrolladores suelen renombrar funciones, reescribir la lógica o portar el software a lenguajes de programación completamente diferentes. Los métodos tradicionales para rastrear estos linajes suelen basarse en la coincidencia del texto fuente o de los nombres de las funciones. Sin embargo, un estudio de 43 descendientes del código fuente original de DOOM demuestra que estas etiquetas pueden ser engañosas. Por ejemplo, 'Chocolate Doom' conserva el 87% de los nombres de funciones del original, pero solo el 35% del código real dentro de esas funciones permanece sin cambios. En otros casos, como 'Doom Retro', se mantienen los nombres mientras que casi el 100% del código interno es reescrito.

Para superar las limitaciones del texto legible por humanos, los investigadores utilizaron un motor de medición de código que ignora por completo los nombres y los comentarios. En su lugar, analiza la 'forma' de un programa registrando docenas de mediciones para cada función, incluyendo su longitud, patrones de ramificación y qué otras funciones llama. Al identificar funciones 'parecidas' cuyas mediciones coinciden demasiado para ser una coincidencia, el motor puede identificar copias con una precisión del 93%. Esta huella dactilar estructural es lo suficientemente robusta como para distinguir a DOOM de programas en C no relacionados como Quake o Quake II, que comparten entre el 0% y el 0,6% de la forma de DOOM.

Un collage que representa el linaje y el ADN estructural del código fuente de DOOM.
La investigación sobre los descendientes de DOOM muestra que las estructuras de código internas persisten incluso cuando los nombres de las funciones y las líneas específicas se reescriben.squid-protocol.github.io

La imagen ilustra el concepto de la 'forma' de un programa o huella dactilar estructural que sobrevive a través de diferentes versiones y puertos.

Cuando un proyecto se reescribe completamente en un nuevo lenguaje, como Go o Scheme, las formas de las funciones individuales pueden desaparecer, pero el 'cableado' —el mapa de qué subsistemas del juego (como el renderizador o la física) se llaman entre sí— a menudo sobrevive. En una prueba ciega donde todos los nombres estaban ocultos, la traducción en Go todavía clasificó el 60% de sus funciones en las partes correctas del juego, superando significativamente la suposición aleatoria del 20%. Sin embargo, este plano estructural no es universal. Las versiones en lenguajes como Java, Kotlin y C# no mostraron linaje detectable porque reorganizaron el código en piezas diminutas y fragmentadas (a menudo de tres líneas o menos), borrando efectivamente la firma del diseño original. Esto resalta un compromiso crítico: si bien el análisis estructural puede rastrear el linaje a través de la mayoría de las versiones, falla cuando la 'forma' arquitectónica se desmantela fundamentalmente durante el proceso de traducción.