Come posso generare in modo incrementale un grafico?


8

Ho appena iniziato un nuovo progetto in cui vorrei che il mondo di gioco consistesse in luoghi generati proceduralmente collegati da teletrasporto. Dopo un po 'di ricerche, ho scoperto che questo si chiama "teoria dei grafi" o "maledettamente complicato", a seconda di chi ne sta discutendo. Sfortunatamente, ho trovato pochissime informazioni sulla generazione di grafici; la maggior parte degli strumenti che ho visto sono diretti verso l'esame di grafici esistenti.

Supponendo che la terminologia sia corretta, i miei requisiti sono che il grafico sia:

  • semplice - nessuna posizione (vertice) dovrebbe avere un teletrasporto (bordo) che si ricollega a se stesso, né due vertici dovrebbero avere bordi multipli che li collegano
  • connesso - dovrebbe essere possibile viaggiare tra due vertici nel grafico (anche se non prevedo mai la necessità di trovare il percorso; è sufficiente sapere che il giocatore potrebbe trovarne uno se lo sceglie)
  • ciclico: dovrebbe esserci più di un percorso tra due vertici
  • non orientato: tutti i bordi possono essere percorsi in entrambe le direzioni
  • infinito - se il giocatore lo desidera, dovrebbe essere in grado di viaggiare indefinitamente, con il grafico che continua a generare in modo incrementale mentre si avvicinano ai suoi vertici più esterni inesplorati
  • localmente finito - il grado di un vertice non dovrebbe mai cambiare dopo che il giocatore lo ha visitato
  • stabilmente etichettato - ogni vertice rappresenta una posizione che sarà essa stessa generata proceduralmente da un seme; lo stesso seme deve essere assegnato a un vertice indipendentemente dal percorso che il giocatore ha usato per viaggiare lì o da quanto è grande il grafico quando lo fa

Ho avuto alcune idee (che non ho ancora provato a implementare) per quanto riguarda l'utilizzo massimi locali di 2D Perlin rumore come vertici (l'ingresso x e y poteva quindi essere utilizzato come la sua etichetta), ma che si sente goffo e troppo complicata.

C'è un modo migliore per generare un grafico come questo? Sto sviluppando in Python 2.6 usando Panda3D e numpy, e ovviamente sarei disposto a guardare includendo altre librerie se aiuteranno con questo problema!

modificare

Penso di aver fatto un pessimo lavoro spiegando alcune delle mie esigenze, quindi è tempo di illustrazione! Spero che questo chiarisca le cose.

Quello che intendo per avere etichette stabili è che voglio, ad esempio, che il Giocatore A sia in grado di fare un mucchio di esplorazioni e trovare, tra le altre cose, un percorso ciclico che ritorni alla posizione di partenza e una montagna che assomigli a un gatto. Il suo gioco ora è simile al seguente (i vertici sono numerati con il loro seme e bordi nell'ordine in cui il giocatore li ha attraversati). Ha iniziato con il vertice 8329 (verde) e Happycat Mountain è nel vertice 6745 (blu).

Grafico mondiale del giocatore A.

Il buon amico del giocatore A Il giocatore B è un fan dei gatti, quindi vuole mostrarglielo. Le dà il seme di radice per il suo mondo e le indicazioni lungo il percorso più breve verso la montagna di interesse. Il suo gioco ora dovrebbe apparire così:

Grafico mondiale del giocatore B.

Il problema con cui sto attualmente incontrando maggiori difficoltà è "Come faccio a generare gli stessi semi per il giocatore B quando la sua esplorazione non ha seguito lo stesso percorso?" Questo è ciò che mi ha portato all'idea di usare il rumore di Perlin: finché si utilizza lo stesso seme di radice, i massimi non si muoveranno, quindi le loro coordinate potrebbero essere usate come semi di vertice stabili.


Perché un grafico collegato non è adatto a questo? mathworld.wolfram.com/ConnectedGraph.html Tuttavia, mi potrebbe mancare il punto. Se un utente desidera passare da una posizione all'altra e sono tutti connessi, fornisci loro un elenco di posizioni e sposta la loro posizione sulla mappa del mondo nella nuova posizione.
Brandon,

@brandon - "Connected" è la seconda proprietà che elenco. :-)
Ben Blank,

il mio punto è, se puoi passare da un nodo all'altro. Quando visitano un teletrasporto, dai loro un elenco di tutti i nodi che hanno visitato tranne questo. Non è necessario disporre di un grafico, si conserva un elenco di tutti i nodi visitati e le relative posizioni e si teletrasporta solo nella posizione scelta. Sto fraintendendo?
Brandon,

quasi tutte le descrizioni di questi termini sono corrette, ad eccezione di "ciclico" e "localmente finito". Il primo limita i tuoi grafici in modo che sembrino: un cerchio. Un termine che potresti utilizzare per il requisito che ci siano più percorsi da un vertice all'altro è "2-connesso". "Localmente finito" significa solo che ogni vertice ha un numero finito di spigoli.
Harry Stern,

@Harry Stern - La mia comprensione è che i grafici ciclici sono grafici contenenti almeno un ciclo di grafici . Sembra che tu stia parlando di un grafico del ciclo , che è un grafico costituito da un singolo ciclo grafico e nient'altro. In particolare non cerco grafici che siano "2-connessi" (vedi "semplice"). E sì, questo è ciò che intendevo per "localmente finito".
Ben Blank,

