Skip to content

Instantly share code, notes, and snippets.

@mmdts
Last active February 13, 2021 05:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmdts/e3a66a7100ac700d2562963efa239b73 to your computer and use it in GitHub Desktop.
Save mmdts/e3a66a7100ac700d2562963efa239b73 to your computer and use it in GitHub Desktop.
// This is duels using selection from a pool of biased non-binary weighted randoms.
// This makes it so that all players HAVE A TENDENCY duel in a random order before any player duels twice.
// 1) It DOES incentivize players with less duels to being picked in duels.
// 2) It HAS SOMETHING preventing two players from duelling twice in a row.
// 3) It has nothing to prevent 2 duels in a row when only 2 players are left.
const ITERATIONS = 1000;
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE_INCREMENT = 0.005; // There is a 4% chance that a player loses on any given round. For simulation purposes.
const FULL = 100;
const BIAS = 40;
function weighted_random(weights) {
let sum = weights.reduce((acc, o) => acc + o);
let rnd = ~~(Math.random() * sum);
for (let i = 0; i < weights.length; i++) {
if (rnd - weights[i] < 0) return i;
rnd -= weights[i];
}
return ~~(Math.random() * weights.length);
}
Number.prototype.p = function (l) {
return ('' + this).padStart(l, '0');
}
Array.prototype.p = function (l) {
return this.map((o) => ('' + o).padStart(l, '0'));
}
let total_round_count = 0;
for (let k = 0; k < ITERATIONS; k++) {
let elimination_chance = ELIMINATION_CHANCE_INCREMENT;
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_weights = Array(PLAYER_COUNT).fill(0); // For the weighted random.
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
console.log(`===================`);
console.log(`=====GAME #${("00" + k).slice (-3)}=====`);
console.log(`===================`);
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let living_player_weights = player_weights.filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
let weighted_random_result;
if (Math.random() < duel_chance) { // A duel was rolled
console.log(` Living player weights: ${living_player_weights}.`);
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_1 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_2 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
// Calculate new deul probability weights.
let most_duels = player_duels_played.reduce((acc, o) => Math.max(acc, o));
for (let i = 0; i < PLAYER_COUNT; i++) {
if (player_eliminated[i] == 0) {
player_weights[i] = (most_duels - player_duels_played[i]) * FULL + ~~(Math.random() * BIAS);
}
}
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < elimination_chance) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl == 1) break; // Get out of the loop when there's only one player alive.
round_number++;
elimination_chance += ELIMINATION_CHANCE_INCREMENT;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
}
total_round_count += round_number;
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
}
console.log(`The average rounds per game was ${total_round_count/1000}.`);
// This is uniform random duels.
// 1) It does not incentivize players with less duels to being picked in duels.
// 2) It has nothing preventing two players from duelling twice in a row.
// 3) It has nothing to prevent 2 duels in a row when only 2 players are left.
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE = 0.04; // There is a 4% chance that a player loses on any given round. For simulation purposes.
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
if (Math.random() < duel_chance) { // A duel was rolled
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
duelist_1 = living_players.splice(~~(Math.random() * living_players.length), 1)[0];
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
duelist_2 = living_players.splice(~~(Math.random() * living_players.length), 1)[0];
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < ELIMINATION_CHANCE) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl <= 1) break; // Get out of the loop when there's only one player alive.
round_number++;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
}
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
// This is duels using selection from a pool of binary weighted randoms.
// This makes it so that all players duel in a random order before any player duels twice.
// 1) It DOES incentivize players with less duels to being picked in duels.
// 2) It HAS SOMETHING preventing two players from duelling twice in a row.
// 3) It has nothing to prevent 2 duels in a row when only 2 players are left.
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE = 0.04; // There is a 4% chance that a player loses on any given round. For simulation purposes.
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_weights = Array(PLAYER_COUNT).fill(0); // For the weighted random.
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
function weighted_random(weights) {
let sum = weights.reduce((acc, o) => acc + o);
let rnd = ~~(Math.random() * sum);
for (let i = 0; i < weights.length; i++) {
if (rnd - weights[i] < 0) return i;
rnd -= weights[i];
}
return ~~(Math.random() * weights.length);
}
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let living_player_weights = player_weights.filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
let weighted_random_result;
if (Math.random() < duel_chance) { // A duel was rolled
console.log(` Living player weights: ${living_player_weights}.`);
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_1 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_2 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
// Calculate new deul probability weights.
let most_duels = player_duels_played.reduce((acc, o) => Math.max(acc, o));
for (let i = 0; i < PLAYER_COUNT; i++) {
if (player_eliminated[i] == 0) {
player_weights[i] = most_duels - player_duels_played[i];
}
}
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < ELIMINATION_CHANCE) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl == 1) break; // Get out of the loop when there's only one player alive.
round_number++;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
}
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
// This is duels using selection from a pool of biased non-binary weighted randoms.
// This makes it so that all players HAVE A TENDENCY duel in a random order before any player duels twice.
// 1) It DOES incentivize players with less duels to being picked in duels.
// 2) It HAS SOMETHING preventing two players from duelling twice in a row.
// 3) It has nothing to prevent 2 duels in a row when only 2 players are left.
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE = 0.04; // There is a 4% chance that a player loses on any given round. For simulation purposes.
const FULL = 100;
const BIAS = 40;
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_weights = Array(PLAYER_COUNT).fill(0); // For the weighted random.
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
function weighted_random(weights) {
let sum = weights.reduce((acc, o) => acc + o);
let rnd = ~~(Math.random() * sum);
for (let i = 0; i < weights.length; i++) {
if (rnd - weights[i] < 0) return i;
rnd -= weights[i];
}
return ~~(Math.random() * weights.length);
}
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let living_player_weights = player_weights.filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
let weighted_random_result;
if (Math.random() < duel_chance) { // A duel was rolled
console.log(` Living player weights: ${living_player_weights}.`);
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_1 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_2 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
// Calculate new deul probability weights.
let most_duels = player_duels_played.reduce((acc, o) => Math.max(acc, o));
for (let i = 0; i < PLAYER_COUNT; i++) {
if (player_eliminated[i] == 0) {
player_weights[i] = (most_duels - player_duels_played[i]) * FULL + ~~(Math.random() * BIAS);
}
}
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < ELIMINATION_CHANCE) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl == 1) break; // Get out of the loop when there's only one player alive.
round_number++;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
}
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
// This is duels using selection from a pool of biased non-binary weighted randoms.
// This makes it so that all players HAVE A TENDENCY duel in a random order before any player duels twice.
// 1) It DOES incentivize players with less duels to being picked in duels.
// 2) It HAS SOMETHING preventing two players from duelling twice in a row.
// 3) It has nothing to prevent 2 duels in a row when only 2 players are left.
const ITERATIONS = 1000;
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE_INCREMENT = 0.005; // There is a 4% chance that a player loses on any given round. For simulation purposes.
const FULL = 100;
const BIAS = 40;
function weighted_random(weights) {
let sum = weights.reduce((acc, o) => acc + o);
let rnd = ~~(Math.random() * sum);
for (let i = 0; i < weights.length; i++) {
if (rnd - weights[i] < 0) return i;
rnd -= weights[i];
}
return ~~(Math.random() * weights.length);
}
Number.prototype.p = function (l) {
return ('' + this).padStart(l, '0');
}
Array.prototype.p = function (l) {
return this.map((o) => ('' + o).padStart(l, '0'));
}
let total_round_count = 0;
for (let k = 0; k < ITERATIONS; k++) {
let elimination_chance = ELIMINATION_CHANCE_INCREMENT;
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_weights = Array(PLAYER_COUNT).fill(0); // For the weighted random.
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
console.log(`===================`);
console.log(`=====GAME #${("00" + k).slice (-3)}=====`);
console.log(`===================`);
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let living_player_weights = player_weights.filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
let weighted_random_result;
if (Math.random() < duel_chance) { // A duel was rolled
console.log(` Living player weights: ${living_player_weights}.`);
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_1 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_2 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
// Calculate new deul probability weights.
let most_duels = player_duels_played.reduce((acc, o) => Math.max(acc, o));
for (let i = 0; i < PLAYER_COUNT; i++) {
if (player_eliminated[i] == 0) {
player_weights[i] = (most_duels - player_duels_played[i]) * FULL + ~~(Math.random() * BIAS);
}
}
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < elimination_chance) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl == 1) break; // Get out of the loop when there's only one player alive.
round_number++;
elimination_chance += ELIMINATION_CHANCE_INCREMENT;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
}
total_round_count += round_number;
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
}
console.log(`The average rounds per game was ${total_round_count/1000}.`);
// This is duels using selection from a pool of biased non-binary weighted randoms with a specific rules for when two players are left.
// This makes it so that all players HAVE A TENDENCY duel in a random order before any player duels twice.
// 1) It DOES incentivize players with less duels to being picked in duels.
// 2) It HAS SOMETHING preventing two players from duelling twice in a row.
// 3) It HAS SOMETHING to prevent 2 duels in a row when only 2 players are left.
const PLAYER_COUNT = 10; // The number of players, or in duo mode, the number of teams.
const ELIMINATION_CHANCE = 0.04; // There is a 4% chance that a player loses on any given round. For simulation purposes.
const FULL = 100;
const BIAS = 40;
let player_duels_played = Array(PLAYER_COUNT).fill(0);
let player_weights = Array(PLAYER_COUNT).fill(0); // For the weighted random.
let player_eliminated = Array(PLAYER_COUNT).fill(0);
let round_number = 1; // The current round number.
let duel_chance = 0; // The chance that a duel takes place. It is zero for the first round.
function weighted_random(weights) {
let sum = weights.reduce((acc, o) => acc + o);
let rnd = ~~(Math.random() * sum);
for (let i = 0; i < weights.length; i++) {
if (rnd - weights[i] < 0) return i;
rnd -= weights[i];
}
return ~~(Math.random() * weights.length);
}
while (true) { // Game loop
console.log(`Round ${round_number}:`);
let nothing_happens = true; // For console.log purposes.
let duel_happens = false;
// The array of players who have not yet been eliminated.
let living_players = Array.from(Array(PLAYER_COUNT), (_, i) => i).filter((_, i) => player_eliminated[i] != 1);
let living_player_weights = player_weights.filter((_, i) => player_eliminated[i] != 1);
let lpl = living_players.length;
let duelist_1 = -1;
let duelist_2 = -1;
let weighted_random_result;
if (Math.random() < duel_chance) { // A duel was rolled
console.log(` Living player weights: ${living_player_weights}.`);
// Choose a random player to be duelist_1 and remove duelist_1 from the array so duelist_2 has no chance
// of ending up the same as them and so duelist_1 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_1 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
// Choose a random player to be the duelist_2 and remove duelist_2 from the array so duelist_2 has no chance of being eliminated in this round.
weighted_random_result = weighted_random(living_player_weights);
duelist_2 = living_players.splice(weighted_random_result, 1)[0];
living_player_weights.splice(weighted_random_result, 1);
player_duels_played[duelist_1]++;
player_duels_played[duelist_2]++;
nothing_happens = false;
duel_happens = true;
console.log(` Duel between Player ${duelist_1} and Player ${duelist_2}!`);
console.log(` Total duels by living players: ${player_duels_played.filter((_, i) => player_eliminated[i] != 1)}.`);
// Calculate new deul probability weights.
let most_duels = player_duels_played.reduce((acc, o) => Math.max(acc, o));
for (let i = 0; i < PLAYER_COUNT; i++) {
if (player_eliminated[i] == 0) {
player_weights[i] = (most_duels - player_duels_played[i]) * FULL + ~~(Math.random() * BIAS);
}
}
}
// The rest of the players play the round.
for (let o of living_players) {
if (o == duelist_1 || o == duelist_2) continue; // This if statement should never be true.
if (Math.random() < ELIMINATION_CHANCE) { // A player that wasn't eliminated dies in this simulation.
player_eliminated[o]++;
lpl--;
console.log(` Player ${o} has been eliminated!`);
nothing_happens = false;
if (lpl <= 1) break; // To prevent a case of double elimination of last two players in this simulation.
}
}
if (nothing_happens) console.log(` Nothing happens...`);
if (lpl == 1) break; // Get out of the loop when there's only one player alive.
round_number++;
duel_chance = lpl / PLAYER_COUNT; // Set a new duel chance based on number of players alive.
if (duel_happens && lpl == 2) duel_chance = 0; // The only two players left cannot duel twice in a row.
}
console.log(`The game ends on round ${round_number}.`);
console.log(`Player ${player_eliminated.indexOf(0)} wins!`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment