En el juego 2D con el que estoy trabajando, el motor del juego me puede dar, para cada unidad, la lista de otras unidades que están en su rango de visión.
Me gustaría saber si existe un algoritmo establecido para clasificar las unidades en grupos , donde cada grupo estaría definido por todas esas unidades que están "conectadas" entre sí (incluso a través de otras).
Un ejemplo podría ayudar a comprender mejor la pregunta (E = enemigo, O = propia unidad). Primero los datos que obtendría del motor del juego:
E1 can see E2, E3, O5
E2 can see E1
E3 can see E1
E4 can see O5
E5 can see O2
E6 can see E7, O9, O1
E7 can see E6
O1 can see E6
O2 can see O5, E5
O5 can see E1, E4, O2
O9 can see E6
Entonces debería calcular los grupos de la siguiente manera:
G1 = E1, E2, E3, E4, E5, O2, O5
G2 = O1, O9, E6, E7
Se puede suponer con seguridad que existe una propiedad conmutativa para el campo de visión: [si A ve B, entonces B ve A].
Solo para aclarar: ya escribí una implementación ingenua que se repite en cada fila de la información del motor del juego, pero por lo que parece, parece un problema lo suficientemente general como para que se haya estudiado en profundidad y tenga varios algoritmos establecidos (tal vez pasando a través de alguna estructura en forma de árbol?). Mi problema es que no pude encontrar una manera de describir mi problema que arrojó resultados de Google útiles.
¡Gracias de antemano por su ayuda!
Respuestas:
Si su relación "puede ver" es simétrica, de modo que "A puede ver B" implica que "B puede ver A", entonces los grupos que desea calcular son los componentes conectados del gráfico definidos por la relación "puede ver". Como otros han señalado, existen algoritmos simples para calcularlos, tales como:
(Se puede usar una cola o cualquier otra colección que implemente eficientemente las operaciones "agregar nuevo elemento" y "eliminar y devolver algún elemento" en lugar de la pila
s
anterior).Si su relación "puede ver" no es simétrica, debe decidir si desea que sus grupos sean los componentes fuertemente o débilmente conectados. Para componentes débilmente conectados, el algoritmo anterior funcionará tal cual, excepto que la línea
for each unit w that v can see
debe reemplazarse porfor each unit w that can see v, or that v can see
. Para componentes fuertemente conectados , puede usar uno de los algoritmos (de Kosaraju , Tarjan o Gabow ) mencionados en la página de Wikipedia vinculada.Para las relaciones no simétricas, es posible que también desee calcular el cierre transitivo de la relación, o de sus componentes fuertemente conectados. Para esto, puede usar el algoritmo Floyd – Warshall ; vea esta respuesta en SO para obtener (un poco) más información.
PD. Como el artículo de Wikipedia que he vinculado a las notas anteriores, puede ser más eficiente actualizar dinámicamente los grupos a medida que cambia la relación de visibilidad. No estoy familiarizado con los algoritmos avanzados (?) Mencionados en Wikipedia, pero no debería ser difícil improvisar algo que al menos sea mejor que volver a calcular los grupos desde cero cada vez.
La mitad de esto es fácil: si dos unidades en diferentes grupos adquieren una línea de visión entre ellas, fusiona los grupos. Tratar con unidades que se pierden de vista es un poco más complicado; Una solución simple pero quizás no óptima es volver a ejecutar el algoritmo de agrupación para las unidades en el grupo afectado siempre que eso suceda. Hay algunas optimizaciones que puede hacer para eso, si los cambios de visibilidad ocurren un par de unidades a la vez:
fuente
Lo que tienes es un gráfico de conectividad. Y, en general, la mejor manera de agrupar los nodos conectados (es decir, los caracteres) juntos es con un algoritmo de búsqueda de gráficos. Profundidad primero, ancho primero, lo que sea. Todo lo que está haciendo es crear una lista de qué nodos son accesibles desde todos los demás. Mientras su gráfico no esté dirigido (si A es visible para B, entonces B es visible para A), esto funciona bien.
Puede haber algunos algoritmos para mejorar esto para casos específicos. Por ejemplo, si a veces los personajes no se mueven (y el terreno tampoco se mueve, por lo que los personajes inmóviles permanecen visibles), puede optar por no probarlos nuevamente para actualizar sus gráficos de conectividad.
Pero, en general, tendrá que volver a probar la visibilidad en cada fotograma. Las probabilidades son que va a ser más lento que el recorrido del gráfico para encontrar los grupos de visibilidad.
fuente
Parece un problema de conectividad gráfica estándar. Puede haber algún tipo de algoritmo para esto, y podría verse así:
Espero que sea posible implementar esto a través de un árbol, como el agrupamiento jerárquico, pero dudo que eso funcione más rápido: los árboles tienden a ser O (log N), mientras que la mayoría de las comprobaciones que doy anteriormente se pueden implementar como O (1) .
fuente
Estoy de acuerdo con todos los demás que respondieron en términos de que se trata de un problema de conectividad gráfica, sin embargo, permítanme señalar que lo que necesita aquí es el gráfico de triangulación de Delaunay generado a partir de todas sus unidades relevantes. Lo que esto hace es garantizar que solo las unidades más cercanas entre sí se conectarán en el gráfico que genere. Le resultará muy difícil hacer esto de cualquier otra manera, ya que los cruces de gráficos (sin planaridad) harán que las unidades demasiado alejadas entre sí estén conectadas incorrectamente dentro del gráfico.
Lo anterior solo se aplica si está utilizando un espacio continuo (como en la mayoría de los FPS de movimiento libre); sin embargo, si ya tiene una cuadrícula subyacente (un gráfico plano) en el que se mueven sus unidades, puede usarla para evaluar la conectividad.
fuente