Generate Universe

by InfinitiesLoop

HTML

<script src="https://d3js.org/d3.v3.js"></script>

CSS

.link {
    stroke: #666;
    opacity: 0.6;
    stroke-width: 1.5px;
}
.node circle {
    stroke: #fff;
    opacity: 0.6;
    stroke-width: 1.5px;
}
text {
    font: 15px serif;
    opacity: 0.6;
    pointer-events: none;
}

JavaScript

generate(200, 10);

function generate(numSectors, numReserved) {
  var context = {
    allSectors: [],
    sectorList: [],
    eligibleBackExits: [],
    sectorMap: {},
    queue: [],
    maxExits: 6,
    connectedness: 0.2
  };
  numReserved = numReserved || 0;
  for (var i = 0; i < numReserved; i++) {
    var sector = { sector: i, exits: [] };
    context.allSectors.push(sector);
    context.sectorMap[i] = sector;
  }
  
  for(var i = 1 + numReserved; i <= numSectors; i++) {
    var sector = { sector: i, exits: [] };
    context.sectorList.push(i);
    context.allSectors.push(sector);
    context.sectorMap[i] = sector;
  }

  var start = pickRandom(context.sectorList);
  context.eligibleBackExits.push(start);
  context.queue.push(start);
  
  while(context.queue.length)
    processNext(context);
    
  console.log('universe:');
  console.log(context.allSectors);
  
  for(var s of context.allSectors) {
    console.log(`${s.sector}: ${s.exits.map(e => e.sector).join(' ')}`);
  }
  
  makeD3(context.allSectors);
}

function processNext(context) {
  var sector = context.queue.shift();
  var exitCount = rand(1, context.maxExits);
  for (var i = context.sectorMap[sector].exits.length; i < exitCount; i++) {
    var backExit = roll(context.connectedness);
    if (backExit) {
      var exit = pickRandom(context.eligibleBackExits, sector, true);
      //console.log(['back', context.eligibleBackExits.length, exit]);
      if (exit) {
        connect(context, sector, exit);
        if (context.sectorMap[exit].exits.length >= context.maxExits) {
        	// that one is full so is no longer eligible
          context.eligibleBackExits.splice(context.eligibleBackExits.findIndex(s => s === exit), 1);
        }
      }
    }
    else {
      var exit = pickRandom(context.sectorList, sector);
      if (exit) {
        connect(context, sector, exit);
        // the exit we picked is eligible for future back connections if it isn't full
        if...