arx-level-generator
Version:
A tool for creating Arx Fatalis maps
92 lines • 3 kB
JavaScript
import { repeat, sum } from './faux-ramda.js';
export const randomSort = (items) => {
const copyOfItems = [...items];
const sortedItems = [];
while (copyOfItems.length) {
const idx = pickRandomIdx(copyOfItems);
sortedItems.push(copyOfItems.splice(idx, 1)[0]);
}
return sortedItems;
};
/**
* const values = pickWeightedRandoms(10, [
* { value: -6, weight: 10 },
* { value: 0, weight: 100 },
* { value: 6, weight: 10 },
* ])
*
* values === [
* { value: 0, weight: 100 },
* { value: -6, weight: 10 },
* { value: 0, weight: 100 },
* { value: 0, weight: 100 },
* { value: 0, weight: 100 },
* { value: 6, weight: 10 },
* { value: 0, weight: 100 },
* { value: 0, weight: 100 },
* { value: 0, weight: 100 },
* { value: 0, weight: 100 }
* ]
*
* guaranteePresenceOfAll=true will sort items with smaller weights to the beginning of the weightedSet
* so they will always be present in the list of items, no matter how heavy other items are
* this way the item with weight=1 will be guaranteed to show up in the selected list
*/
export const pickWeightedRandoms = (amount, set, guaranteePresenceOfAll = false) => {
const weights = set.map(({ weight }) => weight);
const totalWeight = sum(weights);
const percentages = weights.map((weight) => weight / totalWeight);
const weightedSet = percentages
.map((weight, idx) => ({
idx,
originalWeight: set[idx].weight,
weight: Math.ceil(weight * amount),
}))
.sort((a, b) => {
if (guaranteePresenceOfAll) {
return a.originalWeight - b.originalWeight;
}
else {
return b.originalWeight - a.originalWeight;
}
})
.flatMap(({ weight, idx }) => repeat(set[idx], weight))
.slice(0, amount);
return randomSort(weightedSet);
};
/**
* creates a random floating point number between a (inclusive) and b (exclusive)
*/
export const randomBetween = (a, b) => {
return a + Math.random() * (b - a);
};
/**
* creates a random integer between min and max (both inclusive)
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive
*/
export const randomIntBetween = (min, max) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1) + min);
};
export const pickRandoms = (n, set) => {
if (set.length <= n) {
return set;
}
else {
const remaining = set.slice();
let matches = [];
for (let i = 0; i < n; i++) {
const idx = randomIntBetween(0, remaining.length - 1);
matches = matches.concat(remaining.splice(idx, 1));
}
return matches;
}
};
export const pickRandom = (set) => {
return pickRandoms(1, set)[0];
};
export const pickRandomIdx = (set) => {
return pickRandom([...set.keys()]);
};
//# sourceMappingURL=random.js.map