-1

I started to make a dungeon-game that creates randomly new dungeons. There for I have the seededRandom function. Judging from my test, this function is correct.

function seededRandom (seed, min = 0, max = 1) {
  const random = ((seed * 9301 + 49297) % 233280) / 233280
  return min + random * (max - min)
}

It will be called inside the createDungeon function with Date.now() as argument for seed

function createDungeon(numberOfRooms, rooms = []) {
  ...
  const randomWidth = Math.floor(Generator.seededRandom(Date.now(), 10, 20))
  const randomHeight = Math.floor(Generator.seededRandom(Date.now(), 10, 20))
  const randomTopLeftCoordinate = Coordinate.create(
    Math.floor(Generator.seededRandom(Date.now(), 10, previousRoom.width)), // x position
    Math.floor(Generator.seededRandom(Date.now(), 10, previousRoom.height)) // y position
  )
  ...
}

Inside my tests I logged the start timestemp, createDungeon return value and end timestemp and apparently Date.now() is not exactly enough.

1502301604075 // start timestemp
[ 
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } },
  ...
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } },
  { width: 19, height: 19, topLeftCoordinate: { x: 18, y: 18 } } 
] 
1502301604075 // end timestemp

Question

What could I use as seed to have in each object a different value based on the seed?

Roman
  • 4,922
  • 3
  • 22
  • 31

1 Answers1

1

Like the comments mentioned: there are several seeded random number libraries out there that should be perfectly suitable for your application. I used this one in my example.

The key is to create a seeded random number generator before getting the dungeon's properties:

const DungeonCreator = seed => {
  const rnd = new Math.seedrandom(seed);

  return nrOfRooms => ({
    width: inRange(rnd(), 0, 20),
    height: inRange(rnd(), 0, 20),
    topLeft: {
      x: inRange(rnd(), 0, 10),
      y: inRange(rnd(), 0, 10)
    },
    nrOfRooms
  })
}

This method returns a dungeon generator that will give you a new dungeon every time you call it. However, generators that were created using the same seed, will give you the same dungeons.

Although not "pure", it makes the code testable.

const DungeonCreator = seed => {
  const rnd = new Math.seedrandom(seed);
  
  return nrOfRooms => ({
    width: inRange(rnd(), 0, 20),
    height: inRange(rnd(), 0, 20),
    topLeft: {
      x: inRange(rnd(), 0, 10),
      y: inRange(rnd(), 0, 10)
    },
    nrOfRooms
  })
}

const myDungeonCreator1 = DungeonCreator("seedOne");
const myDungeonCreator2 = DungeonCreator("seedTwo");
const myDungeonCreator3 = DungeonCreator("seedOne");

const roomSizes = [1, 3, 6, 3, 2, 6];

const dungeons1 = roomSizes.map(myDungeonCreator1);
const dungeons2 = roomSizes.map(myDungeonCreator2);
const dungeons3 = roomSizes.map(myDungeonCreator3);

console.log("Creator 1 & 3 created the same dungeons:",
  dungeonsEqual(dungeons1, dungeons3)
);

console.log("Creator 1 & 2 created the same dungeons:",
  dungeonsEqual(dungeons1, dungeons2)
);

console.log("Creator 2 & 3 created the same dungeons:",
  dungeonsEqual(dungeons2, dungeons3)
);


// Util
function inRange(value, min, max) {
  return min + Math.floor(value * (max - min));
};

function dungeonEqual(d1, d2) {
  return (
  d1.nrOfRooms === d2.nrOfRooms &&
  d1.width === d2.width &&
  d1.height === d2.height &&
  d1.topLeft.x === d2.topLeft.x &&
  d1.topLeft.y === d2.topLeft.y
  );
}

function dungeonsEqual(ds1, ds2) {
  return ds1.every((d, i) => dungeonEqual(d, ds2[i]));
};
<script src="//cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js">
</script>
user3297291
  • 22,592
  • 4
  • 29
  • 45