Published
Edited
Mar 11, 2021
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = {
const numTeams = 20;
const teamSize = 3;
const numLobbies = 10;
const lobbySize = numTeams * teamSize;

let players = _.range(0, numTeams * teamSize * numLobbies).map(
id => new Player({ team: null, id, skill: Math.random() })
);
let sort = _.sortBy(p => p.numKills);

for (let i = 0; i < 1000; i++) {
sort(players);
for (const lobby of _.chunk(lobbySize, players)) {
_.chunk(teamSize, lobby).forEach((team, teamNum) =>
team.forEach(p => (p.team = teamNum))
);
simulateGame({ players: lobby, arenaSize: lobby.length / 2 });
yield players;
}
players.forEach(p => p.respawn());
}

return players;
}
Insert cell
simulateGame = ({ players, arenaSize, arenaShrink = 0.9 } = {}) => {
while (countRemainingTeams(players) > 1) {
let arena = _.range(0, arenaSize).map(() => []);
for (let player of players) {
const slot = _.sample(arena);
slot.push(player);
}

for (let player of arena[0].filter(p => p.isAlive)) {
player.dealDamage({ damage: ringDamage, killer: theRing });
}

for (const slot of _.filter(s => s.length > 1, arena)) {
fight({ players: slot });
}
arenaSize = Math.max(1, arenaSize * arenaShrink);
}

for (let player of players) {
if (player.isAlive) {
player.numWins += 1;
}
}
return players;
}
Insert cell
fight = ({ players }) => {
while (countRemainingTeams(players) > 1) {
let livingPlayers = _.filter(p => p.isAlive, players);
let attacker = _.sample(livingPlayers);
let enemies = _.filter(p => p.team != attacker.team, livingPlayers);
let target = _.sample(enemies);
target.dealDamage({
damage: playerDamage * attacker.skill,
killer: attacker
});
}
}
Insert cell
Insert cell
Insert cell
class Player {
constructor({ team, skill } = {}) {
this.team = team;
this.skill = skill;

this.numKills = 0;
this.numDeaths = 0;
this.ringDeaths = 0;
this.numWins = 0;
this.health = 1.0;
this.damageDealt = 0;
this.damageReceived = 0;
this.numGames = 0;
}

dealDamage({ damage, killer }) {
this.health -= damage;
this.damageReceived += damage;
if (this.health <= 0) {
this.numDeaths += 1;
if (killer === theRing) {
this.ringDeaths += 1;
} else {
killer.numKills += 1;
killer.damageDealt += damage;
}
}
}

get kdr() {
return this.numKills / this.numDeaths;
}

get isDead() {
return this.health <= 0;
}

get isAlive() {
return this.health > 0;
}

get averageDamageDealt() {
return this.damageDealt / this.numGames;
}

get averageDamageReceived() {
return this.damageReceived / this.numGames;
}

respawn() {
this.health = 1.0;
this.numGames += 1;
}
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more