Risposte:


6

Non puoi creare un grafico infinito. La tua memoria è finita, quindi anche il numero di vertici e bordi è finito. Quello che puoi fare è creare un grafico finito, quindi aggiungerne altro. Sembra che tu l'abbia capito, ma penso che sia importante che sia esplicitamente dichiarato in modo da non percorrere una strada senza uscita.

Devi stare molto attento quando parli di "vertici più esterni". Un grafico è un insieme di vertici, un insieme di bordi e una funzione che collega i due. Non esiste un'interpretazione geometrica definita se non ne applichi una. Ad esempio: entrambe queste immagini mostrano esattamente lo stesso grafico. Nella prima immagine, il vertice 2 potrebbe essere considerato un vertice "più esterno", mentre nella seconda immagine il vertice 2 non sarebbe considerato "più esterno". Se hai considerato tre dimensioni, potresti dire che tutti i vertici sono "più esterni".

Grafico 1 Grafico 2

Questo significa che devi avere qualche altra informazione per poter sapere cos'è un vertice "più esterno". Potresti usare coppie (x, y) in quanto ciò ti darebbe una rappresentazione geometrica facile da visualizzare, tuttavia non penso che tu debba andare così lontano. Da quello che dici, tutto ciò che devi sapere è già quali vertici sono nel grafico.

Se lo hai eseguito ogni volta che hai visitato un vertice:

if(this.needsNeighbours)
{
    List<int> connections = genRandomNumbers(n);
    foreach (int connection in connections)
    {
        //Simple graph
        if(connection == this.seed || this.hasNeighbour(connection))
        {
            continue;
        }
        //Connections to already existing, unvisited vertices
        else if(nodeMap.containsKey(connection) && 
                nodeMap.getByKey(connection).needsNeighbours)
        {
            nodeMap.getByKey(connection).addNeighbour(this.seed);
            this.addNeighbour(connection);
        }
        //Grow graph with new vertices
        else
        {
            nodeMap.add(connection, new Node(connection));
            nodeMap.getByKey(connection).addNeighbour(this.seed);
            this.addNeighbour(connection);
        }
    }
    this.needsNeighbours = false;
}

il tuo grafico soddisferebbe tutti i tuoi requisiti tranne che per essere ciclico. Non so se hai davvero bisogno di una garanzia. In tal caso, è possibile selezionare in modo specifico un nodo non visitato e stabilire una connessione, ciò garantirebbe un percorso tra il nodo corrente e un nodo già visitato poiché tutti i nodi non visitati sono connessi ad almeno un nodo visitato e poiché è stato necessario aver visitato un il nodo visitato per arrivare dove sei ora ci sono almeno due percorsi.

È semplice perché esiste un controllo esplicito, collegato perché tutti i nuovi nodi ottengono almeno una connessione, localmente finito perché i bordi vengono aggiunti solo prima della visita o alla prima visita e solo ai nodi non visitati. Tecnicamente non è non indirizzato, ma funzionalmente è lo stesso che si crea un bordo direzionale in entrambe le direzioni. Puoi etichettare il nodo come vuoi, io uso il numero casuale generato, ma potresti aggiungere altri parametri al costruttore, uno dei quali è il tuo seme.


Capisci esattamente cosa intendevo per "infinito" e il tuo punto su "estremo" è ben preso - ho modificato la verbosità della mia domanda. Tuttavia, o non capisco correttamente il tuo generatore o ho spiegato male le mie esigenze, poiché sembra che questo non genererebbe gli stessi semi per percorsi diversi verso lo stesso vertice. Ho aggiunto alcune illustrazioni alla mia domanda che, si spera, renderanno più chiaro ciò che sto cercando di realizzare. :-)
Ben Blank,

Capisco cosa intendi adesso. È un po 'più difficile. Quello che dovresti fare è cambiare la chiamata genRandomNumbers in una funzione che restituisce sempre lo stesso insieme di numeri per il suo input e usa il seed del nodo come argomento. Ciò garantirebbe che otterresti le stesse connessioni e seed, indipendentemente dal percorso che prendi o dal nodo da cui inizi. Dovresti fare attenzione che l'insieme di numeri per il nodo B al quale A si connette contenga anche A in modo da ottenere la proprietà del tuo grafico non indirizzato. Se non lo fai, otterrai un grafico diretto.
Chewy Gumball,

1

Un metodo:

init:
  root = generateLocation using random seed
  store root's seed
  place player in root location

when the player enters a new location:
  release the memory used by locations that are further than 1 edge away, but keep their seeds
  generate some neighbors for the new location. for every neighbor n:
    gen.seed(getSeed(n))
    n = generateLocation using n's random seed
    numCyclicEdges = gen.randint(0, 1)
    create numCycleEdges edges to existing locations

getSeed(n):
  if(n already has a seed) return n's seed
  else return randomSeed()

Ci sono molti dettagli che ho lasciato fuori, ma questo dovrebbe catturare l'idea generale. Potresti voler tenere in memoria i vicini che si trovano più bordi dalla posizione corrente, a seconda della distanza del mondo tra i portali, della memoria disponibile disponibile, ecc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.